This is an analysis of the contribution of WT and Gmnc KO cells to
distinct clusters. I start from a Seurat object generated previouly.
Load the dataset
Gmnc.cleanup <- readRDS("Gmnc.cleanup.RDS")
DimPlot(Gmnc.cleanup, reduction = "Spring", pt.size = 0.2, label = T, label.size = 3, label.box = T, repel = T, cols = met.brewer("Klimt", 23)) + NoAxes()
# Cluster composition
df <- as.data.frame(table(Gmnc.cleanup$seurat_clusters,Gmnc.cleanup$orig.ident))
colnames(df) <- c("Cluster", "Genotype", "ncells")
pct.WT <- prop.table(table(Gmnc.cleanup$orig.ident))[2]
p1 <- ggplot(df, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) + NoLegend()
p2 <- ggplot(df, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells")
p1+p2
# Create a supertype class
Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(2,8)] <- "Inhib.N"
Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(0, 4, 9, 10, 13)] <- "Excit.N"
Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(6)] <- "OPC"
Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(3, 5, 11)] <- "Cycling prog."
Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(14, 15, 16, 18, 20, 22)] <- "Non-neuro"
Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(1, 7, 12, 17, 19)] <- "Astro/Epend"
#Gmnc.cleanup@meta.data$Supertype[Gmnc.cleanup$seurat_clusters %in% c(21)] <- "Doublets/lowQ"
DimPlot(Gmnc.cleanup, reduction = "Spring", group.by = "Supertype", pt.size = 0.2, label = F, label.size = 3, cols = met.brewer("Archambault", 6)) + NoAxes()

