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 libraries

library(Seurat)
library(cowplot)
library(dplyr)
library(ggplot2)
library(ggExtra)
library(ggrepel)
library(reticulate)
library(Matrix)
library(viridis)
library(RColorBrewer)
library(MetBrewer)
library(wesanderson)
library(R.utils)

# Set ggplot theme as classic
theme_set(theme_classic())

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

  1. IPNP & Imagine Institute, Paris, France, ↩︎

LS0tCnRpdGxlOiAiQ2x1c3RlciBjb21wb3NpdGlvbiBQMCBHbW5jIEtPIgphdXRob3I6IAogIC0gRnLDqWTDqXJpYyBDYXVzZXJldF5bSVBOUCAmIEltYWdpbmUgSW5zdGl0dXRlLCBQYXJpcywgRnJhbmNlLCBmcmVkZXJpYy5jYXVzZXJldEBpbnNlcm0uZnJdIFshW10oaHR0cHM6Ly9vcmNpZC5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9pbWFnZXMvb3JjaWRfMTZ4MTYucG5nKV0oaHR0cHM6Ly9vcmNpZC5vcmcvMDAwMC0wMDAyLTA1NDMtNDkzOCkKIApkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBkZl9wcmludDogcGFnZWQKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KaDEgewogIGZvbnQtc2l6ZTogMzRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICNlNjRkMDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDQwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDIgewogIGZvbnQtc2l6ZTogMzBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDMgewogIGZvbnQtc2l6ZTogMjRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDQgewogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDUgewogIGZvbnQtc2l6ZTogMTZweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KCnAgewogIGZvbnQtc2l6ZTogMTZweDsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQpgYGAKClRoaXMgaXMgYW4gYW5hbHlzaXMgb2YgdGhlIGNvbnRyaWJ1dGlvbiBvZiBXVCBhbmQgR21uYyBLTyBjZWxscyB0byBkaXN0aW5jdCBjbHVzdGVycy4KSSBzdGFydCBmcm9tIGEgU2V1cmF0IG9iamVjdCBnZW5lcmF0ZWQgcHJldmlvdWx5LgoKCiMgTG9hZCBsaWJyYXJpZXMKCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dFeHRyYSkKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoTWF0cml4KQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KE1ldEJyZXdlcikKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShSLnV0aWxzKQoKIyBTZXQgZ2dwbG90IHRoZW1lIGFzIGNsYXNzaWMKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKYGBgCgojIExvYWQgdGhlIGRhdGFzZXQKCmBgYHtyfQoKR21uYy5jbGVhbnVwIDwtIHJlYWRSRFMoIkdtbmMuY2xlYW51cC5SRFMiKQoKRGltUGxvdChHbW5jLmNsZWFudXAsIHJlZHVjdGlvbiA9ICJTcHJpbmciLCBwdC5zaXplID0gMC4yLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIGNvbHMgPSBtZXQuYnJld2VyKCJLbGltdCIsIDIzKSkgKyBOb0F4ZXMoKSAKCmBgYAojIENsdXN0ZXIgY29tcG9zaXRpb24gIAoKYGBge3J9CmRmIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoR21uYy5jbGVhbnVwJHNldXJhdF9jbHVzdGVycyxHbW5jLmNsZWFudXAkb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmKSA8LSBjKCJDbHVzdGVyIiwgIkdlbm90eXBlIiwgIm5jZWxscyIpCgpwY3QuV1QgPC0gcHJvcC50YWJsZSh0YWJsZShHbW5jLmNsZWFudXAkb3JpZy5pZGVudCkpWzJdCgpwMSA8LSBnZ3Bsb3QoZGYsIGFlcyhmaWxsPUdlbm90eXBlLCB5PW5jZWxscywgeD1DbHVzdGVyKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vTGVnZW5kKCkKCnAyIDwtIGdncGxvdChkZiwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCnAxK3AyCgpgYGAKIyBDcmVhdGUgYSBzdXBlcnR5cGUgY2xhc3MgIAoKCmBgYHtyfQpHbW5jLmNsZWFudXBAbWV0YS5kYXRhJFN1cGVydHlwZVtHbW5jLmNsZWFudXAkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygyLDgpXSA8LSAiSW5oaWIuTiIKR21uYy5jbGVhbnVwQG1ldGEuZGF0YSRTdXBlcnR5cGVbR21uYy5jbGVhbnVwJHNldXJhdF9jbHVzdGVycyAlaW4lIGMoMCwgNCwgOSwgMTAsIDEzKV0gPC0gIkV4Y2l0Lk4iCkdtbmMuY2xlYW51cEBtZXRhLmRhdGEkU3VwZXJ0eXBlW0dtbmMuY2xlYW51cCRzZXVyYXRfY2x1c3RlcnMgJWluJSBjKDYpXSA8LSAiT1BDIgpHbW5jLmNsZWFudXBAbWV0YS5kYXRhJFN1cGVydHlwZVtHbW5jLmNsZWFudXAkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygzLCA1LCAxMSldIDwtICJDeWNsaW5nIHByb2cuIgpHbW5jLmNsZWFudXBAbWV0YS5kYXRhJFN1cGVydHlwZVtHbW5jLmNsZWFudXAkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygxNCwgMTUsIDE2LCAxOCwgMjAsIDIyKV0gPC0gIk5vbi1uZXVybyIKR21uYy5jbGVhbnVwQG1ldGEuZGF0YSRTdXBlcnR5cGVbR21uYy5jbGVhbnVwJHNldXJhdF9jbHVzdGVycyAlaW4lIGMoMSwgNywgMTIsIDE3LCAxOSldIDwtICJBc3Ryby9FcGVuZCIKI0dtbmMuY2xlYW51cEBtZXRhLmRhdGEkU3VwZXJ0eXBlW0dtbmMuY2xlYW51cCRzZXVyYXRfY2x1c3RlcnMgJWluJSBjKDIxKV0gPC0gIkRvdWJsZXRzL2xvd1EiCgpEaW1QbG90KEdtbmMuY2xlYW51cCwgcmVkdWN0aW9uID0gIlNwcmluZyIsIGdyb3VwLmJ5ID0gIlN1cGVydHlwZSIsIHB0LnNpemUgPSAwLjIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDMsIGNvbHMgPSBtZXQuYnJld2VyKCJBcmNoYW1iYXVsdCIsIDYpKSArIE5vQXhlcygpIAoKCgoKYGBgCgojIFN1cGVydHlwZSBjb21wb3NpdGlvbgpgYGB7cn0KZGYxIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoR21uYy5jbGVhbnVwJFN1cGVydHlwZSxHbW5jLmNsZWFudXAkb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmMSkgPC0gYygiU3VwZXJ0eXBlIiwgIkdlbm90eXBlIiwgIm5jZWxscyIpCgpwMSA8LSBnZ3Bsb3QoZGYxLCBhZXMoZmlsbD1HZW5vdHlwZSwgeT1uY2VsbHMsIHg9U3VwZXJ0eXBlKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIAogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdD0xKSkgKyBOb0xlZ2VuZCgpCgpwMiA8LSBnZ3Bsb3QoZGYxLCBhZXMoZmlsbD1HZW5vdHlwZSwgeT1uY2VsbHMsIHg9U3VwZXJ0eXBlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBwY3QuV1QsIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIm49IixuY2VsbHMpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9maWxsKHZqdXN0ID0gMC41KSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArICAgICAgIHlsYWIoIiUgY2VsbHMiKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgaGp1c3Q9MSkpCgpwMStwMgoKYGBgCgojIENlbGwgY3ljbGUgcGhhc2VzCmBgYHtyfQpkZjIgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShHbW5jLmNsZWFudXAkUGhhc2UsR21uYy5jbGVhbnVwJG9yaWcuaWRlbnQpKQpjb2xuYW1lcyhkZjIpIDwtIGMoIlBoYXNlIiwgIkdlbm90eXBlIiwgIm5jZWxscyIpCgpwMSA8LSBnZ3Bsb3QoZGYyLCBhZXMoZmlsbD1HZW5vdHlwZSwgeT1uY2VsbHMsIHg9UGhhc2UpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmMiwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PVBoYXNlKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBwY3QuV1QsIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIm49IixuY2VsbHMpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9maWxsKHZqdXN0ID0gMC41KSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArICAgICAgIHlsYWIoIiUgY2VsbHMiKQoKcDErcDIKCmBgYAoKIyBOb24tbmV1cm9uYWwgY2VsbHMKYGBge3J9CiNTdWJzZXQgbm9uIG5ldXJvbmFsIGNlbGxzCm5vbi5uZXVybyA8LSBzdWJzZXQoR21uYy5jbGVhbnVwLHN1YnNldCA9IFN1cGVydHlwZSA9PSAiTm9uLW5ldXJvIikKbm9uLm5ldXJvIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKG5vbi5uZXVybywgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpub24ubmV1cm8gPC0gU2NhbGVEYXRhKG5vbi5uZXVybywgdmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiKQpub24ubmV1cm8gPC0gUnVuUENBKG5vbi5uZXVybywgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKG9iamVjdCA9IG5vbi5uZXVybykpCm5vbi5uZXVybyA8LSBSdW5VTUFQKG5vbi5uZXVybywgZGltcyA9IDE6MjApCgojU2F2ZSBwcmV2aW91cyBjbHVzdGVyIG51bWJlciBhbmQgZGlzcGxheSBvbiBuZXcgVU1BUCBjb29yZGluYXRlcwpub24ubmV1cm8kcHJldi5jbHVzdGVyIDwtIG5vbi5uZXVybyRzZXVyYXRfY2x1c3RlcnMKRGltUGxvdChub24ubmV1cm8sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBULCBsYWJlbC5zaXplID0gMywgbGFiZWwuYm94ID0gVCwgcmVwZWwgPSBULCBwdC5zaXplID0gMC40LCBncm91cC5ieSA9ICJwcmV2LmNsdXN0ZXIiLCAgY29scyA9IG1ldC5icmV3ZXIoIktsaW10IiwgMjMpW2MoMTUsIDE2LCAxNywgMTgsIDIxLCAyMyldKSArIE5vQXhlcygpCgojUGVyZm9ybSBuZXcgY2x1c3RlcmluZwpub24ubmV1cm8gPC0gRmluZE5laWdoYm9ycyhub24ubmV1cm8sIGRpbXMgPSAxOjIwKQpub24ubmV1cm8gPC0gRmluZENsdXN0ZXJzKG5vbi5uZXVybywgcmVzb2x1dGlvbiA9IDAuMiwgdmVyYm9zZSA9IEYpCkRpbVBsb3Qobm9uLm5ldXJvLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJOZXdLaW5nZG9tIiwgOSkpICsgTm9BeGVzKCkKCiNQbG90IG1hcmtlciBnZW5lcyBmb3IgYW5ub3RhdGlvbgpWbG5QbG90KG5vbi5uZXVybywgZmVhdHVyZXM9YygiQzFxYSIsICJDc2YxciIsICJMeXZlMSIsICJTaWdsZWNoIiwiTWtpNjciLCAiRm94YzEiLCAiS2NuajgiLCAiUGVjYW0xIiwgIkx1bSIsICJTbGM2YTEzIiksY29scyA9IG1ldC5icmV3ZXIoIk5ld0tpbmdkb20iLCA5KSwgcHQuc2l6ZSA9IDAsIHN0YWNrID0gVCwgZmxpcCA9IFQsIGZpbGwuYnkgPSAiaWRlbnQiKSAmIE5vTGVnZW5kKCkKCkZlYXR1cmVQbG90KG5vbi5uZXVybywgZmVhdHVyZXM9YygiQzFxYSIsICJDc2YxciIsICJMeXZlMSIsICJTaWdsZWNoIiwiTWtpNjciLCAiRm94YzEiLCAiS2NuajgiLCAiUGVjYW0xIiwgIkx1bSIsICJTbGM2YTEzIiksIG5jb2w9MywgcmVkdWN0aW9uID0gInVtYXAiLCBvcmRlciA9IEYsIHB0LnNpemUgPSAwLjIpICYgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycz1jKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSkgJiBOb0xlZ2VuZCgpICYgTm9BeGVzKCkKCiNDbHVzdGVyIGNvbXBvc2l0aW9uCkRpbVBsb3Qobm9uLm5ldXJvLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDIsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGNvbHMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vQXhlcygpCgpkZjMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShub24ubmV1cm8kc2V1cmF0X2NsdXN0ZXJzLCBub24ubmV1cm8kb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmMykgPC0gYygiQ2x1c3RlciIsICJHZW5vdHlwZSIsICJuY2VsbHMiKQoKcDEgPC0gZ2dwbG90KGRmMywgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmMywgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCgpwMStwMgoKYGBgCgojIEluaGliaXRvcnkgbmV1cm9ucwpgYGB7cn0KI1N1YnNldCBpbmhpYml0b3J5IG5ldXJvbnMKSW5oaWIuTiA8LSBzdWJzZXQoR21uYy5jbGVhbnVwLHN1YnNldCA9IFN1cGVydHlwZSA9PSAiSW5oaWIuTiIpCkluaGliLk4gPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoSW5oaWIuTiwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpJbmhpYi5OIDwtIFNjYWxlRGF0YShJbmhpYi5OLCB2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIpCkluaGliLk4gPC0gUnVuUENBKEluaGliLk4sIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBJbmhpYi5OKSkKSW5oaWIuTiA8LSBSdW5VTUFQKEluaGliLk4sIGRpbXMgPSAxOjIwKQoKI1NhdmUgcHJldmlvdXMgY2x1c3RlciBudW1iZXIgYW5kIGRpc3BsYXkgb24gbmV3IFVNQVAgY29vcmRpbmF0ZXMKSW5oaWIuTiRwcmV2LmNsdXN0ZXIgPC0gSW5oaWIuTiRzZXVyYXRfY2x1c3RlcnMKRGltUGxvdChJbmhpYi5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAicHJldi5jbHVzdGVyIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJLbGltdCIsIDIzKVtjKDMsIDkpXSkgKyBOb0F4ZXMoKQoKI1BlcmZvcm0gbmV3IGNsdXN0ZXJpbmcKSW5oaWIuTiA8LSBGaW5kTmVpZ2hib3JzKEluaGliLk4sIGRpbXMgPSAxOjIwKQpJbmhpYi5OIDwtIEZpbmRDbHVzdGVycyhJbmhpYi5OLCByZXNvbHV0aW9uID0gMC4yLCB2ZXJib3NlID0gRikKRGltUGxvdChJbmhpYi5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJIb2t1c2FpMyIsIDkpKSArIE5vQXhlcygpCgojUGxvdCBtYXJrZXIgZ2VuZXMgZm9yIGFubm90YXRpb24KVmxuUGxvdChJbmhpYi5OLCBmZWF0dXJlcz1jKCJMaHg2IiwgIkZveHAxIiwgIlpmcDUwMyIsICJFYmYxIiwgIklzbDEiLCAiSHRyM2EiLCAiUHJveDEiLCAiU3A4IiwgIlNwOSIpLGNvbHMgPSBtZXQuYnJld2VyKCJIb2t1c2FpMyIsIDkpLCBwdC5zaXplID0gMCwgc3RhY2sgPSBULCBmbGlwID0gVCwgZmlsbC5ieSA9ICJpZGVudCIpICYgTm9MZWdlbmQoKQoKRmVhdHVyZVBsb3QoSW5oaWIuTiwgZmVhdHVyZXM9YygiTGh4NiIsICJGb3hwMSIsICJaZnA1MDMiLCAiSHRyM2EiLCAiUHJveDEiLCAiRWJmMSIsICJJc2wxIiwgIlNwOCIsICJTcDkiKSwgbmNvbD0zLCByZWR1Y3Rpb24gPSAidW1hcCIsIG9yZGVyID0gRiwgcHQuc2l6ZSA9IDAuMikgJiBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzPWMoImdyZXk5MCIsIGJyZXdlci5wYWwoOSwiWWxHbkJ1IikpKSAmIE5vTGVnZW5kKCkgJiBOb0F4ZXMoKQoKI0NsdXN0ZXIgY29tcG9zaXRpb24KRGltUGxvdChJbmhpYi5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDIsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLCBjb2xzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKyBOb0F4ZXMoKQoKZGY0IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoSW5oaWIuTiRzZXVyYXRfY2x1c3RlcnMsIEluaGliLk4kb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmNCkgPC0gYygiQ2x1c3RlciIsICJHZW5vdHlwZSIsICJuY2VsbHMiKQoKcDEgPC0gZ2dwbG90KGRmNCwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmNCwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCgpwMStwMgoKYGBgCgoKIyBFeGNpdGF0b3J5IG5ldXJvbnMKYGBge3J9CiNTdWJzZXQgZXhjaXRhdG9yeSBuZXVyb25zCkV4Y2l0Lk4gPC0gc3Vic2V0KEdtbmMuY2xlYW51cCxzdWJzZXQgPSBTdXBlcnR5cGUgPT0gIkV4Y2l0Lk4iKQpFeGNpdC5OIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEV4Y2l0Lk4sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKRXhjaXQuTiA8LSBTY2FsZURhdGEoRXhjaXQuTiwgdmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiKQpFeGNpdC5OIDwtIFJ1blBDQShFeGNpdC5OLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gRXhjaXQuTikpCkV4Y2l0Lk4gPC0gUnVuVU1BUChFeGNpdC5OLCBkaW1zID0gMToyMCkKCiNTYXZlIHByZXZpb3VzIGNsdXN0ZXIgbnVtYmVyIGFuZCBkaXNwbGF5IG9uIG5ldyBVTUFQIGNvb3JkaW5hdGVzCkV4Y2l0Lk4kcHJldi5jbHVzdGVyIDwtIEV4Y2l0Lk4kc2V1cmF0X2NsdXN0ZXJzCkRpbVBsb3QoRXhjaXQuTiwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gInByZXYuY2x1c3RlciIsICBjb2xzID0gbWV0LmJyZXdlcigiS2xpbXQiLCAyMylbYygxLCA1LCAxMCwgMTEsIDE0KV0pICsgTm9BeGVzKCkKCiNQZXJmb3JtIG5ldyBjbHVzdGVyaW5nCkV4Y2l0Lk4gPC0gRmluZE5laWdoYm9ycyhFeGNpdC5OLCBkaW1zID0gMToyMCkKRXhjaXQuTiA8LSBGaW5kQ2x1c3RlcnMoRXhjaXQuTiwgcmVzb2x1dGlvbiA9IDAuMiwgdmVyYm9zZSA9IEYpCkRpbVBsb3QoRXhjaXQuTiwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsICBjb2xzID0gbWV0LmJyZXdlcigiT0tlZWZmZTIiLCA4KSkgKyBOb0F4ZXMoKQoKI1Bsb3QgbWFya2VyIGdlbmVzIGZvciBhbm5vdGF0aW9uClZsblBsb3QoRXhjaXQuTiwgZmVhdHVyZXM9YygiVHJwNzMiLCAiUmVsbiIsICJIczNzdDQiLCAiVGNlcmcxbCIsICJGZXpmMiIsICJQb3UzZjIiLCAiU2F0YjIiLCAiVGJyMSIsICJFb21lcyIsICJQcm94MSIgLCJHYWQyIiwgIkFsYXMyIiksY29scyA9IG1ldC5icmV3ZXIoIk9LZWVmZmUyIiwgOCksIHB0LnNpemUgPSAwLCBzdGFjayA9IFQsIGZsaXAgPSBULCBmaWxsLmJ5ID0gImlkZW50IikgJiBOb0xlZ2VuZCgpCgpGZWF0dXJlUGxvdChFeGNpdC5OLCBmZWF0dXJlcz1jKCJUcnA3MyIsICJSZWxuIiwgIkhzM3N0NCIsICJUY2VyZzFsIiwgIkZlemYyIiwgIlBvdTNmMiIsICJTYXRiMiIsICJUYnIxIiwgIkVvbWVzIiwgIlByb3gxIiwgIkdhZDIiLCAiQWxhczIiKSwgbmNvbD0zLCByZWR1Y3Rpb24gPSAidW1hcCIsIG9yZGVyID0gRiwgcHQuc2l6ZSA9IDAuMikgJiBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzPWMoImdyZXk5MCIsIGJyZXdlci5wYWwoOSwiWWxHbkJ1IikpKSAmIE5vTGVnZW5kKCkgJiBOb0F4ZXMoKQoKI0NsdXN0ZXIgY29tcG9zaXRpb24KRGltUGxvdChFeGNpdC5OLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgbGFiZWwuc2l6ZSA9IDIsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLCBjb2xzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKyBOb0F4ZXMoKQoKZGY1IDwtIGFzLmRhdGEuZnJhbWUodGFibGUoRXhjaXQuTiRzZXVyYXRfY2x1c3RlcnMsIEV4Y2l0Lk4kb3JpZy5pZGVudCkpCmNvbG5hbWVzKGRmNSkgPC0gYygiQ2x1c3RlciIsICJHZW5vdHlwZSIsICJuY2VsbHMiKQoKcDEgPC0gZ2dwbG90KGRmNSwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArIAogICAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsgTm9MZWdlbmQoKQoKcDIgPC0gZ2dwbG90KGRmNSwgYWVzKGZpbGw9R2Vub3R5cGUsIHk9bmNlbGxzLCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiLCBzdGF0PSJpZGVudGl0eSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0LmJyZXdlcigiRWd5cHQiLCA0KSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IHBjdC5XVCwgY29sb3VyID0gImJsYWNrIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLG5jZWxscykpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ZpbGwodmp1c3QgPSAwLjUpLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsgICAgICAgeWxhYigiJSBjZWxscyIpCgpwMStwMgoKCmBgYAoKIyBBc3Ryb2VwZW5keW1hbCBjZWxscwpgYGB7cn0KI1N1YnNldCBhc3Ryb2VwZW5keW1hbCBjZWxscwpBc3Ryby5FcGVuZCA8LSBzdWJzZXQoR21uYy5jbGVhbnVwLHN1YnNldCA9IFN1cGVydHlwZSA9PSAiQXN0cm8vRXBlbmQiKQpBc3Ryby5FcGVuZCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhBc3Ryby5FcGVuZCwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpBc3Ryby5FcGVuZCA8LSBTY2FsZURhdGEoQXN0cm8uRXBlbmQsIHZhcnMudG8ucmVncmVzcyA9ICJwZXJjZW50Lm10IikKQXN0cm8uRXBlbmQgPC0gUnVuUENBKEFzdHJvLkVwZW5kLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gQXN0cm8uRXBlbmQpKQpBc3Ryby5FcGVuZCA8LSBSdW5VTUFQKEFzdHJvLkVwZW5kLCBkaW1zID0gMToyMCkKCiNTYXZlIHByZXZpb3VzIGNsdXN0ZXIgbnVtYmVyIGFuZCBkaXNwbGF5IG9uIG5ldyBVTUFQIGNvb3JkaW5hdGVzCkFzdHJvLkVwZW5kJHByZXYuY2x1c3RlciA8LSBBc3Ryby5FcGVuZCRzZXVyYXRfY2x1c3RlcnMKRGltUGxvdChBc3Ryby5FcGVuZCwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFQsIGxhYmVsLnNpemUgPSAzLCBsYWJlbC5ib3ggPSBULCByZXBlbCA9IFQsIHB0LnNpemUgPSAwLjQsIGdyb3VwLmJ5ID0gInByZXYuY2x1c3RlciIsICBjb2xzID0gbWV0LmJyZXdlcigiS2xpbXQiLCAyMylbYygyLCA4LCAxMywgMTgsIDIwKV0pICsgTm9BeGVzKCkKCiNQZXJmb3JtIG5ldyBjbHVzdGVyaW5nCkFzdHJvLkVwZW5kIDwtIEZpbmROZWlnaGJvcnMoQXN0cm8uRXBlbmQsIGRpbXMgPSAxOjIwKQpBc3Ryby5FcGVuZCA8LSBGaW5kQ2x1c3RlcnMoQXN0cm8uRXBlbmQsIHJlc29sdXRpb24gPSAwLjIsIHZlcmJvc2UgPSBGKQpEaW1QbG90KEFzdHJvLkVwZW5kLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVCwgbGFiZWwuc2l6ZSA9IDMsIGxhYmVsLmJveCA9IFQsIHJlcGVsID0gVCwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgIGNvbHMgPSBtZXQuYnJld2VyKCJIb2t1c2FpMSIsIDkpKSArIE5vQXhlcygpCgojUGxvdCBtYXJrZXIgZ2VuZXMgZm9yIGFubm90YXRpb24KVmxuUGxvdChBc3Ryby5FcGVuZCwgZmVhdHVyZXM9YygiR2ZhcCIsICJBcXA0IiwgIklkMyIsICJWZXBoMSIsICJMaHg5IiwiR2FkMiIsICJTbGMxN2E2IiwgIkZveGoxIiwgIlRycDczIiwgIkxteDFhIiksY29scyA9IG1ldC5icmV3ZXIoIkhva3VzYWkxIiwgOSksIHB0LnNpemUgPSAwLCBzdGFjayA9IFQsIGZsaXAgPSBULCBmaWxsLmJ5ID0gImlkZW50IikgJiBOb0xlZ2VuZCgpCgpGZWF0dXJlUGxvdChBc3Ryby5FcGVuZCwgZmVhdHVyZXM9YygiR2ZhcCIsICJBcXA0IiwgIklkMyIsICJWZXBoMSIsICJMaHg5IiwiR2FkMiIsICJTbGMxN2E2IiwgIkZveGoxIiwgIlRycDczIiwgIkxteDFhIiksIG5jb2w9MywgcmVkdWN0aW9uID0gInVtYXAiLCBvcmRlciA9IEYsIHB0LnNpemUgPSAwLjIpICYgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycz1jKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSkgJiBOb0xlZ2VuZCgpICYgTm9BeGVzKCkKCiNDbHVzdGVyIGNvbXBvc2l0aW9uCkRpbVBsb3QoQXN0cm8uRXBlbmQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGLCBsYWJlbC5zaXplID0gMiwgcHQuc2l6ZSA9IDAuNCwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGNvbHMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vQXhlcygpCgpkZjYgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShBc3Ryby5FcGVuZCRzZXVyYXRfY2x1c3RlcnMsIEFzdHJvLkVwZW5kJG9yaWcuaWRlbnQpKQpjb2xuYW1lcyhkZjYpIDwtIGMoIkNsdXN0ZXIiLCAiR2Vub3R5cGUiLCAibmNlbGxzIikKCnAxIDwtIGdncGxvdChkZjYsIGFlcyhmaWxsPUdlbm90eXBlLCB5PW5jZWxscywgeD1DbHVzdGVyKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXQuYnJld2VyKCJFZ3lwdCIsIDQpKSArIE5vTGVnZW5kKCkKCnAyIDwtIGdncGxvdChkZjYsIGFlcyhmaWxsPUdlbm90eXBlLCB5PW5jZWxscywgeD1DbHVzdGVyKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uPSJmaWxsIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldC5icmV3ZXIoIkVneXB0IiwgNCkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBwY3QuV1QsIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoIm49IixuY2VsbHMpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9maWxsKHZqdXN0ID0gMC41KSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArICAgICAgIHlsYWIoIiUgY2VsbHMiKQoKcDErcDIKCmBgYAoKIyBTZXNzaW9uIEluZm8KCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUg6JU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGAK