1 Gene clustering using COTAN

[1] "calculating gene coexpression space: output tanh of reduced coex matrix"
     L11      L12    L2/31    L2/32      L41      L42    L5/61    L5/62    Prog1    Prog2 
  "Reln"   "Lhx5"  "Satb2"   "Cux1"   "Rorb"   "Sox5" "Bcl11b"  "Fezf2"    "Vim"   "Hes1" 
[1] "Get p-values on a set of genes on columns genome wide on rows"
[1] "Using function S"
[1] "function to generate S "
[1] "Secondary markers:181"
[1] "function to generate S "
[1] "Columns (V set) number: 181 Rows (U set) number: 1236"

1.2 Import of markers from Loo et al. paper

Gene present in the 10% of most differentially expressed genes by COTAN

[1] 33

of total genes detected as markers by Loo et al

[1] 48

Number of genes detected:

[1] 43

Removed becouse not detected

    L.I2    PROG4   PROG10   PROG19   PROG22 
  "Gdf5" "Cdc25c" "Gas2l3"  "Rspo1"  "Wnt8b" 
$L.I
[1] "Ebf3"  "Gdf5"  "Lhx1"  "Lhx5"  "Ndnf"  "Reln"  "Samd3" "Trp73"

$L.II.IV
[1] "Satb2"         "3110047P20Rik" "9130024F11Rik" "Dok5"          "Inhba"         "Pou3f1"       

$L.V.VI
 [1] "Bcl11b" "Crym"   "Fezf2"  "Hs3st4" "Mc4r"   "Nfe2l3" "Nxph3"  "Plxna4" "Rwdd3"  "Sla"    "Sybu"   "Tbr1"  

$PROG
 [1] "Aldoc"    "Arhgef39" "Aspm"     "Cdc25c"   "Cdkn3"    "Cyr61"    "Dkk3"     "Ednrb"    "Gas1"    
[10] "Gas2l3"   "Hes1"     "Hes5"     "Htra1"    "Nde1"     "Nek2"     "Pax6"     "Pkmyt1"   "Plk1"    
[19] "Rspo1"    "Tcf19"    "Tk1"      "Wnt8b"   

Primary markers also used by Loo et al.

     L11      L12    L2/31    L5/61    L5/62    Prog2 
  "Reln"   "Lhx5"  "Satb2" "Bcl11b"  "Fezf2"   "Hes1" 

Table

       3        6        2        5        1 
  "Reln"  "Satb2"   "Rorb" "Bcl11b"    "Vim" 

1.3 Comparition between Loo et al. markers and COTAN markers

Without secondary markers

2 WGCNA

2.1 Test with the 2000 most varied genes

This seems the best option for the analysis with WGCNA.

Feature names cannot have underscores ('_'), replacing with dashes ('-')

Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
When using repel, set xnudge and ynudge to 0 for optimal results

Centering and scaling data matrix

  |                                                                                                            
  |                                                                                                      |   0%
  |                                                                                                            
  |========                                                                                              |   8%
  |                                                                                                            
  |================                                                                                      |  15%
  |                                                                                                            
  |========================                                                                              |  23%
  |                                                                                                            
  |===============================                                                                       |  31%
  |                                                                                                            
  |=======================================                                                               |  38%
  |                                                                                                            
  |===============================================                                                       |  46%
  |                                                                                                            
  |=======================================================                                               |  54%
  |                                                                                                            
  |===============================================================                                       |  62%
  |                                                                                                            
  |=======================================================================                               |  69%
  |                                                                                                            
  |==============================================================================                        |  77%
  |                                                                                                            
  |======================================================================================                |  85%
  |                                                                                                            
  |==============================================================================================        |  92%
  |                                                                                                            
  |======================================================================================================| 100%
PC_ 1 
Positive:  Fabp7, Aldoc, Mfge8, Dbi, Ednrb, Vim, Slc1a3, Mt3, Apoe, Ttyh1 
       Tnc, Sox2, Atp1a2, Ddah1, Hes5, Sparc, Mlc1, Ppap2b, Rgcc, Bcan 
       Ndrg2, Qk, Lxn, Id3, Phgdh, Slc9a3r1, Nr2e1, Aldh1l1, Gpx8, Mt1 
Negative:  Tubb3, Stmn2, Neurod6, Stmn4, Map1b, Stmn1, Myt1l, Mef2c, Thra, 4930506M07Rik 
       Bcl11a, Gap43, Bhlhe22, Syt4, Cntn2, Nell2, Hs6st2, 9130024F11Rik, Olfm1, Satb2 
       Akap9, Ptprd, Rbfox1, Clmp, Ina, Enc1, Camk2b, Dync1i1, Dab1, Atp2b1 
PC_ 2 
Positive:  Sstr2, Mdk, Meis2, Pou3f2, Eomes, Zbtb20, Unc5d, Sema3c, Fos, Tead2 
       Palmd, Mfap4, Nhlh1, Ulk4, H1f0, Uaca, Neurog2, Neurod1, Ezr, Ier2 
       Nrn1, Baz2b, Pdzrn3, Btg2, Egr1, Mfap2, Loxl1, H2afv, Hbp1, Nnat 
Negative:  Gap43, Sybu, Dync1i1, Meg3, Mef2c, Map1b, Fezf2, Camk2b, Ina, Stmn2 
       Cdh13, Thra, Nin, Rac3, Igfbp3, Ssbp2, Neto2, Cd200, Hmgcs1, Tuba1b 
       Syt1, Slc6a15, Mapre2, Plk2, Rprm, Atp1b1, Cadm2, Arpp21, Kitl, Ntrk2 
PC_ 3 
Positive:  Meg3, Smpdl3a, Slc9a3r1, Slc15a2, Timp3, Tmem47, Ndrg2, Apoe, Ttyh1, Fmo1 
       Mlc1, Scrg1, Islr2, Malat1, Gstm1, Gja1, Ndnf, Aldh1l1, Mt3, Sparc 
       Serpinh1, Paqr7, Asrgl1, Sepp1, S100a1, Atp1b1, Ctsl, Cpe, S100a16, Lhx5 
Negative:  Birc5, Top2a, Cenpm, Pbk, Tpx2, Cenpe, Mki67, Cdca8, Gmnn, Cks2 
       Ccnb1, Ccnb2, Spc24, Hmgb2, Cenpf, Tk1, Hmmr, Prc1, Kif11, Ccna2 
       2810417H13Rik, C330027C09Rik, Cdca2, Ect2, Nusap1, Cenpa, Uhrf1, Plk1, Spc25, Knstrn 
PC_ 4 
Positive:  Lhx5, Nhlh2, Snhg11, Reln, 1500016L03Rik, Trp73, Cacna2d2, Ndnf, Car10, Lhx1 
       Islr2, Pcp4, Meg3, RP24-351J24.2, Rcan2, Pnoc, Mab21l1, Zic1, E330013P04Rik, Emx2 
       Malat1, Ebf3, Nr2f2, Zcchc12, Zbtb20, Celf4, Tmem163, Ache, Calb2, Unc5b 
Negative:  Ptn, Satb2, 9130024F11Rik, Neurod6, Mef2c, Dab1, Limch1, Hs6st2, Abracl, Dok5 
       Gucy1a3, Nell2, Ptprz1, Syt4, Ttc28, Clmp, Macrod2, Fam19a2, Smpdl3a, Ndrg1 
       Gstm1, 4930506M07Rik, Paqr7, Aldh1l1, Myt1l, Hmgcs1, Slc15a2, Pdzrn4, Slc9a3r1, Aldoc 
PC_ 5 
Positive:  Fam210b, Sfrp1, Pax6, Enkur, Tubb3, Tuba1b, Mcm3, Veph1, Stmn1, Eif1b 
       Map1b, Hopx, Abracl, Cdk2ap2, Tfap2c, Rps27l, 2810025M15Rik, Slc14a2, Prdx1, Hells 
       Gap43, Sept11, Egln3, Gm1840, Ezr, Cpne2, 9130024F11Rik, Nes, Efnb2, Cux1 
