Pallial neurons clustering

Extract pallial late neurons by k-means clustering

We extract the most mature pallial cells in two steps :

  • We seleted the glutamatergic neuronal branch
  • From this cells we extracted the one with the most mature signature score

Seletion the glutamatergic neuronal branch

We perform Kmeans clustering on the 3 cell state scores :

  • Apical progenitors AP
  • Sub-pallial neurons SP
  • Pallial neurons Pal

We then extract the glutamatergic neuron branch as the cluster with the highest mean Pallial neurons signature

Extract late neurons

We then extract the glutamatergic neuron with the highest mean Late neurons signature

Perform iterative clustering implemented in scrattch.hicat package

For more detail on the scrattch.hicat please refer to the package page.

Prepare the dataset for clustering with scrattch.hicat

Iterative clustering

Run the iterative clustering

The default iter_clust function use in this version of the scrattch.hicat package does not allow to set the k.param argument. We modified this function to allow this argument to be set to other values.

## [1] "test-iter_clust"
##   Finding nearest neighbors...DONE ~ 0.006 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.011 s
##   Build undirected graph from the weighted links...DONE ~ 0.024 s
##   Run louvain clustering on the graph ...DONE ~ 0.012 s
##   Return a community class
##   -Modularity value: 0.8698811 
##   -Number of clusters: 21[1] "test-iter_clust.1"
## [1] "test-iter_clust.2"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.3210654 
##   -Number of clusters: 2[1] "test-iter_clust.3"
## [1] "test-iter_clust.4"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.002 s
##   Build undirected graph from the weighted links...DONE ~ 0.004 s
##   Run louvain clustering on the graph ...DONE ~ 0.002 s
##   Return a community class
##   -Modularity value: 0.7275928 
##   -Number of clusters: 9[1] "test-iter_clust.4.1"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.5114614 
##   -Number of clusters: 3[1] "test-iter_clust.4.2"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.002 s
##   Build undirected graph from the weighted links...DONE ~ 0.004 s
##   Run louvain clustering on the graph ...DONE ~ 0.002 s
##   Return a community class
##   -Modularity value: 0.7128587 
##   -Number of clusters: 7[1] "test-iter_clust.5"
## [1] "test-iter_clust.6"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.5893365 
##   -Number of clusters: 4[1] "test-iter_clust.7"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.4688921 
##   -Number of clusters: 3[1] "test-iter_clust.8"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.6325457 
##   -Number of clusters: 5[1] "test-iter_clust.9"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.002 s
##   Build undirected graph from the weighted links...DONE ~ 0.004 s
##   Run louvain clustering on the graph ...DONE ~ 0.002 s
##   Return a community class
##   -Modularity value: 0.7003194 
##   -Number of clusters: 6[1] "test-iter_clust.10"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.626505 
##   -Number of clusters: 4[1] "test-iter_clust.11"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.003 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.7033592 
##   -Number of clusters: 7[1] "test-iter_clust.12"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.5403066 
##   -Number of clusters: 3

Transfert these ident on the full dataset

## [1] "Cluster_23: 109 Cells"
## [1] "Cluster_18: 86 Cells"
## [1] "Cluster_24: 45 Cells"
## [1] "Cluster_26: 26 Cells"
## [1] "Cluster_19: 48 Cells"
## [1] "Cluster_14: 16 Cells"
## [1] "Cluster_1: 33 Cells"
## [1] "Cluster_22: 37 Cells"
## [1] "Cluster_25: 66 Cells"
## [1] "Cluster_21: 24 Cells"
## [1] "Cluster_20: 31 Cells"
## [1] "Cluster_16: 24 Cells"
## [1] "Cluster_13: 16 Cells"

Refine the cell type taxonomie on the most mature clusters

Prepare data for scrattch.hicat

Hierarchical clustering

Scrattch.hicat perform hierarchical clustering on a cluster correlation matrix based on median expression values for the top 50 most DEGs between every pair of clusters. It estimates branch confidence level using a bootstrap approach implemented by the pvclust package

## Bootstrap (r = 0.5)... Done.
## Bootstrap (r = 0.6)... Done.
## Bootstrap (r = 0.7)... Done.
## Bootstrap (r = 0.8)... Done.
## Bootstrap (r = 0.9)... Done.
## Bootstrap (r = 1.0)... Done.
## Bootstrap (r = 1.1)... Done.
## Bootstrap (r = 1.2)... Done.
## Bootstrap (r = 1.3)... Done.
## Bootstrap (r = 1.4)... Done.
Manuscript Fig. 2D dendrogramme

Manuscript Fig. 2D dendrogramme

Identify core cells using centroide classifier (Manuscript Fig. 2C)

Because some cells display intermediate transcriptomic signatures between two closely related clusters we used only clusters’ signatures on their core cells

## 
 Running iteration 1 of 100.        
 Running iteration 2 of 100.        
 Running iteration 3 of 100.        
 Running iteration 4 of 100.        
 Running iteration 5 of 100.        
 Running iteration 6 of 100.        
 Running iteration 7 of 100.        
 Running iteration 8 of 100.        
 Running iteration 9 of 100.        
 Running iteration 10 of 100.        
 Running iteration 11 of 100.        
 Running iteration 12 of 100.        
 Running iteration 13 of 100.        
 Running iteration 14 of 100.        
 Running iteration 15 of 100.        
 Running iteration 16 of 100.        
 Running iteration 17 of 100.        
 Running iteration 18 of 100.        
 Running iteration 19 of 100.        
 Running iteration 20 of 100.        
 Running iteration 21 of 100.        
 Running iteration 22 of 100.        
 Running iteration 23 of 100.        
 Running iteration 24 of 100.        
 Running iteration 25 of 100.        
 Running iteration 26 of 100.        
 Running iteration 27 of 100.        
 Running iteration 28 of 100.        
 Running iteration 29 of 100.        
 Running iteration 30 of 100.        
 Running iteration 31 of 100.        
 Running iteration 32 of 100.        
 Running iteration 33 of 100.        
 Running iteration 34 of 100.        
 Running iteration 35 of 100.        
 Running iteration 36 of 100.        
 Running iteration 37 of 100.        
 Running iteration 38 of 100.        
 Running iteration 39 of 100.        
 Running iteration 40 of 100.        
 Running iteration 41 of 100.        
 Running iteration 42 of 100.        
 Running iteration 43 of 100.        
 Running iteration 44 of 100.        
 Running iteration 45 of 100.        
 Running iteration 46 of 100.        
 Running iteration 47 of 100.        
 Running iteration 48 of 100.        
 Running iteration 49 of 100.        
 Running iteration 50 of 100.        
 Running iteration 51 of 100.        
 Running iteration 52 of 100.        
 Running iteration 53 of 100.        
 Running iteration 54 of 100.        
 Running iteration 55 of 100.        
 Running iteration 56 of 100.        
 Running iteration 57 of 100.        
 Running iteration 58 of 100.        
 Running iteration 59 of 100.        
 Running iteration 60 of 100.        
 Running iteration 61 of 100.        
 Running iteration 62 of 100.        
 Running iteration 63 of 100.        
 Running iteration 64 of 100.        
 Running iteration 65 of 100.        
 Running iteration 66 of 100.        
 Running iteration 67 of 100.        
 Running iteration 68 of 100.        
 Running iteration 69 of 100.        
 Running iteration 70 of 100.        
 Running iteration 71 of 100.        
 Running iteration 72 of 100.        
 Running iteration 73 of 100.        
 Running iteration 74 of 100.        
 Running iteration 75 of 100.        
 Running iteration 76 of 100.        
 Running iteration 77 of 100.        
 Running iteration 78 of 100.        
 Running iteration 79 of 100.        
 Running iteration 80 of 100.        
 Running iteration 81 of 100.        
 Running iteration 82 of 100.        
 Running iteration 83 of 100.        
 Running iteration 84 of 100.        
 Running iteration 85 of 100.        
 Running iteration 86 of 100.        
 Running iteration 87 of 100.        
 Running iteration 88 of 100.        
 Running iteration 89 of 100.        
 Running iteration 90 of 100.        
 Running iteration 91 of 100.        
 Running iteration 92 of 100.        
 Running iteration 93 of 100.        
 Running iteration 94 of 100.        
 Running iteration 95 of 100.        
 Running iteration 96 of 100.        
 Running iteration 97 of 100.        
 Running iteration 98 of 100.        
 Running iteration 99 of 100.        
 Running iteration 100 of 100.

Manuscript element Fig. 2C

Manuscript element Fig. 2C

Sub-pallial neurons clustering

Load QC filtered dataset

Extract sub-pallial late neurons by k-means clustering on the cell state space

Selection of sub-pallial neuronal branche

As for the glutamaterigic neurons, we extract the most mature sub-pallial cells in two steps :

  • We seleted thesubplallial neuronal branche
  • From this we extracted cells with the most mature signature

We perform K-means clustering on the 3 cell state scores :

  • Apical progenitors AP
  • Sub-pallial neurons SP
  • Pallial neurons Pal

We then extract the GABAergic neuron branche as beeing the K-means cluster with the highest mean Sub-Pallial neurons signature

Extract late sub-pallial neurons

Perform iterative clustering implemented in scrattch.hicat package

We perform the clustering procedure as for the glutamatergic neurons

Prepare the dataset for clustering with scrattch.hicat

Iterative clustering

Run the iterative clustering

## [1] "test-iter_clust"
##   Finding nearest neighbors...DONE ~ 0.002 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.008 s
##   Build undirected graph from the weighted links...DONE ~ 0.013 s
##   Run louvain clustering on the graph ...DONE ~ 0.006 s
##   Return a community class
##   -Modularity value: 0.7894448 
##   -Number of clusters: 11[1] "test-iter_clust.1"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.4405265 
##   -Number of clusters: 3[1] "test-iter_clust.2"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.002 s
##   Build undirected graph from the weighted links...DONE ~ 0.003 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.6305993 
##   -Number of clusters: 4[1] "test-iter_clust.3"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0 s
##   Return a community class
##   -Modularity value: 0.4473667 
##   -Number of clusters: 2[1] "test-iter_clust.4"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.002 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.2015328 
##   -Number of clusters: 2[1] "test-iter_clust.5"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.003 s
##   Build undirected graph from the weighted links...DONE ~ 0.007 s
##   Run louvain clustering on the graph ...DONE ~ 0.003 s
##   Return a community class
##   -Modularity value: 0.6771333 
##   -Number of clusters: 7[1] "test-iter_clust.6"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.002 s
##   Build undirected graph from the weighted links...DONE ~ 0.004 s
##   Run louvain clustering on the graph ...DONE ~ 0.002 s
##   Return a community class
##   -Modularity value: 0.6456297 
##   -Number of clusters: 4

Broad neuronal types dotplot (Fig. 2B)

Hierarchical clustering using scrattch.hicat tools

Prepare data for used by scrattch.hicat

Hierarchical clustering

Scrattch.hicat perform hierarchical clustering on a cluster correlation matrix based on median expression values for the top 50 most DEGs between every pair of clusters. It estimates branch confidence level using a bootstrap approach implemented by the pvclust package

## Bootstrap (r = 0.5)... Done.
## Bootstrap (r = 0.6)... Done.
## Bootstrap (r = 0.7)... Done.
## Bootstrap (r = 0.8)... Done.
## Bootstrap (r = 0.9)... Done.
## Bootstrap (r = 1.0)... Done.
## Bootstrap (r = 1.1)... Done.
## Bootstrap (r = 1.2)... Done.
## Bootstrap (r = 1.3)... Done.
## Bootstrap (r = 1.4)... Done.
## Bootstrap (r = 0.5)... Done.
## Bootstrap (r = 0.6)... Done.
## Bootstrap (r = 0.7)... Done.
## Bootstrap (r = 0.8)... Done.
## Bootstrap (r = 0.9)... Done.
## Bootstrap (r = 1.0)... Done.
## Bootstrap (r = 1.1)... Done.
## Bootstrap (r = 1.2)... Done.
## Bootstrap (r = 1.3)... Done.
## Bootstrap (r = 1.4)... Done.

Session Info

## [1] "30 novembre, 2020, 10,34"
## 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] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] pvclust_2.2-0         limma_3.42.0          Rphenograph_0.99.1   
##  [4] igraph_1.2.5          wesanderson_0.3.6     ggExtra_0.9          
##  [7] tidyr_1.0.0           ggdendro_0.1-20       scrattch.vis_0.0.210 
## [10] purrr_0.3.3           ggbeeswarm_0.6.0      RColorBrewer_1.1-2   
## [13] Seurat_2.3.4          cowplot_1.0.0         ggplot2_3.2.1        
## [16] Matrix_1.2-17         matrixStats_0.55.0    dplyr_0.8.3          
## [19] dendextend_1.12.0     scrattch.hicat_0.0.16
## 
## 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          lazyeval_0.2.2      splines_3.6.3      
##   [7] digest_0.6.25       foreach_1.4.7       htmltools_0.5.0    
##  [10] viridis_0.5.1       lars_1.2            gdata_2.18.0       
##  [13] magrittr_1.5        checkmate_1.9.4     cluster_2.1.0      
##  [16] mixtools_1.1.0      ROCR_1.0-7          R.utils_2.9.0      
##  [19] colorspace_1.4-1    xfun_0.18           crayon_1.3.4       
##  [22] jsonlite_1.7.0      zeallot_0.1.0       survival_2.44-1.1  
##  [25] zoo_1.8-6           iterators_1.0.12    ape_5.3            
##  [28] glue_1.4.1          gtable_0.3.0        kernlab_0.9-29     
##  [31] prabclus_2.3-1      DEoptimR_1.0-8      scales_1.1.0       
##  [34] bibtex_0.4.2        miniUI_0.1.1.1      Rcpp_1.0.5         
##  [37] metap_1.1           dtw_1.21-3          viridisLite_0.3.0  
##  [40] xtable_1.8-4        htmlTable_1.13.2    reticulate_1.13    
##  [43] foreign_0.8-72      bit_4.0.4           proxy_0.4-23       
##  [46] mclust_5.4.5        SDMTools_1.1-221.1  Formula_1.2-3      
##  [49] stats4_3.6.3        tsne_0.1-3          htmlwidgets_1.5.1  
##  [52] httr_1.4.1          gplots_3.0.1.1      fpc_2.2-3          
##  [55] ellipsis_0.3.0      acepack_1.4.1       modeltools_0.2-22  
##  [58] ica_1.0-2           farver_2.0.1        pkgconfig_2.0.3    
##  [61] R.methodsS3_1.7.1   flexmix_2.3-15      nnet_7.3-14        
##  [64] tidyselect_0.2.5    labeling_0.3        rlang_0.4.7        
##  [67] reshape2_1.4.3      later_1.0.0         munsell_0.5.0      
##  [70] tools_3.6.3         ggridges_0.5.1      evaluate_0.14      
##  [73] stringr_1.4.0       fastmap_1.0.1       yaml_2.2.1         
##  [76] npsurv_0.4-0        knitr_1.26          bit64_4.0.2        
##  [79] fitdistrplus_1.0-14 robustbase_0.93-5   caTools_1.17.1.2   
##  [82] RANN_2.6.1          pbapply_1.4-2       nlme_3.1-141       
##  [85] mime_0.7            R.oo_1.23.0         hdf5r_1.3.2.9000   
##  [88] compiler_3.6.3      rstudioapi_0.11     beeswarm_0.2.3     
##  [91] png_0.1-7           lsei_1.2-0          tibble_2.1.3       
##  [94] stringi_1.4.6       highr_0.8           lattice_0.20-41    
##  [97] vctrs_0.2.0         pillar_1.4.2        lifecycle_0.1.0    
## [100] Rdpack_0.11-0       lmtest_0.9-37       data.table_1.12.6  
## [103] bitops_1.0-6        irlba_2.3.3         gbRd_0.4-11        
## [106] httpuv_1.5.2        R6_2.4.1            latticeExtra_0.6-28
## [109] promises_1.1.0      KernSmooth_2.23-15  gridExtra_2.3      
## [112] vipor_0.4.5         codetools_0.2-16    MASS_7.3-53        
## [115] gtools_3.8.1        assertthat_0.2.1    withr_2.1.2        
## [118] diptest_0.75-7      parallel_3.6.3      doSNOW_1.0.18      
## [121] grid_3.6.3          rpart_4.1-15        class_7.3-17       
## [124] rmarkdown_2.5       segmented_1.0-0     Rtsne_0.15         
## [127] shiny_1.4.0         base64enc_0.1-3

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