Supertype composition
df1 <- as.data.frame(table(Gmnc.cleanup$Supertype,Gmnc.cleanup$orig.ident))
colnames(df1) <- c("Supertype", "Genotype", "ncells")
p1 <- ggplot(df1, aes(fill=Genotype, y=ncells, x=Supertype)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1)) + NoLegend()
p2 <- ggplot(df1, aes(fill=Genotype, y=ncells, x=Supertype)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells") +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))
p1+p2

Cell cycle phases
df2 <- as.data.frame(table(Gmnc.cleanup$Phase,Gmnc.cleanup$orig.ident))
colnames(df2) <- c("Phase", "Genotype", "ncells")
p1 <- ggplot(df2, aes(fill=Genotype, y=ncells, x=Phase)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) + NoLegend()
p2 <- ggplot(df2, aes(fill=Genotype, y=ncells, x=Phase)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells")
p1+p2

Non-neuronal cells
#Subset non neuronal cells
non.neuro <- subset(Gmnc.cleanup,subset = Supertype == "Non-neuro")
non.neuro <- FindVariableFeatures(non.neuro, selection.method = "vst", nfeatures = 2000)
non.neuro <- ScaleData(non.neuro, vars.to.regress = "percent.mt")
non.neuro <- RunPCA(non.neuro, features = VariableFeatures(object = non.neuro))
non.neuro <- RunUMAP(non.neuro, dims = 1:20)
#Save previous cluster number and display on new UMAP coordinates
non.neuro$prev.cluster <- non.neuro$seurat_clusters
DimPlot(non.neuro, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "prev.cluster", cols = met.brewer("Klimt", 23)[c(15, 16, 17, 18, 21, 23)]) + NoAxes()

#Perform new clustering
non.neuro <- FindNeighbors(non.neuro, dims = 1:20)
non.neuro <- FindClusters(non.neuro, resolution = 0.2, verbose = F)
DimPlot(non.neuro, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "seurat_clusters", cols = met.brewer("NewKingdom", 9)) + NoAxes()

#Plot marker genes for annotation
VlnPlot(non.neuro, features=c("C1qa", "Csf1r", "Lyve1", "Siglech","Mki67", "Foxc1", "Kcnj8", "Pecam1", "Lum", "Slc6a13"),cols = met.brewer("NewKingdom", 9), pt.size = 0, stack = T, flip = T, fill.by = "ident") & NoLegend()

FeaturePlot(non.neuro, features=c("C1qa", "Csf1r", "Lyve1", "Siglech","Mki67", "Foxc1", "Kcnj8", "Pecam1", "Lum", "Slc6a13"), ncol=3, reduction = "umap", order = F, pt.size = 0.2) & scale_color_gradientn(colors=c("grey90", brewer.pal(9,"YlGnBu"))) & NoLegend() & NoAxes()

#Cluster composition
DimPlot(non.neuro, reduction = "umap", label = F, label.size = 2, label.box = T, repel = T, pt.size = 0.4, group.by = "orig.ident", cols = met.brewer("Egypt", 4)) + NoAxes()

df3 <- as.data.frame(table(non.neuro$seurat_clusters, non.neuro$orig.ident))
colnames(df3) <- c("Cluster", "Genotype", "ncells")
p1 <- ggplot(df3, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) + NoLegend()
p2 <- ggplot(df3, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells")
p1+p2

Inhibitory neurons
#Subset inhibitory neurons
Inhib.N <- subset(Gmnc.cleanup,subset = Supertype == "Inhib.N")
Inhib.N <- FindVariableFeatures(Inhib.N, selection.method = "vst", nfeatures = 2000)
Inhib.N <- ScaleData(Inhib.N, vars.to.regress = "percent.mt")
Inhib.N <- RunPCA(Inhib.N, features = VariableFeatures(object = Inhib.N))
Inhib.N <- RunUMAP(Inhib.N, dims = 1:20)
#Save previous cluster number and display on new UMAP coordinates
Inhib.N$prev.cluster <- Inhib.N$seurat_clusters
DimPlot(Inhib.N, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "prev.cluster", cols = met.brewer("Klimt", 23)[c(3, 9)]) + NoAxes()

#Perform new clustering
Inhib.N <- FindNeighbors(Inhib.N, dims = 1:20)
Inhib.N <- FindClusters(Inhib.N, resolution = 0.2, verbose = F)
DimPlot(Inhib.N, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "seurat_clusters", cols = met.brewer("Hokusai3", 9)) + NoAxes()

#Plot marker genes for annotation
VlnPlot(Inhib.N, features=c("Lhx6", "Foxp1", "Zfp503", "Ebf1", "Isl1", "Htr3a", "Prox1", "Sp8", "Sp9"),cols = met.brewer("Hokusai3", 9), pt.size = 0, stack = T, flip = T, fill.by = "ident") & NoLegend()

FeaturePlot(Inhib.N, features=c("Lhx6", "Foxp1", "Zfp503", "Htr3a", "Prox1", "Ebf1", "Isl1", "Sp8", "Sp9"), ncol=3, reduction = "umap", order = F, pt.size = 0.2) & scale_color_gradientn(colors=c("grey90", brewer.pal(9,"YlGnBu"))) & NoLegend() & NoAxes()

#Cluster composition
DimPlot(Inhib.N, reduction = "umap", label = F, label.size = 2, pt.size = 0.4, group.by = "orig.ident", cols = met.brewer("Egypt", 4)) + NoAxes()

df4 <- as.data.frame(table(Inhib.N$seurat_clusters, Inhib.N$orig.ident))
colnames(df4) <- c("Cluster", "Genotype", "ncells")
p1 <- ggplot(df4, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) + NoLegend()
p2 <- ggplot(df4, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells")
p1+p2

Excitatory neurons
#Subset excitatory neurons
Excit.N <- subset(Gmnc.cleanup,subset = Supertype == "Excit.N")
Excit.N <- FindVariableFeatures(Excit.N, selection.method = "vst", nfeatures = 2000)
Excit.N <- ScaleData(Excit.N, vars.to.regress = "percent.mt")
Excit.N <- RunPCA(Excit.N, features = VariableFeatures(object = Excit.N))
Excit.N <- RunUMAP(Excit.N, dims = 1:20)
#Save previous cluster number and display on new UMAP coordinates
Excit.N$prev.cluster <- Excit.N$seurat_clusters
DimPlot(Excit.N, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "prev.cluster", cols = met.brewer("Klimt", 23)[c(1, 5, 10, 11, 14)]) + NoAxes()

#Perform new clustering
Excit.N <- FindNeighbors(Excit.N, dims = 1:20)
Excit.N <- FindClusters(Excit.N, resolution = 0.2, verbose = F)
DimPlot(Excit.N, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "seurat_clusters", cols = met.brewer("OKeeffe2", 8)) + NoAxes()

#Plot marker genes for annotation
VlnPlot(Excit.N, features=c("Trp73", "Reln", "Hs3st4", "Tcerg1l", "Fezf2", "Pou3f2", "Satb2", "Tbr1", "Eomes", "Prox1" ,"Gad2", "Alas2"),cols = met.brewer("OKeeffe2", 8), pt.size = 0, stack = T, flip = T, fill.by = "ident") & NoLegend()

FeaturePlot(Excit.N, features=c("Trp73", "Reln", "Hs3st4", "Tcerg1l", "Fezf2", "Pou3f2", "Satb2", "Tbr1", "Eomes", "Prox1", "Gad2", "Alas2"), ncol=3, reduction = "umap", order = F, pt.size = 0.2) & scale_color_gradientn(colors=c("grey90", brewer.pal(9,"YlGnBu"))) & NoLegend() & NoAxes()

#Cluster composition
DimPlot(Excit.N, reduction = "umap", label = F, label.size = 2, pt.size = 0.4, group.by = "orig.ident", cols = met.brewer("Egypt", 4)) + NoAxes()

df5 <- as.data.frame(table(Excit.N$seurat_clusters, Excit.N$orig.ident))
colnames(df5) <- c("Cluster", "Genotype", "ncells")
p1 <- ggplot(df5, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) + NoLegend()
p2 <- ggplot(df5, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells")
p1+p2

Astroependymal cells
#Subset astroependymal cells
Astro.Epend <- subset(Gmnc.cleanup,subset = Supertype == "Astro/Epend")
Astro.Epend <- FindVariableFeatures(Astro.Epend, selection.method = "vst", nfeatures = 2000)
Astro.Epend <- ScaleData(Astro.Epend, vars.to.regress = "percent.mt")
Astro.Epend <- RunPCA(Astro.Epend, features = VariableFeatures(object = Astro.Epend))
Astro.Epend <- RunUMAP(Astro.Epend, dims = 1:20)
#Save previous cluster number and display on new UMAP coordinates
Astro.Epend$prev.cluster <- Astro.Epend$seurat_clusters
DimPlot(Astro.Epend, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "prev.cluster", cols = met.brewer("Klimt", 23)[c(2, 8, 13, 18, 20)]) + NoAxes()

#Perform new clustering
Astro.Epend <- FindNeighbors(Astro.Epend, dims = 1:20)
Astro.Epend <- FindClusters(Astro.Epend, resolution = 0.2, verbose = F)
DimPlot(Astro.Epend, reduction = "umap", label = T, label.size = 3, label.box = T, repel = T, pt.size = 0.4, group.by = "seurat_clusters", cols = met.brewer("Hokusai1", 9)) + NoAxes()

#Plot marker genes for annotation
VlnPlot(Astro.Epend, features=c("Gfap", "Aqp4", "Id3", "Veph1", "Lhx9","Gad2", "Slc17a6", "Foxj1", "Trp73", "Lmx1a"),cols = met.brewer("Hokusai1", 9), pt.size = 0, stack = T, flip = T, fill.by = "ident") & NoLegend()

FeaturePlot(Astro.Epend, features=c("Gfap", "Aqp4", "Id3", "Veph1", "Lhx9","Gad2", "Slc17a6", "Foxj1", "Trp73", "Lmx1a"), ncol=3, reduction = "umap", order = F, pt.size = 0.2) & scale_color_gradientn(colors=c("grey90", brewer.pal(9,"YlGnBu"))) & NoLegend() & NoAxes()

#Cluster composition
DimPlot(Astro.Epend, reduction = "umap", label = F, label.size = 2, pt.size = 0.4, group.by = "orig.ident", cols = met.brewer("Egypt", 4)) + NoAxes()

df6 <- as.data.frame(table(Astro.Epend$seurat_clusters, Astro.Epend$orig.ident))
colnames(df6) <- c("Cluster", "Genotype", "ncells")
p1 <- ggplot(df6, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="stack", stat="identity") + scale_fill_manual(values = met.brewer("Egypt", 4)) + NoLegend()
p2 <- ggplot(df6, aes(fill=Genotype, y=ncells, x=Cluster)) +
geom_bar(position="fill", stat="identity") +
scale_fill_manual(values = met.brewer("Egypt", 4)) +
geom_hline(yintercept = pct.WT, colour = "black", linetype = 2) +
geom_text(aes(label = paste0("n=",ncells)), position = position_fill(vjust = 0.5), colour = "black", size = 3, angle=90) + ylab("% cells")
p1+p2

Session Info
#date
format(Sys.time(), "%d %B, %Y, %H:%M")
## [1] "11 January, 2024, 16:22"
#Packages used
sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-conda-linux-gnu (64-bit)
## Running under: CentOS Linux 7 (Core)
##
## Matrix products: default
## BLAS/LAPACK: /shared/ifbstor1/software/miniconda/envs/r-4.1.1/lib/libopenblasp-r0.3.18.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] R.utils_2.11.0 R.oo_1.24.0 R.methodsS3_1.8.1 wesanderson_0.3.6
## [5] MetBrewer_0.2.0 RColorBrewer_1.1-3 viridis_0.6.2 viridisLite_0.4.1
## [9] Matrix_1.6-4 reticulate_1.24 ggrepel_0.9.1 ggExtra_0.9
## [13] ggplot2_3.3.6 dplyr_1.0.10 cowplot_1.1.1 Seurat_5.0.1
## [17] SeuratObject_5.0.1 sp_2.1-2
##
## loaded via a namespace (and not attached):
## [1] Rtsne_0.16 colorspace_2.0-3 deldir_1.0-6
## [4] ellipsis_0.3.2 ggridges_0.5.3 RcppHNSW_0.3.0
## [7] spatstat.data_3.0-3 rstudioapi_0.13 farver_2.1.1
## [10] leiden_0.3.10 listenv_0.8.0 RSpectra_0.16-1
## [13] fansi_1.0.3 codetools_0.2-18 splines_4.1.1
## [16] knitr_1.40 polyclip_1.10-0 spam_2.7-0
## [19] jsonlite_1.8.2 ica_1.0-2 cluster_2.1.2
## [22] png_0.1-7 uwot_0.1.11 spatstat.sparse_3.0-3
## [25] shiny_1.7.1 sctransform_0.4.1 compiler_4.1.1
## [28] httr_1.4.4 assertthat_0.2.1 fastmap_1.1.0
## [31] lazyeval_0.2.2 cli_3.4.1 later_1.3.0
## [34] htmltools_0.5.2 tools_4.1.1 igraph_1.3.1
## [37] dotCall64_1.0-1 gtable_0.3.1 glue_1.6.2
## [40] RANN_2.6.1 reshape2_1.4.4 Rcpp_1.0.9
## [43] scattermore_1.2 jquerylib_0.1.4 vctrs_0.4.2
## [46] nlme_3.1-153 spatstat.explore_3.2-5 progressr_0.10.0
## [49] lmtest_0.9-40 spatstat.random_3.2-2 xfun_0.34
## [52] stringr_1.4.1 globals_0.14.0 mime_0.12
## [55] miniUI_0.1.1.1 lifecycle_1.0.3 irlba_2.3.5.1
## [58] goftest_1.2-3 future_1.25.0 MASS_7.3-54
## [61] zoo_1.8-10 scales_1.2.1 spatstat.utils_3.0-4
## [64] promises_1.2.0.1 parallel_4.1.1 yaml_2.3.6
## [67] pbapply_1.5-0 gridExtra_2.3 sass_0.4.1
## [70] stringi_1.7.8 highr_0.9 fastDummies_1.7.3
## [73] rlang_1.0.6 pkgconfig_2.0.3 matrixStats_0.62.0
## [76] evaluate_0.17 lattice_0.20-45 tensor_1.5
## [79] ROCR_1.0-11 purrr_0.3.5 labeling_0.4.2
## [82] patchwork_1.1.1 htmlwidgets_1.5.4 tidyselect_1.2.0
## [85] parallelly_1.31.1 RcppAnnoy_0.0.19 plyr_1.8.7
## [88] magrittr_2.0.3 R6_2.5.1 generics_0.1.3
## [91] DBI_1.1.2 withr_2.5.0 pillar_1.8.1
## [94] fitdistrplus_1.1-8 abind_1.4-5 survival_3.2-13
## [97] tibble_3.1.8 future.apply_1.9.0 crayon_1.5.2
## [100] KernSmooth_2.23-20 utf8_1.2.2 spatstat.geom_3.2-7
## [103] plotly_4.10.0 rmarkdown_2.11 grid_4.1.1
## [106] data.table_1.14.2 digest_0.6.30 xtable_1.8-4
## [109] tidyr_1.2.1 httpuv_1.6.5 munsell_0.5.0
## [112] bslib_0.3.1
LS0tCnRpdGxlOiAiQ2x1c3RlciBjb21wb3NpdGlvbiBQMCBHbW5jIEtPIgphdXRob3I6IAogIC0gRnLDqWTDqXJpYyBDYXVzZXJldF5bSVBOUCAmIEltYWdpbmUgSW5zdGl0dXRlLCBQYXJpcywgRnJhbmNlLCBmcmVkZXJpYy5jYXVzZXJldEBpbnNlcm0uZnJdIFshW10oaHR0cHM6Ly9vcmNpZC5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9pbWFnZXMvb3JjaWRfMTZ4MTYucG5nKV0oaHR0cHM6Ly9vcmNpZC5vcmcvMDAwMC0wMDAyLTA1NDMtNDkzOCkKIApkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBkZl9wcmludDogcGFnZWQKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KaDEgewogIGZvbnQtc2l6ZTogMzRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICNlNjRkMDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDQwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDIgewogIGZvbnQtc2l6ZTogMzBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDMgewogIGZvbnQtc2l6ZTogMjRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDQgewogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDUgewogIGZvbnQtc2l6ZTogMTZweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KCnAgewogIGZvbnQtc2l6ZTogMTZweDsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQpgYGAKClRoaXMgaXMgYW4gYW5hbHlzaXMgb2YgdGhlIGNvbnRyaWJ1dGlvbiBvZiBXVCBhbmQgR21uYyBLTyBjZWxscyB0byBkaXN0aW5jdCBjbHVzdGVycy4KSSBzdGFydCBmcm9tIGEgU2V1cmF0IG9iamVjdCBnZW5lcmF0ZWQgcHJldmlvdWx5LgoKCiMgTG9hZCBsaWJyYXJpZXMKCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dFeHRyYSkKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoTWF0cml4KQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KE1ldEJyZXdlcikKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShSLnV0aWxzKQoKIyBTZXQgZ2dwbG90IHRoZW1lIGFzIGNsYXNzaWMKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKYGBgCgojIExvYWQgdGhlIGRhdGFzZXQKCmBgYHtyfQoKR21uYy5jbGVhbnVwIDwtIHJlYWRSRFMoIkdtbmMuY2xlYW51cC5SRFMiKQoKRGltUGxvdChHbW5jLmNsZWFudXAsIHJlZHVjdGlvbiA9ICJTcHJpbmciLCBwdC5zaXplID0gMC4yLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIGNvbHMgPSBtZXQuYnJld2VyKCJLbGltdCIsIDIzKSkgKyBOb0F4ZXMoKSAKCmBgYAojIENsdXN0ZXIgY29tcG9zaXRpb24gIAoKYGBge3J9CmRmIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoR21uYy5jbGVhbnVwJHNldXJhdF9jbHVzdGVycyxHbW5jLmNsZWFudXAkb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmKSA8LSBjKCJDbHVzdGVyIiwgIkdlbm90eXBlIiwgIm5jZWxscyIpCgpwY3QuV1QgPC0gcHJvcC50YWJsZSh0YWJsZShHbW5jLmNsZWFudXAkb3JpZy5pZGVudCkpWzJdCgpwMSA8LSBnZ3Bsb3QoZGYsIGFlcyhmaWxsPUdlbm90eXBlLCB5PW5jZWxscywgeD1DbHVzdGVyKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vTGVnZW5kKCkKCnAyIDwtIGdncGxvdChkZiwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCnAxK3AyCgpgYGAKIyBDcmVhdGUgYSBzdXBlcnR5cGUgY2xhc3MgIAoKCmBgYHtyfQpHbW5jLmNsZWFudXBAbWV0YS5kYXRhJFN1cGVydHlwZVtHbW5jLmNsZWFudXAkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygyLDgpXSA8LSAiSW5oaWIuTiIKR21uYy5jbGVhbnVwQG1ldGEuZGF0YSRTdXBlcnR5cGVbR21uYy5jbGVhbnVwJHNldXJhdF9jbHVzdGVycyAlaW4lIGMoMCwgNCwgOSwgMTAsIDEzKV0gPC0gIkV4Y2l0Lk4iCkdtbmMuY2xlYW51cEBtZXRhLmRhdGEkU3VwZXJ0eXBlW0dtbmMuY2xlYW51cCRzZXVyYXRfY2x1c3RlcnMgJWluJSBjKDYpXSA8LSAiT1BDIgpHbW5jLmNsZWFudXBAbWV0YS5kYXRhJFN1cGVydHlwZVtHbW5jLmNsZWFudXAkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygzLCA1LCAxMSldIDwtICJDeWNsaW5nIHByb2cuIgpHbW5jLmNsZWFudXBAbWV0YS5kYXRhJFN1cGVydHlwZVtHbW5jLmNsZWFudXAkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygxNCwgMTUsIDE2LCAxOCwgMjAsIDIyKV0gPC0gIk5vbi1uZXVybyIKR21uYy5jbGVhbnVwQG1ldGEuZGF0YSRTdXBlcnR5cGVbR21uYy5jbGVhbnVwJHNldXJhdF9jbHVzdGVycyAlaW4lIGMoMSwgNywgMTIsIDE3LCAxOSldIDwtICJBc3Ryby9FcGVuZCIKI0dtbmMuY2xlYW51cEBtZXRhLmRhdGEkU3VwZXJ0eXBlW0dtbmMuY2xlYW51cCRzZXVyYXRfY2x1c3RlcnMgJWluJSBjKDIxKV0gPC0gIkRvdWJsZXRzL2xvd1EiCgpEaW1QbG90KEdtbmMuY2xlYW51cCwgcmVkdWN0aW9uID0gIlNwcmluZyIsIGdyb3VwLmJ5ID0gIlN1cGVydHlwZSIsIHB0LnNpemUgPSAwLjIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDMsIGNvbHMgPSBtZXQuYnJld2VyKCJBcmNoYW1iYXVsdCIsIDYpKSArIE5vQXhlcygpIAoKCgoKYGBgCgojIFN1cGVydHlwZSBjb21wb3NpdGlvbgpgYGB7cn0KZGYxIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoR21uYy5jbGVhbnVwJFN1cGVydHlwZSxHbW5jLmNsZWFudXAkb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmMSkgPC0gYygiU3VwZXJ0eXBlIiwgIkdlbm90eXBlIiwgIm5jZWxscyIpCgpwMSA8LSBnZ3Bsb3QoZGYxLCBhZXMoZmlsbD1HZW5vdHlwZSwgeT1uY2VsbHMsIHg9U3VwZXJ0eXBlKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIAogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdD0xKSkgKyBOb0xlZ2VuZCgpCgpwMiA8LSBnZ3Bsb3QoZGYxLCBhZXMoZmlsbD1HZW5vdHlwZSwgeT1uY2VsbHMsIHg9U3VwZXJ0eXBlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBwY3QuV1QsIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIm49IixuY2VsbHMpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9maWxsKHZqdXN0ID0gMC41KSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArICAgICAgIHlsYWIoIiUgY2VsbHMiKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgaGp1c3Q9MSkpCgpwMStwMgoKYGBgCgojIENlbGwgY3ljbGUgcGhhc2VzCmBgYHtyfQpkZjIgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShHbW5jLmNsZWFudXAkUGhhc2UsR21uYy5jbGVhbnVwJG9yaWcuaWRlbnQpKQpjb2xuYW1lcyhkZjIpIDwtIGMoIlBoYXNlIiwgIkdlbm90eXBlIiwgIm5jZWxscyIpCgpwMSA8LSBnZ3Bsb3QoZGYyLCBhZXMoZmlsbD1HZW5vdHlwZSwgeT1uY2VsbHMsIHg9UGhhc2UpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmMiwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PVBoYXNlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBwY3QuV1QsIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIm49IixuY2VsbHMpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9maWxsKHZqdXN0ID0gMC41KSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArICAgICAgIHlsYWIoIiUgY2VsbHMiKQoKcDErcDIKCmBgYAoKIyBOb24tbmV1cm9uYWwgY2VsbHMKYGBge3J9CiNTdWJzZXQgbm9uIG5ldXJvbmFsIGNlbGxzCm5vbi5uZXVybyA8LSBzdWJzZXQoR21uYy5jbGVhbnVwLHN1YnNldCA9IFN1cGVydHlwZSA9PSAiTm9uLW5ldXJvIikKbm9uLm5ldXJvIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKG5vbi5uZXVybywgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpub24ubmV1cm8gPC0gU2NhbGVEYXRhKG5vbi5uZXVybywgdmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiKQpub24ubmV1cm8gPC0gUnVuUENBKG5vbi5uZXVybywgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKG9iamVjdCA9IG5vbi5uZXVybykpCm5vbi5uZXVybyA8LSBSdW5VTUFQKG5vbi5uZXVybywgZGltcyA9IDE6MjApCgojU2F2ZSBwcmV2aW91cyBjbHVzdGVyIG51bWJlciBhbmQgZGlzcGxheSBvbiBuZXcgVU1BUCBjb29yZGluYXRlcwpub24ubmV1cm8kcHJldi5jbHVzdGVyIDwtIG5vbi5uZXVybyRzZXVyYXRfY2x1c3RlcnMKRGltUGxvdChub24ubmV1cm8sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBULCBsYWJlbC5zaXplID0gMywgbGFiZWwuYm94ID0gVCwgcmVwZWwgPSBULCBwdC5zaXplID0gMC40LCBncm91cC5ieSA9ICJwcmV2LmNsdXN0ZXIiLCAgY29scyA9IG1ldC5icmV3ZXIoIktsaW10IiwgMjMpW2MoMTUsIDE2LCAxNywgMTgsIDIxLCAyMyldKSArIE5vQXhlcygpCgojUGVyZm9ybSBuZXcgY2x1c3RlcmluZwpub24ubmV1cm8gPC0gRmluZE5laWdoYm9ycyhub24ubmV1cm8sIGRpbXMgPSAxOjIwKQpub24ubmV1cm8gPC0gRmluZENsdXN0ZXJzKG5vbi5uZXVybywgcmVzb2x1dGlvbiA9IDAuMiwgdmVyYm9zZSA9IEYpCkRpbVBsb3Qobm9uLm5ldXJvLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJOZXdLaW5nZG9tIiwgOSkpICsgTm9BeGVzKCkKCiNQbG90IG1hcmtlciBnZW5lcyBmb3IgYW5ub3RhdGlvbgpWbG5QbG90KG5vbi5uZXVybywgZmVhdHVyZXM9YygiQzFxYSIsICJDc2YxciIsICJMeXZlMSIsICJTaWdsZWNoIiwiTWtpNjciLCAiRm94YzEiLCAiS2NuajgiLCAiUGVjYW0xIiwgIkx1bSIsICJTbGM2YTEzIiksY29scyA9IG1ldC5icmV3ZXIoIk5ld0tpbmdkb20iLCA5KSwgcHQuc2l6ZSA9IDAsIHN0YWNrID0gVCwgZmxpcCA9IFQsIGZpbGwuYnkgPSAiaWRlbnQiKSAmIE5vTGVnZW5kKCkKCkZlYXR1cmVQbG90KG5vbi5uZXVybywgZmVhdHVyZXM9YygiQzFxYSIsICJDc2YxciIsICJMeXZlMSIsICJTaWdsZWNoIiwiTWtpNjciLCAiRm94YzEiLCAiS2NuajgiLCAiUGVjYW0xIiwgIkx1bSIsICJTbGM2YTEzIiksIG5jb2w9MywgcmVkdWN0aW9uID0gInVtYXAiLCBvcmRlciA9IEYsIHB0LnNpemUgPSAwLjIpICYgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycz1jKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSkgJiBOb0xlZ2VuZCgpICYgTm9BeGVzKCkKCiNDbHVzdGVyIGNvbXBvc2l0aW9uCkRpbVBsb3Qobm9uLm5ldXJvLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDIsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGNvbHMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vQXhlcygpCgpkZjMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShub24ubmV1cm8kc2V1cmF0X2NsdXN0ZXJzLCBub24ubmV1cm8kb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmMykgPC0gYygiQ2x1c3RlciIsICJHZW5vdHlwZSIsICJuY2VsbHMiKQoKcDEgPC0gZ2dwbG90KGRmMywgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmMywgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCgpwMStwMgoKYGBgCgojIEluaGliaXRvcnkgbmV1cm9ucwpgYGB7cn0KI1N1YnNldCBpbmhpYml0b3J5IG5ldXJvbnMKSW5oaWIuTiA8LSBzdWJzZXQoR21uYy5jbGVhbnVwLHN1YnNldCA9IFN1cGVydHlwZSA9PSAiSW5oaWIuTiIpCkluaGliLk4gPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoSW5oaWIuTiwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpJbmhpYi5OIDwtIFNjYWxlRGF0YShJbmhpYi5OLCB2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIpCkluaGliLk4gPC0gUnVuUENBKEluaGliLk4sIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBJbmhpYi5OKSkKSW5oaWIuTiA8LSBSdW5VTUFQKEluaGliLk4sIGRpbXMgPSAxOjIwKQoKI1NhdmUgcHJldmlvdXMgY2x1c3RlciBudW1iZXIgYW5kIGRpc3BsYXkgb24gbmV3IFVNQVAgY29vcmRpbmF0ZXMKSW5oaWIuTiRwcmV2LmNsdXN0ZXIgPC0gSW5oaWIuTiRzZXVyYXRfY2x1c3RlcnMKRGltUGxvdChJbmhpYi5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAicHJldi5jbHVzdGVyIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJLbGltdCIsIDIzKVtjKDMsIDkpXSkgKyBOb0F4ZXMoKQoKI1BlcmZvcm0gbmV3IGNsdXN0ZXJpbmcKSW5oaWIuTiA8LSBGaW5kTmVpZ2hib3JzKEluaGliLk4sIGRpbXMgPSAxOjIwKQpJbmhpYi5OIDwtIEZpbmRDbHVzdGVycyhJbmhpYi5OLCByZXNvbHV0aW9uID0gMC4yLCB2ZXJib3NlID0gRikKRGltUGxvdChJbmhpYi5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJIb2t1c2FpMyIsIDkpKSArIE5vQXhlcygpCgojUGxvdCBtYXJrZXIgZ2VuZXMgZm9yIGFubm90YXRpb24KVmxuUGxvdChJbmhpYi5OLCBmZWF0dXJlcz1jKCJMaHg2IiwgIkZveHAxIiwgIlpmcDUwMyIsICJFYmYxIiwgIklzbDEiLCAiSHRyM2EiLCAiUHJveDEiLCAiU3A4IiwgIlNwOSIpLGNvbHMgPSBtZXQuYnJld2VyKCJIb2t1c2FpMyIsIDkpLCBwdC5zaXplID0gMCwgc3RhY2sgPSBULCBmbGlwID0gVCwgZmlsbC5ieSA9ICJpZGVudCIpICYgTm9MZWdlbmQoKQoKRmVhdHVyZVBsb3QoSW5oaWIuTiwgZmVhdHVyZXM9YygiTGh4NiIsICJGb3hwMSIsICJaZnA1MDMiLCAiSHRyM2EiLCAiUHJveDEiLCAiRWJmMSIsICJJc2wxIiwgIlNwOCIsICJTcDkiKSwgbmNvbD0zLCByZWR1Y3Rpb24gPSAidW1hcCIsIG9yZGVyID0gRiwgcHQuc2l6ZSA9IDAuMikgJiBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzPWMoImdyZXk5MCIsIGJyZXdlci5wYWwoOSwiWWxHbkJ1IikpKSAmIE5vTGVnZW5kKCkgJiBOb0F4ZXMoKQoKI0NsdXN0ZXIgY29tcG9zaXRpb24KRGltUGxvdChJbmhpYi5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDIsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLCBjb2xzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKyBOb0F4ZXMoKQoKZGY0IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoSW5oaWIuTiRzZXVyYXRfY2x1c3RlcnMsIEluaGliLk4kb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmNCkgPC0gYygiQ2x1c3RlciIsICJHZW5vdHlwZSIsICJuY2VsbHMiKQoKcDEgPC0gZ2dwbG90KGRmNCwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmNCwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCgpwMStwMgoKYGBgCgoKIyBFeGNpdGF0b3J5IG5ldXJvbnMKYGBge3J9CiNTdWJzZXQgZXhjaXRhdG9yeSBuZXVyb25zCkV4Y2l0Lk4gPC0gc3Vic2V0KEdtbmMuY2xlYW51cCxzdWJzZXQgPSBTdXBlcnR5cGUgPT0gIkV4Y2l0Lk4iKQpFeGNpdC5OIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEV4Y2l0Lk4sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKRXhjaXQuTiA8LSBTY2FsZURhdGEoRXhjaXQuTiwgdmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiKQpFeGNpdC5OIDwtIFJ1blBDQShFeGNpdC5OLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gRXhjaXQuTikpCkV4Y2l0Lk4gPC0gUnVuVU1BUChFeGNpdC5OLCBkaW1zID0gMToyMCkKCiNTYXZlIHByZXZpb3VzIGNsdXN0ZXIgbnVtYmVyIGFuZCBkaXNwbGF5IG9uIG5ldyBVTUFQIGNvb3JkaW5hdGVzCkV4Y2l0Lk4kcHJldi5jbHVzdGVyIDwtIEV4Y2l0Lk4kc2V1cmF0X2NsdXN0ZXJzCkRpbVBsb3QoRXhjaXQuTiwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gInByZXYuY2x1c3RlciIsICBjb2xzID0gbWV0LmJyZXdlcigiS2xpbXQiLCAyMylbYygxLCA1LCAxMCwgMTEsIDE0KV0pICsgTm9BeGVzKCkKCiNQZXJmb3JtIG5ldyBjbHVzdGVyaW5nCkV4Y2l0Lk4gPC0gRmluZE5laWdoYm9ycyhFeGNpdC5OLCBkaW1zID0gMToyMCkKRXhjaXQuTiA8LSBGaW5kQ2x1c3RlcnMoRXhjaXQuTiwgcmVzb2x1dGlvbiA9IDAuMiwgdmVyYm9zZSA9IEYpCkRpbVBsb3QoRXhjaXQuTiwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsICBjb2xzID0gbWV0LmJyZXdlcigiT0tlZWZmZTIiLCA4KSkgKyBOb0F4ZXMoKQoKI1Bsb3QgbWFya2VyIGdlbmVzIGZvciBhbm5vdGF0aW9uClZsblBsb3QoRXhjaXQuTiwgZmVhdHVyZXM9YygiVHJwNzMiLCAiUmVsbiIsICJIczNzdDQiLCAiVGNlcmcxbCIsICJGZXpmMiIsICJQb3UzZjIiLCAiU2F0YjIiLCAiVGJyMSIsICJFb21lcyIsICJQcm94MSIgLCJHYWQyIiwgIkFsYXMyIiksY29scyA9IG1ldC5icmV3ZXIoIk9LZWVmZmUyIiwgOCksIHB0LnNpemUgPSAwLCBzdGFjayA9IFQsIGZsaXAgPSBULCBmaWxsLmJ5ID0gImlkZW50IikgJiBOb0xlZ2VuZCgpCgpGZWF0dXJlUGxvdChFeGNpdC5OLCBmZWF0dXJlcz1jKCJUcnA3MyIsICJSZWxuIiwgIkhzM3N0NCIsICJUY2VyZzFsIiwgIkZlemYyIiwgIlBvdTNmMiIsICJTYXRiMiIsICJUYnIxIiwgIkVvbWVzIiwgIlByb3gxIiwgIkdhZDIiLCAiQWxhczIiKSwgbmNvbD0zLCByZWR1Y3Rpb24gPSAidW1hcCIsIG9yZGVyID0gRiwgcHQuc2l6ZSA9IDAuMikgJiBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzPWMoImdyZXk5MCIsIGJyZXdlci5wYWwoOSwiWWxHbkJ1IikpKSAmIE5vTGVnZW5kKCkgJiBOb0F4ZXMoKQoKI0NsdXN0ZXIgY29tcG9zaXRpb24KRGltUGxvdChFeGNpdC5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDIsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLCBjb2xzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKyBOb0F4ZXMoKQoKZGY1IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoRXhjaXQuTiRzZXVyYXRfY2x1c3RlcnMsIEV4Y2l0Lk4kb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmNSkgPC0gYygiQ2x1c3RlciIsICJHZW5vdHlwZSIsICJuY2VsbHMiKQoKcDEgPC0gZ2dwbG90KGRmNSwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmNSwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCgpwMStwMgoKCmBgYAoKIyBBc3Ryb2VwZW5keW1hbCBjZWxscwpgYGB7cn0KI1N1YnNldCBhc3Ryb2VwZW5keW1hbCBjZWxscwpBc3Ryby5FcGVuZCA8LSBzdWJzZXQoR21uYy5jbGVhbnVwLHN1YnNldCA9IFN1cGVydHlwZSA9PSAiQXN0cm8vRXBlbmQiKQpBc3Ryby5FcGVuZCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhBc3Ryby5FcGVuZCwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpBc3Ryby5FcGVuZCA8LSBTY2FsZURhdGEoQXN0cm8uRXBlbmQsIHZhcnMudG8ucmVncmVzcyA9ICJwZXJjZW50Lm10IikKQXN0cm8uRXBlbmQgPC0gUnVuUENBKEFzdHJvLkVwZW5kLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gQXN0cm8uRXBlbmQpKQpBc3Ryby5FcGVuZCA8LSBSdW5VTUFQKEFzdHJvLkVwZW5kLCBkaW1zID0gMToyMCkKCiNTYXZlIHByZXZpb3VzIGNsdXN0ZXIgbnVtYmVyIGFuZCBkaXNwbGF5IG9uIG5ldyBVTUFQIGNvb3JkaW5hdGVzCkFzdHJvLkVwZW5kJHByZXYuY2x1c3RlciA8LSBBc3Ryby5FcGVuZCRzZXVyYXRfY2x1c3RlcnMKRGltUGxvdChBc3Ryby5FcGVuZCwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gInByZXYuY2x1c3RlciIsICBjb2xzID0gbWV0LmJyZXdlcigiS2xpbXQiLCAyMylbYygyLCA4LCAxMywgMTgsIDIwKV0pICsgTm9BeGVzKCkKCiNQZXJmb3JtIG5ldyBjbHVzdGVyaW5nCkFzdHJvLkVwZW5kIDwtIEZpbmROZWlnaGJvcnMoQXN0cm8uRXBlbmQsIGRpbXMgPSAxOjIwKQpBc3Ryby5FcGVuZCA8LSBGaW5kQ2x1c3RlcnMoQXN0cm8uRXBlbmQsIHJlc29sdXRpb24gPSAwLjIsIHZlcmJvc2UgPSBGKQpEaW1QbG90KEFzdHJvLkVwZW5kLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJIb2t1c2FpMSIsIDkpKSArIE5vQXhlcygpCgojUGxvdCBtYXJrZXIgZ2VuZXMgZm9yIGFubm90YXRpb24KVmxuUGxvdChBc3Ryby5FcGVuZCwgZmVhdHVyZXM9YygiR2ZhcCIsICJBcXA0IiwgIklkMyIsICJWZXBoMSIsICJMaHg5IiwiR2FkMiIsICJTbGMxN2E2IiwgIkZveGoxIiwgIlRycDczIiwgIkxteDFhIiksY29scyA9IG1ldC5icmV3ZXIoIkhva3VzYWkxIiwgOSksIHB0LnNpemUgPSAwLCBzdGFjayA9IFQsIGZsaXAgPSBULCBmaWxsLmJ5ID0gImlkZW50IikgJiBOb0xlZ2VuZCgpCgpGZWF0dXJlUGxvdChBc3Ryby5FcGVuZCwgZmVhdHVyZXM9YygiR2ZhcCIsICJBcXA0IiwgIklkMyIsICJWZXBoMSIsICJMaHg5IiwiR2FkMiIsICJTbGMxN2E2IiwgIkZveGoxIiwgIlRycDczIiwgIkxteDFhIiksIG5jb2w9MywgcmVkdWN0aW9uID0gInVtYXAiLCBvcmRlciA9IEYsIHB0LnNpemUgPSAwLjIpICYgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycz1jKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSkgJiBOb0xlZ2VuZCgpICYgTm9BeGVzKCkKCiNDbHVzdGVyIGNvbXBvc2l0aW9uCkRpbVBsb3QoQXN0cm8uRXBlbmQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGLCBsYWJlbC5zaXplID0gMiwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGNvbHMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vQXhlcygpCgpkZjYgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShBc3Ryby5FcGVuZCRzZXVyYXRfY2x1c3RlcnMsIEFzdHJvLkVwZW5kJG9yaWcuaWRlbnQpKQpjb2xuYW1lcyhkZjYpIDwtIGMoIkNsdXN0ZXIiLCAiR2Vub3R5cGUiLCAibmNlbGxzIikKCnAxIDwtIGdncGxvdChkZjYsIGFlcyhmaWxsPUdlbm90eXBlLCB5PW5jZWxscywgeD1DbHVzdGVyKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vTGVnZW5kKCkKCnAyIDwtIGdncGxvdChkZjYsIGFlcyhmaWxsPUdlbm90eXBlLCB5PW5jZWxscywgeD1DbHVzdGVyKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBwY3QuV1QsIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIm49IixuY2VsbHMpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9maWxsKHZqdXN0ID0gMC41KSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArICAgICAgIHlsYWIoIiUgY2VsbHMiKQoKcDErcDIKCmBgYAoKIyBTZXNzaW9uIEluZm8KCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUg6JU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGAK