Introduction
scRepertoire is designed to take filter contig outputs from
the 10x Genomics Cell Ranger pipeline, process that data to assign
clonotype based on two TCR or Ig chains and analyze the clonotype
dynamics. The latter can be separated into 1) clonotype-only analysis
functions, such as unique clonotypes or clonal space quantification, and
2) interaction with mRNA expression data using Seurat or
SingleCellExperiment packages.
Load libraries
Load Seurat Object
1. Load contigs
scRepertoire functions using the
filtered_contig_annotations.csv output from the 10x Genomics Cell
Ranger. This file is located in the ./outs/ directory of the VDJ
alignment folder. To generate a list of contigs to use for
scRepertoire:
2. Combining Contigs into Clones
contig_list <- list(L1, L2, L3_B, L4_B,L5,L6, L7)
contig_list_with_PBMC <- list(L1, L2, L3_B, L4_B,L5,L6, L7, PBMC)
combined.TCR <- combineTCR(contig_list,
samples = c("L1", "L2", "L3_B", "L4_B", "L5", "L6", "L7"),
removeNA = FALSE,
removeMulti = FALSE,
filterMulti = FALSE)
combined.TCR_with_PBMC <- combineTCR(contig_list_with_PBMC,
samples = c("L1", "L2", "L3_B", "L4_B", "L5", "L6", "L7",
"PBMC"),
removeNA = FALSE,
removeMulti = FALSE,
filterMulti = FALSE)
# exportClones(combined.TCR,
# write.file = TRUE,
# dir = "../TCR_Analysis/",
# file.name = "clones.csv")
#
# exportClones(combined.TCR_with_PBMC,
# write.file = TRUE,
# dir = "../TCR_Analysis/",
# file.name = "clones_with_PBMC.csv")
head(combined.TCR_with_PBMC[[1]])
NA
3. Basic Clonal Visualizations
3.1. clonalQuant
#clonalQuant
clonalQuant(combined.TCR,
cloneCall="strict",
chain = "both",
scale = TRUE)

clonalQuant(combined.TCR_with_PBMC,
cloneCall="strict",
chain = "both",
scale = TRUE)

clonalQuant(combined.TCR, cloneCall = "gene", group.by = "sample", scale = TRUE)

clonalQuant(combined.TCR_with_PBMC, cloneCall = "gene", group.by = "sample", scale = TRUE)

NA
NA
3.2 clonalAbundance
#clonalAbundance
clonalAbundance(combined.TCR_with_PBMC,
cloneCall = "gene", palette = "Zissou 1",
scale = FALSE)+
scale_fill_manual(values = hcl.colors(8,"geyser"))
clonalAbundance(combined.TCR_with_PBMC,
cloneCall = "gene", palette = "Zissou 1",
scale = TRUE)
3.3 clonalLength
#clonalLength
clonalLength(combined.TCR_with_PBMC,
cloneCall="nt",
chain = "both")
clonalLength(combined.TCR_with_PBMC,
cloneCall="aa",
chain = "both")
#TRA
clonalLength(combined.TCR_with_PBMC,
cloneCall="nt",
chain = "TRA",
scale = TRUE)
clonalLength(combined.TCR_with_PBMC,
cloneCall="aa",
chain = "TRA",
scale = TRUE)
#TRB
clonalLength(combined.TCR_with_PBMC,
cloneCall="nt",
chain = "TRB",
scale = TRUE)
clonalLength(combined.TCR_with_PBMC,
cloneCall="aa",
chain = "TRB",
scale = TRUE)
3.4 clonalCompare
# clonalCompare
clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L1", "L2"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L3_B", "L4_B"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L5", "L6","L7"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L5","L6"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L5","L7"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L6","L7"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L1", "L2", "L3_B", "L4_B", "L5", "L6", "L7", "PBMC"),
cloneCall="aa",
graph = "alluvial")

# clonalCompare(combined.TCR_with_PBMC,
# top.clones = 10,
# highlight.clones = c("CVVSDNTGGFKTIF_CASSVRRERANTGELFF", "NA_CASSVRRERANTGELFF"),
# relabel.clones = TRUE,
# samples = c("L1", "L2"),
# cloneCall="aa",
# graph = "alluvial")
#
#
# clonalCompare(combined.TCR_with_PBMC, clones = c("CVVSDNTGGFKTIF_CASSVRRERANTGELFF", "NA_CASSVRRERANTGELFF"),
# relabel.clones = TRUE, samples = c("L1", "L2"), cloneCall = "aa", graph = "alluvial")
3.5 clonalScatter
#clonalScatter
clonalScatter(combined.TCR_with_PBMC,
cloneCall ="gene",
x.axis = "L1",
y.axis = "L2",
dot.size = "total",
graph = "proportion")

clonalScatter(combined.TCR_with_PBMC,
cloneCall ="gene",
x.axis = "L3_B",
y.axis = "L4_B",
dot.size = "total",
graph = "proportion")

clonalScatter(combined.TCR_with_PBMC,
cloneCall ="gene",
x.axis = "L5",
y.axis = "L6",
dot.size = "total",
graph = "proportion")

clonalScatter(combined.TCR_with_PBMC,
cloneCall ="gene",
x.axis = "L5",
y.axis = "L7",
dot.size = "total",
graph = "proportion")

clonalScatter(combined.TCR_with_PBMC,
cloneCall ="gene",
x.axis = "L6",
y.axis = "L7",
dot.size = "total",
graph = "proportion")

4. Visualizing Clonal Dynamics
4.1 clonalHomeostasis
# Visualizing Clonal Dynamics
# clonalHomeostasis
clonalHomeostasis(combined.TCR_with_PBMC,
cloneCall = "gene")

clonalHomeostasis(combined.TCR_with_PBMC,
cloneCall = "gene",
cloneSize = c(Rare = 0.001, Small = 0.01, Medium = 0.1, Large = 0.3, Hyperexpanded =1))

4.2 clonalProportion
# clonalProportion
clonalProportion(combined.TCR_with_PBMC,
cloneCall = "gene")

clonalProportion(combined.TCR_with_PBMC,
cloneCall = "nt",
clonalSplit = c(1, 5, 10, 100, 1000, 10000))

NA
NA
NA
5. Summarizing Repertoires
# Summarizing Repertoires
#percentAA
percentAA(combined.TCR,
chain = "TRB",
aa.length = 20)
Warning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generated

# positionalEntropy
# We can also quantify the level of entropy/diversity across amino acid residues along the cdr3 sequence. positionalEntropy() combines the quantification by residue of percentAA() with the diversity calls in clonalDiversity().
#
# method
#
# “shannon” - Shannon Diversity
# “inv.simpson” - Inverse Simpson Diversity
# “norm.entropy” - Normalized Entropy
positionalEntropy(combined.TCR_with_PBMC,
chain = "TRB",
aa.length = 20)
Warning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generated

# positionalProperty
# Like positionalEntropy(), we can also examine a series of amino acid properties along the cdr3 sequences using positionalProperty(). Important differences from the above function for positionalProperty() is dropping NA values as they would void the mean calculation. positionalProperty() also display a ribbon with the 95% confidence interval surrounding the mean value for the selected properties.
#
# method
#
# “Atchley” - Atchley Factors
# “Kidera” - Kidera Factors
# “stScales” - stScales Vectors
# “tScales” - tScales Vectors
# “VHSE” - Vectors of Hydrophobic, Steric, and Electronic properties
# positionalProperty(combined.TCR_with_PBMC[c(1,2)],
# chain = "TRB",
# aa.length = 20,
# method = "Atchley") +
# scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
#
# positionalProperty(combined.TCR_with_PBMC[c(3,4)],
# chain = "TRB",
# aa.length = 20,
# method = "Atchley") +
# scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
#
# positionalProperty(combined.TCR_with_PBMC[c(5,6)],
# chain = "TRB",
# aa.length = 20,
# method = "Atchley") +
# scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
#
# positionalProperty(combined.TCR_with_PBMC[c(5,7)],
# chain = "TRB",
# aa.length = 20,
# method = "Atchley") +
# scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
#
#
# positionalProperty(combined.TCR_with_PBMC[c(6,7)],
# chain = "TRB",
# aa.length = 20,
# method = "Atchley") +
# scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
#
# positionalProperty(combined.TCR_with_PBMC[c(5,6,7)],
# chain = "TRB",
# aa.length = 20,
# method = "Atchley") +
# scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
# vizGenes
# A visualization of the relative usage of genes of the TCR or BCR, using vizGenes(). There is some functional crossover between vizGenes() and two functions below called percentGenes() and percentVJ(). But vizGenes() is more adaptable to allow for comparisons across chains, scaling, etc.
vizGenes(combined.TCR_with_PBMC,
x.axis = "TRBV",
y.axis = NULL,
plot = "barplot",
scale = TRUE)

vizGenes(combined.TCR_with_PBMC,
x.axis = "TRAV",
y.axis = NULL,
plot = "barplot",
scale = TRUE)

vizGenes(combined.TCR[c(1,2,3,4,5,6,7)],
x.axis = "TRBV",
y.axis = "TRBJ",
plot = "heatmap",
scale = TRUE)

vizGenes(combined.TCR[c(1,2,3,4,5,6,7)],
x.axis = "TRAV",
y.axis = "TRAJ",
plot = "heatmap",
scale = TRUE)

# For the P17 patient samples, what if we are interested in chain pairings, we can look at TRBV and TRAV at the same time using them as inputs to x.axis and y.axis.
vizGenes(combined.TCR[c(1,2)],
x.axis = "TRBV",
y.axis = "TRAV",
plot = "heatmap",
scale = FALSE)

# percentGenes
# Quantify the proportion of V or J gene usage with percentGenes(). Like percentAA(), we select the chain of interest and then indicate the gene of interest with the gene parameter. Two major limitations of percentGenes() are, 1) the function quantifies only V or J genes, and 2) the quantification of the genes are limited to all the V or J genes seen across the samples, not all possible V or J genes.
percentGenes(combined.TCR_with_PBMC,
chain = "TRB",
gene = "Vgene")

percentGenes(combined.TCR_with_PBMC,
chain = "TRA",
gene = "Vgene")

percentGenes(combined.TCR_with_PBMC,
chain = "TRB",
gene = "Jgene")

percentGenes(combined.TCR_with_PBMC,
chain = "TRA",
gene = "Jgene")

# percentVJ
# Quantify the proportion of V and J gene usage with percentVJ(). Like percentGenes(), this function will quantify the percentage of V and J paired together across individual repertoires. The output can be visualized using a heatmap or as input for further dimensional reduction.
percentVJ(combined.TCR_with_PBMC,
chain = "TRB")

percentVJ(combined.TCR_with_PBMC,
chain = "TRA")

# percentKmer
# Another quantification of the composition of the CDR3 sequence is to define motifs by sliding across the amino acid or nucleotide sequences at set intervals resulting in substrings or kmers.
#
# motif.length
#
# Numerical value for the length of the kmer.
# top.motifs
#
# Display the most variable genes determined by mean absolute deviation (MAD).
percentKmer(combined.TCR_with_PBMC,
cloneCall = "aa",
chain = "TRB",
motif.length = 3,
top.motifs = 25)

percentKmer(combined.TCR_with_PBMC,
cloneCall = "aa",
chain = "TRA",
motif.length = 3,
top.motifs = 25)

percentKmer(combined.TCR_with_PBMC,
cloneCall = "nt",
chain = "TRB",
motif.length = 3,
top.motifs = 25)

percentKmer(combined.TCR_with_PBMC,
cloneCall = "nt",
chain = "TRA",
motif.length = 3,
top.motifs = 25)

NA
NA
NA
NA
NA
NA
NA
NA
NA
6. Comparing Clonal Diversity and Overlap
# clonalDiversity
clonalDiversity(combined.TCR_with_PBMC,
cloneCall = "gene")

#clonalSizeDistribution
clonalSizeDistribution(combined.TCR_with_PBMC,
cloneCall = "aa",
method= "ward.D2")

#clonalOverlap
clonalOverlap(combined.TCR_with_PBMC,
cloneCall = "strict",
method = "morisita")

clonalOverlap(combined.TCR_with_PBMC,
cloneCall = "strict",
method = "raw")

7. Combining Clones and Single-Cell Objects
# Combining Clones and Single-Cell Objects
#Getting a sample of a Seurat object
scRep_example <- get(data("All_samples_Merged"))
Warning: data set 'All_samples_Merged' not found
#Define color palette
colorblind_vector <- hcl.colors(n=7, palette = "inferno", fixup = TRUE)
scRep_example <- combineExpression(combined.TCR,
scRep_example,
cloneCall="gene",
group.by = "sample",
proportion = FALSE,
cloneSize=c(Single=1, Small=5, Medium=20, Large=100, Hyperexpanded=500))
DimPlot(scRep_example, group.by = "cloneSize")

DimPlot(scRep_example, group.by = "cloneSize") +
scale_color_manual(values=rev(colorblind_vector[c(1,3,4,5,6)]))

NA
NA
8. Visualizations for Single-Cell Objects
# Visualizations for Single-Cell Objects
# clonalOverlay
#Adding patient information
scRep_example$Patient_origin <- substr(scRep_example$orig.ident, 1,3)
clonalOverlay(scRep_example,
reduction = "umap",
freq.cutpoint = 1,
bins = 10,
facet.by = "Patient_origin") +
guides(color = "none")