LS0tCnRpdGxlOiAiQ2x1c3RlcmluZyB0aGUgcGFsbGlhbCBuZXVyb25hbCBwb3B1bGF0aW9uIgphdXRob3I6CiAgIC0gTWF0dGhpZXUgTW9yZWF1XltJbnN0aXR1dGUgb2YgUHN5Y2hpYXRyeSBhbmQgTmV1cm9zY2llbmNlIG9mIFBhcmlzLCBJTlNFUk0gVTEyNjYsIDc1MDE0LCBQYXJpcywgRnJhbmNlLCBtYXR0aGlldS5tb3JlYXVAaW5zZXJtLmZyXSBbIVtdKGh0dHBzOi8vb3JjaWQub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvaW1hZ2VzL29yY2lkXzE2eDE2LnBuZyldKGh0dHBzOi8vb3JjaWQub3JnLzAwMDAtMDAwMi0yNTkyLTIzNzMpCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgZGZfcHJpbnQ6IHRpYmJsZQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICBpbmNsdWRlczoKICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbAogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KaDEgewogIGZvbnQtc2l6ZTogMzRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICNlNjRkMDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDQwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDIgewogIGZvbnQtc2l6ZTogMzBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDMgewogIGZvbnQtc2l6ZTogMjRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDQgewogIGZvbnQtc2l6ZTogMjBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDUgewogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KCi5zY3JvbGwtMTAwIHsKICBtYXgtaGVpZ2h0OiAyMDBweDsKICBvdmVyZmxvdy15OiBhdXRvOwogIGJhY2tncm91bmQtY29sb3I6IGluaGVyaXQ7Cn0KCnAgewogIGZvbnQtc2l6ZTogMTZweDsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQpgYGAKCiMgTG9hZCBsaWJyYXJpZXMgYW5kIFFDRmlsdGVyZWQgZGF0YXNldAoKYGBge3IgfQojbG9hZCBsaWJyYXJ5CmxpYnJhcnkoc2NyYXR0Y2guaGljYXQpCmxpYnJhcnkoZGVuZGV4dGVuZCkKbGlicmFyeShkcGx5cikKbGlicmFyeShtYXRyaXhTdGF0cykKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShzY3JhdHRjaC52aXMpCmxpYnJhcnkoZ2dkZW5kcm8pCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dFeHRyYSkKbGlicmFyeSh3ZXNhbmRlcnNvbikKCiNTZXQgZ2dwbG90IHRoZW1lCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKYGBge3J9ClFDRmlsdGVyZWQuZGF0YSA8LSByZWFkUkRTKCIuL1FDLmZpbHRlcmVkLmNlbGxzLlJEUyIpCmBgYAoKIyBQYWxsaWFsIG5ldXJvbnMgY2x1c3RlcmluZwoKIyMgRXh0cmFjdCBwYWxsaWFsIGxhdGUgbmV1cm9ucyBieSBrLW1lYW5zIGNsdXN0ZXJpbmcKCldlIGV4dHJhY3QgdGhlIG1vc3QgbWF0dXJlIHBhbGxpYWwgY2VsbHMgaW4gdHdvIHN0ZXBzIDoKCi0gV2Ugc2VsZXRlZCB0aGUgZ2x1dGFtYXRlcmdpYyBuZXVyb25hbCBicmFuY2gKLSBGcm9tIHRoaXMgY2VsbHMgd2UgZXh0cmFjdGVkIHRoZSBvbmUgd2l0aCB0aGUgbW9zdCBtYXR1cmUgc2lnbmF0dXJlIHNjb3JlCgojIyMgU2VsZXRpb24gdGhlIGdsdXRhbWF0ZXJnaWMgbmV1cm9uYWwgYnJhbmNoCmBgYHtyIGZpZy5kaW09Yyg5LCA4KX0KIyBDZWxsIHN0YXRlIHNjb3JlcyB1c2UgdG8gc2VsZWN0CkZlYXR1cmVQbG90KG9iamVjdCA9IFFDRmlsdGVyZWQuZGF0YSwKICAgICAgICAgICAgZmVhdHVyZXMucGxvdCA9IGMoIkFQX3NpZ25hdHVyZTEiLCAiU1Bfc2lnbmF0dXJlMSIsICJQYWxfc2lnbmF0dXJlMSIpLAogICAgICAgICAgICBjb2xzLnVzZSA9IHJldihicmV3ZXIucGFsKDEwLCJTcGVjdHJhbCIpKSwKICAgICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgICAgICBvdmVybGF5ID0gRiwKICAgICAgICAgICAgZGFyay50aGVtZSA9IEYKICAgICAgICAgICAgKQpgYGAKCldlIHBlcmZvcm0gS21lYW5zIGNsdXN0ZXJpbmcgb24gdGhlIDMgY2VsbCBzdGF0ZSBzY29yZXMgOgoKLSBBcGljYWwgcHJvZ2VuaXRvcnMgYEFQYAotIFN1Yi1wYWxsaWFsIG5ldXJvbnMgYFNQYAotIFBhbGxpYWwgbmV1cm9ucyBgUGFsYAoKYGBge3J9CiMgSy1tZWFucyBjbHVzdGVyaW5nIGJhc2VkIG9uIEFQLCBTUCBhbmQgUGFsIHNpZ25hdHVyZSBzY29yZXMKc2V0LnNlZWQoMTAwKQpjbCA8LSBrbWVhbnMoY2JpbmQoUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSRBUF9zaWduYXR1cmUxLAogICAgICAgICAgICAgICAgICAgUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSRTUF9zaWduYXR1cmUxLAogICAgICAgICAgICAgICAgICAgUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSRQYWxfc2lnbmF0dXJlMSksIDMpCgpRQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJGttZWFuQ2x1c3QgPC0gcGFzdGUwKCJDbHVzdC4iLGNsJGNsdXN0ZXIpCmBgYAoKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQpjb2wucGFsIDwtIHdlc19wYWxldHRlKCJHcmFuZEJ1ZGFwZXN0MSIsIDMsIHR5cGUgPSAiZGlzY3JldGUiKQoKcDEgPC0gZ2dwbG90KFFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEsIGFlcyh4PVBhbF9zaWduYXR1cmUxLCB5PVNQX3NpZ25hdHVyZTEsIGNvbG91ciA9IGttZWFuQ2x1c3QpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2wucGFsKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKZ2dNYXJnaW5hbChwMSwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiKQoKRGltUGxvdChRQ0ZpbHRlcmVkLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGNvbHMudXNlID0gY29sLnBhbCwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gVCkKYGBgCgpXZSB0aGVuIGV4dHJhY3QgdGhlIGdsdXRhbWF0ZXJnaWMgbmV1cm9uIGJyYW5jaCBhcyB0aGUgY2x1c3RlciB3aXRoIHRoZSBoaWdoZXN0IG1lYW4gYFBhbGxpYWwgbmV1cm9uc2Agc2lnbmF0dXJlCgpgYGB7cn0KIyBGaW5kIHRoZSBrLW1lYW5zIGNsdXN0ZXIgd2l0aCB0aGUgaGlnaGVzdCBtZWFuIFBhbF9zaWduYXR1cmUxIHNjb3JlCk1lYW5LY2x1c3QuUGFsc2NvcmUgPC0gYWdncmVnYXRlKFBhbF9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSwgbWVhbikKUGFsY2x1c3QgPC0gTWVhbktjbHVzdC5QYWxzY29yZSAlPiUgZmlsdGVyKFBhbF9zaWduYXR1cmUxID09IG1heChQYWxfc2lnbmF0dXJlMSkpICU+JSBwdWxsKGttZWFuQ2x1c3QpCgojIEV4dHJhY3QgYmFyY29kZXMgYW5kIGZpbHRlciB0aGUgc2V1cmF0IG9iamVjdApHbHV0LmNlbGxzIDwtIFFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihrbWVhbkNsdXN0ID09IFBhbGNsdXN0KSAlPiUgcHVsbChCYXJjb2RlcykKR2x1dC5RQ0ZpbHRlcmVkLmRhdGEgPC0gIFN1YnNldERhdGEoUUNGaWx0ZXJlZC5kYXRhLCBjZWxscy51c2UgPSBHbHV0LmNlbGxzICwgc3Vic2V0LnJhdyA9IFQsICBkby5jbGVhbiA9IEYpCmBgYAoKCiMjIyBFeHRyYWN0IGxhdGUgbmV1cm9ucwoKYGBge3J9CiMgSy1tZWFucyBjbHVzdGVyaW5nIGJhc2VkIG9uIEVOIGFuZCBMTiBzaWduYXR1cmUgc2NvcmVzCmNsIDwtIGttZWFucyhjYmluZChHbHV0LlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkRU5fc2lnbmF0dXJlMSwgR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJExOX3NpZ25hdHVyZTEpLCAyKQoKR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJGttZWFuQ2x1c3QgPC0gcGFzdGUwKCJDbHVzdC4iLGNsJGNsdXN0ZXIpCmBgYAoKYGBge3J9CiMgRmluZCB0aGUgay1tZWFucyBjbHVzdGVyIHdpdGggdGhlIGhpZ2hlc3QgbWVhbiBMYXRlX3NpZ25hdHVyZTEgc2NvcmUKTWVhbktjbHVzdC5MTnNjb3JlIDwtIGFnZ3JlZ2F0ZShMTl9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhLCBtZWFuKQpMTi5jbHVzdCA8LSBNZWFuS2NsdXN0LkxOc2NvcmUgJT4lIGZpbHRlcihMTl9zaWduYXR1cmUxID09IG1heChMTl9zaWduYXR1cmUxKSkgJT4lIHB1bGwoa21lYW5DbHVzdCkKCiMgRXh0cmFjdCBiYXJjb2RlcwpMTi5jZWxscyA8LSBHbHV0LlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihrbWVhbkNsdXN0ID09IExOLmNsdXN0KSAlPiUgcHVsbChCYXJjb2RlcykKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbC5wYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgMiwgdHlwZSA9ICJkaXNjcmV0ZSIpCgpwMSA8LSBnZ3Bsb3QoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhLCBhZXMoeD1MTl9zaWduYXR1cmUxLCB5PUVOX3NpZ25hdHVyZTEsIGNvbG91ciA9IGttZWFuQ2x1c3QpKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSBwYXN0ZTAobGVuZ3RoKExOLmNlbGxzKSwgIiBMYXRlIE5ldXJvbnMiKSwgeCA9IDEsIHkgPTEuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sLnBhbCkgKwogIGdlb21fcG9pbnQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpIApnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpIDsgcm0ocDEpCgpEaW1QbG90KEdsdXQuUUNGaWx0ZXJlZC5kYXRhLAogICAgICAgICBncm91cC5ieSA9ICJrbWVhbkNsdXN0IiwKICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgICBjb2xzLnVzZSA9IGNvbC5wYWwsCiAgICAgICAgIGRpbS4xID0gMSwKICAgICAgICAgZGltLjIgPSAyLAogICAgICAgICBkby5sYWJlbD1ULAogICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICAgbm8ubGVnZW5kID0gVCkKYGBgCgpXZSB0aGVuIGV4dHJhY3QgdGhlIGdsdXRhbWF0ZXJnaWMgbmV1cm9uIHdpdGggdGhlIGhpZ2hlc3QgbWVhbiBgTGF0ZSBuZXVyb25zYCBzaWduYXR1cmUKCmBgYHtyfQojIEZpbHRlciB0aGUgc2V1cmF0IG9iamVjdApHbHV0LlFDRmlsdGVyZWQuZGF0YSA8LSAgU3Vic2V0RGF0YShHbHV0LlFDRmlsdGVyZWQuZGF0YSwgY2VsbHMudXNlID0gTE4uY2VsbHMgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KRGltUGxvdChHbHV0LlFDRmlsdGVyZWQuZGF0YSwKICAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICAgY29scy51c2UgPSAiIzk2OTY5NiIsCiAgICAgICAgIGRpbS4xID0gMSwKICAgICAgICAgZGltLjIgPSAyLAogICAgICAgICBkby5sYWJlbD1GLAogICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICAgbm8ubGVnZW5kID0gVCkKYGBgCgoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgIkdsdXQuUUNGaWx0ZXJlZC5kYXRhIl0pCmBgYAoKIyMgUGVyZm9ybSBpdGVyYXRpdmUgY2x1c3RlcmluZyBpbXBsZW1lbnRlZCBpbiBzY3JhdHRjaC5oaWNhdCBwYWNrYWdlCgpGb3IgbW9yZSBkZXRhaWwgb24gdGhlIHNjcmF0dGNoLmhpY2F0IHBsZWFzZSByZWZlciB0byB0aGUgW3BhY2thZ2UgcGFnZV0oaHR0cHM6Ly9naXRodWIuY29tL0FsbGVuSW5zdGl0dXRlL3NjcmF0dGNoLmhpY2F0KS4gCgojIyMgUHJlcGFyZSB0aGUgZGF0YXNldCBmb3IgY2x1c3RlcmluZyB3aXRoIHNjcmF0dGNoLmhpY2F0CgojIyMjIEluZGVwZW5kZW50IGdlbmUgZmlsdGVyaW5nCgpXZSBkZWNpZGUgdG8gZXhjbHVkZSAqKkNlbGwgY3ljbGUqKiwgKipyaWJvc29tYWwqKiBhbmQgKiptaXRvY2hvbmRyaWFsKiogYXNzb2NpYXRlZCBnZW5lcywgYXMgd2VsbCBhcyAqKlhpc3QqKiBmb3IgdGhlIGNsdXN0ZXJpbmcgc3RlcC4KCmBgYHtyfQojIEV4Y2x1ZGUgY2VsbCBjeWNsZSBhc3NvY2lhdGVkIGdlbmVzCnMuZ2VuZXMgPC0gYygiTWNtNSIsICJQY25hIiwgIlR5bTUiLCAiRmVuMSIsICJNY20yIiwgIk1jbTQiLCAiUnJtMSIsICJVbmciLCAiR2luczIiLCAiTWNtNiIsICJDZGNhNyIsICJEdGwiLCAiUHJpbTEiLCAiVWhyZjEiLCAiTWxmMWlwIiwgIkhlbGxzIiwgIlJmYzIiLCAiUmFwMiIsICJOYXNwIiwgIlJhZDUxYXAxIiwgIkdtbm4iLCAiV2RyNzYiLCAiU2xicCIsICJDY25lMiIsICJVYnI3IiwgIlBvbGQzIiwgIk1zaDIiLCAiQXRhZDIiLCAiUmFkNTEiLCAiUnJtMiIsICJDZGM0NSIsICJDZGM2IiwgIkV4bzEiLCAiVGlwaW4iLCAiRHNjYzEiLCAiQmxtIiwgIiBDYXNwOGFwMiIsICJVc3AxIiwgIkNsc3BuIiwgIlBvbGExIiwgIkNoYWYxYiIsICJCcmlwMSIsICJFMmY4IikKZzJtLmdlbmVzIDwtIGMoIkhtZ2IyIiwgIkRkazEiLCJOdXNhcDEiLCAiVWJlMmMiLCAiQmlyYzUiLCAiVHB4MiIsICJUb3AyYSIsICJOZGM4MCIsICJDa3MyIiwgIk51ZjIiLCAiQ2tzMWIiLCAiTWtpNjciLCAiVG1wbyIsICIgQ2VucGsiLCAiVGFjYzMiLCAiRmFtNjRhIiwgIlNtYzQiLCAiQ2NuYjIiLCAiQ2thcDJsIiwgIkNrYXAyIiwgIkF1cmtiIiwgIkJ1YjEiLCAiS2lmMTEiLCAiQW5wMzJlIiwgIlR1YmI0YiIsICJHdHNlMSIsICJraWYyMGIiLCAiSGp1cnAiLCAiQ2RjYTMiLCAiSG4xIiwgIkNkYzIwIiwgIlR0ayIsICJDZGMyNWMiLCAia2lmMmMiLCAiUmFuZ2FwMSIsICJOY2FwZDIiLCAiRGxnYXA1IiwgIkNkY2EyIiwgIkNkY2E4IiwgIkVjdDIiLCAiS2lmMjMiLCAiSG1tciIsICJBdXJrYSIsICJQc3JjMSIsICJBbmxuIiwgIkxiciIsICJDa2FwNSIsICJDZW5wZSIsICJDdGNmIiwgIk5lazIiLCAiRzJlMyIsICJHYXMybDMiLCAiQ2J4NSIsICJDZW5wYSIpCgojIEV4Y2x1ZGUgZ2VuZXMgZGV0ZWN0ZWQgaW4gbGVzcyB0aGFuIDMgY2VsbHMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhHbHV0LlFDRmlsdGVyZWQuZGF0YUBkYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbd2hpY2goeCA9IG51bS5jZWxscyA+PSAzKV0pCgpHZW5lc1RvUmVtb3ZlIDwtIGMoZ3JlcChwYXR0ZXJuID0gIiheUnBsfF5ScHN8Xk1ycCkiLCB4ID0gZ2VuZXMudXNlLCB2YWx1ZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgZ3JlcChwYXR0ZXJuID0gIl5tdC0iLCB4ID0gZ2VuZXMudXNlLCB2YWx1ZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgIlhpc3QiLCBzLmdlbmVzLCBnMm0uZ2VuZXMpCgpnZW5lcy51c2UgPC0gZ2VuZXMudXNlWyFnZW5lcy51c2UgJWluJSBHZW5lc1RvUmVtb3ZlXQpgYGAKCiMjIyMgTm9ybWFsaXphdGlvbgpgYGB7cn0KZGdlTWF0cml4X2NvdW50IDwtIGFzLm1hdHJpeChHbHV0LlFDRmlsdGVyZWQuZGF0YUByYXcuZGF0YSlbcm93bmFtZXMoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAcmF3LmRhdGEpICVpbiUgZ2VuZXMudXNlLF0KZGdlTWF0cml4X2NwbSA8LSBjcG0oZGdlTWF0cml4X2NvdW50KQpub3JtLmRhdCA8LSBsb2cyKGRnZU1hdHJpeF9jcG0gKyAxKQpgYGAKCmBgYHtyfQpub3JtLmRhdCA8LSBNYXRyaXgobm9ybS5kYXQsIHNwYXJzZSA9IFRSVUUpCkRhdGEubWF0cml4IDwtIGxpc3QocmF3LmRhdD1kZ2VNYXRyaXhfY291bnQsIG5vcm0uZGF0PW5vcm0uZGF0KQphdHRhY2goRGF0YS5tYXRyaXgpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiR2x1dC5RQ0ZpbHRlcmVkLmRhdGEiLCAiRGF0YS5tYXRyaXgiKV0pCmBgYAoKIyMjIyBTZWxlY3QgZmVhdHVyZXMgdXNlZCB0byByZW1vdmUgUENzIHdoaWNoIHdvdWxkIGNvcnJlbGF0ZSB3aXRoIHVud2FudGVkIHNvdXJjZXMgb2YgdmFyaWF0aW9uCgpgYGB7cn0KZ2VuZS5jb3VudHMgPC0gbG9nMihjb2xTdW1zKGFzLm1hdHJpeChEYXRhLm1hdHJpeCRub3JtLmRhdCkgPiAwKSkKblVNSSA8LSBsb2cyKGNvbFN1bXMoRGF0YS5tYXRyaXgkcmF3LmRhdCkpCnBlcmN0TWl0byA8LSBHbHV0LlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkcGVyY2VudC5taXRvCnBlcmN0UmlibyA8LSBHbHV0LlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkcGVyY2VudC5yaWJvCgpybS5laWdlbiA8LSBhcy5tYXRyaXgoY2JpbmQoZ2VuZS5jb3VudHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuVU1JLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyY3RNaXRvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyY3RSaWJvKSkKCnJvdy5uYW1lcyhybS5laWdlbikgPC0gbmFtZXMoZ2VuZS5jb3VudHMpCgpjb2xuYW1lcyhybS5laWdlbikgPC0gYygibG9nMm5HZW5lcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJsb2cyblVNSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjdE1pdG8iLAogICAgICAgICAgICAgICAgICAgICAgICAicGVyY3RSaWJvIikKCnJtKGdlbmUuY291bnRzLCBuVU1JLCBwZXJjdE1pdG8sIHBlcmN0UmlibykKYGBgCgojIyMgSXRlcmF0aXZlIGNsdXN0ZXJpbmcKCmBgYHtyfQojIFBhcmFtZXRlcnMgZm9yIGl0ZXJhdGl2ZSBjbHVzdGVyaW5nCmRlLnBhcmFtIDwtIGRlX3BhcmFtKHBhZGoudGggICAgID0gMC4wMSwgCiAgICAgICAgICAgICAgICAgICAgIGxmYy50aCAgICAgID0gMC45LAogICAgICAgICAgICAgICAgICAgICBsb3cudGggICAgICA9IDEsIAogICAgICAgICAgICAgICAgICAgICBxMS50aCAgICAgICA9IDAuMjUsIAogICAgICAgICAgICAgICAgICAgICBxMi50aCAgICAgICA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgIHEuZGlmZi50aCAgID0gMC43LAogICAgICAgICAgICAgICAgICAgICBkZS5zY29yZS50aCA9IDMwLAogICAgICAgICAgICAgICAgICAgICBtaW4uY2VsbHMgPSAxMCkKYGBgCgojIyMjIFJ1biB0aGUgaXRlcmF0aXZlIGNsdXN0ZXJpbmcKClRoZSBkZWZhdWx0IGl0ZXJfY2x1c3QgZnVuY3Rpb24gdXNlIGluIHRoaXMgdmVyc2lvbiBvZiB0aGUgc2NyYXR0Y2guaGljYXQgcGFja2FnZSBkb2VzIG5vdCBhbGxvdyB0byBzZXQgdGhlIGsucGFyYW0gYXJndW1lbnQuIFdlIG1vZGlmaWVkIHRoaXMgZnVuY3Rpb24gdG8gYWxsb3cgdGhpcyBhcmd1bWVudCB0byBiZSBzZXQgdG8gb3RoZXIgdmFsdWVzLgoKYGBge3IgY2xhc3Mub3V0cHV0PSJzY3JvbGwtMTAwIn0KIyBQZXJmb3JtIHRoZSBpdGVyYXRpdmUgY2x1c3RlcmluZyAKaXRlci5yZXN1bHQgPC0gaXRlcl9jbHVzdChub3JtLmRhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRzID0gcmF3LmRhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICBkaW0ubWV0aG9kID0gInBjYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmRpbSA9IDE1LAogICAgICAgICAgICAgICAgICAgICAgICAgIGRlLnBhcmFtID0gZGUucGFyYW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJ1bmRpcmVjdGlvbmFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBybS5laWdlbiA9IHJtLmVpZ2VuLAogICAgICAgICAgICAgICAgICAgICAgICAgIGsucGFyYW0gPSA4LAogICAgICAgICAgICAgICAgICAgICAgICAgIHJtLnRoID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgICAgIHZnLnBhZGoudGggPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImxvdXZhaW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCA9ICJ0ZXN0LWl0ZXJfY2x1c3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGKQoKYGBgCgojIyMjIE1lcmdlIGNsdXN0ZXJzIG5vdCBzZXBlcmFibGUgYnkgREVHcwoKYGBge3J9CiMgTWVyZ2UgY2x1c3RlcnMgd2hpY2ggYXJlIG5vdCBzZXBlcmFibGUgYnkgREVHcwpyZC5kYXQgPC0gdChub3JtLmRhdFtpdGVyLnJlc3VsdCRtYXJrZXJzLF0pCm1lcmdlLnJlc3VsdCA8LSBtZXJnZV9jbChub3JtLmRhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjbCA9IGl0ZXIucmVzdWx0JGNsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHJkLmRhdCA9IHJkLmRhdCwKICAgICAgICAgICAgICAgICAgICAgICAgIGRlLnBhcmFtID0gZGUucGFyYW0pCgpjYXQobGVuZ3RoKHVuaXF1ZShtZXJnZS5yZXN1bHQkY2wpKSwiIENsdXN0ZXJzXG4iKQpjYXQobGVuZ3RoKHVuaXF1ZShtZXJnZS5yZXN1bHQkbWFya2VycykpLCAiIERFIGdlbmVzIikKYGBgCgojIyMjIEltcG9ydCBjZWxsIGxhYmVscyBpbnRvIHRoZSBTZXVyYXQgb2JqCgoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCksIGZpZy5jYXA9ICJNYW51c2NyaXB0IGVsZW1lbnQgRmlnLiAyQyJ9CkdsdXQuUUNGaWx0ZXJlZC5kYXRhQGlkZW50IDwtIGFzLmZhY3RvcihtZXJnZS5yZXN1bHQkY2wpCkdsdXQuUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSRMTi5pZGVudCA8LWFzLmNoYXJhY3RlcihHbHV0LlFDRmlsdGVyZWQuZGF0YUBpZGVudCkKCmNvbG9ycyA8LSAgYygiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsICIjY2M4Nzc4IiAsICIjZDE0YzhkIiwgIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiwiI2U2YmI5YiIsICIjMDQ2YzlhIiwgIiM0Nzg0YTIiICwgIiM0OTkwYzkiKQoKRGltUGxvdChHbHV0LlFDRmlsdGVyZWQuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiR2x1dC5RQ0ZpbHRlcmVkLmRhdGEiLCAiY29sb3JzIildKQpgYGAKCiMjIyBUcmFuc2ZlcnQgdGhlc2UgaWRlbnQgb24gdGhlIGZ1bGwgZGF0YXNldAoKYGBge3J9CiMgTG9hZCBmdWxsIGRhdGFzZXQKQWxsY2VsbHMuZGF0YSA8LSByZWFkUkRTKCIuL1FDLmZpbHRlcmVkLmNlbGxzLlJEUyIpCgojIFRyYW5zZmVyIHRoZSBpZGVudGl0aWVzClJlbmFtZS5DbHVzdCA8LSAgZnVuY3Rpb24oQ2x1c3RkYXRhLCBSYXdRQ2RhdGEpIHsKICB1bkNsdXN0ZXJlZC5jZWxscyA8LSBSYXdRQ2RhdGFAbWV0YS5kYXRhJEJhcmNvZGVzCiAgUmF3UUNkYXRhIDwtIFNldElkZW50KFJhd1FDZGF0YSwgY2VsbHMudXNlID0gdW5DbHVzdGVyZWQuY2VsbHMsIGlkZW50LnVzZSA9ICJBbGwuVW5jbHVzdGVyZWQuQ2VsbHMiKQogIAogIGZvcihpIGluIHVuaXF1ZShDbHVzdGRhdGFAbWV0YS5kYXRhJExOLmlkZW50KSl7CiAgTmV3LmlkZW50IDwtIGkKICBCYXJjb2RlcyA8LSByb3duYW1lcyhzdWJzZXQoQ2x1c3RkYXRhQG1ldGEuZGF0YSwgQ2x1c3RkYXRhQG1ldGEuZGF0YSRMTi5pZGVudCA9PSBpKSkKICBwcmludChwYXN0ZTAoIkNsdXN0ZXJfIixpLCI6ICIsbGVuZ3RoKEJhcmNvZGVzKSwgIiBDZWxscyIpKQogIEJhcmNvZGVzIDwtIEJhcmNvZGVzW0JhcmNvZGVzICVpbiUgcm93bmFtZXMoUmF3UUNkYXRhQG1ldGEuZGF0YSldCiAgUmF3UUNkYXRhIDwtIFNldElkZW50KFJhd1FDZGF0YSwgY2VsbHMudXNlID0gQmFyY29kZXMgLGlkZW50LnVzZSA9IHBhc3RlMCgiTE4uR2x1dC4iLGkpKQogIH0KICByZXR1cm4oUmF3UUNkYXRhKQp9CgpBbGxjZWxscy5kYXRhIDwtIFJlbmFtZS5DbHVzdChDbHVzdGRhdGEgPSBHbHV0LlFDRmlsdGVyZWQuZGF0YSwgUmF3UUNkYXRhID0gQWxsY2VsbHMuZGF0YSkKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KY29sb3JzIDwtICBjKCIjOTY5Njk2Iixjb2xvcnMpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLCAKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDIsCiAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICBjb2xzLnVzZSA9IGNvbG9ycykKYGBgCgpgYGB7cn0KQWxsY2VsbHMuZGF0YSA8LSBTdGFzaElkZW50KEFsbGNlbGxzLmRhdGEsIHNhdmUubmFtZSA9ICJDbHVzdGVyLmlkZW50IikKc2F2ZVJEUyhBbGxjZWxscy5kYXRhLCAiLi9DbHVzdGVyZWQuY2VsbHMuUkRTIikKcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJHbHV0LlFDRmlsdGVyZWQuZGF0YSIsICJjb2xvcnMiKV0pCmBgYAoKCiMjIFJlZmluZSB0aGUgY2VsbCB0eXBlIHRheG9ub21pZSBvbiB0aGUgbW9zdCBtYXR1cmUgY2x1c3RlcnMKCiMjIyBTZWxlY3QgbW9zdCBtYXR1cmUgbmV1cm9uIGNsdXN0ZXJzIChMTiBzY29yZSA+IDEpCgpgYGB7ciBmaWcuZGltPWMoNiwgNC41KX0KR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhICU+JSBnZ3Bsb3QoYWVzKHg9IExOLmlkZW50LCB5PSBMTl9zaWduYXR1cmUxLCBjb2xvdXI9IExOLmlkZW50KSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbG9yc1stMV0pICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9ib3hwbG90KCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LCAzLjUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBlbGVtZW50IEZpZy4gMkMifQojIEV4dHJhY3QgY2x1c3RlcnMgd2l0aCBtZWRpYW4gTE5fc2NvcmUgPiAxCk1lZGlhbl9MTl9zY29yZSA8LSBhZ2dyZWdhdGUoTE5fc2lnbmF0dXJlMSB+IExOLmlkZW50LCBHbHV0LlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEsIG1lZGlhbikKbWF0dXJlX0xOIDwtIE1lZGlhbl9MTl9zY29yZSAlPiUgZmlsdGVyKExOX3NpZ25hdHVyZTEgPiAxKSAlPiUgcHVsbChMTi5pZGVudCkKCkdsdXQuUUNGaWx0ZXJlZC5kYXRhIDwtIFN1YnNldERhdGEoR2x1dC5RQ0ZpbHRlcmVkLmRhdGEsIGlkZW50LnVzZSA9IG1hdHVyZV9MTiAsIHN1YnNldC5yYXcgPSBULCAgZG8uY2xlYW4gPSBGKQoKY29sb3JzIDwtIGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsICIjMDQ2YzlhIiwgIiM0OTkwYzkiKSAjY29sb3JzWy1jKDEsNSwxMCwxMildCkRpbVBsb3QoR2x1dC5RQ0ZpbHRlcmVkLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLCAKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDUsCiAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICBjb2xzLnVzZSA9IGNvbG9ycykKYGBgCgojIyMgUHJlcGFyZSBkYXRhIGZvciBzY3JhdHRjaC5oaWNhdCAKCiMjIyMgQW5ub3RhdGlvbiBkYXRhLmZyYW1lCgpgYGB7cn0KCiMgUHJlcGFyZSBhbm5vdGF0aW9uIGZvciBoaWNhdCBwaXBlbGluZQpjb2xvcnNpZGVudCA8LSBjYmluZChpZGVudCA9IHVuaXF1ZShhcy5jaGFyYWN0ZXIoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAaWRlbnQpKSwKICAgICAgICAgICAgICAgICAgICAgY29sb3JzID0gY29sb3JzLAogICAgICAgICAgICAgICAgICAgICBpZCA9IHVuaXF1ZShhcy5jaGFyYWN0ZXIoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAaWRlbnQpKSkKCiMgQ3JlYXRlIGFubm90YXRpb24gZGF0YS5mcmFtZQphbm5vLmRmIDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQoCiAgc2FtcGxlX25hbWUgPSByb3cubmFtZXMoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhKSwKICBwcmltYXJ5X3R5cGVfaWQgPSBjb2xvcnNpZGVudFttYXRjaChhcy5jaGFyYWN0ZXIoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAaWRlbnQpLCBjb2xvcnNpZGVudFssMV0pLDNdLAogIHByaW1hcnlfdHlwZV9sYWJlbCA9IGFzLmNoYXJhY3RlcihHbHV0LlFDRmlsdGVyZWQuZGF0YUBpZGVudCksCiAgcHJpbWFyeV90eXBlX2NvbG9yID0gY29sb3JzaWRlbnRbbWF0Y2goYXMuY2hhcmFjdGVyKEdsdXQuUUNGaWx0ZXJlZC5kYXRhQGlkZW50KSwgY29sb3JzaWRlbnRbLDFdKSwyXQopKQoKIyBNYWtlIGEgZGF0YS5mcmFtZSBvZiB1bmlxdWUgY2x1c3RlciBpZCwgdHlwZSwgY29sb3IsIGFuZCBicm9hZCB0eXBlCmNsLmRmIDwtIGFubm8uZGYgJT4lCiAgc2VsZWN0KHByaW1hcnlfdHlwZV9pZCwgCiAgICAgICAgIHByaW1hcnlfdHlwZV9sYWJlbCwgCiAgICAgICAgIHByaW1hcnlfdHlwZV9jb2xvcikgJT4lCiAgdW5pcXVlKCkKCmNvbG5hbWVzKGNsLmRmKVsxOjNdIDwtIGMoImNsdXN0ZXJfaWQiLCAiY2x1c3Rlcl9sYWJlbCIsICJjbHVzdGVyX2NvbG9yIikKCiMgU29ydCBieSBjbHVzdGVyX2lkCmNsLmRmIDwtIGFycmFuZ2UoY2wuZGYsIGNsdXN0ZXJfaWQpCnJvdy5uYW1lcyhjbC5kZikgPC0gY2wuZGYkY2x1c3Rlcl9pZAoKY2wuZmFjdCA8LSBzZXROYW1lcyhmYWN0b3IoYW5uby5kZiRwcmltYXJ5X3R5cGVfaWQpLCBhbm5vLmRmJHNhbXBsZV9uYW1lKQpgYGAKCiMjIyMgRXhwcmVzc2lvbiBtYXRyaXgKCmBgYHtyfQojIEZpbHRlciBnZW5lcwpudW0uY2VsbHMgPC0gTWF0cml4Ojpyb3dTdW1zKEdsdXQuUUNGaWx0ZXJlZC5kYXRhQGRhdGEgPiAwKSAKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbd2hpY2goeCA9IG51bS5jZWxscyA+PSAxMCldKSAKR2VuZXNUb1JlbW92ZSA8LSBjKGdyZXAocGF0dGVybiA9ICIoXlJwbHxeUnBzfF5NcnApIiwgeCA9IGdlbmVzLnVzZSwgdmFsdWUgPSBUUlVFKSwgZ3JlcChwYXR0ZXJuID0gIl5tdC0iLCB4ID0gZ2VuZXMudXNlLCB2YWx1ZSA9IFRSVUUpLCAiWGlzdCIpCgpnZW5lcy51c2UgPC0gZ2VuZXMudXNlWyFnZW5lcy51c2UgJWluJSBHZW5lc1RvUmVtb3ZlXSA7IHJtKEdlbmVzVG9SZW1vdmUsIG51bS5jZWxscykKCkdsdXQuUUNGaWx0ZXJlZC5kYXRhQHJhdy5kYXRhIDwtIEdsdXQuUUNGaWx0ZXJlZC5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQpHbHV0LlFDRmlsdGVyZWQuZGF0YSA8LSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IEdsdXQuUUNGaWx0ZXJlZC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLmZhY3RvciA9IHJvdW5kKG1lZGlhbihHbHV0LlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkblVNSSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKIyBGaW5kIGFsbCB2YXIgZ2VuZXMKR2x1dC5RQ0ZpbHRlcmVkLmRhdGEgPC0gRmluZFZhcmlhYmxlR2VuZXMob2JqZWN0ID0gR2x1dC5RQ0ZpbHRlcmVkLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Lmxvdy5jdXRvZmYgPSAwLjAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4LmhpZ2guY3V0b2ZmID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeS5jdXRvZmYgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8ucGxvdCA9IEYsIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKZGdlTWF0cml4X2NvdW50IDwtIGFzLm1hdHJpeChHbHV0LlFDRmlsdGVyZWQuZGF0YUByYXcuZGF0YSlbcm93bmFtZXMoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAcmF3LmRhdGEpICVpbiUgR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAdmFyLmdlbmVzLF0KZGdlTWF0cml4X2NwbSA8LSBjcG0oZGdlTWF0cml4X2NvdW50KSAKbm9ybS5kYXQgPC0gbG9nMihkZ2VNYXRyaXhfY3BtICsgMSkgOyBybShkZ2VNYXRyaXhfY3BtKQoKRGF0YS5tYXRyaXggPC0gbGlzdChyYXcuZGF0PWRnZU1hdHJpeF9jb3VudCwgbm9ybS5kYXQ9bm9ybS5kYXQpIDsgYXR0YWNoKERhdGEubWF0cml4KQoKcm0oZGdlTWF0cml4X2NvdW50LG5vcm0uZGF0KQpgYGAKCiMjIyBIaWVyYXJjaGljYWwgY2x1c3RlcmluZwoKU2NyYXR0Y2guaGljYXQgcGVyZm9ybSBoaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvbiBhIGNsdXN0ZXIgY29ycmVsYXRpb24gbWF0cml4IGJhc2VkIG9uIG1lZGlhbiBleHByZXNzaW9uIHZhbHVlcyBmb3IgdGhlIHRvcCA1MCBtb3N0IERFR3MgYmV0d2VlbiBldmVyeSBwYWlyIG9mIGNsdXN0ZXJzLiBJdCBlc3RpbWF0ZXMgYnJhbmNoIGNvbmZpZGVuY2UgbGV2ZWwgdXNpbmcgYSBib290c3RyYXAgYXBwcm9hY2ggaW1wbGVtZW50ZWQgYnkgdGhlIHB2Y2x1c3QgcGFja2FnZQoKYGBge3J9CiMgVGFrZSB0aGUgbWVhbiBleHByZXNzaW9uIG92ZXIgY2x1c3RlcnMKY2wubWVkIDwtIGdldF9jbF9tZWFucyhub3JtLmRhdCwgY2wuZmFjdCkKYGBgCgpgYGB7cn0KIyBCdWlsZCB0aGUgZGVuZHJvZ3JhbQpkZW5kLnJlc3VsdCA8LSBidWlsZF9kZW5kKGNsLm1lZFssbGV2ZWxzKGNsLmZhY3QpXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsLmNvbG9yPSBzZXROYW1lcyhhcy5jaGFyYWN0ZXIoY2wuZGYkY2x1c3Rlcl9jb2xvciksIHJvdy5uYW1lcyhjbC5kZikpLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5ib290ID0gMTAwKQoKYGBgCgpgYGB7ciBmaWcuZGltPWMoNSwgMy41KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiAyRCBkZW5kcm9ncmFtbWUifQojIEF0dGFjaCBjbHVzdGVyIGxhYmVscyB0byB0aGUgbGVhdmVzIG9mIHRoZSB0cmVlCmRlbmQubGFiZWxlZCA8LSBkZW5kLnJlc3VsdCRkZW5kCmxhYmVscyhkZW5kLmxhYmVsZWQpIDwtIGNsLmRmW2xhYmVscyhkZW5kLmxhYmVsZWQpLCAiY2x1c3Rlcl9sYWJlbCJdCgpwbG90KGRlbmQubGFiZWxlZCkgCmBgYAoKYGBge3J9CiMgUmVvcmRlciB0aGUgY2x1c3RlcnMgZm9yIHVzZSBpbiBvdGhlciBwbG90cwpjbC5mYWN0IDwtIHNldE5hbWVzKGZhY3Rvcihhcy5jaGFyYWN0ZXIoY2wuZmFjdCksbGV2ZWxzID0gbGFiZWxzKGRlbmQubGFiZWxlZCkpLCBuYW1lcyhjbC5mYWN0KSkKCmNsLmRmIDwtIGNsLmRmW2xldmVscyhjbC5mYWN0KSxdCmBgYAoKIyMjIElkZW50aWZ5IGNvcmUgY2VsbHMgdXNpbmcgY2VudHJvaWRlIGNsYXNzaWZpZXIgKE1hbnVzY3JpcHQgRmlnLiAyQykKCkJlY2F1c2Ugc29tZSBjZWxscyBkaXNwbGF5IGludGVybWVkaWF0ZSB0cmFuc2NyaXB0b21pYyBzaWduYXR1cmVzIGJldHdlZW4gdHdvIGNsb3NlbHkgcmVsYXRlZCBjbHVzdGVycyB3ZSB1c2VkIG9ubHkgY2x1c3RlcnMnIHNpZ25hdHVyZXMgb24gdGhlaXIgY29yZSBjZWxscwoKYGBge3IgY2xhc3Mub3V0cHV0PSJzY3JvbGwtMTAwIn0KIyBTZWxlY3QgbWFya2VyIGdlbmVzCmRlLnBhcmFtIDwtIGRlX3BhcmFtKHBhZGoudGggICAgID0gMC4wMSwKICAgICAgICAgICAgICAgICAgICAgbGZjLnRoICAgICAgPSAwLjYsCiAgICAgICAgICAgICAgICAgICAgIGxvdy50aCAgICAgID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgcTEudGggICAgICAgPSAwLjI1LAogICAgICAgICAgICAgICAgICAgICBxMi50aCAgICAgICA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgIHEuZGlmZi50aCAgID0gMC42LCAKICAgICAgICAgICAgICAgICAgICAgZGUuc2NvcmUudGggPSAyMCwgCiAgICAgICAgICAgICAgICAgICAgIG1pbi5jZWxscyA9IDUpCgpkaXNwbGF5LnJlc3VsdCA8LSBkaXNwbGF5X2NsKEdsdXQuUUNGaWx0ZXJlZC5kYXRhQGlkZW50LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtLmRhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdD1GLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZS5wYXJhbSA9IGRlLnBhcmFtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4ubWFya2VycyA9IDUwKQoKc2VsZWN0Lm1hcmtlcnMgPC0gc2VsZWN0X21hcmtlcnMobm9ybS5kYXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbC5mYWN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGUuZ2VuZXMgPSBkaXNwbGF5LnJlc3VsdCRkZS5nZW5lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbi5tYXJrZXJzID0gNTApCgptYXJrZXIuZ2VuZXMgPC0gc2VsZWN0Lm1hcmtlcnMkbWFya2VycwpgYGAKCgpgYGB7ciBjbGFzcy5vdXRwdXQ9InNjcm9sbC0xMDAifQojIFJ1biB0aGUgY2VudHJvaWRlIGNsYXNzaWZpZXIKbWFwLnJlc3VsdHMgPC0gbWFwX3NhbXBsaW5nKHRyYWluLmRhdCA9IG5vcm0uZGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW4uY2wgPSBHbHV0LlFDRmlsdGVyZWQuZGF0YUBpZGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QuZGF0ID0gbm9ybS5kYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJzID0gbWFya2VyLmdlbmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2Vycy5wZXJjID0gMC44LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDEwMCkKYGBgCgpgYGB7ciBmaWcuZGltPWMoNSwgMy41KX0KR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJENvcmVfY2VsbHMgPC0gaWZlbHNlKG1hcC5yZXN1bHRzJG1hcC5kZiRwcm9iID4gMC45NSwgIkNvcmUuQ2VsbHMiLCAiSW50ZXJtZWRpYXRlIikKCkRpbVBsb3QoR2x1dC5RQ0ZpbHRlcmVkLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAiQ29yZV9jZWxscyIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGNvbHMudXNlID0gd2VzX3BhbGV0dGUoIlJveWFsMSIsIDIsIHR5cGUgPSAiZGlzY3JldGUiKSwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPUYsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDIsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgpgYGB7cn0KIyBSZW1vdmUgaW50ZXJtZWRpYXRlIGNlbGxzCkNvcmUuY2VsbHMgPC0gR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhICU+JSBkcGx5cjo6ZmlsdGVyKENvcmVfY2VsbHMgPT0gIkNvcmUuQ2VsbHMiKSAlPiUgcHVsbChCYXJjb2RlcykKCkdsdXQuUUNGaWx0ZXJlZC5kYXRhIDwtIFN1YnNldERhdGEoR2x1dC5RQ0ZpbHRlcmVkLmRhdGEsIGNlbGxzLnVzZSA9IENvcmUuY2VsbHMgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKCmFubm8uZGYgPC0gYW5uby5kZiAlPiUgZmlsdGVyKHNhbXBsZV9uYW1lICVpbiUgQ29yZS5jZWxscykKYGBgCgpgYGB7ciBmaWcuZGltPWMoNSwgMy41KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgZWxlbWVudCBGaWcuIDJDIn0KRGltUGxvdChHbHV0LlFDRmlsdGVyZWQuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzKQpgYGAKCgojIyMgQnVpbHQgdGhlIGNsdXN0ZXIgbWFya2VycyBiYXJwbG90IChNYW51c2NyaXB0IEZpZy4gMkQpCgpgYGB7ciBmaWcuZGltPWMoNywgMTApLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDJEIn0KZGF0YSA8LSBjYmluZChzYW1wbGVfbmFtZSA9IGNvbG5hbWVzKEdsdXQuUUNGaWx0ZXJlZC5kYXRhQGRhdGEpLAogICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUodChhcy5tYXRyaXgoR2x1dC5RQ0ZpbHRlcmVkLmRhdGFAZGF0YSkpKSkKClNlbGVjdGVkLm1hcmtlcnMgPC0gYygiU2xjMTdhNiIsIlRicjEiLCAiR2FwNDMiLCAiRm94ZzEiLCJNbjEiLCJSZWxuIiwKICAgICAgICAgICAgICAgICAgICAgICJMaHg1IiwiQ2FsYjIiLCJTYW1kMyIsICJEbXJ0YTIiLCAiTnIyZjIiLCAiRWJmMiIsCiAgICAgICAgICAgICAgICAgICAgICAiR20yNzE5OSIsICJDaGwxIiwiVW5jNWMiLCAiR3JtMSIsICJJbnNtMiIsIlRycDczIiwKICAgICAgICAgICAgICAgICAgICAgICJFYmYzIiwgIkNka24xYSIsICJMaHgxIiwgIkxoeDFvcyIsIlpmcDUwMyIsICJDYWNuYTJkMiIsCiAgICAgICAgICAgICAgICAgICAgICAiU2VycGluZTIiLCAiUnNwbzMiLCAiR3JtMiIsICJDeGNyNCIsIkxhbXA1IiwiTmV1cm9kMiIsCiAgICAgICAgICAgICAgICAgICAgICAiTmV1cm9kNiIsICJUY2Y0IiwiTHJmbjUiLCAiRmV6ZjEiLCAiRmV6ZjIiLCAiUGNwNCIsCiAgICAgICAgICAgICAgICAgICAgICAiTmZpYSIsICJOZmliIiwgICJOZml4IiwgIkJobGhlMjIiLCJQcHAxcjE0YyIsICJTY2cyIiwKICAgICAgICAgICAgICAgICAgICAgICJNZWlzMiIsIlBieDMiLCAiTWFiMjFsMSIsICJCYXJobDIiLCAgIlJ1bngxdDEiLCJNZWYyYyIsCiAgICAgICAgICAgICAgICAgICAgICAiTnhwaDEiLCAiTWVpczEiLCAgIlRzaHoyIiwiTGh4OSIsICJOcjRhMiIsICJDY2siLCAiRm94cDIiLAogICAgICAgICAgICAgICAgICAgICAgIlBvdTNmMiIsICJTb3g2IiwiRWJmMSIsIk5yaXAzIiwgIlppYzEiLCAiRXR2MSIsICJUZmFwMmUiLCAiUGF4NiIpCgpzYW1wbGVfYmFyX3Bsb3QoZGF0YSwgCiAgICAgICAgICAgICAgICBhbm5vLmRmLCAKICAgICAgICAgICAgICAgIGdlbmVzID0gU2VsZWN0ZWQubWFya2VycywKICAgICAgICAgICAgICAgIGdyb3VwX29yZGVyID0gbGV2ZWxzKGNsLmZhY3QpLAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAicHJpbWFyeV90eXBlIiwKICAgICAgICAgICAgICAgIGxvZ19zY2FsZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgZm9udF9zaXplID0gNywKICAgICAgICAgICAgICAgIGxhYmVsX2hlaWdodCA9IDEwLAogICAgICAgICAgICAgICAgbGFiZWxfdHlwZSA9ICJhbmdsZSIsCiAgICAgICAgICAgICAgICBiZ19jb2xvciA9IiNmN2Y3ZjciKQpgYGAKCmBgYHtyfQpybShsaXN0ID0gbHMoKSkKYGBgCgojIFN1Yi1wYWxsaWFsIG5ldXJvbnMgY2x1c3RlcmluZwoKTG9hZCBRQyBmaWx0ZXJlZCBkYXRhc2V0CgpgYGB7cn0KUUNGaWx0ZXJlZC5kYXRhIDwtIHJlYWRSRFMoIi4vUUMuZmlsdGVyZWQuY2VsbHMuUkRTIikKYGBgCgojIyBFeHRyYWN0IHN1Yi1wYWxsaWFsIGxhdGUgbmV1cm9ucyBieSBrLW1lYW5zIGNsdXN0ZXJpbmcgb24gdGhlIGNlbGwgc3RhdGUgc3BhY2UKCiMjIyBTZWxlY3Rpb24gb2Ygc3ViLXBhbGxpYWwgbmV1cm9uYWwgYnJhbmNoZQoKQXMgZm9yIHRoZSBnbHV0YW1hdGVyaWdpYyBuZXVyb25zLCB3ZSBleHRyYWN0IHRoZSBtb3N0IG1hdHVyZSBzdWItcGFsbGlhbCBjZWxscyBpbiB0d28gc3RlcHMgOgoKLSBXZSBzZWxldGVkIHRoZXN1YnBsYWxsaWFsIG5ldXJvbmFsIGJyYW5jaGUKLSBGcm9tIHRoaXMgd2UgZXh0cmFjdGVkIGNlbGxzIHdpdGggdGhlIG1vc3QgbWF0dXJlIHNpZ25hdHVyZQoKYGBge3IgZmlnLmRpbT1jKDksIDgpfQpGZWF0dXJlUGxvdChvYmplY3QgPSBRQ0ZpbHRlcmVkLmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzLnBsb3QgPSBjKCJBUF9zaWduYXR1cmUxIiwgIlBhbF9zaWduYXR1cmUxIiwgIlNQX3NpZ25hdHVyZTEiKSwKICAgICAgICAgICAgY29scy51c2UgPSByZXYoYnJld2VyLnBhbCgxMCwiU3BlY3RyYWwiKSksCiAgICAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICAgICAgb3ZlcmxheSA9IEYsCiAgICAgICAgICAgIGRhcmsudGhlbWUgPSBGCikKCmBgYAoKV2UgcGVyZm9ybSBLLW1lYW5zIGNsdXN0ZXJpbmcgb24gdGhlIDMgY2VsbCBzdGF0ZSBzY29yZXMgOgoKLSBBcGljYWwgcHJvZ2VuaXRvcnMgYEFQYAotIFN1Yi1wYWxsaWFsIG5ldXJvbnMgYFNQYAotIFBhbGxpYWwgbmV1cm9ucyBgUGFsYAoKYGBge3J9CiMgSy1tZWFucyBjbHVzdGVyaW5nIGJhc2VkIG9uIEFQLCBTUCBhbmQgUGFsIHNpZ25hdHVyZSBzY29yZXMKc2V0LnNlZWQoMTAwKQpjbCA8LSBrbWVhbnMoeCA9IGNiaW5kKFFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkQVBfc2lnbmF0dXJlMSwKICAgICAgICAgICAgICAgICAgIFFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkU1Bfc2lnbmF0dXJlMSwKICAgICAgICAgICAgICAgICAgIFFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkUGFsX3NpZ25hdHVyZTEpLAogICAgICAgICAgICAgY2VudGVycyA9IDMpCgpRQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJGttZWFuQ2x1c3QgPC0gcGFzdGUwKCJDbHVzdC4iLGNsJGNsdXN0ZXIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbC5wYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgMywgdHlwZSA9ICJkaXNjcmV0ZSIpCgpwMSA8LSBnZ3Bsb3QoUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSwgYWVzKHg9UGFsX3NpZ25hdHVyZTEsIHk9U1Bfc2lnbmF0dXJlMSwgY29sb3VyID0ga21lYW5DbHVzdCkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbC5wYWwpICsKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CkRpbVBsb3QoUUNGaWx0ZXJlZC5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gImttZWFuQ2x1c3QiLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICBjb2xzLnVzZSA9IGNvbC5wYWwsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IFQpCmBgYAoKV2UgdGhlbiBleHRyYWN0IHRoZSBHQUJBZXJnaWMgbmV1cm9uIGJyYW5jaGUgYXMgYmVlaW5nIHRoZSBLLW1lYW5zIGNsdXN0ZXIgd2l0aCB0aGUgaGlnaGVzdCBtZWFuIGBTdWItUGFsbGlhbCBuZXVyb25zYCBzaWduYXR1cmUKCmBgYHtyfQojIEZpbmQgdGhlIGstbWVhbnMgY2x1c3RlcnMgd2l0aCB0aGUgaGlnaGVzdCBtZWFuIFNQX3NpZ25hdHVyZTEgc2NvcmUKTWVhbktjbHVzdC5TUHNjb3JlIDwtIGFnZ3JlZ2F0ZShTUF9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSwgbWVhbikKU1BjbHVzdCA8LSBNZWFuS2NsdXN0LlNQc2NvcmUgJT4lIGZpbHRlcihTUF9zaWduYXR1cmUxID09IG1heChTUF9zaWduYXR1cmUxKSkgJT4lIHB1bGwoa21lYW5DbHVzdCkKCiMgRXh0cmFjdCBiYXJjb2RlcyBhbmQgZmlsdGVyIHRoZSBzZXVyYXQgb2JqZWN0ClNQLmNlbGxzIDwtIFFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihrbWVhbkNsdXN0ID09IFNQY2x1c3QpICU+JSBwdWxsKEJhcmNvZGVzKQpTUC5RQ0ZpbHRlcmVkLmRhdGEgPC0gIFN1YnNldERhdGEoUUNGaWx0ZXJlZC5kYXRhLCBjZWxscy51c2UgPSBTUC5jZWxscyAsIHN1YnNldC5yYXcgPSBULCAgZG8uY2xlYW4gPSBGKQpgYGAKCiMjIyBFeHRyYWN0IGxhdGUgc3ViLXBhbGxpYWwgbmV1cm9ucwoKYGBge3J9CiMgQ2FsY3VsYXRlIFNQIGVhcmx5IG5ldXJvbnMgc2lnbmF0dXJlIHNjb3JlIGJhc2VkIG9uIHNlbGVjdGVkIG1hcmtlciBnZW5lcwpMTmdlbmVzIDwtIGMoIkRseDZvczEiLCAiTnVkdDQiLCAiQWJyYWNsIiwgIkFybDRkIiwgIlRtZW0xMjMiLCAiQ2NkYzEwOWIiLCAiSG1nbjIiLCAiRTEzMDAwNkQwMVJpayIsICJDZGNhNyIpCmdlbmVzLmxpc3QgPC0gbGlzdChMTmdlbmVzKQplbnJpY2gubmFtZSA8LSAiRU5fc2lnbmF0dXJlIgpTUC5RQ0ZpbHRlcmVkLmRhdGEgPC0gQWRkTW9kdWxlU2NvcmUoU1AuUUNGaWx0ZXJlZC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXMubGlzdCA9IGdlbmVzLmxpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcy5wb29sID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4uYmluID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQudXNlID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmwuc2l6ZSA9IGxlbmd0aChnZW5lcy5saXN0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZS5rID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnJpY2gubmFtZSA9IGVucmljaC5uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tLnNlZWQgPSAxKQpgYGAKCgpgYGB7cn0KIyBLLW1lYW5zIGNsdXN0ZXJpbmcgYmFzZWQgb24gRU4gYW5kIExOIHNpZ25hdHVyZSBzY29yZXMKY2wgPC0ga21lYW5zKGNiaW5kKFNQLlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEkRU5fc2lnbmF0dXJlMSwgU1AuUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSRMTl9zaWduYXR1cmUxKSwgMykKClNQLlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEka21lYW5DbHVzdCA8LSBwYXN0ZTAoIkNsdXN0LiIsY2wkY2x1c3RlcikKCiMgRmluZCB0aGUgay1tZWFucyBjbHVzdGVycyB3aXRoIHRoZSBoaWdoZXN0IG1lYW4gTGF0ZV9zaWduYXR1cmUxIHNjb3JlCk1lYW5LY2x1c3QuTE5zY29yZSA8LSBhZ2dyZWdhdGUoTE5fc2lnbmF0dXJlMSB+IGttZWFuQ2x1c3QsIFNQLlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEsIG1lYW4pCkxOLmNsdXN0IDwtIE1lYW5LY2x1c3QuTE5zY29yZSAlPiUgZmlsdGVyKExOX3NpZ25hdHVyZTEgPT0gbWF4KExOX3NpZ25hdHVyZTEpKSAlPiUgcHVsbChrbWVhbkNsdXN0KQoKIyBFeHRyYWN0IGJhcmNvZGVzCkxOLmNlbGxzIDwtIFNQLlFDRmlsdGVyZWQuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihrbWVhbkNsdXN0ID09IExOLmNsdXN0KSAlPiUgcHVsbChCYXJjb2RlcykKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KY29sLnBhbCA8LSB3ZXNfcGFsZXR0ZSgiR3JhbmRCdWRhcGVzdDEiLCAzLCB0eXBlID0gImRpc2NyZXRlIikKCnAxIDwtIGdncGxvdChTUC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhLCBhZXMoeD1MTl9zaWduYXR1cmUxLCB5PUVOX3NpZ25hdHVyZTEsIGNvbG91ciA9IGttZWFuQ2x1c3QpKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSBwYXN0ZTAobGVuZ3RoKExOLmNlbGxzKSwgIiBMYXRlIE5ldXJvbnMiKSwgeCA9IDEsIHkgPTEuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sLnBhbCkgKwogIGdlb21fcG9pbnQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpIApnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpIDsgcm0ocDEpCgpEaW1QbG90KFNQLlFDRmlsdGVyZWQuZGF0YSwKICAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICAgY29scy51c2UgPSBjb2wucGFsLAogICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgIGRpbS4yID0gMiwKICAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgIG5vLmxlZ2VuZCA9IFQpCmBgYAoKYGBge3J9CiMgRmlsdGVyIHRoZSBzZXVyYXQgb2JqZWN0ClNQLlFDRmlsdGVyZWQuZGF0YSA8LSAgU3Vic2V0RGF0YShTUC5RQ0ZpbHRlcmVkLmRhdGEsIGNlbGxzLnVzZSA9IExOLmNlbGxzICwgc3Vic2V0LnJhdyA9IFQsICBkby5jbGVhbiA9IEYpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CkRpbVBsb3QoU1AuUUNGaWx0ZXJlZC5kYXRhLAogICAgICAgICBncm91cC5ieSA9ICJrbWVhbkNsdXN0IiwKICAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgICBjb2xzLnVzZSA9ICIjOTY5Njk2IiwKICAgICAgICAgZGltLjEgPSAxLAogICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgIGRvLmxhYmVsPUYsCiAgICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgICBuby5sZWdlbmQgPSBUKQpgYGAKCgojIyBQZXJmb3JtIGl0ZXJhdGl2ZSBjbHVzdGVyaW5nIGltcGxlbWVudGVkIGluIHNjcmF0dGNoLmhpY2F0IHBhY2thZ2UKCldlIHBlcmZvcm0gdGhlIGNsdXN0ZXJpbmcgcHJvY2VkdXJlIGFzIGZvciB0aGUgZ2x1dGFtYXRlcmdpYyBuZXVyb25zCgojIyMgUHJlcGFyZSB0aGUgZGF0YXNldCBmb3IgY2x1c3RlcmluZyB3aXRoIHNjcmF0dGNoLmhpY2F0CgojIyMjIEluZGVwZW5kZW50IGdlbmUgZmlsdGVyaW5nCgpXZSBkZWNpZGUgdG8gZXhjbHVkZSAqKkNlbGwgY3ljbGUqKiwgKipyaWJvc29tYWwqKiBhbmQgKiptaXRvY2hvbmRyaWFsKiogYXNzb2NpYXRlZCBnZW5lcywgYXMgd2VsbCBhcyAqKlhpc3QqKiBmb3IgdGhlIGNsdXN0ZXJpbmcgc3RlcC4KCmBgYHtyfQojIEV4Y2x1ZGUgY2VsbCBjeWNsZSBhc3NvY2lhdGVkIGdlbmVzCnMuZ2VuZXMgPC0gYygiTWNtNSIsICJQY25hIiwgIlR5bTUiLCAiRmVuMSIsICJNY20yIiwgIk1jbTQiLCAiUnJtMSIsICJVbmciLCAiR2luczIiLCAiTWNtNiIsICJDZGNhNyIsICJEdGwiLCAiUHJpbTEiLCAiVWhyZjEiLCAiTWxmMWlwIiwgIkhlbGxzIiwgIlJmYzIiLCAiUmFwMiIsICJOYXNwIiwgIlJhZDUxYXAxIiwgIkdtbm4iLCAiV2RyNzYiLCAiU2xicCIsICJDY25lMiIsICJVYnI3IiwgIlBvbGQzIiwgIk1zaDIiLCAiQXRhZDIiLCAiUmFkNTEiLCAiUnJtMiIsICJDZGM0NSIsICJDZGM2IiwgIkV4bzEiLCAiVGlwaW4iLCAiRHNjYzEiLCAiQmxtIiwgIiBDYXNwOGFwMiIsICJVc3AxIiwgIkNsc3BuIiwgIlBvbGExIiwgIkNoYWYxYiIsICJCcmlwMSIsICJFMmY4IikKZzJtLmdlbmVzIDwtIGMoIkhtZ2IyIiwgIkRkazEiLCJOdXNhcDEiLCAiVWJlMmMiLCAiQmlyYzUiLCAiVHB4MiIsICJUb3AyYSIsICJOZGM4MCIsICJDa3MyIiwgIk51ZjIiLCAiQ2tzMWIiLCAiTWtpNjciLCAiVG1wbyIsICIgQ2VucGsiLCAiVGFjYzMiLCAiRmFtNjRhIiwgIlNtYzQiLCAiQ2NuYjIiLCAiQ2thcDJsIiwgIkNrYXAyIiwgIkF1cmtiIiwgIkJ1YjEiLCAiS2lmMTEiLCAiQW5wMzJlIiwgIlR1YmI0YiIsICJHdHNlMSIsICJraWYyMGIiLCAiSGp1cnAiLCAiQ2RjYTMiLCAiSG4xIiwgIkNkYzIwIiwgIlR0ayIsICJDZGMyNWMiLCAia2lmMmMiLCAiUmFuZ2FwMSIsICJOY2FwZDIiLCAiRGxnYXA1IiwgIkNkY2EyIiwgIkNkY2E4IiwgIkVjdDIiLCAiS2lmMjMiLCAiSG1tciIsICJBdXJrYSIsICJQc3JjMSIsICJBbmxuIiwgIkxiciIsICJDa2FwNSIsICJDZW5wZSIsICJDdGNmIiwgIk5lazIiLCAiRzJlMyIsICJHYXMybDMiLCAiQ2J4NSIsICJDZW5wYSIpCgojIEV4Y2x1ZGUgZ2VuZXMgZGV0ZWN0ZWQgaW4gbGVzcyB0aGFuIDMgY2VsbHMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhTUC5RQ0ZpbHRlcmVkLmRhdGFAZGF0YSA+IDApCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMyldKQoKR2VuZXNUb1JlbW92ZSA8LSBjKGdyZXAocGF0dGVybiA9ICIoXlJwbHxeUnBzfF5NcnApIiwgeCA9IGdlbmVzLnVzZSwgdmFsdWUgPSBUUlVFKSwgZ3JlcChwYXR0ZXJuID0gIl5tdC0iLCB4ID0gZ2VuZXMudXNlLCB2YWx1ZSA9IFRSVUUpLCBzLmdlbmVzLCBnMm0uZ2VuZXMsICJYaXN0IikKCmdlbmVzLnVzZSA8LSBnZW5lcy51c2VbIWdlbmVzLnVzZSAlaW4lIEdlbmVzVG9SZW1vdmVdCmBgYAoKIyMjIyBOb3JtYWxpemF0aW9uCmBgYHtyfQpkZ2VNYXRyaXhfY291bnQgPC0gYXMubWF0cml4KFNQLlFDRmlsdGVyZWQuZGF0YUByYXcuZGF0YSlbcm93bmFtZXMoU1AuUUNGaWx0ZXJlZC5kYXRhQHJhdy5kYXRhKSAlaW4lIGdlbmVzLnVzZSxdCmRnZU1hdHJpeF9jcG0gPC0gY3BtKGRnZU1hdHJpeF9jb3VudCkKbm9ybS5kYXQgPC0gbG9nMihkZ2VNYXRyaXhfY3BtICsgMSkKYGBgCgpgYGB7cn0Kbm9ybS5kYXQgPC0gTWF0cml4KG5vcm0uZGF0LCBzcGFyc2UgPSBUUlVFKQpEYXRhLm1hdHJpeCA8LSBsaXN0KHJhdy5kYXQ9ZGdlTWF0cml4X2NvdW50LCBub3JtLmRhdD1ub3JtLmRhdCkKYXR0YWNoKERhdGEubWF0cml4KQpgYGAKCmBgYHtyfQpybShsaXN0ID0gbHMoKVshbHMoKSAlaW4lIGMoIlNQLlFDRmlsdGVyZWQuZGF0YSIsICJEYXRhLm1hdHJpeCIpXSkKYGBgCgojIyMjIFNlbGVjdCBmZWF0dXJlcyB1c2VkIHRvIHJlbW92ZSBQQ3Mgd2hpY2ggd291bGQgY29ycmVsYXRlIHdpdGggdW53YW50ZWQgc291cmNlcyBvZiB2YXJpYXRpb24gCgpgYGB7cn0KZ2VuZS5jb3VudHMgPC0gbG9nMihjb2xTdW1zKGFzLm1hdHJpeChEYXRhLm1hdHJpeCRub3JtLmRhdCkgPiAwKSkKblVNSSA8LSBsb2cyKGNvbFN1bXMoRGF0YS5tYXRyaXgkcmF3LmRhdCkpCnBlcmN0TWl0byA8LSBTUC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJHBlcmNlbnQubWl0bwpwZXJjdFJpYm8gPC0gU1AuUUNGaWx0ZXJlZC5kYXRhQG1ldGEuZGF0YSRwZXJjZW50LnJpYm8KCnJtLmVpZ2VuIDwtIGFzLm1hdHJpeChjYmluZChnZW5lLmNvdW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5VTUksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdE1pdG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdFJpYm8pKQoKcm93Lm5hbWVzKHJtLmVpZ2VuKSA8LSBuYW1lcyhnZW5lLmNvdW50cykKCmNvbG5hbWVzKHJtLmVpZ2VuKSA8LSBjKCJsb2cybkdlbmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgImxvZzJuVU1JIiwKICAgICAgICAgICAgICAgICAgICAgICAgInBlcmN0TWl0byIsCiAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjdFJpYm8iKQoKcm0oZ2VuZS5jb3VudHMsIG5VTUksIHBlcmN0TWl0bywgcGVyY3RSaWJvKQpgYGAKCiMjIyBJdGVyYXRpdmUgY2x1c3RlcmluZwoKYGBge3J9CiMgUGFyYW1ldGVycyBmb3IgaXRlcmF0aXZlIGNsdXN0ZXJpbmcKZGUucGFyYW0gPC0gZGVfcGFyYW0ocGFkai50aCAgICAgPSAwLjAxLCAKICAgICAgICAgICAgICAgICAgICAgbGZjLnRoICAgICAgPSAwLjksCiAgICAgICAgICAgICAgICAgICAgIGxvdy50aCAgICAgID0gMSwgCiAgICAgICAgICAgICAgICAgICAgIHExLnRoICAgICAgID0gMC4yNSwgCiAgICAgICAgICAgICAgICAgICAgIHEyLnRoICAgICAgID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgcS5kaWZmLnRoICAgPSAwLjcsCiAgICAgICAgICAgICAgICAgICAgIGRlLnNjb3JlLnRoID0gMzAsCiAgICAgICAgICAgICAgICAgICAgIG1pbi5jZWxscyA9IDEwKQpgYGAKCiMjIyMgUnVuIHRoZSBpdGVyYXRpdmUgY2x1c3RlcmluZwoKYGBge3IgY2xhc3Mub3V0cHV0PSJzY3JvbGwtMTAwIn0KIyBQZXJmb3JtIHRoZSBpdGVyYXRpdmUgY2x1c3RlcmluZyAKaXRlci5yZXN1bHQgPC0gaXRlcl9jbHVzdChub3JtLmRhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRzID0gcmF3LmRhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICBkaW0ubWV0aG9kID0gInBjYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmRpbSA9IDE1LAogICAgICAgICAgICAgICAgICAgICAgICAgIGRlLnBhcmFtID0gZGUucGFyYW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJ1bmRpcmVjdGlvbmFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBybS5laWdlbiA9IHJtLmVpZ2VuLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJtLnRoID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgICAgIHZnLnBhZGoudGggPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImxvdXZhaW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCA9ICJ0ZXN0LWl0ZXJfY2x1c3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGKQoKYGBgCgojIyMjIE1lcmdlIGNsdXN0ZXJzIG5vdCBzZXBlcmFibGUgYnkgREVHcwoKYGBge3J9CiMgTWVyZ2UgY2x1c3RlcnMgd2hpY2ggYXJlIG5vdCBzZXBlcmFibGUgYnkgREVHcwpyZC5kYXQgPC0gdChub3JtLmRhdFtpdGVyLnJlc3VsdCRtYXJrZXJzLF0pCm1lcmdlLnJlc3VsdCA8LSBtZXJnZV9jbChub3JtLmRhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjbCA9IGl0ZXIucmVzdWx0JGNsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHJkLmRhdCA9IHJkLmRhdCwKICAgICAgICAgICAgICAgICAgICAgICAgIGRlLnBhcmFtID0gZGUucGFyYW0pCgpjYXQobGVuZ3RoKHVuaXF1ZShtZXJnZS5yZXN1bHQkY2wpKSwiIENsdXN0ZXJzXG4iKQpjYXQobGVuZ3RoKHVuaXF1ZShtZXJnZS5yZXN1bHQkbWFya2VycykpLCAiIERFIGdlbmVzIikKYGBgCgojIyMjIEltcG9ydCBjZWxsIGxhYmVscyBpbnRvIHRoZSBTZXVyYXQgb2JqCgoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9ClNQLlFDRmlsdGVyZWQuZGF0YUBpZGVudCA8LSBhcy5mYWN0b3IobWVyZ2UucmVzdWx0JGNsKQpTUC5RQ0ZpbHRlcmVkLmRhdGFAbWV0YS5kYXRhJExOLmlkZW50IDwtYXMuY2hhcmFjdGVyKFNQLlFDRmlsdGVyZWQuZGF0YUBpZGVudCkKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbG9ycyA8LSAgYygiI2M3NzNhNyIsICIjYjc5ZjBiIiwgIiMzY2E3M2YiLCAiIzMxYjZiZCIsICIjZWM3NTZkIiwgIiM3MjkzYzgiKQoKRGltUGxvdChTUC5RQ0ZpbHRlcmVkLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzKQpgYGAKCmBgYHtyfQpybShsaXN0ID0gbHMoKVshbHMoKSAlaW4lIGMoIlNQLlFDRmlsdGVyZWQuZGF0YSIsICJjb2xvcnMiKV0pCmBgYAoKIyMjIFRyYW5zZmVydCB0aGVzZSBpZGVudCBvbiB0aGUgZnVsbCBkYXRhc2V0IChNYW51c2NyaXB0IEZpZy4gMkEpCgpgYGB7cn0KIyBMb2FkIGZ1bGwgZGF0YXNldApBbGxjZWxscy5kYXRhIDwtIHJlYWRSRFMoIi4vQ2x1c3RlcmVkLmNlbGxzLlJEUyIpCgojIFRyYW5zZmVyIHRoZSBpZGVudGl0aWVzClJlbmFtZS5DbHVzdCA8LSAgZnVuY3Rpb24oQ2x1c3RkYXRhLCBSYXdRQ2RhdGEpIHsKICBmb3IoaSBpbiB1bmlxdWUoQ2x1c3RkYXRhQG1ldGEuZGF0YSRMTi5pZGVudCkpewogICAgTmV3LmlkZW50IDwtIGkKICAgIEJhcmNvZGVzIDwtIHJvd25hbWVzKHN1YnNldChDbHVzdGRhdGFAbWV0YS5kYXRhLCBDbHVzdGRhdGFAbWV0YS5kYXRhJExOLmlkZW50ID09IGkpKQogICAgcHJpbnQocGFzdGUwKCJDbHVzdGVyXyIsaSwiOiAiLGxlbmd0aChCYXJjb2RlcyksICIgQ2VsbHMiKSkKICAgIEJhcmNvZGVzIDwtIEJhcmNvZGVzW0JhcmNvZGVzICVpbiUgcm93bmFtZXMoUmF3UUNkYXRhQG1ldGEuZGF0YSldCiAgICBSYXdRQ2RhdGEgPC0gU2V0SWRlbnQoUmF3UUNkYXRhLCBjZWxscy51c2UgPSBCYXJjb2RlcyAsaWRlbnQudXNlID0gcGFzdGUwKCJMTi5HQUJBLiIsaSkpCiAgfQogIHJldHVybihSYXdRQ2RhdGEpCn0KCkFsbGNlbGxzLmRhdGEgPC0gUmVuYW1lLkNsdXN0KENsdXN0ZGF0YSA9IFNQLlFDRmlsdGVyZWQuZGF0YSwgUmF3UUNkYXRhID0gQWxsY2VsbHMuZGF0YSkKYGBgCgpgYGB7ciBmaWcuZGltPWMoOCwgNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gMkEifQpjb2xvcnMyIDwtICBjKCIjOTY5Njk2IiwKICAgICAgICAgICAgICAiI2VjNzU2ZCIsICIjYzc3M2E3IiwgIiM3MjkzYzgiLCAiI2I3OWYwYiIsICIjM2NhNzNmIiwiIzMxYjZiZCIsCiAgICAgICAgICAgICAgIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsIiNlNmJiOWIiLCAiIzA0NmM5YSIsICIjNDc4NGEyIiAsICIjNDk5MGM5IikKCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMiwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzMikKYGBgCgpgYGB7cn0KQWxsY2VsbHMuZGF0YSA8LVN0YXNoSWRlbnQoQWxsY2VsbHMuZGF0YSwgc2F2ZS5uYW1lID0gIkNsdXN0ZXIuaWRlbnQiKQpzYXZlUkRTKEFsbGNlbGxzLmRhdGEsICIuL0NsdXN0ZXJlZC5jZWxscy5SRFMiKQpybShsaXN0ID0gbHMoKVshbHMoKSAlaW4lIGMoIkFsbGNlbGxzLmRhdGEiKV0pCmBgYAoKIyBCcm9hZCBuZXVyb25hbCB0eXBlcyBkb3RwbG90IChGaWcuIDJCKQoKYGBge3J9CiMgRXh0cmFjdCBsYXRlIG5ldXJvbnMgY2x1c3RlcnMKZ2x1dC5jbHVzdGVycyA8LSBwYXN0ZTAoYygiTE4uR2x1dC4iKSxjKCIxMyIsICIxIiwgIjE0IiwgIjIyIiwgIjE2IiwgIjE5IiwgIjI0IiwgIjI2IiwgIjIwIiwgIjIxIikpCmdhYmEuY2x1c3RlcnMgPC0gcGFzdGUwKCBjKCJMTi5HQUJBLiIpLGMoIjEiLCAiNyIsICI4IiwgIjkiLCAiMTAiLCAiMTEiKSkKY2x1c3RlcnMgPC0gYyhnYWJhLmNsdXN0ZXJzLCBnbHV0LmNsdXN0ZXJzKQpBbGwuTE4uZGF0YSA8LSBTdWJzZXREYXRhKEFsbGNlbGxzLmRhdGEsIGlkZW50LnVzZSA9IGNsdXN0ZXJzLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKCnJtKGdsdXQuY2x1c3RlcnMsIGdhYmEuY2x1c3RlciwgY2x1c3RlcnMpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbG9ycyA8LSBjKCIjZWM3NTZkIiwgIiNjNzczYTciLCAiIzcyOTNjOCIsICIjYjc5ZjBiIiwgIiMzY2E3M2YiLCIjMzFiNmJkIiwKICAgICAgICAgICAgIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsICIjMDQ2YzlhIiwgIiM0OTkwYzkiKSAKCkRpbVBsb3QoQWxsLkxOLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLCAKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDIsCiAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICBjb2xzLnVzZSA9IGNvbG9ycykKYGBgCgojIyBIaWVyYXJjaGljYWwgY2x1c3RlcmluZyB1c2luZyBzY3JhdHRjaC5oaWNhdCB0b29scwoKIyMjIE1lcmdlIGNsdXN0ZXJzIHRvIGJyb2FkIG5ldXJvbmFsIHR5cGVzCgpgYGB7cn0KIyBTdWItcGFsbGlhbCBuZXVyb25zCkFsbC5MTi5kYXRhIDwtIFNldElkZW50KEFsbC5MTi5kYXRhLCBjZWxscy51c2UgPSBXaGljaENlbGxzKEFsbC5MTi5kYXRhLCBpZGVudCA9IHBhc3RlMCgiTE4uR0FCQS4iLCBjKDgsMTEpKSksIGlkZW50LnVzZSA9ICJkTEdFIikKQWxsLkxOLmRhdGEgPC0gU2V0SWRlbnQoQWxsLkxOLmRhdGEsIGNlbGxzLnVzZSA9IFdoaWNoQ2VsbHMoQWxsLkxOLmRhdGEsIGlkZW50ID0gcGFzdGUwKCJMTi5HQUJBLiIsIGMoNyw5LDEwKSkpLCBpZGVudC51c2UgPSAiU3RyaWF0YWxfSU4iKQpBbGwuTE4uZGF0YSA8LSBTZXRJZGVudChBbGwuTE4uZGF0YSwgY2VsbHMudXNlID0gV2hpY2hDZWxscyhBbGwuTE4uZGF0YSwgaWRlbnQgPSBwYXN0ZTAoIkxOLkdBQkEuIiwgYygxKSkpLCBpZGVudC51c2UgPSAiQ29ydGljYWxfSU4iKQoKIyBQYWxsaWFsIG5ldXJvbnMKQWxsLkxOLmRhdGEgPC0gU2V0SWRlbnQoQWxsLkxOLmRhdGEsIGNlbGxzLnVzZSA9IFdoaWNoQ2VsbHMoQWxsLkxOLmRhdGEsIGlkZW50ID0gcGFzdGUwKCJMTi5HbHV0LiIsIGMoMSwxMywxNCkpKSwgaWRlbnQudXNlID0gIkNSIikKQWxsLkxOLmRhdGEgPC0gU2V0SWRlbnQoQWxsLkxOLmRhdGEsIGNlbGxzLnVzZSA9IFdoaWNoQ2VsbHMoQWxsLkxOLmRhdGEsIGlkZW50ID0gcGFzdGUwKCJMTi5HbHV0LiIsIGMoMjIpKSksIGlkZW50LnVzZSA9ICJGZXpmMSIpCkFsbC5MTi5kYXRhIDwtIFNldElkZW50KEFsbC5MTi5kYXRhLCBjZWxscy51c2UgPSBXaGljaENlbGxzKEFsbC5MTi5kYXRhLCBpZGVudCA9IHBhc3RlMCgiTE4uR2x1dC4iLCBjKDE2LDE5KSkpLCBpZGVudC51c2UgPSAiUGNwNCIpCkFsbC5MTi5kYXRhIDwtIFNldElkZW50KEFsbC5MTi5kYXRhLCBjZWxscy51c2UgPSBXaGljaENlbGxzKEFsbC5MTi5kYXRhLCBpZGVudCA9IHBhc3RlMCgiTE4uR2x1dC4iLCBjKDI0KSkpLCBpZGVudC51c2UgPSAiTnI0YTIiKQpBbGwuTE4uZGF0YSA8LSBTZXRJZGVudChBbGwuTE4uZGF0YSwgY2VsbHMudXNlID0gV2hpY2hDZWxscyhBbGwuTE4uZGF0YSwgaWRlbnQgPSBwYXN0ZTAoIkxOLkdsdXQuIiwgYygyNiwyMCwyMSkpKSwgaWRlbnQudXNlID0gIkZveHAyIikKYGBgCgoKIyMjIFByZXBhcmUgZGF0YSBmb3IgdXNlZCBieSBzY3JhdHRjaC5oaWNhdCAKCiMjIyMgQW5ub3RhdGlvbiBkYXRhLmZyYW1lCgpgYGB7cn0KY29sb3JzIDwtIGMoIiNlYTY1NjkiLCAiIzc2OTRjOCIsICIjZTZhMGM0IiwgIiNlMmQyMDMiLCAiIzA5NmI5YSIsICIjNDlhZGM3IiwgIiNlNTg2MDYiLCAiI2IzMTAyMSIpCgojIFByZXBhcmUgYW5ub3RhdGlvbiBmb3IgaGljYXQgcGlwZWxpbmUKY29sb3JzaWRlbnQgPC0gY2JpbmQoaWRlbnQgPSB1bmlxdWUoYXMuY2hhcmFjdGVyKEFsbC5MTi5kYXRhQGlkZW50KSksCiAgICAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGNvbG9ycywKICAgICAgICAgICAgICAgICAgICAgaWQgPSB1bmlxdWUoYXMuY2hhcmFjdGVyKEFsbC5MTi5kYXRhQGlkZW50KSkpCgojIENyZWF0ZSBhbm5vdGF0aW9uIGRhdGEuZnJhbWUKYW5uby5kZiA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKAogIHNhbXBsZV9uYW1lID0gcm93Lm5hbWVzKEFsbC5MTi5kYXRhQG1ldGEuZGF0YSksCiAgcHJpbWFyeV90eXBlX2lkID0gY29sb3JzaWRlbnRbbWF0Y2goYXMuY2hhcmFjdGVyKEFsbC5MTi5kYXRhQGlkZW50KSwgY29sb3JzaWRlbnRbLDFdKSwzXSwKICBwcmltYXJ5X3R5cGVfbGFiZWwgPSBhcy5jaGFyYWN0ZXIoQWxsLkxOLmRhdGFAaWRlbnQpLAogIHByaW1hcnlfdHlwZV9jb2xvciA9IGNvbG9yc2lkZW50W21hdGNoKGFzLmNoYXJhY3RlcihBbGwuTE4uZGF0YUBpZGVudCksIGNvbG9yc2lkZW50WywxXSksMl0KKSkKCiMgTWFrZSBhIGRhdGEuZnJhbWUgb2YgdW5pcXVlIGNsdXN0ZXIgaWQsIHR5cGUsIGNvbG9yLCBhbmQgYnJvYWQgdHlwZQpjbC5kZiA8LSBhbm5vLmRmICU+JQogICAgICAgICBzZWxlY3QocHJpbWFyeV90eXBlX2lkLCBwcmltYXJ5X3R5cGVfbGFiZWwsIHByaW1hcnlfdHlwZV9jb2xvcikgJT4lCiAgICAgICAgIHVuaXF1ZSgpCgpjb2xuYW1lcyhjbC5kZilbMTozXSA8LSBjKCJjbHVzdGVyX2lkIiwgImNsdXN0ZXJfbGFiZWwiLCAiY2x1c3Rlcl9jb2xvciIpCgojIFNvcnQgYnkgY2x1c3Rlcl9pZApjbC5kZiA8LSBhcnJhbmdlKGNsLmRmLCBjbHVzdGVyX2lkKQpyb3cubmFtZXMoY2wuZGYpIDwtIGNsLmRmJGNsdXN0ZXJfaWQKCmNsLmZhY3QgPC0gc2V0TmFtZXMoZmFjdG9yKGFubm8uZGYkcHJpbWFyeV90eXBlX2lkKSwgYW5uby5kZiRzYW1wbGVfbmFtZSkKYGBgCgojIyMjIEV4cHJlc3Npb24gbWF0cml4CgpgYGB7cn0KIyBGaWx0ZXIgZ2VuZXMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhBbGwuTE4uZGF0YUBkYXRhID4gMCkgCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMTApXSkgCkdlbmVzVG9SZW1vdmUgPC0gYyhncmVwKHBhdHRlcm4gPSAiKF5ScGx8XlJwc3xeTXJwKSIsIHggPSBnZW5lcy51c2UsIHZhbHVlID0gVFJVRSksIGdyZXAocGF0dGVybiA9ICJebXQtIiwgeCA9IGdlbmVzLnVzZSwgdmFsdWUgPSBUUlVFKSwgIlhpc3QiKQoKZ2VuZXMudXNlIDwtIGdlbmVzLnVzZVshZ2VuZXMudXNlICVpbiUgR2VuZXNUb1JlbW92ZV0gOyBybShHZW5lc1RvUmVtb3ZlLCBudW0uY2VsbHMpCgpBbGwuTE4uZGF0YUByYXcuZGF0YSA8LSBBbGwuTE4uZGF0YUByYXcuZGF0YVtnZW5lcy51c2UsIF0KQWxsLkxOLmRhdGEgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSBBbGwuTE4uZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZS5mYWN0b3IgPSByb3VuZChtZWRpYW4oQWxsLkxOLmRhdGFAbWV0YS5kYXRhJG5VTUkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gRikKCiMgRmluZCBhbGwgdmFyIGdlbmVzCkFsbC5MTi5kYXRhIDwtIEZpbmRWYXJpYWJsZUdlbmVzKG9iamVjdCA9IEFsbC5MTi5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuLmZ1bmN0aW9uID0gRXhwTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2lvbi5mdW5jdGlvbiA9IExvZ1ZNUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeC5sb3cuY3V0b2ZmID0gMC4wMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeC5oaWdoLmN1dG9mZiA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkuY3V0b2ZmID0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnBsb3QgPSBGLCBkaXNwbGF5LnByb2dyZXNzID0gRikKCmRnZU1hdHJpeF9jb3VudCA8LSBhcy5tYXRyaXgoQWxsLkxOLmRhdGFAcmF3LmRhdGEpW3Jvd25hbWVzKEFsbC5MTi5kYXRhQHJhdy5kYXRhKSAlaW4lIEFsbC5MTi5kYXRhQHZhci5nZW5lcyxdCmRnZU1hdHJpeF9jcG0gPC0gY3BtKGRnZU1hdHJpeF9jb3VudCkgCm5vcm0uZGF0IDwtIGxvZzIoZGdlTWF0cml4X2NwbSArIDEpIDsgcm0oZGdlTWF0cml4X2NwbSkKCkRhdGEubWF0cml4IDwtIGxpc3QocmF3LmRhdD1kZ2VNYXRyaXhfY291bnQsIG5vcm0uZGF0PW5vcm0uZGF0KSA7IGF0dGFjaChEYXRhLm1hdHJpeCkKCnJtKGRnZU1hdHJpeF9jb3VudCxub3JtLmRhdCkKYGBgCgojIyMgSGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcKClNjcmF0dGNoLmhpY2F0IHBlcmZvcm0gaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcgb24gYSBjbHVzdGVyIGNvcnJlbGF0aW9uIG1hdHJpeCBiYXNlZCBvbiBtZWRpYW4gZXhwcmVzc2lvbiB2YWx1ZXMgZm9yIHRoZSB0b3AgNTAgbW9zdCBERUdzIGJldHdlZW4gZXZlcnkgcGFpciBvZiBjbHVzdGVycy4gSXQgZXN0aW1hdGVzIGJyYW5jaCBjb25maWRlbmNlIGxldmVsIHVzaW5nIGEgYm9vdHN0cmFwIGFwcHJvYWNoIGltcGxlbWVudGVkIGJ5IHRoZSBwdmNsdXN0IHBhY2thZ2UKCmBgYHtyfQojIFRha2UgbWVkaWFuIGV4cHJlc3Npb24gb3ZlciBjbHVzdGVyCmNsLm1lZCA8LSBnZXRfY2xfbWVhbnMobm9ybS5kYXQsIGNsLmZhY3QpCmBgYAoKYGBge3J9CiMgQnVpbGQgdGhlIGRlbmRyb2dyYW0KZGVuZC5yZXN1bHQgPC0gYnVpbGRfZGVuZChjbC5tZWRbLGxldmVscyhjbC5mYWN0KV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgbC5jb2xvcj0gc2V0TmFtZXMoYXMuY2hhcmFjdGVyKGNsLmRmJGNsdXN0ZXJfY29sb3IpLCByb3cubmFtZXMoY2wuZGYpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBuYm9vdCA9IDEwMCkKCiMgQXR0YWNoIGNsdXN0ZXIgbGFiZWxzIHRvIHRoZSBsZWF2ZXMgb2YgdGhlIHRyZWUKZGVuZC5sYWJlbGVkIDwtIGRlbmQucmVzdWx0JGRlbmQKbGFiZWxzKGRlbmQubGFiZWxlZCkgPC0gY2wuZGZbbGFiZWxzKGRlbmQubGFiZWxlZCksICJjbHVzdGVyX2xhYmVsIl0KYGBgCgpgYGB7ciBmaWcuZGltPWMoNSwgMy41KX0KIyBSb3RhdGUgZGVuZHJvZ3JhbW1lIGxlYWZzCk5ld09yZGVyIDwtIGMoIkNvcnRpY2FsX0lOIiwiU3RyaWF0YWxfSU4iLCJkTEdFIiwiQ1IiLCJGZXpmMSIsIlBjcDQiLCJOcjRhMiIsIkZveHAyIikKbC5yYW5rIDwtIHNldE5hbWVzKDE6bnJvdyhjbC5kZiksIE5ld09yZGVyKSAjc2V0IHRoZSBjbHVzdGVyIG9yZGVyIAoKIyBDb2xvciBvZiB0aGUgbGVhZiBub2Rlcy4KbC5jb2xvciA8LSBzZXROYW1lcyhhcy5jaGFyYWN0ZXIoY2wuZGYkY2x1c3Rlcl9jb2xvciksIE5ld09yZGVyKSAKCiMgUmUtYnVpbGQgdGhlIGRlbmRyb2dyYW0KY2wubWVkIDwtIGdldF9jbF9tZWRpYW5zKG5vcm0uZGF0LCBjbC5mYWN0KQoKCmRlbmQucmVzdWx0IDwtIGJ1aWxkX2RlbmQoY2wubWVkWyxsZXZlbHMoY2wuZmFjdCldLAogICAgICAgICAgICAgICAgICAgICAgICAgIGwucmFuaywKICAgICAgICAgICAgICAgICAgICAgICAgICBsLmNvbG9yPWwuY29sb3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmJvb3QgPSAxMDApIAoKZGVuZCA8LSBkZW5kLnJlc3VsdCRkZW5kCgpkZW5kLmxhYmVsZWQgPC0gZGVuZC5yZXN1bHQkZGVuZApsYWJlbHMoZGVuZC5sYWJlbGVkKSA8LSBjbC5kZltsYWJlbHMoZGVuZC5sYWJlbGVkKSwgImNsdXN0ZXJfbGFiZWwiXQoKcGxvdChkZW5kLmxhYmVsZWQpIApgYGAKCgojIyBQbG90IEZpZ3VyZSAyQgoKYGBge3J9CiMgTG9hZCBjdXN0b20gcGxvdHRpbmcgZnVuY3Rpb25zCnNvdXJjZSgiLi9mdW5jdGlvbnMvQ2x1c3RlclBsb3RGdW5jdGlvbnMuUiIpCmBgYAoKYGBge3IgfQojIEltcG9ydCBkZW5kcm9ncmFtIGludG8gU2V1cmF0IG9iamVjdApBbGwuTE4uZGF0YUBjbHVzdGVyLnRyZWVbWzFdXSA8LSBhcGU6OmFzLnBoeWxvKGRlbmQubGFiZWxlZCkKbGFiZWxzKEFsbC5MTi5kYXRhQGNsdXN0ZXIudHJlZVtbMV1dKSA8LSBjbC5kZlthcy5udW1lcmljKGxhYmVscyhBbGwuTE4uZGF0YUBjbHVzdGVyLnRyZWVbWzFdXSkpLCAiY2x1c3Rlcl9sYWJlbCJdCkFsbC5MTi5kYXRhQGlkZW50IDwtIGZhY3RvcihBbGwuTE4uZGF0YUBpZGVudCwgbGV2ZWxzID0gYygiQ29ydGljYWxfSU4iLCJTdHJpYXRhbF9JTiIsImRMR0UiLCJDUiIsIkZlemYxIiwiUGNwNCIsIk5yNGEyIiwiRm94cDIiKSkKYGBgCgpgYGB7ciBmaWcuZGltPWMoNiwgNCksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gMkIifQpwMSA8LSBnZ2RlbmRyb2dyYW0oZGVuZHJvX2RhdGEoYXMuaGNsdXN0KGRlbmQubGFiZWxlZCkpLCBsYWJlbHMgPSBGLCByb3RhdGUgPSBUKSArIHNjYWxlX3lfcmV2ZXJzZSgpCgpwMiA8LSBDbHVzdGVyLmRvdHBsb3QoQWxsLkxOLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICBNYXJrZXIuZ2VuZXMgPSByZXYoYygiRm94ZzEiLCJUYnIxIiwgIlNsYzE3YTYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVsbiIsICJMaHg1IiwgIk5ldXJvZDYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUGNwNCIsICJGZXpmMSIsICAiUGJ4MyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGb3hwMiIsICJOcjRhMiIsICJEbHg1IiwgIkdhZDIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2l4MyIsICJTcDgiLCAiWmZwNTAzIiwgIklzbDEiLCAgIkxoeDYiLCAiU3N0IikpLAogICAgICAgICAgICAgICAgICAgICAgbWluLmV4cHJlc3Npb24gPSAwLjcsIHBlcmNlbnQubWk9MC4xNSwgbWF4ZG90LnNpemUgPSA1KQoKcGxvdF9ncmlkKHBsb3RsaXN0ID0gbGlzdChwMSxwMiksIG5jb2w9MiwgYWxpZ249J2gnLCByZWxfd2lkdGhzID0gYygwLjIsIDEuNSkpCmBgYAoKIyBTZXNzaW9uIEluZm8KYGBge3J9CiNkYXRlCmZvcm1hdChTeXMudGltZSgpLCAiJWQgJUIsICVZLCAlSCwlTSIpCgojUGFja2FnZXMgdXNlZApzZXNzaW9uSW5mbygpCmBgYAo=