Load libraries

library(Seurat)
library(princurve)
library(Revelio)
library(monocle)
library(gprofiler2)
library(seriation)
library(Matrix)
library(dplyr)
library(RColorBrewer)
library(ggplot2)
library(ggExtra)
library(cowplot)
library(wesanderson)

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

Load integrated datasets

WT.KO.integrated <- readRDS("WT_KO.integrated.RDS")
DefaultAssay(WT.KO.integrated) <- "RNA"
DimPlot(WT.KO.integrated,
        reduction = "integrated_spring",
        group.by = "Lineage",
        pt.size = 1,
        cols =   c("#cc391b","#e7823a","#969696","#026c9a")
        ) + NoAxes()

CPx.data <-  subset(WT.KO.integrated,
                        subset = Lineage %in% c("Choroid_Plexus") & orig.ident %in% c("Hem1", "Gmnc_KO"))

DimPlot(CPx.data,
        group.by = "orig.ident",
        reduction = "integrated_spring",
        pt.size = 1,
        cols =  c("#cc391b","#026c9a")
        ) + NoAxes()

rm(WT.KO.integrated)
gc()
##             used   (Mb) gc trigger   (Mb)   max used   (Mb)
## Ncells   3373160  180.2    6316384  337.4    5080289  271.4
## Vcells 149511464 1140.7 1017816426 7765.4 1158667588 8840.0

Pseudotime in WT

WT.data <-  subset(CPx.data,
                   subset = orig.ident =="Hem1")

Exclude septal cells

FeaturePlot(object = WT.data,
            features = c("Fgf8", "Fgf17", "Adamts15", "Fgfbp1"),
            pt.size = 0.5,
            cols = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction = "integrated_spring",
            order = T) & NoAxes() & NoLegend()

WT.data <- AddModuleScore(WT.data,
                           features = list(c("Fgf8", "Fgf17", "Adamts15", "Fgfbp1")),
                           ctrl = 10,
                           name = "Septum")

FeaturePlot(object = WT.data,
            features = c("Septum1"),
            pt.size = 1,
            cols = rev(brewer.pal(10,"Spectral")),
            reduction = "integrated_spring",
            order = T) & NoAxes()

WT.data$Septal.prog <- WT.data$Septum1 > 0
p1 <- DimPlot(WT.data,
        reduction = "integrated_spring",
        group.by = "Septal.prog",
        pt.size = 1) + NoAxes()

p2 <- FeaturePlot(object = WT.data,
            features = c("Fgf17"),
            pt.size = 0.5,
            cols = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction = "integrated_spring",
            order = T) & NoAxes() & NoLegend()

p1 + p2

WT.data<- subset(WT.data,
                   subset = Septal.prog == FALSE & WT.data$Spring_1 > 1300)

Fit principal curve

Trajectories.ChP <- WT.data@meta.data %>%
                    dplyr::select("Barcodes", "Spring_1", "Spring_2")