Negative:  Serpine2, Id1, Olig1, Sparcl1, Igfbp3, Fam212b, Ccnb2, Ppic, Gng12, Ccnb1 
       Bcan, Cenpe, Pbk, Id3, Rasl11a, Plk1, Aqp4, Aspm, Hmmr, Slc6a1 
       Slc4a4, Malat1, Myo6, Timp3, Meg3, Cdk1, Prrx1, Npy, B2m, Cspg4 

Centering and scaling data matrix

  |                                                                                                            
  |                                                                                                      |   0%
  |                                                                                                            
  |========                                                                                              |   8%
  |                                                                                                            
  |================                                                                                      |  15%
  |                                                                                                            
  |========================                                                                              |  23%
  |                                                                                                            
  |===============================                                                                       |  31%
  |                                                                                                            
  |=======================================                                                               |  38%
  |                                                                                                            
  |===============================================                                                       |  46%
  |                                                                                                            
  |=======================================================                                               |  54%
  |                                                                                                            
  |===============================================================                                       |  62%
  |                                                                                                            
  |=======================================================================                               |  69%
  |                                                                                                            
  |==============================================================================                        |  77%
  |                                                                                                            
  |======================================================================================                |  85%
  |                                                                                                            
  |==============================================================================================        |  92%
  |                                                                                                            
  |======================================================================================================| 100%
 Flagging genes and samples with too many missing values...
  ..step 1
[1] TRUE

No outliner detected

pickSoftThreshold: will use block size 2000.
 pickSoftThreshold: calculating connectivity for given powers...
   ..working on genes 1 through 2000 of 2000

Plot the results:

Tested with 5, 3 and 2 and 4. The best seems 2

 Calculating module eigengenes block-wise from all genes
   Flagging genes and samples with too many missing values...
    ..step 1
 ..Working on block 1 .
    TOM calculation: adjacency..
    ..will not use multithreading.
     Fraction of slow calculations: 0.000000
    ..connectivity..
    ..matrix multiplication (system BLAS)..
    ..normalization..
    ..done.
   ..saving TOM for block 1 into file E17.5-block.1.RData
 ....clustering..
 ....detecting modules..
 ....calculating module eigengenes..
 ....checking kME in modules..
     ..removing 552 genes from module 1 because their KME is too low.
     ..removing 154 genes from module 2 because their KME is too low.
     ..removing 86 genes from module 3 because their KME is too low.
     ..removing 42 genes from module 4 because their KME is too low.
     ..removing 20 genes from module 5 because their KME is too low.
 ..merging modules that are too close..
     mergeCloseModules: Merging modules whose distance is less than 0.25
       Calculating new MEs...

2.2 Comparition between Loo et al. markers and WGCNA markers

Warning: Not all gene names were recognized. Only the following genes were recognized. 
    Ebf3,     Lhx1,     Lhx5,     Ndnf,     Reln,     Samd3,     Trp73,     Satb2,     9130024F11Rik,     Dok5,     Inhba,     Bcl11b,     Crym,     Fezf2,     Hs3st4,     Nfe2l3,     Nxph3,     Rwdd3,     Sla,     Sybu,     Aldoc,     Arhgef39,     Aspm,     Cdc25c,     Cyr61,     Ednrb,     Gas1,     Hes1,     Hes5,     Htra1,     Nek2,     Pax6,     Plk1,     Tcf19,     Tk1
..connectivity..
..matrix multiplication (system BLAS)..
..normalization..
..done.

There were 15 warnings (use warnings() to see them)
Warning: Not all gene names were recognized. Only the following genes were recognized. 
    Ebf3,     Lhx1,     Lhx5,     Ndnf,     Reln,     Samd3,     Trp73,     Satb2,     9130024F11Rik,     Dok5,     Inhba,     Bcl11b,     Crym,     Fezf2,     Hs3st4,     Nfe2l3,     Nxph3,     Rwdd3,     Sla,     Sybu,     Aldoc,     Arhgef39,     Aspm,     Cdc25c,     Cyr61,     Ednrb,     Gas1,     Hes1,     Hes5,     Htra1,     Nek2,     Pax6,     Plk1,     Tcf19,     Tk1
..connectivity..
..matrix multiplication (system BLAS)..
..normalization..
..done.

..connectivity..
..matrix multiplication (system BLAS)..
..normalization..
..done.

..connectivity..
..matrix multiplication (system BLAS)..
..normalization..
..done.

TOM calculation: adjacency..
..will not use multithreading.
 Fraction of slow calculations: 0.000000
..connectivity..
..matrix multiplication (system BLAS)..
..normalization..
..done.

9130024F11Rik         Aldoc      Arhgef39          Aspm        Bcl11b        Cdc25c          Crym         Cyr61 
            0             1             0             2             0             2             0             1 
         Dok5          Ebf3         Ednrb         Fezf2          Gas1          Hes1          Hes5        Hs3st4 
            0             4             1             0             1             1             1             0 
        Htra1         Inhba          Lhx1          Lhx5          Ndnf          Nek2        Nfe2l3         Nxph3 
            1             0             4             4             4             2             0             0 
         Pax6          Plk1          Reln         Rwdd3         Samd3         Satb2           Sla          Sybu 
            1             2             4             0             0             0             0             0 
        Tcf19           Tk1         Trp73 
            0             2             4 
There were 15 warnings (use warnings() to see them)

WGCNA using the 2000 genes most varied by Seurat, detects the following number of markers.

[1] 35
  Reln   Lhx5  Satb2   Cux1   Rorb   Sox5 Bcl11b  Fezf2    Vim   Hes1 
     4      4      0      0      0      0      0      0      1      1 

R version 4.0.4 (2021-02-15)
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/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               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    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] gplots_3.1.1          patchwork_1.1.1       dplyr_1.0.4           SeuratObject_4.0.0   
 [5] Seurat_4.0.0          cluster_2.1.1         WGCNA_1.70-3          fastcluster_1.1.25   
 [9] dynamicTreeCut_1.63-1 dendextend_1.14.0     ggrepel_0.9.1         factoextra_1.0.7     
[13] Matrix_1.3-2          data.table_1.13.6     ggplot2_3.3.3         COTAN_0.1.0          

loaded via a namespace (and not attached):
  [1] R.utils_2.10.1        reticulate_1.18       tidyselect_1.1.0      RSQLite_2.2.3        
  [5] AnnotationDbi_1.52.0  htmlwidgets_1.5.3     grid_4.0.4            Rtsne_0.15           
  [9] munsell_0.5.0         preprocessCore_1.52.1 codetools_0.2-18      ica_1.0-2            
 [13] future_1.21.0         miniUI_0.1.1.1        withr_2.4.1           colorspace_2.0-0     
 [17] Biobase_2.50.0        filelock_1.0.2        knitr_1.31            rstudioapi_0.13      
 [21] stats4_4.0.4          ROCR_1.0-11           ggsignif_0.6.1        tensor_1.5           
 [25] listenv_0.8.0         labeling_0.4.2        polyclip_1.10-0       bit64_4.0.5          
 [29] farver_2.0.3          basilisk_1.2.1        parallelly_1.23.0     vctrs_0.3.6          
 [33] generics_0.1.0        xfun_0.20             R6_2.5.0              doParallel_1.0.16    
 [37] clue_0.3-58           bitops_1.0-6          spatstat.utils_2.0-0  cachem_1.0.3         
 [41] gridGraphics_0.5-1    assertthat_0.2.1      promises_1.1.1        scales_1.1.1         
 [45] nnet_7.3-15           gtable_0.3.0          Cairo_1.5-12.2        globals_0.14.0       
 [49] goftest_1.2-2         rlang_0.4.10          GlobalOptions_0.1.2   splines_4.0.4        
 [53] rstatix_0.7.0         lazyeval_0.2.2        impute_1.64.0         checkmate_2.0.0      
 [57] broom_0.7.5           BiocManager_1.30.10   yaml_2.2.1            reshape2_1.4.4       
 [61] abind_1.4-5           backports_1.2.1       httpuv_1.5.5          Hmisc_4.5-0          
 [65] tools_4.0.4           ggplotify_0.0.5       ellipsis_0.3.1        jquerylib_0.1.3      
 [69] RColorBrewer_1.1-2    BiocGenerics_0.36.0   ggridges_0.5.3        Rcpp_1.0.6           
 [73] plyr_1.8.6            base64enc_0.1-3       purrr_0.3.4           basilisk.utils_1.2.2 
 [77] ggpubr_0.4.0          rpart_4.1-15          deldir_0.2-10         pbapply_1.4-3        
 [81] GetoptLong_1.0.5      viridis_0.5.1         cowplot_1.1.1         S4Vectors_0.28.1     
 [85] zoo_1.8-8             haven_2.3.1           magrittr_2.0.1        scattermore_0.7      
 [89] openxlsx_4.2.3        circlize_0.4.12       lmtest_0.9-38         RANN_2.6.1           
 [93] fitdistrplus_1.1-3    matrixStats_0.58.0    hms_1.0.0             mime_0.9             
 [97] evaluate_0.14         xtable_1.8-4          jpeg_0.1-8.1          rio_0.5.16           
