tissue_of_interest = "Liver"
library(here)
source("/restricted/projectnb/waxmanlab/kkarri/scRNAseq_data_integration/boilerplate.R")
#tiss = load_tissue_droplet(tissue_of_interest)
#library(scater)
library(dplyr)
library(Seurat)
library(cowplot)
#library(MAST)
require(stringr)
require(reshape2)
require(ggplot2)
require(MASS)
library(tools)
require(data.table)
library(ggfortify)
library(tidyverse)
require(dplyr)
library(miscTools)
library(caret)
library(Rtsne)
library(ggrepel)
G172
G172.umis <- Read10X("/net/waxman-server/mnt/data/waxmanlabvm_home/kkarri/G172/10X_TCPO_premRNA_Transcript/outs/filtered_feature_bc_matrix")
#G172.umis.raw <- Read10X("/net/waxman-server/mnt/data/waxmanlabvm_home/kkarri/G172/10X_TCPO_premRNA_Transcript/outs/raw_feature_bc_matrix/")
G172.htos <- Read10X("/net/waxman-server/mnt/data/waxmanlabvm_home/kkarri/G172/HASH_Citeseq/HASH_Results_filtered-10X-BC/umi_count", gene.column=1)
# Select cell barcodes detected by both RNA and HTO In the example datasets we have already
# filtered the cells for you, but perform this step for clarity.
joint.bcs <- intersect(colnames(G172.umis), colnames(G172.htos))
# Subset RNA and HTO counts by joint cell barcodes
joint_cite1_cite2 <- intersect(colnames(G172.htos), colnames(df2))
G172.umis <- G172.umis[, joint.bcs]
G172.htos <- as.matrix(G172.htos[, joint.bcs])
G172.htos <- G172.htos[-5,]
# Confirm that the HTO have the correct names
rownames(G172.htos)
# Setup Seurat object
G172.hashtag <- CreateSeuratObject(counts = G172.umis)
# Normalize RNA data with log normalization
G172.hashtag <- NormalizeData(G172.hashtag)
# Find and scale variable features
G172.hashtag <- FindVariableFeatures(G172.hashtag, selection.method = "mean.var.plot")
G172.hashtag <- ScaleData(G172.hashtag, features = VariableFeatures(G172.hashtag))
# Add HTO data as a new assay independent from RNA
G172.hashtag[["HTO"]] <- CreateAssayObject(counts = G172.htos)
# Normalize HTO data, here we use centered log-ratio (CLR) transformation
G172.hashtag <- NormalizeData(G172.hashtag, assay = "HTO", normalization.method = "CLR")
# If you have a very large dataset we suggest using k_function = 'clara'. This is a k-medoid
# clustering function for large applications You can also play with additional parameters (see
# documentation for HTODemux()) to adjust the threshold for classification Here we are using the
# default settings
G172.hashtag <- HTODemux(G172.hashtag, assay = "HTO", positive.quantile = 0.99, kfunc = 'clara')
# Global classification results
table(G172.hashtag$HTO_classification.global)
table(G172.hashtag$hash.ID)
# Group cells based on the max HTO signal
Idents(G172.hashtag) <- "hash.ID"
RidgePlot(G172.hashtag, assay = "HTO", features = rownames(G172.hashtag[["HTO"]])[1:4], ncol = 2, nrow=2)
#Idents(G172.hashtag) <- "HTO_classification.global"
# First, we will remove negative cells from the object
G172.hashtag.subset <- subset(G172.hashtag, idents =c("Negative","Doublet"), invert = TRUE)
## Feature scatterplot for hastags IDs ########
FeatureScatter(G172.hashtag.subset, feature1 = "M1-ATGATGAACAGCCAG", feature2 = "M2-TGACGCCGTTGTTGT")
FeatureScatter(G172.hashtag.subset, feature1 = "M1-ATGATGAACAGCCAG", feature2 = "M3-GCCTAGTATGATCCA")
FeatureScatter(G172.hashtag.subset, feature1 = "M1-ATGATGAACAGCCAG", feature2 = "M4-AGTCACAGTATTCCA")
FeatureScatter(G172.hashtag.subset, feature1 = "M2-TGACGCCGTTGTTGT", feature2 = "M3-GCCTAGTATGATCCA")
FeatureScatter(G172.hashtag.subset, feature1 = "M2-TGACGCCGTTGTTGT", feature2 = "M4-AGTCACAGTATTCCA")
FeatureScatter(G172.hashtag.subset, feature1 = "M3-GCCTAGTATGATCCA", feature2 = "M4-AGTCACAGTATTCCA")
# Calculate a distance matrix using HTO
hto.dist.mtx <- as.matrix(dist(t(GetAssayData(object = G172.hashtag.subset, assay = "HTO"))))
# Calculate tSNE embeddings with a distance matrix
G172.hashtag.subset <- RunTSNE(G172.hashtag.subset, distance.matrix = hto.dist.mtx, perplexity = 100)
DimPlot(G172.hashtag.subset)
HTOHeatmap(G172.hashtag, assay = "HTO", ncells = 26740)
########################## Rescue doublets ########################
G172.doublet <- subset(G172.hashtag, idents = "Doublet")
G172.doublet.rescue <- HTODemux(G172.doublet, assay = "HTO", positive.quantile = 0.99, kfunc = 'clara')
Idents(G172.doublet.rescue) <- "hash.ID"
RidgePlot(G172.doublet.rescue, assay = "HTO", features = rownames(G172.doublet.rescue[["HTO"]])[1:4], ncol = 2, nrow=2)
###############################################################################
# Extract the singlets M1 #############3
G172.M1 <- subset(G172.hashtag, idents = "M1-ATGATGAACAGCCAG", subset = nFeature_RNA > 500 & nCount_RNA > 1000)
G172.M1$stim <- "G172M1"
DefaultAssay(G172.M1) <- "RNA"
G172.M1 <- SCTransform(G172.M1,verbose =TRUE)
# Select the top 1000 most variable features
G172.M1 <- NormalizeData(G172.M1, verbose = FALSE)
G172.M1 <- FindVariableFeatures(G172.M1, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M1 <- ScaleData(G172.M1, features = VariableFeatures(G172.M1))
# Run PCA
G172.M1 <- RunPCA(G172.M1,npcs = 30, features = VariableFeatures(G172.M1))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M1 <- RunUMAP(G172.M1, reduction = "pca", dims = 1:25)
G172.M1 <- FindNeighbors(G172.M1, reduction = "pca", dims = 1:25)
G172.M1 <- FindClusters(G172.M1, resolution = 0.6 )
G172.M1.p1<- UMAPPlot(G172.M1, reduction = "umap", label=TRUE, label.size=5)
G172.M1.p1
DefaultAssay(G172.M1) <- "RNA"
G172.M1 <- NormalizeData(G172.M1, verbose = TRUE)
d1 <- DotPlot(G172.M1, features = all_genes)+RotatedAxis()
plot_grid(G172.M1.p1,d1)
# Extract the singlet for M2 #############3
G172.M2 <- subset(G172.hashtag, idents = "M2-TGACGCCGTTGTTGT", subset = nFeature_RNA > 500 & nCount_RNA > 1000)
G172.M2$stim <- "G172M2"
DefaultAssay(G172.M2) <- "RNA"
G172.M2 <- SCTransform(G172.M2,verbose =TRUE)
# Select the top 1000 most variable features
G172.M2 <- NormalizeData(G172.M2, verbose = FALSE)
G172.M2 <- FindVariableFeatures(G172.M2, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M2 <- ScaleData(G172.M2, features = VariableFeatures(G172.M2))
# Run PCA
G172.M2 <- RunPCA(G172.M2,npcs = 30, features = VariableFeatures(G172.M2))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M2 <- RunUMAP(G172.M2, reduction = "pca", dims = 1:25)
G172.M2 <- FindNeighbors(G172.M2, reduction = "pca", dims = 1:25)
G172.M2 <- FindClusters(G172.M2, resolution = 0.5 )
G172.M2.p1<- UMAPPlot(G172.M2, reduction = "umap", label=TRUE, label.size=5)
G172.M2.p1
DefaultAssay(G172.M2) <- "RNA"
G172.M2 <- NormalizeData(G172.M2, verbose = TRUE)
d2 <- DotPlot(G172.M2, features = all_genes)+RotatedAxis()
plot_grid(G172.M2.p1,d2)
#### Extract the singlet for M3 #####
G172.M3 <- subset(G172.hashtag, idents = "M3-GCCTAGTATGATCCA", subset = nFeature_RNA > 500 & nCount_RNA > 1000)
DefaultAssay(G172.M3) <- "RNA"
G172.M3 <- SCTransform(G172.M3,verbose =TRUE)
# Select the top 1000 most variable features
G172.M3 <- NormalizeData(G172.M3, verbose = FALSE)
G172.M3 <- FindVariableFeatures(G172.M3, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M3 <- ScaleData(G172.M3, features = VariableFeatures(G172.M3))
# Run PCA
G172.M3 <- RunPCA(G172.M3,npcs = 30, features = VariableFeatures(G172.M3))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M3 <- RunUMAP(G172.M3, reduction = "pca", dims = 1:25)
G172.M3 <- FindNeighbors(G172.M3, reduction = "pca", dims = 1:25)
G172.M3 <- FindClusters(G172.M3, resolution = 0.5 )
G172.M3.p1<- UMAPPlot(G172.M3, reduction = "umap", label=TRUE, label.size=5)
G172.M3.p1
DefaultAssay(G172.M3) <- "RNA"
G172.M3 <- NormalizeData(G172.M3, verbose = TRUE)
d3 <- DotPlot(G172.M3, features = all_genes)+RotatedAxis()
plot_grid(G172.M3.p1,d3)
##### Extract the singlet for M4 #####
G172.M4 <- subset(G172.hashtag, idents = "M4-AGTCACAGTATTCCA", subset = nFeature_RNA > 500 & nCount_RNA > 1000)
DefaultAssay(G172.M4) <- "RNA"
G172.M4 <- SCTransform(G172.M4,verbose =TRUE)
# Select the top 1000 most variable features
G172.M4 <- NormalizeData(G172.M4, verbose = FALSE)
G172.M4 <- FindVariableFeatures(G172.M4, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M4 <- ScaleData(G172.M4, features = VariableFeatures(G172.M4))
# Run PCA
G172.M4 <- RunPCA(G172.M4,npcs = 30, features = VariableFeatures(G172.M4))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M4 <- RunUMAP(G172.M4, reduction = "pca", dims = 1:25)
G172.M4 <- FindNeighbors(G172.M4, reduction = "pca", dims = 1:25)
G172.M4 <- FindClusters(G172.M4, resolution = 0.5 )
G172.M4.p1<- UMAPPlot(G172.M4, reduction = "umap", label=TRUE, label.size=5)
G172.M4.p1
DefaultAssay(G172.M4) <- "RNA"
G172.M4 <- NormalizeData(G172.M4, verbose = TRUE)
d4 <- DotPlot(G172.M4, features = all_genes)+RotatedAxis()
plot_grid(G172.M4.p1,d4)
############## Combined ####################33
G172.M5 <- subset(G172.hashtag, idents = c("M1-ATGATGAACAGCCAG","M2-TGACGCCGTTGTTGT","M3-GCCTAGTATGATCCA","M4-AGTCACAGTATTCCA"), subset = nFeature_RNA > 500 & nCount_RNA > 1000)
DefaultAssay(G172.M5) <- "RNA"
G172.M5 <- SCTransform(G172.M5,verbose =TRUE)
# Select the top 1000 most variable features
G172.M5 <- NormalizeData(G172.M5, verbose = FALSE)
G172.M5 <- FindVariableFeatures(G172.M5, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M5 <- ScaleData(G172.M5, features = VariableFeatures(G172.M5))
# Run PCA
G172.M5 <- RunPCA(G172.M5,npcs = 30, features = VariableFeatures(G172.M5))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M5 <- RunUMAP(G172.M5, reduction = "pca", dims = 1:25)
G172.M5 <- FindNeighbors(G172.M5, reduction = "pca", dims = 1:25)
G172.M5 <- FindClusters(G172.M5, resolution = 0.5 )
G172.M5.p1<- UMAPPlot(G172.M5, reduction = "umap", label=TRUE, label.size=5)
G172.M5.p1
DefaultAssay(G172.M5) <- "RNA"
G172.M5 <- NormalizeData(G172.M5, verbose = TRUE)
d5 <- DotPlot(G172.M5, features = c(all_genes,'Cyp2b10','Cyp2d9'))+RotatedAxis()
plot_grid(G172.M5.p1,d5)
### control
G172.M6 <- subset(G172.hashtag.subset, idents = c("M1-ATGATGAACAGCCAG","M3-GCCTAGTATGATCCA"), subset = nFeature_RNA > 500 & nCount_RNA > 1000)
DefaultAssay(G172.M6) <- "RNA"
#G172.M6 <- SCTransform(G172.M6,verbose =TRUE)
# Select the top 1000 most variable features
G172.M6 <- NormalizeData(G172.M6, verbose = FALSE)
G172.M6 <- FindVariableFeatures(G172.M6, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M6 <- ScaleData(G172.M6, features = VariableFeatures(G172.M6))
# Run PCA
G172.M6 <- RunPCA(G172.M6,npcs = 30, features = VariableFeatures(G172.M6))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M6 <- RunUMAP(G172.M6, reduction = "pca", dims = 1:25)
G172.M6 <- FindNeighbors(G172.M6, reduction = "pca", dims = 1:25)
G172.M6 <- FindClusters(G172.M6, resolution = 0.5 )
G172.M6.p1<- UMAPPlot(G172.M6, reduction = "umap", label=TRUE, label.size=5)
G172.M6.p1
DefaultAssay(G172.M6) <- "RNA"
G172.M6 <- NormalizeData(G172.M6, verbose = TRUE)
d6 <- DotPlot(G172.M6, features = c(all_genes,'Cyp2b10','Cyp2d9'))+RotatedAxis()
plot_grid(G172.M6.p1,d6)
#### TCPO
G172.M7 <- subset(G172.hashtag, idents = c("M2-TGACGCCGTTGTTGT","M4-AGTCACAGTATTCCA"), subset = nFeature_RNA > 500 & nCount_RNA > 1000)
DefaultAssay(G172.M7) <- "RNA"
G172.M7 <- SCTransform(G172.M7,verbose =TRUE)
# Select the top 1000 most variable features
G172.M7 <- NormalizeData(G172.M7, verbose = FALSE)
G172.M7 <- FindVariableFeatures(G172.M7, selection.method = "vst", nfeatures = 2000)
# Scaling RNA data, we only scale the variable features here for efficiency
G172.M7 <- ScaleData(G172.M7, features = VariableFeatures(G172.M7))
# Run PCA
G172.M7 <- RunPCA(G172.M7,npcs = 30, features = VariableFeatures(G172.M7))
# We select the top 10 PCs for clustering and tSNE based on PCElbowPlot
G172.M7 <- RunUMAP(G172.M7, reduction = "pca", dims = 1:25)
G172.M7 <- FindNeighbors(G172.M7, reduction = "pca", dims = 1:25)
G172.M7 <- FindClusters(G172.M7, resolution = 0.5 )
G172.M7.p1<- UMAPPlot(G172.M7, reduction = "umap", label=TRUE, label.size=5)
G172.M7.p1
DefaultAssay(G172.M7) <- "RNA"
G172.M7 <- NormalizeData(G172.M7, verbose = TRUE)
d7 <- DotPlot(G172.M7, features = c(all_genes,'Cyp2b10','Cyp2d9'))+RotatedAxis()
plot_grid(G172.M7.p1,d7, nrow=2)
########## function load_tissue_droplet############
droplet_metadata <- read.csv("/restricted/projectnb/waxmanlab/kkarri/scRNAseq_data_integration/metadata_droplet_liver.csv", sep=",", header = TRUE)
colnames(droplet_metadata)[1] <- "channel"
tissue_metadata = filter(droplet_metadata, tissue == tissue_of_interest)[,c('channel','tissue','subtissue','mouse.sex', 'mouse.id')]
raw.data <- Read10X("/restricted/projectnb/waxmanlab/kkarri/scRNAseq_data_integration/Refined_cellmatrices/Liver-10X_P4_2/")
colnames(raw.data) <- lapply(colnames(raw.data), function(x) paste0(tissue_metadata$channel[1],'_',x))
meta.data1 = data.frame(row.names = colnames(raw.data))
meta.data1['channel'] = tissue_metadata$channel[1]
if (length(tissue_metadata$channel) > 1){
# Some tissues, like Thymus and Heart had only one channel
for(i in 2:nrow(tissue_metadata)){
subfolder = paste0("/restricted/projectnb/waxmanlab/kkarri/scRNAseq_data_integration/Refined_cellmatrices/",tissue_of_interest, '-', tissue_metadata$channel[i])
new.data1 <- Read10X(data.dir = subfolder)
colnames(new.data1) <- lapply(colnames(new.data1), function(x) paste0(tissue_metadata$channel[i],'_', x))
new.metadata1 = data.frame(row.names = colnames(new.data1))
new.metadata1['channel'] = tissue_metadata$channel[i]
raw.data = cbind(raw.data, new.data1)
meta.data1 = rbind(meta.data1, new.metadata1)
}
}
rnames = row.names(meta.data1)
meta.data1 <- merge(meta.data1, tissue_metadata, sort = F)
row.names(meta.data1) <- rnames
# Order the cells alphabetically to ensure consistency.
ordered_cell_names = order(colnames(raw.data))
raw.data = raw.data[,ordered_cell_names]
meta.data1 = meta.data1[ordered_cell_names,]
# Find ERCC's, compute the percent ERCC, and drop them from the raw data.
erccs <- grep(pattern = "^ERCC-", x = rownames(x = raw.data), value = TRUE)
percent.ercc <- Matrix::colSums(raw.data[erccs, ])/Matrix::colSums(raw.data)
ercc.index <- grep(pattern = "^ERCC-", x = rownames(x = raw.data), value = FALSE)
raw.data <- raw.data[-ercc.index,]
# Create the Seurat object with all the data
droplet <- CreateSeuratObject(raw.data) # dropseq
droplet <- AddMetaData(object = droplet, meta.data1)
droplet@meta.data$tech <- "droplet"
#n.pcs = 10
#droplet <- SubsetData(droplet,subset.names = c("nGene", "nUMI"), low.thresholds = c(500, 1000)) # old version of seurat
droplet <- subset(droplet, subset = nFeature_RNA > 500 & nCount_RNA > 1000)
droplet <- NormalizeData(droplet, verbose = FALSE)
droplet <- FindVariableFeatures(droplet, selection.method = "vst", nfeatures = 2000)
droplet <- ScaleData(droplet, verbose = FALSE)
#droplet <- RunPCA(droplet, npcs = 10, verbose = FALSE)
droplet$stim <- "droplet"
droplet$cond <- "ctrl"
# droplet <- ScaleData(droplet, verbose = FALSE)
droplet <- RunPCA(droplet, npcs = 30, verbose = FALSE)
droplet <- RunUMAP(droplet, reduction = "pca", dims = 1:25)
droplet <- FindNeighbors(droplet, reduction = "pca", dims = 1:10)
droplet <- FindClusters(droplet, resolution = 0.5 )
p1<- UMAPPlot(droplet, reduction = "umap", group.by = "channel", label=TRUE, label.size=5)
p2 <- UMAPPlot(droplet, label=TRUE, label.size=6)
p3<- UMAPPlot(droplet, reduction = "umap", group.by = "mouse.sex", label=TRUE, label.size=5)
res.used <- 1
#droplet <- FindClusters(object = droplet, reduction.type = "pca", dims.use = 1:n.pcs, resolution = res.used, print.output = 0, save.SNN = TRUE, force.recalc = TRUE)
droplet <- RunTSNE(object = droplet, dims.use = 1:n.pcs, seed.use = 10, perplexity=30)
TSNEPlot(object = droplet, do.label = T, pt.size = 1.2, label.size = 4)
droplet <- RenameIdents(droplet, `0` = "Hep-Mid-M", `1` = "Hep-PC-F", `2` = "Hep-PP-F",`3` = "Hep-PP-M", `4` = "Hep-Mid-M", `5` = "Hep-PC-M", `6` = "Hep-Mid-F", `7` = "Hep-Mid-F", `8` = "Endo-F", `9` = "Bileduct-F")
### this is tranformation option for develpment SCtransform program #######
droplet <- SCTransform(droplet,verbose =TRUE)
######3 Smartseq #########################
plate_metadata <- read.csv("/restricted/projectnb/waxmanlab/kkarri/scRNAseq_data_integration/Liver_facs_annotation.csv", sep=",", header = TRUE)
colnames(plate_metadata)[1] <- "plate.barcode"
raw.data = read.csv("/restricted/projectnb/waxmanlab/kkarri/scRNAseq_data_integration/liver_facs_scrna_data.csv", sep=",", row.names=1)
colnames(plate_metadata)[1] <- "plate.barcode"
plate.barcodes = lapply(colnames(raw.data), function(x) strsplit(strsplit(x, "_")[[1]][1], '.', fixed=TRUE)[[1]][2])
barcode.df = t.data.frame(as.data.frame(plate.barcodes))
rownames(barcode.df) = colnames(raw.data)
barcode.df= cbind(barcode.df, colnames(raw.data))
colnames(barcode.df) = c('plate.barcode1', 'plate.barcode')
rnames = row.names(barcode.df)
meta.data <- merge(barcode.df, plate_metadata, by='plate.barcode', sort = F)
row.names(meta.data) <- rnames
# Sort cells by cell name
meta.data = meta.data[order(rownames(meta.data)), ]
raw.data = raw.data[,rownames(meta.data)]
# Create the Seurat object with all the data
smartseq <- CreateSeuratObject(raw.data)
smartseq <- AddMetaData(object = smartseq, meta.data)
#smartseq@meta.data$tech <- "smartseq"
smartseq$stim <- "smartseq"
smartseq$cond <- "ctrl"
#smartseq <- SubsetData(smartseq,subset.names = c("nGene", "nUMI"),low.thresholds = c(500, 1000)) #old version of seurat
smartseq<- subset(smartseq, subset = nFeature_RNA > 500 & nCount_RNA > 1000)
#smartseq <- SCTransform(smartseq)
smartseq <- NormalizeData(smartseq, verbose = FALSE)
smartseq <- FindVariableFeatures(smartseq, selection.method = "vst", nfeatures = 2000)
smartseq <- ScaleData(smartseq, verbose = FALSE)
smartseq <- RunPCA(smartseq, npcs = 30, verbose = FALSE)
smartseq <- RunUMAP(smartseq, reduction = "pca", dims = 1:25)
smartseq <- FindNeighbors(smartseq, reduction = "pca", dims = 1:25)
smartseq <- FindClusters(smartseq, resolution = 0.5 )
#p4<- UMAPPlot(smartseq, reduction = "umap", group.by = "channel", label=TRUE, label.size=5)
p5 <- UMAPPlot(smartseq, label=TRUE, label.size=6)
p6<- UMAPPlot(smartseq, reduction = "umap", group.by = "mouse.sex", label=TRUE, label.size=5)
########## sctransform ###################3
smartseq <- SCTransform(smartseq)
############################### Integration Regular workflow ############################
anchors <- FindIntegrationAnchors(object.list = c(droplet.list, smartseq.list,G171B.list, G172.M1.list, G172.M2.list), dims = 1:50, anchor.features = 3000)
combined <- IntegrateData(anchorset = anchors, dims = 1:50)
DefaultAssay(combined) <- "integrated"
# Run the standard workflow for visualization and clustering
combined <- ScaleData(combined, verbose = FALSE)
combined <- RunPCA(combined, npcs = 30, verbose = FALSE)
# t-SNE and Clustering
combined <- RunUMAP(combined, reduction = "pca", dims = 1:20)
combined <- FindNeighbors(combined, reduction = "pca", dims = 1:20)
combined <- FindClusters(combined, resolution = 0.5 )
#combined <- RunTSNE(combined, reduction = "pca", dims = 1:20)
# Visualization
p1 <- DimPlot(combined, reduction = "umap", group.by = "stim")
p2 <- DimPlot(combined, reduction = "umap", group.by = "mouse.sex")
p3 <- DimPlot(combined, reduction = "umap", label = TRUE)
p4 <- UMAPPlot(combined, label=TRUE)
plot_grid(p2, p3,p4)
DimPlot(combined, reduction = "umap", split.by = "stim")
p5 <- DimPlot(combined, reduction = "tsne", group.by = "stim")
p6 <- DimPlot(combined, reduction = "tsne", group.by = "mouse.sex")
p7 <- DimPlot(combined, reduction = "tsne", label = TRUE)
p8 <- TSNEPlot(combined, label =T)
plot_grid(p6, p7,p8)
DimPlot(combined, reduction = "tsne", split.by = "stim")
#################################### Refernce based Integration ################################
droplet.list <- SplitObject(droplet, split.by = "mouse.sex")
smartseq.list <- SplitObject(smartseq, split.by = "stim")
G172.M1.list <- SplitObject(G172.M1, split.by = "stim")
G172.M2.list <- SplitObject(G172.M2, split.by = "stim")
G172.M6.list <- SplitObject(G172.M6, split.by = "stim")
G171B.list <- SplitObject(G171B, split.by="stim")
ctrl.list <- c(droplet.list, smartseq.list)
for (i in names(ctrl.list)) {
ctrl.list[[i]] <- SCTransform(ctrl.list[[i]], verbose =TRUE)
}
ctrl.list1 <- c(ctrl.list, G171B.list)
#dims = 1:50
ref.features <- SelectIntegrationFeatures(object.list = ctrl.list1, dims=1:50, anchor.features = 3000)
ref.list <- PrepSCTIntegration(object.list = ctrl.list1, anchor.features = ref.features)
ref.anchors <- FindIntegrationAnchors(object.list = ref.list, normalization.method = "SCT", anchor.features = ref.features, reference = c(1,2,3))
ref.integrated <- IntegrateData(anchorset = ref.anchors, normalization.method = "SCT")
DefaultAssay(ref.integrated) <- "integrated"
ref.integrated <- ScaleData(ref.integrated, verbose = FALSE)
ref.integrated <- RunPCA(object = ref.integrated, npcs=30,verbose = FALSE)
ref.integrated <- RunUMAP(object = ref.integrated ,dims = 1:30, seed.use = 10, perplexity=30)
ref.integrated <- FindNeighbors(ref.integrated, reduction = "pca", dims = 1:30)
ref.integrated <- FindClusters(ref.integrated, resolution = 0.2 )
r1 <- DimPlot(ref.integrated, split.by="stim", pt.size = 0.5)
r2 <- DimPlot(ref.integrated, label=TRUE, pt.size = 0.5)
r3 <- DimPlot(ref.integrated, split.by = c("cond"), pt.size = 0.5)
plots <- lapply(X = plots, FUN = function(x) x + theme(legend.position = "top") + guides(color = guide_legend(nrow = 4,
byrow = TRUE, override.aes = list(size = 2.5))))
CombinePlots(plots)
ref.integrated$celltype.stim <- paste(Idents(ref.integrated), ref.integrated$stim, sep = "_")
ref.integrated$seurat_clusters <- Idents(ref.integrated)
Idents(ref.integrated) <- "celltype.stim"
fp <- FeaturePlot(ref.integrated, features = "ncRNA-as-chr10-8460", cols = c("lightgrey","darkred"), order = TRUE, shape.by = "stim", pt.size = 2)
DefaultAssay(ref.integrated) <-"RNA"
ref.integrated <- NormalizeData(ref.integrated)
ref.integrated <- ScaleData(ref.integrated)
dot1 <- DotPlot(ref.integrated, features= all_genes)+RotatedAxis()
d1 <- DoHeatmap(ref.integrated, features = c(all_genes,"Mup20","Xist"), group.by = "seurat_clusters", assay= 'RNA')
#d1 <- DoHeatmap(ref.integrated, features = highTPM, group.by = "celltype.stim", assay= 'RNA',raster = F, disp.max = 0.5)+scale_fill_gradientn(colors = (RColorBrewer::brewer.pal(n = 9, name = "PuRd")) ) + guides(color=FALSE)
Drop.combined.markers <- FindAllMarkers(object = ref.integrated, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
############ merge G172 M1 #############33
droplet.list <- SplitObject(droplet, split.by = "mouse.sex")
smartseq.list <- SplitObject(smartseq, split.by = "stim")
G172.M1.list <- SplitObject(G172.M1, split.by = "stim")
G172.M2.list <- SplitObject(G172.M2, split.by = "stim")
G172.M6.list <- SplitObject(G172.M6, split.by = "stim")
G171B.list <- SplitObject(G171B, split.by="stim")
ctrl.list.2 <- c( G172.M1.list, G172.M2.list)
for (i in names(ctrl.list.2)) {
ctrl.list.2[[i]] <- SCTransform(ctrl.list.2[[i]], verbose =TRUE)
}
ref.features.1 <- SelectIntegrationFeatures(object.list = ctrl.list.2, dims = 1:50, anchor.features = 3000)
ref.list.1 <- PrepSCTIntegration(object.list = ctrl.list.2, anchor.features = ref.features.1)
ref.anchors.1 <- FindIntegrationAnchors(object.list = ref.list.1, normalization.method = "SCT",
anchor.features = ref.features.1, reference = c(1,2))
ref.integrated.1 <- IntegrateData(anchorset = ref.anchors.1, normalization.method = "SCT")
DefaultAssay(ref.integrated.1) <- "integrated"
ref.integrated.1 <- ScaleData(ref.integrated.1, verbose = FALSE)
ref.integrated.1 <- RunPCA(object = ref.integrated.1, npcs=30,verbose = FALSE)
ref.integrated.1 <- RunUMAP(object = ref.integrated.1, dims = 1:30, seed.use = 10 , perplexity=30)
#ref.integrated.1 <- RunTSNE(object = ref.integrated.1, dims.use = 1:n.pcs, seed.use = 10, perplexity=30)
ref.integrated.1 <- FindNeighbors(ref.integrated.1, reduction = "pca", dims = 1:30)
ref.integrated.1 <- FindClusters(ref.integrated.1, resolution = 0.2)
rG172M1.1 <- UMAPPlot(ref.integrated.1, split.by="stim", label=T)
rG172M1.2 <- UMAPPlot(ref.integrated.1, label=TRUE, combine = FALSE)
rG172M1.3 <- UMAPPlot(ref.integrated.1, split.by = c("mouse.sex"))
rG172M1.4 <- TSNEPlot(ref.integrated.1, split.by="stim")
DefaultAssay(ref.integrated.1) <-"RNA"
ref.integrated.1 <- NormalizeData(ref.integrated.1)
ref.integrated.1 <- ScaleData(ref.integrated.1)
DoHeatmap(ref.integrated.1, features = c(all_genes,'Sox9','Mup20'), group.by = "seurat_clusters", assay= 'RNA' ,raster = F)+scale_fill_gradientn(colors = (RColorBrewer::brewer.pal(n = 9, name = "PuRd")) ) + guides(color=FALSE)
ref.integrated.1$celltype <- RenameIdents(ref.integrated.1, c(`0` = "PP", `1` = "PC", `2` = "Endo",`3` = "HSC", `4` = "Kupffer", `5` = "Dividing", `6` = "Immune", `7` = "B-NK", `8` = "NA"))
ref.integrated.1.markers <- FindAllMarkers(ref.integrated.1, only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
ref.integrated.1.markers %>% group_by(cluster) %>% top_n(n = 2, wt = avg_logFC)
write.csv(ref.integrated.1.markers, "ref_integrated_G172M1-M2_Allmarker")
ref.integrated.1$celltype.stim <- paste(Idents(ref.integrated.1), ref.integrated.1$stim, sep = "_")
ref.integrated.1$celltype <- Idents(ref.integrated.1)
Idents(ref.integrated.1) <- "celltype.stim"
DoHeatmap(ref.integrated.1, features = TPM4, group.by = "seurat_clusters", assay= 'RNA' )
ref.integrated.1.markers <- FindMarkers(ref.integrated.1, only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
ref.integrated.1.markers %>% group_by(cluster) %>% top_n(n = 2, wt = avg_logFC)
G172M1 and G172 M2 DE analysis
DE1.1 <- FindMarkers(ref.integrated.1, ident.1 = c("0_G172M1" ,"1_G172M1", "2_G172M1" ,"3_G172M1" ,"4_G172M1" ,"5_G172M1" ,"6_G172M1","7_G172M1", "8_G172M1"), ident.2 = c("0_G172M2" ,"1_G172M2", "2_G172M2" ,"3_G172M2" ,"4_G172M2" ,"5_G172M2" ,"6_G172M2","7_G172M2", "8_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE_All_M1_M2 <- DE1.1
DE_hep_NPC <- FindMarkers(ref.integrated.1, ident.1 = c("0_G172M2" ,"1_G172M2"), ident.2 = c("2_G172M2" ,"3_G172M2" ,"4_G172M2" ,"5_G172M2" ,"6_G172M2","7_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE_NPC_M1_M2 <- FindMarkers(ref.integrated.1, ident.1 = c( "2_G172M1" ,"3_G172M1" ,"4_G172M1" ,"5_G172M1" ,"6_G172M1","7_G172M1"), ident.2 = c("2_G172M2" ,"3_G172M2" ,"4_G172M2" ,"5_G172M2" ,"6_G172M2","7_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE_Drop <- FindAllMarkers(ref.integrated, features = )
DE0.1 <- FindMarkers(ref.integrated.1, ident.1 = c("0_G172M1"), ident.2 = c("0_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
write.csv(DE0.1, "marker/DE0.1_G172_0_M1_M2")
DE1.1 <- FindMarkers(ref.integrated.1, ident.1 = c("1_G172M1"), ident.2 = c("1_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE2.1 <- FindMarkers(ref.integrated.1, ident.1 = c("2_G172M1"), ident.2 = c("2_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE3.1 <- FindMarkers(ref.integrated.1, ident.1 = c("3_G172M1"), ident.2 = c("3_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE4.1 <- FindMarkers(ref.integrated.1, ident.1 = c("4_G172M1"), ident.2 = c("4_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE5.1 <- FindMarkers(ref.integrated.1, ident.1 = c("5_G172M1"), ident.2 = c("5_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE6.1 <- FindMarkers(ref.integrated.1, ident.1 = c("6_G172M1"), ident.2 = c("6_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE7.1 <- FindMarkers(ref.integrated.1, ident.1 = c("7_G172M1"), ident.2 = c("7_G172M2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
################# G171 TCPO expsosed ########
G171B_metadata_G171B <- read.csv("/net/waxman-server/mnt/data/waxmanlabvm_home/kkarri/G171/Analysis/G171_metadata_droplet_liver.csv", sep=",", header = TRUE)
colnames(G171B_metadata_G171B)[1] <- "channel"
tissue_metadata_G171B = filter(G171B_metadata_G171B, tissue == tissue_of_interest)[,c('channel','tissue','subtissue','mouse.sex', 'mouse.id')]
raw.data <- Read10X("/net/waxman-server/mnt/data/waxmanlabvm_home/kkarri/G171/Analysis/Transcript_Refined/Liver-10X_G171B/")
colnames(raw.data) <- lapply(colnames(raw.data), function(x) paste0(tissue_metadata_G171B$channel[1],'_',x))
meta.data1 = data.frame(row.names = colnames(raw.data))
meta.data1['channel'] = tissue_metadata_G171B$channel[1]
rnames = row.names(meta.data1)
meta.data1 <- merge(meta.data1, tissue_metadata_G171B, sort = F)
row.names(meta.data1) <- rnames
# Order the cells alphabetically to ensure consistency.
ordered_cell_names = order(colnames(raw.data))
raw.data = raw.data[,ordered_cell_names]
meta.data1 = meta.data1[ordered_cell_names,]
# Find ERCC's, compute the percent ERCC, and drop them from the raw data.
erccs <- grep(pattern = "^ERCC-", x = rownames(x = raw.data), value = TRUE)
percent.ercc <- Matrix::colSums(raw.data[erccs, ])/Matrix::colSums(raw.data)
ercc.index <- grep(pattern = "^ERCC-", x = rownames(x = raw.data), value = FALSE)
raw.data <- raw.data[-ercc.index,]
ncRNA.genes <- grep(pattern = "^ncRNA", x = rownames(x = raw.data), value = TRUE)
percent.ncRNA <- Matrix::colSums(raw.data[ncRNA.genes, ])/Matrix::colSums(raw.data)
KRAB.genes <- grep(pattern = "^KRAB", x = rownames(x = raw.data), value = TRUE)
cherry.genes <- grep(pattern = "^mcherry", x = rownames(x = raw.data), value = TRUE)
# Create the Seurat object with all the data
G171B <- CreateSeuratObject(raw.data) # dropseq
G171B <- AddMetaData(object = G171B, meta.data1)
G171B@meta.data$tech <- "G171B"
#G171B <- SubsetData(G171B,subset.names = c("nGene", "nUMI"), low.thresholds = c(500, 1000)) # old version of seurat
#G171B <- subset(G171B, subset = nFeature_RNA > 500 & nCount_RNA > 1000)
G171B <- NormalizeData(G171B, verbose = FALSE)
G171B <- FindVariableFeatures(G171B, selection.method = "vst", nfeatures = 2000)
G171B$stim <- "G171B"
G171B$cond <- "TCPO"
### this is tranformation option for develpment SCtransform program #######
G171B <- SCTransform(G171B,verbose =TRUE)
diffusion plt code
# Before running MDS, we first calculate a distance matrix between all pairs of cells. Here we
# use a simple euclidean distance metric on all genes, using scale.data as input
d <- dist(t(GetAssayData(combined, slot = "scale.data")))
# Run the MDS procedure, k determines the number of dimensions
mds <- cmdscale(d = d, k = 2)
# cmdscale returns the cell embeddings, we first label the columns to ensure downstream
# consistency
colnames(mds) <- paste0("MDS_", 1:2)
# We will now store this as a custom dimensional reduction called 'mds'
combined[["mds"]] <- CreateDimReducObject(embeddings = mds, key = "MDS_", assay = DefaultAssay(combined))
# We can now use this as you would any other dimensional reduction in all downstream functions
DimPlot(combined, reduction = "mds", pt.size = 0.5)
genes_hep_main =c('Alb', 'Ttr', 'Apoa1', 'Serpina1c')
genes_hep = c('Alb', 'Ttr', 'Apoa1', 'Serpina1c',
'Cyp2e1', 'Glul', 'Oat', 'Gulo',
'Ass1', 'Hamp', 'Gstp1', 'Ubb',
'Cyp2f2', 'Pck1', 'Hal', 'Cdh1')
genes_endo = c('Pecam1', 'Nrp1', 'Kdr','Oit3')
genes_kuppfer = c( 'Clec4f', 'Cd68')
genes_nk = c('Il2rb', 'Nkg7', 'Cxcr6', 'Gzma')
genes_b = c('Cd79a', 'Cd79b')
genes_bec = c('Epcam', 'Krt19', 'Krt7')
genes_immune = 'Ptprc'
HSC = c("Dcn","Lama1","Nes")
Dividing = "Top2a"
Bplasma= "Jchain"
Mac= "Csf1r"
Chol="Sox9"
sex <- c("Cyp2d9", "ncRNA-inter_chrX-15394")
all_genes = c(genes_hep, genes_endo, genes_kuppfer, Mac,genes_nk, genes_b, genes_bec, genes_immune, HSC, Dividing)
genes_bec_b_immune = c(genes_bec,genes_b,genes_immune)
genes_zones = c('Cyp2e1', 'Glul', 'Oat', 'Gulo',
'Ass1', 'Hamp', 'Gstp1', 'Ubb',
'Cyp2f2', 'Pck1', 'Hal', 'Cdh1')
receptor_KO <- c("ncRNA-inter-chr7-5998","Cyp2b10","Nr1i2","Nr1i3","Ppara","Pparg","Ppargc1b","Ppard")
cell <- c("Stab2","Csf1r","Cd3g","Ebf1","Irf8","Sox9","Apoc3","Top2a","Dcn")
TPM4<- c('ncRNA-inter-chr7-6524',
'ncRNA-inter-chr19-14853',
'ncRNA-inter-chr6-5675',
'ncRNA-inter-chr4-3468',
'ncRNA-inter-chr9-8122',
'ncRNA-inter-chr12-10476',
'ncRNA-inter-chr17-14026',
'ncRNA-as-chr2-1457',
'ncRNA-as-chr19-14883',
'ncRNA-as-chr10-8460',
'ncRNA-as-chr5-4325',
'ncRNA-inter-chr7-5998',
'ncRNA-as-chr9-7843',
'ncRNA-as-chr9-8142',
'ncRNA-inter-chr11-9925',
'ncRNA-inter-chr19-14873',
'ncRNA-as-chr9-8172',
'ncRNA-inter-chr4-3779',
'ncRNA-inter-chr3-2504',
'ncRNA-as-chr19-15054',
'ncRNA-inter-chr8-7423',
'ncRNA-as-chr7-6302',
'ncRNA-inter-chr10-9418',
'ncRNA-inter-chr12-10454',
'ncRNA-as-chr7-5999',
'ncRNA-as-chr6-5335',
'ncRNA-inter-chr19-14987',
'ncRNA-inter-chr16-13170',
'ncRNA-inter-chr3-2988',
'ncRNA-inter-chr8-7430',
'ncRNA-inter-chr3-2168',
'ncRNA-inter-chr9-7874',
'ncRNA-inter-chr4-3778',
'ncRNA-inter-chr2-2011',
'ncRNA-inter-chr5-4335',
'ncRNA-inter-chr9-8301',
'ncRNA-inter-chr16-13510',
'ncRNA-as-chr9-8401',
'ncRNA-as-chr16-13512',
'ncRNA-as-chr12-10896',
'ncRNA-as-chr8-7359',
'ncRNA-as-chr5-4744',
'ncRNA-inter-chr5-4499',
'ncRNA-inter-chr16-13509',
'ncRNA-inter-chr17-13692',
'ncRNA-as-chr17-13834',
'ncRNA-inter-chr9-8147',
'ncRNA-inter-chr10-8697',
'ncRNA-inter-chr6-5551',
'ncRNA-as-chr9-8317',
'ncRNA-inter-chr7-6509',
'ncRNA-as-chr19-14977',
'ncRNA-inter-chr6-5318',
'ncRNA-inter-chr5-4578',
'ncRNA-inter-chr12-10509',
'ncRNA-as-chr10-9015',
'ncRNA-inter-chr3-2411',
'ncRNA-inter-chr9-7875',
'ncRNA-inter-chr5-4336',
'ncRNA-inter-chr12-10910',
'ncRNA-as-chr1-782',
'ncRNA-inter-chr17-13924',
'ncRNA-intra-chr7-5920',
'ncRNA-inter-chr16-13225',
'ncRNA-inter-chr3-2269',
'ncRNA-inter-chr14-12016',
'ncRNA-as-chr4-3800',
'ncRNA-as-chr5-4655',
'ncRNA-inter-chr9-7989',
'ncRNA-intra-chr5-4728',
'ncRNA-inter-chrX-15248',
'ncRNA-inter-chr10-8767',
'ncRNA-inter-chr19-14717',
'ncRNA-inter-chr8-6766',
'ncRNA-inter-chr13-11122',
'ncRNA-inter-chr7-6074',
'ncRNA-inter-chr15-12439',
'ncRNA-as-chr11-9787',
'ncRNA-inter-chr2-1827',
'ncRNA-as-chr19-14976',
'ncRNA-inter-chr19-14947',
'ncRNA-inter-chr6-5248',
'ncRNA-inter-chr2-1098',
'ncRNA-inter-chr8-7180',
'ncRNA-inter-chr9-8118',
'ncRNA-inter-chr14-12199',
'ncRNA-as-chr6-5336',
'ncRNA-inter-chr4-3867',
'ncRNA-inter-chr10-9000',
'ncRNA-inter-chr14-12290',
'ncRNA-inter-chr2-1491',
'ncRNA-inter-chr15-12606',
'ncRNA-inter-chr10-9222',
'ncRNA-inter-chr5-4322',
'ncRNA-inter-chr12-10942',
'ncRNA-inter-chr18-14690',
'ncRNA-inter-chr2-1471',
'ncRNA-inter-chr3-2410',
'ncRNA-inter-chr19-14880',
'ncRNA-inter-chr13-11074',
'ncRNA-inter-chr9-8056',
'ncRNA-inter-chr5-4654',
'ncRNA-inter-chr3-2166',
'ncRNA-inter-chr8-6944',
'ncRNA-as-chr7-6065',
'ncRNA-inter-chr8-6896',
'ncRNA-inter-chr2-1963',
'ncRNA-inter-chr4-3425',
'ncRNA-inter-chr13-11385',
'ncRNA-inter-chr9-7885',
'ncRNA-as-chr10-9411',
'ncRNA-as-chr9-8419',
'ncRNA-as-chr12-10618',
'ncRNA-inter-chr7-6390',
'ncRNA-inter-chr17-14151',
'ncRNA-as-chr13-11787',
'ncRNA-as-chr2-1965',
'ncRNA-inter-chr6-5721',
'ncRNA-inter-chr6-5822',
'ncRNA-inter-chr11-9635',
'ncRNA-inter-chr11-9965',
'ncRNA-inter-chr4-3052',
'ncRNA-inter-chr17-13857',
'ncRNA-inter-chr13-11201',
'ncRNA-inter-chr6-5249',
'ncRNA-inter-chr19-14851',
'ncRNA-inter-chr6-5638',
'ncRNA-inter-chr17-14130',
'ncRNA-inter-chr9-7993',
'ncRNA-inter-chr18-14656',
'ncRNA-inter-chr9-7992',
'ncRNA-inter-chr1-566',
'ncRNA-inter-chr12-10715',
'ncRNA-inter-chr17-14102',
'ncRNA-inter-chr4-3010',
'ncRNA-inter-chr3-2764',
'ncRNA-inter-chr4-3306',
'ncRNA-inter-chr19-14979',
'ncRNA-inter-chr1-570',
'ncRNA-inter-chr19-14790',
'ncRNA-inter-chr4-3282',
'ncRNA-inter-chr5-4777',
'ncRNA-inter-chr8-7605',
'ncRNA-inter-chr9-8000',
'ncRNA-as-chr15-12920',
'ncRNA-as-chr1-369',
'ncRNA-inter-chr19-14952',
'ncRNA-as-chr9-8393',
'ncRNA-as-chr14-12074',
'ncRNA-inter-chr12-10415',
'ncRNA-inter-chr7-6559',
'ncRNA-inter-chr1-630',
'ncRNA-inter-chr4-3142',
'ncRNA-inter-chr6-5131',
'ncRNA-inter-chr16-13050',
'ncRNA-inter-chr7-6411',
'ncRNA-inter-chr5-4746',
'ncRNA-inter-chr1-633',
'ncRNA-inter-chr10-8461',
'ncRNA-inter-chr2-2016',
'ncRNA-inter-chr6-5137',
'ncRNA-as-chr4-3300',
'ncRNA-inter-chr4-3009',
'ncRNA-inter-chr2-1923',
'ncRNA-inter-chr1-670',
'ncRNA-inter-chr15-12835',
'ncRNA-inter-chr18-14655',
'ncRNA-inter-chr16-13211',
'ncRNA-as-chr7-6050',
'ncRNA-inter-chr7-6508',
'ncRNA-inter-chr11-10206',
'ncRNA-inter-chr13-11399',
'ncRNA-inter-chr8-6757',
'ncRNA-inter-chr1-129',
'ncRNA-inter-chr12-10459',
'ncRNA-inter-chr7-6709',
'ncRNA-inter-chr12-10713',
'ncRNA-inter-chr7-6523',
'ncRNA-inter-chr2-2017',
'ncRNA-inter-chr7-6343',
'ncRNA-inter-chr1-63',
'ncRNA-as-chr3-2936',
'ncRNA-inter-chr18-14691',
'ncRNA-inter-chr7-6097',
'ncRNA-inter-chr6-5723')
DefaultAssay(droplet) <- "RNA"
#droplet <- NormalizeData(combined, verbose = TRUE, normalization.method = "RC", scale.factor = 1e6)
combined <- NormalizeData(combined, verbose = TRUE)
DotPlot(combined, features = all_genes)
FeaturePlot(combined, features = genes_hep_main, min.cutoff = "q9")
#hepatocytes
subtissplot <- DotPlot(combined, features = c(genes_hep_main, genes_endo, genes_bec_b_immune, genes_kuppfer, genes_nk))
PC <- DotPlot(combined, features = c(genes_hep_main,genes_zones))
NPC <- DotPlot(combined, features = c(genes_endo,genes_kuppfer, genes_nk))
all <- DotPlot(combined, features=c(all_genes))
### coexpression plots####
f1 <- FeaturePlot(KO.cells, features = c('Cyp2b10','ncRNA-inter-chr7-5998'), reduction = "mds", order = TRUE,split.by = "stim", blend = TRUE,sort.cell = TRUE, max.cutoff = 0.5)
########## this is exact averaging formula ###############33
x <- (AverageExpression(KO.cells, verbose = TRUE, assays = "RNA" ,slot="counts")$RNA)
x["ncRNA-inter-chr7-5998",]
# G171B G171C
#ncRNA-inter-chr7-5998 1.871795 1.091463
########
#Idents(combined) <- factor(Idents(combined), levels = c(0,1,12))
markers.to.plot <- c("Alb","ncRNA-inter-chr7-5998")
DotPlot(combined, features = rev(markers.to.plot), cols = c("blue", "red"), dot.scale = 8,
split.by = "stim") + RotatedAxis()
FeaturePlot(combined, features = c("Alb", "ncRNA-inter-chr7-5998","Cyp2b10","dSaCas9","KRAB","AAV8-mCherry"), split.by = "stim", max.cutoff = 3, cols = c("grey", "red"))
######################### vlnplot ##########################
plots <- VlnPlot(combined, features = c("Alb", "ncRNA-inter-chr7-5998","Cyp2b10","dSaCas9"), split.by = "stim", group.by = "seurat_clusters", pt.size = 0, combine = FALSE)
CombinePlots(plots = plots, ncol = 1)
plots <- VlnPlot(combined, features = c("Lhx4","Dtna","Fam189a1","Galnt16","Kalrn"), split.by = "stim", group.by = "seurat_clusters", pt.size = 0, combine = FALSE)
CombinePlots(plots = plots, ncol = 1)
#endothelial
DotPlot(combined, features = genes_endo)
#zones
zones <- DotPlot(combined, features = genes_zones)
f1 <- FeaturePlot(combined, features = c('Cyp2e1','Cyp2f2','Ass1'), min.cutoff = "q9", reduction = "tsne")
DimPlot(combined, label = TRUE)
save(combined, file="Seurat_smart-drop_integrated.Robj")
################# save raw counts from cluster #####################
Idents(combined) <- "stim"
### to avergae out the matrix from KO cells
combined.raw.data.0.1 <- as.matrix(GetAssayData(combined, slot = "data")[, WhichCells(combined, ident = 0,idents = "stim")])
combined.raw.data.1 <- as.matrix(GetAssayData(combined, slot = "counts")[, WhichCells(combined, ident = 0)])
combined.raw.data.2 <- as.matrix(GetAssayData(combined, slot = "counts")[, WhichCells(combined, ident = 0)])
#combined.raw.data.[i] <- as.matrix(GetAssayData(combined, slot = "counts")[, WhichCells(combined, ident = 1)])
#combined.raw.data.12 <-as.matrix(GetAssayData(combined, slot = "counts")[, WhichCells(combined, ident = 12)])
#combined.raw.data.1 <- as.matrix(GetAssayData(combined, slot = "counts"))
x <- AverageExpression(test.combined,assays = "RNA",add.ident = "stim", slot = "data",use.scale = FALSE, use.counts = FALSE)$RNA
#}######## CAR data
avg.combined.cells <- (AverageExpression(combined, verbose = FALSE)$RNA)
avg.combined.cells$gene <- rownames(avg.combined.cells)
CAR_FP <- FeaturePlot(combined, features = c('Cyp2b10','Nr1i3'), reduction = "umap", order = TRUE,split.by = "stim", blend = TRUE,sort.cell = TRUE, max.cutoff = 1, min.cutoff = 0, pt.size = 0.5, repel = TRUE)
CAR_DOT_NR <- DotPlot(combined, features = 'Nr1i3', col.min = 0)
Cyp2b10_FP <- FeaturePlot(combined, features = 'Cyp2b10', reduction = "umap", min.cutoff = 0)
########### tSNE #################################
combined <- NormalizeData(object = combined)
combined <- FindVariableFeatures(combined, selection.method = "vst", nfeatures = 2000)
G172_TPM_count <- ref.integrated.1
G172_TPM_count <- NormalizeData(G172_TPM_count,assay = "RNA", normalization.method = "RC", scale.factor = 1e6)
TPMcount0M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '0_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '0_G172M1')]))
TPMcount1M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '1_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '1_G172M1')]))
TPMcount2M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '2_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '2_G172M1')]))
TPMcount3M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '3_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '3_G172M1')]))
TPMcount4M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '4_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '4_G172M1')]))
TPMcount5M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '5_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '5_G172M1')]))
TPMcount6M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '6_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '6_G172M1')]))
TPMcount7M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '7_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '7_G172M1')]))
TPMcount8M1<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '8_G172M1')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '8_G172M1')]))
TPMcount0M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '0_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '0_G172M2')]))
TPMcount1M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '1_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '1_G172M2')]))
TPMcount2M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '2_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '2_G172M2')]))
TPMcount3M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '3_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '3_G172M2')]))
TPMcount4M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '4_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '4_G172M2')]))
TPMcount5M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '5_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '5_G172M2')]))
TPMcount6M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '6_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '6_G172M2')]))
TPMcount7M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '7_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '7_G172M2')]))
TPMcount8M2<- cbind(as.matrix(GetAssayData(G172_TPM_count, slot = "counts")[, WhichCells(G172_TPM_count, ident = '8_G172M2')]), as.matrix(GetAssayData(G172_TPM_count, slot = "data")[, WhichCells(G172_TPM_count, ident = '8_G172M2')]))
write.csv(TPMcount0M1, "CountResult/counts_TPMcount0M1")
write.csv(TPMcount1M1, "CountResult/counts_TPMcount1M1")
write.csv(TPMcount2M1, "CountResult/counts_TPMcount2M1")
write.csv(TPMcount3M1, "CountResult/counts_TPMcount3M1")
write.csv(TPMcount4M1, "CountResult/counts_TPMcount4M1")
write.csv(TPMcount5M1, "CountResult/counts_TPMcount5M1")
write.csv(TPMcount6M1, "CountResult/counts_TPMcount6M1")
write.csv(TPMcount7M1, "CountResult/counts_TPMcount7M1")
write.csv(TPMcount8M1, "CountResult/counts_TPMcount8M1")
write.csv(TPMcount0M2, "CountResult/counts_TPMcount0M2")
write.csv(TPMcount1M2, "CountResult/counts_TPMcount1M2")
write.csv(TPMcount2M2, "CountResult/counts_TPMcount2M2")
write.csv(TPMcount3M2, "CountResult/counts_TPMcount3M2")
write.csv(TPMcount4M2, "CountResult/counts_TPMcount4M2")
write.csv(TPMcount5M2, "CountResult/counts_TPMcount5M2")
write.csv(TPMcount6M2, "CountResult/counts_TPMcount6M2")
write.csv(TPMcount7M2, "CountResult/counts_TPMcount7M2")
write.csv(TPMcount8M2, "CountResult/counts_TPMcount8M2")
#avg.KO.cells <- log1p(AverageExpression(KO.cells, verbose = FALSE)$RNA) #original code log transformed
avg.KO.cells <- (AverageExpression(KO.cells, verbose = FALSE)$RNA)
avg.KO.cells$gene <- rownames(avg.KO.cells)
genes.to.label= ("ncRNA-inter-chr7-5998")
#genes.to.label = c("ISG15", "LY6E", "IFI6", "ISG20", "MX1", "IFIT2", "IFIT1", "CXCL10", "CCL8")
p1 <- ggplot(avg.KO.cells, aes(CTRL, STIM)) + geom_point() + ggtitle("CD4 Naive T Cells")
p1 <- LabelPoints(plot = p1, points = genes.to.label, repel = TRUE)
p2 <- ggplot(avg.cd14.mono, aes(CTRL, STIM)) + geom_point() + ggtitle("CD14 Monocytes")
p2 <- LabelPoints(plot = p2, points = genes.to.label, repel = TRUE)
plot_grid(p1, p2)
KO.cells <- RunUMAP(KO.cells, reduction = "pca", dims = 1:20 )
KO.cells <- FindNeighbors(KO.cells, reduction = "pca", dims = 1:20)
KO.cells <- FindClusters(KO.cells, resolution = 0.5 )
KO.cells <- RunTSNE(KO.cells, reduction = "pca", dims = 1:20)
Hep.cells <- RunUMAP(Hep.cells, reduction = "pca", dims = 1:20 )
Hep.cells <- FindNeighbors(Hep.cells, reduction = "pca", dims = 1:20)
Hep.cells <- FindClusters(Hep.cells, resolution = 0.5 )
Hep.cells <- RunTSNE(Hep.cells, reduction = "pca", dims = 1:20)
# Visualization
p1 <- UMAPPlot(KO.cells, reduction = "umap", group.by = "stim")
p2 <- UMAPPlot(KO.cells, reduction = "umap", group.by = "mouse.sex")
p3 <- UMAPPlot(KO.cells, reduction = "umap", label = TRUE)
p4 <- UMAPPlot(KO.cells, label=TRUE)
plot_grid(p1,p4)
DimPlot(KO.cells, reduction = "umap", split.by = "stim")
#hepatocyte cells
p5 <- UMAPPlot(Hep.cells, reduction = "umap", group.by = "stim")
p6 <- UMAPPlot(Hep.cells, reduction = "umap", group.by = "mouse.sex")
p7 <- UMAPPlot(Hep.cells, reduction = "umap", label = TRUE)
p8 <- UMAPPlot(Hep.cells, label=TRUE)
plot_grid(p5,p8)
DimPlot(KO.cells, reduction = "umap", split.by = "stim")
raw.data.KO.0 <- as.matrix(GetAssayData(KO.cells, slot = "counts")[, WhichCells(KO.cells, ident = 0)])
raw.data.KO.1 <- as.matrix(GetAssayData(KO.cells, slot = "counts")[, WhichCells(KO.cells, ident = 1)])
raw.data.KO.2 <-as.matrix(GetAssayData(KO.cells, slot = "counts")[, WhichCells(KO.cells, ident = 2)])
raw.data.KO.3 <-as.matrix(GetAssayData(KO.cells, slot = "counts")[, WhichCells(KO.cells, ident = 3)])
raw.data.KO.4 <-as.matrix(GetAssayData(KO.cells, slot = "counts")[, WhichCells(KO.cells, ident = 4)])
raw.data.KO.5 <-as.matrix(GetAssayData(KO.cells, slot = "counts")[, WhichCells(KO.cells, ident = 5)])
write.csv(raw.data.KO.0, "CountResult/Markers/raw.data.KO.0")
write.csv(raw.data.KO.1, "CountResult/Markers/raw.data.KO.1")
write.csv(raw.data.KO.2, "CountResult/Markers/raw.data.KO.2")
write.csv(raw.data.KO.3, "CountResult/Markers/raw.data.KO.3")
write.csv(raw.data.KO.4, "CountResult/Markers/raw.data.KO.4")
write.csv(raw.data.KO.5, "CountResult/Markers/raw.data.KO.5")
f1 <- FeaturePlot(KO.cells, features = c('ncRNA-inter-chr7-5998'), reduction = "umap", split.by = "stim")
plot_grid(f1,p1,p4)
DefaultAssay(KO.cells) <- "RNA"
KO.cells <- NormalizeData(KO.cells, verbose = FALSE)
plots <- VlnPlot(KO.cells, features = c("Alb", "ncRNA-inter-chr7-5998","Cyp2b10","Cyp2e1","Cyp2f2"), split.by = "stim", group.by = "seurat_clusters", pt.size = 0, combine = FALSE)
CombinePlots(plots = plots, ncol = 1)
Three_five_six <- subset(KO.cells, idents = c("5","6"))
Three_five_six <- RunUMAP(Three_five_six, reduction = "pca", dims = 1:20 )
Three_five_six <- FindNeighbors(Three_five_six, reduction = "pca", dims = 1:20)
Three_five_six <- FindClusters(Three_five_six, resolution = 1 )
Three_five_six <- RunTSNE(Three_five_six, reduction = "pca", dims = 1:20)
p1 <- UMAPPlot(Three_five_six, reduction = "umap", group.by = "stim")
p2 <- UMAPPlot(Three_five_six, reduction = "umap", group.by = "mouse.sex")
p3 <- UMAPPlot(Three_five_six, reduction = "umap", label = TRUE)
p4 <- UMAPPlot(Three_five_six, label=TRUE)
plot_grid(p1,p4)
DimPlot(Three_five_six, reduction = "umap", split.by = "stim")
f1 <- FeaturePlot(Three_five_six, features = c('ncRNA-inter-chr7-5998'), reduction = "umap", split.by = "stim")
lnc5998 <- subset(combined, cells = lnc5998.cells, idents = "1")
lnc5998 <- RunUMAP(lnc5998, reduction = "pca", dims = 1:20 )
lnc5998 <- FindNeighbors(lnc5998, reduction = "pca", dims = 1:20)
lnc5998 <- FindClusters(lnc5998, resolution = 1 )
lnc5998 <- RunTSNE(lnc5998, reduction = "pca", dims = 1:20)
# Visualization
p1 <- UMAPPlot(lnc5998, reduction = "umap", group.by = "stim")
p2 <- UMAPPlot(lnc5998, reduction = "umap", group.by = "mouse.sex")
p3 <- UMAPPlot(lnc5998, reduction = "umap", label = TRUE)
p4 <- UMAPPlot(lnc5998, label=TRUE)
plot_grid(p1,p4)
DimPlot(lnc5998, reduction = "umap", split.by = "stim")
lnc5998.cells <- WhichCells(object = combined, expression = "ncRNA-inter-chr7-5998" > 1)
FeaturePlot(lnc5998, features = c("ncRNA-inter-chr7-5998"), split.by = "stim",
+ cols = c("grey", "red"), cells = lnc5998.cells,min.cutoff = 0.5)
DefaultAssay(lnc5998) <- "RNA"
lnc5998 <- NormalizeData(lnc5998, verbose = FALSE)
plots <- VlnPlot(lnc5998, features = c("Alb", "ncRNA-inter-chr7-5998","Cyp2b10","Cyp2e1","Cyp2f2"), split.by = "stim", group.by = "seurat_clusters", pt.size = 0, combine = FALSE)
CombinePlots(plots = plots, ncol = 1)
d <- dist(t(GetAssayData(KO.cells, slot = "scale.data")))
# Run the MDS procedure, k determines the number of dimensions
mds <- cmdscale(d = d, k = 2)
# cmdscale returns the cell embeddings, we first label the columns to ensure downstream
# consistency
colnames(mds) <- paste0("MDS_", 1:2)
# We will now store this as a custom dimensional reduction called 'mds'
KO.cells[["mds"]] <- CreateDimReducObject(embeddings = mds, key = "MDS_", assay = DefaultAssay(KO.cells))
# We can now use this as you would any other dimensional reduction in all downstream functions
DimPlot(KO.cells, reduction = "mds", pt.size = 0.5)
Find differential markers
KO.cells$celltype.stim <- paste(Idents(KO.cells), KO.cells$stim, sep = "_")
KO.cells$celltype <- Idents(KO.cells)
Idents(KO.cells) <- "celltype.stim"
response3 <- FindMarkers(KO.cells, ident.1 = c("1_G171B","0_G171B","2_G171B"), ident.2 = c("1_G171C", "0_G171C","2_G171C"), verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(response3, n = 15)
#DE1: Compare cluster 0+1+12 (that expressed lnc5998) with Other hepatocyte clusters (2+5+8)
#DE2: compare cluster 1 (showed major effects in the KD) vs Cluster 0 (that showed little KD)
#DE3: For KO.cells that formed five subcluster, compare clusters 3+4+5+1 vs 2+0
#DE4: for KO.cells that formed five clusters. Comapre cluster 4 vs. 2
DE0112.258 <- FindMarkers(combined, ident.1 = c("0","1","12" ), ident.2 = c("2","5","8"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE0112.All <- FindMarkers(combined, ident.1 = c("0","1","12" ), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE1.2 <- FindMarkers(combined, ident.1 = c("1" ), ident.2 = c("2"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE1.5 <- FindMarkers(combined, ident.1 = c("1" ), ident.2 = c("5"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE1.8 <- FindMarkers(combined, ident.1 = c("1" ), ident.2 = c("8"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE2.5 <- FindMarkers(combined, ident.1 = c("2" ), ident.2 = c("5"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE2.8 <- FindMarkers(combined, ident.1 = c("2" ), ident.2 = c("8"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DE5.8 <- FindMarkers(combined, ident.1 = c("5" ), ident.2 = c("8"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK4351.20 <- FindMarkers(KO.cells, ident.1 = c("3","4","5","1" ), ident.2 = c("2","0"),verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK4.3 <- FindMarkers(KO.cells, ident.1 = "4", ident.2 = "3",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK4.2 <- FindMarkers(KO.cells, ident.1 = "4", ident.2 = "2",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK4.0 <- FindMarkers(KO.cells, ident.1 = "4", ident.2 = "0",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK4.1 <- FindMarkers(KO.cells, ident.1 = "4", ident.2 = "1",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK4.5 <- FindMarkers(KO.cells, ident.1 = "4", ident.2 = "5",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
##### comaprison between G171B vs G171C for KO.cell clusters of 0+1+12 ######33
DEK4_C.B <- FindMarkers(KO.cells, ident.1 = "4_G171C", ident.2 = "4_G171B",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK3_C.B <- FindMarkers(KO.cells, ident.1 = "3_G171C", ident.2 = "3_G171B",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK1_C.B <- FindMarkers(KO.cells, ident.1 = "1_G171C", ident.2 = "1_G171B",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK2_C.B <- FindMarkers(KO.cells, ident.1 = "2_G171C", ident.2 = "2_G171B",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK0_C.B <- FindMarkers(KO.cells, ident.1 = "0_G171C", ident.2 = "0_G171B",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
DEK5_C.B <- FindMarkers(KO.cells, ident.1 = "5_G171C", ident.2 = "5_G171B",verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
################################### Write the results #########################
write.csv(DE0112.258, "CountResult/Markers/DE0112.258")
write.csv(DE0112.All, "CountResult/Markers/DE0112.All")
write.csv(DE1.2, "CountResult/Markers/DE1.2")
write.csv(DE1.5, "CountResult/Markers/DE1.5")
write.csv(DE1.8, "CountResult/Markers/DE1.8")
write.csv(DE2.5, "CountResult/Markers/DE2.5")
write.csv(DE2.8, "CountResult/Markers/DE2.8")
write.csv(DE5.8, "CountResult/Markers/DE5.8")
write.csv(DEK4351.20, "CountResult/Markers/DEK4351.20")
write.csv(DEK4.3, "CountResult/Markers/DEK4.3")
write.csv(DEK4.2, "CountResult/Markers/DEK4.2")
write.csv(DEK4.0, "CountResult/Markers/DEK4.0")
write.csv(DEK4.1, "CountResult/Markers/DEK4.1")
write.csv(DEK4.5, "CountResult/Markers/DEK4.5")
write.csv(DEK4_C.B, "CountResult/Markers/DEK4_C.B")
write.csv(DEK3_C.B, "CountResult/Markers/DEK3_C.B")
write.csv(DEK1_C.B, "CountResult/Markers/DEK1_C.B")
write.csv(DEK2_C.B, "CountResult/Markers/DEK2_C.B")
write.csv(DEK0_C.B, "CountResult/Markers/DEK0_C.B")
write.csv(DEK5_C.B, "CountResult/Markers/DEK5_C.B")
combined$celltype.stim <- paste(Idents(combined), combined$stim, sep = "_")
combined$celltype <- Idents(combined)
Idents(combined) <- "celltype.stim"
test.combined$celltype.stim <- paste(Idents(test.combined), test.combined$stim, sep = "_")
test.combined$celltype <- Idents(test.combined)
Idents(test.combined) <- "celltype.stim"
Combined_G171B_vs_G171C <- FindMarkers(combined, ident.1 = c("0_G171B","1_G171B","2_G171B","3_G171B","4_G171B","5_G171B","6_G171B","7_G171B","8_G171B","9_G171B","10_G171B","11_G171B","12_G171B" ), ident.2 = c("0_G171C","1_G171C","2_G171C","3_G171C","4_G171C","5_G171C","6_G171C","7_G171C","8_G171C","9_G171C","10_G171C","11_G171C","12_G171C" ), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust1 <- FindMarkers(combined, ident.1 = c("1_G171C"), ident.2 = c("1_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust0 <- FindMarkers(combined, ident.1 = c("0_G171C"), ident.2 = c("0_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust12 <- FindMarkers(combined, ident.1 = c("12_G171C"), ident.2 = c("12_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust2 <- FindMarkers(combined, ident.1 = c("2_G171C"), ident.2 = c("2_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust5 <- FindMarkers(combined, ident.1 = c("5_G171C"), ident.2 = c("5_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust8 <- FindMarkers(combined, ident.1 = c("8_G171C"), ident.2 = c("8_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust3 <- FindMarkers(combined, ident.1 = c("3_G171C"), ident.2 = c("3_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust4 <- FindMarkers(combined, ident.1 = c("4_G171C"), ident.2 = c("4_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust6 <- FindMarkers(combined, ident.1 = c("6_G171C"), ident.2 = c("6_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust7 <- FindMarkers(combined, ident.1 = c("7_G171C"), ident.2 = c("7_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust9 <- FindMarkers(combined, ident.1 = c("9_G171C"), ident.2 = c("9_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust10 <- FindMarkers(combined, ident.1 = c("10_G171C"), ident.2 = c("10_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
Combined_G171C_vs_G171B_Clust11 <- FindMarkers(combined, ident.1 = c("11_G171C"), ident.2 = c("11_G171B"), verbose = TRUE, logfc.threshold = FALSE,min.pct = FALSE)
write.csv(Combined_G171C_vs_G171B_Clust1, "CountResult/Markers/Combined_G171C_vs_G171B_Clust1")
write.csv(Combined_G171C_vs_G171B_Clust0, "CountResult/Markers/Combined_G171C_vs_G171B_Clust0")
write.csv(Combined_G171C_vs_G171B_Clust12, "CountResult/Markers/Combined_G171C_vs_G171B_Clust12")
write.csv(Combined_G171C_vs_G171B_Clust2, "CountResult/Markers/Combined_G171C_vs_G171B_Clust2")
write.csv(Combined_G171C_vs_G171B_Clust5, "CountResult/Markers/Combined_G171C_vs_G171B_Clust5")
write.csv(Combined_G171C_vs_G171B_Clust8, "CountResult/Markers/Combined_G171C_vs_G171B_Clust8")
write.csv(Combined_G171C_vs_G171B_Clust3, "CountResult/Markers/Combined_G171C_vs_G171B_Clust3")
write.csv(Combined_G171C_vs_G171B_Clust4, "CountResult/Markers/Combined_G171C_vs_G171B_Clust4")
write.csv(Combined_G171C_vs_G171B_Clust6, "CountResult/Markers/Combined_G171C_vs_G171B_Clust6")
write.csv(Combined_G171C_vs_G171B_Clust7, "CountResult/Markers/Combined_G171C_vs_G171B_Clust7")
write.csv(Combined_G171C_vs_G171B_Clust9, "CountResult/Markers/Combined_G171C_vs_G171B_Clust9")
write.csv(Combined_G171C_vs_G171B_Clust10, "CountResult/Markers/Combined_G171C_vs_G171B_Clust10")
write.csv(Combined_G171C_vs_G171B_Clust11, "CountResult/Markers/Combined_G171C_vs_G171B_Clust11")
PC_vs_PP_G171B <- FindMarkers(KO.cells, ident.1 = c("4_G171B","3_G171B"), ident.2 = c("0_G171B","2_G171B"), verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(PC_vs_PP_G171B, n = 15)
PC_vs_PP_G171C <- FindMarkers(KO.cells, ident.1 = c("4_G171C","3_G171C"), ident.2 = c("0_G171C","2_G171C"), verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(PC_vs_PP_G171C, n = 15)
PC_vs_PP_G171BC <- FindMarkers(KO.cells, ident.1 = c("4_G171B","3_G171B","4_G171C","3_G171C"), ident.2 = c("0_G171B","2_G171B","0_G171C","2_G171C"), verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(PC_vs_PP_G171C, n = 15)
lnc5998_KO_DE_1 <- FindMarkers(KO.cells, ident.1 = c("4_G171B","3_G171B","5_G171B"), ident.2 = c("4_G171C","3_G171C","5_G171C"), verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(lnc5998_KO_DE, n = 15)
lnc5998_KO_DE_2 <- FindMarkers(KO.cells, ident.1 = c("4_G171C","3_G171C","5_G171C"), ident.2 =c("4_G171B","3_G171B","5_G171B") , verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(lnc5998_KO_DE, n = 15)
cell.type.genes <- (PC_vs_PP_G171BC[1]) # Takes all the unique cell type specific genes
GOterms = topGOterms(fg.genes = cell.type.genes, bg.genes = rownames(KO.cells@assays$RNA@dataKO.cells@assays$RNA@data), organism = "Mouse")
cell.type.genes <- (PC_vs_PP_G171BC[1]) # Takes all the unique cell type specific genes
GOterms = topGOterms(fg.genes = rownames(cell.type.genes), bg.genes = rownames(KO.cells@assays$RNA@data), organism = "Mouse")
AvergeExpression2 <- function (object, assays = NULL, features = NULL, return.seurat = FALSE,
add.ident = NULL, slot = "data", use.scale = FALSE, use.counts = FALSE,
verbose = TRUE, ...)
{
fxn.average <- switch(EXPR = slot, data = function(x) {
return(mean(x = x))
}, mean)
object.assays <- FilterObjects(object = object, classes.keep = "Assay")
assays <- assays %||% object.assays
ident.orig <- Idents(object = object)
orig.levels <- levels(x = Idents(object = object))
ident.new <- c()
if (!all(assays %in% object.assays)) {
assays <- assays[assays %in% object.assays]
if (length(assays) == 0) {
stop("None of the requested assays are present in the object")
}
else {
warning("Requested assays that do not exist in object. Proceeding with existing assays only.")
}
}
if (!is.null(x = add.ident)) {
new.data <- FetchData(object = object, vars = add.ident)
new.ident <- paste(Idents(object)[rownames(x = new.data)],
new.data[, 1], sep = "_")
Idents(object, cells = rownames(new.data)) <- new.ident
}
data.return <- list()
for (i in 1:length(x = assays)) {
data.use <- GetAssayData(object = object, assay = assays[i],
slot = slot)
features.assay <- features
if (length(x = intersect(x = features, y = rownames(x = data.use))) <
1) {
features.assay <- rownames(x = data.use)
}
data.all <- data.frame(row.names = features.assay)
for (j in levels(x = Idents(object))) {
temp.cells <- WhichCells(object = object, idents = j)
features.assay <- unique(x = intersect(x = features.assay,
y = rownames(x = data.use)))
if (length(x = temp.cells) == 1) {
data.temp <- (data.use[features.assay, temp.cells])
if (slot == "data") {
data.temp <- data.temp
}
}
if (length(x = temp.cells) > 1) {
data.temp <- apply(X = data.use[features.assay,
temp.cells, drop = FALSE], MARGIN = 1, FUN = fxn.average)
}
data.all <- cbind(data.all, data.temp)
colnames(x = data.all)[ncol(x = data.all)] <- j
if (verbose) {
message(paste("Finished averaging", assays[i],
"for cluster", j))
}
if (i == 1) {
ident.new <- c(ident.new, as.character(x = ident.orig[temp.cells[1]]))
}
}
names(x = ident.new) <- levels(x = Idents(object))
data.return[[i]] <- data.all
names(x = data.return)[i] <- assays[[i]]
}
if (return.seurat) {
toRet <- CreateSeuratObject(counts = data.return[[1]],
project = "Average", assay = names(x = data.return)[1],
...)
if (length(x = data.return) > 1) {
for (i in 2:length(x = data.return)) {
toRet[[names(x = data.return)[i]]] <- CreateAssayObject(counts = data.return[[i]])
}
}
if (DefaultAssay(object = object) %in% names(x = data.return)) {
DefaultAssay(object = toRet) <- DefaultAssay(object = object)
}
Idents(toRet, cells = colnames(x = toRet)) <- ident.new[colnames(x = toRet)]
Idents(object = toRet) <- factor(x = Idents(object = toRet),
levels = as.character(x = orig.levels), ordered = TRUE)
toRet <- NormalizeData(object = toRet, verbose = verbose)
toRet <- ScaleData(object = toRet, verbose = verbose)
return(toRet)
}
else {
return(data.return)
}
}
Find differential expression markers
combined.markers <- FindAllMarkers(object = combined, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
combined.markers %>% group_by(cluster) %>% top_n(2, avg_logFC)
KO.markers <- FindAllMarkers(object = KO.cells, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
response3 <- FindMarkers(combined, ident.1 = c("1_G171B","0_G171B","2_G171B"), ident.2 = c("1_G171C", "0_G171C","2_G171C"), verbose = TRUE, test.use = "MAST", logfc.threshold = FALSE,min.pct = FALSE)
head(response3, n = 15)
Visualize top genes in principal components
Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.
PCElbowPlot(object = tiss1)
Choose the number of principal components to use.
# Set number of principal components.
n.pcs = 10
The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale. Higher resolution will give more clusters, lower resolution will give fewer.
For the top-level clustering, aim to under-cluster instead of over-cluster. It will be easy to subset groups and further analyze them below.
# Set resolution
res.used <- 4
tiss1 <- FindClusters(object = tiss1, reduction.type = "pca", dims.use = 1:n.pcs,
resolution = res.used, print.output = 0, save.SNN = TRUE, force.recalc = TRUE)
We use TSNE solely to visualize the data.
# If cells are too spread out, you can raise the perplexity. If you have few cells, try a lower perplexity (but never less than 10).
tiss1 <- RunTSNE(object = tiss1, dims.use = 1:n.pcs, seed.use = 10, perplexity=30)
TSNEPlot(object = tiss1, do.label = T, pt.size = 1.2, label.size = 4)
Compare to previous annotations
previous_annotation = read.csv("/Users/kkarri/Documents/Lab/Single_cell_project/dropseq/Liver_droplet_annotation.csv", stringsAsFactors = FALSE)
cols = c('free_annotation', 'cell_ontology_class')
for (col in cols){
previous_col = paste0('previous_', col)
tiss1@meta.data[, previous_col] <- "NA"
tiss1@meta.data[as.character(previous_annotation$X), previous_col] <- previous_annotation[, col]
print(table(tiss1@meta.data[, previous_col]))
print(table(tiss1@meta.data[, previous_col], tiss@ident))
}
tiss1 = compare_previous_annotation(tiss1, tissue_of_interest, "droplet")
TSNEPlot(object = tiss1, do.return = TRUE, group.by = "previous_cell_ontology_class")
table(tiss1@meta.data[, "previous_cell_ontology_class"], tiss@ident)
tiss1 = compare_previous_annotation(tiss1, tissue_of_interest, "droplet")
TSNEPlot(object = tiss1, do.return = TRUE, group.by = "previous_cell_ontology_class")
table(tiss1@meta.data[, "previous_cell_ontology_class"], tiss1@ident)
TSNEPlot(tiss1, group.by="mouse.sex")
TSNEPlot(tiss1, group.by="mouse.id")
Significant genes:
hepatocyte: Alb, Ttr, Apoa1, and Serpina1c pericentral: Cyp2e1, Glul, Oat, Gulo midlobular: Ass1, Hamp, Gstp1, Ubb periportal: Cyp2f2, Pck1, Hal, Cdh1
endothelial cells: Pecam1, Nrp1, Kdr+ and Oit3+ Kuppfer cells: Emr1, Clec4f, Cd68, Irf7 NK/NKT cells: Zap70, Il2rb, Nkg7, Cxcr6, Klr1c, Gzma B cells: Cd79a, Cd79b, Cd74 and Cd19 Immune cells: Ptprc
Dotplots let you see the intensity of exppression and the fraction of cells expressing for each of your genes of interest. The radius shows you the percent of cells in that cluster with at least one read sequenced from that gene. The color level indicates the average Z-score of gene expression for cells in that cluster, where the scaling is done over taken over all cells in the sample.
We have various immune cell types in the last cluster
Using the markers above, we can confidentaly label many of the clusters:
19: endothelial cells 20: bile duct epithelial cells 21: immune cells rest are hepatocytes
We will add those cell_ontology_classes to the dataset.
tiss1 <- StashIdent(object = tiss1, save.name = "cluster.ids")
cluster.ids <- c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
free_annotation <- c(
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
"bile duct epithelial cells",
"endothelial cell of hepatic sinusoid",
NA
)
cell_ontology_class <- c(
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"hepatocyte",
"duct epithelial cell",
"endothelial cell of hepatic sinusoid",
"hepatocyte")
tiss1 = stash_annotations(tiss1, cluster.ids, free_annotation, cell_ontology_class)
Checking for batch effects
Color by metadata, like plate barcode, to check for batch effects.
TSNEPlot(object = tiss1, do.return = TRUE, group.by = "channel")
TSNEPlot(object = tiss1, do.return = TRUE, group.by = "free_annotation")
Subcluster
Let’s drill down on the hepatocytes.
subtiss1 = SubsetData(tiss1, ident.use = c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20))
subtiss1 <- subtiss1 %>% ScaleData() %>%
FindVariableGenes(do.plot = FALSE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
RunPCA(do.print = FALSE)
PCHeatmap(object = subtiss1, pc.use = 1:3, cells.use = 20, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)
PCElbowPlot(subtiss1)
sub.n.pcs = 8
sub.res.use = 0.5
subtiss1 <- subtiss1 %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs,
resolution = sub.res.use, print.output = 0, save.SNN = TRUE, force.recalc = TRUE) %>%
RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=8)
TSNEPlot(object = subtiss1, do.label = T, pt.size = 1, label.size = 4)
BuildClusterTree(subtiss1)
From these genes, it appears that the clusters represent:
0: midlobular male 1: pericentral female 2: periportal female 3: periportal male 4: midlobular male 5: pericentral male 6: midlobular female 7: midlobular female
The multitude of clusters of each type correspond mostly to individual animals/sexes.
table(FetchData(subtiss1, c('mouse.sex','ident')) %>% droplevels())
sub.cluster.ids <- c(0, 1, 2, 3, 4, 5, 6, 7)
sub.free_annotation <- c("periportal female", "midlobular male", "pericentral female", "periportal male", "midlobular male", "pericentral male", "midlobular female", "midlobular female")
sub.cell_ontology_class <- c("hepatocyte", "hepatocyte", "hepatocyte", "hepatocyte", "hepatocyte", "hepatocyte", "hepatocyte", "hepatocyte")
subtiss1 = stash_annotations(subtiss1, sub.cluster.ids, sub.free_annotation, sub.cell_ontology_class)
tiss1 = stash_subtiss_in_tiss(tiss1, subtiss1)
Liver zonation markers
genes_zones = c('Cyp2e1', 'Glul', 'Oat', 'Gulo',
'Ass1', 'Hamp', 'Gstp1', 'Ubb',
'Cyp2f2', 'Pck1', 'Hal', 'Cdh1')
FeaturePlot(subtiss1,c(genes_zones),cols.use = c("grey", "red"), pt.size = 1, nCol = 4)
DotPlot(subtiss1,c(genes_zones), plot.legend = T, col.max = 2.5, do.return = T) + coord_flip()
TSNEPlot(object = subtiss1, do.label = T, pt.size = 1, label.size = 4, group.by="free_annotation")
TSNEPlot(object = tiss1, do.label = T, pt.size = 1, label.size = 4, group.by="free_annotation")
Find cluster markers for lncRNAs
MIN_LOGFOLD_CHANGE = 1 # set to minimum required average log fold change in gene expression.
MIN_PCT_CELLS_EXPR_GENE = 0.1
all.markers = FindAllMarkers(tiss1,
min.pct = MIN_PCT_CELLS_EXPR_GENE,
logfc.threshold = MIN_LOGFOLD_CHANGE,
only.pos = TRUE,
test.use="bimod") # likelihood ratio test
lnc_all_markers <- grep(pattern = "^ncRNA", x= rownames(all.markers), value = TRUE)
lnc_all_markers
#[1] "ncRNA_inter_chr10_92081" "ncRNA_intra_chr16_13383" "ncRNA_inter_chr17_13605" "ncRNA_inter_chr14_11815"
#[5] "ncRNA_inter_chr18_14344"
FeaturePlot(subtiss1,c(lnc_all_markers),cols.use = c("grey", "red"), pt.size = 1, nCol = 4)
######################### lncRNA markers- CELL TYPE MARKER ############
markers.hep <- FindMarkers(object = tiss1, ident.1 = c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20), ident.2 = c(18,19),only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
lnc_markers_hep <- grep(pattern = "^ncRNA", x= rownames(markers.hep), value = TRUE)
lnc_markers_hep
FeaturePlot(tiss1,c(lnc_markers_hep),cols.use = c("grey", "red"), pt.size = 1, nCol = 4)
DotPlot(tiss1,lnc_markers_hep, plot.legend = T, col.max = 2.5, do.return = T) + coord_flip()
#[1] "ncRNA_as_chr11_9423" "ncRNA_as_chr7_6166" "ncRNA_inter_chr4_3295" "ncRNA_inter_chr17_14026"
#[5] "ncRNA_inter_chr3_2915" "ncRNA_inter_chr5_4547" "ncRNA_inter_chr15_12684"
markers.hep.MAST <- FindMarkers(object = tiss1, ident.1 = c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20), ident.2 = c(18,19),only.pos = TRUE, test.use = "MAST")
lnc_markers_hep_MAST_TABLE <- subset(markers.hep.MAST, grepl("^ncRNA", rownames(markers.hep.MAST)))
lnc_markers_hep_MAST <- grep(pattern = "^ncRNA", x= rownames(markers.hep.MAST), value = TRUE)
lnc_markers_hep_MAST
markers.endo <- FindMarkers(object = tiss1, ident.1 = c(18,19), only.pos = TRUE, min.pct = 0.25, thresh.use = 0.5)
lnc_markers_endo <- grep(pattern = "^ncRNA", x= rownames(markers.endo), value = TRUE)
lnc_markers_endo
FeaturePlot(tiss1,c(lnc_markers_endo),cols.use = c("grey", "red"), pt.size = 1, nCol = 4)
DotPlot(tiss1,lnc_markers_endo, plot.legend = T, col.max = 2.5, do.return = T) + coord_flip()
#"ncRNA_inter_chr15_12770", "ncRNA_inter_chr12_10817", "ncRNA_as_chr13_11451",
markers.endo.MAST <- FindMarkers(object = tiss1, ident.1 = 19, test.use = "MAST" ,only.pos = TRUE)
lnc_markers_endo_MAST_TABLE <- subset(markers.endo.MAST, grepl("^ncRNA", rownames(markers.endo.MAST)))
lnc_markers_endo_MAST <- grep(pattern = "^ncRNA", x= rownames(markers.endo.MAST), value = TRUE)
lnc_markers_endo_MAST
################## lncRNA expression ########################3
# "ncRNA_inter_chr17_13605" , "ncRNA_intra_chr16_13383"
########## Periporal markers- zonation markers ############
markers.pc <- FindMarkers(object = subtiss1, ident.1 = c(2,5),
only.pos = FALSE, min.pct = 0.001, thresh.use = 0.001, test.use = "bimod" )
markers.pc.MAST <- FindMarkers(object = subtiss1, ident.1 = c(2,5), ident.2 = c(0,3), test.use = "MAST" ,only.pos = TRUE)
lnc_markers_pc <- subset(markers.pc, grepl("^ncRNA", rownames(markers.pc)))
lnc_markers_pc <- grep(pattern = "^ncRNA", x= rownames(markers.pc), value = TRUE)
lnc_markers_pc
markers.pc.MAST <- FindMarkers(object = subtiss1, ident.1 = c(2,5), ident.2 = c(0,3), test.use = "MAST" ,only.pos = TRUE)
lnc_markers_pc_MAST <- subset(markers.pc.MAST, grepl("^ncRNA", rownames(markers.pc.MAST)))
lnc_markers_pc_MAST <- grep(pattern = "^ncRNA", x= rownames(markers.pc.MAST), value = TRUE)
lnc_markers_pc_MAST
DotPlot(tiss1, lnc_markers_pc, plot.legend = T, col.max = 2.5, do.return = T, group.by="free_annotation") + coord_flip()
FeaturePlot(subtiss1,c(lnc_markers_pc),cols.use = c("grey", "red"), pt.size = 1, nCol = 4)
############################### midlobular genes #############
markers.mid <- FindMarkers(object = subtiss1, ident.1 = c(1,4,6,7),
only.pos = FALSE, min.pct = 0.001, thresh.use = 0.05)
lnc_markers_mid <- subset(markers.mid, grepl("^ncRNA", rownames(markers.mid)))
lnc_markers_mid <- grep(pattern = "^ncRNA", x= rownames(markers.mid), value = TRUE)
lnc_markers_mid
DotPlot(tiss1, lnc_markers_mid, plot.legend = T, col.max = 2.5, do.return = T, group.by="free_annotation") + coord_flip()
FeaturePlot(subtiss1,c(lnc_markers_mid),cols.use = c("grey", "red"), pt.size = 1, nCol = 4)
markers.mid.MAST <- FindMarkers(object = subtiss1, ident.1 = c(1,4,6,7),test.use = "MAST",only.pos = TRUE )
lnc_markers_mid_MAST_TABLE <- subset(markers.mid.MAST, grepl("^ncRNA", rownames(markers.mid.MAST)))
lnc_markers_mid_MAST <- grep(pattern = "^ncRNA", x= rownames(markers.mid.MAST), value = TRUE)
lnc_markers_mid_MAST
#####3 periportalmarker genes############3
markers.pp <- FindMarkers(object = subtiss1, ident.1 = c(0,3),
only.pos = FALSE, min.pct = 0.001, thresh.use = 0.05)
lnc_markers_pp <- subset(markers.pp, grepl("^ncRNA", rownames(markers.pp)))
lnc_markers_pp <- grep(pattern = "^ncRNA", x= rownames(markers.pp), value = TRUE)
lnc_markers_pp
markers.pp.MAST <- FindMarkers(object = subtiss1, ident.1 = c(0,3), ident.2 = c(2,5),test.use = "MAST",only.pos = TRUE )
lnc_markers_pp_MAST_TABLE <- subset(markers.pp.MAST, grepl("^ncRNA", rownames(markers.pp.MAST)))
lnc_markers_pp_MAST <- grep(pattern = "^ncRNA", x= rownames(markers.pp.MAST), value = TRUE)
lnc_markers_pp_MAST
FeaturePlot(subtiss1,c(lnc_markers_pp),cols.use = c("grey", "red"), pt.size = 1, nCol = 4, max.cutoff = 1)
DotPlot(tiss1, c(lnc_markers_pp,"Cyp2e1","Cyp2f2"), plot.legend = T, col.max = 2.5, do.return = T, group.by= "free_annotation") + coord_flip()
################## amle and female specific ############################
markers.female <- FindMarkers(object = subtiss1, ident.1 = c(0,2,6,7),
only.pos = TRUE, min.pct = 0.1, logfc.threshold = 1)
lnc_markers_female <- subset(markers.female, grepl("^ncRNA", rownames(markers.female)))
lnc_markers_female <- grep(pattern = "^ncRNA", x= rownames(markers.female), value = TRUE)
lnc_markers_female
FeaturePlot(subtiss1,c(lnc_markers_female),cols.use = c("grey", "red"), pt.size = 1, nCol = 4, max.cutoff = 1)
DotPlot(tiss1, c(lnc_markers_female,"Cyp2e1","Cyp2f2"), plot.legend = T, col.max = 2.5, do.return = T, group.by= "free_annotation") + coord_flip()
markers.male <- FindMarkers(object = subtiss1, ident.1 = c(1,3,4,5),
only.pos = TRUE, min.pct = 0.001, thresh.use = 0.05)
lnc_markers_male <- subset(markers.male, grepl("^ncRNA", rownames(markers.male)))
lnc_markers_male <- grep(pattern = "^ncRNA", x= rownames(markers.male), value = TRUE)
lnc_markers_male
FeaturePlot(subtiss1,c(lnc_markers_male),cols.use = c("grey", "red"), pt.size = 1, nCol = 4, max.cutoff = 1)
DotPlot(tiss1, c(lnc_markers_male,"Cyp2e1","Cyp2f2"), plot.legend = T, col.max = 2.5, do.return = T, group.by= "free_annotation") + coord_flip()
############################ Female zonate specific genes ###################################
markers.pericentral.female <- FindMarkers(object = tiss1, ident.1 = c(6,11,14,20), test.use = "MAST",
only.pos = TRUE, min.pct = 0.1, ident.2 = c(2,3,15,12,13,8,5,16), logfc.threshold = 1)
markers.periportal.female <- FindMarkers(object = tiss1, ident.1 = c(2,3,15),
only.pos = TRUE, min.pct = 0.1, ident.2 = c(6,11,14,20,12,13,8,5,16), logfc.threshold = 1)
markers.pericentral.male <- FindMarkers(object = tiss1, ident.1 = c(13,12), test.use = "MAST",
only.pos = TRUE, min.pct = 0.1, ident.2 = c(2,3,15,8,5,16,6,11,14,20), logfc.threshold = 1)
markers.periportal.male <- FindMarkers(object = tiss1, ident.1 = c(8,5,16), test.use = "MAST",
only.pos = TRUE, min.pct = 0.1, ident.2 = c(2,3,15,13,12,6,11,14,20), logfc.threshold = 1)
############### xeno-lncs CAR?RXR ##################
FeaturePlot(tiss1,c("ncRNA_inter_chr15_12684","ncRNA_inter_chr8_7430","ncRNA_inter_chr7_6222"),cols.use = c("grey", "red"), pt.size = 1, nCol = 4, max.cutoff = 1)
#######################################################################
markers.endo.2 <- FindMarkers(object = seurat_drop, logfc.threshold = 2,ident.1 = "Endothelial",
only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
lnc.endo.2 <- grep(pattern = "^ncRNA", x= rownames(markers.endo.2), value = TRUE)
lnc.endo.2
Zonated lncRNAs
pp_zontaed <- c('ncRNA_inter_chr14_12016','ncRNA_as_chr19_15090','ncRNA_inter_chr10_9351','ncRNA_inter_chr16_13170',
'ncRNA_inter_chr3_2697','ncRNA_inter_chr1_274','ncRNA_as_chr6_5518','ncRNA_inter_chr14_12066','ncRNA_intra_chr12_10871',
'ncRNA_inter_chr16_13510','ncRNA_inter_chr3_2314','ncRNA_inter_chr10_9264,'ncRNA_inter_chr9_8122')
Checking for batch effects
Color by metadata, like plate barcode, to check for batch effects.
TSNEPlot(object = subtiss1, do.return = TRUE, group.by = "mouse.sex")
Final coloring
Color by cell ontology class on the original TSNE.
TSNEPlot(object = tiss1, do.return = TRUE, group.by = "cell_ontology_class")
Save the Robject for later
filename = here('00_data_ingest', '04_tiss1ue_robj_generated',
paste0("droplet_", tiss1ue_of_interest, "refinedcells_seurat_tiss1.Robj"))
print(filename)
save(tiss1, file=filename)
# To reload a saved object
filename = here('00_data_ingest', '04_tiss1ue_robj_generated',
paste0("droplet_", tissue_of_interest, "seurat_smartdrop-integrated-8272019.Robj"))
load(file=filename)
LS0tCiB0aXRsZTogIkxpdmVyIERyb3BsZXQtIFJhdyBkYXRhIE5vdGVib29rIgogb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCgoKYGBge3J9CnRpc3N1ZV9vZl9pbnRlcmVzdCA9ICJMaXZlciIKbGlicmFyeShoZXJlKQpzb3VyY2UoIi9yZXN0cmljdGVkL3Byb2plY3RuYi93YXhtYW5sYWIva2thcnJpL3NjUk5Bc2VxX2RhdGFfaW50ZWdyYXRpb24vYm9pbGVycGxhdGUuUiIpCiN0aXNzID0gbG9hZF90aXNzdWVfZHJvcGxldCh0aXNzdWVfb2ZfaW50ZXJlc3QpCiNsaWJyYXJ5KHNjYXRlcikKbGlicmFyeShkcGx5cikKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoY293cGxvdCkKI2xpYnJhcnkoTUFTVCkKcmVxdWlyZShzdHJpbmdyKQpyZXF1aXJlKHJlc2hhcGUyKQpyZXF1aXJlKGdncGxvdDIpCnJlcXVpcmUoTUFTUykKbGlicmFyeSh0b29scykKcmVxdWlyZShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdnZm9ydGlmeSkKbGlicmFyeSh0aWR5dmVyc2UpCnJlcXVpcmUoZHBseXIpCmxpYnJhcnkobWlzY1Rvb2xzKQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KFJ0c25lKQpsaWJyYXJ5KGdncmVwZWwpCgpgYGAKCkcxNzIKCmBgYHtyfQoKRzE3Mi51bWlzIDwtIFJlYWQxMFgoIi9uZXQvd2F4bWFuLXNlcnZlci9tbnQvZGF0YS93YXhtYW5sYWJ2bV9ob21lL2trYXJyaS9HMTcyLzEwWF9UQ1BPX3ByZW1STkFfVHJhbnNjcmlwdC9vdXRzL2ZpbHRlcmVkX2ZlYXR1cmVfYmNfbWF0cml4IikKCiNHMTcyLnVtaXMucmF3IDwtIFJlYWQxMFgoIi9uZXQvd2F4bWFuLXNlcnZlci9tbnQvZGF0YS93YXhtYW5sYWJ2bV9ob21lL2trYXJyaS9HMTcyLzEwWF9UQ1BPX3ByZW1STkFfVHJhbnNjcmlwdC9vdXRzL3Jhd19mZWF0dXJlX2JjX21hdHJpeC8iKQoKRzE3Mi5odG9zIDwtIFJlYWQxMFgoIi9uZXQvd2F4bWFuLXNlcnZlci9tbnQvZGF0YS93YXhtYW5sYWJ2bV9ob21lL2trYXJyaS9HMTcyL0hBU0hfQ2l0ZXNlcS9IQVNIX1Jlc3VsdHNfZmlsdGVyZWQtMTBYLUJDL3VtaV9jb3VudCIsIGdlbmUuY29sdW1uPTEpCgojIFNlbGVjdCBjZWxsIGJhcmNvZGVzIGRldGVjdGVkIGJ5IGJvdGggUk5BIGFuZCBIVE8gSW4gdGhlIGV4YW1wbGUgZGF0YXNldHMgd2UgaGF2ZSBhbHJlYWR5CiMgZmlsdGVyZWQgdGhlIGNlbGxzIGZvciB5b3UsIGJ1dCBwZXJmb3JtIHRoaXMgc3RlcCBmb3IgY2xhcml0eS4Kam9pbnQuYmNzIDwtIGludGVyc2VjdChjb2xuYW1lcyhHMTcyLnVtaXMpLCBjb2xuYW1lcyhHMTcyLmh0b3MpKQojIFN1YnNldCBSTkEgYW5kIEhUTyBjb3VudHMgYnkgam9pbnQgY2VsbCBiYXJjb2Rlcwpqb2ludF9jaXRlMV9jaXRlMiA8LSBpbnRlcnNlY3QoY29sbmFtZXMoRzE3Mi5odG9zKSwgY29sbmFtZXMoZGYyKSkKRzE3Mi51bWlzIDwtIEcxNzIudW1pc1ssIGpvaW50LmJjc10KRzE3Mi5odG9zIDwtIGFzLm1hdHJpeChHMTcyLmh0b3NbLCBqb2ludC5iY3NdKQpHMTcyLmh0b3MgPC0gRzE3Mi5odG9zWy01LF0KCiMgQ29uZmlybSB0aGF0IHRoZSBIVE8gaGF2ZSB0aGUgY29ycmVjdCBuYW1lcwpyb3duYW1lcyhHMTcyLmh0b3MpCgojIFNldHVwIFNldXJhdCBvYmplY3QKRzE3Mi5oYXNodGFnIDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBHMTcyLnVtaXMpCiMgTm9ybWFsaXplIFJOQSBkYXRhIHdpdGggbG9nIG5vcm1hbGl6YXRpb24KRzE3Mi5oYXNodGFnIDwtIE5vcm1hbGl6ZURhdGEoRzE3Mi5oYXNodGFnKQojIEZpbmQgYW5kIHNjYWxlIHZhcmlhYmxlIGZlYXR1cmVzCkcxNzIuaGFzaHRhZyA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhHMTcyLmhhc2h0YWcsIHNlbGVjdGlvbi5tZXRob2QgPSAibWVhbi52YXIucGxvdCIpCkcxNzIuaGFzaHRhZyA8LSBTY2FsZURhdGEoRzE3Mi5oYXNodGFnLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5oYXNodGFnKSkKIyBBZGQgSFRPIGRhdGEgYXMgYSBuZXcgYXNzYXkgaW5kZXBlbmRlbnQgZnJvbSBSTkEKRzE3Mi5oYXNodGFnW1siSFRPIl1dIDwtIENyZWF0ZUFzc2F5T2JqZWN0KGNvdW50cyA9IEcxNzIuaHRvcykKIyBOb3JtYWxpemUgSFRPIGRhdGEsIGhlcmUgd2UgdXNlIGNlbnRlcmVkIGxvZy1yYXRpbyAoQ0xSKSB0cmFuc2Zvcm1hdGlvbgpHMTcyLmhhc2h0YWcgPC0gTm9ybWFsaXplRGF0YShHMTcyLmhhc2h0YWcsIGFzc2F5ID0gIkhUTyIsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkNMUiIpCgojIElmIHlvdSBoYXZlIGEgdmVyeSBsYXJnZSBkYXRhc2V0IHdlIHN1Z2dlc3QgdXNpbmcga19mdW5jdGlvbiA9ICdjbGFyYScuIFRoaXMgaXMgYSBrLW1lZG9pZAojIGNsdXN0ZXJpbmcgZnVuY3Rpb24gZm9yIGxhcmdlIGFwcGxpY2F0aW9ucyBZb3UgY2FuIGFsc28gcGxheSB3aXRoIGFkZGl0aW9uYWwgcGFyYW1ldGVycyAoc2VlCiMgZG9jdW1lbnRhdGlvbiBmb3IgSFRPRGVtdXgoKSkgdG8gYWRqdXN0IHRoZSB0aHJlc2hvbGQgZm9yIGNsYXNzaWZpY2F0aW9uIEhlcmUgd2UgYXJlIHVzaW5nIHRoZQojIGRlZmF1bHQgc2V0dGluZ3MKRzE3Mi5oYXNodGFnIDwtIEhUT0RlbXV4KEcxNzIuaGFzaHRhZywgYXNzYXkgPSAiSFRPIiwgcG9zaXRpdmUucXVhbnRpbGUgPSAwLjk5LCBrZnVuYyA9ICdjbGFyYScpCiMgR2xvYmFsIGNsYXNzaWZpY2F0aW9uIHJlc3VsdHMKdGFibGUoRzE3Mi5oYXNodGFnJEhUT19jbGFzc2lmaWNhdGlvbi5nbG9iYWwpCnRhYmxlKEcxNzIuaGFzaHRhZyRoYXNoLklEKQoKIyBHcm91cCBjZWxscyBiYXNlZCBvbiB0aGUgbWF4IEhUTyBzaWduYWwKSWRlbnRzKEcxNzIuaGFzaHRhZykgPC0gImhhc2guSUQiClJpZGdlUGxvdChHMTcyLmhhc2h0YWcsIGFzc2F5ID0gIkhUTyIsIGZlYXR1cmVzID0gcm93bmFtZXMoRzE3Mi5oYXNodGFnW1siSFRPIl1dKVsxOjRdLCBuY29sID0gMiwgbnJvdz0yKQoKI0lkZW50cyhHMTcyLmhhc2h0YWcpIDwtICJIVE9fY2xhc3NpZmljYXRpb24uZ2xvYmFsIgoKIyBGaXJzdCwgd2Ugd2lsbCByZW1vdmUgbmVnYXRpdmUgY2VsbHMgZnJvbSB0aGUgb2JqZWN0CkcxNzIuaGFzaHRhZy5zdWJzZXQgPC0gc3Vic2V0KEcxNzIuaGFzaHRhZywgaWRlbnRzID1jKCJOZWdhdGl2ZSIsIkRvdWJsZXQiKSwgaW52ZXJ0ID0gVFJVRSkKCiMjIEZlYXR1cmUgc2NhdHRlcnBsb3QgZm9yIGhhc3RhZ3MgSURzICMjIyMjIyMjCkZlYXR1cmVTY2F0dGVyKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGZlYXR1cmUxID0gIk0xLUFUR0FUR0FBQ0FHQ0NBRyIsIGZlYXR1cmUyID0gIk0yLVRHQUNHQ0NHVFRHVFRHVCIpCkZlYXR1cmVTY2F0dGVyKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGZlYXR1cmUxID0gIk0xLUFUR0FUR0FBQ0FHQ0NBRyIsIGZlYXR1cmUyID0gIk0zLUdDQ1RBR1RBVEdBVENDQSIpCkZlYXR1cmVTY2F0dGVyKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGZlYXR1cmUxID0gIk0xLUFUR0FUR0FBQ0FHQ0NBRyIsIGZlYXR1cmUyID0gIk00LUFHVENBQ0FHVEFUVENDQSIpCkZlYXR1cmVTY2F0dGVyKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGZlYXR1cmUxID0gIk0yLVRHQUNHQ0NHVFRHVFRHVCIsIGZlYXR1cmUyID0gIk0zLUdDQ1RBR1RBVEdBVENDQSIpCkZlYXR1cmVTY2F0dGVyKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGZlYXR1cmUxID0gIk0yLVRHQUNHQ0NHVFRHVFRHVCIsIGZlYXR1cmUyID0gIk00LUFHVENBQ0FHVEFUVENDQSIpCkZlYXR1cmVTY2F0dGVyKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGZlYXR1cmUxID0gIk0zLUdDQ1RBR1RBVEdBVENDQSIsIGZlYXR1cmUyID0gIk00LUFHVENBQ0FHVEFUVENDQSIpCgoKIyBDYWxjdWxhdGUgYSBkaXN0YW5jZSBtYXRyaXggdXNpbmcgSFRPCmh0by5kaXN0Lm10eCA8LSBhcy5tYXRyaXgoZGlzdCh0KEdldEFzc2F5RGF0YShvYmplY3QgPSBHMTcyLmhhc2h0YWcuc3Vic2V0LCBhc3NheSA9ICJIVE8iKSkpKQoKIyBDYWxjdWxhdGUgdFNORSBlbWJlZGRpbmdzIHdpdGggYSBkaXN0YW5jZSBtYXRyaXgKRzE3Mi5oYXNodGFnLnN1YnNldCA8LSBSdW5UU05FKEcxNzIuaGFzaHRhZy5zdWJzZXQsIGRpc3RhbmNlLm1hdHJpeCA9IGh0by5kaXN0Lm10eCwgcGVycGxleGl0eSA9IDEwMCkKRGltUGxvdChHMTcyLmhhc2h0YWcuc3Vic2V0KQpIVE9IZWF0bWFwKEcxNzIuaGFzaHRhZywgYXNzYXkgPSAiSFRPIiwgbmNlbGxzID0gMjY3NDApCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgUmVzY3VlIGRvdWJsZXRzICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpHMTcyLmRvdWJsZXQgPC0gc3Vic2V0KEcxNzIuaGFzaHRhZywgaWRlbnRzID0gIkRvdWJsZXQiKQpHMTcyLmRvdWJsZXQucmVzY3VlIDwtIEhUT0RlbXV4KEcxNzIuZG91YmxldCwgYXNzYXkgPSAiSFRPIiwgcG9zaXRpdmUucXVhbnRpbGUgPSAwLjk5LCBrZnVuYyA9ICdjbGFyYScpCklkZW50cyhHMTcyLmRvdWJsZXQucmVzY3VlKSA8LSAiaGFzaC5JRCIKUmlkZ2VQbG90KEcxNzIuZG91YmxldC5yZXNjdWUsIGFzc2F5ID0gIkhUTyIsIGZlYXR1cmVzID0gcm93bmFtZXMoRzE3Mi5kb3VibGV0LnJlc2N1ZVtbIkhUTyJdXSlbMTo0XSwgbmNvbCA9IDIsIG5yb3c9MikKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgRXh0cmFjdCB0aGUgc2luZ2xldHMgTTEgIyMjIyMjIyMjIyMjIzMKRzE3Mi5NMSA8LSBzdWJzZXQoRzE3Mi5oYXNodGFnLCBpZGVudHMgPSAiTTEtQVRHQVRHQUFDQUdDQ0FHIiwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNTAwICYgbkNvdW50X1JOQSA+IDEwMDApCkcxNzIuTTEkc3RpbSAgPC0gIkcxNzJNMSIKRGVmYXVsdEFzc2F5KEcxNzIuTTEpIDwtICJSTkEiCkcxNzIuTTEgPC0gU0NUcmFuc2Zvcm0oRzE3Mi5NMSx2ZXJib3NlID1UUlVFKQojIFNlbGVjdCB0aGUgdG9wIDEwMDAgbW9zdCB2YXJpYWJsZSBmZWF0dXJlcwpHMTcyLk0xIDwtIE5vcm1hbGl6ZURhdGEoRzE3Mi5NMSwgdmVyYm9zZSA9IEZBTFNFKQpHMTcyLk0xIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTEsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKIyBTY2FsaW5nIFJOQSBkYXRhLCB3ZSBvbmx5IHNjYWxlIHRoZSB2YXJpYWJsZSBmZWF0dXJlcyBoZXJlIGZvciBlZmZpY2llbmN5CkcxNzIuTTEgPC0gU2NhbGVEYXRhKEcxNzIuTTEsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhHMTcyLk0xKSkKIyBSdW4gUENBCkcxNzIuTTEgPC0gUnVuUENBKEcxNzIuTTEsbnBjcyA9IDMwLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NMSkpCiMgV2Ugc2VsZWN0IHRoZSB0b3AgMTAgUENzIGZvciBjbHVzdGVyaW5nIGFuZCB0U05FIGJhc2VkIG9uIFBDRWxib3dQbG90CkcxNzIuTTEgPC0gUnVuVU1BUChHMTcyLk0xLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjUpCkcxNzIuTTEgPC0gRmluZE5laWdoYm9ycyhHMTcyLk0xLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjUpCkcxNzIuTTEgPC0gRmluZENsdXN0ZXJzKEcxNzIuTTEsIHJlc29sdXRpb24gPSAwLjYgKSAgIApHMTcyLk0xLnAxPC0gVU1BUFBsb3QoRzE3Mi5NMSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbD1UUlVFLCBsYWJlbC5zaXplPTUpCkcxNzIuTTEucDEKRGVmYXVsdEFzc2F5KEcxNzIuTTEpIDwtICJSTkEiCkcxNzIuTTEgPC0gTm9ybWFsaXplRGF0YShHMTcyLk0xLCB2ZXJib3NlID0gVFJVRSkKZDEgPC0gRG90UGxvdChHMTcyLk0xLCBmZWF0dXJlcyA9IGFsbF9nZW5lcykrUm90YXRlZEF4aXMoKQpwbG90X2dyaWQoRzE3Mi5NMS5wMSxkMSkKCgojIEV4dHJhY3QgdGhlIHNpbmdsZXQgZm9yIE0yICMjIyMjIyMjIyMjIyMzCkcxNzIuTTIgPC0gc3Vic2V0KEcxNzIuaGFzaHRhZywgaWRlbnRzID0gIk0yLVRHQUNHQ0NHVFRHVFRHVCIsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDUwMCAmIG5Db3VudF9STkEgPiAxMDAwKQpHMTcyLk0yJHN0aW0gIDwtICJHMTcyTTIiCkRlZmF1bHRBc3NheShHMTcyLk0yKSA8LSAiUk5BIgpHMTcyLk0yIDwtIFNDVHJhbnNmb3JtKEcxNzIuTTIsdmVyYm9zZSA9VFJVRSkKIyBTZWxlY3QgdGhlIHRvcCAxMDAwIG1vc3QgdmFyaWFibGUgZmVhdHVyZXMKRzE3Mi5NMiA8LSBOb3JtYWxpemVEYXRhKEcxNzIuTTIsIHZlcmJvc2UgPSBGQUxTRSkKRzE3Mi5NMiA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhHMTcyLk0yLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCiMgU2NhbGluZyBSTkEgZGF0YSwgd2Ugb25seSBzY2FsZSB0aGUgdmFyaWFibGUgZmVhdHVyZXMgaGVyZSBmb3IgZWZmaWNpZW5jeQpHMTcyLk0yIDwtIFNjYWxlRGF0YShHMTcyLk0yLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NMikpCiMgUnVuIFBDQQpHMTcyLk0yIDwtIFJ1blBDQShHMTcyLk0yLG5wY3MgPSAzMCwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTIpKQojIFdlIHNlbGVjdCB0aGUgdG9wIDEwIFBDcyBmb3IgY2x1c3RlcmluZyBhbmQgdFNORSBiYXNlZCBvbiBQQ0VsYm93UGxvdApHMTcyLk0yIDwtIFJ1blVNQVAoRzE3Mi5NMiwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjI1KQpHMTcyLk0yIDwtIEZpbmROZWlnaGJvcnMoRzE3Mi5NMiwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjI1KQpHMTcyLk0yIDwtIEZpbmRDbHVzdGVycyhHMTcyLk0yLCByZXNvbHV0aW9uID0gMC41ICkgICAKRzE3Mi5NMi5wMTwtIFVNQVBQbG90KEcxNzIuTTIsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWw9VFJVRSwgbGFiZWwuc2l6ZT01KQpHMTcyLk0yLnAxCkRlZmF1bHRBc3NheShHMTcyLk0yKSA8LSAiUk5BIgpHMTcyLk0yIDwtIE5vcm1hbGl6ZURhdGEoRzE3Mi5NMiwgdmVyYm9zZSA9IFRSVUUpCmQyIDwtIERvdFBsb3QoRzE3Mi5NMiwgZmVhdHVyZXMgPSBhbGxfZ2VuZXMpK1JvdGF0ZWRBeGlzKCkKcGxvdF9ncmlkKEcxNzIuTTIucDEsZDIpCgoKIyMjIyBFeHRyYWN0IHRoZSBzaW5nbGV0IGZvciBNMyAjIyMjIwpHMTcyLk0zIDwtIHN1YnNldChHMTcyLmhhc2h0YWcsIGlkZW50cyA9ICJNMy1HQ0NUQUdUQVRHQVRDQ0EiLCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA1MDAgJiBuQ291bnRfUk5BID4gMTAwMCkKRGVmYXVsdEFzc2F5KEcxNzIuTTMpIDwtICJSTkEiCkcxNzIuTTMgPC0gU0NUcmFuc2Zvcm0oRzE3Mi5NMyx2ZXJib3NlID1UUlVFKQojIFNlbGVjdCB0aGUgdG9wIDEwMDAgbW9zdCB2YXJpYWJsZSBmZWF0dXJlcwpHMTcyLk0zIDwtIE5vcm1hbGl6ZURhdGEoRzE3Mi5NMywgdmVyYm9zZSA9IEZBTFNFKQpHMTcyLk0zIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTMsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKIyBTY2FsaW5nIFJOQSBkYXRhLCB3ZSBvbmx5IHNjYWxlIHRoZSB2YXJpYWJsZSBmZWF0dXJlcyBoZXJlIGZvciBlZmZpY2llbmN5CkcxNzIuTTMgPC0gU2NhbGVEYXRhKEcxNzIuTTMsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhHMTcyLk0zKSkKIyBSdW4gUENBCkcxNzIuTTMgPC0gUnVuUENBKEcxNzIuTTMsbnBjcyA9IDMwLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NMykpCiMgV2Ugc2VsZWN0IHRoZSB0b3AgMTAgUENzIGZvciBjbHVzdGVyaW5nIGFuZCB0U05FIGJhc2VkIG9uIFBDRWxib3dQbG90CkcxNzIuTTMgPC0gUnVuVU1BUChHMTcyLk0zLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjUpCkcxNzIuTTMgPC0gRmluZE5laWdoYm9ycyhHMTcyLk0zLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjUpCkcxNzIuTTMgPC0gRmluZENsdXN0ZXJzKEcxNzIuTTMsIHJlc29sdXRpb24gPSAwLjUgKSAgIApHMTcyLk0zLnAxPC0gVU1BUFBsb3QoRzE3Mi5NMywgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbD1UUlVFLCBsYWJlbC5zaXplPTUpCkcxNzIuTTMucDEKRGVmYXVsdEFzc2F5KEcxNzIuTTMpIDwtICJSTkEiCkcxNzIuTTMgPC0gTm9ybWFsaXplRGF0YShHMTcyLk0zLCB2ZXJib3NlID0gVFJVRSkKZDMgPC0gRG90UGxvdChHMTcyLk0zLCBmZWF0dXJlcyA9IGFsbF9nZW5lcykrUm90YXRlZEF4aXMoKQpwbG90X2dyaWQoRzE3Mi5NMy5wMSxkMykKCiMjIyMjIEV4dHJhY3QgdGhlIHNpbmdsZXQgZm9yIE00ICMjIyMjCkcxNzIuTTQgPC0gc3Vic2V0KEcxNzIuaGFzaHRhZywgaWRlbnRzID0gIk00LUFHVENBQ0FHVEFUVENDQSIsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDUwMCAmIG5Db3VudF9STkEgPiAxMDAwKQpEZWZhdWx0QXNzYXkoRzE3Mi5NNCkgPC0gIlJOQSIKRzE3Mi5NNCA8LSBTQ1RyYW5zZm9ybShHMTcyLk00LHZlcmJvc2UgPVRSVUUpCiMgU2VsZWN0IHRoZSB0b3AgMTAwMCBtb3N0IHZhcmlhYmxlIGZlYXR1cmVzCkcxNzIuTTQgPC0gTm9ybWFsaXplRGF0YShHMTcyLk00LCB2ZXJib3NlID0gRkFMU0UpCkcxNzIuTTQgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NNCwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQojIFNjYWxpbmcgUk5BIGRhdGEsIHdlIG9ubHkgc2NhbGUgdGhlIHZhcmlhYmxlIGZlYXR1cmVzIGhlcmUgZm9yIGVmZmljaWVuY3kKRzE3Mi5NNCA8LSBTY2FsZURhdGEoRzE3Mi5NNCwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTQpKQojIFJ1biBQQ0EKRzE3Mi5NNCA8LSBSdW5QQ0EoRzE3Mi5NNCxucGNzID0gMzAsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhHMTcyLk00KSkKIyBXZSBzZWxlY3QgdGhlIHRvcCAxMCBQQ3MgZm9yIGNsdXN0ZXJpbmcgYW5kIHRTTkUgYmFzZWQgb24gUENFbGJvd1Bsb3QKRzE3Mi5NNCA8LSBSdW5VTUFQKEcxNzIuTTQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKRzE3Mi5NNCA8LSBGaW5kTmVpZ2hib3JzKEcxNzIuTTQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKRzE3Mi5NNCA8LSBGaW5kQ2x1c3RlcnMoRzE3Mi5NNCwgcmVzb2x1dGlvbiA9IDAuNSApICAgCkcxNzIuTTQucDE8LSBVTUFQUGxvdChHMTcyLk00LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsPVRSVUUsIGxhYmVsLnNpemU9NSkKRzE3Mi5NNC5wMQpEZWZhdWx0QXNzYXkoRzE3Mi5NNCkgPC0gIlJOQSIKRzE3Mi5NNCA8LSBOb3JtYWxpemVEYXRhKEcxNzIuTTQsIHZlcmJvc2UgPSBUUlVFKQpkNCA8LSBEb3RQbG90KEcxNzIuTTQsIGZlYXR1cmVzID0gYWxsX2dlbmVzKStSb3RhdGVkQXhpcygpCnBsb3RfZ3JpZChHMTcyLk00LnAxLGQ0KQoKCiMjIyMjIyMjIyMjIyMjIENvbWJpbmVkICMjIyMjIyMjIyMjIyMjIyMjIyMjMzMKRzE3Mi5NNSA8LSBzdWJzZXQoRzE3Mi5oYXNodGFnLCBpZGVudHMgPSBjKCJNMS1BVEdBVEdBQUNBR0NDQUciLCJNMi1UR0FDR0NDR1RUR1RUR1QiLCJNMy1HQ0NUQUdUQVRHQVRDQ0EiLCJNNC1BR1RDQUNBR1RBVFRDQ0EiKSwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNTAwICYgbkNvdW50X1JOQSA+IDEwMDApCkRlZmF1bHRBc3NheShHMTcyLk01KSA8LSAiUk5BIgpHMTcyLk01IDwtIFNDVHJhbnNmb3JtKEcxNzIuTTUsdmVyYm9zZSA9VFJVRSkKIyBTZWxlY3QgdGhlIHRvcCAxMDAwIG1vc3QgdmFyaWFibGUgZmVhdHVyZXMKRzE3Mi5NNSA8LSBOb3JtYWxpemVEYXRhKEcxNzIuTTUsIHZlcmJvc2UgPSBGQUxTRSkKRzE3Mi5NNSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhHMTcyLk01LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCiMgU2NhbGluZyBSTkEgZGF0YSwgd2Ugb25seSBzY2FsZSB0aGUgdmFyaWFibGUgZmVhdHVyZXMgaGVyZSBmb3IgZWZmaWNpZW5jeQpHMTcyLk01IDwtIFNjYWxlRGF0YShHMTcyLk01LCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NNSkpCiMgUnVuIFBDQQpHMTcyLk01IDwtIFJ1blBDQShHMTcyLk01LG5wY3MgPSAzMCwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTUpKQojIFdlIHNlbGVjdCB0aGUgdG9wIDEwIFBDcyBmb3IgY2x1c3RlcmluZyBhbmQgdFNORSBiYXNlZCBvbiBQQ0VsYm93UGxvdApHMTcyLk01IDwtIFJ1blVNQVAoRzE3Mi5NNSwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjI1KQpHMTcyLk01IDwtIEZpbmROZWlnaGJvcnMoRzE3Mi5NNSwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjI1KQpHMTcyLk01IDwtIEZpbmRDbHVzdGVycyhHMTcyLk01LCByZXNvbHV0aW9uID0gMC41ICkgICAKRzE3Mi5NNS5wMTwtIFVNQVBQbG90KEcxNzIuTTUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWw9VFJVRSwgbGFiZWwuc2l6ZT01KQpHMTcyLk01LnAxCkRlZmF1bHRBc3NheShHMTcyLk01KSA8LSAiUk5BIgpHMTcyLk01IDwtIE5vcm1hbGl6ZURhdGEoRzE3Mi5NNSwgdmVyYm9zZSA9IFRSVUUpCmQ1IDwtIERvdFBsb3QoRzE3Mi5NNSwgZmVhdHVyZXMgPSBjKGFsbF9nZW5lcywnQ3lwMmIxMCcsJ0N5cDJkOScpKStSb3RhdGVkQXhpcygpCnBsb3RfZ3JpZChHMTcyLk01LnAxLGQ1KQoKCiMjIyBjb250cm9sIApHMTcyLk02IDwtIHN1YnNldChHMTcyLmhhc2h0YWcuc3Vic2V0LCBpZGVudHMgPSBjKCJNMS1BVEdBVEdBQUNBR0NDQUciLCJNMy1HQ0NUQUdUQVRHQVRDQ0EiKSwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNTAwICYgbkNvdW50X1JOQSA+IDEwMDApCkRlZmF1bHRBc3NheShHMTcyLk02KSA8LSAiUk5BIgojRzE3Mi5NNiA8LSBTQ1RyYW5zZm9ybShHMTcyLk02LHZlcmJvc2UgPVRSVUUpCiMgU2VsZWN0IHRoZSB0b3AgMTAwMCBtb3N0IHZhcmlhYmxlIGZlYXR1cmVzCkcxNzIuTTYgPC0gTm9ybWFsaXplRGF0YShHMTcyLk02LCB2ZXJib3NlID0gRkFMU0UpCkcxNzIuTTYgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NNiwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQojIFNjYWxpbmcgUk5BIGRhdGEsIHdlIG9ubHkgc2NhbGUgdGhlIHZhcmlhYmxlIGZlYXR1cmVzIGhlcmUgZm9yIGVmZmljaWVuY3kKRzE3Mi5NNiA8LSBTY2FsZURhdGEoRzE3Mi5NNiwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTYpKQojIFJ1biBQQ0EKRzE3Mi5NNiA8LSBSdW5QQ0EoRzE3Mi5NNixucGNzID0gMzAsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhHMTcyLk02KSkKIyBXZSBzZWxlY3QgdGhlIHRvcCAxMCBQQ3MgZm9yIGNsdXN0ZXJpbmcgYW5kIHRTTkUgYmFzZWQgb24gUENFbGJvd1Bsb3QKRzE3Mi5NNiA8LSBSdW5VTUFQKEcxNzIuTTYsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKRzE3Mi5NNiA8LSBGaW5kTmVpZ2hib3JzKEcxNzIuTTYsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKRzE3Mi5NNiA8LSBGaW5kQ2x1c3RlcnMoRzE3Mi5NNiwgcmVzb2x1dGlvbiA9IDAuNSApICAgCkcxNzIuTTYucDE8LSBVTUFQUGxvdChHMTcyLk02LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsPVRSVUUsIGxhYmVsLnNpemU9NSkKRzE3Mi5NNi5wMQpEZWZhdWx0QXNzYXkoRzE3Mi5NNikgPC0gIlJOQSIKRzE3Mi5NNiA8LSBOb3JtYWxpemVEYXRhKEcxNzIuTTYsIHZlcmJvc2UgPSBUUlVFKQpkNiA8LSBEb3RQbG90KEcxNzIuTTYsIGZlYXR1cmVzID0gYyhhbGxfZ2VuZXMsJ0N5cDJiMTAnLCdDeXAyZDknKSkrUm90YXRlZEF4aXMoKQpwbG90X2dyaWQoRzE3Mi5NNi5wMSxkNikKCgojIyMjIFRDUE8gCkcxNzIuTTcgPC0gc3Vic2V0KEcxNzIuaGFzaHRhZywgaWRlbnRzID0gYygiTTItVEdBQ0dDQ0dUVEdUVEdUIiwiTTQtQUdUQ0FDQUdUQVRUQ0NBIiksIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDUwMCAmIG5Db3VudF9STkEgPiAxMDAwKQpEZWZhdWx0QXNzYXkoRzE3Mi5NNykgPC0gIlJOQSIKRzE3Mi5NNyA8LSBTQ1RyYW5zZm9ybShHMTcyLk03LHZlcmJvc2UgPVRSVUUpCiMgU2VsZWN0IHRoZSB0b3AgMTAwMCBtb3N0IHZhcmlhYmxlIGZlYXR1cmVzCkcxNzIuTTcgPC0gTm9ybWFsaXplRGF0YShHMTcyLk03LCB2ZXJib3NlID0gRkFMU0UpCkcxNzIuTTcgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoRzE3Mi5NNywgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQojIFNjYWxpbmcgUk5BIGRhdGEsIHdlIG9ubHkgc2NhbGUgdGhlIHZhcmlhYmxlIGZlYXR1cmVzIGhlcmUgZm9yIGVmZmljaWVuY3kKRzE3Mi5NNyA8LSBTY2FsZURhdGEoRzE3Mi5NNywgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKEcxNzIuTTcpKQojIFJ1biBQQ0EKRzE3Mi5NNyA8LSBSdW5QQ0EoRzE3Mi5NNyxucGNzID0gMzAsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhHMTcyLk03KSkKIyBXZSBzZWxlY3QgdGhlIHRvcCAxMCBQQ3MgZm9yIGNsdXN0ZXJpbmcgYW5kIHRTTkUgYmFzZWQgb24gUENFbGJvd1Bsb3QKRzE3Mi5NNyA8LSBSdW5VTUFQKEcxNzIuTTcsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKRzE3Mi5NNyA8LSBGaW5kTmVpZ2hib3JzKEcxNzIuTTcsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKRzE3Mi5NNyA8LSBGaW5kQ2x1c3RlcnMoRzE3Mi5NNywgcmVzb2x1dGlvbiA9IDAuNSApICAgCkcxNzIuTTcucDE8LSBVTUFQUGxvdChHMTcyLk03LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsPVRSVUUsIGxhYmVsLnNpemU9NSkKRzE3Mi5NNy5wMQpEZWZhdWx0QXNzYXkoRzE3Mi5NNykgPC0gIlJOQSIKRzE3Mi5NNyA8LSBOb3JtYWxpemVEYXRhKEcxNzIuTTcsIHZlcmJvc2UgPSBUUlVFKQpkNyA8LSBEb3RQbG90KEcxNzIuTTcsIGZlYXR1cmVzID0gYyhhbGxfZ2VuZXMsJ0N5cDJiMTAnLCdDeXAyZDknKSkrUm90YXRlZEF4aXMoKQpwbG90X2dyaWQoRzE3Mi5NNy5wMSxkNywgbnJvdz0yKQoKCmBgYAoKCmBgYHtyfQojIyMjIyMjIyMjIGZ1bmN0aW9uIGxvYWRfdGlzc3VlX2Ryb3BsZXQjIyMjIyMjIyMjIyMKZHJvcGxldF9tZXRhZGF0YSA8LSByZWFkLmNzdigiL3Jlc3RyaWN0ZWQvcHJvamVjdG5iL3dheG1hbmxhYi9ra2Fycmkvc2NSTkFzZXFfZGF0YV9pbnRlZ3JhdGlvbi9tZXRhZGF0YV9kcm9wbGV0X2xpdmVyLmNzdiIsIHNlcD0iLCIsIGhlYWRlciA9IFRSVUUpCmNvbG5hbWVzKGRyb3BsZXRfbWV0YWRhdGEpWzFdIDwtICJjaGFubmVsIgp0aXNzdWVfbWV0YWRhdGEgPSBmaWx0ZXIoZHJvcGxldF9tZXRhZGF0YSwgdGlzc3VlID09IHRpc3N1ZV9vZl9pbnRlcmVzdClbLGMoJ2NoYW5uZWwnLCd0aXNzdWUnLCdzdWJ0aXNzdWUnLCdtb3VzZS5zZXgnLCAnbW91c2UuaWQnKV0KCnJhdy5kYXRhIDwtIFJlYWQxMFgoIi9yZXN0cmljdGVkL3Byb2plY3RuYi93YXhtYW5sYWIva2thcnJpL3NjUk5Bc2VxX2RhdGFfaW50ZWdyYXRpb24vUmVmaW5lZF9jZWxsbWF0cmljZXMvTGl2ZXItMTBYX1A0XzIvIikKY29sbmFtZXMocmF3LmRhdGEpIDwtIGxhcHBseShjb2xuYW1lcyhyYXcuZGF0YSksIGZ1bmN0aW9uKHgpIHBhc3RlMCh0aXNzdWVfbWV0YWRhdGEkY2hhbm5lbFsxXSwnXycseCkpCiAgbWV0YS5kYXRhMSA9IGRhdGEuZnJhbWUocm93Lm5hbWVzID0gY29sbmFtZXMocmF3LmRhdGEpKQogIG1ldGEuZGF0YTFbJ2NoYW5uZWwnXSA9IHRpc3N1ZV9tZXRhZGF0YSRjaGFubmVsWzFdCgogIGlmIChsZW5ndGgodGlzc3VlX21ldGFkYXRhJGNoYW5uZWwpID4gMSl7CiAgICAjIFNvbWUgdGlzc3VlcywgbGlrZSBUaHltdXMgYW5kIEhlYXJ0IGhhZCBvbmx5IG9uZSBjaGFubmVsCiAgICBmb3IoaSBpbiAyOm5yb3codGlzc3VlX21ldGFkYXRhKSl7CnN1YmZvbGRlciA9IHBhc3RlMCgiL3Jlc3RyaWN0ZWQvcHJvamVjdG5iL3dheG1hbmxhYi9ra2Fycmkvc2NSTkFzZXFfZGF0YV9pbnRlZ3JhdGlvbi9SZWZpbmVkX2NlbGxtYXRyaWNlcy8iLHRpc3N1ZV9vZl9pbnRlcmVzdCwgJy0nLCB0aXNzdWVfbWV0YWRhdGEkY2hhbm5lbFtpXSkKICAgICAgbmV3LmRhdGExIDwtIFJlYWQxMFgoZGF0YS5kaXIgPSBzdWJmb2xkZXIpCiAgICAgIGNvbG5hbWVzKG5ldy5kYXRhMSkgPC0gbGFwcGx5KGNvbG5hbWVzKG5ldy5kYXRhMSksIGZ1bmN0aW9uKHgpIHBhc3RlMCh0aXNzdWVfbWV0YWRhdGEkY2hhbm5lbFtpXSwnXycsIHgpKQogICAgICAKICAgICAgbmV3Lm1ldGFkYXRhMSA9IGRhdGEuZnJhbWUocm93Lm5hbWVzID0gY29sbmFtZXMobmV3LmRhdGExKSkKICAgICAgbmV3Lm1ldGFkYXRhMVsnY2hhbm5lbCddID0gdGlzc3VlX21ldGFkYXRhJGNoYW5uZWxbaV0KICAgICAgCiAgICAgIHJhdy5kYXRhID0gY2JpbmQocmF3LmRhdGEsIG5ldy5kYXRhMSkKICAgICAgbWV0YS5kYXRhMSA9IHJiaW5kKG1ldGEuZGF0YTEsIG5ldy5tZXRhZGF0YTEpCiAgICB9CiAgfQogIAogIHJuYW1lcyA9IHJvdy5uYW1lcyhtZXRhLmRhdGExKQogIG1ldGEuZGF0YTEgPC0gbWVyZ2UobWV0YS5kYXRhMSwgdGlzc3VlX21ldGFkYXRhLCBzb3J0ID0gRikKICByb3cubmFtZXMobWV0YS5kYXRhMSkgPC0gcm5hbWVzCiAgIyBPcmRlciB0aGUgY2VsbHMgYWxwaGFiZXRpY2FsbHkgdG8gZW5zdXJlIGNvbnNpc3RlbmN5LgogICAgb3JkZXJlZF9jZWxsX25hbWVzID0gb3JkZXIoY29sbmFtZXMocmF3LmRhdGEpKQogIHJhdy5kYXRhID0gcmF3LmRhdGFbLG9yZGVyZWRfY2VsbF9uYW1lc10KICBtZXRhLmRhdGExID0gbWV0YS5kYXRhMVtvcmRlcmVkX2NlbGxfbmFtZXMsXQogICAgIyBGaW5kIEVSQ0MncywgY29tcHV0ZSB0aGUgcGVyY2VudCBFUkNDLCBhbmQgZHJvcCB0aGVtIGZyb20gdGhlIHJhdyBkYXRhLgogIGVyY2NzIDwtIGdyZXAocGF0dGVybiA9ICJeRVJDQy0iLCB4ID0gcm93bmFtZXMoeCA9IHJhdy5kYXRhKSwgdmFsdWUgPSBUUlVFKQogIHBlcmNlbnQuZXJjYyA8LSBNYXRyaXg6OmNvbFN1bXMocmF3LmRhdGFbZXJjY3MsIF0pL01hdHJpeDo6Y29sU3VtcyhyYXcuZGF0YSkKICBlcmNjLmluZGV4IDwtIGdyZXAocGF0dGVybiA9ICJeRVJDQy0iLCB4ID0gcm93bmFtZXMoeCA9IHJhdy5kYXRhKSwgdmFsdWUgPSBGQUxTRSkKICByYXcuZGF0YSA8LSByYXcuZGF0YVstZXJjYy5pbmRleCxdCiAgCiAgIyBDcmVhdGUgdGhlIFNldXJhdCBvYmplY3Qgd2l0aCBhbGwgdGhlIGRhdGEKICBkcm9wbGV0IDwtIENyZWF0ZVNldXJhdE9iamVjdChyYXcuZGF0YSkgICAjIGRyb3BzZXEKICBkcm9wbGV0IDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IGRyb3BsZXQsIG1ldGEuZGF0YTEpIAogIGRyb3BsZXRAbWV0YS5kYXRhJHRlY2ggPC0gImRyb3BsZXQiCgojbi5wY3MgPSAxMAogICNkcm9wbGV0IDwtIFN1YnNldERhdGEoZHJvcGxldCxzdWJzZXQubmFtZXMgPSBjKCJuR2VuZSIsICJuVU1JIiksIGxvdy50aHJlc2hvbGRzID0gYyg1MDAsIDEwMDApKSAgIyBvbGQgdmVyc2lvbiBvZiBzZXVyYXQKZHJvcGxldCA8LSAgc3Vic2V0KGRyb3BsZXQsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDUwMCAmIG5Db3VudF9STkEgPiAxMDAwKQpkcm9wbGV0IDwtIE5vcm1hbGl6ZURhdGEoZHJvcGxldCwgdmVyYm9zZSA9IEZBTFNFKQpkcm9wbGV0IDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGRyb3BsZXQsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKZHJvcGxldCA8LSBTY2FsZURhdGEoZHJvcGxldCwgdmVyYm9zZSA9IEZBTFNFKQojZHJvcGxldCA8LSBSdW5QQ0EoZHJvcGxldCwgbnBjcyA9IDEwLCB2ZXJib3NlID0gRkFMU0UpCmRyb3BsZXQkc3RpbSA8LSAiZHJvcGxldCIKZHJvcGxldCRjb25kIDwtICJjdHJsIgoKIyBkcm9wbGV0IDwtIFNjYWxlRGF0YShkcm9wbGV0LCB2ZXJib3NlID0gRkFMU0UpCiBkcm9wbGV0IDwtIFJ1blBDQShkcm9wbGV0LCBucGNzID0gMzAsIHZlcmJvc2UgPSBGQUxTRSkKIGRyb3BsZXQgPC0gUnVuVU1BUChkcm9wbGV0LCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjUpCiBkcm9wbGV0IDwtIEZpbmROZWlnaGJvcnMoZHJvcGxldCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjEwKQogZHJvcGxldCA8LSBGaW5kQ2x1c3RlcnMoZHJvcGxldCwgcmVzb2x1dGlvbiA9IDAuNSApICAgCiBwMTwtIFVNQVBQbG90KGRyb3BsZXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2hhbm5lbCIsIGxhYmVsPVRSVUUsIGxhYmVsLnNpemU9NSkKIHAyIDwtIFVNQVBQbG90KGRyb3BsZXQsIGxhYmVsPVRSVUUsIGxhYmVsLnNpemU9NikKIHAzPC0gVU1BUFBsb3QoZHJvcGxldCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJtb3VzZS5zZXgiLCBsYWJlbD1UUlVFLCBsYWJlbC5zaXplPTUpCgpyZXMudXNlZCA8LSAxCiNkcm9wbGV0IDwtIEZpbmRDbHVzdGVycyhvYmplY3QgPSBkcm9wbGV0LCByZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCBkaW1zLnVzZSA9IDE6bi5wY3MsIHJlc29sdXRpb24gPSByZXMudXNlZCwgcHJpbnQub3V0cHV0ID0gMCwgc2F2ZS5TTk4gPSBUUlVFLCBmb3JjZS5yZWNhbGMgPSBUUlVFKQoKZHJvcGxldCA8LSBSdW5UU05FKG9iamVjdCA9IGRyb3BsZXQsIGRpbXMudXNlID0gMTpuLnBjcywgc2VlZC51c2UgPSAxMCwgcGVycGxleGl0eT0zMCkKVFNORVBsb3Qob2JqZWN0ID0gZHJvcGxldCwgZG8ubGFiZWwgPSBULCBwdC5zaXplID0gMS4yLCBsYWJlbC5zaXplID0gNCkKCgpkcm9wbGV0IDwtIFJlbmFtZUlkZW50cyhkcm9wbGV0LCBgMGAgPSAiSGVwLU1pZC1NIiwgYDFgID0gIkhlcC1QQy1GIiwgYDJgID0gIkhlcC1QUC1GIixgM2AgPSAiSGVwLVBQLU0iLCBgNGAgPSAiSGVwLU1pZC1NIiwgYDVgID0gIkhlcC1QQy1NIiwgYDZgID0gIkhlcC1NaWQtRiIsIGA3YCA9ICJIZXAtTWlkLUYiLCBgOGAgPSAiRW5kby1GIiwgYDlgID0gIkJpbGVkdWN0LUYiKQoKCgojIyMgdGhpcyBpcyB0cmFuZm9ybWF0aW9uIG9wdGlvbiBmb3IgZGV2ZWxwbWVudCBTQ3RyYW5zZm9ybSBwcm9ncmFtICMjIyMjIyMKZHJvcGxldCA8LSBTQ1RyYW5zZm9ybShkcm9wbGV0LHZlcmJvc2UgPVRSVUUpCgoKIyMjIyMjMyBTbWFydHNlcSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpwbGF0ZV9tZXRhZGF0YSA8LSByZWFkLmNzdigiL3Jlc3RyaWN0ZWQvcHJvamVjdG5iL3dheG1hbmxhYi9ra2Fycmkvc2NSTkFzZXFfZGF0YV9pbnRlZ3JhdGlvbi9MaXZlcl9mYWNzX2Fubm90YXRpb24uY3N2Iiwgc2VwPSIsIiwgIGhlYWRlciA9IFRSVUUpCmNvbG5hbWVzKHBsYXRlX21ldGFkYXRhKVsxXSA8LSAicGxhdGUuYmFyY29kZSIKICAKcmF3LmRhdGEgPSByZWFkLmNzdigiL3Jlc3RyaWN0ZWQvcHJvamVjdG5iL3dheG1hbmxhYi9ra2Fycmkvc2NSTkFzZXFfZGF0YV9pbnRlZ3JhdGlvbi9saXZlcl9mYWNzX3Njcm5hX2RhdGEuY3N2Iiwgc2VwPSIsIiwgcm93Lm5hbWVzPTEpCmNvbG5hbWVzKHBsYXRlX21ldGFkYXRhKVsxXSA8LSAicGxhdGUuYmFyY29kZSIKICAKcGxhdGUuYmFyY29kZXMgPSBsYXBwbHkoY29sbmFtZXMocmF3LmRhdGEpLCBmdW5jdGlvbih4KSBzdHJzcGxpdChzdHJzcGxpdCh4LCAiXyIpW1sxXV1bMV0sICcuJywgZml4ZWQ9VFJVRSlbWzFdXVsyXSkKCiAgYmFyY29kZS5kZiA9IHQuZGF0YS5mcmFtZShhcy5kYXRhLmZyYW1lKHBsYXRlLmJhcmNvZGVzKSkKICAKICByb3duYW1lcyhiYXJjb2RlLmRmKSA9IGNvbG5hbWVzKHJhdy5kYXRhKQogIGJhcmNvZGUuZGY9IGNiaW5kKGJhcmNvZGUuZGYsIGNvbG5hbWVzKHJhdy5kYXRhKSkKICBjb2xuYW1lcyhiYXJjb2RlLmRmKSA9IGMoJ3BsYXRlLmJhcmNvZGUxJywgJ3BsYXRlLmJhcmNvZGUnKQogIAogIHJuYW1lcyA9IHJvdy5uYW1lcyhiYXJjb2RlLmRmKQogIG1ldGEuZGF0YSA8LSBtZXJnZShiYXJjb2RlLmRmLCBwbGF0ZV9tZXRhZGF0YSwgYnk9J3BsYXRlLmJhcmNvZGUnLCBzb3J0ID0gRikKICByb3cubmFtZXMobWV0YS5kYXRhKSA8LSBybmFtZXMKICAgIAogICMgU29ydCBjZWxscyBieSBjZWxsIG5hbWUKICBtZXRhLmRhdGEgPSBtZXRhLmRhdGFbb3JkZXIocm93bmFtZXMobWV0YS5kYXRhKSksIF0KICByYXcuZGF0YSA9IHJhdy5kYXRhWyxyb3duYW1lcyhtZXRhLmRhdGEpXQogIAogICMgQ3JlYXRlIHRoZSBTZXVyYXQgb2JqZWN0IHdpdGggYWxsIHRoZSBkYXRhCiAgc21hcnRzZXEgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KHJhdy5kYXRhKQogIHNtYXJ0c2VxIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IHNtYXJ0c2VxLCBtZXRhLmRhdGEpCiAgI3NtYXJ0c2VxQG1ldGEuZGF0YSR0ZWNoIDwtICJzbWFydHNlcSIKICBzbWFydHNlcSRzdGltIDwtICJzbWFydHNlcSIKICBzbWFydHNlcSRjb25kIDwtICJjdHJsIgoKI3NtYXJ0c2VxIDwtIFN1YnNldERhdGEoc21hcnRzZXEsc3Vic2V0Lm5hbWVzID0gYygibkdlbmUiLCAiblVNSSIpLGxvdy50aHJlc2hvbGRzID0gYyg1MDAsIDEwMDApKSAgI29sZCB2ZXJzaW9uIG9mIHNldXJhdApzbWFydHNlcTwtICBzdWJzZXQoc21hcnRzZXEsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDUwMCAmIG5Db3VudF9STkEgPiAxMDAwKQojc21hcnRzZXEgPC0gU0NUcmFuc2Zvcm0oc21hcnRzZXEpCnNtYXJ0c2VxIDwtIE5vcm1hbGl6ZURhdGEoc21hcnRzZXEsIHZlcmJvc2UgPSBGQUxTRSkKc21hcnRzZXEgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoc21hcnRzZXEsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKc21hcnRzZXEgPC0gU2NhbGVEYXRhKHNtYXJ0c2VxLCB2ZXJib3NlID0gRkFMU0UpCnNtYXJ0c2VxIDwtIFJ1blBDQShzbWFydHNlcSwgbnBjcyA9IDMwLCB2ZXJib3NlID0gRkFMU0UpCnNtYXJ0c2VxIDwtIFJ1blVNQVAoc21hcnRzZXEsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyNSkKc21hcnRzZXEgPC0gRmluZE5laWdoYm9ycyhzbWFydHNlcSwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjI1KQpzbWFydHNlcSA8LSBGaW5kQ2x1c3RlcnMoc21hcnRzZXEsIHJlc29sdXRpb24gPSAwLjUgKSAgIAojcDQ8LSBVTUFQUGxvdChzbWFydHNlcSwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJjaGFubmVsIiwgbGFiZWw9VFJVRSwgbGFiZWwuc2l6ZT01KQpwNSA8LSBVTUFQUGxvdChzbWFydHNlcSwgbGFiZWw9VFJVRSwgbGFiZWwuc2l6ZT02KQpwNjwtIFVNQVBQbG90KHNtYXJ0c2VxLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gIm1vdXNlLnNleCIsIGxhYmVsPVRSVUUsIGxhYmVsLnNpemU9NSkKCiMjIyMjIyMjIyMgc2N0cmFuc2Zvcm0gIyMjIyMjIyMjIyMjIyMjIyMjIzMKc21hcnRzZXEgPC0gU0NUcmFuc2Zvcm0oc21hcnRzZXEpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEludGVncmF0aW9uIFJlZ3VsYXIgd29ya2Zsb3cgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwphbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBjKGRyb3BsZXQubGlzdCwgc21hcnRzZXEubGlzdCxHMTcxQi5saXN0LCBHMTcyLk0xLmxpc3QsIEcxNzIuTTIubGlzdCksIGRpbXMgPSAxOjUwLCBhbmNob3IuZmVhdHVyZXMgPSAzMDAwKQpjb21iaW5lZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIGRpbXMgPSAxOjUwKSAgICAKCkRlZmF1bHRBc3NheShjb21iaW5lZCkgPC0gImludGVncmF0ZWQiCiMgUnVuIHRoZSBzdGFuZGFyZCB3b3JrZmxvdyBmb3IgdmlzdWFsaXphdGlvbiBhbmQgY2x1c3RlcmluZwpjb21iaW5lZCA8LSBTY2FsZURhdGEoY29tYmluZWQsIHZlcmJvc2UgPSBGQUxTRSkKY29tYmluZWQgPC0gUnVuUENBKGNvbWJpbmVkLCBucGNzID0gMzAsIHZlcmJvc2UgPSBGQUxTRSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAojIHQtU05FIGFuZCBDbHVzdGVyaW5nCmNvbWJpbmVkIDwtIFJ1blVNQVAoY29tYmluZWQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyMCkKY29tYmluZWQgPC0gRmluZE5laWdoYm9ycyhjb21iaW5lZCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwKQpjb21iaW5lZCA8LSBGaW5kQ2x1c3RlcnMoY29tYmluZWQsIHJlc29sdXRpb24gPSAwLjUgKSAgIAojY29tYmluZWQgPC0gUnVuVFNORShjb21iaW5lZCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwKQogICAgCiAjIFZpc3VhbGl6YXRpb24KcDEgPC0gRGltUGxvdChjb21iaW5lZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzdGltIikKcDIgPC0gRGltUGxvdChjb21iaW5lZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJtb3VzZS5zZXgiKQpwMyA8LSBEaW1QbG90KGNvbWJpbmVkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSkKcDQgPC0gVU1BUFBsb3QoY29tYmluZWQsIGxhYmVsPVRSVUUpCnBsb3RfZ3JpZChwMiwgcDMscDQpIApEaW1QbG90KGNvbWJpbmVkLCByZWR1Y3Rpb24gPSAidW1hcCIsIHNwbGl0LmJ5ID0gInN0aW0iKSAgIAoKcDUgPC0gRGltUGxvdChjb21iaW5lZCwgcmVkdWN0aW9uID0gInRzbmUiLCBncm91cC5ieSA9ICJzdGltIikKcDYgPC0gRGltUGxvdChjb21iaW5lZCwgcmVkdWN0aW9uID0gInRzbmUiLCBncm91cC5ieSA9ICJtb3VzZS5zZXgiKQpwNyA8LSBEaW1QbG90KGNvbWJpbmVkLCByZWR1Y3Rpb24gPSAidHNuZSIsIGxhYmVsID0gVFJVRSkKcDggPC0gVFNORVBsb3QoY29tYmluZWQsIGxhYmVsID1UKQpwbG90X2dyaWQocDYsIHA3LHA4KSAKRGltUGxvdChjb21iaW5lZCwgcmVkdWN0aW9uID0gInRzbmUiLCBzcGxpdC5ieSA9ICJzdGltIikgCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgUmVmZXJuY2UgYmFzZWQgSW50ZWdyYXRpb24gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZHJvcGxldC5saXN0IDwtIFNwbGl0T2JqZWN0KGRyb3BsZXQsIHNwbGl0LmJ5ID0gIm1vdXNlLnNleCIpCnNtYXJ0c2VxLmxpc3QgPC0gU3BsaXRPYmplY3Qoc21hcnRzZXEsIHNwbGl0LmJ5ID0gInN0aW0iKQpHMTcyLk0xLmxpc3QgPC0gU3BsaXRPYmplY3QoRzE3Mi5NMSwgc3BsaXQuYnkgPSAic3RpbSIpCkcxNzIuTTIubGlzdCA8LSBTcGxpdE9iamVjdChHMTcyLk0yLCBzcGxpdC5ieSA9ICJzdGltIikKRzE3Mi5NNi5saXN0IDwtIFNwbGl0T2JqZWN0KEcxNzIuTTYsIHNwbGl0LmJ5ID0gInN0aW0iKQpHMTcxQi5saXN0IDwtIFNwbGl0T2JqZWN0KEcxNzFCLCBzcGxpdC5ieT0ic3RpbSIpCmN0cmwubGlzdCA8LSBjKGRyb3BsZXQubGlzdCwgc21hcnRzZXEubGlzdCkKCmZvciAoaSBpbiBuYW1lcyhjdHJsLmxpc3QpKSB7CiAgICBjdHJsLmxpc3RbW2ldXSA8LSBTQ1RyYW5zZm9ybShjdHJsLmxpc3RbW2ldXSwgdmVyYm9zZSA9VFJVRSkKfQoKY3RybC5saXN0MSA8LSBjKGN0cmwubGlzdCwgRzE3MUIubGlzdCkKI2RpbXMgPSAxOjUwCnJlZi5mZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gY3RybC5saXN0MSwgZGltcz0xOjUwLCBhbmNob3IuZmVhdHVyZXMgPSAzMDAwKQpyZWYubGlzdCA8LSBQcmVwU0NUSW50ZWdyYXRpb24ob2JqZWN0Lmxpc3QgPSBjdHJsLmxpc3QxLCBhbmNob3IuZmVhdHVyZXMgPSByZWYuZmVhdHVyZXMpCnJlZi5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSByZWYubGlzdCwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiU0NUIiwgYW5jaG9yLmZlYXR1cmVzID0gcmVmLmZlYXR1cmVzLCByZWZlcmVuY2UgPSBjKDEsMiwzKSkKcmVmLmludGVncmF0ZWQgPC0gSW50ZWdyYXRlRGF0YShhbmNob3JzZXQgPSByZWYuYW5jaG9ycywgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiU0NUIikKCkRlZmF1bHRBc3NheShyZWYuaW50ZWdyYXRlZCkgPC0gImludGVncmF0ZWQiCnJlZi5pbnRlZ3JhdGVkIDwtIFNjYWxlRGF0YShyZWYuaW50ZWdyYXRlZCwgdmVyYm9zZSA9IEZBTFNFKQpyZWYuaW50ZWdyYXRlZCA8LSBSdW5QQ0Eob2JqZWN0ID0gcmVmLmludGVncmF0ZWQsIG5wY3M9MzAsdmVyYm9zZSA9IEZBTFNFKQpyZWYuaW50ZWdyYXRlZCA8LSBSdW5VTUFQKG9iamVjdCA9IHJlZi5pbnRlZ3JhdGVkICxkaW1zID0gMTozMCwgc2VlZC51c2UgPSAxMCwgcGVycGxleGl0eT0zMCkKcmVmLmludGVncmF0ZWQgPC0gRmluZE5laWdoYm9ycyhyZWYuaW50ZWdyYXRlZCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjMwKQpyZWYuaW50ZWdyYXRlZCA8LSBGaW5kQ2x1c3RlcnMocmVmLmludGVncmF0ZWQsIHJlc29sdXRpb24gPSAwLjIgKSAgIAoKcjEgPC0gRGltUGxvdChyZWYuaW50ZWdyYXRlZCwgc3BsaXQuYnk9InN0aW0iLCBwdC5zaXplID0gMC41KQpyMiA8LSBEaW1QbG90KHJlZi5pbnRlZ3JhdGVkLCBsYWJlbD1UUlVFLCBwdC5zaXplID0gMC41KQpyMyA8LSBEaW1QbG90KHJlZi5pbnRlZ3JhdGVkLCBzcGxpdC5ieSA9IGMoImNvbmQiKSwgcHQuc2l6ZSA9IDAuNSkKCgpwbG90cyA8LSBsYXBwbHkoWCA9IHBsb3RzLCBGVU4gPSBmdW5jdGlvbih4KSB4ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSA0LCAKICAgIGJ5cm93ID0gVFJVRSwgb3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gMi41KSkpKQpDb21iaW5lUGxvdHMocGxvdHMpCgoKcmVmLmludGVncmF0ZWQkY2VsbHR5cGUuc3RpbSA8LSBwYXN0ZShJZGVudHMocmVmLmludGVncmF0ZWQpLCByZWYuaW50ZWdyYXRlZCRzdGltLCBzZXAgPSAiXyIpCnJlZi5pbnRlZ3JhdGVkJHNldXJhdF9jbHVzdGVycyA8LSBJZGVudHMocmVmLmludGVncmF0ZWQpCklkZW50cyhyZWYuaW50ZWdyYXRlZCkgPC0gImNlbGx0eXBlLnN0aW0iCgpmcCA8LSBGZWF0dXJlUGxvdChyZWYuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAibmNSTkEtYXMtY2hyMTAtODQ2MCIsIGNvbHMgPSBjKCJsaWdodGdyZXkiLCJkYXJrcmVkIiksIG9yZGVyID0gVFJVRSwgIHNoYXBlLmJ5ID0gInN0aW0iLCBwdC5zaXplID0gMikKCkRlZmF1bHRBc3NheShyZWYuaW50ZWdyYXRlZCkgPC0iUk5BIgpyZWYuaW50ZWdyYXRlZCA8LSBOb3JtYWxpemVEYXRhKHJlZi5pbnRlZ3JhdGVkKQpyZWYuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEocmVmLmludGVncmF0ZWQpCgpkb3QxIDwtIERvdFBsb3QocmVmLmludGVncmF0ZWQsIGZlYXR1cmVzPSBhbGxfZ2VuZXMpK1JvdGF0ZWRBeGlzKCkKZDEgPC0gRG9IZWF0bWFwKHJlZi5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9IGMoYWxsX2dlbmVzLCJNdXAyMCIsIlhpc3QiKSwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgYXNzYXk9ICdSTkEnKQojZDEgPC0gRG9IZWF0bWFwKHJlZi5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9IGhpZ2hUUE0sIGdyb3VwLmJ5ID0gImNlbGx0eXBlLnN0aW0iLCBhc3NheT0gJ1JOQScscmFzdGVyID0gRiwgZGlzcC5tYXggPSAwLjUpK3NjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG9ycyA9IChSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwobiA9IDksIG5hbWUgPSAiUHVSZCIpKSApICsgZ3VpZGVzKGNvbG9yPUZBTFNFKQoKCkRyb3AuY29tYmluZWQubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSByZWYuaW50ZWdyYXRlZCwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCgojIyMjIyMjIyMjIyMgbWVyZ2UgRzE3MiBNMSAjIyMjIyMjIyMjIyMjMzMKZHJvcGxldC5saXN0IDwtIFNwbGl0T2JqZWN0KGRyb3BsZXQsIHNwbGl0LmJ5ID0gIm1vdXNlLnNleCIpCnNtYXJ0c2VxLmxpc3QgPC0gU3BsaXRPYmplY3Qoc21hcnRzZXEsIHNwbGl0LmJ5ID0gInN0aW0iKQpHMTcyLk0xLmxpc3QgPC0gU3BsaXRPYmplY3QoRzE3Mi5NMSwgc3BsaXQuYnkgPSAic3RpbSIpCkcxNzIuTTIubGlzdCA8LSBTcGxpdE9iamVjdChHMTcyLk0yLCBzcGxpdC5ieSA9ICJzdGltIikKRzE3Mi5NNi5saXN0IDwtIFNwbGl0T2JqZWN0KEcxNzIuTTYsIHNwbGl0LmJ5ID0gInN0aW0iKQpHMTcxQi5saXN0IDwtIFNwbGl0T2JqZWN0KEcxNzFCLCBzcGxpdC5ieT0ic3RpbSIpCmN0cmwubGlzdC4yIDwtIGMoIEcxNzIuTTEubGlzdCwgRzE3Mi5NMi5saXN0KQoKCmZvciAoaSBpbiBuYW1lcyhjdHJsLmxpc3QuMikpIHsKICAgIGN0cmwubGlzdC4yW1tpXV0gPC0gU0NUcmFuc2Zvcm0oY3RybC5saXN0LjJbW2ldXSwgdmVyYm9zZSA9VFJVRSkKfQoKcmVmLmZlYXR1cmVzLjEgPC0gU2VsZWN0SW50ZWdyYXRpb25GZWF0dXJlcyhvYmplY3QubGlzdCA9IGN0cmwubGlzdC4yLCBkaW1zID0gMTo1MCwgYW5jaG9yLmZlYXR1cmVzID0gMzAwMCkKcmVmLmxpc3QuMSA8LSBQcmVwU0NUSW50ZWdyYXRpb24ob2JqZWN0Lmxpc3QgPSBjdHJsLmxpc3QuMiwgYW5jaG9yLmZlYXR1cmVzID0gcmVmLmZlYXR1cmVzLjEpCgoKcmVmLmFuY2hvcnMuMSA8LSBGaW5kSW50ZWdyYXRpb25BbmNob3JzKG9iamVjdC5saXN0ID0gcmVmLmxpc3QuMSwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiU0NUIiwgCiAgICBhbmNob3IuZmVhdHVyZXMgPSByZWYuZmVhdHVyZXMuMSwgcmVmZXJlbmNlID0gYygxLDIpKQpyZWYuaW50ZWdyYXRlZC4xIDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gcmVmLmFuY2hvcnMuMSwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiU0NUIikKCkRlZmF1bHRBc3NheShyZWYuaW50ZWdyYXRlZC4xKSA8LSAiaW50ZWdyYXRlZCIKcmVmLmludGVncmF0ZWQuMSA8LSBTY2FsZURhdGEocmVmLmludGVncmF0ZWQuMSwgdmVyYm9zZSA9IEZBTFNFKQpyZWYuaW50ZWdyYXRlZC4xIDwtIFJ1blBDQShvYmplY3QgPSByZWYuaW50ZWdyYXRlZC4xLCBucGNzPTMwLHZlcmJvc2UgPSBGQUxTRSkKcmVmLmludGVncmF0ZWQuMSA8LSBSdW5VTUFQKG9iamVjdCA9IHJlZi5pbnRlZ3JhdGVkLjEsIGRpbXMgPSAxOjMwLCBzZWVkLnVzZSA9IDEwICwgcGVycGxleGl0eT0zMCkKI3JlZi5pbnRlZ3JhdGVkLjEgPC0gUnVuVFNORShvYmplY3QgPSByZWYuaW50ZWdyYXRlZC4xLCBkaW1zLnVzZSA9IDE6bi5wY3MsIHNlZWQudXNlID0gMTAsIHBlcnBsZXhpdHk9MzApCnJlZi5pbnRlZ3JhdGVkLjEgPC0gRmluZE5laWdoYm9ycyhyZWYuaW50ZWdyYXRlZC4xLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MzApCnJlZi5pbnRlZ3JhdGVkLjEgPC0gRmluZENsdXN0ZXJzKHJlZi5pbnRlZ3JhdGVkLjEsIHJlc29sdXRpb24gPSAwLjIpICAgCgpyRzE3Mk0xLjEgPC0gVU1BUFBsb3QocmVmLmludGVncmF0ZWQuMSwgc3BsaXQuYnk9InN0aW0iLCBsYWJlbD1UKQpyRzE3Mk0xLjIgPC0gVU1BUFBsb3QocmVmLmludGVncmF0ZWQuMSwgbGFiZWw9VFJVRSwgY29tYmluZSA9IEZBTFNFKQpyRzE3Mk0xLjMgPC0gVU1BUFBsb3QocmVmLmludGVncmF0ZWQuMSwgc3BsaXQuYnkgPSBjKCJtb3VzZS5zZXgiKSkKCnJHMTcyTTEuNCA8LSBUU05FUGxvdChyZWYuaW50ZWdyYXRlZC4xLCBzcGxpdC5ieT0ic3RpbSIpCgoKRGVmYXVsdEFzc2F5KHJlZi5pbnRlZ3JhdGVkLjEpIDwtIlJOQSIKcmVmLmludGVncmF0ZWQuMSA8LSBOb3JtYWxpemVEYXRhKHJlZi5pbnRlZ3JhdGVkLjEpCnJlZi5pbnRlZ3JhdGVkLjEgPC0gU2NhbGVEYXRhKHJlZi5pbnRlZ3JhdGVkLjEpCgpEb0hlYXRtYXAocmVmLmludGVncmF0ZWQuMSwgZmVhdHVyZXMgPSBjKGFsbF9nZW5lcywnU294OScsJ011cDIwJyksIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGFzc2F5PSAnUk5BJyAscmFzdGVyID0gRikrc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gKFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbChuID0gOSwgbmFtZSA9ICJQdVJkIikpICkgKyBndWlkZXMoY29sb3I9RkFMU0UpCgoKcmVmLmludGVncmF0ZWQuMSRjZWxsdHlwZSA8LSBSZW5hbWVJZGVudHMocmVmLmludGVncmF0ZWQuMSwgYyhgMGAgPSAiUFAiLCBgMWAgPSAiUEMiLCBgMmAgPSAiRW5kbyIsYDNgID0gIkhTQyIsIGA0YCA9ICJLdXBmZmVyIiwgYDVgID0gIkRpdmlkaW5nIiwgYDZgID0gIkltbXVuZSIsIGA3YCA9ICJCLU5LIiwgYDhgID0gIk5BIikpCgoKcmVmLmludGVncmF0ZWQuMS5tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKHJlZi5pbnRlZ3JhdGVkLjEsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIGxvZ2ZjLnRocmVzaG9sZCA9IDAuMjUpCnJlZi5pbnRlZ3JhdGVkLjEubWFya2VycyAgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3BfbihuID0gMiwgd3QgPSBhdmdfbG9nRkMpCgp3cml0ZS5jc3YocmVmLmludGVncmF0ZWQuMS5tYXJrZXJzLCAicmVmX2ludGVncmF0ZWRfRzE3Mk0xLU0yX0FsbG1hcmtlciIpCgpyZWYuaW50ZWdyYXRlZC4xJGNlbGx0eXBlLnN0aW0gPC0gcGFzdGUoSWRlbnRzKHJlZi5pbnRlZ3JhdGVkLjEpLCByZWYuaW50ZWdyYXRlZC4xJHN0aW0sIHNlcCA9ICJfIikKcmVmLmludGVncmF0ZWQuMSRjZWxsdHlwZSA8LSBJZGVudHMocmVmLmludGVncmF0ZWQuMSkKSWRlbnRzKHJlZi5pbnRlZ3JhdGVkLjEpIDwtICJjZWxsdHlwZS5zdGltIgoKRG9IZWF0bWFwKHJlZi5pbnRlZ3JhdGVkLjEsIGZlYXR1cmVzID0gVFBNNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgYXNzYXk9ICdSTkEnICkKCnJlZi5pbnRlZ3JhdGVkLjEubWFya2VycyA8LSBGaW5kTWFya2VycyhyZWYuaW50ZWdyYXRlZC4xLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCBsb2dmYy50aHJlc2hvbGQgPSAwLjI1KQpyZWYuaW50ZWdyYXRlZC4xLm1hcmtlcnMgICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24obiA9IDIsIHd0ID0gYXZnX2xvZ0ZDKQoKCmBgYAoKCkcxNzJNMSBhbmQgRzE3MiBNMiBERSBhbmFseXNpcwpgYGB7cn0KCkRFMS4xIDwtIEZpbmRNYXJrZXJzKHJlZi5pbnRlZ3JhdGVkLjEsIGlkZW50LjEgPSBjKCIwX0cxNzJNMSIgLCIxX0cxNzJNMSIsICIyX0cxNzJNMSIgLCIzX0cxNzJNMSIgLCI0X0cxNzJNMSIgLCI1X0cxNzJNMSIgLCI2X0cxNzJNMSIsIjdfRzE3Mk0xIiwgIjhfRzE3Mk0xIiksIGlkZW50LjIgPSBjKCIwX0cxNzJNMiIgLCIxX0cxNzJNMiIsICIyX0cxNzJNMiIgLCIzX0cxNzJNMiIgLCI0X0cxNzJNMiIgLCI1X0cxNzJNMiIgLCI2X0cxNzJNMiIsIjdfRzE3Mk0yIiwgIjhfRzE3Mk0yIiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCkRFX0FsbF9NMV9NMiA8LSBERTEuMSAKREVfaGVwX05QQyA8LSBGaW5kTWFya2VycyhyZWYuaW50ZWdyYXRlZC4xLCBpZGVudC4xID0gYygiMF9HMTcyTTIiICwiMV9HMTcyTTIiKSwgaWRlbnQuMiA9IGMoIjJfRzE3Mk0yIiAsIjNfRzE3Mk0yIiAsIjRfRzE3Mk0yIiAsIjVfRzE3Mk0yIiAsIjZfRzE3Mk0yIiwiN19HMTcyTTIiKSx2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQoKREVfTlBDX00xX00yIDwtIEZpbmRNYXJrZXJzKHJlZi5pbnRlZ3JhdGVkLjEsIGlkZW50LjEgPSBjKCAiMl9HMTcyTTEiICwiM19HMTcyTTEiICwiNF9HMTcyTTEiICwiNV9HMTcyTTEiICwiNl9HMTcyTTEiLCI3X0cxNzJNMSIpLCBpZGVudC4yID0gYygiMl9HMTcyTTIiICwiM19HMTcyTTIiICwiNF9HMTcyTTIiICwiNV9HMTcyTTIiICwiNl9HMTcyTTIiLCI3X0cxNzJNMiIpLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCgpERV9Ecm9wIDwtIEZpbmRBbGxNYXJrZXJzKHJlZi5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICkKCgoKREUwLjEgPC0gRmluZE1hcmtlcnMocmVmLmludGVncmF0ZWQuMSwgaWRlbnQuMSA9IGMoIjBfRzE3Mk0xIiksIGlkZW50LjIgPSBjKCIwX0cxNzJNMiIpLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCgp3cml0ZS5jc3YoREUwLjEsICJtYXJrZXIvREUwLjFfRzE3Ml8wX00xX00yIikKCkRFMS4xIDwtIEZpbmRNYXJrZXJzKHJlZi5pbnRlZ3JhdGVkLjEsIGlkZW50LjEgPSBjKCIxX0cxNzJNMSIpLCBpZGVudC4yID0gYygiMV9HMTcyTTIiKSx2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQoKREUyLjEgPC0gRmluZE1hcmtlcnMocmVmLmludGVncmF0ZWQuMSwgaWRlbnQuMSA9IGMoIjJfRzE3Mk0xIiksIGlkZW50LjIgPSBjKCIyX0cxNzJNMiIpLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCgpERTMuMSA8LSBGaW5kTWFya2VycyhyZWYuaW50ZWdyYXRlZC4xLCBpZGVudC4xID0gYygiM19HMTcyTTEiKSwgaWRlbnQuMiA9IGMoIjNfRzE3Mk0yIiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCgpERTQuMSA8LSBGaW5kTWFya2VycyhyZWYuaW50ZWdyYXRlZC4xLCBpZGVudC4xID0gYygiNF9HMTcyTTEiKSwgaWRlbnQuMiA9IGMoIjRfRzE3Mk0yIiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCkRFNS4xIDwtIEZpbmRNYXJrZXJzKHJlZi5pbnRlZ3JhdGVkLjEsIGlkZW50LjEgPSBjKCI1X0cxNzJNMSIpLCBpZGVudC4yID0gYygiNV9HMTcyTTIiKSx2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQoKREU2LjEgPC0gRmluZE1hcmtlcnMocmVmLmludGVncmF0ZWQuMSwgaWRlbnQuMSA9IGMoIjZfRzE3Mk0xIiksIGlkZW50LjIgPSBjKCI2X0cxNzJNMiIpLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCgpERTcuMSA8LSBGaW5kTWFya2VycyhyZWYuaW50ZWdyYXRlZC4xLCBpZGVudC4xID0gYygiN19HMTcyTTEiKSwgaWRlbnQuMiA9IGMoIjdfRzE3Mk0yIiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCgpgYGAKCgoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIEcxNzEgVENQTyBleHBzb3NlZCAjIyMjIyMjIwpHMTcxQl9tZXRhZGF0YV9HMTcxQiA8LSByZWFkLmNzdigiL25ldC93YXhtYW4tc2VydmVyL21udC9kYXRhL3dheG1hbmxhYnZtX2hvbWUva2thcnJpL0cxNzEvQW5hbHlzaXMvRzE3MV9tZXRhZGF0YV9kcm9wbGV0X2xpdmVyLmNzdiIsIHNlcD0iLCIsIGhlYWRlciA9IFRSVUUpCmNvbG5hbWVzKEcxNzFCX21ldGFkYXRhX0cxNzFCKVsxXSA8LSAiY2hhbm5lbCIKdGlzc3VlX21ldGFkYXRhX0cxNzFCID0gZmlsdGVyKEcxNzFCX21ldGFkYXRhX0cxNzFCLCB0aXNzdWUgPT0gdGlzc3VlX29mX2ludGVyZXN0KVssYygnY2hhbm5lbCcsJ3Rpc3N1ZScsJ3N1YnRpc3N1ZScsJ21vdXNlLnNleCcsICdtb3VzZS5pZCcpXQoKcmF3LmRhdGEgPC0gUmVhZDEwWCgiL25ldC93YXhtYW4tc2VydmVyL21udC9kYXRhL3dheG1hbmxhYnZtX2hvbWUva2thcnJpL0cxNzEvQW5hbHlzaXMvVHJhbnNjcmlwdF9SZWZpbmVkL0xpdmVyLTEwWF9HMTcxQi8iKQpjb2xuYW1lcyhyYXcuZGF0YSkgPC0gbGFwcGx5KGNvbG5hbWVzKHJhdy5kYXRhKSwgZnVuY3Rpb24oeCkgcGFzdGUwKHRpc3N1ZV9tZXRhZGF0YV9HMTcxQiRjaGFubmVsWzFdLCdfJyx4KSkKICBtZXRhLmRhdGExID0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSBjb2xuYW1lcyhyYXcuZGF0YSkpCiAgbWV0YS5kYXRhMVsnY2hhbm5lbCddID0gdGlzc3VlX21ldGFkYXRhX0cxNzFCJGNoYW5uZWxbMV0KICAKICBybmFtZXMgPSByb3cubmFtZXMobWV0YS5kYXRhMSkKICBtZXRhLmRhdGExIDwtIG1lcmdlKG1ldGEuZGF0YTEsIHRpc3N1ZV9tZXRhZGF0YV9HMTcxQiwgc29ydCA9IEYpCiAgcm93Lm5hbWVzKG1ldGEuZGF0YTEpIDwtIHJuYW1lcwogICMgT3JkZXIgdGhlIGNlbGxzIGFscGhhYmV0aWNhbGx5IHRvIGVuc3VyZSBjb25zaXN0ZW5jeS4KICAKICBvcmRlcmVkX2NlbGxfbmFtZXMgPSBvcmRlcihjb2xuYW1lcyhyYXcuZGF0YSkpCiAgcmF3LmRhdGEgPSByYXcuZGF0YVssb3JkZXJlZF9jZWxsX25hbWVzXQogIG1ldGEuZGF0YTEgPSBtZXRhLmRhdGExW29yZGVyZWRfY2VsbF9uYW1lcyxdCiAgCiAgIyBGaW5kIEVSQ0MncywgY29tcHV0ZSB0aGUgcGVyY2VudCBFUkNDLCBhbmQgZHJvcCB0aGVtIGZyb20gdGhlIHJhdyBkYXRhLgogIGVyY2NzIDwtIGdyZXAocGF0dGVybiA9ICJeRVJDQy0iLCB4ID0gcm93bmFtZXMoeCA9IHJhdy5kYXRhKSwgdmFsdWUgPSBUUlVFKQogIHBlcmNlbnQuZXJjYyA8LSBNYXRyaXg6OmNvbFN1bXMocmF3LmRhdGFbZXJjY3MsIF0pL01hdHJpeDo6Y29sU3VtcyhyYXcuZGF0YSkKICBlcmNjLmluZGV4IDwtIGdyZXAocGF0dGVybiA9ICJeRVJDQy0iLCB4ID0gcm93bmFtZXMoeCA9IHJhdy5kYXRhKSwgdmFsdWUgPSBGQUxTRSkKICByYXcuZGF0YSA8LSByYXcuZGF0YVstZXJjYy5pbmRleCxdCiAgCiAgbmNSTkEuZ2VuZXMgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHggPSByb3duYW1lcyh4ID0gcmF3LmRhdGEpLCB2YWx1ZSA9IFRSVUUpCiAgcGVyY2VudC5uY1JOQSA8LSBNYXRyaXg6OmNvbFN1bXMocmF3LmRhdGFbbmNSTkEuZ2VuZXMsIF0pL01hdHJpeDo6Y29sU3VtcyhyYXcuZGF0YSkKICBLUkFCLmdlbmVzIDwtIGdyZXAocGF0dGVybiA9ICJeS1JBQiIsIHggPSByb3duYW1lcyh4ID0gcmF3LmRhdGEpLCB2YWx1ZSA9IFRSVUUpCiAgY2hlcnJ5LmdlbmVzIDwtIGdyZXAocGF0dGVybiA9ICJebWNoZXJyeSIsIHggPSByb3duYW1lcyh4ID0gcmF3LmRhdGEpLCB2YWx1ZSA9IFRSVUUpCiAgCiAgIyBDcmVhdGUgdGhlIFNldXJhdCBvYmplY3Qgd2l0aCBhbGwgdGhlIGRhdGEKICBHMTcxQiA8LSBDcmVhdGVTZXVyYXRPYmplY3QocmF3LmRhdGEpICAgIyBkcm9wc2VxCiAgRzE3MUIgPC0gQWRkTWV0YURhdGEob2JqZWN0ID0gRzE3MUIsIG1ldGEuZGF0YTEpIAogIEcxNzFCQG1ldGEuZGF0YSR0ZWNoIDwtICJHMTcxQiIKCiNHMTcxQiA8LSBTdWJzZXREYXRhKEcxNzFCLHN1YnNldC5uYW1lcyA9IGMoIm5HZW5lIiwgIm5VTUkiKSwgbG93LnRocmVzaG9sZHMgPSBjKDUwMCwgMTAwMCkpICAjIG9sZCB2ZXJzaW9uIG9mIHNldXJhdAojRzE3MUIgPC0gIHN1YnNldChHMTcxQiwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNTAwICYgbkNvdW50X1JOQSA+IDEwMDApCkcxNzFCIDwtIE5vcm1hbGl6ZURhdGEoRzE3MUIsIHZlcmJvc2UgPSBGQUxTRSkKRzE3MUIgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoRzE3MUIsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKRzE3MUIkc3RpbSA8LSAiRzE3MUIiCkcxNzFCJGNvbmQgPC0gIlRDUE8iCgojIyMgdGhpcyBpcyB0cmFuZm9ybWF0aW9uIG9wdGlvbiBmb3IgZGV2ZWxwbWVudCBTQ3RyYW5zZm9ybSBwcm9ncmFtICMjIyMjIyMKRzE3MUIgPC0gU0NUcmFuc2Zvcm0oRzE3MUIsdmVyYm9zZSA9VFJVRSkKCgpgYGAKCgpkaWZmdXNpb24gcGx0IGNvZGUgCgpgYGB7cn0KIyBCZWZvcmUgcnVubmluZyBNRFMsIHdlIGZpcnN0IGNhbGN1bGF0ZSBhIGRpc3RhbmNlIG1hdHJpeCBiZXR3ZWVuIGFsbCBwYWlycyBvZiBjZWxscy4gIEhlcmUgd2UKIyB1c2UgYSBzaW1wbGUgZXVjbGlkZWFuIGRpc3RhbmNlIG1ldHJpYyBvbiBhbGwgZ2VuZXMsIHVzaW5nIHNjYWxlLmRhdGEgYXMgaW5wdXQKZCA8LSBkaXN0KHQoR2V0QXNzYXlEYXRhKGNvbWJpbmVkLCBzbG90ID0gInNjYWxlLmRhdGEiKSkpCiMgUnVuIHRoZSBNRFMgcHJvY2VkdXJlLCBrIGRldGVybWluZXMgdGhlIG51bWJlciBvZiBkaW1lbnNpb25zCm1kcyA8LSBjbWRzY2FsZShkID0gZCwgayA9IDIpCiMgY21kc2NhbGUgcmV0dXJucyB0aGUgY2VsbCBlbWJlZGRpbmdzLCB3ZSBmaXJzdCBsYWJlbCB0aGUgY29sdW1ucyB0byBlbnN1cmUgZG93bnN0cmVhbQojIGNvbnNpc3RlbmN5CmNvbG5hbWVzKG1kcykgPC0gcGFzdGUwKCJNRFNfIiwgMToyKQojIFdlIHdpbGwgbm93IHN0b3JlIHRoaXMgYXMgYSBjdXN0b20gZGltZW5zaW9uYWwgcmVkdWN0aW9uIGNhbGxlZCAnbWRzJwpjb21iaW5lZFtbIm1kcyJdXSA8LSBDcmVhdGVEaW1SZWR1Y09iamVjdChlbWJlZGRpbmdzID0gbWRzLCBrZXkgPSAiTURTXyIsIGFzc2F5ID0gRGVmYXVsdEFzc2F5KGNvbWJpbmVkKSkKCiMgV2UgY2FuIG5vdyB1c2UgdGhpcyBhcyB5b3Ugd291bGQgYW55IG90aGVyIGRpbWVuc2lvbmFsIHJlZHVjdGlvbiBpbiBhbGwgZG93bnN0cmVhbSBmdW5jdGlvbnMKRGltUGxvdChjb21iaW5lZCwgcmVkdWN0aW9uID0gIm1kcyIsIHB0LnNpemUgPSAwLjUpCmBgYAoKCgpgYGB7cn0KZ2VuZXNfaGVwX21haW4gPWMoJ0FsYicsICdUdHInLCAnQXBvYTEnLCAnU2VycGluYTFjJykKZ2VuZXNfaGVwID0gYygnQWxiJywgJ1R0cicsICdBcG9hMScsICdTZXJwaW5hMWMnLAogICAgICAgICAgICAgICAgICAgJ0N5cDJlMScsICdHbHVsJywgJ09hdCcsICdHdWxvJywKICAgICAgICAgICAgICAgICAgICdBc3MxJywgJ0hhbXAnLCAnR3N0cDEnLCAnVWJiJywKICAgICAgICAgICAgICAgICAgICdDeXAyZjInLCAnUGNrMScsICdIYWwnLCAnQ2RoMScpCmdlbmVzX2VuZG8gPSBjKCdQZWNhbTEnLCAnTnJwMScsICdLZHInLCdPaXQzJykKZ2VuZXNfa3VwcGZlciA9IGMoICdDbGVjNGYnLCAnQ2Q2OCcpCmdlbmVzX25rID0gYygnSWwycmInLCAnTmtnNycsICdDeGNyNicsICdHem1hJykKZ2VuZXNfYiA9IGMoJ0NkNzlhJywgJ0NkNzliJykKZ2VuZXNfYmVjID0gYygnRXBjYW0nLCAnS3J0MTknLCAnS3J0NycpCmdlbmVzX2ltbXVuZSA9ICdQdHByYycKSFNDID0gYygiRGNuIiwiTGFtYTEiLCJOZXMiKQpEaXZpZGluZyA9ICJUb3AyYSIKQnBsYXNtYT0gIkpjaGFpbiIKTWFjPSAiQ3NmMXIiCkNob2w9IlNveDkiCgpzZXggPC0gYygiQ3lwMmQ5IiwgIm5jUk5BLWludGVyX2NoclgtMTUzOTQiKQphbGxfZ2VuZXMgPSBjKGdlbmVzX2hlcCwgZ2VuZXNfZW5kbywgZ2VuZXNfa3VwcGZlciwgTWFjLGdlbmVzX25rLCBnZW5lc19iLCBnZW5lc19iZWMsIGdlbmVzX2ltbXVuZSwgSFNDLCBEaXZpZGluZykKZ2VuZXNfYmVjX2JfaW1tdW5lICA9IGMoZ2VuZXNfYmVjLGdlbmVzX2IsZ2VuZXNfaW1tdW5lKQpnZW5lc196b25lcyA9IGMoJ0N5cDJlMScsICdHbHVsJywgJ09hdCcsICdHdWxvJywKICAgICAgICAgICAgICAnQXNzMScsICdIYW1wJywgJ0dzdHAxJywgJ1ViYicsCiAgICAgICAgICAgICAgJ0N5cDJmMicsICdQY2sxJywgJ0hhbCcsICdDZGgxJykKCnJlY2VwdG9yX0tPIDwtIGMoIm5jUk5BLWludGVyLWNocjctNTk5OCIsIkN5cDJiMTAiLCJOcjFpMiIsIk5yMWkzIiwiUHBhcmEiLCJQcGFyZyIsIlBwYXJnYzFiIiwiUHBhcmQiKQpjZWxsIDwtIGMoIlN0YWIyIiwiQ3NmMXIiLCJDZDNnIiwiRWJmMSIsIklyZjgiLCJTb3g5IiwiQXBvYzMiLCJUb3AyYSIsIkRjbiIpCmBgYAoKYGBge3J9ClRQTTQ8LSBjKCduY1JOQS1pbnRlci1jaHI3LTY1MjQnLAonbmNSTkEtaW50ZXItY2hyMTktMTQ4NTMnLAonbmNSTkEtaW50ZXItY2hyNi01Njc1JywKJ25jUk5BLWludGVyLWNocjQtMzQ2OCcsCiduY1JOQS1pbnRlci1jaHI5LTgxMjInLAonbmNSTkEtaW50ZXItY2hyMTItMTA0NzYnLAonbmNSTkEtaW50ZXItY2hyMTctMTQwMjYnLAonbmNSTkEtYXMtY2hyMi0xNDU3JywKJ25jUk5BLWFzLWNocjE5LTE0ODgzJywKJ25jUk5BLWFzLWNocjEwLTg0NjAnLAonbmNSTkEtYXMtY2hyNS00MzI1JywKJ25jUk5BLWludGVyLWNocjctNTk5OCcsCiduY1JOQS1hcy1jaHI5LTc4NDMnLAonbmNSTkEtYXMtY2hyOS04MTQyJywKJ25jUk5BLWludGVyLWNocjExLTk5MjUnLAonbmNSTkEtaW50ZXItY2hyMTktMTQ4NzMnLAonbmNSTkEtYXMtY2hyOS04MTcyJywKJ25jUk5BLWludGVyLWNocjQtMzc3OScsCiduY1JOQS1pbnRlci1jaHIzLTI1MDQnLAonbmNSTkEtYXMtY2hyMTktMTUwNTQnLAonbmNSTkEtaW50ZXItY2hyOC03NDIzJywKJ25jUk5BLWFzLWNocjctNjMwMicsCiduY1JOQS1pbnRlci1jaHIxMC05NDE4JywKJ25jUk5BLWludGVyLWNocjEyLTEwNDU0JywKJ25jUk5BLWFzLWNocjctNTk5OScsCiduY1JOQS1hcy1jaHI2LTUzMzUnLAonbmNSTkEtaW50ZXItY2hyMTktMTQ5ODcnLAonbmNSTkEtaW50ZXItY2hyMTYtMTMxNzAnLAonbmNSTkEtaW50ZXItY2hyMy0yOTg4JywKJ25jUk5BLWludGVyLWNocjgtNzQzMCcsCiduY1JOQS1pbnRlci1jaHIzLTIxNjgnLAonbmNSTkEtaW50ZXItY2hyOS03ODc0JywKJ25jUk5BLWludGVyLWNocjQtMzc3OCcsCiduY1JOQS1pbnRlci1jaHIyLTIwMTEnLAonbmNSTkEtaW50ZXItY2hyNS00MzM1JywKJ25jUk5BLWludGVyLWNocjktODMwMScsCiduY1JOQS1pbnRlci1jaHIxNi0xMzUxMCcsCiduY1JOQS1hcy1jaHI5LTg0MDEnLAonbmNSTkEtYXMtY2hyMTYtMTM1MTInLAonbmNSTkEtYXMtY2hyMTItMTA4OTYnLAonbmNSTkEtYXMtY2hyOC03MzU5JywKJ25jUk5BLWFzLWNocjUtNDc0NCcsCiduY1JOQS1pbnRlci1jaHI1LTQ0OTknLAonbmNSTkEtaW50ZXItY2hyMTYtMTM1MDknLAonbmNSTkEtaW50ZXItY2hyMTctMTM2OTInLAonbmNSTkEtYXMtY2hyMTctMTM4MzQnLAonbmNSTkEtaW50ZXItY2hyOS04MTQ3JywKJ25jUk5BLWludGVyLWNocjEwLTg2OTcnLAonbmNSTkEtaW50ZXItY2hyNi01NTUxJywKJ25jUk5BLWFzLWNocjktODMxNycsCiduY1JOQS1pbnRlci1jaHI3LTY1MDknLAonbmNSTkEtYXMtY2hyMTktMTQ5NzcnLAonbmNSTkEtaW50ZXItY2hyNi01MzE4JywKJ25jUk5BLWludGVyLWNocjUtNDU3OCcsCiduY1JOQS1pbnRlci1jaHIxMi0xMDUwOScsCiduY1JOQS1hcy1jaHIxMC05MDE1JywKJ25jUk5BLWludGVyLWNocjMtMjQxMScsCiduY1JOQS1pbnRlci1jaHI5LTc4NzUnLAonbmNSTkEtaW50ZXItY2hyNS00MzM2JywKJ25jUk5BLWludGVyLWNocjEyLTEwOTEwJywKJ25jUk5BLWFzLWNocjEtNzgyJywKJ25jUk5BLWludGVyLWNocjE3LTEzOTI0JywKJ25jUk5BLWludHJhLWNocjctNTkyMCcsCiduY1JOQS1pbnRlci1jaHIxNi0xMzIyNScsCiduY1JOQS1pbnRlci1jaHIzLTIyNjknLAonbmNSTkEtaW50ZXItY2hyMTQtMTIwMTYnLAonbmNSTkEtYXMtY2hyNC0zODAwJywKJ25jUk5BLWFzLWNocjUtNDY1NScsCiduY1JOQS1pbnRlci1jaHI5LTc5ODknLAonbmNSTkEtaW50cmEtY2hyNS00NzI4JywKJ25jUk5BLWludGVyLWNoclgtMTUyNDgnLAonbmNSTkEtaW50ZXItY2hyMTAtODc2NycsCiduY1JOQS1pbnRlci1jaHIxOS0xNDcxNycsCiduY1JOQS1pbnRlci1jaHI4LTY3NjYnLAonbmNSTkEtaW50ZXItY2hyMTMtMTExMjInLAonbmNSTkEtaW50ZXItY2hyNy02MDc0JywKJ25jUk5BLWludGVyLWNocjE1LTEyNDM5JywKJ25jUk5BLWFzLWNocjExLTk3ODcnLAonbmNSTkEtaW50ZXItY2hyMi0xODI3JywKJ25jUk5BLWFzLWNocjE5LTE0OTc2JywKJ25jUk5BLWludGVyLWNocjE5LTE0OTQ3JywKJ25jUk5BLWludGVyLWNocjYtNTI0OCcsCiduY1JOQS1pbnRlci1jaHIyLTEwOTgnLAonbmNSTkEtaW50ZXItY2hyOC03MTgwJywKJ25jUk5BLWludGVyLWNocjktODExOCcsCiduY1JOQS1pbnRlci1jaHIxNC0xMjE5OScsCiduY1JOQS1hcy1jaHI2LTUzMzYnLAonbmNSTkEtaW50ZXItY2hyNC0zODY3JywKJ25jUk5BLWludGVyLWNocjEwLTkwMDAnLAonbmNSTkEtaW50ZXItY2hyMTQtMTIyOTAnLAonbmNSTkEtaW50ZXItY2hyMi0xNDkxJywKJ25jUk5BLWludGVyLWNocjE1LTEyNjA2JywKJ25jUk5BLWludGVyLWNocjEwLTkyMjInLAonbmNSTkEtaW50ZXItY2hyNS00MzIyJywKJ25jUk5BLWludGVyLWNocjEyLTEwOTQyJywKJ25jUk5BLWludGVyLWNocjE4LTE0NjkwJywKJ25jUk5BLWludGVyLWNocjItMTQ3MScsCiduY1JOQS1pbnRlci1jaHIzLTI0MTAnLAonbmNSTkEtaW50ZXItY2hyMTktMTQ4ODAnLAonbmNSTkEtaW50ZXItY2hyMTMtMTEwNzQnLAonbmNSTkEtaW50ZXItY2hyOS04MDU2JywKJ25jUk5BLWludGVyLWNocjUtNDY1NCcsCiduY1JOQS1pbnRlci1jaHIzLTIxNjYnLAonbmNSTkEtaW50ZXItY2hyOC02OTQ0JywKJ25jUk5BLWFzLWNocjctNjA2NScsCiduY1JOQS1pbnRlci1jaHI4LTY4OTYnLAonbmNSTkEtaW50ZXItY2hyMi0xOTYzJywKJ25jUk5BLWludGVyLWNocjQtMzQyNScsCiduY1JOQS1pbnRlci1jaHIxMy0xMTM4NScsCiduY1JOQS1pbnRlci1jaHI5LTc4ODUnLAonbmNSTkEtYXMtY2hyMTAtOTQxMScsCiduY1JOQS1hcy1jaHI5LTg0MTknLAonbmNSTkEtYXMtY2hyMTItMTA2MTgnLAonbmNSTkEtaW50ZXItY2hyNy02MzkwJywKJ25jUk5BLWludGVyLWNocjE3LTE0MTUxJywKJ25jUk5BLWFzLWNocjEzLTExNzg3JywKJ25jUk5BLWFzLWNocjItMTk2NScsCiduY1JOQS1pbnRlci1jaHI2LTU3MjEnLAonbmNSTkEtaW50ZXItY2hyNi01ODIyJywKJ25jUk5BLWludGVyLWNocjExLTk2MzUnLAonbmNSTkEtaW50ZXItY2hyMTEtOTk2NScsCiduY1JOQS1pbnRlci1jaHI0LTMwNTInLAonbmNSTkEtaW50ZXItY2hyMTctMTM4NTcnLAonbmNSTkEtaW50ZXItY2hyMTMtMTEyMDEnLAonbmNSTkEtaW50ZXItY2hyNi01MjQ5JywKJ25jUk5BLWludGVyLWNocjE5LTE0ODUxJywKJ25jUk5BLWludGVyLWNocjYtNTYzOCcsCiduY1JOQS1pbnRlci1jaHIxNy0xNDEzMCcsCiduY1JOQS1pbnRlci1jaHI5LTc5OTMnLAonbmNSTkEtaW50ZXItY2hyMTgtMTQ2NTYnLAonbmNSTkEtaW50ZXItY2hyOS03OTkyJywKJ25jUk5BLWludGVyLWNocjEtNTY2JywKJ25jUk5BLWludGVyLWNocjEyLTEwNzE1JywKJ25jUk5BLWludGVyLWNocjE3LTE0MTAyJywKJ25jUk5BLWludGVyLWNocjQtMzAxMCcsCiduY1JOQS1pbnRlci1jaHIzLTI3NjQnLAonbmNSTkEtaW50ZXItY2hyNC0zMzA2JywKJ25jUk5BLWludGVyLWNocjE5LTE0OTc5JywKJ25jUk5BLWludGVyLWNocjEtNTcwJywKJ25jUk5BLWludGVyLWNocjE5LTE0NzkwJywKJ25jUk5BLWludGVyLWNocjQtMzI4MicsCiduY1JOQS1pbnRlci1jaHI1LTQ3NzcnLAonbmNSTkEtaW50ZXItY2hyOC03NjA1JywKJ25jUk5BLWludGVyLWNocjktODAwMCcsCiduY1JOQS1hcy1jaHIxNS0xMjkyMCcsCiduY1JOQS1hcy1jaHIxLTM2OScsCiduY1JOQS1pbnRlci1jaHIxOS0xNDk1MicsCiduY1JOQS1hcy1jaHI5LTgzOTMnLAonbmNSTkEtYXMtY2hyMTQtMTIwNzQnLAonbmNSTkEtaW50ZXItY2hyMTItMTA0MTUnLAonbmNSTkEtaW50ZXItY2hyNy02NTU5JywKJ25jUk5BLWludGVyLWNocjEtNjMwJywKJ25jUk5BLWludGVyLWNocjQtMzE0MicsCiduY1JOQS1pbnRlci1jaHI2LTUxMzEnLAonbmNSTkEtaW50ZXItY2hyMTYtMTMwNTAnLAonbmNSTkEtaW50ZXItY2hyNy02NDExJywKJ25jUk5BLWludGVyLWNocjUtNDc0NicsCiduY1JOQS1pbnRlci1jaHIxLTYzMycsCiduY1JOQS1pbnRlci1jaHIxMC04NDYxJywKJ25jUk5BLWludGVyLWNocjItMjAxNicsCiduY1JOQS1pbnRlci1jaHI2LTUxMzcnLAonbmNSTkEtYXMtY2hyNC0zMzAwJywKJ25jUk5BLWludGVyLWNocjQtMzAwOScsCiduY1JOQS1pbnRlci1jaHIyLTE5MjMnLAonbmNSTkEtaW50ZXItY2hyMS02NzAnLAonbmNSTkEtaW50ZXItY2hyMTUtMTI4MzUnLAonbmNSTkEtaW50ZXItY2hyMTgtMTQ2NTUnLAonbmNSTkEtaW50ZXItY2hyMTYtMTMyMTEnLAonbmNSTkEtYXMtY2hyNy02MDUwJywKJ25jUk5BLWludGVyLWNocjctNjUwOCcsCiduY1JOQS1pbnRlci1jaHIxMS0xMDIwNicsCiduY1JOQS1pbnRlci1jaHIxMy0xMTM5OScsCiduY1JOQS1pbnRlci1jaHI4LTY3NTcnLAonbmNSTkEtaW50ZXItY2hyMS0xMjknLAonbmNSTkEtaW50ZXItY2hyMTItMTA0NTknLAonbmNSTkEtaW50ZXItY2hyNy02NzA5JywKJ25jUk5BLWludGVyLWNocjEyLTEwNzEzJywKJ25jUk5BLWludGVyLWNocjctNjUyMycsCiduY1JOQS1pbnRlci1jaHIyLTIwMTcnLAonbmNSTkEtaW50ZXItY2hyNy02MzQzJywKJ25jUk5BLWludGVyLWNocjEtNjMnLAonbmNSTkEtYXMtY2hyMy0yOTM2JywKJ25jUk5BLWludGVyLWNocjE4LTE0NjkxJywKJ25jUk5BLWludGVyLWNocjctNjA5NycsCiduY1JOQS1pbnRlci1jaHI2LTU3MjMnKQpgYGAKCgpgYGB7cn0KRGVmYXVsdEFzc2F5KGRyb3BsZXQpIDwtICJSTkEiCiNkcm9wbGV0IDwtIE5vcm1hbGl6ZURhdGEoY29tYmluZWQsIHZlcmJvc2UgPSBUUlVFLCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJSQyIsIHNjYWxlLmZhY3RvciA9IDFlNikKY29tYmluZWQgPC0gTm9ybWFsaXplRGF0YShjb21iaW5lZCwgdmVyYm9zZSA9IFRSVUUpCgpEb3RQbG90KGNvbWJpbmVkLCBmZWF0dXJlcyA9IGFsbF9nZW5lcykKRmVhdHVyZVBsb3QoY29tYmluZWQsIGZlYXR1cmVzID0gZ2VuZXNfaGVwX21haW4sIG1pbi5jdXRvZmYgPSAicTkiKQojaGVwYXRvY3l0ZXMgCnN1YnRpc3NwbG90IDwtIERvdFBsb3QoY29tYmluZWQsIGZlYXR1cmVzID0gYyhnZW5lc19oZXBfbWFpbiwgZ2VuZXNfZW5kbywgZ2VuZXNfYmVjX2JfaW1tdW5lLCBnZW5lc19rdXBwZmVyLCBnZW5lc19uaykpClBDIDwtIERvdFBsb3QoY29tYmluZWQsIGZlYXR1cmVzID0gYyhnZW5lc19oZXBfbWFpbixnZW5lc196b25lcykpCk5QQyA8LSBEb3RQbG90KGNvbWJpbmVkLCBmZWF0dXJlcyA9IGMoZ2VuZXNfZW5kbyxnZW5lc19rdXBwZmVyLCBnZW5lc19uaykpCmFsbCA8LSBEb3RQbG90KGNvbWJpbmVkLCBmZWF0dXJlcz1jKGFsbF9nZW5lcykpCgojIyMgY29leHByZXNzaW9uIHBsb3RzIyMjIwoKZjEgPC0gRmVhdHVyZVBsb3QoS08uY2VsbHMsIGZlYXR1cmVzID0gYygnQ3lwMmIxMCcsJ25jUk5BLWludGVyLWNocjctNTk5OCcpLCByZWR1Y3Rpb24gPSAibWRzIiwgb3JkZXIgPSBUUlVFLHNwbGl0LmJ5ID0gInN0aW0iLCBibGVuZCA9IFRSVUUsc29ydC5jZWxsID0gVFJVRSwgbWF4LmN1dG9mZiA9IDAuNSkKCgojIyMjIyMjIyMjIHRoaXMgaXMgZXhhY3QgYXZlcmFnaW5nIGZvcm11bGEgIyMjIyMjIyMjIyMjIyMjMzMKICB4IDwtIChBdmVyYWdlRXhwcmVzc2lvbihLTy5jZWxscywgdmVyYm9zZSA9IFRSVUUsIGFzc2F5cyA9ICJSTkEiICxzbG90PSJjb3VudHMiKSRSTkEpCiAgIHhbIm5jUk5BLWludGVyLWNocjctNTk5OCIsXQojICAgICAgICAgICAgICAgICAgICAgICAgIEcxNzFCICAgIEcxNzFDCiNuY1JOQS1pbnRlci1jaHI3LTU5OTggMS44NzE3OTUgMS4wOTE0NjMKIyMjIyMjIyMKI0lkZW50cyhjb21iaW5lZCkgPC0gZmFjdG9yKElkZW50cyhjb21iaW5lZCksIGxldmVscyA9IGMoMCwxLDEyKSkKbWFya2Vycy50by5wbG90IDwtIGMoIkFsYiIsIm5jUk5BLWludGVyLWNocjctNTk5OCIpCkRvdFBsb3QoY29tYmluZWQsIGZlYXR1cmVzID0gcmV2KG1hcmtlcnMudG8ucGxvdCksIGNvbHMgPSBjKCJibHVlIiwgInJlZCIpLCBkb3Quc2NhbGUgPSA4LCAKICAgIHNwbGl0LmJ5ID0gInN0aW0iKSArIFJvdGF0ZWRBeGlzKCkKCkZlYXR1cmVQbG90KGNvbWJpbmVkLCBmZWF0dXJlcyA9IGMoIkFsYiIsICJuY1JOQS1pbnRlci1jaHI3LTU5OTgiLCJDeXAyYjEwIiwiZFNhQ2FzOSIsIktSQUIiLCJBQVY4LW1DaGVycnkiKSwgc3BsaXQuYnkgPSAic3RpbSIsIG1heC5jdXRvZmYgPSAzLCBjb2xzID0gYygiZ3JleSIsICJyZWQiKSkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHZsbnBsb3QgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCnBsb3RzIDwtIFZsblBsb3QoY29tYmluZWQsIGZlYXR1cmVzID0gYygiQWxiIiwgIm5jUk5BLWludGVyLWNocjctNTk5OCIsIkN5cDJiMTAiLCJkU2FDYXM5IiksIHNwbGl0LmJ5ID0gInN0aW0iLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBwdC5zaXplID0gMCwgY29tYmluZSA9IEZBTFNFKQpDb21iaW5lUGxvdHMocGxvdHMgPSBwbG90cywgbmNvbCA9IDEpCgpwbG90cyA8LSBWbG5QbG90KGNvbWJpbmVkLCBmZWF0dXJlcyA9IGMoIkxoeDQiLCJEdG5hIiwiRmFtMTg5YTEiLCJHYWxudDE2IiwiS2Fscm4iKSwgc3BsaXQuYnkgPSAic3RpbSIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIHB0LnNpemUgPSAwLCBjb21iaW5lID0gRkFMU0UpCkNvbWJpbmVQbG90cyhwbG90cyA9IHBsb3RzLCBuY29sID0gMSkKCgojZW5kb3RoZWxpYWwKRG90UGxvdChjb21iaW5lZCwgZmVhdHVyZXMgPSBnZW5lc19lbmRvKQoKI3pvbmVzCnpvbmVzIDwtIERvdFBsb3QoY29tYmluZWQsIGZlYXR1cmVzID0gZ2VuZXNfem9uZXMpCgpmMSA8LSBGZWF0dXJlUGxvdChjb21iaW5lZCwgZmVhdHVyZXMgPSBjKCdDeXAyZTEnLCdDeXAyZjInLCdBc3MxJyksIG1pbi5jdXRvZmYgPSAicTkiLCByZWR1Y3Rpb24gPSAidHNuZSIpCgpEaW1QbG90KGNvbWJpbmVkLCBsYWJlbCA9IFRSVUUpCgpzYXZlKGNvbWJpbmVkLCBmaWxlPSJTZXVyYXRfc21hcnQtZHJvcF9pbnRlZ3JhdGVkLlJvYmoiKQoKCiMjIyMjIyMjIyMjIyMjIyMjIHNhdmUgcmF3IGNvdW50cyBmcm9tIGNsdXN0ZXIgIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpJZGVudHMoY29tYmluZWQpIDwtICJzdGltIgoKIyMjIHRvIGF2ZXJnYWUgb3V0IHRoZSBtYXRyaXggZnJvbSBLTyBjZWxscyAKCmNvbWJpbmVkLnJhdy5kYXRhLjAuMSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKGNvbWJpbmVkLCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoY29tYmluZWQsIGlkZW50ID0gMCxpZGVudHMgPSAic3RpbSIpXSkKY29tYmluZWQucmF3LmRhdGEuMSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKGNvbWJpbmVkLCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhjb21iaW5lZCwgaWRlbnQgPSAwKV0pCmNvbWJpbmVkLnJhdy5kYXRhLjIgPC0gYXMubWF0cml4KEdldEFzc2F5RGF0YShjb21iaW5lZCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoY29tYmluZWQsIGlkZW50ID0gMCldKQoKI2NvbWJpbmVkLnJhdy5kYXRhLltpXSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKGNvbWJpbmVkLCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhjb21iaW5lZCwgaWRlbnQgPSAxKV0pCiNjb21iaW5lZC5yYXcuZGF0YS4xMiA8LWFzLm1hdHJpeChHZXRBc3NheURhdGEoY29tYmluZWQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKGNvbWJpbmVkLCBpZGVudCA9IDEyKV0pCiNjb21iaW5lZC5yYXcuZGF0YS4xIDwtIGFzLm1hdHJpeChHZXRBc3NheURhdGEoY29tYmluZWQsIHNsb3QgPSAiY291bnRzIikpCnggPC0gQXZlcmFnZUV4cHJlc3Npb24odGVzdC5jb21iaW5lZCxhc3NheXMgPSAiUk5BIixhZGQuaWRlbnQgPSAic3RpbSIsIHNsb3QgPSAiZGF0YSIsdXNlLnNjYWxlID0gRkFMU0UsIHVzZS5jb3VudHMgPSBGQUxTRSkkUk5BCgojfSMjIyMjIyMjIENBUiBkYXRhIAphdmcuY29tYmluZWQuY2VsbHMgPC0gKEF2ZXJhZ2VFeHByZXNzaW9uKGNvbWJpbmVkLCB2ZXJib3NlID0gRkFMU0UpJFJOQSkgCmF2Zy5jb21iaW5lZC5jZWxscyRnZW5lIDwtIHJvd25hbWVzKGF2Zy5jb21iaW5lZC5jZWxscykKCkNBUl9GUCA8LSBGZWF0dXJlUGxvdChjb21iaW5lZCwgZmVhdHVyZXMgPSBjKCdDeXAyYjEwJywnTnIxaTMnKSwgcmVkdWN0aW9uID0gInVtYXAiLCBvcmRlciA9IFRSVUUsc3BsaXQuYnkgPSAic3RpbSIsIGJsZW5kID0gVFJVRSxzb3J0LmNlbGwgPSBUUlVFLCBtYXguY3V0b2ZmID0gMSwgbWluLmN1dG9mZiA9IDAsIHB0LnNpemUgPSAwLjUsIHJlcGVsID0gVFJVRSkKQ0FSX0RPVF9OUiA8LSBEb3RQbG90KGNvbWJpbmVkLCBmZWF0dXJlcyA9ICdOcjFpMycsIGNvbC5taW4gPSAwKQoKQ3lwMmIxMF9GUCA8LSBGZWF0dXJlUGxvdChjb21iaW5lZCwgZmVhdHVyZXMgPSAnQ3lwMmIxMCcsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbWluLmN1dG9mZiA9IDApCiMjIyMjIyMjIyMjIHRTTkUgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmNvbWJpbmVkIDwtIE5vcm1hbGl6ZURhdGEob2JqZWN0ID0gY29tYmluZWQpCmNvbWJpbmVkIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGNvbWJpbmVkLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpgYGAKCgpgYGB7cn0KCkcxNzJfVFBNX2NvdW50ICA8LSByZWYuaW50ZWdyYXRlZC4xCkcxNzJfVFBNX2NvdW50ICA8LSBOb3JtYWxpemVEYXRhKEcxNzJfVFBNX2NvdW50LGFzc2F5ID0gIlJOQSIsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIlJDIiwgc2NhbGUuZmFjdG9yID0gMWU2KQoKCgpUUE1jb3VudDBNMTwtIGNiaW5kKGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICcwX0cxNzJNMScpXSksIGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiZGF0YSIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnMF9HMTcyTTEnKV0pKQoKVFBNY291bnQxTTE8LSBjYmluZChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnMV9HMTcyTTEnKV0pLCBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzFfRzE3Mk0xJyldKSkKClRQTWNvdW50Mk0xPC0gY2JpbmQoYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzJfRzE3Mk0xJyldKSwgYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJkYXRhIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICcyX0cxNzJNMScpXSkpCgpUUE1jb3VudDNNMTwtIGNiaW5kKGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICczX0cxNzJNMScpXSksIGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiZGF0YSIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnM19HMTcyTTEnKV0pKQoKVFBNY291bnQ0TTE8LSBjYmluZChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnNF9HMTcyTTEnKV0pLCBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzRfRzE3Mk0xJyldKSkKClRQTWNvdW50NU0xPC0gY2JpbmQoYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzVfRzE3Mk0xJyldKSwgYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJkYXRhIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICc1X0cxNzJNMScpXSkpCgpUUE1jb3VudDZNMTwtIGNiaW5kKGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICc2X0cxNzJNMScpXSksIGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiZGF0YSIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnNl9HMTcyTTEnKV0pKQoKVFBNY291bnQ3TTE8LSBjYmluZChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnN19HMTcyTTEnKV0pLCBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzdfRzE3Mk0xJyldKSkKClRQTWNvdW50OE0xPC0gY2JpbmQoYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzhfRzE3Mk0xJyldKSwgYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJkYXRhIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICc4X0cxNzJNMScpXSkpCgoKCgpUUE1jb3VudDBNMjwtIGNiaW5kKGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICcwX0cxNzJNMicpXSksIGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiZGF0YSIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnMF9HMTcyTTInKV0pKQoKVFBNY291bnQxTTI8LSBjYmluZChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnMV9HMTcyTTInKV0pLCBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzFfRzE3Mk0yJyldKSkKClRQTWNvdW50Mk0yPC0gY2JpbmQoYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzJfRzE3Mk0yJyldKSwgYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJkYXRhIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICcyX0cxNzJNMicpXSkpCgpUUE1jb3VudDNNMjwtIGNiaW5kKGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICczX0cxNzJNMicpXSksIGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiZGF0YSIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnM19HMTcyTTInKV0pKQoKVFBNY291bnQ0TTI8LSBjYmluZChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnNF9HMTcyTTInKV0pLCBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzRfRzE3Mk0yJyldKSkKClRQTWNvdW50NU0yPC0gY2JpbmQoYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzVfRzE3Mk0yJyldKSwgYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJkYXRhIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICc1X0cxNzJNMicpXSkpCgpUUE1jb3VudDZNMjwtIGNiaW5kKGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiY291bnRzIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICc2X0cxNzJNMicpXSksIGFzLm1hdHJpeChHZXRBc3NheURhdGEoRzE3Ml9UUE1fY291bnQsIHNsb3QgPSAiZGF0YSIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnNl9HMTcyTTInKV0pKQoKVFBNY291bnQ3TTI8LSBjYmluZChhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhHMTcyX1RQTV9jb3VudCwgaWRlbnQgPSAnN19HMTcyTTInKV0pLCBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEcxNzJfVFBNX2NvdW50LCBzbG90ID0gImRhdGEiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzdfRzE3Mk0yJyldKSkKClRQTWNvdW50OE0yPC0gY2JpbmQoYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoRzE3Ml9UUE1fY291bnQsIGlkZW50ID0gJzhfRzE3Mk0yJyldKSwgYXMubWF0cml4KEdldEFzc2F5RGF0YShHMTcyX1RQTV9jb3VudCwgc2xvdCA9ICJkYXRhIilbLCBXaGljaENlbGxzKEcxNzJfVFBNX2NvdW50LCBpZGVudCA9ICc4X0cxNzJNMicpXSkpCgoKCgp3cml0ZS5jc3YoVFBNY291bnQwTTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQwTTEiKQp3cml0ZS5jc3YoVFBNY291bnQxTTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQxTTEiKQp3cml0ZS5jc3YoVFBNY291bnQyTTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQyTTEiKQp3cml0ZS5jc3YoVFBNY291bnQzTTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQzTTEiKQp3cml0ZS5jc3YoVFBNY291bnQ0TTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQ0TTEiKQp3cml0ZS5jc3YoVFBNY291bnQ1TTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQ1TTEiKQp3cml0ZS5jc3YoVFBNY291bnQ2TTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQ2TTEiKQp3cml0ZS5jc3YoVFBNY291bnQ3TTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQ3TTEiKQp3cml0ZS5jc3YoVFBNY291bnQ4TTEsICJDb3VudFJlc3VsdC9jb3VudHNfVFBNY291bnQ4TTEiKQoKCndyaXRlLmNzdihUUE1jb3VudDBNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDBNMiIpCndyaXRlLmNzdihUUE1jb3VudDFNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDFNMiIpCndyaXRlLmNzdihUUE1jb3VudDJNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDJNMiIpCndyaXRlLmNzdihUUE1jb3VudDNNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDNNMiIpCndyaXRlLmNzdihUUE1jb3VudDRNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDRNMiIpCndyaXRlLmNzdihUUE1jb3VudDVNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDVNMiIpCndyaXRlLmNzdihUUE1jb3VudDZNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDZNMiIpCndyaXRlLmNzdihUUE1jb3VudDdNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDdNMiIpCndyaXRlLmNzdihUUE1jb3VudDhNMiwgIkNvdW50UmVzdWx0L2NvdW50c19UUE1jb3VudDhNMiIpCgoKI2F2Zy5LTy5jZWxscyA8LSBsb2cxcChBdmVyYWdlRXhwcmVzc2lvbihLTy5jZWxscywgdmVyYm9zZSA9IEZBTFNFKSRSTkEpICAjb3JpZ2luYWwgY29kZSBsb2cgdHJhbnNmb3JtZWQKYXZnLktPLmNlbGxzIDwtIChBdmVyYWdlRXhwcmVzc2lvbihLTy5jZWxscywgdmVyYm9zZSA9IEZBTFNFKSRSTkEpIAphdmcuS08uY2VsbHMkZ2VuZSA8LSByb3duYW1lcyhhdmcuS08uY2VsbHMpCgpnZW5lcy50by5sYWJlbD0gKCJuY1JOQS1pbnRlci1jaHI3LTU5OTgiKQojZ2VuZXMudG8ubGFiZWwgPSBjKCJJU0cxNSIsICJMWTZFIiwgIklGSTYiLCAiSVNHMjAiLCAiTVgxIiwgIklGSVQyIiwgIklGSVQxIiwgIkNYQ0wxMCIsICJDQ0w4IikKcDEgPC0gZ2dwbG90KGF2Zy5LTy5jZWxscywgYWVzKENUUkwsIFNUSU0pKSArIGdlb21fcG9pbnQoKSArIGdndGl0bGUoIkNENCBOYWl2ZSBUIENlbGxzIikKcDEgPC0gTGFiZWxQb2ludHMocGxvdCA9IHAxLCBwb2ludHMgPSBnZW5lcy50by5sYWJlbCwgcmVwZWwgPSBUUlVFKQpwMiA8LSBnZ3Bsb3QoYXZnLmNkMTQubW9ubywgYWVzKENUUkwsIFNUSU0pKSArIGdlb21fcG9pbnQoKSArIGdndGl0bGUoIkNEMTQgTW9ub2N5dGVzIikKcDIgPC0gTGFiZWxQb2ludHMocGxvdCA9IHAyLCBwb2ludHMgPSBnZW5lcy50by5sYWJlbCwgcmVwZWwgPSBUUlVFKQpwbG90X2dyaWQocDEsIHAyKQpgYGAKCgpgYGB7cn0KS08uY2VsbHMgPC0gUnVuVU1BUChLTy5jZWxscywgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwICkKS08uY2VsbHMgPC0gRmluZE5laWdoYm9ycyhLTy5jZWxscywgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwKQpLTy5jZWxscyA8LSBGaW5kQ2x1c3RlcnMoS08uY2VsbHMsIHJlc29sdXRpb24gPSAwLjUgKSAgIApLTy5jZWxscyA8LSBSdW5UU05FKEtPLmNlbGxzLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjApCiAKCkhlcC5jZWxscyA8LSBSdW5VTUFQKEhlcC5jZWxscywgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwICkKSGVwLmNlbGxzIDwtIEZpbmROZWlnaGJvcnMoSGVwLmNlbGxzLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjApCkhlcC5jZWxscyA8LSBGaW5kQ2x1c3RlcnMoSGVwLmNlbGxzLCByZXNvbHV0aW9uID0gMC41ICkgICAKSGVwLmNlbGxzIDwtIFJ1blRTTkUoSGVwLmNlbGxzLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjApCiAKCiAgIAogIyBWaXN1YWxpemF0aW9uCnAxIDwtIFVNQVBQbG90KEtPLmNlbGxzLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInN0aW0iKQpwMiA8LSBVTUFQUGxvdChLTy5jZWxscywgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJtb3VzZS5zZXgiKQpwMyA8LSBVTUFQUGxvdChLTy5jZWxscywgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUpCnA0IDwtIFVNQVBQbG90KEtPLmNlbGxzLCBsYWJlbD1UUlVFKQpwbG90X2dyaWQocDEscDQpIApEaW1QbG90KEtPLmNlbGxzLCByZWR1Y3Rpb24gPSAidW1hcCIsIHNwbGl0LmJ5ID0gInN0aW0iKSAgIAoKCiNoZXBhdG9jeXRlIGNlbGxzCgpwNSA8LSBVTUFQUGxvdChIZXAuY2VsbHMsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic3RpbSIpCnA2IDwtIFVNQVBQbG90KEhlcC5jZWxscywgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJtb3VzZS5zZXgiKQpwNyA8LSBVTUFQUGxvdChIZXAuY2VsbHMsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBUUlVFKQpwOCA8LSBVTUFQUGxvdChIZXAuY2VsbHMsIGxhYmVsPVRSVUUpCnBsb3RfZ3JpZChwNSxwOCkgCkRpbVBsb3QoS08uY2VsbHMsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgc3BsaXQuYnkgPSAic3RpbSIpICAgCgoKcmF3LmRhdGEuS08uMCA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKEtPLmNlbGxzLCBzbG90ID0gImNvdW50cyIpWywgV2hpY2hDZWxscyhLTy5jZWxscywgaWRlbnQgPSAwKV0pCnJhdy5kYXRhLktPLjEgPC0gYXMubWF0cml4KEdldEFzc2F5RGF0YShLTy5jZWxscywgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoS08uY2VsbHMsIGlkZW50ID0gMSldKQpyYXcuZGF0YS5LTy4yIDwtYXMubWF0cml4KEdldEFzc2F5RGF0YShLTy5jZWxscywgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoS08uY2VsbHMsIGlkZW50ID0gMildKQpyYXcuZGF0YS5LTy4zIDwtYXMubWF0cml4KEdldEFzc2F5RGF0YShLTy5jZWxscywgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoS08uY2VsbHMsIGlkZW50ID0gMyldKQpyYXcuZGF0YS5LTy40IDwtYXMubWF0cml4KEdldEFzc2F5RGF0YShLTy5jZWxscywgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoS08uY2VsbHMsIGlkZW50ID0gNCldKQpyYXcuZGF0YS5LTy41IDwtYXMubWF0cml4KEdldEFzc2F5RGF0YShLTy5jZWxscywgc2xvdCA9ICJjb3VudHMiKVssIFdoaWNoQ2VsbHMoS08uY2VsbHMsIGlkZW50ID0gNSldKQoKCndyaXRlLmNzdihyYXcuZGF0YS5LTy4wLCAiQ291bnRSZXN1bHQvTWFya2Vycy9yYXcuZGF0YS5LTy4wIikKd3JpdGUuY3N2KHJhdy5kYXRhLktPLjEsICJDb3VudFJlc3VsdC9NYXJrZXJzL3Jhdy5kYXRhLktPLjEiKQp3cml0ZS5jc3YocmF3LmRhdGEuS08uMiwgIkNvdW50UmVzdWx0L01hcmtlcnMvcmF3LmRhdGEuS08uMiIpCndyaXRlLmNzdihyYXcuZGF0YS5LTy4zLCAiQ291bnRSZXN1bHQvTWFya2Vycy9yYXcuZGF0YS5LTy4zIikKd3JpdGUuY3N2KHJhdy5kYXRhLktPLjQsICJDb3VudFJlc3VsdC9NYXJrZXJzL3Jhdy5kYXRhLktPLjQiKQp3cml0ZS5jc3YocmF3LmRhdGEuS08uNSwgIkNvdW50UmVzdWx0L01hcmtlcnMvcmF3LmRhdGEuS08uNSIpCgoKCmYxIDwtIEZlYXR1cmVQbG90KEtPLmNlbGxzLCBmZWF0dXJlcyA9IGMoJ25jUk5BLWludGVyLWNocjctNTk5OCcpLCAgcmVkdWN0aW9uID0gInVtYXAiLCBzcGxpdC5ieSA9ICJzdGltIikKcGxvdF9ncmlkKGYxLHAxLHA0KSAKCkRlZmF1bHRBc3NheShLTy5jZWxscykgPC0gIlJOQSIKS08uY2VsbHMgPC0gTm9ybWFsaXplRGF0YShLTy5jZWxscywgdmVyYm9zZSA9IEZBTFNFKQoKcGxvdHMgPC0gVmxuUGxvdChLTy5jZWxscywgZmVhdHVyZXMgPSBjKCJBbGIiLCAibmNSTkEtaW50ZXItY2hyNy01OTk4IiwiQ3lwMmIxMCIsIkN5cDJlMSIsIkN5cDJmMiIpLCBzcGxpdC5ieSA9ICJzdGltIiwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgcHQuc2l6ZSA9IDAsIGNvbWJpbmUgPSBGQUxTRSkKQ29tYmluZVBsb3RzKHBsb3RzID0gcGxvdHMsIG5jb2wgPSAxKQoKVGhyZWVfZml2ZV9zaXggPC0gc3Vic2V0KEtPLmNlbGxzLCBpZGVudHMgPSBjKCI1IiwiNiIpKQoKVGhyZWVfZml2ZV9zaXggPC0gUnVuVU1BUChUaHJlZV9maXZlX3NpeCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwICkKVGhyZWVfZml2ZV9zaXggPC0gRmluZE5laWdoYm9ycyhUaHJlZV9maXZlX3NpeCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwKQpUaHJlZV9maXZlX3NpeCA8LSBGaW5kQ2x1c3RlcnMoVGhyZWVfZml2ZV9zaXgsIHJlc29sdXRpb24gPSAxICkgICAKVGhyZWVfZml2ZV9zaXggPC0gUnVuVFNORShUaHJlZV9maXZlX3NpeCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjIwKQoKcDEgPC0gVU1BUFBsb3QoVGhyZWVfZml2ZV9zaXgsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic3RpbSIpCnAyIDwtIFVNQVBQbG90KFRocmVlX2ZpdmVfc2l4LCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gIm1vdXNlLnNleCIpCnAzIDwtIFVNQVBQbG90KFRocmVlX2ZpdmVfc2l4LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSkKcDQgPC0gVU1BUFBsb3QoVGhyZWVfZml2ZV9zaXgsIGxhYmVsPVRSVUUpCnBsb3RfZ3JpZChwMSxwNCkgCkRpbVBsb3QoVGhyZWVfZml2ZV9zaXgsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgc3BsaXQuYnkgPSAic3RpbSIpICAgCgpmMSA8LSBGZWF0dXJlUGxvdChUaHJlZV9maXZlX3NpeCwgZmVhdHVyZXMgPSBjKCduY1JOQS1pbnRlci1jaHI3LTU5OTgnKSwgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgc3BsaXQuYnkgPSAic3RpbSIpCgoKbG5jNTk5OCA8LSBzdWJzZXQoY29tYmluZWQsIGNlbGxzID0gbG5jNTk5OC5jZWxscywgaWRlbnRzID0gIjEiKQoKbG5jNTk5OCA8LSBSdW5VTUFQKGxuYzU5OTgsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyMCApCmxuYzU5OTggPC0gRmluZE5laWdoYm9ycyhsbmM1OTk4LCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MjApCmxuYzU5OTggPC0gRmluZENsdXN0ZXJzKGxuYzU5OTgsIHJlc29sdXRpb24gPSAxICkgICAKbG5jNTk5OCA8LSBSdW5UU05FKGxuYzU5OTgsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToyMCkKICAgIAogIyBWaXN1YWxpemF0aW9uCnAxIDwtIFVNQVBQbG90KGxuYzU5OTgsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAic3RpbSIpCnAyIDwtIFVNQVBQbG90KGxuYzU5OTgsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAibW91c2Uuc2V4IikKcDMgPC0gVU1BUFBsb3QobG5jNTk5OCwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUpCnA0IDwtIFVNQVBQbG90KGxuYzU5OTgsIGxhYmVsPVRSVUUpCnBsb3RfZ3JpZChwMSxwNCkgCkRpbVBsb3QobG5jNTk5OCwgcmVkdWN0aW9uID0gInVtYXAiLCBzcGxpdC5ieSA9ICJzdGltIikgICAKCmxuYzU5OTguY2VsbHMgPC0gV2hpY2hDZWxscyhvYmplY3QgPSBjb21iaW5lZCwgZXhwcmVzc2lvbiA9ICJuY1JOQS1pbnRlci1jaHI3LTU5OTgiID4gMSkKRmVhdHVyZVBsb3QobG5jNTk5OCwgZmVhdHVyZXMgPSBjKCJuY1JOQS1pbnRlci1jaHI3LTU5OTgiKSwgc3BsaXQuYnkgPSAic3RpbSIsICAKKyAgICAgICAgICAgICBjb2xzID0gYygiZ3JleSIsICJyZWQiKSwgY2VsbHMgPSBsbmM1OTk4LmNlbGxzLG1pbi5jdXRvZmYgPSAwLjUpCgoKRGVmYXVsdEFzc2F5KGxuYzU5OTgpIDwtICJSTkEiCmxuYzU5OTggPC0gTm9ybWFsaXplRGF0YShsbmM1OTk4LCB2ZXJib3NlID0gRkFMU0UpCgpwbG90cyA8LSBWbG5QbG90KGxuYzU5OTgsIGZlYXR1cmVzID0gYygiQWxiIiwgIm5jUk5BLWludGVyLWNocjctNTk5OCIsIkN5cDJiMTAiLCJDeXAyZTEiLCJDeXAyZjIiKSwgc3BsaXQuYnkgPSAic3RpbSIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIHB0LnNpemUgPSAwLCBjb21iaW5lID0gRkFMU0UpCkNvbWJpbmVQbG90cyhwbG90cyA9IHBsb3RzLCBuY29sID0gMSkKCiAKYGBgCgpgYGB7cn0KZCA8LSBkaXN0KHQoR2V0QXNzYXlEYXRhKEtPLmNlbGxzLCBzbG90ID0gInNjYWxlLmRhdGEiKSkpCiMgUnVuIHRoZSBNRFMgcHJvY2VkdXJlLCBrIGRldGVybWluZXMgdGhlIG51bWJlciBvZiBkaW1lbnNpb25zCm1kcyA8LSBjbWRzY2FsZShkID0gZCwgayA9IDIpCiMgY21kc2NhbGUgcmV0dXJucyB0aGUgY2VsbCBlbWJlZGRpbmdzLCB3ZSBmaXJzdCBsYWJlbCB0aGUgY29sdW1ucyB0byBlbnN1cmUgZG93bnN0cmVhbQojIGNvbnNpc3RlbmN5CmNvbG5hbWVzKG1kcykgPC0gcGFzdGUwKCJNRFNfIiwgMToyKQojIFdlIHdpbGwgbm93IHN0b3JlIHRoaXMgYXMgYSBjdXN0b20gZGltZW5zaW9uYWwgcmVkdWN0aW9uIGNhbGxlZCAnbWRzJwpLTy5jZWxsc1tbIm1kcyJdXSA8LSBDcmVhdGVEaW1SZWR1Y09iamVjdChlbWJlZGRpbmdzID0gbWRzLCBrZXkgPSAiTURTXyIsIGFzc2F5ID0gRGVmYXVsdEFzc2F5KEtPLmNlbGxzKSkKCiMgV2UgY2FuIG5vdyB1c2UgdGhpcyBhcyB5b3Ugd291bGQgYW55IG90aGVyIGRpbWVuc2lvbmFsIHJlZHVjdGlvbiBpbiBhbGwgZG93bnN0cmVhbSBmdW5jdGlvbnMKRGltUGxvdChLTy5jZWxscywgcmVkdWN0aW9uID0gIm1kcyIsIHB0LnNpemUgPSAwLjUpCmBgYAoKRmluZCBkaWZmZXJlbnRpYWwgbWFya2VycwoKYGBge3J9CktPLmNlbGxzJGNlbGx0eXBlLnN0aW0gPC0gcGFzdGUoSWRlbnRzKEtPLmNlbGxzKSwgS08uY2VsbHMkc3RpbSwgc2VwID0gIl8iKQpLTy5jZWxscyRjZWxsdHlwZSA8LSBJZGVudHMoS08uY2VsbHMpCklkZW50cyhLTy5jZWxscykgPC0gImNlbGx0eXBlLnN0aW0iCnJlc3BvbnNlMyA8LSBGaW5kTWFya2VycyhLTy5jZWxscywgaWRlbnQuMSA9IGMoIjFfRzE3MUIiLCIwX0cxNzFCIiwiMl9HMTcxQiIpLCBpZGVudC4yID0gYygiMV9HMTcxQyIsICIwX0cxNzFDIiwiMl9HMTcxQyIpLCB2ZXJib3NlID0gVFJVRSwgdGVzdC51c2UgPSAiTUFTVCIsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKaGVhZChyZXNwb25zZTMsIG4gPSAxNSkKCgojREUxOiBDb21wYXJlIGNsdXN0ZXIgMCsxKzEyICh0aGF0IGV4cHJlc3NlZCBsbmM1OTk4KSB3aXRoIE90aGVyIGhlcGF0b2N5dGUgY2x1c3RlcnMgKDIrNSs4KQojREUyOiBjb21wYXJlIGNsdXN0ZXIgMSAoc2hvd2VkIG1ham9yIGVmZmVjdHMgaW4gdGhlIEtEKSB2cyBDbHVzdGVyIDAgKHRoYXQgc2hvd2VkIGxpdHRsZSBLRCkKI0RFMzogRm9yIEtPLmNlbGxzIHRoYXQgZm9ybWVkIGZpdmUgc3ViY2x1c3RlciwgY29tcGFyZSBjbHVzdGVycyAzKzQrNSsxIHZzIDIrMAojREU0OiBmb3IgS08uY2VsbHMgdGhhdCBmb3JtZWQgZml2ZSBjbHVzdGVycy4gQ29tYXByZSBjbHVzdGVyIDQgdnMuIDIKCkRFMDExMi4yNTggPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCIwIiwiMSIsIjEyIiApLCBpZGVudC4yID0gYygiMiIsIjUiLCI4IiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREUwMTEyLkFsbCA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjAiLCIxIiwiMTIiICksIHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCkRFMS4yIDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiMSIgKSwgaWRlbnQuMiA9IGMoIjIiKSx2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpERTEuNSA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjEiICksIGlkZW50LjIgPSBjKCI1IiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREUxLjggPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCIxIiApLCBpZGVudC4yID0gYygiOCIpLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCgoKREUyLjUgPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCIyIiApLCBpZGVudC4yID0gYygiNSIpLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCkRFMi44IDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiMiIgKSwgaWRlbnQuMiA9IGMoIjgiKSx2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpERTUuOCA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjUiICksIGlkZW50LjIgPSBjKCI4IiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCgpERUs0MzUxLjIwIDwtIEZpbmRNYXJrZXJzKEtPLmNlbGxzLCBpZGVudC4xID0gYygiMyIsIjQiLCI1IiwiMSIgKSwgaWRlbnQuMiA9IGMoIjIiLCIwIiksdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCkRFSzQuMyA8LSBGaW5kTWFya2VycyhLTy5jZWxscywgaWRlbnQuMSA9ICI0IiwgaWRlbnQuMiA9ICIzIix2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpERUs0LjIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiNCIsIGlkZW50LjIgPSAiMiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREVLNC4wIDwtIEZpbmRNYXJrZXJzKEtPLmNlbGxzLCBpZGVudC4xID0gIjQiLCBpZGVudC4yID0gIjAiLHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCkRFSzQuMSA8LSBGaW5kTWFya2VycyhLTy5jZWxscywgaWRlbnQuMSA9ICI0IiwgaWRlbnQuMiA9ICIxIix2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpERUs0LjUgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiNCIsIGlkZW50LjIgPSAiNSIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCgoKIyMjIyMgY29tYXByaXNvbiBiZXR3ZWVuIEcxNzFCIHZzIEcxNzFDIGZvciBLTy5jZWxsIGNsdXN0ZXJzIG9mIDArMSsxMiAjIyMjIyMzMwoKREVLNF9DLkIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiNF9HMTcxQyIsIGlkZW50LjIgPSAiNF9HMTcxQiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREVLM19DLkIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiM19HMTcxQyIsIGlkZW50LjIgPSAiM19HMTcxQiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREVLMV9DLkIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiMV9HMTcxQyIsIGlkZW50LjIgPSAiMV9HMTcxQiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREVLMl9DLkIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiMl9HMTcxQyIsIGlkZW50LjIgPSAiMl9HMTcxQiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREVLMF9DLkIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiMF9HMTcxQyIsIGlkZW50LjIgPSAiMF9HMTcxQiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKREVLNV9DLkIgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSAiNV9HMTcxQyIsIGlkZW50LjIgPSAiNV9HMTcxQiIsdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBXcml0ZSB0aGUgcmVzdWx0cyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCndyaXRlLmNzdihERTAxMTIuMjU4LCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERTAxMTIuMjU4IikKd3JpdGUuY3N2KERFMDExMi5BbGwsICJDb3VudFJlc3VsdC9NYXJrZXJzL0RFMDExMi5BbGwiKQp3cml0ZS5jc3YoREUxLjIsICJDb3VudFJlc3VsdC9NYXJrZXJzL0RFMS4yIikKd3JpdGUuY3N2KERFMS41LCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERTEuNSIpCndyaXRlLmNzdihERTEuOCwgIkNvdW50UmVzdWx0L01hcmtlcnMvREUxLjgiKQp3cml0ZS5jc3YoREUyLjUsICJDb3VudFJlc3VsdC9NYXJrZXJzL0RFMi41IikKd3JpdGUuY3N2KERFMi44LCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERTIuOCIpCndyaXRlLmNzdihERTUuOCwgIkNvdW50UmVzdWx0L01hcmtlcnMvREU1LjgiKQoKd3JpdGUuY3N2KERFSzQzNTEuMjAsICJDb3VudFJlc3VsdC9NYXJrZXJzL0RFSzQzNTEuMjAiKQp3cml0ZS5jc3YoREVLNC4zLCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUs0LjMiKQp3cml0ZS5jc3YoREVLNC4yLCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUs0LjIiKQp3cml0ZS5jc3YoREVLNC4wLCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUs0LjAiKQp3cml0ZS5jc3YoREVLNC4xLCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUs0LjEiKQp3cml0ZS5jc3YoREVLNC41LCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUs0LjUiKQoKCndyaXRlLmNzdihERUs0X0MuQiwgIkNvdW50UmVzdWx0L01hcmtlcnMvREVLNF9DLkIiKQp3cml0ZS5jc3YoREVLM19DLkIsICJDb3VudFJlc3VsdC9NYXJrZXJzL0RFSzNfQy5CIikKd3JpdGUuY3N2KERFSzFfQy5CLCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUsxX0MuQiIpCndyaXRlLmNzdihERUsyX0MuQiwgIkNvdW50UmVzdWx0L01hcmtlcnMvREVLMl9DLkIiKQp3cml0ZS5jc3YoREVLMF9DLkIsICJDb3VudFJlc3VsdC9NYXJrZXJzL0RFSzBfQy5CIikKd3JpdGUuY3N2KERFSzVfQy5CLCAiQ291bnRSZXN1bHQvTWFya2Vycy9ERUs1X0MuQiIpCgoKCgpjb21iaW5lZCRjZWxsdHlwZS5zdGltIDwtIHBhc3RlKElkZW50cyhjb21iaW5lZCksIGNvbWJpbmVkJHN0aW0sIHNlcCA9ICJfIikKY29tYmluZWQkY2VsbHR5cGUgPC0gSWRlbnRzKGNvbWJpbmVkKQpJZGVudHMoY29tYmluZWQpIDwtICJjZWxsdHlwZS5zdGltIgoKCnRlc3QuY29tYmluZWQkY2VsbHR5cGUuc3RpbSA8LSBwYXN0ZShJZGVudHModGVzdC5jb21iaW5lZCksIHRlc3QuY29tYmluZWQkc3RpbSwgc2VwID0gIl8iKQp0ZXN0LmNvbWJpbmVkJGNlbGx0eXBlIDwtIElkZW50cyh0ZXN0LmNvbWJpbmVkKQpJZGVudHModGVzdC5jb21iaW5lZCkgPC0gImNlbGx0eXBlLnN0aW0iCgoKCgpDb21iaW5lZF9HMTcxQl92c19HMTcxQyA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjBfRzE3MUIiLCIxX0cxNzFCIiwiMl9HMTcxQiIsIjNfRzE3MUIiLCI0X0cxNzFCIiwiNV9HMTcxQiIsIjZfRzE3MUIiLCI3X0cxNzFCIiwiOF9HMTcxQiIsIjlfRzE3MUIiLCIxMF9HMTcxQiIsIjExX0cxNzFCIiwiMTJfRzE3MUIiICksIGlkZW50LjIgPSBjKCIwX0cxNzFDIiwiMV9HMTcxQyIsIjJfRzE3MUMiLCIzX0cxNzFDIiwiNF9HMTcxQyIsIjVfRzE3MUMiLCI2X0cxNzFDIiwiN19HMTcxQyIsIjhfRzE3MUMiLCI5X0cxNzFDIiwiMTBfRzE3MUMiLCIxMV9HMTcxQyIsIjEyX0cxNzFDIiApLCB2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQoKCkNvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MSA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjFfRzE3MUMiKSwgaWRlbnQuMiA9IGMoIjFfRzE3MUIiKSwgdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3QwIDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiMF9HMTcxQyIpLCBpZGVudC4yID0gYygiMF9HMTcxQiIpLCB2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDEyIDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiMTJfRzE3MUMiKSwgaWRlbnQuMiA9IGMoIjEyX0cxNzFCIiksIHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCkNvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MiA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjJfRzE3MUMiKSwgaWRlbnQuMiA9IGMoIjJfRzE3MUIiKSwgdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3Q1IDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiNV9HMTcxQyIpLCBpZGVudC4yID0gYygiNV9HMTcxQiIpLCB2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDggPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCI4X0cxNzFDIiksIGlkZW50LjIgPSBjKCI4X0cxNzFCIiksIHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCgoKQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3QzIDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiM19HMTcxQyIpLCBpZGVudC4yID0gYygiM19HMTcxQiIpLCB2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDQgPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCI0X0cxNzFDIiksIGlkZW50LjIgPSBjKCI0X0cxNzFCIiksIHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCkNvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0NiA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjZfRzE3MUMiKSwgaWRlbnQuMiA9IGMoIjZfRzE3MUIiKSwgdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3Q3IDwtIEZpbmRNYXJrZXJzKGNvbWJpbmVkLCBpZGVudC4xID0gYygiN19HMTcxQyIpLCBpZGVudC4yID0gYygiN19HMTcxQiIpLCB2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDkgPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCI5X0cxNzFDIiksIGlkZW50LjIgPSBjKCI5X0cxNzFCIiksIHZlcmJvc2UgPSBUUlVFLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCkNvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MTAgPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCIxMF9HMTcxQyIpLCBpZGVudC4yID0gYygiMTBfRzE3MUIiKSwgdmVyYm9zZSA9IFRSVUUsIGxvZ2ZjLnRocmVzaG9sZCA9IEZBTFNFLG1pbi5wY3QgPSBGQUxTRSkKQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3QxMSA8LSBGaW5kTWFya2Vycyhjb21iaW5lZCwgaWRlbnQuMSA9IGMoIjExX0cxNzFDIiksIGlkZW50LjIgPSBjKCIxMV9HMTcxQiIpLCB2ZXJib3NlID0gVFJVRSwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQoKCgoKCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDEsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MSIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDAsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MCIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDEyLCAiQ291bnRSZXN1bHQvTWFya2Vycy9Db21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDEyIikKd3JpdGUuY3N2KENvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MiwgIkNvdW50UmVzdWx0L01hcmtlcnMvQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3QyIikKd3JpdGUuY3N2KENvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0NSwgIkNvdW50UmVzdWx0L01hcmtlcnMvQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3Q1IikKd3JpdGUuY3N2KENvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0OCwgIkNvdW50UmVzdWx0L01hcmtlcnMvQ29tYmluZWRfRzE3MUNfdnNfRzE3MUJfQ2x1c3Q4IikKCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDMsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MyIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDQsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0NCIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDYsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0NiIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDcsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0NyIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDksICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0OSIpCndyaXRlLmNzdihDb21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDEwLCAiQ291bnRSZXN1bHQvTWFya2Vycy9Db21iaW5lZF9HMTcxQ192c19HMTcxQl9DbHVzdDEwIikKd3JpdGUuY3N2KENvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MTEsICJDb3VudFJlc3VsdC9NYXJrZXJzL0NvbWJpbmVkX0cxNzFDX3ZzX0cxNzFCX0NsdXN0MTEiKQoKCgoKClBDX3ZzX1BQX0cxNzFCIDwtIEZpbmRNYXJrZXJzKEtPLmNlbGxzLCBpZGVudC4xID0gYygiNF9HMTcxQiIsIjNfRzE3MUIiKSwgaWRlbnQuMiA9IGMoIjBfRzE3MUIiLCIyX0cxNzFCIiksIHZlcmJvc2UgPSBUUlVFLCB0ZXN0LnVzZSA9ICJNQVNUIiwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpoZWFkKFBDX3ZzX1BQX0cxNzFCLCBuID0gMTUpCgoKUENfdnNfUFBfRzE3MUMgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSBjKCI0X0cxNzFDIiwiM19HMTcxQyIpLCBpZGVudC4yID0gYygiMF9HMTcxQyIsIjJfRzE3MUMiKSwgdmVyYm9zZSA9IFRSVUUsIHRlc3QudXNlID0gIk1BU1QiLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCmhlYWQoUENfdnNfUFBfRzE3MUMsIG4gPSAxNSkKCgpQQ192c19QUF9HMTcxQkMgPC0gRmluZE1hcmtlcnMoS08uY2VsbHMsIGlkZW50LjEgPSBjKCI0X0cxNzFCIiwiM19HMTcxQiIsIjRfRzE3MUMiLCIzX0cxNzFDIiksIGlkZW50LjIgPSBjKCIwX0cxNzFCIiwiMl9HMTcxQiIsIjBfRzE3MUMiLCIyX0cxNzFDIiksIHZlcmJvc2UgPSBUUlVFLCB0ZXN0LnVzZSA9ICJNQVNUIiwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpoZWFkKFBDX3ZzX1BQX0cxNzFDLCBuID0gMTUpCgoKbG5jNTk5OF9LT19ERV8xIDwtIEZpbmRNYXJrZXJzKEtPLmNlbGxzLCBpZGVudC4xID0gYygiNF9HMTcxQiIsIjNfRzE3MUIiLCI1X0cxNzFCIiksIGlkZW50LjIgPSBjKCI0X0cxNzFDIiwiM19HMTcxQyIsIjVfRzE3MUMiKSwgdmVyYm9zZSA9IFRSVUUsIHRlc3QudXNlID0gIk1BU1QiLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCmhlYWQobG5jNTk5OF9LT19ERSwgbiA9IDE1KQoKCmxuYzU5OThfS09fREVfMiA8LSBGaW5kTWFya2VycyhLTy5jZWxscywgaWRlbnQuMSA9IGMoIjRfRzE3MUMiLCIzX0cxNzFDIiwiNV9HMTcxQyIpLCBpZGVudC4yID1jKCI0X0cxNzFCIiwiM19HMTcxQiIsIjVfRzE3MUIiKSAsIHZlcmJvc2UgPSBUUlVFLCB0ZXN0LnVzZSA9ICJNQVNUIiwgbG9nZmMudGhyZXNob2xkID0gRkFMU0UsbWluLnBjdCA9IEZBTFNFKQpoZWFkKGxuYzU5OThfS09fREUsIG4gPSAxNSkKCmNlbGwudHlwZS5nZW5lcyA8LSAoUENfdnNfUFBfRzE3MUJDWzFdKSAjIFRha2VzIGFsbCB0aGUgdW5pcXVlIGNlbGwgdHlwZSBzcGVjaWZpYyBnZW5lcwpHT3Rlcm1zID0gdG9wR090ZXJtcyhmZy5nZW5lcyA9IGNlbGwudHlwZS5nZW5lcywgYmcuZ2VuZXMgPSByb3duYW1lcyhLTy5jZWxsc0Bhc3NheXMkUk5BQGRhdGFLTy5jZWxsc0Bhc3NheXMkUk5BQGRhdGEpLCBvcmdhbmlzbSA9ICJNb3VzZSIpCgpjZWxsLnR5cGUuZ2VuZXMgPC0gKFBDX3ZzX1BQX0cxNzFCQ1sxXSkgIyBUYWtlcyBhbGwgdGhlIHVuaXF1ZSBjZWxsIHR5cGUgc3BlY2lmaWMgZ2VuZXMKR090ZXJtcyA9IHRvcEdPdGVybXMoZmcuZ2VuZXMgPSByb3duYW1lcyhjZWxsLnR5cGUuZ2VuZXMpLCBiZy5nZW5lcyA9IHJvd25hbWVzKEtPLmNlbGxzQGFzc2F5cyRSTkFAZGF0YSksIG9yZ2FuaXNtID0gIk1vdXNlIikKIApgYGAKCmBgYHtyfQoKQXZlcmdlRXhwcmVzc2lvbjIgPC0gZnVuY3Rpb24gKG9iamVjdCwgYXNzYXlzID0gTlVMTCwgZmVhdHVyZXMgPSBOVUxMLCByZXR1cm4uc2V1cmF0ID0gRkFMU0UsIAogICAgICAgICAgYWRkLmlkZW50ID0gTlVMTCwgc2xvdCA9ICJkYXRhIiwgdXNlLnNjYWxlID0gRkFMU0UsIHVzZS5jb3VudHMgPSBGQUxTRSwgCiAgICAgICAgICB2ZXJib3NlID0gVFJVRSwgLi4uKSAKewogICAgCiAgICBmeG4uYXZlcmFnZSA8LSBzd2l0Y2goRVhQUiA9IHNsb3QsIGRhdGEgPSBmdW5jdGlvbih4KSB7CiAgICAgICAgcmV0dXJuKG1lYW4oeCA9IHgpKQogICAgfSwgbWVhbikKICAgIG9iamVjdC5hc3NheXMgPC0gRmlsdGVyT2JqZWN0cyhvYmplY3QgPSBvYmplY3QsIGNsYXNzZXMua2VlcCA9ICJBc3NheSIpCiAgICBhc3NheXMgPC0gYXNzYXlzICV8fCUgb2JqZWN0LmFzc2F5cwogICAgaWRlbnQub3JpZyA8LSBJZGVudHMob2JqZWN0ID0gb2JqZWN0KQogICAgb3JpZy5sZXZlbHMgPC0gbGV2ZWxzKHggPSBJZGVudHMob2JqZWN0ID0gb2JqZWN0KSkKICAgIGlkZW50Lm5ldyA8LSBjKCkKICAgIGlmICghYWxsKGFzc2F5cyAlaW4lIG9iamVjdC5hc3NheXMpKSB7CiAgICAgICAgYXNzYXlzIDwtIGFzc2F5c1thc3NheXMgJWluJSBvYmplY3QuYXNzYXlzXQogICAgICAgIGlmIChsZW5ndGgoYXNzYXlzKSA9PSAwKSB7CiAgICAgICAgICAgIHN0b3AoIk5vbmUgb2YgdGhlIHJlcXVlc3RlZCBhc3NheXMgYXJlIHByZXNlbnQgaW4gdGhlIG9iamVjdCIpCiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICB3YXJuaW5nKCJSZXF1ZXN0ZWQgYXNzYXlzIHRoYXQgZG8gbm90IGV4aXN0IGluIG9iamVjdC4gUHJvY2VlZGluZyB3aXRoIGV4aXN0aW5nIGFzc2F5cyBvbmx5LiIpCiAgICAgICAgfQogICAgfQogICAgaWYgKCFpcy5udWxsKHggPSBhZGQuaWRlbnQpKSB7CiAgICAgICAgbmV3LmRhdGEgPC0gRmV0Y2hEYXRhKG9iamVjdCA9IG9iamVjdCwgdmFycyA9IGFkZC5pZGVudCkKICAgICAgICBuZXcuaWRlbnQgPC0gcGFzdGUoSWRlbnRzKG9iamVjdClbcm93bmFtZXMoeCA9IG5ldy5kYXRhKV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcuZGF0YVssIDFdLCBzZXAgPSAiXyIpCiAgICAgICAgSWRlbnRzKG9iamVjdCwgY2VsbHMgPSByb3duYW1lcyhuZXcuZGF0YSkpIDwtIG5ldy5pZGVudAogICAgfQogICAgZGF0YS5yZXR1cm4gPC0gbGlzdCgpCiAgICBmb3IgKGkgaW4gMTpsZW5ndGgoeCA9IGFzc2F5cykpIHsKICAgICAgICBkYXRhLnVzZSA8LSBHZXRBc3NheURhdGEob2JqZWN0ID0gb2JqZWN0LCBhc3NheSA9IGFzc2F5c1tpXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSBzbG90KQogICAgICAgIGZlYXR1cmVzLmFzc2F5IDwtIGZlYXR1cmVzCiAgICAgICAgaWYgKGxlbmd0aCh4ID0gaW50ZXJzZWN0KHggPSBmZWF0dXJlcywgeSA9IHJvd25hbWVzKHggPSBkYXRhLnVzZSkpKSA8IAogICAgICAgICAgICAxKSB7CiAgICAgICAgICAgIGZlYXR1cmVzLmFzc2F5IDwtIHJvd25hbWVzKHggPSBkYXRhLnVzZSkKICAgICAgICB9CiAgICAgICAgZGF0YS5hbGwgPC0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSBmZWF0dXJlcy5hc3NheSkKICAgICAgICBmb3IgKGogaW4gbGV2ZWxzKHggPSBJZGVudHMob2JqZWN0KSkpIHsKICAgICAgICAgICAgdGVtcC5jZWxscyA8LSBXaGljaENlbGxzKG9iamVjdCA9IG9iamVjdCwgaWRlbnRzID0gaikKICAgICAgICAgICAgZmVhdHVyZXMuYXNzYXkgPC0gdW5pcXVlKHggPSBpbnRlcnNlY3QoeCA9IGZlYXR1cmVzLmFzc2F5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHJvd25hbWVzKHggPSBkYXRhLnVzZSkpKQogICAgICAgICAgICBpZiAobGVuZ3RoKHggPSB0ZW1wLmNlbGxzKSA9PSAxKSB7CiAgICAgICAgICAgICAgICBkYXRhLnRlbXAgPC0gKGRhdGEudXNlW2ZlYXR1cmVzLmFzc2F5LCB0ZW1wLmNlbGxzXSkKICAgICAgICAgICAgICAgIGlmIChzbG90ID09ICJkYXRhIikgewogICAgICAgICAgICAgICAgICAgIGRhdGEudGVtcCA8LSAgZGF0YS50ZW1wCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGxlbmd0aCh4ID0gdGVtcC5jZWxscykgPiAxKSB7CiAgICAgICAgICAgICAgICBkYXRhLnRlbXAgPC0gYXBwbHkoWCA9IGRhdGEudXNlW2ZlYXR1cmVzLmFzc2F5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcC5jZWxscywgZHJvcCA9IEZBTFNFXSwgTUFSR0lOID0gMSwgRlVOID0gZnhuLmF2ZXJhZ2UpCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGF0YS5hbGwgPC0gY2JpbmQoZGF0YS5hbGwsIGRhdGEudGVtcCkKICAgICAgICAgICAgY29sbmFtZXMoeCA9IGRhdGEuYWxsKVtuY29sKHggPSBkYXRhLmFsbCldIDwtIGoKICAgICAgICAgICAgaWYgKHZlcmJvc2UpIHsKICAgICAgICAgICAgICAgIG1lc3NhZ2UocGFzdGUoIkZpbmlzaGVkIGF2ZXJhZ2luZyIsIGFzc2F5c1tpXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3IgY2x1c3RlciIsIGopKQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChpID09IDEpIHsKICAgICAgICAgICAgICAgIGlkZW50Lm5ldyA8LSBjKGlkZW50Lm5ldywgYXMuY2hhcmFjdGVyKHggPSBpZGVudC5vcmlnW3RlbXAuY2VsbHNbMV1dKSkKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBuYW1lcyh4ID0gaWRlbnQubmV3KSA8LSBsZXZlbHMoeCA9IElkZW50cyhvYmplY3QpKQogICAgICAgIGRhdGEucmV0dXJuW1tpXV0gPC0gZGF0YS5hbGwKICAgICAgICBuYW1lcyh4ID0gZGF0YS5yZXR1cm4pW2ldIDwtIGFzc2F5c1tbaV1dCiAgICB9CiAgICBpZiAocmV0dXJuLnNldXJhdCkgewogICAgICAgIHRvUmV0IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBkYXRhLnJldHVybltbMV1dLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJBdmVyYWdlIiwgYXNzYXkgPSBuYW1lcyh4ID0gZGF0YS5yZXR1cm4pWzFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKQogICAgICAgIGlmIChsZW5ndGgoeCA9IGRhdGEucmV0dXJuKSA+IDEpIHsKICAgICAgICAgICAgZm9yIChpIGluIDI6bGVuZ3RoKHggPSBkYXRhLnJldHVybikpIHsKICAgICAgICAgICAgICAgIHRvUmV0W1tuYW1lcyh4ID0gZGF0YS5yZXR1cm4pW2ldXV0gPC0gQ3JlYXRlQXNzYXlPYmplY3QoY291bnRzID0gZGF0YS5yZXR1cm5bW2ldXSkKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoRGVmYXVsdEFzc2F5KG9iamVjdCA9IG9iamVjdCkgJWluJSBuYW1lcyh4ID0gZGF0YS5yZXR1cm4pKSB7CiAgICAgICAgICAgIERlZmF1bHRBc3NheShvYmplY3QgPSB0b1JldCkgPC0gRGVmYXVsdEFzc2F5KG9iamVjdCA9IG9iamVjdCkKICAgICAgICB9CiAgICAgICAgSWRlbnRzKHRvUmV0LCBjZWxscyA9IGNvbG5hbWVzKHggPSB0b1JldCkpIDwtIGlkZW50Lm5ld1tjb2xuYW1lcyh4ID0gdG9SZXQpXQogICAgICAgIElkZW50cyhvYmplY3QgPSB0b1JldCkgPC0gZmFjdG9yKHggPSBJZGVudHMob2JqZWN0ID0gdG9SZXQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBhcy5jaGFyYWN0ZXIoeCA9IG9yaWcubGV2ZWxzKSwgb3JkZXJlZCA9IFRSVUUpCiAgICAgICAgdG9SZXQgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSB0b1JldCwgdmVyYm9zZSA9IHZlcmJvc2UpCiAgICAgICAgdG9SZXQgPC0gU2NhbGVEYXRhKG9iamVjdCA9IHRvUmV0LCB2ZXJib3NlID0gdmVyYm9zZSkKICAgICAgICByZXR1cm4odG9SZXQpCiAgICB9CiAgICBlbHNlIHsKICAgICAgICByZXR1cm4oZGF0YS5yZXR1cm4pCiAgICB9Cn0KYGBgCgoKCkZpbmQgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gbWFya2VycwoKYGBge3J9CmNvbWJpbmVkLm1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gY29tYmluZWQsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIHRocmVzaC51c2UgPSAwLjI1KQpjb21iaW5lZC5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24oMiwgYXZnX2xvZ0ZDKQoKS08ubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhvYmplY3QgPSBLTy5jZWxscywgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCgpyZXNwb25zZTMgPC0gRmluZE1hcmtlcnMoY29tYmluZWQsIGlkZW50LjEgPSBjKCIxX0cxNzFCIiwiMF9HMTcxQiIsIjJfRzE3MUIiKSwgaWRlbnQuMiA9IGMoIjFfRzE3MUMiLCAiMF9HMTcxQyIsIjJfRzE3MUMiKSwgdmVyYm9zZSA9IFRSVUUsIHRlc3QudXNlID0gIk1BU1QiLCBsb2dmYy50aHJlc2hvbGQgPSBGQUxTRSxtaW4ucGN0ID0gRkFMU0UpCmhlYWQocmVzcG9uc2UzLCBuID0gMTUpCgpgYGAKCgoKClZpc3VhbGl6ZSB0b3AgZ2VuZXMgaW4gcHJpbmNpcGFsIGNvbXBvbmVudHMKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQpQQ0hlYXRtYXAob2JqZWN0ID0gdGlzczEsIHBjLnVzZSA9IDE6MywgY2VsbHMudXNlID0gNTAwLCBkby5iYWxhbmNlZCA9IFRSVUUsIGxhYmVsLmNvbHVtbnMgPSBGQUxTRSwgbnVtLmdlbmVzID0gOCkKYGBgCgpMYXRlciBvbiAoaW4gRmluZENsdXN0ZXJzIGFuZCBUU05FKSB5b3Ugd2lsbCBwaWNrIGEgbnVtYmVyIG9mIHByaW5jaXBhbCBjb21wb25lbnRzIHRvIHVzZS4gVGhpcyBoYXMgdGhlIGVmZmVjdCBvZiBrZWVwaW5nIHRoZSBtYWpvciBkaXJlY3Rpb25zIG9mIHZhcmlhdGlvbiBpbiB0aGUgZGF0YSBhbmQsIGlkZWFsbHksIHN1cHJlc3Npbmcgbm9pc2UuIFRoZXJlIGlzIG5vIGNvcnJlY3QgYW5zd2VyIHRvIHRoZSBudW1iZXIgdG8gdXNlLCBidXQgYSBkZWNlbnQgcnVsZSBvZiB0aHVtYiBpcyB0byBnbyB1bnRpbCB0aGUgcGxvdCBwbGF0ZWF1cy4KCmBgYHtyfQpQQ0VsYm93UGxvdChvYmplY3QgPSB0aXNzMSkKYGBgCgpDaG9vc2UgdGhlIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuCmBgYHtyfQojIFNldCBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMuIApuLnBjcyA9IDEwCmBgYAoKVGhlIGNsdXN0ZXJpbmcgaXMgcGVyZm9ybWVkIGJhc2VkIG9uIGEgbmVhcmVzdCBuZWlnaGJvcnMgZ3JhcGguIENlbGxzIHRoYXQgaGF2ZSBzaW1pbGFyIGV4cHJlc3Npb24gd2lsbCBiZSBqb2luZWQgdG9nZXRoZXIuIFRoZSBMb3V2YWluIGFsZ29yaXRobSBsb29rcyBmb3IgZ3JvdXBzIG9mIGNlbGxzIHdpdGggaGlnaCBtb2R1bGFyaXR5LS1tb3JlIGNvbm5lY3Rpb25zIHdpdGhpbiB0aGUgZ3JvdXAgdGhhbiBiZXR3ZWVuIGdyb3Vwcy4gVGhlIHJlc29sdXRpb24gcGFyYW1ldGVyIGRldGVybWluZXMgdGhlIHNjYWxlLiBIaWdoZXIgcmVzb2x1dGlvbiB3aWxsIGdpdmUgbW9yZSBjbHVzdGVycywgbG93ZXIgcmVzb2x1dGlvbiB3aWxsIGdpdmUgZmV3ZXIuCgpGb3IgdGhlIHRvcC1sZXZlbCBjbHVzdGVyaW5nLCBhaW0gdG8gdW5kZXItY2x1c3RlciBpbnN0ZWFkIG9mIG92ZXItY2x1c3Rlci4gSXQgd2lsbCBiZSBlYXN5IHRvIHN1YnNldCBncm91cHMgYW5kIGZ1cnRoZXIgYW5hbHl6ZSB0aGVtIGJlbG93LgoKYGBge3J9CiMgU2V0IHJlc29sdXRpb24gCnJlcy51c2VkIDwtIDQKdGlzczEgPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IHRpc3MxLCByZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCBkaW1zLnVzZSA9IDE6bi5wY3MsIAogICAgcmVzb2x1dGlvbiA9IHJlcy51c2VkLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUsIGZvcmNlLnJlY2FsYyA9IFRSVUUpCmBgYAoKV2UgdXNlIFRTTkUgc29sZWx5IHRvIHZpc3VhbGl6ZSB0aGUgZGF0YS4KYGBge3J9CiMgSWYgY2VsbHMgYXJlIHRvbyBzcHJlYWQgb3V0LCB5b3UgY2FuIHJhaXNlIHRoZSBwZXJwbGV4aXR5LiBJZiB5b3UgaGF2ZSBmZXcgY2VsbHMsIHRyeSBhIGxvd2VyIHBlcnBsZXhpdHkgKGJ1dCBuZXZlciBsZXNzIHRoYW4gMTApLgp0aXNzMSA8LSBSdW5UU05FKG9iamVjdCA9IHRpc3MxLCBkaW1zLnVzZSA9IDE6bi5wY3MsIHNlZWQudXNlID0gMTAsIHBlcnBsZXhpdHk9MzApCmBgYAoKYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHRpc3MxLCBkby5sYWJlbCA9IFQsIHB0LnNpemUgPSAxLjIsIGxhYmVsLnNpemUgPSA0KQpgYGAKIyMgQ29tcGFyZSB0byBwcmV2aW91cyBhbm5vdGF0aW9ucwpgYGB7cn0KcHJldmlvdXNfYW5ub3RhdGlvbiA9IHJlYWQuY3N2KCIvVXNlcnMva2thcnJpL0RvY3VtZW50cy9MYWIvU2luZ2xlX2NlbGxfcHJvamVjdC9kcm9wc2VxL0xpdmVyX2Ryb3BsZXRfYW5ub3RhdGlvbi5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmNvbHMgPSBjKCdmcmVlX2Fubm90YXRpb24nLCAnY2VsbF9vbnRvbG9neV9jbGFzcycpCiAgICBmb3IgKGNvbCBpbiBjb2xzKXsKICAgICAgcHJldmlvdXNfY29sID0gcGFzdGUwKCdwcmV2aW91c18nLCBjb2wpCiAgICAgIHRpc3MxQG1ldGEuZGF0YVssIHByZXZpb3VzX2NvbF0gPC0gIk5BIgogICAgICB0aXNzMUBtZXRhLmRhdGFbYXMuY2hhcmFjdGVyKHByZXZpb3VzX2Fubm90YXRpb24kWCksIHByZXZpb3VzX2NvbF0gPC0gcHJldmlvdXNfYW5ub3RhdGlvblssIGNvbF0KICAgICAgcHJpbnQodGFibGUodGlzczFAbWV0YS5kYXRhWywgcHJldmlvdXNfY29sXSkpCiAgICAgIHByaW50KHRhYmxlKHRpc3MxQG1ldGEuZGF0YVssIHByZXZpb3VzX2NvbF0sIHRpc3NAaWRlbnQpKQogICAgICAKICAgIH0KICAgIAp0aXNzMSA9IGNvbXBhcmVfcHJldmlvdXNfYW5ub3RhdGlvbih0aXNzMSwgdGlzc3VlX29mX2ludGVyZXN0LCAiZHJvcGxldCIpClRTTkVQbG90KG9iamVjdCA9IHRpc3MxLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwcmV2aW91c19jZWxsX29udG9sb2d5X2NsYXNzIikKdGFibGUodGlzczFAbWV0YS5kYXRhWywgInByZXZpb3VzX2NlbGxfb250b2xvZ3lfY2xhc3MiXSwgdGlzc0BpZGVudCkKYGBgCgoKYGBge3J9CnRpc3MxID0gY29tcGFyZV9wcmV2aW91c19hbm5vdGF0aW9uKHRpc3MxLCB0aXNzdWVfb2ZfaW50ZXJlc3QsICJkcm9wbGV0IikKVFNORVBsb3Qob2JqZWN0ID0gdGlzczEsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gInByZXZpb3VzX2NlbGxfb250b2xvZ3lfY2xhc3MiKQp0YWJsZSh0aXNzMUBtZXRhLmRhdGFbLCAicHJldmlvdXNfY2VsbF9vbnRvbG9neV9jbGFzcyJdLCB0aXNzMUBpZGVudCkKYGBgCgoKYGBge3J9ClRTTkVQbG90KHRpc3MxLCBncm91cC5ieT0ibW91c2Uuc2V4IikKVFNORVBsb3QodGlzczEsIGdyb3VwLmJ5PSJtb3VzZS5pZCIpCmBgYAoKClNpZ25pZmljYW50IGdlbmVzOgoKaGVwYXRvY3l0ZTogQWxiLCBUdHIsIEFwb2ExLCBhbmQgU2VycGluYTFjCnBlcmljZW50cmFsOiBDeXAyZTEsIEdsdWwsIE9hdCwgR3VsbwptaWRsb2J1bGFyOiBBc3MxLCBIYW1wLCBHc3RwMSwgVWJiCnBlcmlwb3J0YWw6IEN5cDJmMiwgUGNrMSwgSGFsLCBDZGgxCgplbmRvdGhlbGlhbCBjZWxsczogUGVjYW0xLCBOcnAxLCBLZHIrIGFuZCBPaXQzKwpLdXBwZmVyIGNlbGxzOiBFbXIxLCBDbGVjNGYsIENkNjgsIElyZjcKTksvTktUIGNlbGxzOiBaYXA3MCwgSWwycmIsIE5rZzcsIEN4Y3I2LCBLbHIxYywgR3ptYQpCIGNlbGxzOiBDZDc5YSwgQ2Q3OWIsIENkNzQgYW5kIENkMTkKSW1tdW5lIGNlbGxzOiBQdHByYwoKCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MTYsIGZpZy53aWR0aD0xMn0KIyBIZXBhdGljIG1hcmtlcgpGZWF0dXJlUGxvdCh0aXNzMSwgYyhnZW5lc19oZXApLCBwdC5zaXplID0gMSwgbkNvbCA9IDQsIGNvbHMudXNlID0gYygiZ3JleSIsICJyZWQiKSkKCiMgRW5kb3RoZWxpYWwgbWFya2VycwpGZWF0dXJlUGxvdCh0aXNzMSwgYyhnZW5lc19lbmRvKSwgcHQuc2l6ZSA9IDEsIG5Db2wgPSA0LCBjb2xzLnVzZSA9IGMoImdyZXkiLCAicmVkIikpCgojIEt1cGZmZXIgY2VsbHMKRmVhdHVyZVBsb3QodGlzczEsIGMoZ2VuZXNfa3VwcGZlciksIHB0LnNpemUgPSAxLCBuQ29sID0gNCwgY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpKQoKIyBnZW5lc19uawpGZWF0dXJlUGxvdCh0aXNzMSwgYyhnZW5lc19uayksIHB0LnNpemUgPSAxLCBuQ29sID0gNCwgY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpKQoKIyBnZW5lc19iCkZlYXR1cmVQbG90KHRpc3MxLCBjKGdlbmVzX2IpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQsIGNvbHMudXNlID0gYygiZ3JleSIsICJyZWQiKSkKCiMgZ2VuZXMgYmlsZSBkdWN0IGVuZG8gY2VsbHMKRmVhdHVyZVBsb3QodGlzczEsIGMoZ2VuZXNfYmVjKSwgcHQuc2l6ZSA9IDEsIG5Db2wgPSA0LCBjb2xzLnVzZSA9IGMoImdyZXkiLCAicmVkIikpCgojIGdlbmVzIGltbXVuZQpGZWF0dXJlUGxvdCh0aXNzMSwgYyhnZW5lc19pbW11bmUpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQsIGNvbHMudXNlID0gYygiZ3JleSIsICJyZWQiKSkKCgpgYGAKCkRvdHBsb3RzIGxldCB5b3Ugc2VlIHRoZSBpbnRlbnNpdHkgb2YgZXhwcHJlc3Npb24gYW5kIHRoZSBmcmFjdGlvbiBvZiBjZWxscyBleHByZXNzaW5nIGZvciBlYWNoIG9mIHlvdXIgZ2VuZXMgb2YgaW50ZXJlc3QuClRoZSByYWRpdXMgc2hvd3MgeW91IHRoZSBwZXJjZW50IG9mIGNlbGxzIGluIHRoYXQgY2x1c3RlciB3aXRoIGF0IGxlYXN0IG9uZSByZWFkIHNlcXVlbmNlZCBmcm9tIHRoYXQgZ2VuZS4gVGhlIGNvbG9yIGxldmVsIGluZGljYXRlcyB0aGUgYXZlcmFnZQpaLXNjb3JlIG9mIGdlbmUgZXhwcmVzc2lvbiBmb3IgY2VsbHMgaW4gdGhhdCBjbHVzdGVyLCB3aGVyZSB0aGUgc2NhbGluZyBpcyBkb25lIG92ZXIgdGFrZW4gb3ZlciBhbGwgY2VsbHMgaW4gdGhlIHNhbXBsZS4KCiNXZSBoYXZlIHZhcmlvdXMgaW1tdW5lIGNlbGwgdHlwZXMgaW4gdGhlIGxhc3QgY2x1c3RlcgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTB9CkRvdFBsb3QodGlzczEsIGMoZ2VuZXNfa3VwcGZlciwgZ2VuZXNfbmssIGdlbmVzX2IsICJQdHByYyIpLCBwbG90LmxlZ2VuZCA9IFQsIGNvbC5tYXggPSAyLjUsIGRvLnJldHVybiA9IFQpICsgY29vcmRfZmxpcCgpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQpEb3RQbG90KHRpc3MxLCBjKGdlbmVzX2hlcF9tYWluLCBnZW5lc19lbmRvLCBnZW5lc19uaywgZ2VuZXNfa3VwcGZlciwgZ2VuZXNfYmVjX2JfaW1tdW5lKSwgcGxvdC5sZWdlbmQgPSBULCBjb2wubWF4ID0gMi41LCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQpgYGAKClVzaW5nIHRoZSBtYXJrZXJzIGFib3ZlLCB3ZSBjYW4gY29uZmlkZW50YWx5IGxhYmVsIG1hbnkgb2YgdGhlIGNsdXN0ZXJzOgoKMTk6IGVuZG90aGVsaWFsIGNlbGxzCjIwOiBiaWxlIGR1Y3QgZXBpdGhlbGlhbCBjZWxscwoyMTogaW1tdW5lIGNlbGxzCnJlc3QgYXJlIGhlcGF0b2N5dGVzCgpXZSB3aWxsIGFkZCB0aG9zZSBjZWxsX29udG9sb2d5X2NsYXNzZXMgdG8gdGhlIGRhdGFzZXQuCgpgYGB7cn0KdGlzczEgPC0gU3Rhc2hJZGVudChvYmplY3QgPSB0aXNzMSwgc2F2ZS5uYW1lID0gImNsdXN0ZXIuaWRzIikKY2x1c3Rlci5pZHMgPC0gYygwLDEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwKQpmcmVlX2Fubm90YXRpb24gPC0gYygKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICBOQSwKICAiYmlsZSBkdWN0IGVwaXRoZWxpYWwgY2VsbHMiLAogICJlbmRvdGhlbGlhbCBjZWxsIG9mIGhlcGF0aWMgc2ludXNvaWQiLAogIE5BCiAgKQpjZWxsX29udG9sb2d5X2NsYXNzIDwtIGMoCiAgImhlcGF0b2N5dGUiLAogICJoZXBhdG9jeXRlIiwKICAiaGVwYXRvY3l0ZSIsCiAgImhlcGF0b2N5dGUiLAogICJoZXBhdG9jeXRlIiwKICAiaGVwYXRvY3l0ZSIsCiAgImhlcGF0b2N5dGUiLAogICJoZXBhdG9jeXRlIiwKICAiaGVwYXRvY3l0ZSIsCiAgImhlcGF0b2N5dGUiLAogICJoZXBhdG9jeXRlIiwKICAiaGVwYXRvY3l0ZSIsCiAgImhlcGF0b2N5dGUiLAogICJoZXBhdG9jeXRlIiwKICAiaGVwYXRvY3l0ZSIsCiAgImhlcGF0b2N5dGUiLAogICJoZXBhdG9jeXRlIiwKICAiaGVwYXRvY3l0ZSIsCiAgImR1Y3QgZXBpdGhlbGlhbCBjZWxsIiwKICAiZW5kb3RoZWxpYWwgY2VsbCBvZiBoZXBhdGljIHNpbnVzb2lkIiwKICAiaGVwYXRvY3l0ZSIpCnRpc3MxID0gc3Rhc2hfYW5ub3RhdGlvbnModGlzczEsIGNsdXN0ZXIuaWRzLCBmcmVlX2Fubm90YXRpb24sIGNlbGxfb250b2xvZ3lfY2xhc3MpCmBgYAoKIyMgQ2hlY2tpbmcgZm9yIGJhdGNoIGVmZmVjdHMKCkNvbG9yIGJ5IG1ldGFkYXRhLCBsaWtlIHBsYXRlIGJhcmNvZGUsIHRvIGNoZWNrIGZvciBiYXRjaCBlZmZlY3RzLgpgYGB7cn0KVFNORVBsb3Qob2JqZWN0ID0gdGlzczEsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gImNoYW5uZWwiKQpUU05FUGxvdChvYmplY3QgPSB0aXNzMSwgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiZnJlZV9hbm5vdGF0aW9uIikKCmBgYAoKIyMgU3ViY2x1c3RlcgoKTGV0J3MgZHJpbGwgZG93biBvbiB0aGUgaGVwYXRvY3l0ZXMuCgpgYGB7cn0Kc3VidGlzczEgPSBTdWJzZXREYXRhKHRpc3MxLCBpZGVudC51c2UgPSBjKDAsMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMjApKQoKCmBgYAoKYGBge3J9CnN1YnRpc3MxIDwtIHN1YnRpc3MxICU+JSBTY2FsZURhdGEoKSAlPiUKICBGaW5kVmFyaWFibGVHZW5lcyhkby5wbG90ID0gRkFMU0UsIHguaGlnaC5jdXRvZmYgPSBJbmYsIHkuY3V0b2ZmID0gMC41KSAlPiUKICBSdW5QQ0EoZG8ucHJpbnQgPSBGQUxTRSkKYGBgCgpgYGB7cn0KUENIZWF0bWFwKG9iamVjdCA9IHN1YnRpc3MxLCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDIwLCBkby5iYWxhbmNlZCA9IFRSVUUsIGxhYmVsLmNvbHVtbnMgPSBGQUxTRSwgbnVtLmdlbmVzID0gOCkKUENFbGJvd1Bsb3Qoc3VidGlzczEpCmBgYAoKCmBgYHtyfQpzdWIubi5wY3MgPSA4CnN1Yi5yZXMudXNlID0gMC41CnN1YnRpc3MxIDwtIHN1YnRpc3MxICU+JSBGaW5kQ2x1c3RlcnMocmVkdWN0aW9uLnR5cGUgPSAicGNhIiwgZGltcy51c2UgPSAxOnN1Yi5uLnBjcywKICAgIHJlc29sdXRpb24gPSBzdWIucmVzLnVzZSwgcHJpbnQub3V0cHV0ID0gMCwgc2F2ZS5TTk4gPSBUUlVFLCBmb3JjZS5yZWNhbGMgPSBUUlVFKSAlPiUKICAgIFJ1blRTTkUoZGltcy51c2UgPSAxOnN1Yi5uLnBjcywgc2VlZC51c2UgPSAxMCwgcGVycGxleGl0eT04KQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzMSwgZG8ubGFiZWwgPSBULCBwdC5zaXplID0gMSwgbGFiZWwuc2l6ZSA9IDQpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MjUsIGZpZy53aWR0aD0yNX0KRmVhdHVyZVBsb3Qoc3VidGlzczEsIGdlbmVzX2hlcCxjb2xzLnVzZSA9IGMoImdyZXkiLCAicmVkIiksIHB0LnNpemUgPSA0LCBuQ29sID0gNCkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CkRvdFBsb3Qoc3VidGlzczEsIGFsbF9nZW5lcywgY29sLm1heCA9IDIuNSwgcGxvdC5sZWdlbmQgPSBULCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQpgYGAKCmBgYHtyfQpCdWlsZENsdXN0ZXJUcmVlKHN1YnRpc3MxKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OH0KI2ZlbWFsZSBnZW5lcyBoYXZlIGxvd2VyIGV4cHJlc3Npb24gaW4gY2x1c3RlciA2IHJlbGF0aXZlIHRvIG90aGVyIGZlbWFsZSBjbHVzdGVycywgZXNwZWNhbGx5IFhpc3QKRmVhdHVyZVBsb3Qoc3VidGlzczEsYygnTXVwMjAnLCAnTXVwMScsJ011cDEyJywgJ011cDIxJywgJ0N5cDJkOScsICdYaXN0JywgJ0ExYmcnLCAnQ3lwMmM2OScpLGNvbHMudXNlID0gYygiZ3JleSIsICJyZWQiKSwgcHQuc2l6ZSA9IDMsIG5Db2wgPSAyKQoKRG90UGxvdCh0aXNzMSxjKCdNdXAyMCcsICdNdXAxJywnTXVwMTInLCAnTXVwMjEnLCAnQ3lwMmQ5JywgJ1hpc3QnLCAnQTFiZycsICdDeXAyYzY5JyksIHBsb3QubGVnZW5kID0gVCwgY29sLm1heCA9IDIuNSwgZG8ucmV0dXJuID0gVCkgKyBjb29yZF9mbGlwKCkKCmBgYAoKCkZyb20gdGhlc2UgZ2VuZXMsIGl0IGFwcGVhcnMgdGhhdCB0aGUgY2x1c3RlcnMgcmVwcmVzZW50OgoKMDogbWlkbG9idWxhciBtYWxlCjE6IHBlcmljZW50cmFsIGZlbWFsZQoyOiBwZXJpcG9ydGFsIGZlbWFsZQozOiBwZXJpcG9ydGFsIG1hbGUKNDogbWlkbG9idWxhciBtYWxlCjU6IHBlcmljZW50cmFsIG1hbGUKNjogbWlkbG9idWxhciBmZW1hbGUKNzogbWlkbG9idWxhciBmZW1hbGUKClRoZSBtdWx0aXR1ZGUgb2YgY2x1c3RlcnMgb2YgZWFjaCB0eXBlIGNvcnJlc3BvbmQgbW9zdGx5IHRvIGluZGl2aWR1YWwgYW5pbWFscy9zZXhlcy4KCmBgYHtyfQp0YWJsZShGZXRjaERhdGEoc3VidGlzczEsIGMoJ21vdXNlLnNleCcsJ2lkZW50JykpICU+JSBkcm9wbGV2ZWxzKCkpCmBgYAoKYGBge3J9CnN1Yi5jbHVzdGVyLmlkcyA8LSBjKDAsIDEsIDIsIDMsIDQsIDUsIDYsIDcpCnN1Yi5mcmVlX2Fubm90YXRpb24gPC0gYygicGVyaXBvcnRhbCBmZW1hbGUiLCAibWlkbG9idWxhciBtYWxlIiwgInBlcmljZW50cmFsIGZlbWFsZSIsICJwZXJpcG9ydGFsIG1hbGUiLCAibWlkbG9idWxhciBtYWxlIiwgInBlcmljZW50cmFsIG1hbGUiLCAibWlkbG9idWxhciBmZW1hbGUiLCAibWlkbG9idWxhciBmZW1hbGUiKQpzdWIuY2VsbF9vbnRvbG9neV9jbGFzcyA8LSBjKCJoZXBhdG9jeXRlIiwgImhlcGF0b2N5dGUiLCAiaGVwYXRvY3l0ZSIsICJoZXBhdG9jeXRlIiwgImhlcGF0b2N5dGUiLCAiaGVwYXRvY3l0ZSIsICJoZXBhdG9jeXRlIiwgImhlcGF0b2N5dGUiKQpzdWJ0aXNzMSA9IHN0YXNoX2Fubm90YXRpb25zKHN1YnRpc3MxLCBzdWIuY2x1c3Rlci5pZHMsIHN1Yi5mcmVlX2Fubm90YXRpb24sIHN1Yi5jZWxsX29udG9sb2d5X2NsYXNzKQp0aXNzMSA9IHN0YXNoX3N1YnRpc3NfaW5fdGlzcyh0aXNzMSwgc3VidGlzczEpCmBgYAoKTGl2ZXIgem9uYXRpb24gbWFya2VycwoKYGBge3J9CmdlbmVzX3pvbmVzID0gYygnQ3lwMmUxJywgJ0dsdWwnLCAnT2F0JywgJ0d1bG8nLAogICAgICAgICAgICAgICdBc3MxJywgJ0hhbXAnLCAnR3N0cDEnLCAnVWJiJywKICAgICAgICAgICAgICAnQ3lwMmYyJywgJ1BjazEnLCAnSGFsJywgJ0NkaDEnKQoKRmVhdHVyZVBsb3Qoc3VidGlzczEsYyhnZW5lc196b25lcyksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQpCgpEb3RQbG90KHN1YnRpc3MxLGMoZ2VuZXNfem9uZXMpLCBwbG90LmxlZ2VuZCA9IFQsIGNvbC5tYXggPSAyLjUsIGRvLnJldHVybiA9IFQpICsgY29vcmRfZmxpcCgpCgoKVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzczEsIGRvLmxhYmVsID0gVCwgcHQuc2l6ZSA9IDEsIGxhYmVsLnNpemUgPSA0LCBncm91cC5ieT0iZnJlZV9hbm5vdGF0aW9uIikKClRTTkVQbG90KG9iamVjdCA9IHRpc3MxLCBkby5sYWJlbCA9IFQsIHB0LnNpemUgPSAxLCBsYWJlbC5zaXplID0gNCwgZ3JvdXAuYnk9ImZyZWVfYW5ub3RhdGlvbiIpCgpgYGAKCgoKIyMjIyMjIyMjIwpGaW5kIGNsdXN0ZXIgbWFya2VycyBmb3IgbG5jUk5BcwpgYGB7cn0KCk1JTl9MT0dGT0xEX0NIQU5HRSA9IDEgIyBzZXQgdG8gbWluaW11bSByZXF1aXJlZCBhdmVyYWdlIGxvZyBmb2xkIGNoYW5nZSBpbiBnZW5lIGV4cHJlc3Npb24uCk1JTl9QQ1RfQ0VMTFNfRVhQUl9HRU5FID0gMC4xCgphbGwubWFya2VycyA9IEZpbmRBbGxNYXJrZXJzKHRpc3MxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5wY3QgPSBNSU5fUENUX0NFTExTX0VYUFJfR0VORSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dmYy50aHJlc2hvbGQgPSBNSU5fTE9HRk9MRF9DSEFOR0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25seS5wb3MgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QudXNlPSJiaW1vZCIpICMgbGlrZWxpaG9vZCByYXRpbyB0ZXN0CmxuY19hbGxfbWFya2VycyA8LSBncmVwKHBhdHRlcm4gPSAiXm5jUk5BIiwgeD0gcm93bmFtZXMoYWxsLm1hcmtlcnMpLCB2YWx1ZSA9IFRSVUUpCmxuY19hbGxfbWFya2VycwoKI1sxXSAibmNSTkFfaW50ZXJfY2hyMTBfOTIwODEiICJuY1JOQV9pbnRyYV9jaHIxNl8xMzM4MyIgIm5jUk5BX2ludGVyX2NocjE3XzEzNjA1IiAibmNSTkFfaW50ZXJfY2hyMTRfMTE4MTUiCiNbNV0gIm5jUk5BX2ludGVyX2NocjE4XzE0MzQ0IgoKRmVhdHVyZVBsb3Qoc3VidGlzczEsYyhsbmNfYWxsX21hcmtlcnMpLGNvbHMudXNlID0gYygiZ3JleSIsICJyZWQiKSwgcHQuc2l6ZSA9IDEsIG5Db2wgPSA0KQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBsbmNSTkEgbWFya2Vycy0gQ0VMTCBUWVBFIE1BUktFUiAjIyMjIyMjIyMjIyMKbWFya2Vycy5oZXAgPC0gRmluZE1hcmtlcnMob2JqZWN0ID0gdGlzczEsIGlkZW50LjEgPSBjKDAsMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMjApLCBpZGVudC4yID0gYygxOCwxOSksb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCmxuY19tYXJrZXJzX2hlcCA8LSBncmVwKHBhdHRlcm4gPSAiXm5jUk5BIiwgeD0gcm93bmFtZXMobWFya2Vycy5oZXApLCB2YWx1ZSA9IFRSVUUpCmxuY19tYXJrZXJzX2hlcApGZWF0dXJlUGxvdCh0aXNzMSxjKGxuY19tYXJrZXJzX2hlcCksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQpCkRvdFBsb3QodGlzczEsbG5jX21hcmtlcnNfaGVwLCBwbG90LmxlZ2VuZCA9IFQsIGNvbC5tYXggPSAyLjUsIGRvLnJldHVybiA9IFQpICsgY29vcmRfZmxpcCgpCiNbMV0gIm5jUk5BX2FzX2NocjExXzk0MjMiICAgICAibmNSTkFfYXNfY2hyN182MTY2IiAgICAgICJuY1JOQV9pbnRlcl9jaHI0XzMyOTUiICAgIm5jUk5BX2ludGVyX2NocjE3XzE0MDI2IgojWzVdICJuY1JOQV9pbnRlcl9jaHIzXzI5MTUiICAgIm5jUk5BX2ludGVyX2NocjVfNDU0NyIgICAibmNSTkFfaW50ZXJfY2hyMTVfMTI2ODQiCgoKbWFya2Vycy5oZXAuTUFTVCA8LSBGaW5kTWFya2VycyhvYmplY3QgPSB0aXNzMSwgaWRlbnQuMSA9IGMoMCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywyMCksIGlkZW50LjIgPSBjKDE4LDE5KSxvbmx5LnBvcyA9IFRSVUUsIHRlc3QudXNlID0gIk1BU1QiKQpsbmNfbWFya2Vyc19oZXBfTUFTVF9UQUJMRSA8LSBzdWJzZXQobWFya2Vycy5oZXAuTUFTVCwgZ3JlcGwoIl5uY1JOQSIsIHJvd25hbWVzKG1hcmtlcnMuaGVwLk1BU1QpKSkKbG5jX21hcmtlcnNfaGVwX01BU1QgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMuaGVwLk1BU1QpLCB2YWx1ZSA9IFRSVUUpCmxuY19tYXJrZXJzX2hlcF9NQVNUCgoKCm1hcmtlcnMuZW5kbyA8LSBGaW5kTWFya2VycyhvYmplY3QgPSB0aXNzMSwgaWRlbnQuMSA9IGMoMTgsMTkpLCAgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuNSkKbG5jX21hcmtlcnNfZW5kbyA8LSBncmVwKHBhdHRlcm4gPSAiXm5jUk5BIiwgeD0gcm93bmFtZXMobWFya2Vycy5lbmRvKSwgdmFsdWUgPSBUUlVFKQpsbmNfbWFya2Vyc19lbmRvCkZlYXR1cmVQbG90KHRpc3MxLGMobG5jX21hcmtlcnNfZW5kbyksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQpCkRvdFBsb3QodGlzczEsbG5jX21hcmtlcnNfZW5kbywgcGxvdC5sZWdlbmQgPSBULCBjb2wubWF4ID0gMi41LCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQoKCiMibmNSTkFfaW50ZXJfY2hyMTVfMTI3NzAiLCAibmNSTkFfaW50ZXJfY2hyMTJfMTA4MTciLCAibmNSTkFfYXNfY2hyMTNfMTE0NTEiLAoKCm1hcmtlcnMuZW5kby5NQVNUIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHRpc3MxLCBpZGVudC4xID0gMTksIHRlc3QudXNlID0gIk1BU1QiICxvbmx5LnBvcyA9IFRSVUUpCmxuY19tYXJrZXJzX2VuZG9fTUFTVF9UQUJMRSA8LSBzdWJzZXQobWFya2Vycy5lbmRvLk1BU1QsIGdyZXBsKCJebmNSTkEiLCByb3duYW1lcyhtYXJrZXJzLmVuZG8uTUFTVCkpKQpsbmNfbWFya2Vyc19lbmRvX01BU1QgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMuZW5kby5NQVNUKSwgdmFsdWUgPSBUUlVFKQpsbmNfbWFya2Vyc19lbmRvX01BU1QKCgojIyMjIyMjIyMjIyMjIyMjIyMgbG5jUk5BIGV4cHJlc3Npb24gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjMwoKIyAibmNSTkFfaW50ZXJfY2hyMTdfMTM2MDUiICwgIm5jUk5BX2ludHJhX2NocjE2XzEzMzgzIgoKIyMjIyMjIyMjIyBQZXJpcG9yYWwgbWFya2Vycy0gem9uYXRpb24gbWFya2VycyAjIyMjIyMjIyMjIyMKbWFya2Vycy5wYyA8LSBGaW5kTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzMSwgaWRlbnQuMSA9IGMoMiw1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gRkFMU0UsIG1pbi5wY3QgPSAwLjAwMSwgdGhyZXNoLnVzZSA9IDAuMDAxLCB0ZXN0LnVzZSA9ICJiaW1vZCIgKQoKbWFya2Vycy5wYy5NQVNUIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHN1YnRpc3MxLCBpZGVudC4xID0gYygyLDUpLCBpZGVudC4yID0gYygwLDMpLCB0ZXN0LnVzZSA9ICJNQVNUIiAsb25seS5wb3MgPSBUUlVFKQpsbmNfbWFya2Vyc19wYyA8LSBzdWJzZXQobWFya2Vycy5wYywgZ3JlcGwoIl5uY1JOQSIsIHJvd25hbWVzKG1hcmtlcnMucGMpKSkKbG5jX21hcmtlcnNfcGMgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMucGMpLCB2YWx1ZSA9IFRSVUUpCmxuY19tYXJrZXJzX3BjIAoKbWFya2Vycy5wYy5NQVNUIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHN1YnRpc3MxLCBpZGVudC4xID0gYygyLDUpLCBpZGVudC4yID0gYygwLDMpLCB0ZXN0LnVzZSA9ICJNQVNUIiAsb25seS5wb3MgPSBUUlVFKQpsbmNfbWFya2Vyc19wY19NQVNUIDwtIHN1YnNldChtYXJrZXJzLnBjLk1BU1QsIGdyZXBsKCJebmNSTkEiLCByb3duYW1lcyhtYXJrZXJzLnBjLk1BU1QpKSkKbG5jX21hcmtlcnNfcGNfTUFTVCA8LSBncmVwKHBhdHRlcm4gPSAiXm5jUk5BIiwgeD0gcm93bmFtZXMobWFya2Vycy5wYy5NQVNUKSwgdmFsdWUgPSBUUlVFKQpsbmNfbWFya2Vyc19wY19NQVNUCgpEb3RQbG90KHRpc3MxLCBsbmNfbWFya2Vyc19wYywgcGxvdC5sZWdlbmQgPSBULCBjb2wubWF4ID0gMi41LCBkby5yZXR1cm4gPSBULCBncm91cC5ieT0iZnJlZV9hbm5vdGF0aW9uIikgKyBjb29yZF9mbGlwKCkKRmVhdHVyZVBsb3Qoc3VidGlzczEsYyhsbmNfbWFya2Vyc19wYyksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQpCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBtaWRsb2J1bGFyIGdlbmVzICMjIyMjIyMjIyMjIyMKCm1hcmtlcnMubWlkIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHN1YnRpc3MxLCBpZGVudC4xID0gYygxLDQsNiw3KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gRkFMU0UsIG1pbi5wY3QgPSAwLjAwMSwgdGhyZXNoLnVzZSA9IDAuMDUpCgpsbmNfbWFya2Vyc19taWQgPC0gc3Vic2V0KG1hcmtlcnMubWlkLCBncmVwbCgiXm5jUk5BIiwgcm93bmFtZXMobWFya2Vycy5taWQpKSkKbG5jX21hcmtlcnNfbWlkIDwtIGdyZXAocGF0dGVybiA9ICJebmNSTkEiLCB4PSByb3duYW1lcyhtYXJrZXJzLm1pZCksIHZhbHVlID0gVFJVRSkKbG5jX21hcmtlcnNfbWlkCkRvdFBsb3QodGlzczEsIGxuY19tYXJrZXJzX21pZCwgcGxvdC5sZWdlbmQgPSBULCBjb2wubWF4ID0gMi41LCBkby5yZXR1cm4gPSBULCBncm91cC5ieT0iZnJlZV9hbm5vdGF0aW9uIikgKyBjb29yZF9mbGlwKCkKCgpGZWF0dXJlUGxvdChzdWJ0aXNzMSxjKGxuY19tYXJrZXJzX21pZCksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQpCgoKCm1hcmtlcnMubWlkLk1BU1QgPC0gRmluZE1hcmtlcnMob2JqZWN0ID0gc3VidGlzczEsIGlkZW50LjEgPSBjKDEsNCw2LDcpLHRlc3QudXNlID0gIk1BU1QiLG9ubHkucG9zID0gVFJVRSApCgpsbmNfbWFya2Vyc19taWRfTUFTVF9UQUJMRSA8LSBzdWJzZXQobWFya2Vycy5taWQuTUFTVCwgZ3JlcGwoIl5uY1JOQSIsIHJvd25hbWVzKG1hcmtlcnMubWlkLk1BU1QpKSkKbG5jX21hcmtlcnNfbWlkX01BU1QgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMubWlkLk1BU1QpLCB2YWx1ZSA9IFRSVUUpCmxuY19tYXJrZXJzX21pZF9NQVNUCgoKIyMjIyMzIHBlcmlwb3J0YWxtYXJrZXIgZ2VuZXMjIyMjIyMjIyMjIyMzCgptYXJrZXJzLnBwIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHN1YnRpc3MxLCBpZGVudC4xID0gYygwLDMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmx5LnBvcyA9IEZBTFNFLCBtaW4ucGN0ID0gMC4wMDEsIHRocmVzaC51c2UgPSAwLjA1KQoKCmxuY19tYXJrZXJzX3BwIDwtIHN1YnNldChtYXJrZXJzLnBwLCBncmVwbCgiXm5jUk5BIiwgcm93bmFtZXMobWFya2Vycy5wcCkpKQpsbmNfbWFya2Vyc19wcCA8LSBncmVwKHBhdHRlcm4gPSAiXm5jUk5BIiwgeD0gcm93bmFtZXMobWFya2Vycy5wcCksIHZhbHVlID0gVFJVRSkKbG5jX21hcmtlcnNfcHAKCm1hcmtlcnMucHAuTUFTVCA8LSBGaW5kTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzMSwgaWRlbnQuMSA9IGMoMCwzKSwgaWRlbnQuMiA9IGMoMiw1KSx0ZXN0LnVzZSA9ICJNQVNUIixvbmx5LnBvcyA9IFRSVUUgKQoKbG5jX21hcmtlcnNfcHBfTUFTVF9UQUJMRSA8LSBzdWJzZXQobWFya2Vycy5wcC5NQVNULCBncmVwbCgiXm5jUk5BIiwgcm93bmFtZXMobWFya2Vycy5wcC5NQVNUKSkpCmxuY19tYXJrZXJzX3BwX01BU1QgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMucHAuTUFTVCksIHZhbHVlID0gVFJVRSkKbG5jX21hcmtlcnNfcHBfTUFTVAoKRmVhdHVyZVBsb3Qoc3VidGlzczEsYyhsbmNfbWFya2Vyc19wcCksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQsIG1heC5jdXRvZmYgPSAxKQpEb3RQbG90KHRpc3MxLCBjKGxuY19tYXJrZXJzX3BwLCJDeXAyZTEiLCJDeXAyZjIiKSwgcGxvdC5sZWdlbmQgPSBULCBjb2wubWF4ID0gMi41LCBkby5yZXR1cm4gPSBULCBncm91cC5ieT0gImZyZWVfYW5ub3RhdGlvbiIpICsgY29vcmRfZmxpcCgpCgoKIyMjIyMjIyMjIyMjIyMjIyMjIGFtbGUgYW5kIGZlbWFsZSBzcGVjaWZpYyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgptYXJrZXJzLmZlbWFsZSA8LSBGaW5kTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzMSwgaWRlbnQuMSA9IGMoMCwyLDYsNyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMSwgbG9nZmMudGhyZXNob2xkID0gMSkKCmxuY19tYXJrZXJzX2ZlbWFsZSA8LSBzdWJzZXQobWFya2Vycy5mZW1hbGUsIGdyZXBsKCJebmNSTkEiLCByb3duYW1lcyhtYXJrZXJzLmZlbWFsZSkpKQpsbmNfbWFya2Vyc19mZW1hbGUgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMuZmVtYWxlKSwgdmFsdWUgPSBUUlVFKQpsbmNfbWFya2Vyc19mZW1hbGUKCkZlYXR1cmVQbG90KHN1YnRpc3MxLGMobG5jX21hcmtlcnNfZmVtYWxlKSxjb2xzLnVzZSA9IGMoImdyZXkiLCAicmVkIiksIHB0LnNpemUgPSAxLCBuQ29sID0gNCwgbWF4LmN1dG9mZiA9IDEpCkRvdFBsb3QodGlzczEsIGMobG5jX21hcmtlcnNfZmVtYWxlLCJDeXAyZTEiLCJDeXAyZjIiKSwgcGxvdC5sZWdlbmQgPSBULCBjb2wubWF4ID0gMi41LCBkby5yZXR1cm4gPSBULCBncm91cC5ieT0gImZyZWVfYW5ub3RhdGlvbiIpICsgY29vcmRfZmxpcCgpCgoKCm1hcmtlcnMubWFsZSA8LSBGaW5kTWFya2VycyhvYmplY3QgPSBzdWJ0aXNzMSwgaWRlbnQuMSA9IGMoMSwzLDQsNSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMDAxLCB0aHJlc2gudXNlID0gMC4wNSkKCmxuY19tYXJrZXJzX21hbGUgPC0gc3Vic2V0KG1hcmtlcnMubWFsZSwgZ3JlcGwoIl5uY1JOQSIsIHJvd25hbWVzKG1hcmtlcnMubWFsZSkpKQpsbmNfbWFya2Vyc19tYWxlIDwtIGdyZXAocGF0dGVybiA9ICJebmNSTkEiLCB4PSByb3duYW1lcyhtYXJrZXJzLm1hbGUpLCB2YWx1ZSA9IFRSVUUpCmxuY19tYXJrZXJzX21hbGUKCkZlYXR1cmVQbG90KHN1YnRpc3MxLGMobG5jX21hcmtlcnNfbWFsZSksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQsIG1heC5jdXRvZmYgPSAxKQpEb3RQbG90KHRpc3MxLCBjKGxuY19tYXJrZXJzX21hbGUsIkN5cDJlMSIsIkN5cDJmMiIpLCBwbG90LmxlZ2VuZCA9IFQsIGNvbC5tYXggPSAyLjUsIGRvLnJldHVybiA9IFQsIGdyb3VwLmJ5PSAiZnJlZV9hbm5vdGF0aW9uIikgKyBjb29yZF9mbGlwKCkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZlbWFsZSB6b25hdGUgc3BlY2lmaWMgZ2VuZXMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCm1hcmtlcnMucGVyaWNlbnRyYWwuZmVtYWxlIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IHRpc3MxLCBpZGVudC4xID0gYyg2LDExLDE0LDIwKSwgdGVzdC51c2UgPSAiTUFTVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjEsIGlkZW50LjIgPSBjKDIsMywxNSwxMiwxMyw4LDUsMTYpLCBsb2dmYy50aHJlc2hvbGQgPSAxKQoKbWFya2Vycy5wZXJpcG9ydGFsLmZlbWFsZSA8LSBGaW5kTWFya2VycyhvYmplY3QgPSB0aXNzMSwgaWRlbnQuMSA9IGMoMiwzLDE1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMSwgaWRlbnQuMiA9IGMoNiwxMSwxNCwyMCwxMiwxMyw4LDUsMTYpLCBsb2dmYy50aHJlc2hvbGQgPSAxKQoKCm1hcmtlcnMucGVyaWNlbnRyYWwubWFsZSA8LSBGaW5kTWFya2VycyhvYmplY3QgPSB0aXNzMSwgaWRlbnQuMSA9IGMoMTMsMTIpLCB0ZXN0LnVzZSA9ICJNQVNUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMSwgaWRlbnQuMiA9IGMoMiwzLDE1LDgsNSwxNiw2LDExLDE0LDIwKSwgbG9nZmMudGhyZXNob2xkID0gMSkKCgptYXJrZXJzLnBlcmlwb3J0YWwubWFsZSA8LSBGaW5kTWFya2VycyhvYmplY3QgPSB0aXNzMSwgaWRlbnQuMSA9IGMoOCw1LDE2KSwgdGVzdC51c2UgPSAiTUFTVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjEsIGlkZW50LjIgPSBjKDIsMywxNSwxMywxMiw2LDExLDE0LDIwKSwgbG9nZmMudGhyZXNob2xkID0gMSkKCgoKCiMjIyMjIyMjIyMjIyMjIyB4ZW5vLWxuY3MgQ0FSP1JYUiAjIyMjIyMjIyMjIyMjIyMjIyMKCkZlYXR1cmVQbG90KHRpc3MxLGMoIm5jUk5BX2ludGVyX2NocjE1XzEyNjg0IiwibmNSTkFfaW50ZXJfY2hyOF83NDMwIiwibmNSTkFfaW50ZXJfY2hyN182MjIyIiksY29scy51c2UgPSBjKCJncmV5IiwgInJlZCIpLCBwdC5zaXplID0gMSwgbkNvbCA9IDQsIG1heC5jdXRvZmYgPSAxKQoKCgoKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKbWFya2Vycy5lbmRvLjIgPC0gRmluZE1hcmtlcnMob2JqZWN0ID0gc2V1cmF0X2Ryb3AsIGxvZ2ZjLnRocmVzaG9sZCA9IDIsaWRlbnQuMSA9ICJFbmRvdGhlbGlhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCB0aHJlc2gudXNlID0gMC4yNSkKCmxuYy5lbmRvLjIgPC0gZ3JlcChwYXR0ZXJuID0gIl5uY1JOQSIsIHg9IHJvd25hbWVzKG1hcmtlcnMuZW5kby4yKSwgdmFsdWUgPSBUUlVFKQpsbmMuZW5kby4yCgoKCgoKYGBgCgoKClpvbmF0ZWQgbG5jUk5BcyAKCmBgYHtyfQpwcF96b250YWVkIDwtIGMoJ25jUk5BX2ludGVyX2NocjE0XzEyMDE2JywnbmNSTkFfYXNfY2hyMTlfMTUwOTAnLCduY1JOQV9pbnRlcl9jaHIxMF85MzUxJywnbmNSTkFfaW50ZXJfY2hyMTZfMTMxNzAnLAonbmNSTkFfaW50ZXJfY2hyM18yNjk3JywnbmNSTkFfaW50ZXJfY2hyMV8yNzQnLCduY1JOQV9hc19jaHI2XzU1MTgnLCduY1JOQV9pbnRlcl9jaHIxNF8xMjA2NicsJ25jUk5BX2ludHJhX2NocjEyXzEwODcxJywKJ25jUk5BX2ludGVyX2NocjE2XzEzNTEwJywnbmNSTkFfaW50ZXJfY2hyM18yMzE0JywnbmNSTkFfaW50ZXJfY2hyMTBfOTI2NCwnbmNSTkFfaW50ZXJfY2hyOV84MTIyJykKCgoKCgpgYGAKCiMjIENoZWNraW5nIGZvciBiYXRjaCBlZmZlY3RzCgpDb2xvciBieSBtZXRhZGF0YSwgbGlrZSBwbGF0ZSBiYXJjb2RlLCB0byBjaGVjayBmb3IgYmF0Y2ggZWZmZWN0cy4KYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3MxLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJtb3VzZS5zZXgiKQoKYGBgCgojIEZpbmFsIGNvbG9yaW5nCgpDb2xvciBieSBjZWxsIG9udG9sb2d5IGNsYXNzIG9uIHRoZSBvcmlnaW5hbCBUU05FLgoKYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHRpc3MxLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJjZWxsX29udG9sb2d5X2NsYXNzIikKYGBgCgojIFNhdmUgdGhlIFJvYmplY3QgZm9yIGxhdGVyCgpgYGB7cn0KZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICcwNF90aXNzMXVlX3JvYmpfZ2VuZXJhdGVkJywgCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiZHJvcGxldF8iLCB0aXNzMXVlX29mX2ludGVyZXN0LCAicmVmaW5lZGNlbGxzX3NldXJhdF90aXNzMS5Sb2JqIikpCnByaW50KGZpbGVuYW1lKQpzYXZlKHRpc3MxLCBmaWxlPWZpbGVuYW1lKQpgYGAKCmBgYHtyfQojIFRvIHJlbG9hZCBhIHNhdmVkIG9iamVjdApmaWxlbmFtZSA9IGhlcmUoJzAwX2RhdGFfaW5nZXN0JywgJzA0X3Rpc3MxdWVfcm9ial9nZW5lcmF0ZWQnLAogICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJkcm9wbGV0XyIsIHRpc3N1ZV9vZl9pbnRlcmVzdCwgInNldXJhdF9zbWFydGRyb3AtaW50ZWdyYXRlZC04MjcyMDE5LlJvYmoiKSkKbG9hZChmaWxlPWZpbGVuYW1lKQpgYGAKCgojIEV4cG9ydCB0aGUgZmluYWwgbWV0YWRhdGEKCgpgYGB7cn0Kc2F2ZV9hbm5vdGF0aW9uX2Nzdih0aXNzMSwgdGlzczF1ZV9vZl9pbnRlcmVzdCwgImRyb3BsZXQiKQpgYGAK