#clonalNetwork
#ggraph needs to be loaded due to issues with ggplot
library(ggraph)
Attaching package: 'ggraph'
The following object is masked from 'package:sp':
geometry
clonalNetwork(scRep_example,
reduction = "umap",
group.by = "seurat_clusters",
filter.clones = NULL,
filter.identity = NULL,
cloneCall = "aa")

#Examining Cluster 3 only
clonalNetwork(scRep_example,
reduction = "umap",
group.by = "seurat_clusters",
filter.identity = 8,
cloneCall = "aa")

shared.clones <- clonalNetwork(scRep_example,
reduction = "umap",
group.by = "seurat_clusters",
cloneCall = "aa",
exportClones = TRUE)
head(shared.clones)
scRep_example <- highlightClones(scRep_example,
cloneCall= "aa",
sequence = c("CATGPNGSSNTGKLIF;CALSNNARLMF_CSATTGFYGYTF",
"CAYSESGGSNYKLTF_CSALAGGYTDTQYF",
"CLVGETGRRALTF_CSARGDRGQPQHF",
"CLVGETGRRALTF_CSARGDRGQPQHF;CATSDFKQVSNQPQHF",
"CATGPNGSSNTGKLIF_CSATTGFYGYTF",
"NA_CSARGDRGQPQHF"
))
Seurat::DimPlot(scRep_example, group.by = "highlight") +
ggplot2::theme(plot.title = element_blank())

#clonalOccupy
clonalOccupy(scRep_example,
x.axis = "seurat_clusters")

clonalOccupy(scRep_example,
x.axis = "ident",
proportion = TRUE,
label = FALSE)

# alluvialClones
# scRep_example$Patient_origin <- substr(scRep_example$orig.ident, 8,8)
#
# alluvialClones(scRep_example,
# cloneCall = "aa",
# y.axes = c("Patient_origin", "orig.ident", "Cell_line_Immunophenotype"),
# color = c("CATGPNGSSNTGKLIF;CALSNNARLMF_CSATTGFYGYTF",
# "CAYSESGGSNYKLTF_CSALAGGYTDTQYF",
# "CLVGETGRRALTF_CSARGDRGQPQHF",
# "CLVGETGRRALTF_CSARGDRGQPQHF;CATSDFKQVSNQPQHF",
# "CATGPNGSSNTGKLIF_CSATTGFYGYTF",
# "NA_CSARGDRGQPQHF")) +
# scale_fill_manual(values = c("grey", colorblind_vector[3]))
#
#
#
# alluvialClones(scRep_example,
# cloneCall = "gene",
# y.axes = c("Patient_origin", "orig.ident", "Cell_line_Immunophenotype"),
# color = "ident")
#getCirclize
library(circlize)
========================================
circlize version 0.4.16
CRAN page: https://cran.r-project.org/package=circlize
Github page: https://github.com/jokergoo/circlize
Documentation: https://jokergoo.github.io/circlize_book/book/
If you use it in published research, please cite:
Gu, Z. circlize implements and enhances circular visualization
in R. Bioinformatics 2014.
This message can be suppressed by:
suppressPackageStartupMessages(library(circlize))
========================================
library(scales)
Attaching package: 'scales'
The following object is masked from 'package:purrr':
discard
The following object is masked from 'package:readr':
col_factor
circles <- getCirclize(scRep_example,
group.by = "seurat_clusters")
#Just assigning the normal colors to each cluster
grid.cols <- hue_pal()(length(unique(scRep_example$seurat_clusters)))
names(grid.cols) <- unique(scRep_example$seurat_clusters)
#Graphing the chord diagram
chordDiagram(circles, self.link = 1, grid.col = grid.cols)

circles <- getCirclize(scRep_example, group.by = "cell_line", proportion = TRUE)
grid.cols <- scales::hue_pal()(length(unique(scRep_example@active.ident)))
names(grid.cols) <- levels(scRep_example@active.ident)
chordDiagram(circles,
self.link = 1,
grid.col = grid.cols,
directional = 1,
direction.type = "arrows",
link.arr.type = "big.arrow")

