Load Telley et al 2019 data and order cells along pseudo-maturation axis

To define temporally versus spatially regulated genes, we used dorso-pallial apical progenitors scRNAseq data obtained by facs sorting 1H after flashtag injection from :

Telley L, Agirman G et al. Temporal patterning of apical progenitors and their daughter neurons in the developing neocortex. Science 2019 May 10;364(6440).

The R script used for the preprocessing of the data can be find here

## 
## E12.1H E13.1H E14.1H E15.1H 
##    178    202    124    221

Run PCA

## Parameters used in latest PCA calculation run on: 2020-11-30 11:03:06
## =============================================================================
## PCs computed    Genes used in calculation    PCs Scaled by Variance Explained
##     10                  815                                TRUE
## -----------------------------------------------------------------------------
## rev.pca 
##  FALSE
## -----------------------------------------------------------------------------
## Full gene list can be accessed using 
##  GetCalcParam(object = object, calculation = "RunPCA", parameter = "pc.genes")

Fit the principal curve over the first 6 PCs

## Starting curve---distance^2: 20282698
## Iteration 1---distance^2: 26243.03
## Iteration 2---distance^2: 25451.13
## Iteration 3---distance^2: 24542.64
## Iteration 4---distance^2: 23847.34
## Iteration 5---distance^2: 23528.5
## Iteration 6---distance^2: 23464.76
## Iteration 7---distance^2: 23435.29
## Iteration 8---distance^2: 23404.87
## Iteration 9---distance^2: 23372.66
## Iteration 10---distance^2: 23359.4

Load E12 dataset

Predict E12 AP pseudo-maturation score with a regression model trainned on Telley 2019 dataset

Train a random forest regression model on Telley 2019 data

We reoptimize the regression model by selecting the 100 most importante features of the first model

Decomposition of spatial vs. temoral aspect of progenitor cells identity

Smooth expression over pseudo-DV and pseudo maturation

Find all variable genes along the pseudo-DV axis in E12 AP

Find all variable genes along the pseudo-maturation axis in Telley 2019 APs

Identify temporal genes as highly anti-correlating between the two datasets

Extract E12 spatial domain genes which do not show E12/E15 difference in Telley data

Manuscript Fig. 6G

Manuscript Fig. 6G

Session Info

## [1] "30 novembre, 2020, 11,09"
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## 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    parallel  stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] RColorBrewer_1.1-2  patchwork_0.0.1     ggExtra_0.9        
##  [4] gridExtra_2.3       pheatmap_1.0.12     dplyr_0.8.3        
##  [7] monocle_2.14.0      DDRTree_0.1.5       irlba_2.3.3        
## [10] VGAM_1.1-2          Biobase_2.46.0      BiocGenerics_0.32.0
## [13] caret_6.0-84        lattice_0.20-41     princurve_2.1.4    
## [16] Seurat_2.3.4        Matrix_1.2-17       cowplot_1.0.0      
## [19] ggplot2_3.2.1      
## 
## loaded via a namespace (and not attached):
##   [1] snow_0.4-3           backports_1.1.5      Hmisc_4.3-0         
##   [4] plyr_1.8.4           igraph_1.2.5         lazyeval_0.2.2      
##   [7] densityClust_0.3     fastICA_1.2-2        digest_0.6.25       
##  [10] foreach_1.4.7        htmltools_0.5.0      viridis_0.5.1       
##  [13] lars_1.2             gdata_2.18.0         magrittr_1.5        
##  [16] checkmate_1.9.4      cluster_2.1.0        gclus_1.3.2         
##  [19] mixtools_1.1.0       ROCR_1.0-7           limma_3.42.0        
##  [22] recipes_0.1.7        gower_0.2.1          matrixStats_0.55.0  
##  [25] docopt_0.6.1         R.utils_2.9.0        colorspace_1.4-1    
##  [28] ggrepel_0.8.1        xfun_0.18            sparsesvd_0.2       
##  [31] crayon_1.3.4         jsonlite_1.7.0       zeallot_0.1.0       
##  [34] survival_2.44-1.1    zoo_1.8-6            iterators_1.0.12    
##  [37] ape_5.3              glue_1.4.1           registry_0.5-1      
##  [40] gtable_0.3.0         ipred_0.9-9          kernlab_0.9-29      
##  [43] prabclus_2.3-1       DEoptimR_1.0-8       scales_1.1.0        
##  [46] bibtex_0.4.2         miniUI_0.1.1.1       Rcpp_1.0.5          
##  [49] metap_1.1            dtw_1.21-3           xtable_1.8-4        
##  [52] viridisLite_0.3.0    htmlTable_1.13.2     reticulate_1.13     
##  [55] foreign_0.8-72       bit_4.0.4            proxy_0.4-23        
##  [58] mclust_5.4.5         SDMTools_1.1-221.1   Formula_1.2-3       
##  [61] tsne_0.1-3           lava_1.6.6           prodlim_2019.11.13  
##  [64] htmlwidgets_1.5.1    httr_1.4.1           FNN_1.1.3           
##  [67] gplots_3.0.1.1       fpc_2.2-3            acepack_1.4.1       
##  [70] modeltools_0.2-22    ica_1.0-2            farver_2.0.1        
##  [73] pkgconfig_2.0.3      R.methodsS3_1.7.1    flexmix_2.3-15      
##  [76] nnet_7.3-14          labeling_0.3         later_1.0.0         
##  [79] tidyselect_0.2.5     rlang_0.4.7          reshape2_1.4.3      
##  [82] munsell_0.5.0        tools_3.6.3          generics_0.0.2      
##  [85] ranger_0.11.2        ggridges_0.5.1       fastmap_1.0.1       
##  [88] evaluate_0.14        stringr_1.4.0        yaml_2.2.1          
##  [91] npsurv_0.4-0         ModelMetrics_1.2.2   knitr_1.26          
##  [94] bit64_4.0.2          fitdistrplus_1.0-14  robustbase_0.93-5   
##  [97] caTools_1.17.1.2     purrr_0.3.3          RANN_2.6.1          
## [100] dendextend_1.12.0    pbapply_1.4-2        nlme_3.1-141        
## [103] mime_0.7             slam_0.1-46          R.oo_1.23.0         
## [106] hdf5r_1.3.2.9000     compiler_3.6.3       rstudioapi_0.11     
## [109] png_0.1-7            e1071_1.7-2          lsei_1.2-0          
## [112] tibble_2.1.3         stringi_1.4.6        highr_0.8           
## [115] HSMMSingleCell_1.6.0 vctrs_0.2.0          pillar_1.4.2        
## [118] lifecycle_0.1.0      combinat_0.0-8       Rdpack_0.11-0       
## [121] lmtest_0.9-37        data.table_1.12.6    bitops_1.0-6        
## [124] seriation_1.2-9      gbRd_0.4-11          httpuv_1.5.2        
## [127] R6_2.4.1             latticeExtra_0.6-28  TSP_1.1-10          
## [130] promises_1.1.0       KernSmooth_2.23-15   codetools_0.2-16    
## [133] MASS_7.3-53          gtools_3.8.1         assertthat_0.2.1    
## [136] withr_2.1.2          qlcMatrix_0.9.7      diptest_0.75-7      
## [139] doSNOW_1.0.18        grid_3.6.3           rpart_4.1-15        
## [142] timeDate_3043.102    tidyr_1.0.0          class_7.3-17        
## [145] rmarkdown_2.5        segmented_1.0-0      Rtsne_0.15          
## [148] shiny_1.4.0          lubridate_1.7.4      base64enc_0.1-3

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