[101] readxl_1.3.1          IRanges_2.24.1        gridExtra_2.3         shape_1.4.5          
[105] compiler_4.0.4        tibble_3.0.6          KernSmooth_2.23-18    crayon_1.4.0         
[109] R.oo_1.24.0           htmltools_0.5.1.1     mgcv_1.8-33           later_1.1.0.1        
[113] Formula_1.2-4         tidyr_1.1.2           DBI_1.1.1             ComplexHeatmap_2.6.2 
[117] MASS_7.3-53.1         rappdirs_0.3.3        car_3.0-10            R.methodsS3_1.8.1    
[121] parallel_4.0.4        igraph_1.2.6          forcats_0.5.1         pkgconfig_2.0.3      
[125] rvcheck_0.1.8         foreign_0.8-81        plotly_4.9.3          foreach_1.5.1        
[129] bslib_0.2.4           stringr_1.4.0         digest_0.6.27         sctransform_0.3.2    
[133] RcppAnnoy_0.0.18      spatstat.data_2.0-0   rmarkdown_2.7         cellranger_1.1.0     
[137] leiden_0.3.7          htmlTable_2.1.0       uwot_0.1.10           curl_4.3             
[141] gtools_3.8.2          shiny_1.6.0           rjson_0.2.20          lifecycle_0.2.0      
[145] nlme_3.1-152          jsonlite_1.7.2        carData_3.0-4         viridisLite_0.3.0    
[149] pillar_1.4.7          lattice_0.20-41       fastmap_1.1.0         httr_1.4.2           
[153] survival_3.2-7        GO.db_3.12.1          glue_1.4.2            zip_2.1.1            
[157] spatstat_1.64-1       png_0.1-7             iterators_1.0.13      bit_4.0.4            
[161] sass_0.3.1            stringi_1.5.3         blob_1.2.1            caTools_1.18.1       
[165] latticeExtra_0.6-29   memoise_2.0.0         irlba_2.3.3           future.apply_1.7.0   
LS0tCnRpdGxlOiAiTG9vIGV0IGFsbCBtYXJrZXJzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvbGxhcHNlZDogbm8KICAgIGNzczogaHRtbC1tZC0wMS5jc3MKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBzcGFjZWxhYgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9ub3RlYm9vazoKICAgIGNvbGxhcHNlZDogbm8KICAgIGNzczogaHRtbC1tZC0wMS5jc3MKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBzcGFjZWxhYgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCi0tLQpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY29sbGFwc2UgPSBUUlVFLAogIGNvbW1lbnQgPSAiIz4iCikKb3B0aW9ucyhybWFya2Rvd24uaHRtbF92aWduZXR0ZS5jaGVja190aXRsZSA9IEZBTFNFKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KENPVEFOKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkoZmFjdG9leHRyYSkKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGRlbmRleHRlbmQpCmBgYAoKCiMgR2VuZSBjbHVzdGVyaW5nIHVzaW5nIENPVEFOCgpgYGB7cn0KaW5wdXRfZGlyID0gIkRhdGEvIgpsYXllcnMgPSBsaXN0KCJMMSI9YygiUmVsbiIsIkxoeDUiKSwgIkwyLzMiPWMoIlNhdGIyIiwiQ3V4MSIpLCAiTDQiPWMoIlJvcmIiLCJTb3g1IikgLCAiTDUvNiI9YygiQmNsMTFiIiwiRmV6ZjIiKSAsICJQcm9nIj1jKCJWaW0iLCJIZXMxIikpCm9iakUxNyA9IHJlYWRSRFMoZmlsZSA9ICJEYXRhL0UxN19jb3J0ZXhfY2wyLmNvdGFuLlJEUyIpCmBgYAoKYGBge3J9Cmcuc3BhY2UgPSBnZXQuZ2VuZS5jb2V4cHJlc3Npb24uc3BhY2Uob2JqRTE3LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuLmdlbmVzLmZvci5tYXJrZXIgPSAyNSwgIHByaW1hcnkubWFya2VycyA9IHVubGlzdChsYXllcnMpKQpgYGAKYGBge3J9Cmcuc3BhY2UgPSBhcy5kYXRhLmZyYW1lKGFzLm1hdHJpeChnLnNwYWNlKSkKCmNvZXgucGNhLmdlbmVzIDwtIHByY29tcCh0KGcuc3BhY2UpLAogICAgICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgc2NhbGUuID0gRikgCgpmdml6X2VpZyhjb2V4LnBjYS5nZW5lcywgYWRkbGFiZWxzPVRSVUUsbmNwID0gMTApCiNmdml6X2VpZyhjb2V4LnBjYS5nZW5lcywgY2hvaWNlID0gImVpZ2VudmFsdWUiLCBhZGRsYWJlbHM9VFJVRSkKYGBgCgojIyBIaWVyYXJjaGljYWwgY2x1c3RlcmluZwoKYGBge3IgZmlnLndpZHRoPTEwfQpjb250cm9scyA9bGlzdCgiZ2VuZXMgcmVsYXRlZCB0byBMNS82Ij1jKCJGb3hwMiIsIlRicjEiKSwgImdlbmVzIHJlbGF0ZWQgdG8gTDIvMyI9YygiTWVmMmMiKSwgImdlbmVzIHJlbGF0ZWQgdG8gUHJvZyI9YygiTmVzIiwiU294MiIpICwgImdlbmVzIHJlbGF0ZWQgdG8gTDEiPWMoKSAsICJnZW5lcyByZWxhdGVkIHRvIEw0Ij1jKCkpCiMgY2x1c3RlcmluZyB1c2lnbiBXYXJkIG1ldGhvZApoYy5ub3JtID0gaGNsdXN0KGRpc3QoZy5zcGFjZSksIG1ldGhvZCA9ICJ3YXJkLkQyIikKCiMgYW5kIGN1dCB0aGUgdHJlZSBpbnRvIDUgY2x1c3RlcnMgKGZvciBleGFtcGxlKQpjdXQgPSBjdXRyZWUoaGMubm9ybSwgayA9IDcsIG9yZGVyX2NsdXN0ZXJzX2FzX2RhdGEgPSBGKQoKIyBJdCBjcmF0ZXMgdGhlIHRyZWUKZGVuZCA8LSBhcy5kZW5kcm9ncmFtKGhjLm5vcm0pCgojIEkgY2FuIHVzZSBhIGRhdGFmcmFtZSBmcm9tIHRoZSBwY2EgdG8gc3RvcmUgc29tZSBkYXRhIHJlZ2FyZGluZyB0aGUgY2x1c3RlcmluZwpwY2FfMSA9IGFzLmRhdGEuZnJhbWUoY29leC5wY2EuZ2VuZXMkcm90YXRpb25bLDE6NV0pCnBjYV8xID0gcGNhXzFbb3JkZXIuZGVuZHJvZ3JhbShkZW5kKSxdCgoKbXljb2xvdXJzIDwtIGMoImdlbmVzIHJlbGF0ZWQgdG8gTDUvNiIgPSAiIzNDNTQ4OEZGIiwiZ2VuZXMgcmVsYXRlZCB0byBMMi8zIj0iI0YzOUI3RkZGIiwiZ2VuZXMgcmVsYXRlZCB0byBQcm9nIj0iIzREQkJENUZGIiwiZ2VuZXMgcmVsYXRlZCB0byBMMSI9IiNFNjRCMzVGRiIsImdlbmVzIHJlbGF0ZWQgdG8gTDQiID0gIiM5MUQxQzJGRiIsICJub3QgbWFya2VkIj0iI0IwOUM4NUZGIikKCiMgc2F2ZSB0aGUgY2x1c3RlciBudW1iZXIgaW50byB0aGUgZGF0YWZyYW1lCnBjYV8xJGhjbHVzdCA9IGN1dAoKZGVuZCA9YnJhbmNoZXNfY29sb3IoZGVuZCxrPTcsY29sPWMoIiM0REJCRDVGRiIsIiM5MUQxQzJGRiIsIiNGMzlCN0ZGRiIsIiNFNjRCMzVGRiIsIiMzQzU0ODhGRiIsIiM5MUQxQzJGRiIsIiNCMDlDODVGRiIgKSxncm91cExhYmVscyA9IFQpCiNkZW5kID1jb2xvcl9sYWJlbHMoZGVuZCxrPTUsbGFiZWxzID0gcm93bmFtZXMocGNhXzEpLGNvbD1wY2FfMSRjb2xvcnMpCgoKCmRlbmQgJT4lCnNldCgibGFiZWxzIiwgaWZlbHNlKGxhYmVscyhkZW5kKSAlaW4lIHJvd25hbWVzKHBjYV8xKVtyb3duYW1lcyhwY2FfMSkgJWluJSBjKHVubGlzdChsYXllcnMpLHVubGlzdChjb250cm9scykpXSwgbGFiZWxzKGRlbmQpLCAiIikpICU+JQogIHNldCgiYnJhbmNoZXNfa19jb2xvciIsIHZhbHVlID0gYygiZ3JheTgwIiwiIzREQkJENUZGIiwiIzkxRDFDMkZGIiAsImdyYXk4MCIsIiNGMzlCN0ZGRiIsIiNFNjRCMzVGRiIsIiMzQzU0ODhGRiIpLCBrID0gNykgJT4lCnBsb3QoaG9yaXo9RiwgYXhlcz1ULHlsaW0gPSBjKDAsMTAwKSkKYGBgCgojIyBJbXBvcnQgb2YgbWFya2VycyBmcm9tIExvbyBldCBhbC4gcGFwZXIKCmBgYHtyfQpNYXJrZXJzX0xvbyA9IHJlYWQuY3N2KCJEYXRhL01hcmtlcnNfTG9vLmNzdiIpCgpnZW5lc19kZXRlY3RlZCA9IHBjYV8xW3Jvd25hbWVzKHBjYV8xKSAlaW4lIHVubGlzdChNYXJrZXJzX0xvbylbIXVubGlzdChNYXJrZXJzX0xvbykgPT0gIiJdLF0KCmBgYAoKR2VuZSBwcmVzZW50IGluIHRoZSAxMCUgb2YgbW9zdCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYnkgQ09UQU4KYGBge3J9CmRpbShnZW5lc19kZXRlY3RlZClbMV0KYGBgCgpvZiB0b3RhbCBnZW5lcyBkZXRlY3RlZCBhcyBtYXJrZXJzIGJ5IExvbyBldCBhbApgYGB7cn0KbGVuZ3RoKHVubGlzdChNYXJrZXJzX0xvbylbIXVubGlzdChNYXJrZXJzX0xvbykgPT0gIiJdKQpgYGAKCk51bWJlciBvZiBnZW5lcyBkZXRlY3RlZDoKYGBge3J9CnN1bSh1bmxpc3QoTWFya2Vyc19Mb28pWyF1bmxpc3QoTWFya2Vyc19Mb28pID09ICIiXSAlaW4lIHJvd25hbWVzKG9iakUxN0Bjb2V4KSkKYGBgClJlbW92ZWQgYmVjb3VzZSBub3QgZGV0ZWN0ZWQKYGBge3J9CnB1cmUubWFya2VycyA9IHVubGlzdChNYXJrZXJzX0xvbykKcHVyZS5tYXJrZXJzID0gcHVyZS5tYXJrZXJzWyF1bmxpc3QoTWFya2Vyc19Mb28pID09ICIiXQpwdXJlLm1hcmtlcnNbIXB1cmUubWFya2VycyAlaW4lIHJvd25hbWVzKG9iakUxN0Bjb2V4KV0KYGBgCmBgYHtyfQpNYXJrZXJzX0xvbyA9IGFzLmxpc3QoTWFya2Vyc19Mb28pCmZvciAoaSBpbiBuYW1lcyhNYXJrZXJzX0xvbykpIHsKICAgIE1hcmtlcnNfTG9vW1tpXV0gPSBNYXJrZXJzX0xvb1tbaV1dWyEgTWFya2Vyc19Mb29bW2ldXSA9PSAiIl0KfQpNYXJrZXJzX0xvbwpgYGAKUHJpbWFyeSBtYXJrZXJzIGFsc28gdXNlZCBieSBMb28gZXQgYWwuCmBgYHtyfQp1bmxpc3QobGF5ZXJzKVt1bmxpc3QobGF5ZXJzKSAlaW4lIHVuaXF1ZSh1bmxpc3QoTWFya2Vyc19Mb28pKV0KYGBgCgoKClRhYmxlCgpgYGB7cn0KdGFibGVNYXJrZXJzQ09UQU4gPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChucm93ID0gNixuY29sID0gNCkpCmNvbG5hbWVzKHRhYmxlTWFya2Vyc0NPVEFOKT1jKCJMb28uTC5JIiwiTG9vLkwuSUkuSVYiLCJMb28uTC5WLlZJIiwiTG9vLlBST0ciKQpyb3duYW1lcyh0YWJsZU1hcmtlcnNDT1RBTik9YygiQ09UQU4uTC5JIiwiQ09UQU4uTC5JSS5JSUkiLCJDT1RBTi5MLklWIiwiQ09UQU4uTC5WLlZJIiwiQ09UQU4uUFJPRyIsIkNPVEFOLk5vdCBHcm91cGVkIikKdGFibGVNYXJrZXJzQ09UQU5fbm9fc2VjID0gdGFibGVNYXJrZXJzQ09UQU4KCmxheWVycy5jbHVzdGVyID0gYygiUmVsbiIsIlNhdGIyIiwiUm9yYiIsIkJjbDExYiIsIlZpbSIpCm5hbWVzKGxheWVycy5jbHVzdGVyKSA9IHVuaXF1ZShjdXRbdW5saXN0KGxheWVycyldKQpsYXllcnMuY2x1c3RlcgpgYGAKCiMjIENvbXBhcml0aW9uIGJldHdlZW4gTG9vIGV0IGFsLiBtYXJrZXJzIGFuZCBDT1RBTiBtYXJrZXJzCgpgYGB7cn0KZ3JvdXBzID0gbGlzdCgiTC5JIj1uYW1lcyh3aGljaChsYXllcnMuY2x1c3RlciA9PSAiUmVsbiIpKQogICAgICAgICAgICAgICwiTC5JSS5JSUkiPW5hbWVzKHdoaWNoKGxheWVycy5jbHVzdGVyID09ICJTYXRiMiIpKSwKICAgICAgICAgICAgICAiTC5JViI9bmFtZXMod2hpY2gobGF5ZXJzLmNsdXN0ZXIgPT0gIlJvcmIiKSksCiAgICAgICAgICAgICAgIkwuVi5WSSI9bmFtZXMod2hpY2gobGF5ZXJzLmNsdXN0ZXIgPT0gIkJjbDExYiIpKSwKICAgICAgICAgICAgICAiUFJPRyI9bmFtZXMod2hpY2gobGF5ZXJzLmNsdXN0ZXIgPT0gIlZpbSIpKSkKCmZvcihsYXllcjEgaW4gYygiTC5JIiwiTC5JSS5JSUkiLCAiTC5JViIsIkwuVi5WSSIsIlBST0ciKSl7CiAgICBmb3IobGF5ZXIyIGluIGMoIkwuSSIsIkwuSUkuSVYiLCJMLlYuVkkiLCJQUk9HIikpewogICAgdGFibGVNYXJrZXJzQ09UQU5bcGFzdGUwKCJDT1RBTi4iLGxheWVyMSkscGFzdGUwKCJMb28uIixsYXllcjIpXSA9CiAgICAgICAgc3VtKHJvd25hbWVzKHBjYV8xW3BjYV8xJGhjbHVzdCAlaW4lIGdyb3Vwc1tbbGF5ZXIxXV0sXSkgJWluJSBNYXJrZXJzX0xvb1tbbGF5ZXIyXV0pCiAgICB0YWJsZU1hcmtlcnNDT1RBTltwYXN0ZTAoIkNPVEFOLiIsIk5vdCBHcm91cGVkIikscGFzdGUwKCJMb28uIixsYXllcjIpXSA9CiAgICAgICAgc3VtKHJvd25hbWVzKHBjYV8xWyFwY2FfMSRoY2x1c3QgJWluJSB1bmxpc3QoZ3JvdXBzKSxdKSAlaW4lIE1hcmtlcnNfTG9vW1tsYXllcjJdXSkKICAgIH0KfQoKdGFibGVNYXJrZXJzQ09UQU4KYGBgCldpdGhvdXQgc2Vjb25kYXJ5IG1hcmtlcnMKCmBgYHtyfQpwY2FfMiA9IHBjYV8xWyEgcm93bmFtZXMocGNhXzEpICVpbiUgY29sbmFtZXMoZy5zcGFjZSksXQoKCmZvcihsYXllcjEgaW4gYygiTC5JIiwiTC5JSS5JSUkiLCAiTC5JViIsIkwuVi5WSSIsIlBST0ciKSl7CiAgICBmb3IobGF5ZXIyIGluIGMoIkwuSSIsIkwuSUkuSVYiLCJMLlYuVkkiLCJQUk9HIikpewogICAgdGFibGVNYXJrZXJzQ09UQU5fbm9fc2VjW3Bhc3RlMCgiQ09UQU4uIixsYXllcjEpLHBhc3RlMCgiTG9vLiIsbGF5ZXIyKV0gPQogICAgICAgIHN1bShyb3duYW1lcyhwY2FfMltwY2FfMiRoY2x1c3QgJWluJSBncm91cHNbW2xheWVyMV1dLF0pICVpbiUgTWFya2Vyc19Mb29bW2xheWVyMl1dKQogICAgdGFibGVNYXJrZXJzQ09UQU5fbm9fc2VjW3Bhc3RlMCgiQ09UQU4uIiwiTm90IEdyb3VwZWQiKSxwYXN0ZTAoIkxvby4iLGxheWVyMildID0KICAgICAgICBzdW0ocm93bmFtZXMocGNhXzJbIXBjYV8yJGhjbHVzdCAlaW4lIHVubGlzdChncm91cHMpLF0pICVpbiUgTWFya2Vyc19Mb29bW2xheWVyMl1dKQogICAgfQp9Cgp0YWJsZU1hcmtlcnNDT1RBTl9ub19zZWMKYGBgCgoKYGBge3J9CnNwZWNpZmljLmdlbmVzLnRhYmxlID0gZGF0YS5mcmFtZSgiZ2VuZXMiPWMoKSwgIkNPVEFOIj1jKCksIkxvby4iPWMoKSkKdHQxID0gYygpCnR0MiA9IGMoKQpmb3IobGF5ZXIxIGluIGMoIkwuSSIsIkwuSUkuSUlJIiwgIkwuSVYiLCJMLlYuVkkiLCJQUk9HIikpewogICAgZm9yKGxheWVyMiBpbiBjKCJMLkkiLCJMLklJLklWIiwiTC5WLlZJIiwiUFJPRyIpKXsKICAgIHR0MSA9IGRhdGEuZnJhbWUoImdlbmVzIj0gcm93bmFtZXMocGNhXzFbcGNhXzEkaGNsdXN0ICVpbiUgZ3JvdXBzW1tsYXllcjFdXSxdKVtyb3duYW1lcyhwY2FfMVtwY2FfMSRoY2x1c3QgCiAgICAgICAgICAgICAgICAgICAgICAgICAgJWluJSBncm91cHNbW2xheWVyMV1dLF0pICVpbiUgTWFya2Vyc19Mb29bW2xheWVyMl1dXSkKICAgIGlmIChkaW0odHQxKVsxXSA+IDApIHsKICAgICAgICAgICAgICAgICAgIHR0MSA9IGNiaW5kKHR0MSwgICJDT1RBTiI9bGF5ZXIxLCAiTG9vLiI9bGF5ZXIyKQogICAgICAgIH0KICAgIHR0MiA9IGRhdGEuZnJhbWUoImdlbmVzIj0gCiAgICAgICAgcm93bmFtZXMocGNhXzFbIXBjYV8xJGhjbHVzdCAlaW4lIHVubGlzdChncm91cHMpLF0pW3Jvd25hbWVzKHBjYV8xWyFwY2FfMSRoY2x1c3QgJWluJSAgICAgICAgICAgICAgICAgICB1bmxpc3QoZ3JvdXBzKSxdKSAlaW4lIE1hcmtlcnNfTG9vW1tsYXllcjJdXV0pCiAgICBpZiAoZGltKHR0MilbMV0gPiAwKSB7CiAgICAgICAgdHQyID0gY2JpbmQodHQyLCAiQ09UQU4iPSAiTm90IEdyb3VwZWQiLCAiTG9vLiI9bGF5ZXIyKQogICAgfQogICAgc3BlY2lmaWMuZ2VuZXMudGFibGUgPSByYmluZChzcGVjaWZpYy5nZW5lcy50YWJsZSx0dDEsdHQyKQogICAgfQp9CgpzcGVjaWZpYy5nZW5lcy50YWJsZVshKGR1cGxpY2F0ZWQoc3BlY2lmaWMuZ2VuZXMudGFibGUpKSAsIF0KCmBgYApgYGB7ciBmaWcuaGVpZ2h0PSA4MCwgZmlnLndpZHRoPSA4fQpkZW5kICU+JQpzZXQoImxhYmVscyIsIGlmZWxzZShsYWJlbHMoZGVuZCkgJWluJSByb3duYW1lcyhwY2FfMSlbcm93bmFtZXMocGNhXzEpICVpbiUgc3BlY2lmaWMuZ2VuZXMudGFibGUkZ2VuZXNdLCBsYWJlbHMoZGVuZCksICIiKSkgJT4lCiAgc2V0KCJicmFuY2hlc19rX2NvbG9yIiwgdmFsdWUgPSBjKCJncmF5ODAiLCIjNERCQkQ1RkYiLCIjOTFEMUMyRkYiICwiZ3JheTgwIiwiI0YzOUI3RkZGIiwiI0U2NEIzNUZGIiwiIzNDNTQ4OEZGIiksIGsgPSA3KSAlPiUKICAgIHBsb3QoaG9yaXo9VCwgYXhlcz1ULHhsaW0gPSBjKDAsODApLGNleCA9IDEwLCBkTGVhZiA9IC03KQoKYGBgCgojIFdHQ05BIAoKYGBge3J9CmxpYnJhcnkoV0dDTkEpCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KE1hdHJpeCkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkodXRpbHMpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGdyYXBoaWNzKQpvcHRpb25zKHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKZGF0YV9kaXIgPSAiRGF0YS8iCmxpYnJhcnkoZ3Bsb3RzKQpteWhlYXRjb2wgPSBjb2xvcnBhbmVsKDI1MCwncmVkJywib3JhbmdlIiwnbGVtb25jaGlmZm9uJykKYGBgCgoKIyMgVGVzdCB3aXRoIHRoZSAyMDAwIG1vc3QgdmFyaWVkIGdlbmVzCgpUaGlzIHNlZW1zIHRoZSBiZXN0IG9wdGlvbiBmb3IgdGhlIGFuYWx5c2lzIHdpdGggV0dDTkEuCgpgYGB7cn0KZGF0YSA9IGFzLmRhdGEuZnJhbWUoZnJlYWQocGFzdGUoaW5wdXRfZGlyLCJFMTc1X29ubHlfY29ydGljYWxfY2VsbHMudHh0Lmd6Iiwgc2VwID0gIi8iKSxzZXAgPSAiXHQiKSkKZGF0YSA9IGFzLmRhdGEuZnJhbWUoZGF0YSkKcm93bmFtZXMoZGF0YSkgPSBkYXRhJFYxCmRhdGEgPSBkYXRhWywyOm5jb2woZGF0YSldCmRhdGFbMToxMCwxOjEwXQpgYGAKCmBgYHtyfQpFMTcgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IGRhdGEsIHByb2plY3QgPSAiQ29ydGV4IEUxNy41IiwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpFMTdbWyJwZXJjZW50Lm10Il1dIDwtIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KEUxNywgcGF0dGVybiA9ICJebXQtIikKVmxuUGxvdChFMTcsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5tdCIpLCBuY29sID0gMykKYGBgCmBgYHtyfQpoaXN0KEUxNyRuRmVhdHVyZV9STkEvRTE3JG5Db3VudF9STkEsIGJyZWFrcyA9IDEwMCkKYGBgCmBgYHtyfQpwbG90MSA8LSBGZWF0dXJlU2NhdHRlcihFMTcsIGZlYXR1cmUxID0gIm5Db3VudF9STkEiLCBmZWF0dXJlMiA9ICJwZXJjZW50Lm10IikKcGxvdDIgPC0gRmVhdHVyZVNjYXR0ZXIoRTE3LCBmZWF0dXJlMSA9ICJuQ291bnRfUk5BIiwgZmVhdHVyZTIgPSAibkZlYXR1cmVfUk5BIikKcGxvdDEgKyBwbG90MgpgYGAKYGBge3J9CkUxNyA8LSBOb3JtYWxpemVEYXRhKEUxNywgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDApCkUxNyA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhFMTcsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKCiMgSWRlbnRpZnkgdGhlIDEwIG1vc3QgaGlnaGx5IHZhcmlhYmxlIGdlbmVzCnRvcDEwIDwtIGhlYWQoVmFyaWFibGVGZWF0dXJlcyhFMTcpLCAxMCkKCiMgcGxvdCB2YXJpYWJsZSBmZWF0dXJlcyB3aXRoIGFuZCB3aXRob3V0IGxhYmVscwpwbG90MSA8LSBWYXJpYWJsZUZlYXR1cmVQbG90KEUxNykKcGxvdDIgPC0gTGFiZWxQb2ludHMocGxvdCA9IHBsb3QxLCBwb2ludHMgPSB0b3AxMCwgcmVwZWwgPSBUUlVFKQpwbG90MgpgYGAKYGBge3J9CmFsbC5nZW5lcyA8LSByb3duYW1lcyhFMTcpCkUxNyA8LSBTY2FsZURhdGEoRTE3LCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKRTE3IDwtIFJ1blBDQShFMTcsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBFMTcpKQpEaW1QbG90KEUxNywgcmVkdWN0aW9uID0gInBjYSIpCmBgYAoKCmBgYHtyfQphbGwuZ2VuZXMgPC0gcm93bmFtZXMoRTE3KQpFMTcgPC0gU2NhbGVEYXRhKEUxNywgZmVhdHVyZXMgPSBhbGwuZ2VuZXMpCgpzZXVyYXQuZGF0YSA9IGFzLm1hdHJpeChFMTdbWyJSTkEiXV1AZGF0YSkKClZhci5nZW5lcyA9IFZhcmlhYmxlRmVhdHVyZXMoRTE3KVsxOjIwMDBdCgpgYGAKCgpgYGB7cn0KZGF0RXhwcjAgPSB0KHNldXJhdC5kYXRhW3Jvd25hbWVzKHNldXJhdC5kYXRhKSAlaW4lIFZhci5nZW5lcyxdKQpnc2cgPSBnb29kU2FtcGxlc0dlbmVzKGRhdEV4cHIwLCB2ZXJib3NlID0gMykKZ3NnJGFsbE9LCmlmICghZ3NnJGFsbE9LKXsKICAgICMgT3B0aW9uYWxseSwgcHJpbnQgdGhlIGdlbmUgYW5kIHNhbXBsZSBuYW1lcyB0aGF0IHdlcmUgcmVtb3ZlZDoKICAgIGlmIChzdW0oIWdzZyRnb29kR2VuZXMpPjApCiAgICAgICAgcHJpbnRGbHVzaChwYXN0ZSgiUmVtb3ZpbmcgZ2VuZXM6IiwgcGFzdGUobmFtZXMoZGF0RXhwcjApWyFnc2ckZ29vZEdlbmVzXSwgY29sbGFwc2UgPSAiLCAiKSkpOwogICAgaWYgKHN1bSghZ3NnJGdvb2RTYW1wbGVzKT4wKQogICAgICAgIHByaW50Rmx1c2gocGFzdGUoIlJlbW92aW5nIHNhbXBsZXM6IiwgcGFzdGUocm93bmFtZXMoZGF0RXhwcjApWyFnc2ckZ29vZFNhbXBsZXNdLCBjb2xsYXBzZSA9ICIsICIpKSk7CiAgICAjIFJlbW92ZSB0aGUgb2ZmZW5kaW5nIGdlbmVzIGFuZCBzYW1wbGVzIGZyb20gdGhlIGRhdGE6CiAgICBkYXRFeHByMCA9IGRhdEV4cHIwW2dzZyRnb29kU2FtcGxlcywgZ3NnJGdvb2RHZW5lc10KfQoKCgpzYW1wbGVUcmVlID0gaGNsdXN0KGRpc3QoZGF0RXhwcjApLCBtZXRob2QgPSAiYXZlcmFnZSIpOwojIFBsb3QgdGhlIHNhbXBsZSB0cmVlOiBPcGVuIGEgZ3JhcGhpYyBvdXRwdXQgd2luZG93IG9mIHNpemUgMTIgYnkgOSBpbmNoZXMKIyBUaGUgdXNlciBzaG91bGQgY2hhbmdlIHRoZSBkaW1lbnNpb25zIGlmIHRoZSB3aW5kb3cgaXMgdG9vIGxhcmdlIG9yIHRvbyBzbWFsbC4Kc2l6ZUdyV2luZG93KDEyLDkpCgpwYXIoY2V4ID0gMC42KTsKcGFyKG1hciA9IGMoMCw0LDIsMCkpCnBsb3Qoc2FtcGxlVHJlZSwgbWFpbiA9ICJTYW1wbGUgY2x1c3RlcmluZyB0byBkZXRlY3Qgb3V0bGllcnMiLCBzdWI9IiIsIHhsYWI9IiIsIGNleC5sYWIgPSAxLjUsCiAgICAgY2V4LmF4aXMgPSAxLjUsIGNleC5tYWluID0gMikKCiMgUGxvdCBhIGxpbmUgdG8gc2hvdyB0aGUgY3V0CiNhYmxpbmUoaCA9IDQwMCwgY29sID0gInJlZCIpCmBgYApObyBvdXRsaW5lciBkZXRlY3RlZAoKYGBge3J9CiMgQXV0b21hdGljIG5ldHdvcmsgY29uc3RydWN0aW9uIGFuZCBtb2R1bGUgZGV0ZWN0aW9uCiMgQ2hvb3NlIGEgc2V0IG9mIHNvZnQtdGhyZXNob2xkaW5nIHBvd2Vycwpwb3dlcnMgPSBjKGMoMToxMCksIHNlcShmcm9tID0gMTAsIHRvPTI1LCBieT0yKSkKIyBDYWxsIHRoZSBuZXR3b3JrIHRvcG9sb2d5IGFuYWx5c2lzIGZ1bmN0aW9uCnNmdCA9IHBpY2tTb2Z0VGhyZXNob2xkKGRhdEV4cHIwLCBwb3dlclZlY3RvciA9IHBvd2VycywgdmVyYm9zZSA9IDUpCmBgYApQbG90IHRoZSByZXN1bHRzOgpgYGB7cn0Kc2l6ZUdyV2luZG93KDksIDUpCnBhcihtZnJvdyA9IGMoMSwyKSk7CmNleDEgPSAwLjk7CiMgU2NhbGUtZnJlZSB0b3BvbG9neSBmaXQgaW5kZXggYXMgYSBmdW5jdGlvbiBvZiB0aGUgc29mdC10aHJlc2hvbGRpbmcgcG93ZXIKcGxvdChzZnQkZml0SW5kaWNlc1ssMV0sIC1zaWduKHNmdCRmaXRJbmRpY2VzWywzXSkqc2Z0JGZpdEluZGljZXNbLDJdLAogICAgIHhsYWI9IlNvZnQgVGhyZXNob2xkIChwb3dlcikiLHlsYWI9IlNjYWxlIEZyZWUgVG9wb2xvZ3kgTW9kZWwgRml0LHNpZ25lZCBSXjIiLHR5cGU9Im4iLAogICAgIG1haW4gPSBwYXN0ZSgiU2NhbGUgaW5kZXBlbmRlbmNlIikpOwp0ZXh0KHNmdCRmaXRJbmRpY2VzWywxXSwgLXNpZ24oc2Z0JGZpdEluZGljZXNbLDNdKSpzZnQkZml0SW5kaWNlc1ssMl0sCiAgICAgbGFiZWxzPXBvd2VycyxjZXg9Y2V4MSxjb2w9InJlZCIpOwojIHRoaXMgbGluZSBjb3JyZXNwb25kcyB0byB1c2luZyBhbiBSXjIgY3V0LW9mZiBvZiBoCmFibGluZShoPTAuOTAsY29sPSJyZWQiKQojIE1lYW4gY29ubmVjdGl2aXR5IGFzIGEgZnVuY3Rpb24gb2YgdGhlIHNvZnQtdGhyZXNob2xkaW5nIHBvd2VyCnBsb3Qoc2Z0JGZpdEluZGljZXNbLDFdLCBzZnQkZml0SW5kaWNlc1ssNV0sCiAgICAgeGxhYj0iU29mdCBUaHJlc2hvbGQgKHBvd2VyKSIseWxhYj0iTWVhbiBDb25uZWN0aXZpdHkiLCB0eXBlPSJuIiwKICAgICBtYWluID0gcGFzdGUoIk1lYW4gY29ubmVjdGl2aXR5IikpCnRleHQoc2Z0JGZpdEluZGljZXNbLDFdLCBzZnQkZml0SW5kaWNlc1ssNV0sIGxhYmVscz1wb3dlcnMsIGNleD1jZXgxLGNvbD0icmVkIikKYGBgClRlc3RlZCB3aXRoIDUsIDMgYW5kIDIgYW5kIDQuIFRoZSBiZXN0IHNlZW1zIDIKYGBge3J9Cm5ldCA9IGJsb2Nrd2lzZU1vZHVsZXMoZGF0RXhwcjAsIHBvd2VyID0gMiwgbWF4QmxvY2tTaXplID0gMjAwMDAsCiAgICAgICAgICAgICAgICAgICAgICAgVE9NVHlwZSA9ICJzaWduZWQiLCBtaW5Nb2R1bGVTaXplID0gMzAsCiAgICAgICAgICAgICAgICAgICAgICAgcmVhc3NpZ25UaHJlc2hvbGQgPSAwLCBtZXJnZUN1dEhlaWdodCA9IDAuMjUsCiAgICAgICAgICAgICAgICAgICAgICAgbnVtZXJpY0xhYmVscyA9IFRSVUUsIHBhbVJlc3BlY3RzRGVuZHJvID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgc2F2ZVRPTXMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIHNhdmVUT01GaWxlQmFzZSA9ICJFMTcuNSIsCiAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IDMpCgpgYGAKYGBge3J9CiMgb3BlbiBhIGdyYXBoaWNzIHdpbmRvdwpzaXplR3JXaW5kb3coMTIsIDkpCiMgQ29udmVydCBsYWJlbHMgdG8gY29sb3JzIGZvciBwbG90dGluZwptZXJnZWRDb2xvcnMgPSBsYWJlbHMyY29sb3JzKG5ldCRjb2xvcnMpCiMgUGxvdCB0aGUgZGVuZHJvZ3JhbSBhbmQgdGhlIG1vZHVsZSBjb2xvcnMgdW5kZXJuZWF0aApwbG90RGVuZHJvQW5kQ29sb3JzKG5ldCRkZW5kcm9ncmFtc1tbMV1dLCBtZXJnZWRDb2xvcnNbbmV0JGJsb2NrR2VuZXNbWzFdXV0sCiAgICAgICAgICAgICAgICAgICAgIk1vZHVsZSBjb2xvcnMiLAogICAgICAgICAgICAgICAgICAgIGRlbmRyb0xhYmVscyA9IEZBTFNFLCBoYW5nID0gMC4wMywKICAgICAgICAgICAgICAgICAgICBhZGRHdWlkZSA9IFRSVUUsIGd1aWRlSGFuZyA9IDAuMDUpCgpgYGAKIyMgQ29tcGFyaXRpb24gYmV0d2VlbiBMb28gZXQgYWwuIG1hcmtlcnMgYW5kIFdHQ05BIG1hcmtlcnMKCmBgYHtyfQpwbG90TmV0d29ya0hlYXRtYXAoZGF0RXhwcjAsIHBsb3RHZW5lcyA9IHVubGlzdChNYXJrZXJzX0xvbyksCm5ldHdvcmtUeXBlPSJzaWduZWQiLCB1c2VUT009VFJVRSwKcG93ZXI9MiwgbWFpbj0iRC4gVE9NIGluIGFuIHNpZ25lZCBuZXR3b3JrIikKCmBgYApgYGB7cn0KcGxvdE5ldHdvcmtIZWF0bWFwKGRhdEV4cHIwLCBwbG90R2VuZXMgPSB1bmxpc3QoTWFya2Vyc19Mb28pLApuZXR3b3JrVHlwZT0idW5zaWduZWQiLCB1c2VUT009VFJVRSwKcG93ZXI9MiwgbWFpbj0iRC4gVE9NIGluIGFuIHVuc2lnbmVkIG5ldHdvcmsiKQoKYGBgCgpgYGB7cn0KcGxvdE5ldHdvcmtIZWF0bWFwKGRhdEV4cHIwLCBwbG90R2VuZXMgPSB1bmlxdWUodW5saXN0KGxheWVycykpLApuZXR3b3JrVHlwZT0ic2lnbmVkIiwgdXNlVE9NPVRSVUUsCnBvd2VyPTIsIG1haW49IkQuIFRPTSBpbiBhbiBzaWduZWQgbmV0d29yayIpCgpgYGAKYGBge3J9CnBsb3ROZXR3b3JrSGVhdG1hcChkYXRFeHByMCwgcGxvdEdlbmVzID0gdW5pcXVlKHVubGlzdChsYXllcnMpKSwKbmV0d29ya1R5cGU9InVuc2lnbmVkIiwgdXNlVE9NPVRSVUUsCnBvd2VyPTIsIG1haW49IkQuIFRPTSBpbiBhbiB1bnNpZ25lZCBuZXR3b3JrIikKCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIHRvcG9sb2dpY2FsIG92ZXJsYXAgYW5ldzogdGhpcyBjb3VsZCBiZSBkb25lIG1vcmUgZWZmaWNpZW50bHkgYnkgc2F2aW5nIHRoZSBUT00KIyBjYWxjdWxhdGVkIGR1cmluZyBtb2R1bGUgZGV0ZWN0aW9uLCBidXQgbGV0IHVzIGRvIGl0IGFnYWluIGhlcmUuCmRpc3NUT00gPSAxLVRPTXNpbWlsYXJpdHlGcm9tRXhwcihkYXRFeHByMCwgcG93ZXIgPSAyKTsKIyBUcmFuc2Zvcm0gZGlzc1RPTSB3aXRoIGEgcG93ZXIgdG8gbWFrZSBtb2RlcmF0ZWx5IHN0cm9uZyBjb25uZWN0aW9ucyBtb3JlIHZpc2libGUgaW4gdGhlIGhlYXRtYXAKcGxvdFRPTSA9IGRpc3NUT01eNzsKIyBTZXQgZGlhZ29uYWwgdG8gTkEgZm9yIGEgbmljZXIgcGxvdApkaWFnKHBsb3RUT00pID0gTkE7CnJvd25hbWVzKGRpc3NUT00pPWNvbG5hbWVzKGRhdEV4cHIwKQpjb2xuYW1lcyhkaXNzVE9NKT1jb2xuYW1lcyhkYXRFeHByMCkKCnNlbGVjdFRPTSA9IGRpc3NUT01bcm93bmFtZXMoZGlzc1RPTSkgJWluJSB1bmxpc3QoTWFya2Vyc19Mb28pLGNvbG5hbWVzKGRpc3NUT00pICVpbiUgdW5saXN0KE1hcmtlcnNfTG9vKV07CiMgVGhlcmXigJlzIG5vIHNpbXBsZSB3YXkgb2YgcmVzdHJpY3RpbmcgYSBjbHVzdGVyaW5nIHRyZWUgdG8gYSBzdWJzZXQgb2YgZ2VuZXMsIHNvIHdlIG11c3QgcmUtY2x1c3Rlci4Kc2VsZWN0VHJlZSA9IGhjbHVzdChhcy5kaXN0KHNlbGVjdFRPTSksIG1ldGhvZCA9ICJhdmVyYWdlIikKbW9kdWxlQ29sb3JzID0gbWVyZ2VkQ29sb3JzCm5hbWVzKG1vZHVsZUNvbG9ycykgPSByb3duYW1lcyhkaXNzVE9NKQpzZWxlY3RDb2xvcnMgPSBtb2R1bGVDb2xvcnNbbmFtZXMobW9kdWxlQ29sb3JzKSAlaW4lIHVubGlzdChNYXJrZXJzX0xvbyldCiMgT3BlbiBhIGdyYXBoaWNhbCB3aW5kb3cKc2l6ZUdyV2luZG93KDksOSkKIyBUYWtpbmcgdGhlIGRpc3NpbWlsYXJpdHkgdG8gYSBwb3dlciwgc2F5IDEwLCBtYWtlcyB0aGUgcGxvdCBtb3JlIGluZm9ybWF0aXZlIGJ5IGVmZmVjdGl2ZWx5IGNoYW5naW5nCiMgdGhlIGNvbG9yIHBhbGV0dGU7IHNldHRpbmcgdGhlIGRpYWdvbmFsIHRvIE5BIGFsc28gaW1wcm92ZXMgdGhlIGNsYXJpdHkgb2YgdGhlIHBsb3QKcGxvdERpc3MgPSBzZWxlY3RUT01eNzsKZGlhZyhwbG90RGlzcykgPSBOQTsKVE9NcGxvdChwbG90RGlzcywgc2VsZWN0VHJlZSwgc2VsZWN0Q29sb3JzLCBtYWluID0gIk5ldHdvcmsgaGVhdG1hcCBwbG90LCBzZWxlY3RlZCBnZW5lcyIsY29sPW15aGVhdGNvbCkKCmBgYAoKYGBge3J9CnBsb3REZW5kcm9BbmRDb2xvcnMoc2VsZWN0VHJlZSxzZWxlY3RDb2xvcnMsCiAgICAgICAgICAgICAgICAgICAgICJNb2R1bGUgY29sb3JzIiwKICAgICAgICAgICAgICAgICAgICAgZGVuZHJvTGFiZWxzID0gTlVMTCwgaGFuZyA9IDAuMDMsCiAgICAgICAgICAgICAgICAgICAgIGFkZEd1aWRlID0gVFJVRSwgZ3VpZGVIYW5nID0gMC4wNSkKYGBgCgpgYGB7cn0KbmV0JGNvbG9yc1tuYW1lcyhuZXQkY29sb3JzKSAlaW4lIHVubGlzdChNYXJrZXJzX0xvbyldCmBgYAoKV0dDTkEgdXNpbmcgdGhlIDIwMDAgZ2VuZXMgbW9zdCB2YXJpZWQgYnkgU2V1cmF0LCBkZXRlY3RzIHRoZSBmb2xsb3dpbmcgbnVtYmVyIG9mIG1hcmtlcnMuCgpgYGB7cn0KbGVuZ3RoKG5ldCRjb2xvcnNbbmFtZXMobmV0JGNvbG9ycykgJWluJSB1bmxpc3QoTWFya2Vyc19Mb28pXSkKYGBgCgpgYGB7cn0KdGFibGVNYXJrZXJzV0dDTkEgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChucm93ID0gNSxuY29sID0gNCkpCmNvbG5hbWVzKHRhYmxlTWFya2Vyc1dHQ05BKT1jKCJMb28uTC5JIiwiTG9vLkwuSUkuSVYiLCJMb28uTC5WLlZJIiwiTG9vLlBST0ciKQpyb3duYW1lcyh0YWJsZU1hcmtlcnNXR0NOQSk9YygiV0dDTkEuTC5JIiwiV0dDTkEuTm90IEdyb3VwZWQiLCJXR0NOQS5QUk9HIiwiV0dDTkEudW5rbm93bjEiLCAiV0dDTkEudW5rbm93bjIiKQoKbmV0JGNvbG9yc1t1bmlxdWUodW5saXN0KGxheWVycykpXQpgYGAKCgpgYGB7cn0KIyBBdHRlbnRpb24hIFRoZSBuZXh0IGxpc3QgbmVlZCB0byBiZSB1cGRhdGVkIGJ5IGhhbmQhCmdyb3VwcyA9IGxpc3QoIkwuSSI9NCwidW5rbm93bjEiPTMsIlBST0ciPTEsICJ1bmtub3duMiI9MiAsICJOb3QgR3JvdXBlZCI9MCApCgpmb3IobGF5ZXIxIGluIGMoIkwuSSIsInVua25vd24xIiwiUFJPRyIsInVua25vd24yIiwiTm90IEdyb3VwZWQiKSl7CiAgICBmb3IobGF5ZXIyIGluIGMoIkwuSSIsIkwuSUkuSVYiLCAiTC5WLlZJIiwiUFJPRyIpKXsKICAgIHRhYmxlTWFya2Vyc1dHQ05BW3Bhc3RlMCgiV0dDTkEuIixsYXllcjEpLHBhc3RlMCgiTG9vLiIsbGF5ZXIyKV0gPQogICAgICAgIHN1bShuYW1lcyhuZXQkY29sb3JzW25ldCRjb2xvcnMgJWluJSBncm91cHNbW2xheWVyMV1dXSkgJWluJSBNYXJrZXJzX0xvb1tbbGF5ZXIyXV0pCiAgICAjdGFibGVNYXJrZXJzV0dDTkFbcGFzdGUwKCJXR0NOQS4iLCJOb3QgR3JvdXBlZCIpLHBhc3RlMCgiTG9vLiIsbGF5ZXIyKV0gPQogICAgICMgICBzdW0obmFtZXMobmV0JGNvbG9yc1shbmV0JGNvbG9ycyAlaW4lIHVubGlzdChncm91cHMpXSkgJWluJSBNYXJrZXJzX0xvb1tbbGF5ZXIyXV0pCiAgICB9Cn0KCnRhYmxlTWFya2Vyc1dHQ05BCmBgYAoKCgoKYGBge3IgZmlnLndpZHRoPSAxMCwgZmlnLmhlaWdodD0gNTB9CgpkZW5kICU+JQpzZXQoImxhYmVscyIsIGlmZWxzZShsYWJlbHMoZGVuZCkgJWluJSByb3duYW1lcyhwY2FfMSlbcm93bmFtZXMocGNhXzEpICVpbiUgdW5saXN0KE1hcmtlcnNfTG9vKV0sIGxhYmVscyhkZW5kKSwgIiIpKSAlPiUKICBzZXQoImJyYW5jaGVzX2tfY29sb3IiLCB2YWx1ZSA9IGMoImdyYXk4MCIsIiM0REJCRDVGRiIsIiM5MUQxQzJGRiIgLCJncmF5ODAiLCIjRjM5QjdGRkYiLCIjRTY0QjM1RkYiLCIjM0M1NDg4RkYiKSwgayA9IDcpICU+JQogICAgc2V0KCJsYWJlbHNfY2V4Ij0wLjEpICU+JQogICAgc2V0KCJicmFuY2hlc19sd2QiLCAwLjUpICU+JQpwbG90X2hvcml6LmRlbmRyb2dyYW0oaG9yaXo9VCwgYXhlcz1ULHhsaW0gPSBjKDAsODApLCBkTGVhZiA9IC0xNSx0ZXh0X3BvcyA9IDMpCgpgYGAKCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAKCgoKCgoKCg==