## Warning in scpcaTools::add_miQC(filtered_sce): prob_compromised was already
## calculated and will be replaced.
## Warning in miQC::mixtureModel(sce): Unable to identify two distributions. Use plotMetrics function
## to confirm assumptions of miQC are met.
## Warning in miQC::mixtureModel(sce): Unable to identify two distributions. Use plotMetrics function
## to confirm assumptions of miQC are met.
## Warning in miQC::mixtureModel(sce): Unable to identify two distributions. Use plotMetrics function
## to confirm assumptions of miQC are met.
RNA-seq Experiment Summary
Cell Statistics
Method used to filter empty droplets
|
emptyDropsCellRanger
|
Number of cells post filtering empty droplets
|
2,308
|
Percent of reads in cells
|
51.29%
|
Median UMI count per cell
|
663
|
Median genes detected per cell
|
605
|
Median percent reads mitochondrial
|
3.03%
|
Method used to filter low quality cells
|
Minimum_gene_cutoff
|
Cells after filtering low quality cells
|
2,306
|
Normalization method
|
deconvolution
|
Minimum genes per cell cutoff
|
200
|
Knee Plot
The total UMI count of each droplet (barcode) plotted against the
rank of that droplet allows visualization of the distribution of
sequencing depth across droplets. The droplets that are expected to
contain cells were identified with DropletUtils::emptyDropsCellRanger()
,
unless otherwise specified in the Cell Statistics
table,
which uses both the total UMI counts and expressed gene content (adapted
from Lun et
al. 2019). As the boundary between droplets passing and failing
this filter is not solely dependent on total UMI count, some regions
contain droplets in both categories. The color in this plot indicates
the percentage of droplets in a region passing the filter.
Cell Read Metrics
The above plot of cell metrics includes only droplets which have
passed the emptyDropsCellRanger()
filter. The plot will
usually display a strong (but curved) relationship between the total UMI
count and the number of genes detected. Cells with low UMI counts and
high mitochondrial percentages may require further filtering.
miQC Model Diagnostics
We calculate the probability that a cell is compromised due to
degradation or rupture using miQC
(Hippen et
al. 2021). This relies on fitting a mixture model using the
number of genes expressed by a cell and the percentage of mitochondrial
reads. The expected plot will show a characteristic triangular shape and
two model fit lines. Cells with low numbers of genes expressed may have
both low and high mitochondrial percentage, but cells with many genes
tend to have a low mitochondrial percentage. Compromised cells are
likely to have a fewer genes detected and higher percentage of
mitochondrial reads.
If the model has failed to fit properly, the pattern of cells may
differ, and there may not be model fit lines. This can be the result of
a low-quality library or may occur if there is no mitochondrial content,
as in the case of a high-quality single-nucleus sample. In such
situations, the calculated probability of compromise may not be valid
(see miQC
vignette for more details).
Removing low quality cells
The below plot highlights cells that were removed prior to
normalization and dimensionality reduction. Cells that should be removed
based on RNA counts are those that are identified to be low quality
cells, such as cells with high probability of being compromised. The
method of filtering is indicated above the plot as either
miQC
or Minimum gene cutoff
. If
miQC
, cells below the specified probability compromised
cutoff and above the minimum number of unique genes identified are kept
for downstream analyses. If only a Minimum gene cutoff
is
used, then miQC
is not used and only those cells that pass
the minimum number of unique genes identified threshold are retained.
The dotted vertical line indicates the minimum gene cutoff used for
filtering.
The raw counts from all cells that remain after filtering low quality
cells (RNA only) are then normalized prior to selection of highly
variable genes and dimensionality reduction.
Dimensionality Reduction
The below plot shows the UMAP (Uniform Manifold Approximation and
Projection) embeddings for each cell, coloring each cell by the total
number of genes detected per cell.
Expression of highly variable genes
The plots below show the same UMAP embeddings, coloring each cell by
the expression level of the labeled gene. The genes chosen for plotting
are the 12 most variable genes identified in the library. Gene symbols
are used when available to label the UMAP plots. If gene symbols are not
available, the Ensembl id will be shown.
CITE-seq Experiment Summary
This section details quality control statistics from the ADT
(antibody-derived tag) component of CITE-seq experiments.
CITE-seq Experiment Statistics
Number of ADTs assayed
|
22
|
Number of reads sequenced
|
34,265,495
|
Percent reads mapped to ADTs
|
92.98%
|
Percent of ADTs in cells
|
6.07%
|
Percent of cells with ADTs
|
79.42%
|
Median ADT UMIs per cell
|
20
|
ADT Statistics
Antibody
|
Mean UMI count per cell
|
Percent of cells detected
|
ADT target type
|
CD45
|
583.37
|
77.21
|
target
|
CD7
|
54.12
|
74.22
|
target
|
CD117
|
47.48
|
60.44
|
target
|
CD10
|
31.37
|
64.08
|
target
|
CD2
|
23.42
|
45.54
|
target
|
CD38
|
22.68
|
67.03
|
target
|
CD5
|
9.91
|
50.43
|
target
|
CD4
|
9.37
|
37.09
|
target
|
CD8A
|
8.86
|
42.16
|
target
|
CD3
|
8.01
|
46.36
|
target
|
CD22
|
6.43
|
43.72
|
target
|
CD15
|
5.94
|
47.36
|
target
|
CD1A
|
4.54
|
37.44
|
target
|
CD34
|
3.67
|
36.74
|
target
|
CD14
|
3.40
|
35.31
|
target
|
HLA-DR
|
3.25
|
31.98
|
target
|
CD66B
|
2.72
|
33.71
|
target
|
CD123
|
2.71
|
34.23
|
target
|
CD94
|
2.57
|
32.84
|
target
|
CD19
|
2.13
|
29.16
|
target
|
CD33
|
1.20
|
19.89
|
target
|
CD56
|
0.88
|
22.44
|
target
|
ADT Post-processing Statistics
Method used to identify cells to filter
|
No filter
|
Normalization method
|
log-normalization
|
Removing low quality cells based on ADT counts
No ADT filtering was performed on this library.
Expression of highly variable ADTs
The plots in this section visualize the top four most variable ADTS
in the library.
The plot below displays normalized expression of these four ADTs,
with one ADT shown per panel.
The plot below displays UMAP embeddings calculated from RNA
expression, where each cell is colored by the expression level of the
given ADT.
Session Info
R session information
## ─ Session info ───────────────────────────────────────────────────────────────
## setting value
## version R version 4.2.3 (2023-03-15)
## os Ubuntu 18.04.3 LTS
## system x86_64, linux-gnu
## ui X11
## language (EN)
## collate C.UTF-8
## ctype C.UTF-8
## tz Etc/UTC
## date 2023-07-14
## pandoc 2.17.1.1 @ /usr/lib/rstudio-server/bin/quarto/bin/ (via rmarkdown)
##
## ─ Packages ───────────────────────────────────────────────────────────────────
## package * version date (UTC) lib source
## beachmat 2.14.2 2023-04-07 [2] Bioconductor
## beeswarm 0.4.0 2021-06-01 [2] CRAN (R 4.2.1)
## Biobase * 2.58.0 2022-11-01 [2] Bioconductor
## BiocGenerics * 0.44.0 2022-11-01 [2] Bioconductor
## BiocNeighbors 1.16.0 2022-11-01 [2] Bioconductor
## BiocParallel 1.32.6 2023-03-17 [2] Bioconductor
## BiocSingular 1.14.0 2022-11-01 [2] Bioconductor
## bitops 1.0-7 2021-04-24 [2] CRAN (R 4.2.1)
## bslib 0.4.2 2022-12-16 [2] CRAN (R 4.2.1)
## cachem 1.0.7 2023-02-24 [2] CRAN (R 4.2.3)
## cli 3.6.1 2023-03-23 [2] CRAN (R 4.2.3)
## codetools 0.2-19 2023-02-01 [2] CRAN (R 4.2.3)
## colorspace 2.1-0 2023-01-23 [2] CRAN (R 4.2.3)
## cowplot 1.1.1 2020-12-30 [2] CRAN (R 4.2.1)
## crayon 1.5.2 2022-09-29 [2] CRAN (R 4.2.1)
## DelayedArray 0.24.0 2022-11-01 [2] Bioconductor
## DelayedMatrixStats 1.20.0 2022-11-01 [2] Bioconductor
## digest 0.6.31 2022-12-11 [2] CRAN (R 4.2.1)
## dplyr * 1.1.2 2023-04-20 [2] RSPM (R 4.2.0)
## evaluate 0.20 2023-01-17 [2] CRAN (R 4.2.3)
## fansi 1.0.4 2023-01-22 [2] CRAN (R 4.2.3)
## farver 2.1.1 2022-07-06 [2] CRAN (R 4.2.1)
## fastmap 1.1.1 2023-02-24 [2] CRAN (R 4.2.3)
## flexmix 2.3-19 2023-03-16 [2] CRAN (R 4.2.3)
## forcats 1.0.0 2023-01-29 [2] CRAN (R 4.2.3)
## generics 0.1.3 2022-07-05 [2] CRAN (R 4.2.1)
## GenomeInfoDb * 1.34.9 2023-02-02 [2] Bioconductor
## GenomeInfoDbData 1.2.9 2023-01-06 [2] Bioconductor
## GenomicRanges * 1.50.2 2022-12-16 [2] Bioconductor
## ggbeeswarm 0.7.1 2022-12-16 [2] CRAN (R 4.2.1)
## ggplot2 * 3.4.2 2023-04-03 [2] RSPM (R 4.2.0)
## ggrepel 0.9.3 2023-02-03 [2] CRAN (R 4.2.3)
## glue 1.6.2 2022-02-24 [2] CRAN (R 4.2.1)
## gridExtra 2.3 2017-09-09 [2] CRAN (R 4.2.1)
## gtable 0.3.3 2023-03-21 [2] CRAN (R 4.2.3)
## highr 0.10 2022-12-22 [2] CRAN (R 4.2.1)
## htmltools 0.5.5 2023-03-23 [2] CRAN (R 4.2.3)
## httr 1.4.5 2023-02-24 [2] CRAN (R 4.2.3)
## IRanges * 2.32.0 2022-11-01 [2] Bioconductor
## irlba 2.3.5.1 2022-10-03 [2] CRAN (R 4.2.1)
## jquerylib 0.1.4 2021-04-26 [2] CRAN (R 4.2.1)
## jsonlite 1.8.4 2022-12-06 [2] CRAN (R 4.2.1)
## kableExtra 1.3.4 2021-02-20 [1] RSPM (R 4.2.0)
## knitr 1.42 2023-01-25 [2] CRAN (R 4.2.3)
## labeling 0.4.2 2020-10-20 [2] CRAN (R 4.2.1)
## lattice 0.21-8 2023-04-05 [2] RSPM (R 4.2.0)
## lifecycle 1.0.3 2022-10-07 [2] CRAN (R 4.2.1)
## magrittr 2.0.3 2022-03-30 [2] CRAN (R 4.2.1)
## Matrix 1.5-4 2023-04-04 [2] RSPM (R 4.2.0)
## MatrixGenerics * 1.10.0 2022-11-01 [2] Bioconductor
## matrixStats * 0.63.0 2022-11-18 [2] CRAN (R 4.2.1)
## miQC 1.6.0 2022-11-01 [2] Bioconductor
## modeltools 0.2-23 2020-03-05 [2] RSPM (R 4.1.0)
## munsell 0.5.0 2018-06-12 [2] CRAN (R 4.2.1)
## nnet 7.3-18 2022-09-28 [2] CRAN (R 4.2.3)
## pillar 1.9.0 2023-03-22 [2] CRAN (R 4.2.3)
## pkgconfig 2.0.3 2019-09-22 [2] CRAN (R 4.2.1)
## purrr 1.0.1 2023-01-10 [2] CRAN (R 4.2.3)
## R6 2.5.1 2021-08-19 [2] CRAN (R 4.2.1)
## Rcpp 1.0.10 2023-01-22 [2] CRAN (R 4.2.3)
## RCurl 1.98-1.12 2023-03-27 [2] RSPM (R 4.2.0)
## rlang 1.1.0 2023-03-14 [2] CRAN (R 4.2.3)
## rmarkdown 2.21 2023-03-26 [2] RSPM (R 4.2.0)
## rstudioapi 0.14 2022-08-22 [2] CRAN (R 4.2.1)
## rsvd 1.0.5 2021-04-16 [2] CRAN (R 4.2.1)
## rvest 1.0.3 2022-08-19 [2] CRAN (R 4.2.1)
## S4Vectors * 0.36.2 2023-02-26 [2] Bioconductor
## sass 0.4.5 2023-01-24 [2] CRAN (R 4.2.3)
## ScaledMatrix 1.6.0 2022-11-01 [2] Bioconductor
## scales 1.2.1 2022-08-20 [2] CRAN (R 4.2.1)
## scater 1.26.1 2022-11-13 [2] Bioconductor
## scpcaTools 0.2.1 2023-05-10 [1] Github (AlexsLemonade/scpcaTools@d2ad3cd)
## scuttle 1.8.4 2023-01-19 [2] Bioconductor
## sessioninfo 1.2.2 2021-12-06 [1] RSPM (R 4.2.0)
## SingleCellExperiment * 1.20.1 2023-03-17 [2] Bioconductor
## sparseMatrixStats 1.10.0 2022-11-01 [2] Bioconductor
## stringi 1.7.12 2023-01-11 [2] CRAN (R 4.2.3)
## stringr 1.5.0 2022-12-02 [2] CRAN (R 4.2.1)
## SummarizedExperiment * 1.28.0 2022-11-01 [2] Bioconductor
## svglite 2.1.1 2023-01-10 [1] RSPM (R 4.2.0)
## systemfonts 1.0.4 2022-02-11 [2] CRAN (R 4.2.1)
## tibble 3.2.1 2023-03-20 [2] CRAN (R 4.2.3)
## tidyr 1.3.0 2023-01-24 [2] CRAN (R 4.2.3)
## tidyselect 1.2.0 2022-10-10 [2] CRAN (R 4.2.1)
## utf8 1.2.3 2023-01-31 [2] CRAN (R 4.2.3)
## vctrs 0.6.2 2023-04-19 [2] RSPM (R 4.2.0)
## vipor 0.4.5 2017-03-22 [2] CRAN (R 4.2.1)
## viridis 0.6.2 2021-10-13 [2] CRAN (R 4.2.1)
## viridisLite 0.4.1 2022-08-22 [2] CRAN (R 4.2.1)
## webshot 0.5.4 2022-09-26 [1] RSPM (R 4.2.0)
## withr 2.5.0 2022-03-03 [2] CRAN (R 4.2.1)
## xfun 0.39 2023-04-20 [2] RSPM (R 4.2.0)
## xml2 1.3.3 2021-11-30 [2] CRAN (R 4.2.1)
## XVector 0.38.0 2022-11-01 [2] Bioconductor
## yaml 2.3.7 2023-01-23 [2] CRAN (R 4.2.3)
## zlibbioc 1.44.0 2022-11-01 [2] Bioconductor
##
## [1] /home/ccdl/stephanie/R/x86_64-pc-linux-gnu-library/4.2
## [2] /opt/R/4.2.3/lib/R/library
##
## ──────────────────────────────────────────────────────────────────────────────
LS0tCnBhcmFtczoKICBsaWJyYXJ5OiBFeGFtcGxlCiAgdW5maWx0ZXJlZF9zY2U6ICFyIHNjcGNhVG9vbHM6OjpzaW1fc2NlKCkKICBmaWx0ZXJlZF9zY2U6IE5VTEwKICBwcm9jZXNzZWRfc2NlOiBOVUxMCiAgZGF0ZTogIXIgU3lzLkRhdGUoKQoKdGl0bGU6ICJgciBnbHVlOjpnbHVlKCdTY1BDQSBRQyByZXBvcnQgZm9yIHtwYXJhbXMkbGlicmFyeX0nKWAiCmF1dGhvcjogIkNoaWxkaG9vZCBDYW5jZXIgRGF0YSBMYWIiCmRhdGU6ICJgciBwYXJhbXMkZGF0ZWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBtZXNzYWdlID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBrbml0ciBvcHRpb25zCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gRkFMU0UKKQoKbGlicmFyeShTaW5nbGVDZWxsRXhwZXJpbWVudCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQoKIyBTZXQgZGVmYXVsdCBnZ3Bsb3QgdGhlbWUKdGhlbWVfc2V0KAogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHBsb3QubWFyZ2luID0gbWFyZ2luKHJlcCgyMCwgNCkpLCAKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAndHJhbnNwYXJlbnQnKSkKKQoKIyBIZWxwZXIgZnVuY3Rpb24gdG8gY2hhbmdlIE5VTEwgLT4gIk4vQSIgaW4gYSBkYXRhIGZyYW1lCnJlZm9ybWF0X251bGxzIDwtIGZ1bmN0aW9uKGRmKSB7CiAgZGYgfD4gbXV0YXRlKAogICAgYWNyb3NzKGV2ZXJ5dGhpbmcoKSwKICAgICAgLmZucyA9IFwoeCkgaWZlbHNlKHggPT0gIk5VTEwiLCAiTi9BIiwgeCkKICAgICkKICApCn0KYGBgCgpgYGB7ciBzY2Vfc2V0dXB9CiMgc2F2ZSBzb21lIHR5cGluZyBsYXRlcgpsaWJyYXJ5X2lkIDwtIHBhcmFtcyRsaWJyYXJ5CnVuZmlsdGVyZWRfc2NlIDwtIHBhcmFtcyR1bmZpbHRlcmVkX3NjZQpmaWx0ZXJlZF9zY2UgPC0gcGFyYW1zJGZpbHRlcmVkX3NjZQpwcm9jZXNzZWRfc2NlIDwtIHBhcmFtcyRwcm9jZXNzZWRfc2NlCgpsaWJyYXJ5X2lkIDwtICJTQ1BDTDAwMDcwNiIgCnVuZmlsdGVyZWRfc2NlIDwtIHJlYWRSRFMoZ2x1ZTo6Z2x1ZSgie2xpYnJhcnlfaWR9X3VuZmlsdGVyZWQucmRzIikpCmZpbHRlcmVkX3NjZSA8LSByZWFkUkRTKGdsdWU6OmdsdWUoIntsaWJyYXJ5X2lkfV9maWx0ZXJlZC5yZHMiKSkKcHJvY2Vzc2VkX3NjZSA8LSByZWFkUkRTKGdsdWU6OmdsdWUoIntsaWJyYXJ5X2lkfV9wcm9jZXNzZWQucmRzIikpCgpoYXNfZmlsdGVyZWQgPC0gIWlzLm51bGwoZmlsdGVyZWRfc2NlKQpoYXNfcHJvY2Vzc2VkIDwtICFpcy5udWxsKHByb2Nlc3NlZF9zY2UpCgojIGlmIHRoZXJlIGlzIG5vIGZpbHRlcmVkIHNjZSwgdXNlIHRoZSB1bmZpbHRlcmVkIGZvciBib3RoCmlmICghaGFzX2ZpbHRlcmVkKXsKICBmaWx0ZXJlZF9zY2UgPC0gdW5maWx0ZXJlZF9zY2UKfQoKIyBncmFiIHNhbXBsZSBpZCBmcm9tIGZpbHRlcmVkIHNjZSwgaWYgbWlzc2luZyBzZXQgc2FtcGxlIGlkIHRvIE5BCmlmKGlzLm51bGwobWV0YWRhdGEoZmlsdGVyZWRfc2NlKSRzYW1wbGVfaWQpKXsKICBzYW1wbGVfaWQgPC0gTkEKfSBlbHNlIHsKICBzYW1wbGVfaWQgPC0gbWV0YWRhdGEoZmlsdGVyZWRfc2NlKSRzYW1wbGVfaWQKfQoKIyBhZGQgY2VsbCBzdGF0cyBpZiBtaXNzaW5nCmlmIChpcy5udWxsKHVuZmlsdGVyZWRfc2NlJHN1bSkpewogIHVuZmlsdGVyZWRfc2NlIDwtIHNjdXR0bGU6OmFkZFBlckNlbGxRQ01ldHJpY3ModW5maWx0ZXJlZF9zY2UpCn0KaWYgKGlzLm51bGwoZmlsdGVyZWRfc2NlJHN1bSkpewogIGZpbHRlcmVkX3NjZSA8LSBzY3V0dGxlOjphZGRQZXJDZWxsUUNNZXRyaWNzKGZpbHRlcmVkX3NjZSkKfQppZiAoaXMubnVsbChmaWx0ZXJlZF9zY2Ukc3Vic2V0c19taXRvX3BlcmNlbnQpKXsKICBmaWx0ZXJlZF9zY2Ukc3Vic2V0c19taXRvX3BlcmNlbnQgPC0gTkFfcmVhbF8KICBza2lwX21pUUMgPC0gVFJVRQp9ZWxzZXsKICBza2lwX21pUUMgPC0gRkFMU0UKfQoKIyB0cnkgdG8gYWRkIG1pUUMgaWYgaXQgaXMgbWlzc2luZwppZiAoaXMubnVsbChtZXRhZGF0YShmaWx0ZXJlZF9zY2UpJG1pUUNfbW9kZWwpICYgIXNraXBfbWlRQyl7CiAgZmlsdGVyZWRfc2NlIDwtIHNjcGNhVG9vbHM6OmFkZF9taVFDKGZpbHRlcmVkX3NjZSkKfQoKIyMgQ2hlY2sgZm9yIGFkZGl0aW9uYWwgbW9kYWxpdGllcwptb2RhbGl0aWVzIDwtIGMoIlJOQS1zZXEiKQoKaGFzX2FkdCA8LSAiYWR0IiAlaW4lIGFsdEV4cE5hbWVzKGZpbHRlcmVkX3NjZSkKaWYgKGhhc19hZHQpIHsKICBtb2RhbGl0aWVzIDwtIGMobW9kYWxpdGllcywgIkFEVCIpCn0KCiMgY2hlY2sgZm9yIGNlbGxoYXNoIHRvIGFkZCB0byBsaXN0IG9mIG1vZGFsaXRpZXMKaGFzX2NlbGxoYXNoIDwtICJjZWxsaGFzaCIgJWluJSBhbHRFeHBOYW1lcyhmaWx0ZXJlZF9zY2UpCmlmIChoYXNfY2VsbGhhc2gpIHsKICBtb2RhbGl0aWVzIDwtIGMobW9kYWxpdGllcywgIk11bHRpcGxleCIpCn0KCiMgY2hlY2sgZm9yIHVtYXAsIG5lZWQgdG8gYmUgc3VyZSB0aGF0IHByb2Nlc3NlZF9zY2UgZXhpc3RzIGZpcnN0CmlmIChoYXNfcHJvY2Vzc2VkKSB7CiAgaGFzX3VtYXAgPC0gIlVNQVAiICVpbiUgcmVkdWNlZERpbU5hbWVzKHByb2Nlc3NlZF9zY2UpCn0gZWxzZSB7CiAgaGFzX3VtYXAgPC0gRkFMU0UKfQpgYGAKCgojIFByb2Nlc3NpbmcgSW5mb3JtYXRpb24gZm9yIGByIGxpYnJhcnlfaWRgCgpgYGB7ciwgcmVzdWx0cz0nYXNpcyd9CiMgb25seSBwcmludCBvdXQgbXVsdGlwbGV4ZWQgd2FybmluZyBpZiBtb3JlIHRoYW4gb25lIHNhbXBsZSBpcyBwcmVzZW50Cmhhc19tdWx0aXBsZXggPC0gbGVuZ3RoKHNhbXBsZV9pZCkgPiAxCgppZiAoaGFzX211bHRpcGxleCkgewogICMgY29udmVydCBzYW1wbGUgaWQgdG8gYnVsbGV0IHNlcGFyYXRlZCBsaXN0CiAgbXVsdGlwbGV4X3NhbXBsZXMgPC0gcGFzdGUwKCI8bGk+IiwgcGFzdGUoc2FtcGxlX2lkLCBjb2xsYXBzZSA9ICc8L2xpPjxsaT4nLCAiPC9saT4iKSkKICBnbHVlOjpnbHVlKCIKICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCI+CgogICAgVGhpcyBsaWJyYXJ5IGlzIG11bHRpcGxleGVkIGFuZCBjb250YWlucyBkYXRhIGZyb20gbW9yZSB0aGFuIG9uZSBzYW1wbGUuCiAgICBEYXRhIGZyb20gdGhlIGZvbGxvd2luZyBzYW1wbGVzIGFyZSBpbmNsdWRlZCBpbiB0aGlzIGxpYnJhcnk6CgogICAge211bHRpcGxleF9zYW1wbGVzfQoKICAgIDwvZGl2PgogICIpCn0KCmBgYAoKIyMgUmF3IFNhbXBsZSBNZXRyaWNzCgpgYGB7ciB9CiMgZXh0cmFjdCBzY2UgbWV0YWRhdGEgY29udGFpbmluZyBwcm9jZXNzaW5nIGluZm9ybWF0aW9uIGFzIHRhYmxlCnVuZmlsdGVyZWRfbWV0YSA8LSBtZXRhZGF0YSh1bmZpbHRlcmVkX3NjZSkKCnNhbXBsZV9pbmZvcm1hdGlvbiA8LSB0aWJibGU6OnRpYmJsZSgKICAiTGlicmFyeSBpZCIgPSBsaWJyYXJ5X2lkLAogICJTYW1wbGUgaWQiID0gcGFzdGUoc2FtcGxlX2lkLCBjb2xsYXBzZSA9ICIsICIpLAogICJUZWNoIHZlcnNpb24iID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSR0ZWNoX3ZlcnNpb24pLCAjIGZvcm1hdCB0byBrZWVwIG51bGxzCiAgIkRhdGEgbW9kYWxpdGllcyIgPSBwYXN0ZShtb2RhbGl0aWVzLCBjb2xsYXBzZSA9ICIsICIpLAogICJDZWxscyByZXBvcnRlZCBieSBhbGV2aW4tZnJ5IiA9CiAgICBmb3JtYXQodW5maWx0ZXJlZF9tZXRhJGFmX251bV9jZWxscywgYmlnLm1hcmsgPSAnLCcsIHNjaWVudGlmaWMgPSBGQUxTRSksCiAgIk51bWJlciBvZiBnZW5lcyBhc3NheWVkIiA9CiAgICBmb3JtYXQobnJvdyh1bmZpbHRlcmVkX3NjZSksIGJpZy5tYXJrID0gJywnLCBzY2llbnRpZmljID0gRkFMU0UpLAogICJOdW1iZXIgb2YgUk5BLXNlcSByZWFkcyBzZXF1ZW5jZWQiID0KICAgIGZvcm1hdCh1bmZpbHRlcmVkX21ldGEkdG90YWxfcmVhZHMsIGJpZy5tYXJrID0gJywnLCBzY2llbnRpZmljID0gRkFMU0UpLAogICJQZXJjZW50IG9mIFJOQS1zZXEgcmVhZHMgbWFwcGVkIHRvIHRyYW5zY3JpcHRzIiA9CiAgICBwYXN0ZTAocm91bmQoKHVuZmlsdGVyZWRfbWV0YSRtYXBwZWRfcmVhZHMvdW5maWx0ZXJlZF9tZXRhJHRvdGFsX3JlYWRzKSAqMTAwLCAyKSwgIiUiKQopCgppZiAoaGFzX2FkdCkgewogIGFkdF9leHAgPC0gYWx0RXhwKGZpbHRlcmVkX3NjZSwgImFkdCIpICMgbXVzdCBiZSBmaWx0ZXJlZF9zY2UgaW4gY2FzZSBoYXNfcHJvY2Vzc2VkIGlzIEZBTFNFCiAgYWR0X21ldGEgPC0gbWV0YWRhdGEoYWR0X2V4cCkKCiAgc2FtcGxlX2luZm9ybWF0aW9uIDwtIHNhbXBsZV9pbmZvcm1hdGlvbiB8PgogICAgbXV0YXRlKAogICAgICAiTnVtYmVyIG9mIGFudGlib2RpZXMgYXNzYXllZCIgPQogICAgICAgIGZvcm1hdChucm93KGFkdF9leHApLCBiaWcubWFyayA9ICcsJywgc2NpZW50aWZpYyA9IEZBTFNFKSwKICAgICAgIk51bWJlciBvZiBBRFQgcmVhZHMgc2VxdWVuY2VkIiA9CiAgICAgICAgZm9ybWF0KGFkdF9tZXRhJHRvdGFsX3JlYWRzLCBiaWcubWFyayA9ICcsJywgc2NpZW50aWZpYyA9IEZBTFNFKSwKICAgICAgIlBlcmNlbnQgb2YgQURUIHJlYWRzIG1hcHBlZCB0byBBRFRzIiA9CiAgICAgICAgcGFzdGUwKHJvdW5kKGFkdF9tZXRhJG1hcHBlZF9yZWFkcy9hZHRfbWV0YSR0b3RhbF9yZWFkcyAqIDEwMCwgZGlnaXRzID0gMiksICIlIikKICAgICkKfQoKaWYgKGhhc19jZWxsaGFzaCkgewogIG11bHRpcGxleF9leHAgPC0gYWx0RXhwKGZpbHRlcmVkX3NjZSwgImNlbGxoYXNoIikKICBtdWx0aXBsZXhfbWV0YSA8LSBtZXRhZGF0YShtdWx0aXBsZXhfZXhwKQoKICBzYW1wbGVfaW5mb3JtYXRpb24gPC0gc2FtcGxlX2luZm9ybWF0aW9uIHw+CiAgICBtdXRhdGUoCiAgICAgICJOdW1iZXIgb2YgSFRPcyBhc3NheWVkIiA9CiAgICAgICAgZm9ybWF0KG5yb3cobXVsdGlwbGV4X2V4cCksIGJpZy5tYXJrID0gJywnLCBzY2llbnRpZmljID0gRkFMU0UpLAogICAgICAiTnVtYmVyIG9mIGNlbGxoYXNoIHJlYWRzIHNlcXVlbmNlZCIgPQogICAgICAgIGZvcm1hdChtdWx0aXBsZXhfbWV0YSR0b3RhbF9yZWFkcywgYmlnLm1hcmsgPSAnLCcsIHNjaWVudGlmaWMgPSBGQUxTRSksCiAgICAgICJQZXJjZW50IG9mIGNlbGxoYXNoIHJlYWRzIG1hcHBlZCB0byBIVE9zIiA9CiAgICAgICAgcGFzdGUwKHJvdW5kKG11bHRpcGxleF9tZXRhJG1hcHBlZF9yZWFkcy9tdWx0aXBsZXhfbWV0YSR0b3RhbF9yZWFkcyAqIDEwMCwgZGlnaXRzID0gMiksICIlIikKICAgICkKfQoKc2FtcGxlX2luZm9ybWF0aW9uIDwtIHNhbXBsZV9pbmZvcm1hdGlvbiB8PgogIHJlZm9ybWF0X251bGxzKCkgfD4KICB0KCkKCiMgbWFrZSB0YWJsZSB3aXRoIHNhbXBsZSBpbmZvcm1hdGlvbgprbml0cjo6a2FibGUoc2FtcGxlX2luZm9ybWF0aW9uLCBhbGlnbiA9ICdyJykgfD4KICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAibGVmdCIpIHw+CiAga2FibGVFeHRyYTo6Y29sdW1uX3NwZWMoMiwgbW9ub3NwYWNlID0gVFJVRSkKYGBgCgojIyBQcmUtUHJvY2Vzc2luZyBJbmZvcm1hdGlvbgoKYGBge3IgfQojIGRlZmluZSB0cmFuc2NyaXB0IHR5cGUKdHJhbnNjcmlwdF90eXBlIDwtIHBhc3RlKHVuZmlsdGVyZWRfbWV0YSR0cmFuc2NyaXB0X3R5cGUsIGNvbGxhcHNlID0gIiAiKQoKcHJvY2Vzc2luZ19pbmZvIDwtIHRpYmJsZTo6dGliYmxlKAogICJTYWxtb24gdmVyc2lvbiIgICAgICAgPSBmb3JtYXQodW5maWx0ZXJlZF9tZXRhJHNhbG1vbl92ZXJzaW9uKSwKICAiQWxldmluLWZyeSB2ZXJzaW9uIiAgID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSRhbGV2aW5mcnlfdmVyc2lvbiksCiAgIlRyYW5zY3JpcHRvbWUgaW5kZXgiICA9IGZvcm1hdCh1bmZpbHRlcmVkX21ldGEkcmVmZXJlbmNlX2luZGV4KSwKICAiQWxldmluLWZyeSBkcm9wbGV0IGRldGVjdGlvbiIgID0gZm9ybWF0KHVuZmlsdGVyZWRfbWV0YSRhZl9wZXJtaXRfdHlwZSksCiAgIlJlc29sdXRpb24iICAgICAgICAgICA9IGZvcm1hdCh1bmZpbHRlcmVkX21ldGEkYWZfcmVzb2x1dGlvbiksCiAgIlRyYW5zY3JpcHRzIGluY2x1ZGVkIiA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgIHRyYW5zY3JpcHRfdHlwZSA9PSAidG90YWwgc3BsaWNlZCIgfiAiVG90YWwgYW5kIHNwbGljZWQgb25seSIsCiAgICAgIHRyYW5zY3JpcHRfdHlwZSA9PSAic3BsaWNlZCIgfiAiU3BsaWNlZCBvbmx5IiwKICAgICAgVFJVRSB+IHRyYW5zY3JpcHRfdHlwZSkKICApIHw+CiAgcmVmb3JtYXRfbnVsbHMoKSB8PgogIHQoKQoKCiMgbWFrZSB0YWJsZSB3aXRoIHByb2Nlc3NpbmcgaW5mb3JtYXRpb24Ka25pdHI6OmthYmxlKHByb2Nlc3NpbmdfaW5mbywgYWxpZ24gPSAncicpIHw+CiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImxlZnQiKSB8PgogIGthYmxlRXh0cmE6OmNvbHVtbl9zcGVjKDIsIG1vbm9zcGFjZSA9IFRSVUUpCmBgYAoKIyBSTkEtc2VxIEV4cGVyaW1lbnQgU3VtbWFyeQoKIyMgQ2VsbCBTdGF0aXN0aWNzCgpgYGB7cn0KYmFzaWNfc3RhdGlzdGljcyA8LSB0aWJibGU6OnRpYmJsZSgKICAiTWV0aG9kIHVzZWQgdG8gZmlsdGVyIGVtcHR5IGRyb3BsZXRzIiAgICAgICAgICA9IG1ldGFkYXRhKGZpbHRlcmVkX3NjZSkkZmlsdGVyaW5nX21ldGhvZCwKICAiTnVtYmVyIG9mIGNlbGxzIHBvc3QgZmlsdGVyaW5nIGVtcHR5IGRyb3BsZXRzIiA9IGZvcm1hdChuY29sKGZpbHRlcmVkX3NjZSksIGJpZy5tYXJrID0gIiwiKSwKICAiUGVyY2VudCBvZiByZWFkcyBpbiBjZWxscyIgICAgICAgICAgICAgICAgICAgICA9IHBhc3RlMChyb3VuZCgoc3VtKGZpbHRlcmVkX3NjZSRzdW0pL3N1bSh1bmZpbHRlcmVkX3NjZSRzdW0pKSoxMDAsMiksIiUiKSwKICAiTWVkaWFuIFVNSSBjb3VudCBwZXIgY2VsbCIgICAgICAgICAgICAgICAgICAgICA9IGZvcm1hdChtZWRpYW4oZmlsdGVyZWRfc2NlJHN1bSksIGJpZy5tYXJrID0gIiwiKSwKICAiTWVkaWFuIGdlbmVzIGRldGVjdGVkIHBlciBjZWxsIiAgICAgICAgICAgICAgICA9IGZvcm1hdChtZWRpYW4oZmlsdGVyZWRfc2NlJGRldGVjdGVkKSwgYmlnLm1hcmsgPSAiLCIpLAogICJNZWRpYW4gcGVyY2VudCByZWFkcyBtaXRvY2hvbmRyaWFsIiAgICAgICAgICAgID0gcGFzdGUwKHJvdW5kKG1lZGlhbihmaWx0ZXJlZF9zY2Ukc3Vic2V0c19taXRvX3BlcmNlbnQpLCAyKSwgIiUiKQogICkKCiMgaWYgcHJvY2Vzc2VkIHNjZSBleGlzdHMgYWRkIGZpbHRlcmluZyBhbmQgbm9ybWFsaXphdGlvbiB0YWJsZQppZiAoaGFzX3Byb2Nlc3NlZCkgewogIHByb2Nlc3NlZF9tZXRhIDwtIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpCgogIGJhc2ljX3N0YXRpc3RpY3MgPC0gYmFzaWNfc3RhdGlzdGljcyB8PgogICAgbXV0YXRlKAogICAgICAiTWV0aG9kIHVzZWQgdG8gZmlsdGVyIGxvdyBxdWFsaXR5IGNlbGxzIiA9IGZvcm1hdChwcm9jZXNzZWRfbWV0YSRzY3BjYV9maWx0ZXJfbWV0aG9kKSwKICAgICAgIkNlbGxzIGFmdGVyIGZpbHRlcmluZyBsb3cgcXVhbGl0eSBjZWxscyIgPSBmb3JtYXQoZGltKHByb2Nlc3NlZF9zY2UpWzJdLCBiaWcubWFyayA9ICcsJywgc2NpZW50aWZpYyA9IEZBTFNFKSwKICAgICAgIk5vcm1hbGl6YXRpb24gbWV0aG9kIiAgICAgICAgICAgICAgICAgICAgPSBmb3JtYXQocHJvY2Vzc2VkX21ldGEkbm9ybWFsaXphdGlvbiksCiAgICAgICJNaW5pbXVtIGdlbmVzIHBlciBjZWxsIGN1dG9mZiIgICAgICAgICAgID0gZm9ybWF0KHByb2Nlc3NlZF9tZXRhJG1pbl9nZW5lX2N1dG9mZikKICAgICkKICBpZiAocHJvY2Vzc2VkX21ldGEkc2NwY2FfZmlsdGVyX21ldGhvZCA9PSAibWlRQyIpIHsKICAgIGJhc2ljX3N0YXRpc3RpY3MgPC0gYmFzaWNfc3RhdGlzdGljcyB8PgogICAgICBtdXRhdGUoCiAgICAgICAgIlByb2JhYmlsaXR5IG9mIGNvbXByb21pc2VkIGNlbGwgY3V0b2ZmIiA9IGZvcm1hdChwcm9jZXNzZWRfbWV0YSRwcm9iX2NvbXByb21pc2VkX2N1dG9mZiwgYmlnLm1hcmsgPSAiLCIsIHNjaWVudGlmaWMgPSBGQUxTRSkKICAgICAgKQogIH0KfQoKYmFzaWNfc3RhdGlzdGljcyA8LSBiYXNpY19zdGF0aXN0aWNzIHw+CiAgcmVmb3JtYXRfbnVsbHMoKSB8PiAjIHJlZm9ybWF0IG51bGxzCiAgdCgpCgojIG1ha2UgdGFibGUgd2l0aCBiYXNpYyBzdGF0aXN0aWNzCmtuaXRyOjprYWJsZShiYXNpY19zdGF0aXN0aWNzLCBhbGlnbiA9ICdyJykgfD4KICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAibGVmdCIpIHw+CiAga2FibGVFeHRyYTo6Y29sdW1uX3NwZWMoMiwgbW9ub3NwYWNlID0gVFJVRSkKCmBgYAoKYGBge3IsIHJlc3VsdHM9J2FzaXMnfQppZiAoaGFzX2ZpbHRlcmVkICYmCiAgIChtZXRhZGF0YShmaWx0ZXJlZF9zY2UpJGZpbHRlcmluZ19tZXRob2QgPT0gIlVNSSBjdXRvZmYiKSkgewogIGdsdWU6OmdsdWUoIgogICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIj4KCiAgICBUaGlzIGxpYnJhcnkgbWF5IGNvbnRhaW4gYSBsb3cgbnVtYmVyIG9mIGNlbGxzIGFuZCB3YXMgdW5hYmxlIHRvIGJlIGZpbHRlcmVkIHVzaW5nIGBEcm9wbGV0VXRpbHNgLgogICAgRHJvcGxldHMgd2l0aCBhIHRvdGFsIFVNSSBjb3VudCDiiaUge21ldGFkYXRhKGZpbHRlcmVkX3NjZSkkdW1pX2N1dG9mZn0gYXJlIGluY2x1ZGVkIGluIHRoZSBmaWx0ZXJlZCBgU2luZ2xlQ2VsbEV4cGVyaW1lbnRgIG9iamVjdC4KCiAgICA8L2Rpdj4KICAiKQp9CmBgYAoKYGBge3IsIHJlc3VsdHM9J2FzaXMnfQojIGNoZWNrIGZvciBudW1iZXIgb2YgZmlsdGVyZWQgY2VsbHMKbWluX2ZpbHRlcmVkIDwtIDEwMAppZihoYXNfZmlsdGVyZWQpewogIGlmKG5jb2woZmlsdGVyZWRfc2NlKSA8IG1pbl9maWx0ZXJlZCl7CiAgICBnbHVlOjpnbHVlKCIKICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIj4KCiAgICAgIFRoaXMgbGlicmFyeSBjb250YWlucyBmZXdlciB0aGFuIHttaW5fZmlsdGVyZWR9IGNlbGxzIGluIHRoZSBmaWx0ZXJlZCBgU2luZ2xlQ2VsbEV4cGVyaW1lbnRgIG9iamVjdC4KICAgICAgVGhpcyBtYXkgYWZmZWN0IHRoZSBpbnRlcnByZXRhdGlvbiBvZiByZXN1bHRzLgoKICAgICAgPC9kaXY+CiAgICAiKQogIH0KfQoKIyBjaGVjayBmb3IgbnVtYmVyIG9mIGNlbGxzIHBvc3QgcHJvY2Vzc2luZwptaW5fcHJvY2Vzc2VkIDwtIDUwCmlmKGhhc19wcm9jZXNzZWQpewogIGlmKG5jb2wocHJvY2Vzc2VkX3NjZSkgPCBtaW5fcHJvY2Vzc2VkKXsKICAgIGdsdWU6OmdsdWUoIgogICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiPgoKICAgICAgVGhpcyBsaWJyYXJ5IGNvbnRhaW5zIGZld2VyIHRoYW4ge21pbl9wcm9jZXNzZWR9IGNlbGxzIGluIHRoZSBwcm9jZXNzZWQgYFNpbmdsZUNlbGxFeHBlcmltZW50YCBvYmplY3QgYWZ0ZXIgcmVtb3ZhbCBvZiBsb3cgcXVhbGl0eSBjZWxscy4KICAgICAgVU1BUCBpcyB1bmFibGUgdG8gYmUgY2FsY3VsYXRlZCBhbmQgcGxvdHMgd2lsbCBub3QgYmUgc2hvd24uCgogICAgICA8L2Rpdj4KICAgICIpCiAgfQp9CmBgYAoKIyMgS25lZSBQbG90CgpgYGB7ciwgZmlnLmFsdD0iU21vb3RoZWQga25lZSBwbG90IG9mIGZpbHRlcmVkIGFuZCB1bmZpbHRlcmVkIGRyb3BsZXRzIn0KdW5maWx0ZXJlZF9jZWxsZGF0YSA8LSBkYXRhLmZyYW1lKGNvbERhdGEodW5maWx0ZXJlZF9zY2UpKSB8PgogIG11dGF0ZSgKICAgIHJhbmsgPSByYW5rKC0gdW5maWx0ZXJlZF9zY2Ukc3VtLCB0aWVzLm1ldGhvZCA9ICJmaXJzdCIpLCAjIHVzaW5nIGZ1bGwgc3BlYyBmb3IgY2xhcml0eQogICAgZmlsdGVyX3Bhc3MgPSBjb2xuYW1lcyh1bmZpbHRlcmVkX3NjZSkgJWluJSBjb2xuYW1lcyhmaWx0ZXJlZF9zY2UpCiAgKSB8PgogIHNlbGVjdChzdW0sIHJhbmssIGZpbHRlcl9wYXNzKSB8PgogIGZpbHRlcihzdW0gPiAwKSAjIHJlbW92ZSB6ZXJvcyBmb3IgcGxvdHRpbmcKCgpncm91cGVkX2NlbGxkYXRhIDwtIHVuZmlsdGVyZWRfY2VsbGRhdGEgfD4KICBtdXRhdGUocmFua19ncm91cCA9IGZsb29yKHJhbmsgLyAxMDApICl8PgogIGdyb3VwX2J5KHJhbmtfZ3JvdXApIHw+CiAgc3VtbWFyaXplKAogICAgbWVkX3N1bSA9IG1lZGlhbihzdW0pLAogICAgbWVkX3JhbmsgPSBtZWRpYW4ocmFuayksCiAgICBwY3RfcGFzc2VkID0gc3VtKGZpbHRlcl9wYXNzKSAvIG4oKSAqIDEwMAogICkKCnRvcF9jZWxsZGF0YSA8LSB1bmZpbHRlcmVkX2NlbGxkYXRhIHw+CiAgZmlsdGVyKHJhbmsgPD0gNTApIHw+CiAgbXV0YXRlKGZpbHRlcl9wY3QgPSBpZmVsc2UoZmlsdGVyX3Bhc3MsIDEwMCwgMCkpCgpnZ3Bsb3QoZ3JvdXBlZF9jZWxsZGF0YSwgYWVzKHggPSBtZWRfcmFuaywgeSA9IG1lZF9zdW0sIGNvbG9yID0gcGN0X3Bhc3NlZCkpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IHJhbmssIHkgPSBzdW0sIGNvbG9yID0gZmlsdGVyX3BjdCksCiAgICAgICAgICAgICBkYXRhID0gdG9wX2NlbGxkYXRhLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMiwgbGluZWVuZCA9ICJyb3VuZCIsIGxpbmVqb2luPSAicm91bmQiKSArCiAgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfeV9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJncmV5NzAiLAogICAgICAgICAgICAgICAgICAgICAgICBtaWQgPSAiZm9yZXN0Z3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gImRhcmtncmVlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgIG1pZHBvaW50ID0gNTApICsKICBsYWJzKAogICAgeCA9ICJSYW5rIiwKICAgIHkgPSAiVG90YWwgVU1JIGNvdW50IiwKICAgIGNvbG9yID0gIiUgcGFzc2luZ1xuY2VsbCBmaWx0ZXIiCiAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLCAwKSwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwwKSwKICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmV5MjAiLCBsaW5ld2lkdGggPSAwLjI1KSwKICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbihyZXAoNSwgNCkpKQpgYGAKClRoZSB0b3RhbCBVTUkgY291bnQgb2YgZWFjaCBkcm9wbGV0IChiYXJjb2RlKSBwbG90dGVkIGFnYWluc3QgdGhlIHJhbmsgb2YgdGhhdCBkcm9wbGV0IGFsbG93cyB2aXN1YWxpemF0aW9uIG9mIHRoZSBkaXN0cmlidXRpb24gb2Ygc2VxdWVuY2luZyBkZXB0aCBhY3Jvc3MgZHJvcGxldHMuClRoZSBkcm9wbGV0cyB0aGF0IGFyZSBleHBlY3RlZCB0byBjb250YWluIGNlbGxzIHdlcmUgaWRlbnRpZmllZCB3aXRoIFtgRHJvcGxldFV0aWxzOjplbXB0eURyb3BzQ2VsbFJhbmdlcigpYF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL0Ryb3BsZXRVdGlscy5odG1sKSwgdW5sZXNzIG90aGVyd2lzZSBzcGVjaWZpZWQgaW4gdGhlIGBDZWxsIFN0YXRpc3RpY3NgIHRhYmxlLCB3aGljaCB1c2VzIGJvdGggdGhlIHRvdGFsIFVNSSBjb3VudHMgYW5kIGV4cHJlc3NlZCBnZW5lIGNvbnRlbnQgKGFkYXB0ZWQgZnJvbSBbTHVuICBfZXQgYWwuXyAyMDE5XShodHRwczovL2RvaS5vcmcvMTAuMTE4Ni9zMTMwNTktMDE5LTE2NjIteSkpLgpBcyB0aGUgYm91bmRhcnkgYmV0d2VlbiBkcm9wbGV0cyBwYXNzaW5nIGFuZCBmYWlsaW5nIHRoaXMgZmlsdGVyIGlzIG5vdCBzb2xlbHkgZGVwZW5kZW50IG9uIHRvdGFsIFVNSSBjb3VudCwgc29tZSByZWdpb25zIGNvbnRhaW4gZHJvcGxldHMgaW4gYm90aCBjYXRlZ29yaWVzLgpUaGUgY29sb3IgaW4gdGhpcyBwbG90IGluZGljYXRlcyB0aGUgcGVyY2VudGFnZSBvZiBkcm9wbGV0cyBpbiBhIHJlZ2lvbiBwYXNzaW5nIHRoZSBmaWx0ZXIuCgojIyBDZWxsIFJlYWQgTWV0cmljcwoKYGBge3IsIGZpZy5hbHQ9IlRvdGFsIFVNSSB4IGdlbmVzIGV4cHJlc3NlZCJ9CmZpbHRlcmVkX2NlbGxkYXRhIDwtIGRhdGEuZnJhbWUoY29sRGF0YShmaWx0ZXJlZF9zY2UpKQoKZ2dwbG90KGZpbHRlcmVkX2NlbGxkYXRhLAogICAgICAgYWVzICh4ID0gc3VtLAogICAgICAgICAgICB5ID0gZGV0ZWN0ZWQsCiAgICAgICAgICAgIGNvbG9yID0gc3Vic2V0c19taXRvX3BlcmNlbnQpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhsaW1pdHMgPSBjKDAsIDEwMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX251bWJlcihhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh4ID0gIlRvdGFsIFVNSSBjb3VudCIsCiAgICAgICB5ID0gIk51bWJlciBvZiBnZW5lcyBkZXRlY3RlZCIsCiAgICAgICBjb2xvciA9ICJQZXJjZW50IHJlYWRzXG5taXRvY2hvbmRyaWFsIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMCwgMSksCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSksCiAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JleTIwIiwgbGluZXdpZHRoID0gMC4yNSksCiAgICAgICAgbGVnZW5kLmJveC5tYXJnaW4gPSBtYXJnaW4ocmVwKDUsIDQpKSkKYGBgCgpUaGUgYWJvdmUgcGxvdCBvZiBjZWxsIG1ldHJpY3MgaW5jbHVkZXMgb25seSBkcm9wbGV0cyB3aGljaCBoYXZlIHBhc3NlZCB0aGUgYGVtcHR5RHJvcHNDZWxsUmFuZ2VyKClgIGZpbHRlci4KVGhlIHBsb3Qgd2lsbCB1c3VhbGx5IGRpc3BsYXkgYSBzdHJvbmcgKGJ1dCBjdXJ2ZWQpIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0b3RhbCBVTUkgY291bnQgYW5kIHRoZSBudW1iZXIgb2YgZ2VuZXMgZGV0ZWN0ZWQuCkNlbGxzIHdpdGggbG93IFVNSSBjb3VudHMgYW5kIGhpZ2ggbWl0b2Nob25kcmlhbCBwZXJjZW50YWdlcyBtYXkgcmVxdWlyZSBmdXJ0aGVyIGZpbHRlcmluZy4KCiMjIG1pUUMgTW9kZWwgRGlhZ25vc3RpY3MKCmBgYHtyLCBmaWcuYWx0PSJtaVFDIG1vZGVsIGRpYWdub3N0aWNzIHBsb3QiLCByZXN1bHRzPSdhc2lzJywgd2FybmluZz1GQUxTRX0KaWYgKHNraXBfbWlRQykgewogIGNhdCgibWlRQyBtb2RlbCBub3QgY3JlYXRlZCwgc2tpcHBpbmcgbWlRQyBwbG90LiBVc3VhbGx5IHRoaXMgaXMgYmVjYXVzZSBtaXRvY2hvbmRyaWFsIGdlbmUgZGF0YSB3YXMgbm90IGF2YWlsYWJsZS4iKQp9IGVsc2UgewogICMgcmVtb3ZlIHByb2JfY29tcHJvbWlzZWQgaWYgaXQgZXhpc3RzLCBhcyB0aGlzIHdpbGwgY2F1c2UgZXJyb3JzIHdpdGggcGxvdE1vZGVsCiAgZmlsdGVyZWRfc2NlJHByb2JfY29tcHJvbWlzZWQgPC0gTlVMTAogIG1pUUNfbW9kZWwgPC0gbWV0YWRhdGEoZmlsdGVyZWRfc2NlKSRtaVFDX21vZGVsCgogIGlmIChpcy5udWxsKG1pUUNfbW9kZWwpIHx8IGxlbmd0aChtaVFDX21vZGVsQGNvbXBvbmVudHMpIDwgMikgewogICAgIyBtb2RlbCBkaWRuJ3QgZml0LCBqdXN0IHBsb3QgbWV0cmljcwogICAgbWlRQ19wbG90IDwtIG1pUUM6OnBsb3RNZXRyaWNzKGZpbHRlcmVkX3NjZSkKICB9IGVsc2UgewogICAgbWlRQ19wbG90IDwtIG1pUUM6OnBsb3RNb2RlbChmaWx0ZXJlZF9zY2UsIG1vZGVsID0gbWlRQ19tb2RlbCkKICB9CgogIG1pUUNfcGxvdCArCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwxMDApKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYWNjdXJhY3kgPSAxKSkgKwogICAgbGFicyh4ID0gIk51bWJlciBvZiBnZW5lcyBkZXRlY3RlZCIsCiAgICAgICAgIHkgPSAiUGVyY2VudCByZWFkcyBtaXRvY2hvbmRyaWFsIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygxLCAxKSwKICAgICAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLDEpLAogICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JleTIwIiwgbGluZXdpZHRoID0gMC4yNSksCiAgICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbihyZXAoNSwgNCkpKQp9CmBgYAoKV2UgY2FsY3VsYXRlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGEgY2VsbCBpcyBjb21wcm9taXNlZCBkdWUgdG8gZGVncmFkYXRpb24gb3IgcnVwdHVyZSB1c2luZyBbYG1pUUNgXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvbWlRQy5odG1sKSAoW0hpcHBlbiBfZXQgYWwuXyAyMDIxXShodHRwczovL2RvaS5vcmcvMTAuMTM3MS9qb3VybmFsLnBjYmkuMTAwOTI5MCkpLgpUaGlzIHJlbGllcyBvbiBmaXR0aW5nIGEgbWl4dHVyZSBtb2RlbCB1c2luZyB0aGUgbnVtYmVyIG9mIGdlbmVzIGV4cHJlc3NlZCBieSBhIGNlbGwgYW5kIHRoZSBwZXJjZW50YWdlIG9mIG1pdG9jaG9uZHJpYWwgcmVhZHMuClRoZSBleHBlY3RlZCBwbG90IHdpbGwgc2hvdyBhIGNoYXJhY3RlcmlzdGljIHRyaWFuZ3VsYXIgc2hhcGUgYW5kIHR3byBtb2RlbCBmaXQgbGluZXMuCkNlbGxzIHdpdGggbG93IG51bWJlcnMgb2YgZ2VuZXMgZXhwcmVzc2VkIG1heSBoYXZlIGJvdGggbG93IGFuZCBoaWdoIG1pdG9jaG9uZHJpYWwgcGVyY2VudGFnZSwgYnV0IGNlbGxzIHdpdGggbWFueSBnZW5lcyB0ZW5kIHRvIGhhdmUgYSBsb3cgbWl0b2Nob25kcmlhbCBwZXJjZW50YWdlLgpDb21wcm9taXNlZCBjZWxscyBhcmUgbGlrZWx5IHRvIGhhdmUgYSBmZXdlciBnZW5lcyBkZXRlY3RlZCBhbmQgaGlnaGVyIHBlcmNlbnRhZ2Ugb2YgbWl0b2Nob25kcmlhbCByZWFkcy4KCklmIHRoZSBtb2RlbCBoYXMgZmFpbGVkIHRvIGZpdCBwcm9wZXJseSwgdGhlIHBhdHRlcm4gb2YgY2VsbHMgbWF5IGRpZmZlciwgYW5kIHRoZXJlIG1heSBub3QgYmUgbW9kZWwgZml0IGxpbmVzLgpUaGlzIGNhbiBiZSB0aGUgcmVzdWx0IG9mIGEgbG93LXF1YWxpdHkgbGlicmFyeSBvciBtYXkgb2NjdXIgaWYgdGhlcmUgaXMgbm8gbWl0b2Nob25kcmlhbCBjb250ZW50LCBhcyBpbiB0aGUgY2FzZSBvZiBhIGhpZ2gtcXVhbGl0eSBzaW5nbGUtbnVjbGV1cyBzYW1wbGUuCkluIHN1Y2ggc2l0dWF0aW9ucywgdGhlIGNhbGN1bGF0ZWQgcHJvYmFiaWxpdHkgb2YgY29tcHJvbWlzZSBtYXkgbm90IGJlIHZhbGlkIChzZWUgW21pUUMgdmlnbmV0dGVdKGh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy8zLjEzL2Jpb2MvdmlnbmV0dGVzL21pUUMvaW5zdC9kb2MvbWlRQy5odG1sI3doZW4tbm90LXRvLXVzZS1taXFjKSBmb3IgbW9yZSBkZXRhaWxzKS4KCiMjIFJlbW92aW5nIGxvdyBxdWFsaXR5IGNlbGxzCgpUaGUgYmVsb3cgcGxvdCBoaWdobGlnaHRzIGNlbGxzIHRoYXQgd2VyZSByZW1vdmVkIHByaW9yIHRvIG5vcm1hbGl6YXRpb24gYW5kIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbi4KQ2VsbHMgdGhhdCBzaG91bGQgYmUgcmVtb3ZlZCBiYXNlZCBvbiBSTkEgY291bnRzIGFyZSB0aG9zZSB0aGF0IGFyZSBpZGVudGlmaWVkIHRvIGJlIGxvdyBxdWFsaXR5IGNlbGxzLCBzdWNoIGFzIGNlbGxzIHdpdGggaGlnaCBwcm9iYWJpbGl0eSBvZiBiZWluZyBjb21wcm9taXNlZC4KVGhlIG1ldGhvZCBvZiBmaWx0ZXJpbmcgaXMgaW5kaWNhdGVkIGFib3ZlIHRoZSBwbG90IGFzIGVpdGhlciBgbWlRQ2Agb3IgYE1pbmltdW0gZ2VuZSBjdXRvZmZgLgpJZiBgbWlRQ2AsIGNlbGxzIGJlbG93IHRoZSBzcGVjaWZpZWQgcHJvYmFiaWxpdHkgY29tcHJvbWlzZWQgY3V0b2ZmIGFuZCBhYm92ZSB0aGUgbWluaW11bSBudW1iZXIgb2YgdW5pcXVlIGdlbmVzIGlkZW50aWZpZWQgYXJlIGtlcHQgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMuCklmIG9ubHkgYSBgTWluaW11bSBnZW5lIGN1dG9mZmAgaXMgdXNlZCwgdGhlbiBgbWlRQ2AgaXMgbm90IHVzZWQgYW5kIG9ubHkgdGhvc2UgY2VsbHMgdGhhdCBwYXNzIHRoZSBtaW5pbXVtIG51bWJlciBvZiB1bmlxdWUgZ2VuZXMgaWRlbnRpZmllZCB0aHJlc2hvbGQgYXJlIHJldGFpbmVkLgpUaGUgZG90dGVkIHZlcnRpY2FsIGxpbmUgaW5kaWNhdGVzIHRoZSBtaW5pbXVtIGdlbmUgY3V0b2ZmIHVzZWQgZm9yIGZpbHRlcmluZy4KCgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KaWYgKGhhc19maWx0ZXJlZCAmIGhhc19wcm9jZXNzZWQpIHsKCiAgIyBncmFiIGN1dG9mZnMgYW5kIGZpbHRlcmluZyBtZXRob2QgZnJvbSBwcm9jZXNzZWQgc2NlCiAgbWluX2dlbmVfY3V0b2ZmIDwtIHByb2Nlc3NlZF9tZXRhJG1pbl9nZW5lX2N1dG9mZgoKICBmaWx0ZXJfbWV0aG9kIDwtIHByb2Nlc3NlZF9tZXRhJHNjcGNhX2ZpbHRlcl9tZXRob2QKCiAgIyBhZGQgY29sdW1uIHRvIGNvbGRhdGEgbGFiZWxpbmcgY2VsbHMgdG8ga2VlcC9yZW1vdmUgYmFzZWQgb24gZmlsdGVyaW5nIG1ldGhvZAogIGZpbHRlcmVkX2NvbGRhdGFfZGYgPC0gY29sRGF0YShmaWx0ZXJlZF9zY2UpIHw+CiAgICBhcy5kYXRhLmZyYW1lKCkgfD4KICAgIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJiYXJjb2RlIikKCiAgZ2dwbG90KGZpbHRlcmVkX2NvbGRhdGFfZGYsIGFlcyh4ID0gZGV0ZWN0ZWQsIHkgPSBzdWJzZXRzX21pdG9fcGVyY2VudCwgY29sb3IgPSBzY3BjYV9maWx0ZXIpKSArCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC41LCBzaXplID0gMSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWluX2dlbmVfY3V0b2ZmLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICBsYWJzKHggPSAiTnVtYmVyIG9mIGdlbmVzIGRldGVjdGVkIiwKICAgICAgICAgeSA9ICJNaXRvY2hvbmRyaWFsIHBlcmNlbnRhZ2UiLAogICAgICAgICBjb2xvciA9ICJGaWx0ZXIiLAogICAgICAgICB0aXRsZSA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlKGZpbHRlcl9tZXRob2QsICJfIiwgIiAiKSkgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDEsIDEpLAogICAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSksCiAgICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmV5MjAiLCBsaW5ld2lkdGggPSAwLjI1KSwKICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCn0gZWxzZSB7CiAgZ2x1ZTo6Z2x1ZSgiCiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiPgoKICAgIE5vIGZpbHRlcmluZyBvZiBsb3cgcXVhbGl0eSBjZWxscyB3YXMgcGVyZm9ybWVkIG9uIHRoaXMgbGlicmFyeS4KCiAgICA8L2Rpdj4KICAiKQp9CmBgYAoKVGhlIHJhdyBjb3VudHMgZnJvbSBhbGwgY2VsbHMgdGhhdCByZW1haW4gYWZ0ZXIgZmlsdGVyaW5nIGxvdyBxdWFsaXR5IGNlbGxzIChSTkEgb25seSkgYXJlIHRoZW4gbm9ybWFsaXplZCBwcmlvciB0byBzZWxlY3Rpb24gb2YgaGlnaGx5IHZhcmlhYmxlIGdlbmVzIGFuZCBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24uCgoKCjwhLS0gTmV4dCBzZWN0aW9uIGluY2x1ZGUgb25seSBpZiBVTUFQIGlzIHByZXNlbnQgLS0+CmBgYHtyLCBjaGlsZD0ndW1hcF9xYy5ybWQnLCBldmFsID0gaGFzX3VtYXB9CgpgYGAKCjwhLS0gTmV4dCBzZWN0aW9uIGluY2x1ZGVkIG9ubHkgaWYgQ0lURS1zZXEgZGF0YSBpcyBwcmVzZW50IC0tPgpgYGB7ciwgY2hpbGQ9J2NpdGVfcWMucm1kJywgZXZhbCA9IGhhc19hZHR9CmBgYAoKPCEtLSBOZXh0IHNlY3Rpb24gb25seSBpbmNsdWRlZCBpZiBtdWx0aXBsZXggZGF0YSBpcyBwcmVzZW50IC0tPgpgYGB7ciwgY2hpbGQ9J211bHRpcGxleF9xYy5ybWQnLCBldmFsID0gaGFzX2NlbGxoYXNofQoKYGBgCgoKIyBTZXNzaW9uIEluZm8KPGRldGFpbHM+CjxzdW1tYXJ5PlIgc2Vzc2lvbiBpbmZvcm1hdGlvbjwvc3VtbWFyeT4KYGBge3Igc2Vzc2lvbl9pbmZvfQppZiAocmVxdWlyZU5hbWVzcGFjZSgic2Vzc2lvbmluZm8iLCBxdWlldGx5ID0gVFJVRSkpIHsKICBzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkKfSBlbHNlIHsKICBzZXNzaW9uSW5mbygpCn0KCmBgYAo8L2RldGFpbHM+Cgo=