LS0tCnRpdGxlOiAiVGVtcG9yYWwgYW5kIHNwYXRpYWwgYXNwZWN0cyBvZiBwcm9nZW5pdG9ycyBpZGVudGl0eSIKYXV0aG9yOgogICAtIE1hdHRoaWV1IE1vcmVhdV5bSW5zdGl0dXRlIG9mIFBzeWNoaWF0cnkgYW5kIE5ldXJvc2NpZW5jZSBvZiBQYXJpcywgSU5TRVJNIFUxMjY2LCA3NTAxNCwgUGFyaXMsIEZyYW5jZSwgbWF0dGhpZXUubW9yZWF1QGluc2VybS5mcl0gWyFbXShodHRwczovL29yY2lkLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL2ltYWdlcy9vcmNpZF8xNngxNi5wbmcpXShodHRwczovL29yY2lkLm9yZy8wMDAwLTAwMDItMjU5Mi0yMzczKQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGRmX3ByaW50OiB0aWJibGUKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgaW5jbHVkZXM6CiAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwotLS0KCmBgYHtjc3MsIGVjaG89RkFMU0V9CmgxIHsKICBmb250LXNpemU6IDM0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjZTY0ZDAwOwogIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQpoMS50aXRsZSB7CiAgZm9udC1zaXplOiA0MHB4OwogIG1hcmdpbi10b3A6IDJyZW07CiAgbWFyZ2luLWJvdHRvbTogMXJlbTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgyIHsKICBmb250LXNpemU6IDMwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgzIHsKICBmb250LXNpemU6IDI0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg0IHsKICBmb250LXNpemU6IDIwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg1IHsKICBmb250LXNpemU6IDE4cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cgouc2Nyb2xsLTEwMCB7CiAgbWF4LWhlaWdodDogMjAwcHg7CiAgb3ZlcmZsb3cteTogYXV0bzsKICBiYWNrZ3JvdW5kLWNvbG9yOiBpbmhlcml0Owp9CgpwIHsKICBmb250LXNpemU6IDE2cHg7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcuYWxpZ24gPSAnY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgojIExvYWQgbGlicmFyaWVzCgpgYGB7ciB9CiMgTG9hZCBsaWJyYXJ5CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KHByaW5jdXJ2ZSkKbGlicmFyeShjYXJldCkKbGlicmFyeShtb25vY2xlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKI1NldCBnZ3Bsb3QgdGhlbWUgYXMgY2xhc3NpYwp0aGVtZV9zZXQodGhlbWVfY2xhc3NpYygpKQpgYGAKCiMgTG9hZCBUZWxsZXkgZXQgYWwgMjAxOSBkYXRhIGFuZCBvcmRlciBjZWxscyBhbG9uZyBwc2V1ZG8tbWF0dXJhdGlvbiBheGlzCgpUbyBkZWZpbmUgdGVtcG9yYWxseSB2ZXJzdXMgc3BhdGlhbGx5IHJlZ3VsYXRlZCBnZW5lcywgd2UgdXNlZCAqKmRvcnNvLXBhbGxpYWwgYXBpY2FsIHByb2dlbml0b3JzKiogc2NSTkFzZXEgZGF0YSBvYnRhaW5lZCBieSBmYWNzIHNvcnRpbmcgMUggYWZ0ZXIgZmxhc2h0YWcgaW5qZWN0aW9uIGZyb20gOgoKPiBUZWxsZXkgTCwgQWdpcm1hbiBHICpldCBhbC4qICoqVGVtcG9yYWwgcGF0dGVybmluZyBvZiBhcGljYWwgcHJvZ2VuaXRvcnMgYW5kIHRoZWlyIGRhdWdodGVyIG5ldXJvbnMgaW4gdGhlIGRldmVsb3BpbmcgbmVvY29ydGV4LioqIFtTY2llbmNlIDIwMTkgTWF5IDEwOzM2NCg2NDQwKS5dKGh0dHBzOi8vc2NpZW5jZS5zY2llbmNlbWFnLm9yZy9jb250ZW50LzM2NC82NDQwL2VhYXYyNTIyLmxvbmcpCgoKPiBUaGUgUiBzY3JpcHQgdXNlZCBmb3IgdGhlIHByZXByb2Nlc3Npbmcgb2YgdGhlIGRhdGEgY2FuIGJlIGZpbmQgW2hlcmVdKGh0dHBzOi8vbWF0dGhpZXV4bW9yZWF1LmdpdGh1Yi5pby9FYXJseVBhbGxpYWxOZXVyb2dlbmVzaXMvaHRtbC1SZXBvcnRzL1RlbGxleTIwMTlQcmVwcm9jZXNzaW5nLmh0bWwpCgpgYGB7cn0KIyBMb2FkIHRoZSBmdWxsIGFubm90YXRlZCBkYXRhc2V0ClRlbGxleS5kYXRhIDwtIHJlYWRSRFMoIi4vVGVsbGV5MjAxOWRhdGEvVGVsbGV5MjAxOS5SRFMiKQpUZWxsZXkuZGF0YSA8LSBTZXRBbGxJZGVudChUZWxsZXkuZGF0YSwgaWQgPSAib3JpZy5pZGVudCIpCgp0YWJsZShUZWxsZXkuZGF0YUBpZGVudCkKYGBgCgojIyBSdW4gUENBCgpgYGB7cn0KIyBTZWxlY3QgYWxsIERFRyBiZXR3ZWVuIHNhbXBsaW5nIGRheXMgYXMgaW5wdXQgdG8gUENBCkFsbG1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnMob2JqZWN0ID0gVGVsbGV5LmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLnBjdCA9IDAuMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dmYy50aHJlc2hvbGQgPSAwLjYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbnQuYmFyID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmx5LnBvcyA9IFQpCgpERS5nZW5lcyA8LSB1bmlxdWUoQWxsbWFya2VycyRnZW5lKQoKIyBQQ0Egd2l0aCBTZXVyYXQKVGVsbGV5LmRhdGEgPC0gUnVuUENBKG9iamVjdCA9IFRlbGxleS5kYXRhLAogICAgICAgICAgICAgICAgICBwY3MuY29tcHV0ZSA9IDEwLAogICAgICAgICAgICAgICAgICBwYy5nZW5lcyA9IERFLmdlbmVzLAogICAgICAgICAgICAgICAgICBkby5wcmludCA9IEYsCiAgICAgICAgICAgICAgICAgIHBjcy5wcmludCA9IDEsCiAgICAgICAgICAgICAgICAgIGdlbmVzLnByaW50ID0gMSwKICAgICAgICAgICAgICAgICAgd2VpZ2h0LmJ5LnZhcj1UKQoKUHJpbnRQQ0FQYXJhbXMoVGVsbGV5LmRhdGEpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CiMgU2VsZWN0IHBjcyBieSAlIHZhcmlhbmNlIGV4cGxhaW5lZAplaWdzIDwtIChUZWxsZXkuZGF0YUBkciRwY2FAc2RldileMgpQZXJjZW50VkFyIDwtIGRhdGEuZnJhbWUoUGVyY2VudFZBciA9IGVpZ3MqMTAwIC8gc3VtKGVpZ3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgUENzID0gMTpsZW5ndGgoZWlncykpCgpnZ3Bsb3QoUGVyY2VudFZBcixhZXMoeD0gYXMuZmFjdG9yKFBDcykseT1QZXJjZW50VkFyKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1LGxpbmV0eXBlID0gMiwgY29sb3VyPSJyZWQiKQpgYGAKCmBgYHtyfQojIEtlZXAgb25seSBQQ3MgZXhwbGFpbmluZyA+IDUlIG9mIHRoZSB2YXJpYW5jZSBvdmVyIHRoZSAxMCBmaXJzdApQQ3MgPC0gUGVyY2VudFZBciAlPiUgZmlsdGVyKFBlcmNlbnRWQXIgPiA1KSAlPiUgcHVsbChQQ3MpCmBgYAoKCiMjIEZpdCB0aGUgcHJpbmNpcGFsIGN1cnZlIG92ZXIgdGhlIGZpcnN0IDYgUENzCgpgYGB7cn0KZGF0YSA8LSBhcy5kYXRhLmZyYW1lKFRlbGxleS5kYXRhQGRyJHBjYUBjZWxsLmVtYmVkZGluZ3NbLFBDc10pCgpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChkYXRhWyxQQ3NdKSwKICAgICAgICAgICAgICAgICAgICAgICBzbW9vdGhlcj0nbG93ZXNzJywKICAgICAgICAgICAgICAgICAgICAgICB0cmFjZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIGYgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJldGNoPTApCmBgYAoKYGBge3J9ClBzZXVkb01hdHVyYXRpb24uc2NvcmUgPC0gZml0JGxhbWJkYS9tYXgoZml0JGxhbWJkYSkKcGMubGluZSA8LSBhcy5kYXRhLmZyYW1lKGZpdCRzW29yZGVyKGZpdCRsYW1iZGEpLF0pCgpkYXRhJENsdXN0ZXIgPC0gVGVsbGV5LmRhdGFAbWV0YS5kYXRhJG9yaWcuaWRlbnQKZGF0YSRQc2V1ZG9NYXR1cmF0aW9uLnNjb3JlIDwtIFBzZXVkb01hdHVyYXRpb24uc2NvcmUKClRlbGxleS5kYXRhQG1ldGEuZGF0YSRQc2V1ZG9NYXR1cmF0aW9uLnNjb3JlIDwtIFBzZXVkb01hdHVyYXRpb24uc2NvcmUKYGBgCgpgYGB7ciBmaWcuZGltPWMoMTIsIDQpfQojIFBsb3QgdGhlIHByaW5jaXBhbCBjdXJ2ZQpwMSA8LSBnZ3Bsb3QoZGF0YSwgYWVzKFBDMSwgUEMyKSkgKyAKICAgICAgZ2VvbV9wb2ludChhZXMoY29sb3I9Q2x1c3RlciksIHNpemU9Mywgc2hhcGU9MTYpICsKICAgICAgZ2VvbV9saW5lKGRhdGE9cGMubGluZSwgY29sb3I9J3JlZCcsIHNpemU9MC43NykgKwogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiNiZGQ4ZWYiLCAiIzZkYjhlMiIsICIjMzU3ZWJjIiwgIiMxYzQ4OTYiKSkKCiMgUGxvdCBwc2V1ZG8tbWF0dXJhdGlvbiBzY29yZQpjb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbChuID0xMSwgbmFtZSA9ICJTcGVjdHJhbCIpKSgxMDApCgpwMiA8LSBnZ3Bsb3QoZGF0YSwgYWVzKFBDMSwgUEMyKSkgKwogICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPVBzZXVkb01hdHVyYXRpb24uc2NvcmUpLCBzaXplPTMsIHNoYXBlPTE2KSArIAogICAgIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzPXJldihjb2xzKSwgbmFtZT0nU3BldWRvdGltZSBzY29yZScpICsKICAgICBnZW9tX2xpbmUoZGF0YT1wYy5saW5lLCBjb2xvcj0ncmVkJywgc2l6ZT0wLjc3KQoKcDEgKyBwMgpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojIFBsb3QgZGVuc2l0eSBvbiBzcGV1ZG90aW1lCmdncGxvdChkYXRhPWRhdGEsIGFlcyh4PVBzZXVkb01hdHVyYXRpb24uc2NvcmUsZmlsbD1DbHVzdGVyKSkgKwogICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI2JkZDhlZiIsICIjNmRiOGUyIiwgIiMzNTdlYmMiLCAiIzFjNDg5NiIpKSArCiAgIGdlb21fZGVuc2l0eShhbHBoYT0uNCkgCmBgYAoKYGBge3J9CnJtKGxpc3Q9bHMoKVshbHMoKSAlaW4lICJUZWxsZXkuZGF0YSJdKQpgYGAKCiMgTG9hZCBFMTIgZGF0YXNldAoKYGBge3J9CkUxMi5BUC5kYXRhIDwtIHJlYWRSRFMoIi4vQVAuZGF0YS5SRFMiKQpgYGAKCiMjIEV4dHJhY3QgcGFsbGlhbCBwcm9nZW5pdG9ycwoKYGBge3J9CiMgRmlsdGVyIHN1YnBhbGxpYWwgcHJvZ2VuaXRvcnMKQVAuaWRlbnQgPC0gdW5pcXVlKEUxMi5BUC5kYXRhQGlkZW50KQpFMTIuQVAuZGF0YSA8LSAgU3Vic2V0RGF0YShFMTIuQVAuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC51c2UgPSBncmVwKCJTdWIiLCBBUC5pZGVudCwgdmFsdWUgPSBULCBpbnZlcnQgPSBUKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQucmF3ID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICBkby5jbGVhbiA9IEYpCgojIFJlc2V0IHRoZSBwc2V1ZG8tRFYgc2NvcmUgdG8gWzAsMV0Kc2NvcmUgPC0gRTEyLkFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZQpFMTIuQVAuZGF0YUBtZXRhLmRhdGEkRG9yc29WZW50cmFsLlNjb3JlIDwtIChzY29yZSAtIG1pbihzY29yZSkpIC8gKG1heChzY29yZSkgLSBtaW4oc2NvcmUpKQpgYGAKCgpgYGB7ciBmaWcuZGltPWMoMTIsIDQpfQpwMSA8LSBEaW1QbG90KEUxMi5BUC5kYXRhLAogICAgICAgICAgICAgICBncm91cC5ieSA9ICJEb21haW5lIiwKICAgICAgICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgICAgICAgIGRpbS4yID0gMiwKICAgICAgICAgICAgICAgZG8ubGFiZWw9RiwKICAgICAgICAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgICAgICAgIGRvLnJldHVybiA9IFQsCiAgICAgICAgICAgICAgIGNvbHMudXNlID0gdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjRTQ2QjZCIikpKQoKCmRhdGEgPC0gZGF0YS5mcmFtZShzcHJpbmcxID0gRTEyLkFQLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1ssMV0sCiAgICAgICAgICAgICAgICAgICBzcHJpbmcyID0gRTEyLkFQLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1ssMl0sCiAgICAgICAgICAgICAgICAgICBEb3Jzb1ZlbnRyYWwuU2NvcmUgPSBFMTIuQVAuZGF0YUBtZXRhLmRhdGEkRG9yc29WZW50cmFsLlNjb3JlKQoKY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobiA9MTEsIG5hbWUgPSAiU3BlY3RyYWwiKSkoMTAwKQpwMiA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHNwcmluZzEsIHNwcmluZzIpKSArIAogICAgICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Eb3Jzb1ZlbnRyYWwuU2NvcmUpLCBzaXplPTIsIHNoYXBlPTE2KSAgKyAKICAgICAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnM9cmV2KGNvbHMpLCBuYW1lPSdTcGV1ZG90aW1lIHNjb3JlJykKCnAxICsgcDIKYGBgCgojIyBGaWx0ZXIsIG5vcm1hbGl6ZSBhbmQgc2NhbGUgdGhlIGV4cHJlc3Npb24gbWF0cml4CgpgYGB7cn0KIyBSZW1vdmUgbm9uIGVwcmVzc2VkIGdlbmVzCm51bS5jZWxscyA8LSBNYXRyaXg6OnJvd1N1bXMoRTEyLkFQLmRhdGFAZGF0YSA+IDApCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMjApXSkKRTEyLkFQLmRhdGFAcmF3LmRhdGEgPC0gRTEyLkFQLmRhdGFAcmF3LmRhdGFbZ2VuZXMudXNlLCBdCkUxMi5BUC5kYXRhQGRhdGEgPC0gRTEyLkFQLmRhdGFAZGF0YVtnZW5lcy51c2UsIF0KCiMgTm9ybWFsaXplIHRoZSBjb3VudHMgbWF0cml4CkUxMi5BUC5kYXRhIDwtIE5vcm1hbGl6ZURhdGEob2JqZWN0ID0gRTEyLkFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLmZhY3RvciA9IHJvdW5kKG1lZGlhbihFMTIuQVAuZGF0YUBtZXRhLmRhdGEkblVNSSkpLCBkaXNwbGF5LnByb2dyZXNzID0gRikKCiMgU2NhbGUgZXhwcmVzc2lvbiBtYXRyaXgKRTEyLkFQLmRhdGEgPC0gU2NhbGVEYXRhKG9iamVjdCA9IEUxMi5BUC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgdmFycy50by5yZWdyZXNzID0gYygiQ0MuRGlmZmVyZW5jZSIsICJwZXJjZW50LnJpYm8iICwiblVNSSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCgoKIyBGaW5kIG1vc3QgdmFyaWFibGUgZ2VuZXMKRTEyLkFQLmRhdGEgPC0gRmluZFZhcmlhYmxlR2VuZXMob2JqZWN0ID0gRTEyLkFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Lmxvdy5jdXRvZmYgPSAwLjAxMjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHguaGlnaC5jdXRvZmYgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5LmN1dG9mZiA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnBsb3QgPSBGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gRikKbGVuZ3RoKEUxMi5BUC5kYXRhQHZhci5nZW5lcykKCmBgYAoKYGBge3J9CnJtKGxpc3Q9bHMoKVshbHMoKSAlaW4lIGMoIkUxMi5BUC5kYXRhIiwiVGVsbGV5LmRhdGEiKV0pCmBgYAoKIyBQcmVkaWN0IEUxMiBBUCBwc2V1ZG8tbWF0dXJhdGlvbiBzY29yZSB3aXRoIGEgcmVncmVzc2lvbiBtb2RlbCB0cmFpbm5lZCBvbiBUZWxsZXkgMjAxOSBkYXRhc2V0CgojIyBUcmFpbiBhIHJhbmRvbSBmb3Jlc3QgcmVncmVzc2lvbiBtb2RlbCBvbiBUZWxsZXkgMjAxOSBkYXRhCgpgYGB7cn0KIyBXZSB0cmFpbmVkIHRoZSBtb2RlbCB1c2luZyBvbmx5IGdlbmVzIGZvdW5kIHRvIGJlIGhpZ2hseSB2YXJpYWJsZSBpbiBvdXIgRTEyIGRhdGFzZXQKbW9kZWwuZGF0YSA8LSBkYXRhLmZyYW1lKFBzZXVkb01hdHVyYXRpb24uc2NvcmUgPSBUZWxsZXkuZGF0YUBtZXRhLmRhdGEkUHNldWRvTWF0dXJhdGlvbi5zY29yZSkKCmdlbmVzIDwtIHQoVGVsbGV5LmRhdGFAc2NhbGUuZGF0YVtyb3duYW1lcyhUZWxsZXkuZGF0YUBzY2FsZS5kYXRhKSAlaW4lIEUxMi5BUC5kYXRhQHZhci5nZW5lcyxdKQpnZW5lcyA8LSBhcy5kYXRhLmZyYW1lKGFzLm1hdHJpeChnZW5lcykpCm1vZGVsLmRhdGEgPC0gY2JpbmQobW9kZWwuZGF0YSxnZW5lcykKCiMgV2UgZGlkIG5vdCBwZXJmb3JtIGNyb3NzLXZhbGlkYXRpbiBidXQgcmVsaWVkIG9uIHRoZSBPdXQgT2YgQmFnIGVycm9yCnRyY3RybCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0gIm5vbmUiKQpgYGAKCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNCkKCiMgVHJhaW4gdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwKVGVsbGV5Lm1vZGVsIDwtIHRyYWluKFBzZXVkb01hdHVyYXRpb24uc2NvcmV+LiwgCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbW9kZWwuZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicmFuZ2VyIiwKICAgICAgICAgICAgICAgICAgICAgIHRyQ29udHJvbD10cmN0cmwsCiAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRhbmNlPSJwZXJtdXRhdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgdHVuZUdyaWQgPSBkYXRhLmZyYW1lKG10cnk9NTAsIG1pbi5ub2RlLnNpemUgPSA1LCBzcGxpdHJ1bGU9InZhcmlhbmNlIikpCmBgYAoKV2UgcmVvcHRpbWl6ZSB0aGUgcmVncmVzc2lvbiBtb2RlbCBieSBzZWxlY3RpbmcgdGhlIDEwMCBtb3N0IGltcG9ydGFudGUgZmVhdHVyZXMgb2YgdGhlIGZpcnN0IG1vZGVsCgpgYGB7cn0KIyBTZWxlY3QgdGhlIHRvcCAxMDAgaW1wb3J0YW50ZSBmZWF0dXJlcwpGZWF0dXJlSW1wb3J0YW5jZSA8LSBzb3J0KFRlbGxleS5tb2RlbCRmaW5hbE1vZGVsJHZhcmlhYmxlLmltcG9ydGFuY2UsIGRlY3JlYXNpbmcgPSBUKQpTZWxlY3RlZEZlYXR1cmVzIDwtIG5hbWVzKEZlYXR1cmVJbXBvcnRhbmNlWzE6MTAwXSkKCiMgUmUtdHJhaW4gdGhlIG1vZGVsIHdpdGggdGhlIHJlc3RyaWN0ZWQgZmVhdHVyZXMKVGVsbGV5Lm1vZGVsIDwtIHRyYWluKFBzZXVkb01hdHVyYXRpb24uc2NvcmV+LiwgCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbW9kZWwuZGF0YVssY29sbmFtZXMobW9kZWwuZGF0YSkgJWluJSBjKFNlbGVjdGVkRmVhdHVyZXMsIlBzZXVkb01hdHVyYXRpb24uc2NvcmUiKV0sIAogICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJhbmdlciIsCiAgICAgICAgICAgICAgICAgICAgICB0ckNvbnRyb2w9dHJjdHJsLAogICAgICAgICAgICAgICAgICAgICAgaW1wb3J0YW5jZT0icGVybXV0YXRpb24iLCAKICAgICAgICAgICAgICAgICAgICAgIHR1bmVHcmlkID0gZGF0YS5mcmFtZShtdHJ5PTUwLCBtaW4ubm9kZS5zaXplID0gNSwgc3BsaXRydWxlPSJ2YXJpYW5jZSIpKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQojIFBsb3QgT2JzZXJ2ZWQgdnMgT09CIHByZWRpY3RlZCB2YWx1ZXMgZnJvbSB0aGUgbW9kZWwKcGxvdChtb2RlbC5kYXRhJFBzZXVkb01hdHVyYXRpb24uc2NvcmUsIFRlbGxleS5tb2RlbCRmaW5hbE1vZGVsJHByZWRpY3Rpb25zLAogICAgIHBjaD0xOSwgeGxhYj0ib2JzZXJ2ZWQgUHNldWRvLW1hdHVyYXRpb24iLAogICAgIHlsYWI9Ik9PQiBwcmVkaWN0ZWQgUHNldWRvLW1hdHVyYXRpb24iKQptdGV4dChwYXN0ZSgiUi1zcXVhcmVkIiwgZm9ybWF0KFRlbGxleS5tb2RlbCRmaW5hbE1vZGVsJHIuc3F1YXJlZCxkaWdpdHM9MikpKQpgYGAKCiMjIFByZWRpY3QgbWF0dXJhdGlvbiBzY29yZSBvZiBFMTIgcGFsbGlhbCBhcGljYWwgcHJvZ2VuaXRvcnMKCmBgYHtyfQojIFByZWRpY3QgbWF0dXJhdGlvbiBzY29yZSBvZiBFMTIgQVBzCkUxMi5kZiA8LSBhcy5kYXRhLmZyYW1lKHQoRTEyLkFQLmRhdGFAc2NhbGUuZGF0YVtyb3duYW1lcyhFMTIuQVAuZGF0YUBzY2FsZS5kYXRhKSAlaW4lIFNlbGVjdGVkRmVhdHVyZXMsXSkpCgpFMTIucHJlZC5tYXR1cmF0aW9uIDwtIHByZWRpY3QoVGVsbGV5Lm1vZGVsLCBFMTIuZGYpCgpFMTIuQVAuZGF0YUBtZXRhLmRhdGEkUHNldWRvTWF0dXJhdGlvbi5zY29yZSA8LSBFMTIucHJlZC5tYXR1cmF0aW9uCgpFMTIucGxvdC5kZiA8LSBFMTIuQVAuZGF0YUBtZXRhLmRhdGEgJT4lIGRwbHlyOjpzZWxlY3QoQmFyY29kZXMsIERvbWFpbmUsIERvcnNvVmVudHJhbC5TY29yZSxQc2V1ZG9NYXR1cmF0aW9uLnNjb3JlKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDZCIn0KIyBQbG90IEUxMiBwcmVkaWN0ZWQgbWF0dXJhdGlvbiBzY29yZSBieSBjbHVzdGVyCmRvbWFpbmUgPC0gZmFjdG9yKEUxMi5wbG90LmRmJERvbWFpbmUsIGxldmVsID0gYygiVmVudHJhbC5QYWxsaXVtIiwibGF0ZXJhbC5QYWxsaXVtLjEiLCJsYXRlcmFsLlBhbGxpdW0uMiIsIkRvcnNhbC5QYWxsaXVtIikpCgpnZ3Bsb3QoRTEyLnBsb3QuZGYsIGFlcyh4PSBkb21haW5lLCB5PSBQc2V1ZG9NYXR1cmF0aW9uLnNjb3JlLCBmaWxsPURvbWFpbmUpKSArCiAgZ2VvbV9ib3hwbG90KG5vdGNoPVRSVUUpICsKICBnZW9tX2ppdHRlcihjb2xvcj0iYmxhY2siLCBzaXplPTAuOCwgYWxwaGE9MC45KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjRTQ2QjZCIikpKSArCiAgeGxhYigiIikKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJUZWxsZXkuZGF0YSIsICJFMTIuQVAuZGF0YSIpXSkKYGBgCgojIERlY29tcG9zaXRpb24gb2Ygc3BhdGlhbCB2cy4gdGVtb3JhbCBhc3BlY3Qgb2YgcHJvZ2VuaXRvciBjZWxscyBpZGVudGl0eQoKIyMgU21vb3RoIGV4cHJlc3Npb24gb3ZlciBwc2V1ZG8tRFYgYW5kIHBzZXVkbyBtYXR1cmF0aW9uCgojIyMgRmluZCBhbGwgdmFyaWFibGUgZ2VuZXMgYWxvbmcgdGhlIHBzZXVkby1EViBheGlzIGluIEUxMiBBUAoKYGBge3J9CiMgVHJhbnNmZXJ0IG1ldGFkYXRhIAptZXRhLmRhdGEgPC0gZGF0YS5mcmFtZShiYXJjb2RlID0gcm93bmFtZXMoRTEyLkFQLmRhdGFAbWV0YS5kYXRhKSwKICAgICAgICAgICAgICAgICAgICAgICAgQ2x1c3RlciA9IEUxMi5BUC5kYXRhQG1ldGEuZGF0YSRvbGQuaWRlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgIERvcnNvVmVudHJhbC5TY29yZSA9ICBFMTIuQVAuZGF0YUBtZXRhLmRhdGEkRG9yc29WZW50cmFsLlNjb3JlLAogICAgICAgICAgICAgICAgICAgICAgICBDZWxsY3ljbGVQaGFzZSA9IEUxMi5BUC5kYXRhQG1ldGEuZGF0YSRQaGFzZSwKICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gcm93bmFtZXMoRTEyLkFQLmRhdGFAbWV0YS5kYXRhKSkKICAgICAgICAgICAgICAgICAgIApBbm5vdC5kYXRhICA8LSBuZXcoJ0Fubm90YXRlZERhdGFGcmFtZScsIGRhdGEgPSBtZXRhLmRhdGEpCgojIFRyYW5zZmVydCBjb3VudCBkYXRhCmNvdW50LmRhdGEgPSBkYXRhLmZyYW1lKGdlbmVfc2hvcnRfbmFtZSA9IHJvd25hbWVzKEUxMi5BUC5kYXRhQHJhdy5kYXRhKSwKICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gcm93bmFtZXMoRTEyLkFQLmRhdGFAcmF3LmRhdGEpKQoKZmVhdHVyZS5kYXRhIDwtIG5ldygnQW5ub3RhdGVkRGF0YUZyYW1lJywgZGF0YSA9IGNvdW50LmRhdGEpCgojIENyZWF0ZSB0aGUgQ2VsbERhdGFTZXQgb2JqZWN0CkUxMi5nYm1fY2RzIDwtIG5ld0NlbGxEYXRhU2V0KGFzLm1hdHJpeChFMTIuQVAuZGF0YUByYXcuZGF0YSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGhlbm9EYXRhID0gQW5ub3QuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlRGF0YSA9IGZlYXR1cmUuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsb3dlckRldGVjdGlvbkxpbWl0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICBleHByZXNzaW9uRmFtaWx5ID0gbmVnYmlub21pYWwoKSkKYGBgCgoKYGBge3J9CkUxMi5nYm1fY2RzIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoRTEyLmdibV9jZHMpCkUxMi5nYm1fY2RzIDwtIGVzdGltYXRlRGlzcGVyc2lvbnMoRTEyLmdibV9jZHMpCkUxMi5nYm1fY2RzIDwtIGRldGVjdEdlbmVzKEUxMi5nYm1fY2RzLCBtaW5fZXhwciA9IDAuMSkKYGBgCgpgYGB7cn0KIyBFeGNsdWRlIGNlbGwgY3ljbGUgYXNzb2NpYXRlZCBnZW5lcwpDQ2dlbmVzIDwtIGFzLmNoYXJhY3RlcihyZWFkLnRhYmxlKCIuL1Byb2dlbml0b3JzL0NlbGxDeWNsZUdlbmVzLmNzdiIsIHNlcCA9ICJcdCIsIGhlYWRlciA9IEYpWywxXSkKSW5wdXQuZ2VuZXMgPC0gRTEyLkFQLmRhdGFAdmFyLmdlbmVzWyFFMTIuQVAuZGF0YUB2YXIuZ2VuZXMgJWluJSBDQ2dlbmVzXQpgYGAKCmBgYHtyfQojIFBlcmZvcm0gdGhlIHRlc3QgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFzIGEgZnVuY3Rpb24gb2YgcHNldWRvLURWIHNjb3JlCkRWLkF4aXMuZ2VuZXMgPC0gZGlmZmVyZW50aWFsR2VuZVRlc3QoRTEyLmdibV9jZHNbSW5wdXQuZ2VuZXMsXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbE1vZGVsRm9ybXVsYVN0ciA9ICJ+c20ubnMoRG9yc29WZW50cmFsLlNjb3JlLCBkZiA9IDMpKkNlbGxjeWNsZVBoYXNlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWNlZE1vZGVsRm9ybXVsYVN0ciA9ICJ+Q2VsbGN5Y2xlUGhhc2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IGRldGVjdENvcmVzKCkgLTIpCgojIEZpbHRlciBnZW5lcyB3aXRoIGEgRkRSIDwgMC4wMDEKRFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQgPC0gRFYuQXhpcy5nZW5lcyAlPiUgZmlsdGVyKHF2YWwgPCAxZS0zKQpgYGAKCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBwc2V1ZG8tRFYgdmVjdG9yIG9mIDUwMCBwb2ludHMKblBvaW50cyA8LSAyMDAKRTEyLm5ld19kYXRhIDwtIGRhdGEuZnJhbWUoRG9yc29WZW50cmFsLlNjb3JlID0gc2VxKG1pbihwRGF0YShFMTIuZ2JtX2NkcykkRG9yc29WZW50cmFsLlNjb3JlKSwgbWF4KHBEYXRhKEUxMi5nYm1fY2RzKSREb3Jzb1ZlbnRyYWwuU2NvcmUpLCBsZW5ndGgub3V0ID0gblBvaW50cykpCgojIFNtb290aCBnZW5lIGV4cHJlc3Npb24KRTEyLnNtb290aC5jdXJ2ZS5tYXRyaXggPC0gZ2VuU21vb3RoQ3VydmVzKEUxMi5nYm1fY2RzW2FzLmNoYXJhY3RlcihEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRnZW5lX3Nob3J0X25hbWUpLF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmVuZF9mb3JtdWxhID0gIn5zbS5ucyhEb3Jzb1ZlbnRyYWwuU2NvcmUsIGRmID0gMykiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRpdmVfZXhwciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfZGF0YSA9IEUxMi5uZXdfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzPSBkZXRlY3RDb3JlcygpIC0gMikKYGBgCgpgYGB7cn0Kcm0obGlzdD1scygpWyFscygpICVpbiUgYygiVGVsbGV5LmRhdGEiLCAiRTEyLkFQLmRhdGEiLCAiRTEyLnNtb290aC5jdXJ2ZS5tYXRyaXgiLCAiRTEyLm5ld19kYXRhIiwgIkRWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkIildKQpgYGAKCiMjIyBGaW5kIGFsbCB2YXJpYWJsZSBnZW5lcyBhbG9uZyB0aGUgcHNldWRvLW1hdHVyYXRpb24gYXhpcyBpbiBUZWxsZXkgMjAxOSBBUHMKCmBgYHtyfQojIFRyYW5zZmVydCBtZXRhZGF0YSAKbWV0YS5kYXRhIDwtIGRhdGEuZnJhbWUoYmFyY29kZSA9IHJvd25hbWVzKFRlbGxleS5kYXRhQG1ldGEuZGF0YSksCiAgICAgICAgICAgICAgICAgICAgICAgIENsdXN0ZXIgPSBUZWxsZXkuZGF0YUBtZXRhLmRhdGEkb3JpZy5pZGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgUHNldWRvTWF0dXJhdGlvbi5zY29yZSA9ICBUZWxsZXkuZGF0YUBtZXRhLmRhdGEkUHNldWRvTWF0dXJhdGlvbi5zY29yZSwKICAgICAgICAgICAgICAgICAgICAgICAgQ2VsbGN5Y2xlUGhhc2UgPSBUZWxsZXkuZGF0YUBtZXRhLmRhdGEkUGhhc2UsCiAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IHJvd25hbWVzKFRlbGxleS5kYXRhQG1ldGEuZGF0YSkpCiAgICAgICAgICAgICAgICAgICAKQW5ub3QuZGF0YSAgPC0gbmV3KCdBbm5vdGF0ZWREYXRhRnJhbWUnLCBkYXRhID0gbWV0YS5kYXRhKQoKIyBUcmFuc2ZlcnQgY291bnQgZGF0YQpjb3VudC5kYXRhID0gZGF0YS5mcmFtZShnZW5lX3Nob3J0X25hbWUgPSByb3duYW1lcyhUZWxsZXkuZGF0YUByYXcuZGF0YSksCiAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IHJvd25hbWVzKFRlbGxleS5kYXRhQHJhdy5kYXRhKSkKCmZlYXR1cmUuZGF0YSA8LSBuZXcoJ0Fubm90YXRlZERhdGFGcmFtZScsIGRhdGEgPSBjb3VudC5kYXRhKQoKIyBDcmVhdGUgdGhlIENlbGxEYXRhU2V0IG9iamVjdApUZWxsZXkuZ2JtX2NkcyA8LSBuZXdDZWxsRGF0YVNldChhcy5tYXRyaXgoVGVsbGV5LmRhdGFAcmF3LmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaGVub0RhdGEgPSBBbm5vdC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlRGF0YSA9IGZlYXR1cmUuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG93ZXJEZXRlY3Rpb25MaW1pdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25GYW1pbHkgPSBuZWdiaW5vbWlhbCgpKQpgYGAKCgpgYGB7cn0KVGVsbGV5LmdibV9jZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhUZWxsZXkuZ2JtX2NkcykKVGVsbGV5LmdibV9jZHMgPC0gZXN0aW1hdGVEaXNwZXJzaW9ucyhUZWxsZXkuZ2JtX2NkcykKVGVsbGV5LmdibV9jZHMgPC0gZGV0ZWN0R2VuZXMoVGVsbGV5LmdibV9jZHMsIG1pbl9leHByID0gMC4xKQpgYGAKCmBgYHtyfQojIEV4Y2x1ZGUgY2VsbCBjeWNsZSBhc3NvY2lhdGVkLCBtdCBhbmQgcmlibyByaWJvCkNDZ2VuZXMgPC0gYXMuY2hhcmFjdGVyKHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvQ2VsbEN5Y2xlR2VuZXMuY3N2Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gRilbLDFdKQpHZW5lc1RvUmVtb3ZlIDwtIGMoZ3JlcChwYXR0ZXJuID0gIiheUnBsfF5ScHN8Xk1ycCkiLCB4ID0gcm93Lm5hbWVzKFRlbGxleS5kYXRhQGRhdGEpLCB2YWx1ZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgZ3JlcChwYXR0ZXJuID0gIl5tdC0iLCB4ID0gcm93Lm5hbWVzKFRlbGxleS5kYXRhQGRhdGEpLCB2YWx1ZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgIlhpc3QiLCBDQ2dlbmVzKQoKSW5wdXQuZ2VuZXMgPC0gcm93Lm5hbWVzKFRlbGxleS5kYXRhQGRhdGEpWyFyb3cubmFtZXMoVGVsbGV5LmRhdGFAZGF0YSkgJWluJSBHZW5lc1RvUmVtb3ZlXQoKIyBXZSBzZWxlY3QgYWxsIGdlbmVzIHdoaWNoIGFyZSBkaWZmZXJlbnRpYWx5IGV4cHJlc3NlZCBiZXR3ZWVuIEUxMiBhbmQgRTE1IEFQIApFMTJ2c0UxNS5ERWdlbmVzIDwtIEZpbmRNYXJrZXJzKG9iamVjdCA9IFRlbGxleS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjEgPSAiRTEyLjFIIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gIkUxNS4xSCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLnBjdCA9IDAuMjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZmMudGhyZXNob2xkID0gMC40LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50LmJhciA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25seS5wb3MgPSBGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVzLnVzZSA9IElucHV0LmdlbmVzKQoKRTEydnNFMTUuREVnZW5lcyRHZW5lIDwtIHJvd25hbWVzKEUxMnZzRTE1LkRFZ2VuZXMpCgpFMTJ2c0UxNS5ERWdlbmVzLmZpbHRlcmVkIDwtIEUxMnZzRTE1LkRFZ2VuZXMgJT4lIGZpbHRlcihwX3ZhbF9hZGogPCAxZS0zKSAlPiUgcHVsbChHZW5lKQpgYGAKCgpgYGB7cn0KIyBDcmVhdGUgYSBuZXcgcHNldWRvLURWIHZlY3RvciBvZiA1MDAgcG9pbnRzCm5Qb2ludHMgPC0gMjAwClRlbGxleS5uZXdfZGF0YSA8LSBkYXRhLmZyYW1lKFBzZXVkb01hdHVyYXRpb24uc2NvcmUgPSBzZXEobWluKHBEYXRhKFRlbGxleS5nYm1fY2RzKSRQc2V1ZG9NYXR1cmF0aW9uLnNjb3JlKSwgbWF4KHBEYXRhKFRlbGxleS5nYm1fY2RzKSRQc2V1ZG9NYXR1cmF0aW9uLnNjb3JlKSwgbGVuZ3RoLm91dCA9IG5Qb2ludHMpKQoKIyBTbW9vdGggZ2VuZSBleHByZXNzaW9uIGFsb25nIHBzZXVkby1tYXR1cmF0aW9uIGF4aXMKVGVsbGV5LnNtb290aC5jdXJ2ZS5tYXRyaXggPC0gZ2VuU21vb3RoQ3VydmVzKFRlbGxleS5nYm1fY2RzW0UxMnZzRTE1LkRFZ2VuZXMuZmlsdGVyZWQsXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZW5kX2Zvcm11bGEgPSAifnNtLm5zKFBzZXVkb01hdHVyYXRpb24uc2NvcmUsIGRmID0gMykiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRpdmVfZXhwciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfZGF0YSA9IFRlbGxleS5uZXdfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzPSBkZXRlY3RDb3JlcygpIC0gMikKYGBgCgojIyBJZGVudGlmeSB0ZW1wb3JhbCBnZW5lcyBhcyBoaWdobHkgYW50aS1jb3JyZWxhdGluZyBiZXR3ZWVuIHRoZSB0d28gZGF0YXNldHMKCiMjIyBJbnRlcnNlY3QgdGhlIHR3byBzbW9vdGhlZCBleHByZXNzaW9uIG1hdHJpY2VzCgpgYGB7cn0KQ29tbW9uR2VuZXMgPC0gaW50ZXJzZWN0KHJvd25hbWVzKEUxMi5zbW9vdGguY3VydmUubWF0cml4KSwgcm93bmFtZXMoVGVsbGV5LnNtb290aC5jdXJ2ZS5tYXRyaXgpKQoKRTEyLlNtb290aC5Db21tb24gPC0gdChzY2FsZSh0KEUxMi5zbW9vdGguY3VydmUubWF0cml4W0NvbW1vbkdlbmVzLF0pKSkKVGVsbGV5LlNtb290aC5Db21tb24gPC0gdChzY2FsZSh0KFRlbGxleS5zbW9vdGguY3VydmUubWF0cml4W0NvbW1vbkdlbmVzLF0pKSkKYGBgCgojIyMgQ2x1c3RlciB0ZW1wb3JhbCBnZW5lcyBhY2NvcmRpbmcgdG8gdGhlaXIgc21vb3RoZWQgZXhwcmVzc2lvbiBpbnZlcnNlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHR3byBkYXRhc2V0cwoKYGBge3J9CiMgQnVpbGQgdGVtcG9yYWwgZ2VuZXMgZGVuZHJvZ3JhbQpjb3IubWF0IDwtIGNvcih4PSB0KEUxMi5TbW9vdGguQ29tbW9uWywyMDA6MV0pLCB5PSB0KFRlbGxleS5TbW9vdGguQ29tbW9uKSwgbWV0aG9kID0gInBlYXJzb24iKQpkc3QgPC0gZGlzdChjb3IubWF0LCBtZXRob2QgPSAiZXVjbGlkZWFuIikKaGMgPC0gIGhjbHVzdChkc3QsIG1ldGhvZCA9ICJjb21wbGV0ZSIpCgojIEZpbmQgMyBjbHVzdGVyIGJhc2VkIG9uIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nCmNsdXN0ZXJzIDwtIGN1dHJlZShoYywgaz0zKQoKVGVtcG9yYWwuZ2VuZS5jbHVzdGVycyA8LSBkYXRhLmZyYW1lKEdlbmUgPSBuYW1lcyhjbHVzdGVycyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2VuZS5DbHVzdGVycyA9IGFzLm51bWVyaWMoY2x1c3RlcnMpKSAlPiUgYXJyYW5nZShHZW5lLkNsdXN0ZXJzKQoKcm93Lm5hbWVzKFRlbXBvcmFsLmdlbmUuY2x1c3RlcnMpIDwtIFRlbXBvcmFsLmdlbmUuY2x1c3RlcnMkR2VuZQpUZW1wb3JhbC5nZW5lLmNsdXN0ZXJzJEdlbmUuQ2x1c3RlcnMgPC0gcGFzdGUwKCJDbHVzdC4iLFRlbXBvcmFsLmdlbmUuY2x1c3RlcnMkR2VuZS5DbHVzdGVycykKCndyaXRlLnRhYmxlKFRlbXBvcmFsLmdlbmUuY2x1c3RlcnMsICIuL1Byb2dlbml0b3JzL1RlbXBvcmFsLmdlbmUuY2x1c3RlcnMuY3N2Iiwgc2VwID0gIjsiLCBxdW90ZSA9IEYpCmBgYAoKCmBgYHtyIGZpZy5kaW09Yyg2LjQsIDQuNCksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gNkUifQpwaGVhdG1hcChjb3IubWF0LAogICAgICAgICBjbHVzdGVyX3Jvd3M9IGhjLAogICAgICAgICBzY2FsZSA9ICJub25lIiwKICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSBUZW1wb3JhbC5nZW5lLmNsdXN0ZXJzICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICBhbm5vdGF0aW9uX2NvbG9ycyA9IGxpc3QoR2VuZS5DbHVzdGVycyA9IGMoQ2x1c3QuMSA9IiM0Nzg0YTIiICwgQ2x1c3QuMj0iI2ViY2IyZSIsQ2x1c3QuMz0iI2NjM2ExYiIpKSwKICAgICAgICAgc2hvd19jb2xuYW1lcyA9IFQsCiAgICAgICAgIHNob3dfcm93bmFtZXMgPSBULAogICAgICAgICBib3JkZXJfY29sb3IgPSBOQSwKICAgICAgICAgY29sb3IgPSByZXYoYnJld2VyLnBhbCg4LCJSZEJ1IikpLAogICAgICAgICBtYWluID0gIkdlbmVzIGludmVyc2UgcGVhcnNvbiBjb3JyZWxhdGlvbiBtYXRyaXgiKQpgYGAKCiMjIyBQbG90IGNvcnJlbGF0aW9uIGJldHdlZW4gc21vb3RoZWQgZXhwcmVzc2lvbiBwcm9maWxlcyAKCmBgYHtyfQpTbW9vdGhlZC5wb2ludC5jb3IgPC0gY29yKHg9IEUxMi5TbW9vdGguQ29tbW9uLCB5PSBUZWxsZXkuU21vb3RoLkNvbW1vblssMjAwOjFdLCBtZXRob2QgPSAicGVhcnNvbiIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDYuNCwgNC40KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA2RCJ9CkRvbWFpbmUuRTEyLkFQIDwtIEUxMi5BUC5kYXRhQG1ldGEuZGF0YSAlPiUgc2VsZWN0KERvcnNvVmVudHJhbC5TY29yZSwgRG9tYWluZSkKRG9tYWluZS5ib3VuZGFyaWVzIDwtIGFnZ3JlZ2F0ZShEb3Jzb1ZlbnRyYWwuU2NvcmUgfiBEb21haW5lLCBEb21haW5lLkUxMi5BUCwgbWF4KSAlPiUgYXJyYW5nZShEb3Jzb1ZlbnRyYWwuU2NvcmUpICU+JSBwdWxsKERvcnNvVmVudHJhbC5TY29yZSkKCkRvbWFpbmUuSWRlbnQgPC0gc2FwcGx5KEUxMi5uZXdfZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUsCiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpeyBpZih4PERvbWFpbmUuYm91bmRhcmllc1sxXSl7IHggPSAiVmVudHJhbC5QYWxsaXVtIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gRG9tYWluZS5ib3VuZGFyaWVzWzFdICYgeDwgRG9tYWluZS5ib3VuZGFyaWVzWzJdKXsgeCA9ImxhdGVyYWwuUGFsbGl1bS4xIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gRG9tYWluZS5ib3VuZGFyaWVzWzNdKXsgeCA9ICJEb3JzYWwuUGFsbGl1bSIKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHg9ImxhdGVyYWwuUGFsbGl1bS4yIn0pIAoKRG9tYWluZXMuQ2x1c3QgPC0gZGF0YS5mcmFtZShEb21haW5lLklkZW50KQoKcGhlYXRtYXAodChTbW9vdGhlZC5wb2ludC5jb3IpLAogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBGLAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IERvbWFpbmVzLkNsdXN0LAogICAgICAgICBnYXBzX2NvbCA9IGN1bXN1bShhcy5udW1lcmljKHRhYmxlKERvbWFpbmVzLkNsdXN0JERvbWFpbmUuSWRlbnQpKVtjKDQsMiwzLDEpXSksCiAgICAgICAgIGFubm90YXRpb25fY29sb3JzID0gbGlzdChEb21haW5lLklkZW50ID0gYyhWZW50cmFsLlBhbGxpdW0gPSAiI2U0NmI2YiIsbGF0ZXJhbC5QYWxsaXVtLjEgPSAiI2UzYzE0OCIsIGxhdGVyYWwuUGFsbGl1bS4yID0gIiNiN2QxNzQiLERvcnNhbC5QYWxsaXVtID0gIiM2OGIwNDEiKSksCiAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGLAogICAgICAgICBzaG93X3Jvd25hbWVzID0gRiwKICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKHJldihicmV3ZXIucGFsKG4gPSAxMCwgbmFtZSA9ICJSZEJ1IikpKSgxMDApLAogICAgICAgICBtYWluID0gIlBlYXJzb24ncyBDb3JyZWxhdGlvbiBtYXRyaXgiKQpgYGAKCiMjIEV4dHJhY3QgRTEyIHNwYXRpYWwgZG9tYWluIGdlbmVzIHdoaWNoIGRvIG5vdCBzaG93IEUxMi9FMTUgZGlmZmVyZW5jZSBpbiBUZWxsZXkgZGF0YQoKYGBge3J9CiMgU2VsZWN0IGdlbmVzIHZhcmlhYmxlIGluIEUxMiBkYXRhc2V0IHdoaWNoIGRvIG5vdCBzaG93IHNpZ25pZmljYXRpdmUgZGlmZmVyZW5jZSBiZXR3ZWVuIEUxMiBhbmQgRTE1IEFQIGluIFRlbGxleSBldCBhbCBkYXRhc2V0CkUxMi5Eb21haW4uc3BlY2lmaWMuZ2VuZXMgPC0gcm93bmFtZXMoRTEyLnNtb290aC5jdXJ2ZS5tYXRyaXgpWyFyb3duYW1lcyhFMTIuc21vb3RoLmN1cnZlLm1hdHJpeCkgJWluJSBDb21tb25HZW5lc10KCkUxMi5zbW9vdGguc3BlY2lmaWMgPC0gRTEyLnNtb290aC5jdXJ2ZS5tYXRyaXhbRTEyLkRvbWFpbi5zcGVjaWZpYy5nZW5lcyxdCmBgYAoKYGBge3IgfQojIEJ1aWxkIHRlbXBvcmFsIGdlbmVzIGRlbmRyb2dyYW0KY29yLm1hdCA8LSBjb3IodChFMTIuc21vb3RoLnNwZWNpZmljKSwgbWV0aG9kID0gInNwZWFybWFuIikKZHN0IDwtIGFzLmRpc3QoMSAtIGNvci5tYXQpCmhjIDwtICBoY2x1c3QoZHN0LCBtZXRob2QgPSAid2FyZC5EIikgIyJ3YXJkLkQiCgojIFNlcmlhdGUgdGhlIGRlbmRyb2dyYW0KZGVuZCA8LSBhcy5kZW5kcm9ncmFtKGhjKQpkZW5kIDwtIGRlbmRleHRlbmQ6OnNlcmlhdGVfZGVuZHJvZ3JhbShkZW5kLCBkc3QsIG1ldGhvZD0iR1ciKQoKIyBGaW5kIDIgY2x1c3RlciBiYXNlZCBvbiBoaWVyYXJjaGljYWwgY2x1c3RlcmluZwpjbHVzdGVycyA8LSBjdXRyZWUoaGMsIGs9NCkKCnJvd25hbWVzKERWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkKSAgPC0gRFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQkZ2VuZV9zaG9ydF9uYW1lCkRWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkIDwtIERWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkW25hbWVzKGNsdXN0ZXJzKSxdCgpTcGF0aWFsLmdlbmUuY2x1c3RlcnMgPC0gZGF0YS5mcmFtZShHZW5lID0gbmFtZXMoY2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsPSBEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRwdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsPSBEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRxdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1fY2VsbHNfZXhwcmVzc2VkPSBEVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRudW1fY2VsbHNfZXhwcmVzc2VkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzID0gYXMubnVtZXJpYyhjbHVzdGVycykpICU+JSBhcnJhbmdlKEdlbmUuQ2x1c3RlcnMpCgpyb3cubmFtZXMoU3BhdGlhbC5nZW5lLmNsdXN0ZXJzKSA8LSBTcGF0aWFsLmdlbmUuY2x1c3RlcnMkR2VuZQpTcGF0aWFsLmdlbmUuY2x1c3RlcnMkR2VuZS5DbHVzdGVycyA8LSBwYXN0ZTAoIkNsdXN0LiIsU3BhdGlhbC5nZW5lLmNsdXN0ZXJzJEdlbmUuQ2x1c3RlcnMpCgp3cml0ZS50YWJsZShTcGF0aWFsLmdlbmUuY2x1c3RlcnMsICIuL1Byb2dlbml0b3JzL1NwYXRpYWwuZ2VuZS5jbHVzdGVycy5jc3YiLCBzZXAgPSAiOyIsIHF1b3RlID0gRikKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDYuNCwgNC40KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA2RyJ9CmFubm8uY29sIDwtIGxpc3QoRG9tYWluZS5JZGVudCA9IGMoVmVudHJhbC5QYWxsaXVtID0gIiNlNDZiNmIiLGxhdGVyYWwuUGFsbGl1bS4xID0gIiNlM2MxNDgiLCBsYXRlcmFsLlBhbGxpdW0uMiA9ICIjYjdkMTc0IixEb3JzYWwuUGFsbGl1bSA9ICIjNjhiMDQxIiksCiAgICAgICAgICAgICAgICAgR2VuZS5DbHVzdGVycyA9IGMoQ2x1c3QuMSA9IiM0Nzg0YTIiICwgQ2x1c3QuMj0iI2ViY2IyZSIsIENsdXN0LjM9IiNjYzNhMWIiLENsdXN0LjQ9IiM0Y2FiZGMiLENsdXN0LjU9IiMzY2E3M2YiKSkKCnBoZWF0bWFwKEUxMi5zbW9vdGguc3BlY2lmaWMsCiAgICAgICAgIGNsdXN0ZXJfcm93cz0gYXMuaGNsdXN0KGRlbmQpLAogICAgICAgICBzY2FsZSA9ICJyb3ciLAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IERvbWFpbmVzLkNsdXN0LAogICAgICAgICBnYXBzX2NvbCA9IGN1bXN1bShhcy5udW1lcmljKHRhYmxlKERvbWFpbmVzLkNsdXN0JERvbWFpbmUuSWRlbnQpKVtjKDQsMiwzLDEpXSksCiAgICAgICAgIGFubm90YXRpb25fcm93ID0gU3BhdGlhbC5nZW5lLmNsdXN0ZXJzICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICBhbm5vdGF0aW9uX2NvbG9ycyA9IGFubm8uY29sLAogICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwKICAgICAgICAgc2hvd19yb3duYW1lcyA9IEYsCiAgICAgICAgIGNvbG9yID0gcmV2KGJyZXdlci5wYWwoMTEsIlJkQnUiKSksCiAgICAgICAgIGJyZWFrcyA9IHNlcSgtMi41LDIuNSwgbGVuZ3RoLm91dCA9IDExKSwKICAgICAgICAgbWFpbiA9ICJTcGF0aWFsIHNtb290aGVkIGV4cHJlc3Npb24gYWxvbmcgcHNldWRvRFYgYXhpcyIpCmBgYAoKIyBQbG90IHRoZSByZXByZXNlbnRhdGl2ZSB0cmVuZHMKCmBgYHtyfQpkYXRhRTEyIDwtIGRhdGEuZnJhbWUoQ2x1c3RlciA9IHBhc3RlMCgiQ2x1c3RlciIsYXMuY2hhcmFjdGVyKEUxMi5BUC5kYXRhQGlkZW50KSksCiAgICAgICAgICAgICAgICAgICBEb3Jzb1ZlbnRyYWwuU2NvcmUgPSAgRTEyLkFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZSwKICAgICAgICAgICAgICAgICAgIFpidGIyMCA9IEUxMi5BUC5kYXRhQGRhdGFbIlpidGIyMCIsXSwKICAgICAgICAgICAgICAgICAgIExycm4xID0gRTEyLkFQLmRhdGFAZGF0YVsiTHJybjEiLF0sCiAgICAgICAgICAgICAgICAgICBMbW80ID0gRTEyLkFQLmRhdGFAZGF0YVsiTG1vNCIsXSwKICAgICAgICAgICAgICAgICAgIE1wcGVkMiA9RTEyLkFQLmRhdGFAZGF0YVsiTXBwZWQyIixdKQoKZGF0YVRlbGxleSA8LSBkYXRhLmZyYW1lKENsdXN0ZXIgPSBwYXN0ZTAoIkNsdXN0ZXIiLGFzLmNoYXJhY3RlcihUZWxsZXkuZGF0YUBpZGVudCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgUHNldWRvTWF0dXJhdGlvbi5zY29yZSA9ICBUZWxsZXkuZGF0YUBtZXRhLmRhdGEkUHNldWRvTWF0dXJhdGlvbi5zY29yZSwKICAgICAgICAgICAgICAgICAgICAgICAgIFpidGIyMCA9IFRlbGxleS5kYXRhQGRhdGFbIlpidGIyMCIsXSwKICAgICAgICAgICAgICAgICAgICAgICAgIExycm4xID0gVGVsbGV5LmRhdGFAZGF0YVsiTHJybjEiLF0sCiAgICAgICAgICAgICAgICAgICAgICAgICBMbW80ID0gVGVsbGV5LmRhdGFAZGF0YVsiTG1vNCIsXSwKICAgICAgICAgICAgICAgICAgICAgICAgIE1wcGVkMiA9IFRlbGxleS5kYXRhQGRhdGFbIk1wcGVkMiIsXSkKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDYsIDQuNSl9CmdncGxvdChkYXRhPWRhdGFFMTIsIGFlcyh4PURvcnNvVmVudHJhbC5TY29yZSwgeT1aYnRiMjAsIGNvbG9yPUNsdXN0ZXIpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0gdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjRTQ2QjZCIikpKSArIAogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIG49IDMwLCBjb2xvcj0icmVkIiwgZmlsbD0iZ3JleSIpICsgCiAgICBnZ3RpdGxlKCJaYnRiMjAiKSArCiAgICB5bGltKDAsTkEpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCmBgYApgYGB7ciBmaWcuZGltPWMoNiwgNC41KX0KZ2dwbG90KGRhdGE9ZGF0YUUxMiwgYWVzKHg9RG9yc29WZW50cmFsLlNjb3JlLCB5PUxycm4xLCBjb2xvcj1DbHVzdGVyKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9IHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiI0U0NkI2QiIpKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBuPSAzMCwgY29sb3I9InJlZCIsIGZpbGw9ImdyZXkiKSArIAogICAgZ2d0aXRsZSgiTHJybjEiKSArCiAgICB5bGltKDAsTkEpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDYsIDQuNSl9CmdncGxvdChkYXRhPWRhdGFFMTIsIGFlcyh4PURvcnNvVmVudHJhbC5TY29yZSwgeT1MbW80LCBjb2xvcj1DbHVzdGVyKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9IHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiI0U0NkI2QiIpKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBuPSAzMCwgY29sb3I9InJlZCIsIGZpbGw9ImdyZXkiKSArIAogICAgZ2d0aXRsZSgiTG1vNCIpICsKICAgIHlsaW0oMCxOQSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKYGBgCmBgYHtyIGZpZy5kaW09Yyg2LCA0LjUpfQpnZ3Bsb3QoZGF0YT1kYXRhRTEyLCBhZXMoeD1Eb3Jzb1ZlbnRyYWwuU2NvcmUsIHk9TXBwZWQyLCBjb2xvcj1DbHVzdGVyKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9IHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiI0U0NkI2QiIpKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBuPSAzMCwgY29sb3I9InJlZCIsIGZpbGw9ImdyZXkiKSArIAogICAgZ2d0aXRsZSgiTXBwZWQyIikgKwogICAgeWxpbSgwLE5BKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpgYGAKYGBge3IgZmlnLmRpbT1jKDYsIDQuNSl9CmdncGxvdChkYXRhPWRhdGFUZWxsZXksIGFlcyh4PVBzZXVkb01hdHVyYXRpb24uc2NvcmUsIHk9WmJ0YjIwLCBjb2xvcj1DbHVzdGVyKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9IGMoIiNiZGQ4ZWYiLCAiIzZkYjhlMiIsICIjMzU3ZWJjIiwgIiMxYzQ4OTYiKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBuPSAzMCwgY29sb3I9InJlZCIsIGZpbGw9ImdyZXkiLHNwYW4gPSAwLjUpICsgCiAgICBnZ3RpdGxlKCJaYnRiMjAiKSArCiAgICB5bGltKDAsTkEpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCmBgYApgYGB7ciBmaWcuZGltPWMoNiwgNC41KX0KZ2dwbG90KGRhdGE9ZGF0YVRlbGxleSwgYWVzKHg9UHNldWRvTWF0dXJhdGlvbi5zY29yZSwgeT1McnJuMSwgY29sb3I9Q2x1c3RlcikpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPSBjKCIjYmRkOGVmIiwgIiM2ZGI4ZTIiLCAiIzM1N2ViYyIsICIjMWM0ODk2IikpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgbj0gMzAsIGNvbG9yPSJyZWQiLCBmaWxsPSJncmV5IikgKyAKICAgIGdndGl0bGUoIkxycm4xIikgKwogICAgeWxpbSgwLE5BKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg2LCA0LjUpfQpnZ3Bsb3QoZGF0YT1kYXRhVGVsbGV5LCBhZXMoeD1Qc2V1ZG9NYXR1cmF0aW9uLnNjb3JlLCB5PUxtbzQsIGNvbG9yPUNsdXN0ZXIpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0gYygiI2JkZDhlZiIsICIjNmRiOGUyIiwgIiMzNTdlYmMiLCAiIzFjNDg5NiIpKSArIAogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIG49IDMwLCBjb2xvcj0icmVkIiwgZmlsbD0iZ3JleSIpICsgCiAgICBnZ3RpdGxlKCJMbW80IikgKwogICAgeWxpbSgwLE5BKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpgYGAKYGBge3IgZmlnLmRpbT1jKDYsIDQuNSl9CmdncGxvdChkYXRhPWRhdGFUZWxsZXksIGFlcyh4PVBzZXVkb01hdHVyYXRpb24uc2NvcmUsIHk9TXBwZWQyLCBjb2xvcj1DbHVzdGVyKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9IGMoIiNiZGQ4ZWYiLCAiIzZkYjhlMiIsICIjMzU3ZWJjIiwgIiMxYzQ4OTYiKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBuPSAzMCwgY29sb3I9InJlZCIsIGZpbGw9ImdyZXkiKSArIAogICAgZ2d0aXRsZSgiTXBwZWQyIikgKwogICAgeWxpbSgwLE5BKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpgYGAKCiMgU2Vzc2lvbiBJbmZvCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=