NA
NA
NA
NA
LS0tCnRpdGxlOiAiVENSIEFuYWx5c2lzIgphdXRob3I6ICJOYXNpciBNYWhtb29kIEFiYmFzaSIKZGF0ZTogIjIwMjQtMDQtMTkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCiAgICB0aGVtZTogZGFya2x5CiAgIAotLS0KCiMgSW50cm9kdWN0aW9uCgoqKnNjUmVwZXJ0b2lyZSBpcyBkZXNpZ25lZCB0byB0YWtlIGZpbHRlciBjb250aWcgb3V0cHV0cyBmcm9tIHRoZSAxMHggR2Vub21pY3MgQ2VsbCBSYW5nZXIgcGlwZWxpbmUsIHByb2Nlc3MgdGhhdCBkYXRhIHRvIGFzc2lnbiBjbG9ub3R5cGUgYmFzZWQgb24gdHdvIFRDUiBvciBJZyBjaGFpbnMgYW5kIGFuYWx5emUgdGhlIGNsb25vdHlwZSBkeW5hbWljcy4gVGhlIGxhdHRlciBjYW4gYmUgc2VwYXJhdGVkIGludG8gMSkgY2xvbm90eXBlLW9ubHkgYW5hbHlzaXMgZnVuY3Rpb25zLCBzdWNoIGFzIHVuaXF1ZSBjbG9ub3R5cGVzIG9yIGNsb25hbCBzcGFjZSBxdWFudGlmaWNhdGlvbiwgYW5kIDIpIGludGVyYWN0aW9uIHdpdGggbVJOQSBleHByZXNzaW9uIGRhdGEgdXNpbmcgU2V1cmF0IG9yIFNpbmdsZUNlbGxFeHBlcmltZW50IHBhY2thZ2VzLioqCgojIExvYWQgbGlicmFyaWVzCgpgYGB7ciBsaWJyYXJpZXMsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQpsaWJyYXJ5KFNldXJhdERhdGEpCgpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShBemltdXRoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeSh0aW55dGV4KQoKbGlicmFyeShncmlkKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkocHJlc3RvKQojVENSIEFuYWx5c2lzCmxpYnJhcnkoc2NSZXBlcnRvaXJlKQpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQoKbGlicmFyeShjaXJjbGl6ZSkKbGlicmFyeShzY2FsZXMpCmBgYAoKIyBMb2FkIFNldXJhdCBPYmplY3QKCmBgYHtyIGxvYWRfc2V1cmF0LCBpbmNsdWRlPUZBTFNFfQoKI0xvYWQgU2V1cmF0IE9iamVjdCBtZXJnZWQgZnJvbSBjZWxsIGxpbmVzIGFuZCBhIGNvbnRyb2woUEJNQykgYWZ0ZXIgZmlsdHJhdGlvbgpsb2FkKCIuLi8wLjctT0JKL1NTX0FsbF9TYW1wbGVfTWVyZ2VkX0F6aW11dGhfUHJvamVjdFRpbHNfc2luZ2xlUl9BTk5PVEFUSU9OX29uX015X1VNQVAwLjdfSFBDLlJvYmoiKQoKYGBgCgojIDEuIExvYWQgY29udGlncwoKKipzY1JlcGVydG9pcmUgZnVuY3Rpb25zIHVzaW5nIHRoZSBmaWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IG91dHB1dCBmcm9tIHRoZSAxMHggR2Vub21pY3MgQ2VsbCBSYW5nZXIuIFRoaXMgZmlsZSBpcyBsb2NhdGVkIGluIHRoZSAuL291dHMvIGRpcmVjdG9yeSBvZiB0aGUgVkRKIGFsaWdubWVudCBmb2xkZXIuIFRvIGdlbmVyYXRlIGEgbGlzdCBvZiBjb250aWdzIHRvIHVzZSBmb3Igc2NSZXBlcnRvaXJlOioqCgotICAgbG9hZCB0aGUgZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiBmb3IgZWFjaCBvZiB0aGUgc2FtcGxlcy4KCi0gICBtYWtlIGEgbGlzdCBpbiB0aGUgUiBlbnZpcm9ubWVudC4KCgpgYGB7ciBUQ1IsIGluY2x1ZGU9RkFMU0V9CgpMMSA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MMS9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MMS92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKTDIgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDIvb3V0cy9wZXJfc2FtcGxlX291dHMvTDIvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkwzX0IgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDNfQ0lURV9CLy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MM19DSVRFX0IvL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNF9CIDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjEzNS41LHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YS9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w0X0Ivb3V0cy9wZXJfc2FtcGxlX291dHMvTDRfQi8vdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkw1IDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjEzNS41LHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YS9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w1L291dHMvcGVyX3NhbXBsZV9vdXRzL0w1L3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNiA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MNl9DSVRFLy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MNl9DSVRFLy92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKTDcgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDcvb3V0cy9wZXJfc2FtcGxlX291dHMvTDcvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpClBCTUMgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvUEJNQy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9QQk1DL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQoKYGBgCgoKIyAyLiBDb21iaW5pbmcgQ29udGlncyBpbnRvIENsb25lcwpgYGB7ciBjb21iaW5lZFRDUiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KCmNvbnRpZ19saXN0IDwtIGxpc3QoTDEsIEwyLCBMM19CLCBMNF9CLEw1LEw2LCBMNykKY29udGlnX2xpc3Rfd2l0aF9QQk1DIDwtIGxpc3QoTDEsIEwyLCBMM19CLCBMNF9CLEw1LEw2LCBMNywgUEJNQykKCmNvbWJpbmVkLlRDUiA8LSBjb21iaW5lVENSKGNvbnRpZ19saXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiLCAiTDNfQiIsICJMNF9CIiwgIkw1IiwgIkw2IiwgIkw3IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU5BID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU11bHRpID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlck11bHRpID0gRkFMU0UpCgpjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DIDwtIGNvbWJpbmVUQ1IoY29udGlnX2xpc3Rfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiwgIkwzX0IiLCAiTDRfQiIsICJMNSIsICJMNiIsICJMNyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEJNQyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVOQSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlTXVsdGkgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlck11bHRpID0gRkFMU0UpCgojICBleHBvcnRDbG9uZXMoY29tYmluZWQuVENSLCAKIyAgICAgICAgICAgICAgIHdyaXRlLmZpbGUgPSBUUlVFLAojICAgICAgICAgICAgICAgZGlyID0gIi4uL1RDUl9BbmFseXNpcy8iLAojICAgICAgICAgICAgICBmaWxlLm5hbWUgPSAiY2xvbmVzLmNzdiIpCiMgCiMgZXhwb3J0Q2xvbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAojICAgICAgICAgICAgICB3cml0ZS5maWxlID0gVFJVRSwKIyAgICAgICAgICAgICAgZGlyID0gIi4uL1RDUl9BbmFseXNpcy8iLAojICAgICAgICAgICAgICBmaWxlLm5hbWUgPSAiY2xvbmVzX3dpdGhfUEJNQy5jc3YiKQoKaGVhZChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW1sxXV0pCgpgYGAKIyAzLiBCYXNpYyBDbG9uYWwgVmlzdWFsaXphdGlvbnMKCiMjIDMuMS4gY2xvbmFsUXVhbnQKYGBge3IgQ2xvbmFsLVZpc3VhbGl6YXRpb24sIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiNjbG9uYWxRdWFudAogY2xvbmFsUXVhbnQoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgY2xvbmVDYWxsPSJzdHJpY3QiLCAKICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIsIAogICAgICAgICAgICBzY2FsZSA9IFRSVUUpCgoKY2xvbmFsUXVhbnQoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgIGNsb25lQ2FsbD0ic3RyaWN0IiwgCiAgICAgICAgICAgIGNoYWluID0gImJvdGgiLCAKICAgICAgICAgICAgc2NhbGUgPSBUUlVFKQoKY2xvbmFsUXVhbnQoY29tYmluZWQuVENSLCBjbG9uZUNhbGwgPSAiZ2VuZSIsIGdyb3VwLmJ5ID0gInNhbXBsZSIsIHNjYWxlID0gVFJVRSkKCmNsb25hbFF1YW50KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIGNsb25lQ2FsbCA9ICJnZW5lIiwgZ3JvdXAuYnkgPSAic2FtcGxlIiwgc2NhbGUgPSBUUlVFKQpgYGAKIyMgMy4yIGNsb25hbEFidW5kYW5jZQpgYGB7ciBWMiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KI2Nsb25hbEFidW5kYW5jZQoKY2xvbmFsQWJ1bmRhbmNlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiLCAgcGFsZXR0ZSA9ICJaaXNzb3UgMSIsCiAgICAgICAgICAgICAgICBzY2FsZSA9IEZBTFNFKSsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg4LCJnZXlzZXIiKSkKCmNsb25hbEFidW5kYW5jZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwgcGFsZXR0ZSA9ICJaaXNzb3UgMSIsCiAgICAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpCmBgYAojIyAzLjMgY2xvbmFsTGVuZ3RoCmBgYHtyIFYzLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojY2xvbmFsTGVuZ3RoCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gImJvdGgiKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgIGNoYWluID0gImJvdGgiKSAKI1RSQQpjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjbG9uZUNhbGw9Im50IiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIHNjYWxlID0gVFJVRSkgCgpjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIHNjYWxlID0gVFJVRSkgCgojVFJCCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKYGBgCiMjIDMuNCBjbG9uYWxDb21wYXJlCmBgYHtyIFY0LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojIGNsb25hbENvbXBhcmUKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiksIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICAgICAgIGdyYXBoID0gImFsbHV2aWFsIikKCmNsb25hbENvbXBhcmUoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIHRvcC5jbG9uZXMgPSAxMCwgCiAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMM19CIiwgIkw0X0IiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwgIkw2IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwiTDYiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw2IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiwgIkwzX0IiLCAiTDRfQiIsICJMNSIsICJMNiIsICJMNyIsICJQQk1DIiksIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICAgICAgIGdyYXBoID0gImFsbHV2aWFsIikKCiMgY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKIyAgICAgICAgICAgICAgIHRvcC5jbG9uZXMgPSAxMCwKIyAgICAgICAgICAgICAgIGhpZ2hsaWdodC5jbG9uZXMgPSBjKCJDVlZTRE5UR0dGS1RJRl9DQVNTVlJSRVJBTlRHRUxGRiIsICJOQV9DQVNTVlJSRVJBTlRHRUxGRiIpLAojICAgICAgICAgICAgICAgcmVsYWJlbC5jbG9uZXMgPSBUUlVFLAojICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiksIAojICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAojICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQojIAojIAojIGNsb25hbENvbXBhcmUoY29tYmluZWQuVENSX3dpdGhfUEJNQywgY2xvbmVzID0gYygiQ1ZWU0ROVEdHRktUSUZfQ0FTU1ZSUkVSQU5UR0VMRkYiLCAiTkFfQ0FTU1ZSUkVSQU5UR0VMRkYiKSwKIyAgICAgcmVsYWJlbC5jbG9uZXMgPSBUUlVFLCBzYW1wbGVzID0gYygiTDEiLCAiTDIiKSwgY2xvbmVDYWxsID0gImFhIiwgZ3JhcGggPSAiYWxsdXZpYWwiKQoKYGBgCiMjIDMuNSBjbG9uYWxTY2F0dGVyCmBgYHtyIFY1LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojY2xvbmFsU2NhdHRlcgoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkwxIiwgCiAgICAgICAgICAgICAgeS5heGlzID0gIkwyIiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCgoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkwzX0IiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDRfQiIsCiAgICAgICAgICAgICAgZG90LnNpemUgPSAidG90YWwiLAogICAgICAgICAgICAgIGdyYXBoID0gInByb3BvcnRpb24iKQoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkw1IiwgCiAgICAgICAgICAgICAgeS5heGlzID0gIkw2IiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDUiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDciLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKCmNsb25hbFNjYXR0ZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0iZ2VuZSIsIAogICAgICAgICAgICAgIHguYXhpcyA9ICJMNiIsIAogICAgICAgICAgICAgIHkuYXhpcyA9ICJMNyIsCiAgICAgICAgICAgICAgZG90LnNpemUgPSAidG90YWwiLAogICAgICAgICAgICAgIGdyYXBoID0gInByb3BvcnRpb24iKQpgYGAKIyA0LiBWaXN1YWxpemluZyBDbG9uYWwgRHluYW1pY3MKCiMjIDQuMSBjbG9uYWxIb21lb3N0YXNpcwpgYGB7ciBWNiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KIyBWaXN1YWxpemluZyBDbG9uYWwgRHluYW1pY3MKCiMgY2xvbmFsSG9tZW9zdGFzaXMKCmNsb25hbEhvbWVvc3Rhc2lzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIpCgoKY2xvbmFsSG9tZW9zdGFzaXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwKICAgICAgICAgICAgICAgICAgY2xvbmVTaXplID0gYyhSYXJlID0gMC4wMDEsIFNtYWxsID0gMC4wMSwgTWVkaXVtID0gMC4xLCBMYXJnZSA9IDAuMywgSHlwZXJleHBhbmRlZCA9MSkpCgpgYGAKIyMgNC4yIGNsb25hbFByb3BvcnRpb24KYGBge3IgU3RhdHMsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiMgY2xvbmFsUHJvcG9ydGlvbgoKY2xvbmFsUHJvcG9ydGlvbihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIpIAoKY2xvbmFsUHJvcG9ydGlvbihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICAgICAgIGNsb25hbFNwbGl0ID0gYygxLCA1LCAxMCwgMTAwLCAxMDAwLCAxMDAwMCkpIApgYGAKIyA1LiBTdW1tYXJpemluZyBSZXBlcnRvaXJlcwpgYGB7ciBERSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KIyBTdW1tYXJpemluZyBSZXBlcnRvaXJlcwoKI3BlcmNlbnRBQQoKcGVyY2VudEFBKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgIGFhLmxlbmd0aCA9IDIwKQoKIyBwb3NpdGlvbmFsRW50cm9weQojIFdlIGNhbiBhbHNvIHF1YW50aWZ5IHRoZSBsZXZlbCBvZiBlbnRyb3B5L2RpdmVyc2l0eSBhY3Jvc3MgYW1pbm8gYWNpZCByZXNpZHVlcyBhbG9uZyB0aGUgY2RyMyBzZXF1ZW5jZS4gcG9zaXRpb25hbEVudHJvcHkoKSBjb21iaW5lcyB0aGUgcXVhbnRpZmljYXRpb24gYnkgcmVzaWR1ZSBvZiBwZXJjZW50QUEoKSB3aXRoIHRoZSBkaXZlcnNpdHkgY2FsbHMgaW4gY2xvbmFsRGl2ZXJzaXR5KCkuCiMgCiMgbWV0aG9kCiMgCiMg4oCcc2hhbm5vbuKAnSAtIFNoYW5ub24gRGl2ZXJzaXR5CiMg4oCcaW52LnNpbXBzb27igJ0gLSBJbnZlcnNlIFNpbXBzb24gRGl2ZXJzaXR5CiMg4oCcbm9ybS5lbnRyb3B54oCdIC0gTm9ybWFsaXplZCBFbnRyb3B5Cgpwb3NpdGlvbmFsRW50cm9weShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwKQoKCiMgcG9zaXRpb25hbFByb3BlcnR5CiMgTGlrZSBwb3NpdGlvbmFsRW50cm9weSgpLCB3ZSBjYW4gYWxzbyBleGFtaW5lIGEgc2VyaWVzIG9mIGFtaW5vIGFjaWQgcHJvcGVydGllcyBhbG9uZyB0aGUgY2RyMyBzZXF1ZW5jZXMgdXNpbmcgcG9zaXRpb25hbFByb3BlcnR5KCkuIEltcG9ydGFudCBkaWZmZXJlbmNlcyBmcm9tIHRoZSBhYm92ZSBmdW5jdGlvbiBmb3IgcG9zaXRpb25hbFByb3BlcnR5KCkgaXMgZHJvcHBpbmcgTkEgdmFsdWVzIGFzIHRoZXkgd291bGQgdm9pZCB0aGUgbWVhbiBjYWxjdWxhdGlvbi4gcG9zaXRpb25hbFByb3BlcnR5KCkgYWxzbyBkaXNwbGF5IGEgcmliYm9uIHdpdGggdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIHN1cnJvdW5kaW5nIHRoZSBtZWFuIHZhbHVlIGZvciB0aGUgc2VsZWN0ZWQgcHJvcGVydGllcy4KIyAKIyBtZXRob2QKIyAKIyDigJxBdGNobGV54oCdIC0gQXRjaGxleSBGYWN0b3JzCiMg4oCcS2lkZXJh4oCdIC0gS2lkZXJhIEZhY3RvcnMKIyDigJxzdFNjYWxlc+KAnSAtIHN0U2NhbGVzIFZlY3RvcnMKIyDigJx0U2NhbGVz4oCdIC0gdFNjYWxlcyBWZWN0b3JzCiMg4oCcVkhTReKAnSAtIFZlY3RvcnMgb2YgSHlkcm9waG9iaWMsIFN0ZXJpYywgYW5kIEVsZWN0cm9uaWMgcHJvcGVydGllcwoKIyBwb3NpdGlvbmFsUHJvcGVydHkoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tjKDEsMildLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQojIAojIHBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW2MoMyw0KV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCiMgCiMgcG9zaXRpb25hbFByb3BlcnR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbYyg1LDYpXSwgCiMgICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiMgICAgICAgICAgICAgICAgICAgYWEubGVuZ3RoID0gMjAsIAojICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJBdGNobGV5IikgKyAKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBoY2wuY29sb3JzKDUsICJpbmZlcm5vIilbYygyLDQpXSkKIyAKIyBwb3NpdGlvbmFsUHJvcGVydHkoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tjKDUsNyldLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQojIAojIAojIHBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW2MoNiw3KV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCiMgCiMgcG9zaXRpb25hbFByb3BlcnR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbYyg1LDYsNyldLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQoKCiMgdml6R2VuZXMKIyBBIHZpc3VhbGl6YXRpb24gb2YgdGhlIHJlbGF0aXZlIHVzYWdlIG9mIGdlbmVzIG9mIHRoZSBUQ1Igb3IgQkNSLCB1c2luZyB2aXpHZW5lcygpLiBUaGVyZSBpcyBzb21lIGZ1bmN0aW9uYWwgY3Jvc3NvdmVyIGJldHdlZW4gdml6R2VuZXMoKSBhbmQgdHdvIGZ1bmN0aW9ucyBiZWxvdyBjYWxsZWQgcGVyY2VudEdlbmVzKCkgYW5kIHBlcmNlbnRWSigpLiBCdXQgdml6R2VuZXMoKSBpcyBtb3JlIGFkYXB0YWJsZSB0byBhbGxvdyBmb3IgY29tcGFyaXNvbnMgYWNyb3NzIGNoYWlucywgc2NhbGluZywgZXRjLgoKdml6R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgIHguYXhpcyA9ICJUUkJWIiwKICAgICAgICAgeS5heGlzID0gTlVMTCwKICAgICAgICAgcGxvdCA9ICJiYXJwbG90IiwgIAogICAgICAgICBzY2FsZSA9IFRSVUUpCgp2aXpHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICB4LmF4aXMgPSAiVFJBViIsCiAgICAgICAgeS5heGlzID0gTlVMTCwKICAgICAgICBwbG90ID0gImJhcnBsb3QiLCAgCiAgICAgICAgc2NhbGUgPSBUUlVFKQoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyLDMsNCw1LDYsNyldLCAKICAgICAgICAgeC5heGlzID0gIlRSQlYiLAogICAgICAgICB5LmF4aXMgPSAiVFJCSiIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsICAKICAgICAgICAgc2NhbGUgPSBUUlVFKQoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyLDMsNCw1LDYsNyldLCAKICAgICAgICAgeC5heGlzID0gIlRSQVYiLAogICAgICAgICB5LmF4aXMgPSAiVFJBSiIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsICAKICAgICAgICAgc2NhbGUgPSBUUlVFKQoKIyBGb3IgdGhlIFAxNyBwYXRpZW50IHNhbXBsZXMsIHdoYXQgaWYgd2UgYXJlIGludGVyZXN0ZWQgaW4gY2hhaW4gcGFpcmluZ3MsIHdlIGNhbiBsb29rIGF0IFRSQlYgYW5kIFRSQVYgYXQgdGhlIHNhbWUgdGltZSB1c2luZyB0aGVtIGFzIGlucHV0cyB0byB4LmF4aXMgYW5kIHkuYXhpcy4Kdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyKV0sIAogICAgICAgICB4LmF4aXMgPSAiVFJCViIsCiAgICAgICAgIHkuYXhpcyA9ICJUUkFWIiwKICAgICAgICAgcGxvdCA9ICJoZWF0bWFwIiwgCiAgICAgICAgIHNjYWxlID0gRkFMU0UpCiMgcGVyY2VudEdlbmVzCiMgUXVhbnRpZnkgdGhlIHByb3BvcnRpb24gb2YgViBvciBKIGdlbmUgdXNhZ2Ugd2l0aCBwZXJjZW50R2VuZXMoKS4gTGlrZSBwZXJjZW50QUEoKSwgd2Ugc2VsZWN0IHRoZSBjaGFpbiBvZiBpbnRlcmVzdCBhbmQgdGhlbiBpbmRpY2F0ZSB0aGUgZ2VuZSBvZiBpbnRlcmVzdCB3aXRoIHRoZSBnZW5lIHBhcmFtZXRlci4gVHdvIG1ham9yIGxpbWl0YXRpb25zIG9mIHBlcmNlbnRHZW5lcygpIGFyZSwgMSkgdGhlIGZ1bmN0aW9uIHF1YW50aWZpZXMgb25seSBWIG9yIEogZ2VuZXMsIGFuZCAyKSB0aGUgcXVhbnRpZmljYXRpb24gb2YgdGhlIGdlbmVzIGFyZSBsaW1pdGVkIHRvIGFsbCB0aGUgViBvciBKIGdlbmVzIHNlZW4gYWNyb3NzIHRoZSBzYW1wbGVzLCBub3QgYWxsIHBvc3NpYmxlIFYgb3IgSiBnZW5lcy4KCnBlcmNlbnRHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgZ2VuZSA9ICJWZ2VuZSIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIGdlbmUgPSAiVmdlbmUiKQoKcGVyY2VudEdlbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBnZW5lID0gIkpnZW5lIikKCnBlcmNlbnRHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgZ2VuZSA9ICJKZ2VuZSIpCgoKIyBwZXJjZW50VkoKIyBRdWFudGlmeSB0aGUgcHJvcG9ydGlvbiBvZiBWIGFuZCBKIGdlbmUgdXNhZ2Ugd2l0aCBwZXJjZW50VkooKS4gTGlrZSBwZXJjZW50R2VuZXMoKSwgdGhpcyBmdW5jdGlvbiB3aWxsIHF1YW50aWZ5IHRoZSBwZXJjZW50YWdlIG9mIFYgYW5kIEogcGFpcmVkIHRvZ2V0aGVyIGFjcm9zcyBpbmRpdmlkdWFsIHJlcGVydG9pcmVzLiBUaGUgb3V0cHV0IGNhbiBiZSB2aXN1YWxpemVkIHVzaW5nIGEgaGVhdG1hcCBvciBhcyBpbnB1dCBmb3IgZnVydGhlciBkaW1lbnNpb25hbCByZWR1Y3Rpb24uCgpwZXJjZW50VkooY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICBjaGFpbiA9ICJUUkIiKQoKcGVyY2VudFZKKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgY2hhaW4gPSAiVFJBIikKCiMgcGVyY2VudEttZXIKIyBBbm90aGVyIHF1YW50aWZpY2F0aW9uIG9mIHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgQ0RSMyBzZXF1ZW5jZSBpcyB0byBkZWZpbmUgbW90aWZzIGJ5IHNsaWRpbmcgYWNyb3NzIHRoZSBhbWlubyBhY2lkIG9yIG51Y2xlb3RpZGUgc2VxdWVuY2VzIGF0IHNldCBpbnRlcnZhbHMgcmVzdWx0aW5nIGluIHN1YnN0cmluZ3Mgb3Iga21lcnMuCiMgCiMgbW90aWYubGVuZ3RoCiMgCiMgTnVtZXJpY2FsIHZhbHVlIGZvciB0aGUgbGVuZ3RoIG9mIHRoZSBrbWVyLgojIHRvcC5tb3RpZnMKIyAKIyBEaXNwbGF5IHRoZSBtb3N0IHZhcmlhYmxlIGdlbmVzIGRldGVybWluZWQgYnkgbWVhbiBhYnNvbHV0ZSBkZXZpYXRpb24gKE1BRCkuCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKYGBgCiMgNi4gQ29tcGFyaW5nIENsb25hbCBEaXZlcnNpdHkgYW5kIE92ZXJsYXAKYGBge3IgY2xvbmFsRGl2ZXJzaXR5LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojIGNsb25hbERpdmVyc2l0eQoKCmNsb25hbERpdmVyc2l0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIikKCiNjbG9uYWxTaXplRGlzdHJpYnV0aW9uCgoKY2xvbmFsU2l6ZURpc3RyaWJ1dGlvbihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLCAKICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9ICJ3YXJkLkQyIikKCgoKI2Nsb25hbE92ZXJsYXAKCmNsb25hbE92ZXJsYXAoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0gInN0cmljdCIsIAogICAgICAgICAgICAgIG1ldGhvZCA9ICJtb3Jpc2l0YSIpCgoKY2xvbmFsT3ZlcmxhcChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAic3RyaWN0IiwgCiAgICAgICAgICAgICAgbWV0aG9kID0gInJhdyIpCmBgYAojIDcuIENvbWJpbmluZyBDbG9uZXMgYW5kIFNpbmdsZS1DZWxsIE9iamVjdHMKYGBge3IgU0MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgojIENvbWJpbmluZyBDbG9uZXMgYW5kIFNpbmdsZS1DZWxsIE9iamVjdHMKCiNHZXR0aW5nIGEgc2FtcGxlIG9mIGEgU2V1cmF0IG9iamVjdApzY1JlcF9leGFtcGxlIDwtIGdldChkYXRhKCJBbGxfc2FtcGxlc19NZXJnZWQiKSkKCgojRGVmaW5lIGNvbG9yIHBhbGV0dGUgCmNvbG9yYmxpbmRfdmVjdG9yIDwtIGhjbC5jb2xvcnMobj03LCBwYWxldHRlID0gImluZmVybm8iLCBmaXh1cCA9IFRSVUUpCgoKc2NSZXBfZXhhbXBsZSA8LSBjb21iaW5lRXhwcmVzc2lvbihjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iZ2VuZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNhbXBsZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BvcnRpb24gPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVTaXplPWMoU2luZ2xlPTEsIFNtYWxsPTUsIE1lZGl1bT0yMCwgTGFyZ2U9MTAwLCBIeXBlcmV4cGFuZGVkPTUwMCkpCgpEaW1QbG90KHNjUmVwX2V4YW1wbGUsIGdyb3VwLmJ5ID0gImNsb25lU2l6ZSIpCgpEaW1QbG90KHNjUmVwX2V4YW1wbGUsIGdyb3VwLmJ5ID0gImNsb25lU2l6ZSIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9cmV2KGNvbG9yYmxpbmRfdmVjdG9yW2MoMSwzLDQsNSw2KV0pKQoKCmBgYAojIDguIFZpc3VhbGl6YXRpb25zIGZvciBTaW5nbGUtQ2VsbCBPYmplY3RzCmBgYHtyIFZfc2MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgojIFZpc3VhbGl6YXRpb25zIGZvciBTaW5nbGUtQ2VsbCBPYmplY3RzCiMgY2xvbmFsT3ZlcmxheQoKI0FkZGluZyBwYXRpZW50IGluZm9ybWF0aW9uCnNjUmVwX2V4YW1wbGUkUGF0aWVudF9vcmlnaW4gPC0gc3Vic3RyKHNjUmVwX2V4YW1wbGUkb3JpZy5pZGVudCwgMSwzKQoKY2xvbmFsT3ZlcmxheShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGZyZXEuY3V0cG9pbnQgPSAxLCAKICAgICAgICAgICAgICBiaW5zID0gMTAsIAogICAgICAgICAgICAgIGZhY2V0LmJ5ID0gIlBhdGllbnRfb3JpZ2luIikgKyAKICAgICAgICAgICAgICBndWlkZXMoY29sb3IgPSAibm9uZSIpCgojY2xvbmFsTmV0d29yawojZ2dyYXBoIG5lZWRzIHRvIGJlIGxvYWRlZCBkdWUgdG8gaXNzdWVzIHdpdGggZ2dwbG90CmxpYnJhcnkoZ2dyYXBoKQoKY2xvbmFsTmV0d29yayhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICAgZmlsdGVyLmNsb25lcyA9IE5VTEwsCiAgICAgICAgICAgICAgZmlsdGVyLmlkZW50aXR5ID0gTlVMTCwKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiKQoKCiNFeGFtaW5pbmcgQ2x1c3RlciAzIG9ubHkKY2xvbmFsTmV0d29yayhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICAgZmlsdGVyLmlkZW50aXR5ID0gOCwKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiKQoKCnNoYXJlZC5jbG9uZXMgPC0gY2xvbmFsTmV0d29yayhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImFhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBvcnRDbG9uZXMgPSBUUlVFKQpoZWFkKHNoYXJlZC5jbG9uZXMpCgoKc2NSZXBfZXhhbXBsZSA8LSBoaWdobGlnaHRDbG9uZXMoc2NSZXBfZXhhbXBsZSwgCiAgICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSAiYWEiLCAKICAgICAgICAgICAgICAgICAgICBzZXF1ZW5jZSA9IGMoIkNBVEdQTkdTU05UR0tMSUY7Q0FMU05OQVJMTUZfQ1NBVFRHRllHWVRGIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQVlTRVNHR1NOWUtMVEZfQ1NBTEFHR1lURFRRWUYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0xWR0VUR1JSQUxURl9DU0FSR0RSR1FQUUhGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNMVkdFVEdSUkFMVEZfQ1NBUkdEUkdRUFFIRjtDQVRTREZLUVZTTlFQUUhGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNBVEdQTkdTU05UR0tMSUZfQ1NBVFRHRllHWVRGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5BX0NTQVJHRFJHUVBRSEYiKSkKClNldXJhdDo6RGltUGxvdChzY1JlcF9leGFtcGxlLCBncm91cC5ieSA9ICJoaWdobGlnaHQiKSArIAogIGdncGxvdDI6OnRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgojY2xvbmFsT2NjdXB5CmNsb25hbE9jY3VweShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAic2V1cmF0X2NsdXN0ZXJzIikKCmNsb25hbE9jY3VweShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICAgeC5heGlzID0gImlkZW50IiwgCiAgICAgICAgICAgICAgICAgICAgIHByb3BvcnRpb24gPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBGQUxTRSkKIyBhbGx1dmlhbENsb25lcwoKIyBzY1JlcF9leGFtcGxlJFBhdGllbnRfb3JpZ2luIDwtIHN1YnN0cihzY1JlcF9leGFtcGxlJG9yaWcuaWRlbnQsIDgsOCkKIyAKIyBhbGx1dmlhbENsb25lcyhzY1JlcF9leGFtcGxlLCAKIyAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLCAKIyAgICAgICAgICAgICAgICB5LmF4ZXMgPSBjKCJQYXRpZW50X29yaWdpbiIsICJvcmlnLmlkZW50IiwgIkNlbGxfbGluZV9JbW11bm9waGVub3R5cGUiKSwgCiMgICAgICAgICAgICAgICAgY29sb3IgPSBjKCJDQVRHUE5HU1NOVEdLTElGO0NBTFNOTkFSTE1GX0NTQVRUR0ZZR1lURiIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQVlTRVNHR1NOWUtMVEZfQ1NBTEFHR1lURFRRWUYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDTFZHRVRHUlJBTFRGX0NTQVJHRFJHUVBRSEYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDTFZHRVRHUlJBTFRGX0NTQVJHRFJHUVBRSEY7Q0FUU0RGS1FWU05RUFFIRiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNBVEdQTkdTU05UR0tMSUZfQ1NBVFRHRllHWVRGIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFfQ1NBUkdEUkdRUFFIRiIpKSArIAojICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5IiwgY29sb3JibGluZF92ZWN0b3JbM10pKQojIAojIAojIAojIGFsbHV2aWFsQ2xvbmVzKHNjUmVwX2V4YW1wbGUsIAojICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIsIAojICAgICAgICAgICAgICAgICAgICB5LmF4ZXMgPSBjKCJQYXRpZW50X29yaWdpbiIsICJvcmlnLmlkZW50IiwgIkNlbGxfbGluZV9JbW11bm9waGVub3R5cGUiKSwgCiMgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImlkZW50IikgCgoKCmxpYnJhcnkoY2lyY2xpemUpCmxpYnJhcnkoc2NhbGVzKQoKY2lyY2xlcyA8LSBnZXRDaXJjbGl6ZShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiKQoKI0p1c3QgYXNzaWduaW5nIHRoZSBub3JtYWwgY29sb3JzIHRvIGVhY2ggY2x1c3RlcgpncmlkLmNvbHMgPC0gaHVlX3BhbCgpKGxlbmd0aCh1bmlxdWUoc2NSZXBfZXhhbXBsZSRzZXVyYXRfY2x1c3RlcnMpKSkKbmFtZXMoZ3JpZC5jb2xzKSA8LSB1bmlxdWUoc2NSZXBfZXhhbXBsZSRzZXVyYXRfY2x1c3RlcnMpCgojR3JhcGhpbmcgdGhlIGNob3JkIGRpYWdyYW0KY2hvcmREaWFncmFtKGNpcmNsZXMsIHNlbGYubGluayA9IDEsIGdyaWQuY29sID0gZ3JpZC5jb2xzKQoKCmNpcmNsZXMgPC0gZ2V0Q2lyY2xpemUoc2NSZXBfZXhhbXBsZSwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgcHJvcG9ydGlvbiA9IFRSVUUpCgpncmlkLmNvbHMgPC0gc2NhbGVzOjpodWVfcGFsKCkobGVuZ3RoKHVuaXF1ZShzY1JlcF9leGFtcGxlQGFjdGl2ZS5pZGVudCkpKQpuYW1lcyhncmlkLmNvbHMpIDwtIGxldmVscyhzY1JlcF9leGFtcGxlQGFjdGl2ZS5pZGVudCkKCmNob3JkRGlhZ3JhbShjaXJjbGVzLCAKICAgICAgICAgICAgIHNlbGYubGluayA9IDEsIAogICAgICAgICAgICAgZ3JpZC5jb2wgPSBncmlkLmNvbHMsIAogICAgICAgICAgICAgZGlyZWN0aW9uYWwgPSAxLCAKICAgICAgICAgICAgIGRpcmVjdGlvbi50eXBlID0gICJhcnJvd3MiLAogICAgICAgICAgICAgbGluay5hcnIudHlwZSA9ICJiaWcuYXJyb3ciKQpgYGA=