fit <- principal_curve(as.matrix(Trajectories.ChP[,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=TRUE,
                       f = 0.8, 
                       stretch=2)
## Starting curve---distance^2: 32583625527
## Iteration 1---distance^2: 22649223
## Iteration 2---distance^2: 20882914
## Iteration 3---distance^2: 20559041
## Iteration 4---distance^2: 20476272
## Iteration 5---distance^2: 20454340
## Iteration 6---distance^2: 20457685
#The principal curve smoothed
ChP.pc.line <- as.data.frame(fit$s[order(fit$lambda),]) 

#Pseudotime score
Trajectories.ChP$Pseudotime <- fit$lambda/max(fit$lambda)

#Inverse the score if positive correlation with progenitor marker
if (cor(Trajectories.ChP$Pseudotime, WT.data@assays$SCT@data['Hmga2', Trajectories.ChP$Barcodes]) > 0) {
  Trajectories.ChP$Pseudotime <- -(Trajectories.ChP$Pseudotime - max(Trajectories.ChP$Pseudotime))
}

WT.data$Pseudotime <- Trajectories.ChP$Pseudotime
FeaturePlot(object = WT.data,
            features = "Pseudotime",
            pt.size = 2,
            cols = rev(colorRampPalette(brewer.pal(n =10, name = "Spectral"))(100)),
            reduction = "integrated_spring",
            order = T) & NoAxes()

Pseudotime in KO

KO.data <-  subset(CPx.data,
                   subset = orig.ident =="Gmnc_KO")

Exclude septal cells

FeaturePlot(object = KO.data,
            features = c("Fgf8", "Fgf17", "Adamts15", "Fgfbp1"),
            pt.size = 0.5,
            cols = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction = "integrated_spring",
            order = T) & NoAxes() & NoLegend()

KO.data <- AddModuleScore(KO.data,
                          features = list(c("Fgf8", "Fgf17", "Adamts15", "Fgfbp1")),
                          ctrl = 10,
                          name = "Septum")

FeaturePlot(object = KO.data,
            features = c("Septum1"),
            pt.size = 1,
            cols = rev(brewer.pal(10,"Spectral")),
            reduction = "integrated_spring",
            order = T) & NoAxes()

KO.data$Septal.prog <- KO.data$Septum1 > 0
p1 <- DimPlot(KO.data,
              reduction = "integrated_spring",
              group.by = "Septal.prog",
              pt.size = 1) + NoAxes()

p2 <- FeaturePlot(object = KO.data,
                  features = c("Fgf17"),
                  pt.size = 0.5,
                  cols = c("grey90", brewer.pal(9,"YlGnBu")),
                  reduction = "integrated_spring",
                  order = T) & NoAxes() & NoLegend()

p1 + p2

KO.data<- subset(KO.data,
                 subset = Septal.prog == FALSE & KO.data$Spring_1 > 2000)

Fit principal curve

Trajectories.ChP <- KO.data@meta.data %>%
  dplyr::select("Barcodes", "Spring_1", "Spring_2")

fit <- principal_curve(as.matrix(Trajectories.ChP[,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=TRUE,
                       f = 0.8, 
                       stretch=2)
## Starting curve---distance^2: 5080053369
## Iteration 1---distance^2: 3624561
## Iteration 2---distance^2: 3590262
## Iteration 3---distance^2: 3588718
#The principal curve smoothed
ChP.pc.line <- as.data.frame(fit$s[order(fit$lambda),]) 

#Pseudotime score
Trajectories.ChP$Pseudotime <- fit$lambda/max(fit$lambda)

#Inverse the score if positive correlation with progenitor marker
if (cor(Trajectories.ChP$Pseudotime, KO.data@assays$SCT@data['Hmga2', Trajectories.ChP$Barcodes]) > 0) {
  Trajectories.ChP$Pseudotime <- -(Trajectories.ChP$Pseudotime - max(Trajectories.ChP$Pseudotime))
}

KO.data$Pseudotime <- Trajectories.ChP$Pseudotime
FeaturePlot(object = KO.data,
            features = "Pseudotime",
            pt.size = 2,
            cols = rev(colorRampPalette(brewer.pal(n =10, name = "Spectral"))(100)),
            reduction = "integrated_spring",
            order = T) & NoAxes()

Subset the full integrated dataset

Trajectories <- rbind(WT.data@meta.data %>% select(Barcodes, Pseudotime), KO.data@meta.data %>% select(Barcodes, Pseudotime))
WT.KO.integrated <- readRDS("WT_KO.integrated.RDS")

meta.data <- WT.KO.integrated@meta.data[Trajectories$Barcodes,]
meta.data$Pseudotime <- Trajectories$Pseudotime
WT.KO.integrated <- CreateSeuratObject(counts = WT.KO.integrated@assays$RNA@counts[, Trajectories$Barcodes],
                                       meta.data = meta.data)

spring <- as.matrix(WT.KO.integrated@meta.data %>% select("Integrated_Spring_1", "Integrated_Spring_2"))
  
WT.KO.integrated[["integrated_spring"]] <- CreateDimReducObject(embeddings = spring, key = "Spring_", assay = DefaultAssay(WT.KO.integrated))
p1 <- FeaturePlot(object = WT.KO.integrated,
            features = "Pseudotime",
            pt.size = 0.5,
            cols = rev(colorRampPalette(brewer.pal(n =11, name = "Spectral"))(100)),
            reduction = "integrated_spring",
            order = T) & NoAxes()

p2 <- DimPlot(object = WT.KO.integrated,
        group.by = "orig.ident",
        pt.size = 0.5,
        reduction = "integrated_spring",
        cols =  c("#cc391b", "#026c9a")) & NoAxes()


p1 + p2

Normalization

WT.KO.integrated <- NormalizeData(WT.KO.integrated, normalization.method = "LogNormalize", scale.factor = 10000, assay = "RNA")
WT.KO.integrated <- FindVariableFeatures(WT.KO.integrated, selection.method = "disp", nfeatures = 6500, assay = "RNA")

Plot some genes along pseudotime

source("../Functions/functions_GeneTrends.R")

Plot.Genes.trend(Seurat.data= WT.KO.integrated,
                 group.by = "Genotype",
                 genes= c("Nasp","Ttr","Htr2c", "Gmnc", "Trp73", "Foxj1", "Pifo", "Ccdc67"))

Use monocle2 to model gene expression along cycling axis

rm(list = ls()[!ls() %in% c("WT.KO.integrated")])
gc()
##            used  (Mb) gc trigger   (Mb)   max used    (Mb)
## Ncells  3498548 186.9    6316384  337.4    6316384   337.4
## Vcells 28981446 221.2  944420894 7205.4 1335753510 10191.0

Initialize a monocle object

# Transfer metadata
Annot.data  <- new('AnnotatedDataFrame',
                   data = data.frame(Barcode= WT.KO.integrated$Barcodes,
                                     Lineage= WT.KO.integrated$Lineage,
                                     Pseudotime= WT.KO.integrated$Pseudotime,
                                     Genotype= WT.KO.integrated$orig.ident))

# Transfer counts data
feature.data <- new('AnnotatedDataFrame',
                    data = data.frame(gene_short_name = rownames(WT.KO.integrated[["RNA"]]@counts),
                                      row.names = rownames(WT.KO.integrated[["RNA"]]@counts)))

# Create the CellDataSet object including variable genes only
gbm_cds <- newCellDataSet(WT.KO.integrated[["RNA"]]@counts,
                              phenoData = Annot.data,
                              featureData = feature.data,
                              lowerDetectionLimit = 0,
                              expressionFamily = negbinomial())
gbm_cds <- estimateSizeFactors(gbm_cds)
gbm_cds <- estimateDispersions(gbm_cds)
gbm_cds <- detectGenes(gbm_cds, min_expr = 0.1)
rm(list = ls()[!ls() %in% c("WT.KO.integrated", "gbm_cds")])
gc()
##            used  (Mb) gc trigger   (Mb)   max used    (Mb)
## Ncells  3566447 190.5    6316384  337.4    6316384   337.4
## Vcells 29460924 224.8  755536716 5764.3 1335753510 10191.0

Plot WT CR dynamic genes along WT and KO trajectories

# Load WT CPx variable genes along pseudotime
WT.CPx.genes <- read.table("../ChoroidPlexus_trajectory/ChP.Gene.dynamique.csv", sep = ";", header = T)

# Create a new pseudotime vector of 300 points
nPoints <- 100

new_data = list()
for (Genotype in unique(WT.KO.integrated$orig.ident)){
  new_data[[length(new_data) + 1]] = data.frame(Pseudotime = seq(min(WT.KO.integrated$Pseudotime), max(WT.KO.integrated$Pseudotime), length.out = nPoints), Genotype= Genotype)
}

new_data = do.call(rbind, new_data)

# Smooth gene expression
Diff.curve_matrix <- genSmoothCurves(gbm_cds[WT.CPx.genes$Gene, ],
                                      trend_formula = "~sm.ns(Pseudotime, df = 3)*Genotype",
                                      relative_expr = TRUE,
                                      new_data = new_data,
                                      cores= parallel::detectCores() - 2)
# Order the rows using seriation
dst <- as.dist((1-cor(scale(t(Diff.curve_matrix[,1:100])), method = "pearson")))
row.ser <- seriation::seriate(dst, method ="R2E") #"R2E" #TSP #"GW" "GW_ward"
gene.order <- rownames(Diff.curve_matrix[,1:100][get_order(row.ser),])

# Set annotation colors
pal <- wes_palette("Darjeeling1")
anno.colors <- list(lineage = c(Gmnc_KO="#026c9a", Gmnc_WT="#cc391b"),
                    Gene.Clusters = c(Clust.1 =pal[1] , Clust.2=pal[2], Clust.3=pal[3], Clust.4=pal[4], Clust.5=pal[5]))


pheatmap::pheatmap(Diff.curve_matrix[gene.order,
                                c(200:101,#KO 
                                  1:100)], #WT
                   scale = "row",
                   cluster_rows = F,
                   cluster_cols = F,
                   annotation_row = WT.CPx.genes  %>% dplyr::select(Gene.Clusters),
                   annotation_col = data.frame(lineage = rep(c("Gmnc_KO","Gmnc_WT"), each=100)),
                   annotation_colors = anno.colors,
                   show_colnames = F,
                   show_rownames = F,
                   fontsize_row = 8,
                   border_color = NA,
                   color =  viridis::viridis(9),
                   breaks = seq(-2.5,2.5, length.out = 9),
                   main = "")

TF only

TFs <- read.table("TF.csv", sep = ";")[,1]

gene.order <- gene.order[gene.order %in% TFs]

heatmap.gene <- pheatmap::pheatmap(Diff.curve_matrix[gene.order,
                                c(200:101,#KO 
                                  1:100)], #WT
                       scale = "row",
                       cluster_rows = F,
                       cluster_cols = F,
                       annotation_row = WT.CPx.genes %>% dplyr::select(Gene.Clusters),
                       annotation_col = data.frame(lineage = rep(c("Gmnc_KO","Gmnc_WT"), each=100)),
                       annotation_colors = anno.colors,
                       show_colnames = F,
                       show_rownames = F,
                       fontsize_row = 8,
                       border_color = NA,
                       color =  viridis::viridis(9),
                       breaks = seq(-2.5,2.5, length.out = 9),
                       main = "WT CPx dynamic genes along GmncWT trajectories")

source("../Functions/functions_GeneTrends.R")

Plot.Genes.trend(Seurat.data= WT.KO.integrated,
                 group.by = "Genotype",
                 genes= c("Gmnc", "Trp73", "E2f7", "Foxj1", "Irx5", "Carhsp1", "Foxa2", "Sox9", "Pou3f2", "Myb", 
                          "Plagl1", "Prdm16", "Aebp1"))

KO dynamic genes along pseudotime

Find DEG in the KO

KO.pData <- pData(gbm_cds) %>% subset(Genotype == "Gmnc_KO")

pseudo.maturation.diff <- differentialGeneTest(gbm_cds[WT.KO.integrated[["RNA"]]@var.features, KO.pData$Barcode], 
                                                 fullModelFormulaStr = "~sm.ns(Pseudotime, df = 3)",
                                                 cores = parallel::detectCores() - 2)

# Filter genes based on FDR
pseudo.maturation.diff.filtered <- pseudo.maturation.diff %>% filter(qval < 1e-30)
# Create a new pseudo-DV vector of 300 points
nPoints <- 100

new_data = list()
for (Lineage in unique(KO.pData$Lineage)){
  new_data[[length(new_data) + 1]] = data.frame(Pseudotime = seq(min(KO.pData$Pseudotime), max(KO.pData$Pseudotime), length.out = nPoints), Lineage=Lineage)
}

new_data = do.call(rbind, new_data)

# Smooth gene expression
Diff.curve_matrix <- genSmoothCurves(gbm_cds[as.character(pseudo.maturation.diff.filtered$gene_short_name), KO.pData$Barcode],
                                      trend_formula = "~sm.ns(Pseudotime, df = 3)",
                                      relative_expr = TRUE,
                                      new_data = new_data,
                                      cores= parallel::detectCores() - 2)
Pseudotime.genes.clusters <- cluster::pam(as.dist((1 - cor(Matrix::t(Diff.curve_matrix),method = "pearson"))), k= 5)

KO_CPx_Gene.dynamique <- data.frame(Gene= names(Pseudotime.genes.clusters$clustering),
                                     Waves= Pseudotime.genes.clusters$clustering,
                                     Gene.Clusters = Pseudotime.genes.clusters$clustering,
                                     q.val = pseudo.maturation.diff.filtered$qval
                                     ) %>% arrange(Gene.Clusters)

row.names(KO_CPx_Gene.dynamique) <- KO_CPx_Gene.dynamique$Gene
KO_CPx_Gene.dynamique$Gene.Clusters <- paste0("Clust.", KO_CPx_Gene.dynamique$Gene.Clusters)

write.table(KO_CPx_Gene.dynamique, "KO_CPx_dynamic_genes.csv", sep = ";", quote = F, row.names = F)
# Order the rows using seriation
dst <- as.dist((1-cor(scale(t(Diff.curve_matrix)), method = "pearson")))
row.ser <- seriation::seriate(dst, method ="R2E") #"R2E" #TSP #"GW" "GW_ward"
gene.order <- rev(rownames(Diff.curve_matrix[get_order(row.ser),]))

# Set annotation colors
pal <- wes_palette("Darjeeling1")
anno.colors <- list(Gene.Clusters = c(Clust.1 =pal[1] , Clust.2=pal[2], Clust.3=pal[3], Clust.4=pal[4], Clust.5=pal[5]))


pheatmap::pheatmap(Diff.curve_matrix[gene.order,],
                   scale = "row",
                   cluster_rows = F,
                   cluster_cols = F,
                   annotation_row = KO_CPx_Gene.dynamique %>% dplyr::select(Gene.Clusters),
                   annotation_colors = anno.colors,
                   show_colnames = F,
                   show_rownames = F,
                   fontsize_row = 8,
                   border_color = NA,
                   color =  viridis::viridis(9),
                   breaks = seq(-2.5,2.5, length.out = 9),
                   main = "")

Session Info

#date
format(Sys.time(), "%d %B, %Y, %H,%M")
## [1] "16 juin, 2022, 16,15"
#Packages used
sessionInfo()
## R version 4.2.0 (2022-04-22)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.4 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] splines   stats4    stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] wesanderson_0.3.6   cowplot_1.1.1       ggExtra_0.9        
##  [4] RColorBrewer_1.1-2  dplyr_1.0.7         seriation_1.3.1    
##  [7] gprofiler2_0.2.1    monocle_2.22.0      DDRTree_0.1.5      
## [10] irlba_2.3.3         VGAM_1.1-5          ggplot2_3.3.5      
## [13] Biobase_2.54.0      BiocGenerics_0.40.0 Matrix_1.4-1       
## [16] Revelio_0.1.0       princurve_2.1.6     SeuratObject_4.0.4 
## [19] Seurat_4.0.5       
## 
## loaded via a namespace (and not attached):
##   [1] plyr_1.8.6            igraph_1.2.11         lazyeval_0.2.2       
##   [4] densityClust_0.3      listenv_0.8.0         scattermore_0.7      
##   [7] fastICA_1.2-3         digest_0.6.29         foreach_1.5.1        
##  [10] htmltools_0.5.2       viridis_0.6.2         fansi_0.5.0          
##  [13] magrittr_2.0.2        tensor_1.5            cluster_2.1.3        
##  [16] ROCR_1.0-11           limma_3.50.0          globals_0.14.0       
##  [19] matrixStats_0.61.0    docopt_0.7.1          spatstat.sparse_2.0-0
##  [22] colorspace_2.0-2      ggrepel_0.9.1         xfun_0.28            
##  [25] sparsesvd_0.2         crayon_1.4.2          jsonlite_1.7.2       
##  [28] spatstat.data_2.1-0   survival_3.2-13       zoo_1.8-9            
##  [31] iterators_1.0.13      glue_1.5.1            polyclip_1.10-0      
##  [34] registry_0.5-1        gtable_0.3.0          leiden_0.3.9         
##  [37] future.apply_1.8.1    abind_1.4-5           scales_1.1.1         
##  [40] pheatmap_1.0.12       DBI_1.1.1             miniUI_0.1.1.1       
##  [43] Rcpp_1.0.8            viridisLite_0.4.0     xtable_1.8-4         
##  [46] reticulate_1.22       spatstat.core_2.3-1   htmlwidgets_1.5.4    
##  [49] httr_1.4.2            FNN_1.1.3             ellipsis_0.3.2       
##  [52] ica_1.0-2             farver_2.1.0          pkgconfig_2.0.3      
##  [55] sass_0.4.0            uwot_0.1.10           deldir_1.0-6         
##  [58] utf8_1.2.2            labeling_0.4.2        tidyselect_1.1.1     
##  [61] rlang_0.4.12          reshape2_1.4.4        later_1.3.0          
##  [64] munsell_0.5.0         tools_4.2.0           generics_0.1.1       
##  [67] ggridges_0.5.3        evaluate_0.14         stringr_1.4.0        
##  [70] fastmap_1.1.0         yaml_2.2.1            goftest_1.2-3        
##  [73] knitr_1.36            fitdistrplus_1.1-6    purrr_0.3.4          
##  [76] RANN_2.6.1            pbapply_1.5-0         future_1.23.0        
##  [79] nlme_3.1-153          mime_0.12             slam_0.1-49          
##  [82] compiler_4.2.0        plotly_4.10.0         png_0.1-7            
##  [85] spatstat.utils_2.2-0  tibble_3.1.6          bslib_0.3.1          
##  [88] stringi_1.7.6         highr_0.9             lattice_0.20-45      
##  [91] HSMMSingleCell_1.14.0 vctrs_0.3.8           pillar_1.6.4         
##  [94] lifecycle_1.0.1       spatstat.geom_2.3-0   combinat_0.0-8       
##  [97] lmtest_0.9-39         jquerylib_0.1.4       RcppAnnoy_0.0.19     
## [100] data.table_1.14.2     httpuv_1.6.3          patchwork_1.1.1      
## [103] R6_2.5.1              promises_1.2.0.1      TSP_1.1-11           
## [106] KernSmooth_2.23-20    gridExtra_2.3         parallelly_1.29.0    
## [109] codetools_0.2-18      MASS_7.3-57           assertthat_0.2.1     
## [112] withr_2.4.3           qlcMatrix_0.9.7       sctransform_0.3.2    
## [115] mgcv_1.8-40           parallel_4.2.0        grid_4.2.0           
## [118] rpart_4.1.16          tidyr_1.1.4           rmarkdown_2.11       
## [121] Rtsne_0.15            shiny_1.7.1

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France, ↩︎

LS0tCnRpdGxlOiAiQ29tcGFyaXNvbiBiZXR3ZWVuIHRyYWplY3RvcmllcyBpbiB0aGUgR21uYyBXVC9LTyIKYXV0aG9yOgogICAtIE1hdHRoaWV1IE1vcmVhdV5bSW5zdGl0dXRlIG9mIFBzeWNoaWF0cnkgYW5kIE5ldXJvc2NpZW5jZSBvZiBQYXJpcywgSU5TRVJNIFUxMjY2LCA3NTAxNCwgUGFyaXMsIEZyYW5jZSwgbWF0dGhpZXUubW9yZWF1QGluc2VybS5mcl0gWyFbXShodHRwczovL29yY2lkLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL2ltYWdlcy9vcmNpZF8xNngxNi5wbmcpXShodHRwczovL29yY2lkLm9yZy8wMDAwLTAwMDItMjU5Mi0yMzczKQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGRmX3ByaW50OiB0aWJibGUKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgdGhlbWU6IGNvc21vCiAgICBjc3M6ICIuLi9zdHlsZS5jc3MiCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZmlnLmFsaWduID0gJ2NlbnRlcicsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlLmxhenkgPSBGQUxTRSkKCiMgVG8gdXNlIGJpb21hcnQgCm5ld19jb25maWcgPC0gaHR0cjo6Y29uZmlnKHNzbF92ZXJpZnlwZWVyID0gRkFMU0UpCmh0dHI6OnNldF9jb25maWcobmV3X2NvbmZpZywgb3ZlcnJpZGUgPSBGQUxTRSkKYGBgCgojIExvYWQgbGlicmFyaWVzCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShwcmluY3VydmUpCmxpYnJhcnkoUmV2ZWxpbykKbGlicmFyeShtb25vY2xlKQpsaWJyYXJ5KGdwcm9maWxlcjIpCmxpYnJhcnkoc2VyaWF0aW9uKQpsaWJyYXJ5KE1hdHJpeCkKbGlicmFyeShkcGx5cikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ0V4dHJhKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkod2VzYW5kZXJzb24pCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKIyBMb2FkIGludGVncmF0ZWQgZGF0YXNldHMKCmBgYHtyfQpXVC5LTy5pbnRlZ3JhdGVkIDwtIHJlYWRSRFMoIldUX0tPLmludGVncmF0ZWQuUkRTIikKRGVmYXVsdEFzc2F5KFdULktPLmludGVncmF0ZWQpIDwtICJSTkEiCmBgYAoKCmBgYHtyfQpEaW1QbG90KFdULktPLmludGVncmF0ZWQsCiAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICBncm91cC5ieSA9ICJMaW5lYWdlIiwKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBjb2xzID0gICBjKCIjY2MzOTFiIiwiI2U3ODIzYSIsIiM5Njk2OTYiLCIjMDI2YzlhIikKICAgICAgICApICsgTm9BeGVzKCkKYGBgCgpgYGB7cn0KQ1B4LmRhdGEgPC0gIHN1YnNldChXVC5LTy5pbnRlZ3JhdGVkLAogICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQgPSBMaW5lYWdlICVpbiUgYygiQ2hvcm9pZF9QbGV4dXMiKSAmIG9yaWcuaWRlbnQgJWluJSBjKCJIZW0xIiwgIkdtbmNfS08iKSkKCkRpbVBsb3QoQ1B4LmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsCiAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBjb2xzID0gIGMoIiNjYzM5MWIiLCIjMDI2YzlhIikKICAgICAgICApICsgTm9BeGVzKCkKCnJtKFdULktPLmludGVncmF0ZWQpCmdjKCkKYGBgCiMgUHNldWRvdGltZSBpbiBXVAoKYGBge3J9CldULmRhdGEgPC0gIHN1YnNldChDUHguZGF0YSwKICAgICAgICAgICAgICAgICAgIHN1YnNldCA9IG9yaWcuaWRlbnQgPT0iSGVtMSIpCmBgYAoKIyMgRXhjbHVkZSBzZXB0YWwgY2VsbHMKCmBgYHtyfQpGZWF0dXJlUGxvdChvYmplY3QgPSBXVC5kYXRhLAogICAgICAgICAgICBmZWF0dXJlcyA9IGMoIkZnZjgiLCAiRmdmMTciLCAiQWRhbXRzMTUiLCAiRmdmYnAxIiksCiAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsCiAgICAgICAgICAgIGNvbHMgPSBjKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSwKICAgICAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICAgICAgb3JkZXIgPSBUKSAmIE5vQXhlcygpICYgTm9MZWdlbmQoKQpgYGAKCmBgYHtyfQpXVC5kYXRhIDwtIEFkZE1vZHVsZVNjb3JlKFdULmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gbGlzdChjKCJGZ2Y4IiwgIkZnZjE3IiwgIkFkYW10czE1IiwgIkZnZmJwMSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY3RybCA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlNlcHR1bSIpCgpGZWF0dXJlUGxvdChvYmplY3QgPSBXVC5kYXRhLAogICAgICAgICAgICBmZWF0dXJlcyA9IGMoIlNlcHR1bTEiKSwKICAgICAgICAgICAgcHQuc2l6ZSA9IDEsCiAgICAgICAgICAgIGNvbHMgPSByZXYoYnJld2VyLnBhbCgxMCwiU3BlY3RyYWwiKSksCiAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJpbnRlZ3JhdGVkX3NwcmluZyIsCiAgICAgICAgICAgIG9yZGVyID0gVCkgJiBOb0F4ZXMoKQoKV1QuZGF0YSRTZXB0YWwucHJvZyA8LSBXVC5kYXRhJFNlcHR1bTEgPiAwCmBgYAoKCmBgYHtyfQpwMSA8LSBEaW1QbG90KFdULmRhdGEsCiAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICBncm91cC5ieSA9ICJTZXB0YWwucHJvZyIsCiAgICAgICAgcHQuc2l6ZSA9IDEpICsgTm9BeGVzKCkKCnAyIDwtIEZlYXR1cmVQbG90KG9iamVjdCA9IFdULmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzID0gYygiRmdmMTciKSwKICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwKICAgICAgICAgICAgY29scyA9IGMoImdyZXk5MCIsIGJyZXdlci5wYWwoOSwiWWxHbkJ1IikpLAogICAgICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgICAgICBvcmRlciA9IFQpICYgTm9BeGVzKCkgJiBOb0xlZ2VuZCgpCgpwMSArIHAyCmBgYAoKYGBge3J9CldULmRhdGE8LSBzdWJzZXQoV1QuZGF0YSwKICAgICAgICAgICAgICAgICAgIHN1YnNldCA9IFNlcHRhbC5wcm9nID09IEZBTFNFICYgV1QuZGF0YSRTcHJpbmdfMSA+IDEzMDApCmBgYAoKIyMgRml0IHByaW5jaXBhbCBjdXJ2ZQoKYGBge3J9ClRyYWplY3Rvcmllcy5DaFAgPC0gV1QuZGF0YUBtZXRhLmRhdGEgJT4lCiAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdCgiQmFyY29kZXMiLCAiU3ByaW5nXzEiLCAiU3ByaW5nXzIiKQoKZml0IDwtIHByaW5jaXBhbF9jdXJ2ZShhcy5tYXRyaXgoVHJhamVjdG9yaWVzLkNoUFssYygiU3ByaW5nXzEiLCAiU3ByaW5nXzIiKV0pLAogICAgICAgICAgICAgICAgICAgICAgIHNtb290aGVyPSdsb3dlc3MnLAogICAgICAgICAgICAgICAgICAgICAgIHRyYWNlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgZiA9IDAuOCwgCiAgICAgICAgICAgICAgICAgICAgICAgc3RyZXRjaD0yKQoKI1RoZSBwcmluY2lwYWwgY3VydmUgc21vb3RoZWQKQ2hQLnBjLmxpbmUgPC0gYXMuZGF0YS5mcmFtZShmaXQkc1tvcmRlcihmaXQkbGFtYmRhKSxdKSAKCiNQc2V1ZG90aW1lIHNjb3JlClRyYWplY3Rvcmllcy5DaFAkUHNldWRvdGltZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKQoKI0ludmVyc2UgdGhlIHNjb3JlIGlmIHBvc2l0aXZlIGNvcnJlbGF0aW9uIHdpdGggcHJvZ2VuaXRvciBtYXJrZXIKaWYgKGNvcihUcmFqZWN0b3JpZXMuQ2hQJFBzZXVkb3RpbWUsIFdULmRhdGFAYXNzYXlzJFNDVEBkYXRhWydIbWdhMicsIFRyYWplY3Rvcmllcy5DaFAkQmFyY29kZXNdKSA+IDApIHsKICBUcmFqZWN0b3JpZXMuQ2hQJFBzZXVkb3RpbWUgPC0gLShUcmFqZWN0b3JpZXMuQ2hQJFBzZXVkb3RpbWUgLSBtYXgoVHJhamVjdG9yaWVzLkNoUCRQc2V1ZG90aW1lKSkKfQoKV1QuZGF0YSRQc2V1ZG90aW1lIDwtIFRyYWplY3Rvcmllcy5DaFAkUHNldWRvdGltZQpgYGAKYGBge3J9CkZlYXR1cmVQbG90KG9iamVjdCA9IFdULmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzID0gIlBzZXVkb3RpbWUiLAogICAgICAgICAgICBwdC5zaXplID0gMiwKICAgICAgICAgICAgY29scyA9IHJldihjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobiA9MTAsIG5hbWUgPSAiU3BlY3RyYWwiKSkoMTAwKSksCiAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJpbnRlZ3JhdGVkX3NwcmluZyIsCiAgICAgICAgICAgIG9yZGVyID0gVCkgJiBOb0F4ZXMoKQpgYGAKCgojIFBzZXVkb3RpbWUgaW4gS08KCmBgYHtyfQpLTy5kYXRhIDwtICBzdWJzZXQoQ1B4LmRhdGEsCiAgICAgICAgICAgICAgICAgICBzdWJzZXQgPSBvcmlnLmlkZW50ID09IkdtbmNfS08iKQpgYGAKCiMjIEV4Y2x1ZGUgc2VwdGFsIGNlbGxzCgpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gS08uZGF0YSwKICAgICAgICAgICAgZmVhdHVyZXMgPSBjKCJGZ2Y4IiwgIkZnZjE3IiwgIkFkYW10czE1IiwgIkZnZmJwMSIpLAogICAgICAgICAgICBwdC5zaXplID0gMC41LAogICAgICAgICAgICBjb2xzID0gYygiZ3JleTkwIiwgYnJld2VyLnBhbCg5LCJZbEduQnUiKSksCiAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJpbnRlZ3JhdGVkX3NwcmluZyIsCiAgICAgICAgICAgIG9yZGVyID0gVCkgJiBOb0F4ZXMoKSAmIE5vTGVnZW5kKCkKYGBgCgpgYGB7cn0KS08uZGF0YSA8LSBBZGRNb2R1bGVTY29yZShLTy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gbGlzdChjKCJGZ2Y4IiwgIkZnZjE3IiwgIkFkYW10czE1IiwgIkZnZmJwMSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjdHJsID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJTZXB0dW0iKQoKRmVhdHVyZVBsb3Qob2JqZWN0ID0gS08uZGF0YSwKICAgICAgICAgICAgZmVhdHVyZXMgPSBjKCJTZXB0dW0xIiksCiAgICAgICAgICAgIHB0LnNpemUgPSAxLAogICAgICAgICAgICBjb2xzID0gcmV2KGJyZXdlci5wYWwoMTAsIlNwZWN0cmFsIikpLAogICAgICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgICAgICBvcmRlciA9IFQpICYgTm9BeGVzKCkKCktPLmRhdGEkU2VwdGFsLnByb2cgPC0gS08uZGF0YSRTZXB0dW0xID4gMApgYGAKCgpgYGB7cn0KcDEgPC0gRGltUGxvdChLTy5kYXRhLAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJpbnRlZ3JhdGVkX3NwcmluZyIsCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiU2VwdGFsLnByb2ciLAogICAgICAgICAgICAgIHB0LnNpemUgPSAxKSArIE5vQXhlcygpCgpwMiA8LSBGZWF0dXJlUGxvdChvYmplY3QgPSBLTy5kYXRhLAogICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGMoIkZnZjE3IiksCiAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsCiAgICAgICAgICAgICAgICAgIGNvbHMgPSBjKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSwKICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUKSAmIE5vQXhlcygpICYgTm9MZWdlbmQoKQoKcDEgKyBwMgpgYGAKCmBgYHtyfQpLTy5kYXRhPC0gc3Vic2V0KEtPLmRhdGEsCiAgICAgICAgICAgICAgICAgc3Vic2V0ID0gU2VwdGFsLnByb2cgPT0gRkFMU0UgJiBLTy5kYXRhJFNwcmluZ18xID4gMjAwMCkKYGBgCgojIyBGaXQgcHJpbmNpcGFsIGN1cnZlCgpgYGB7cn0KVHJhamVjdG9yaWVzLkNoUCA8LSBLTy5kYXRhQG1ldGEuZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KCJCYXJjb2RlcyIsICJTcHJpbmdfMSIsICJTcHJpbmdfMiIpCgpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChUcmFqZWN0b3JpZXMuQ2hQWyxjKCJTcHJpbmdfMSIsICJTcHJpbmdfMiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J2xvd2VzcycsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICBmID0gMC44LCAKICAgICAgICAgICAgICAgICAgICAgICBzdHJldGNoPTIpCgojVGhlIHByaW5jaXBhbCBjdXJ2ZSBzbW9vdGhlZApDaFAucGMubGluZSA8LSBhcy5kYXRhLmZyYW1lKGZpdCRzW29yZGVyKGZpdCRsYW1iZGEpLF0pIAoKI1BzZXVkb3RpbWUgc2NvcmUKVHJhamVjdG9yaWVzLkNoUCRQc2V1ZG90aW1lIDwtIGZpdCRsYW1iZGEvbWF4KGZpdCRsYW1iZGEpCgojSW52ZXJzZSB0aGUgc2NvcmUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24gd2l0aCBwcm9nZW5pdG9yIG1hcmtlcgppZiAoY29yKFRyYWplY3Rvcmllcy5DaFAkUHNldWRvdGltZSwgS08uZGF0YUBhc3NheXMkU0NUQGRhdGFbJ0htZ2EyJywgVHJhamVjdG9yaWVzLkNoUCRCYXJjb2Rlc10pID4gMCkgewogIFRyYWplY3Rvcmllcy5DaFAkUHNldWRvdGltZSA8LSAtKFRyYWplY3Rvcmllcy5DaFAkUHNldWRvdGltZSAtIG1heChUcmFqZWN0b3JpZXMuQ2hQJFBzZXVkb3RpbWUpKQp9CgpLTy5kYXRhJFBzZXVkb3RpbWUgPC0gVHJhamVjdG9yaWVzLkNoUCRQc2V1ZG90aW1lCmBgYApgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gS08uZGF0YSwKICAgICAgICAgICAgZmVhdHVyZXMgPSAiUHNldWRvdGltZSIsCiAgICAgICAgICAgIHB0LnNpemUgPSAyLAogICAgICAgICAgICBjb2xzID0gcmV2KGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbChuID0xMCwgbmFtZSA9ICJTcGVjdHJhbCIpKSgxMDApKSwKICAgICAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICAgICAgb3JkZXIgPSBUKSAmIE5vQXhlcygpCmBgYAoKIyBTdWJzZXQgdGhlIGZ1bGwgaW50ZWdyYXRlZCBkYXRhc2V0CgpgYGB7cn0KVHJhamVjdG9yaWVzIDwtIHJiaW5kKFdULmRhdGFAbWV0YS5kYXRhICU+JSBzZWxlY3QoQmFyY29kZXMsIFBzZXVkb3RpbWUpLCBLTy5kYXRhQG1ldGEuZGF0YSAlPiUgc2VsZWN0KEJhcmNvZGVzLCBQc2V1ZG90aW1lKSkKYGBgCgoKYGBge3J9CldULktPLmludGVncmF0ZWQgPC0gcmVhZFJEUygiV1RfS08uaW50ZWdyYXRlZC5SRFMiKQoKbWV0YS5kYXRhIDwtIFdULktPLmludGVncmF0ZWRAbWV0YS5kYXRhW1RyYWplY3RvcmllcyRCYXJjb2RlcyxdCm1ldGEuZGF0YSRQc2V1ZG90aW1lIDwtIFRyYWplY3RvcmllcyRQc2V1ZG90aW1lCmBgYAoKYGBge3J9CldULktPLmludGVncmF0ZWQgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IFdULktPLmludGVncmF0ZWRAYXNzYXlzJFJOQUBjb3VudHNbLCBUcmFqZWN0b3JpZXMkQmFyY29kZXNdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhLmRhdGEgPSBtZXRhLmRhdGEpCgpzcHJpbmcgPC0gYXMubWF0cml4KFdULktPLmludGVncmF0ZWRAbWV0YS5kYXRhICU+JSBzZWxlY3QoIkludGVncmF0ZWRfU3ByaW5nXzEiLCAiSW50ZWdyYXRlZF9TcHJpbmdfMiIpKQogIApXVC5LTy5pbnRlZ3JhdGVkW1siaW50ZWdyYXRlZF9zcHJpbmciXV0gPC0gQ3JlYXRlRGltUmVkdWNPYmplY3QoZW1iZWRkaW5ncyA9IHNwcmluZywga2V5ID0gIlNwcmluZ18iLCBhc3NheSA9IERlZmF1bHRBc3NheShXVC5LTy5pbnRlZ3JhdGVkKSkKYGBgCgpgYGB7cn0KcDEgPC0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICAgICAgZmVhdHVyZXMgPSAiUHNldWRvdGltZSIsCiAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsCiAgICAgICAgICAgIGNvbHMgPSByZXYoY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKG4gPTExLCBuYW1lID0gIlNwZWN0cmFsIikpKDEwMCkpLAogICAgICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgICAgICBvcmRlciA9IFQpICYgTm9BeGVzKCkKCnAyIDwtIERpbVBsb3Qob2JqZWN0ID0gV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICBncm91cC5ieSA9ICJvcmlnLmlkZW50IiwKICAgICAgICBwdC5zaXplID0gMC41LAogICAgICAgIHJlZHVjdGlvbiA9ICJpbnRlZ3JhdGVkX3NwcmluZyIsCiAgICAgICAgY29scyA9ICBjKCIjY2MzOTFiIiwgIiMwMjZjOWEiKSkgJiBOb0F4ZXMoKQoKCnAxICsgcDIKYGBgCgojIyBOb3JtYWxpemF0aW9uCgpgYGB7cn0KV1QuS08uaW50ZWdyYXRlZCA8LSBOb3JtYWxpemVEYXRhKFdULktPLmludGVncmF0ZWQsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwLCBhc3NheSA9ICJSTkEiKQpgYGAKCmBgYHtyfQpXVC5LTy5pbnRlZ3JhdGVkIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKFdULktPLmludGVncmF0ZWQsIHNlbGVjdGlvbi5tZXRob2QgPSAiZGlzcCIsIG5mZWF0dXJlcyA9IDY1MDAsIGFzc2F5ID0gIlJOQSIpCmBgYAoKIyMgUGxvdCBzb21lIGdlbmVzIGFsb25nIHBzZXVkb3RpbWUKCmBgYHtyIGZpZy5kaW09YygxNSw5KSwgd2FybmluZz1GQUxTRX0Kc291cmNlKCIuLi9GdW5jdGlvbnMvZnVuY3Rpb25zX0dlbmVUcmVuZHMuUiIpCgpQbG90LkdlbmVzLnRyZW5kKFNldXJhdC5kYXRhPSBXVC5LTy5pbnRlZ3JhdGVkLAogICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICBnZW5lcz0gYygiTmFzcCIsIlR0ciIsIkh0cjJjIiwgIkdtbmMiLCAiVHJwNzMiLCAiRm94ajEiLCAiUGlmbyIsICJDY2RjNjciKSkKYGBgCgojIFVzZSBtb25vY2xlMiB0byBtb2RlbCBnZW5lIGV4cHJlc3Npb24gYWxvbmcgY3ljbGluZyBheGlzCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJXVC5LTy5pbnRlZ3JhdGVkIildKQpnYygpCmBgYAoKIyMjIEluaXRpYWxpemUgYSBtb25vY2xlIG9iamVjdAoKYGBge3J9CiMgVHJhbnNmZXIgbWV0YWRhdGEKQW5ub3QuZGF0YSAgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEuZnJhbWUoQmFyY29kZT0gV1QuS08uaW50ZWdyYXRlZCRCYXJjb2RlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExpbmVhZ2U9IFdULktPLmludGVncmF0ZWQkTGluZWFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBzZXVkb3RpbWU9IFdULktPLmludGVncmF0ZWQkUHNldWRvdGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlPSBXVC5LTy5pbnRlZ3JhdGVkJG9yaWcuaWRlbnQpKQoKIyBUcmFuc2ZlciBjb3VudHMgZGF0YQpmZWF0dXJlLmRhdGEgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLmZyYW1lKGdlbmVfc2hvcnRfbmFtZSA9IHJvd25hbWVzKFdULktPLmludGVncmF0ZWRbWyJSTkEiXV1AY291bnRzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhXVC5LTy5pbnRlZ3JhdGVkW1siUk5BIl1dQGNvdW50cykpKQoKIyBDcmVhdGUgdGhlIENlbGxEYXRhU2V0IG9iamVjdCBpbmNsdWRpbmcgdmFyaWFibGUgZ2VuZXMgb25seQpnYm1fY2RzIDwtIG5ld0NlbGxEYXRhU2V0KFdULktPLmludGVncmF0ZWRbWyJSTkEiXV1AY291bnRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaGVub0RhdGEgPSBBbm5vdC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlRGF0YSA9IGZlYXR1cmUuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG93ZXJEZXRlY3Rpb25MaW1pdCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25GYW1pbHkgPSBuZWdiaW5vbWlhbCgpKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9CmdibV9jZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhnYm1fY2RzKQpnYm1fY2RzIDwtIGVzdGltYXRlRGlzcGVyc2lvbnMoZ2JtX2NkcykKZ2JtX2NkcyA8LSBkZXRlY3RHZW5lcyhnYm1fY2RzLCBtaW5fZXhwciA9IDAuMSkKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJXVC5LTy5pbnRlZ3JhdGVkIiwgImdibV9jZHMiKV0pCmdjKCkKYGBgCiMgUGxvdCBXVCBDUiBkeW5hbWljIGdlbmVzIGFsb25nIFdUIGFuZCBLTyB0cmFqZWN0b3JpZXMKCmBgYHtyIGNhY2hlPVRSVUV9CiMgTG9hZCBXVCBDUHggdmFyaWFibGUgZ2VuZXMgYWxvbmcgcHNldWRvdGltZQpXVC5DUHguZ2VuZXMgPC0gcmVhZC50YWJsZSgiLi4vQ2hvcm9pZFBsZXh1c190cmFqZWN0b3J5L0NoUC5HZW5lLmR5bmFtaXF1ZS5jc3YiLCBzZXAgPSAiOyIsIGhlYWRlciA9IFQpCgojIENyZWF0ZSBhIG5ldyBwc2V1ZG90aW1lIHZlY3RvciBvZiAzMDAgcG9pbnRzCm5Qb2ludHMgPC0gMTAwCgpuZXdfZGF0YSA9IGxpc3QoKQpmb3IgKEdlbm90eXBlIGluIHVuaXF1ZShXVC5LTy5pbnRlZ3JhdGVkJG9yaWcuaWRlbnQpKXsKICBuZXdfZGF0YVtbbGVuZ3RoKG5ld19kYXRhKSArIDFdXSA9IGRhdGEuZnJhbWUoUHNldWRvdGltZSA9IHNlcShtaW4oV1QuS08uaW50ZWdyYXRlZCRQc2V1ZG90aW1lKSwgbWF4KFdULktPLmludGVncmF0ZWQkUHNldWRvdGltZSksIGxlbmd0aC5vdXQgPSBuUG9pbnRzKSwgR2Vub3R5cGU9IEdlbm90eXBlKQp9CgpuZXdfZGF0YSA9IGRvLmNhbGwocmJpbmQsIG5ld19kYXRhKQoKIyBTbW9vdGggZ2VuZSBleHByZXNzaW9uCkRpZmYuY3VydmVfbWF0cml4IDwtIGdlblNtb290aEN1cnZlcyhnYm1fY2RzW1dULkNQeC5nZW5lcyRHZW5lLCBdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZW5kX2Zvcm11bGEgPSAifnNtLm5zKFBzZXVkb3RpbWUsIGRmID0gMykqR2Vub3R5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbGF0aXZlX2V4cHIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld19kYXRhID0gbmV3X2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXM9IHBhcmFsbGVsOjpkZXRlY3RDb3JlcygpIC0gMikKYGBgCgpgYGB7cn0KIyBPcmRlciB0aGUgcm93cyB1c2luZyBzZXJpYXRpb24KZHN0IDwtIGFzLmRpc3QoKDEtY29yKHNjYWxlKHQoRGlmZi5jdXJ2ZV9tYXRyaXhbLDE6MTAwXSkpLCBtZXRob2QgPSAicGVhcnNvbiIpKSkKcm93LnNlciA8LSBzZXJpYXRpb246OnNlcmlhdGUoZHN0LCBtZXRob2QgPSJSMkUiKSAjIlIyRSIgI1RTUCAjIkdXIiAiR1dfd2FyZCIKZ2VuZS5vcmRlciA8LSByb3duYW1lcyhEaWZmLmN1cnZlX21hdHJpeFssMToxMDBdW2dldF9vcmRlcihyb3cuc2VyKSxdKQoKIyBTZXQgYW5ub3RhdGlvbiBjb2xvcnMKcGFsIDwtIHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMSIpCmFubm8uY29sb3JzIDwtIGxpc3QobGluZWFnZSA9IGMoR21uY19LTz0iIzAyNmM5YSIsIEdtbmNfV1Q9IiNjYzM5MWIiKSwKICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzID0gYyhDbHVzdC4xID1wYWxbMV0gLCBDbHVzdC4yPXBhbFsyXSwgQ2x1c3QuMz1wYWxbM10sIENsdXN0LjQ9cGFsWzRdLCBDbHVzdC41PXBhbFs1XSkpCgoKcGhlYXRtYXA6OnBoZWF0bWFwKERpZmYuY3VydmVfbWF0cml4W2dlbmUub3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygyMDA6MTAxLCNLTyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE6MTAwKV0sICNXVAogICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEYsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSBXVC5DUHguZ2VuZXMgICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBkYXRhLmZyYW1lKGxpbmVhZ2UgPSByZXAoYygiR21uY19LTyIsIkdtbmNfV1QiKSwgZWFjaD0xMDApKSwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sb3JzID0gYW5uby5jb2xvcnMsCiAgICAgICAgICAgICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwKICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgZm9udHNpemVfcm93ID0gOCwKICAgICAgICAgICAgICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSAgdmlyaWRpczo6dmlyaWRpcyg5KSwKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgtMi41LDIuNSwgbGVuZ3RoLm91dCA9IDkpLAogICAgICAgICAgICAgICAgICAgbWFpbiA9ICIiKQpgYGAKCiMjIFRGIG9ubHkKCmBgYHtyfQpURnMgPC0gcmVhZC50YWJsZSgiVEYuY3N2Iiwgc2VwID0gIjsiKVssMV0KCmdlbmUub3JkZXIgPC0gZ2VuZS5vcmRlcltnZW5lLm9yZGVyICVpbiUgVEZzXQoKaGVhdG1hcC5nZW5lIDwtIHBoZWF0bWFwOjpwaGVhdG1hcChEaWZmLmN1cnZlX21hdHJpeFtnZW5lLm9yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoMjAwOjEwMSwjS08gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxOjEwMCldLCAjV1QKICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSA9ICJyb3ciLAogICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRiwKICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uX3JvdyA9IFdULkNQeC5nZW5lcyAlPiUgZHBseXI6OnNlbGVjdChHZW5lLkNsdXN0ZXJzKSwKICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IGRhdGEuZnJhbWUobGluZWFnZSA9IHJlcChjKCJHbW5jX0tPIiwiR21uY19XVCIpLCBlYWNoPTEwMCkpLAogICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sb3JzID0gYW5uby5jb2xvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2xuYW1lcyA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgZm9udHNpemVfcm93ID0gOCwKICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJfY29sb3IgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICB2aXJpZGlzOjp2aXJpZGlzKDkpLAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgtMi41LDIuNSwgbGVuZ3RoLm91dCA9IDkpLAogICAgICAgICAgICAgICAgICAgICAgIG1haW4gPSAiV1QgQ1B4IGR5bmFtaWMgZ2VuZXMgYWxvbmcgR21uY1dUIHRyYWplY3RvcmllcyIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDE1LDkpLCB3YXJuaW5nPUZBTFNFfQpzb3VyY2UoIi4uL0Z1bmN0aW9ucy9mdW5jdGlvbnNfR2VuZVRyZW5kcy5SIikKClBsb3QuR2VuZXMudHJlbmQoU2V1cmF0LmRhdGE9IFdULktPLmludGVncmF0ZWQsCiAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiR2Vub3R5cGUiLAogICAgICAgICAgICAgICAgIGdlbmVzPSBjKCJHbW5jIiwgIlRycDczIiwgIkUyZjciLCAiRm94ajEiLCAiSXJ4NSIsICJDYXJoc3AxIiwgIkZveGEyIiwgIlNveDkiLCAiUG91M2YyIiwgIk15YiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICJQbGFnbDEiLCAiUHJkbTE2IiwgIkFlYnAxIikpCmBgYAoKIyBLTyBkeW5hbWljIGdlbmVzIGFsb25nIHBzZXVkb3RpbWUKCiMjIEZpbmQgREVHIGluIHRoZSBLTwoKYGBge3IgY2FjaGU9VFJVRX0KS08ucERhdGEgPC0gcERhdGEoZ2JtX2NkcykgJT4lIHN1YnNldChHZW5vdHlwZSA9PSAiR21uY19LTyIpCgpwc2V1ZG8ubWF0dXJhdGlvbi5kaWZmIDwtIGRpZmZlcmVudGlhbEdlbmVUZXN0KGdibV9jZHNbV1QuS08uaW50ZWdyYXRlZFtbIlJOQSJdXUB2YXIuZmVhdHVyZXMsIEtPLnBEYXRhJEJhcmNvZGVdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGxNb2RlbEZvcm11bGFTdHIgPSAifnNtLm5zKFBzZXVkb3RpbWUsIGRmID0gMykiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSBwYXJhbGxlbDo6ZGV0ZWN0Q29yZXMoKSAtIDIpCgojIEZpbHRlciBnZW5lcyBiYXNlZCBvbiBGRFIKcHNldWRvLm1hdHVyYXRpb24uZGlmZi5maWx0ZXJlZCA8LSBwc2V1ZG8ubWF0dXJhdGlvbi5kaWZmICU+JSBmaWx0ZXIocXZhbCA8IDFlLTMwKQpgYGAKCmBgYHtyIGNhY2hlPVRSVUV9CiMgQ3JlYXRlIGEgbmV3IHBzZXVkby1EViB2ZWN0b3Igb2YgMzAwIHBvaW50cwpuUG9pbnRzIDwtIDEwMAoKbmV3X2RhdGEgPSBsaXN0KCkKZm9yIChMaW5lYWdlIGluIHVuaXF1ZShLTy5wRGF0YSRMaW5lYWdlKSl7CiAgbmV3X2RhdGFbW2xlbmd0aChuZXdfZGF0YSkgKyAxXV0gPSBkYXRhLmZyYW1lKFBzZXVkb3RpbWUgPSBzZXEobWluKEtPLnBEYXRhJFBzZXVkb3RpbWUpLCBtYXgoS08ucERhdGEkUHNldWRvdGltZSksIGxlbmd0aC5vdXQgPSBuUG9pbnRzKSwgTGluZWFnZT1MaW5lYWdlKQp9CgpuZXdfZGF0YSA9IGRvLmNhbGwocmJpbmQsIG5ld19kYXRhKQoKIyBTbW9vdGggZ2VuZSBleHByZXNzaW9uCkRpZmYuY3VydmVfbWF0cml4IDwtIGdlblNtb290aEN1cnZlcyhnYm1fY2RzW2FzLmNoYXJhY3Rlcihwc2V1ZG8ubWF0dXJhdGlvbi5kaWZmLmZpbHRlcmVkJGdlbmVfc2hvcnRfbmFtZSksIEtPLnBEYXRhJEJhcmNvZGVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZW5kX2Zvcm11bGEgPSAifnNtLm5zKFBzZXVkb3RpbWUsIGRmID0gMykiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbGF0aXZlX2V4cHIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld19kYXRhID0gbmV3X2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXM9IHBhcmFsbGVsOjpkZXRlY3RDb3JlcygpIC0gMikKYGBgCgpgYGB7cn0KUHNldWRvdGltZS5nZW5lcy5jbHVzdGVycyA8LSBjbHVzdGVyOjpwYW0oYXMuZGlzdCgoMSAtIGNvcihNYXRyaXg6OnQoRGlmZi5jdXJ2ZV9tYXRyaXgpLG1ldGhvZCA9ICJwZWFyc29uIikpKSwgaz0gNSkKCktPX0NQeF9HZW5lLmR5bmFtaXF1ZSA8LSBkYXRhLmZyYW1lKEdlbmU9IG5hbWVzKFBzZXVkb3RpbWUuZ2VuZXMuY2x1c3RlcnMkY2x1c3RlcmluZyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXYXZlcz0gUHNldWRvdGltZS5nZW5lcy5jbHVzdGVycyRjbHVzdGVyaW5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2VuZS5DbHVzdGVycyA9IFBzZXVkb3RpbWUuZ2VuZXMuY2x1c3RlcnMkY2x1c3RlcmluZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHEudmFsID0gcHNldWRvLm1hdHVyYXRpb24uZGlmZi5maWx0ZXJlZCRxdmFsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSBhcnJhbmdlKEdlbmUuQ2x1c3RlcnMpCgpyb3cubmFtZXMoS09fQ1B4X0dlbmUuZHluYW1pcXVlKSA8LSBLT19DUHhfR2VuZS5keW5hbWlxdWUkR2VuZQpLT19DUHhfR2VuZS5keW5hbWlxdWUkR2VuZS5DbHVzdGVycyA8LSBwYXN0ZTAoIkNsdXN0LiIsIEtPX0NQeF9HZW5lLmR5bmFtaXF1ZSRHZW5lLkNsdXN0ZXJzKQoKd3JpdGUudGFibGUoS09fQ1B4X0dlbmUuZHluYW1pcXVlLCAiS09fQ1B4X2R5bmFtaWNfZ2VuZXMuY3N2Iiwgc2VwID0gIjsiLCBxdW90ZSA9IEYsIHJvdy5uYW1lcyA9IEYpCmBgYAoKYGBge3J9CiMgT3JkZXIgdGhlIHJvd3MgdXNpbmcgc2VyaWF0aW9uCmRzdCA8LSBhcy5kaXN0KCgxLWNvcihzY2FsZSh0KERpZmYuY3VydmVfbWF0cml4KSksIG1ldGhvZCA9ICJwZWFyc29uIikpKQpyb3cuc2VyIDwtIHNlcmlhdGlvbjo6c2VyaWF0ZShkc3QsIG1ldGhvZCA9IlIyRSIpICMiUjJFIiAjVFNQICMiR1ciICJHV193YXJkIgpnZW5lLm9yZGVyIDwtIHJldihyb3duYW1lcyhEaWZmLmN1cnZlX21hdHJpeFtnZXRfb3JkZXIocm93LnNlciksXSkpCgojIFNldCBhbm5vdGF0aW9uIGNvbG9ycwpwYWwgPC0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcxIikKYW5uby5jb2xvcnMgPC0gbGlzdChHZW5lLkNsdXN0ZXJzID0gYyhDbHVzdC4xID1wYWxbMV0gLCBDbHVzdC4yPXBhbFsyXSwgQ2x1c3QuMz1wYWxbM10sIENsdXN0LjQ9cGFsWzRdLCBDbHVzdC41PXBhbFs1XSkpCgoKcGhlYXRtYXA6OnBoZWF0bWFwKERpZmYuY3VydmVfbWF0cml4W2dlbmUub3JkZXIsXSwKICAgICAgICAgICAgICAgICAgIHNjYWxlID0gInJvdyIsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBGLAogICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRiwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fcm93ID0gS09fQ1B4X0dlbmUuZHluYW1pcXVlICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vLmNvbG9ycywKICAgICAgICAgICAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IEYsCiAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3cgPSA4LAogICAgICAgICAgICAgICAgICAgYm9yZGVyX2NvbG9yID0gTkEsCiAgICAgICAgICAgICAgICAgICBjb2xvciA9ICB2aXJpZGlzOjp2aXJpZGlzKDkpLAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKC0yLjUsMi41LCBsZW5ndGgub3V0ID0gOSksCiAgICAgICAgICAgICAgICAgICBtYWluID0gIiIpCmBgYAoKIyBTZXNzaW9uIEluZm8KCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=