1. Introduction
Single-cell sequencing is an emerging technology in the field of
immunology and oncology that allows researchers to couple RNA
quantification and other modalities, like immune cell receptor profiling
at the level of an individual cell. A number of workflows and software
packages have been created to process and analyze single-cell
transcriptomic data. These packages allow users to take the vast
dimensionality of the data generated in single-cell-based experiments
and distill the data into novel insights. Unlike the transcriptomic
field, there is a lack of options for software that allow for
single-cell immune receptor profiling. Enabling users to easily combine
RNA and immune profiling, the scRepertoire framework supports use of
10x, single-cell clonal formats and interaction with popular R-based
single-cell data pipelines.
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.
References:
Prerequisite: Ensure the
All_samples_Merged Seurat object is loaded into your R
environment before running the chunks below.
1.1 Load libraries
library(Seurat)
library(SeuratObject)
library(SeuratObject)
library(SeuratData)
library(patchwork)
library(dplyr)
library(ggplot2)
library(tidyverse)
library(rmarkdown)
library(tinytex)
library(grid)
library(cowplot)
library(presto)
#TCR Analysis
library(scRepertoire)
library(SingleCellExperiment)
library(circlize)
library(scales)
1.2 Load Seurat Object
#Load Seurat Object merged from cell lines and a control(PBMC) after filtration
All_samples_Merged <- readRDS("../0-Seurat_RDS_OBJECT_FINAL/All_samples_Merged_with_Renamed_Clusters_final-26-10-2025.rds")
All_samples_Merged
An object of class Seurat
62900 features across 49305 samples within 6 assays
Active assay: RNA (36601 features, 0 variable features)
2 layers present: data, counts
5 other assays present: ADT, prediction.score.celltype.l1, prediction.score.celltype.l2, prediction.score.celltype.l3, SCT
5 dimensional reductions calculated: integrated_dr, ref.umap, pca, umap, harmony
1.3. 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:
- load the filtered_contig_annotations.csv for each of the
samples.
- make a list in the R environment.
2. Combining Contigs into Clones
There are varying definitions of clones in the literature. For the
purposes of scRepertoire, we define a clone as cells with
shared/trackable complementarity-determining region 3 (CDR3) sequences.
Within this definition, one might use amino acid (aa) sequences of one
or both chains to define a clone. Alternatively, we could use nucleotide
(nt) or the V(D)JC genes (genes) to define a clone. The latter, genes,
would be a more permissive definition of “clones,” as multiple amino
acid or nucleotide sequences can result from the same gene combination.
Another option to define a clone is the use of the V(D)JC and nucleotide
sequence (strict). scRepertoire allows for the use of all these
definitions of clones and enables users to select both or individual
chains to examine.
2.1 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", "L4", "L5", "L6", "L7"),
removeNA = FALSE,
removeMulti = FALSE,
filterMulti = FALSE)
combined.TCR_with_PBMC <- combineTCR(contig_list_with_PBMC,
samples = c("L1", "L2", "L3", "L4", "L5", "L6", "L7",
"CD4T_lab"),
removeNA = FALSE,
removeMulti = FALSE,
filterMulti = FALSE)
exportClones(combined.TCR,
write.file = TRUE,
dir = "TCR_analysis-7-11-2025/",
file.name = "clones.csv")
exportClones(combined.TCR_with_PBMC,
write.file = TRUE,
dir = "TCR_analysis-7-11-2025/",
file.name = "clones_with_PBMC.csv")
head(combined.TCR[[1]])
head(combined.TCR_with_PBMC[[1]])
# Combine all data frames in the list into a single data frame
combined_TCR_df <- do.call(rbind, combined.TCR)
# Write the combined data frame to a CSV file
write.csv(combined_TCR_df, file = "TCR_analysis-7-11-2025/combined_TCR.csv", row.names = FALSE)
# Combine all data frames in the list into a single data frame
combined_TCR_with_PBMC_df <- do.call(rbind, combined.TCR_with_PBMC)
# Write the combined data frame to a CSV file
write.csv(combined_TCR_with_PBMC_df, file = "TCR_analysis-7-11-2025/combined_TCR_with_PBMC.csv", row.names = FALSE)
2.2 Write the fasta file for phylogeny
# Define the FASTA file for alpha chains
alpha_fasta_file <- "TCR_analysis-7-11-2025/Phylogeny/cdr3_alpha_sequences.fasta"
# Open a connection to the file
f <- file(alpha_fasta_file, open = "w")
# Loop through the data frame
for (i in seq_len(nrow(combined_TCR_with_PBMC_df))) {
if (!is.na(combined_TCR_with_PBMC_df$cdr3_nt1[i])) {
# Write the header and sequence
writeLines(paste0(">", combined_TCR_df$sample[i], "_alpha"), f)
writeLines(combined_TCR_df$cdr3_nt1[i], f)
}
}
# Close the connection
close(f)
cat("Alpha chain FASTA file created at:", alpha_fasta_file, "\n")
Alpha chain FASTA file created at: TCR_analysis-7-11-2025/Phylogeny/cdr3_alpha_sequences.fasta
# Define the FASTA file for beta chains
beta_fasta_file <- "TCR_analysis-7-11-2025/Phylogeny/cdr3_beta_sequences.fasta"
# Open a connection to the file
f <- file(beta_fasta_file, open = "w")
# Loop through the data frame
for (i in seq_len(nrow(combined_TCR_with_PBMC_df))) {
if (!is.na(combined_TCR_with_PBMC_df$cdr3_nt2[i])) {
# Write the header and sequence
writeLines(paste0(">", combined_TCR_with_PBMC_df$sample[i], "_beta"), f)
writeLines(combined_TCR_df$cdr3_nt2[i], f)
}
}
# Close the connection
close(f)
cat("Beta chain FASTA file created at:", beta_fasta_file, "\n")
Beta chain FASTA file created at: TCR_analysis-7-11-2025/Phylogeny/cdr3_beta_sequences.fasta
3. Basic Clonal Visualizations
3.1. clonalQuant: Quantifying Unique Clones
#clonalQuant
clonalQuant(combined.TCR,
cloneCall="strict",
chain = "both",
scale = TRUE)

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

#clonalQuant
clonalQuant(combined.TCR,
cloneCall="strict",
chain = "both",
scale = FALSE)

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

3.2 clonalAbundance: Distribution of Clones by Size
#clonalAbundance
clonalAbundance(combined.TCR_with_PBMC,
cloneCall = "gene", palette = "Zissou 1",
scale = FALSE)

clonalAbundance(combined.TCR_with_PBMC,
cloneCall = "gene", palette = "Zissou 1",
scale = TRUE)

clonalAbundance(combined.TCR,
cloneCall = "gene",
scale = FALSE)

clonalAbundance(combined.TCR,
cloneCall = "gene",
scale = TRUE)

3.3 clonalLength: Distribution of Sequence Lengths
#clonalLength
clonalLength(combined.TCR_with_PBMC,
cloneCall="nt",
chain = "both")

clonalLength(combined.TCR_with_PBMC,
cloneCall="aa",
chain = "both")

clonalLength(combined.TCR,
cloneCall="nt",
chain = "both")

clonalLength(combined.TCR,
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)

clonalLength(combined.TCR,
cloneCall="nt",
chain = "TRA",
scale = TRUE)

clonalLength(combined.TCR,
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)

clonalLength(combined.TCR,
cloneCall="nt",
chain = "TRB",
scale = TRUE)

clonalLength(combined.TCR,
cloneCall="aa",
chain = "TRB",
scale = TRUE)

3.5 clonalCompare: Clonal Dynamics Between Categorical
Variables
# clonalCompare
clonalCompare(combined.TCR,
top.clones = 10,
samples = c("L1", "L2"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR,
top.clones = 10,
samples = c("L3", "L4"),
cloneCall="aa",
graph = "alluvial")

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

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

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

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

# clonalCompare
clonalCompare(combined.TCR_with_PBMC,
top.clones = 10,
samples = c("L1", "L2", "L3", "L4", "L5", "L6", "L7", "CD4T_lab"),
cloneCall="aa",
graph = "alluvial")

clonalCompare(combined.TCR,
top.clones = 10,
samples = c("L1", "L2", "L3", "L4", "L5", "L6", "L7"),
cloneCall="aa",
graph = "alluvial")

3.6 clonalScatter: Scatterplot of Two Variables
#clonalScatter
clonalScatter(combined.TCR,
cloneCall ="gene",
x.axis = "L1",
y.axis = "L2",
dot.size = "total",
graph = "proportion")

clonalScatter(combined.TCR,
cloneCall ="gene",
x.axis = "L3",
y.axis = "L4",
dot.size = "total",
graph = "proportion")

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

clonalScatter(combined.TCR,
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")

5. Summarizing Repertoires
# Summarizing Repertoires
# percentAA
percentAA(combined.TCR,
chain = "TRB",
aa.length = 20)

# positionalEntropy
positionalEntropy(combined.TCR,
chain = "TRB",
aa.length = 20)

positionalEntropy(combined.TCR_with_PBMC,
chain = "TRB",
aa.length = 20)

# positionalProperty
positionalProperty(combined.TCR[c(1,2)],
chain = "TRB",
aa.length = 20,
method = "atchleyFactors") +
scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])

NA
NA
# percentGeneUsage
vizGenes(combined.TCR,
x.axis = "TRBV",
y.axis = NULL,
plot = "barplot",
summary.fun = "proportion")

vizGenes(combined.TCR,
x.axis = "TRAV",
y.axis = NULL,
plot = "barplot",
summary.fun = "proportion")

vizGenes(combined.TCR_with_PBMC,
x.axis = "TRBV",
y.axis = NULL,
plot = "barplot",
summary.fun = "proportion")

vizGenes(combined.TCR_with_PBMC,
x.axis = "TRAV",
y.axis = NULL,
plot = "barplot",
summary.fun = "proportion")

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

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

vizGenes(combined.TCR[c(1,2)],
x.axis = "TRBV",
y.axis = "TRAV",
plot = "heatmap",
summary.fun = "percent")

vizGenes(combined.TCR[c(3,4)],
x.axis = "TRBV",
y.axis = "TRAV",
plot = "heatmap",
summary.fun = "percent")

vizGenes(combined.TCR[c(5,6,7)],
x.axis = "TRBV",
y.axis = "TRAV",
plot = "heatmap",
summary.fun = "percent")

# percentGenes: Quantifying Single Gene Usage
percentGenes(combined.TCR,
chain = "TRB",
gene = "Vgene",
summary.fun = "percent")

percentGenes(combined.TCR,
chain = "TRA",
gene = "Vgene",
summary.fun = "percent")

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

percentGenes(combined.TCR,
chain = "TRA",
gene = "Jgene",
summary.fun = "percent")

# percentGenes: Quantifying Single Gene Usage
percentGenes(combined.TCR_with_PBMC,
chain = "TRB",
gene = "Vgene",
summary.fun = "percent")

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

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

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

# 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",
summary.fun = "percent")

percentVJ(combined.TCR_with_PBMC,
chain = "TRA",
summary.fun = "percent")

# percentKmer
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)

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

clonalDiversity(combined.TCR,
cloneCall = "gene")

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

clonalSizeDistribution(combined.TCR,
cloneCall = "nt",
method= "ward.D2")

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

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

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

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

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

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

clonalRarefaction(combined.TCR,
plot.type = 1,
hill.numbers = 0,
n.boots = 2)

clonalRarefaction(combined.TCR_with_PBMC,
plot.type = 1,
hill.numbers = 0,
n.boots = 2)

clonalRarefaction(combined.TCR,
plot.type = 2,
hill.numbers = 0,
n.boots = 2)

clonalRarefaction(combined.TCR_with_PBMC,
plot.type = 2,
hill.numbers = 0,
n.boots = 2)

clonalRarefaction(combined.TCR,
plot.type = 3,
hill.numbers = 0,
n.boots = 2)

clonalRarefaction(combined.TCR_with_PBMC,
plot.type = 3,
hill.numbers = 0,
n.boots = 2)

# Rarefaction using Shannon Diversity (q = 1)
clonalRarefaction(combined.TCR,
plot.type = 1,
hill.numbers = 1,
n.boots = 2)

clonalRarefaction(combined.TCR_with_PBMC,
plot.type = 1,
hill.numbers = 1,
n.boots = 2)

LS0tCnRpdGxlOiAiVENSIEFuYWx5c2lzLTctMTEtMjAyNSIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICAjIHBkZl9kb2N1bWVudDogZGVmYXVsdAogICMgd29yZF9kb2N1bWVudDogZGVmYXVsdAogICMgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCgojICoqMS4gSW50cm9kdWN0aW9uKioKClNpbmdsZS1jZWxsIHNlcXVlbmNpbmcgaXMgYW4gZW1lcmdpbmcgdGVjaG5vbG9neSBpbiB0aGUgZmllbGQgb2YgaW1tdW5vbG9neSBhbmQgb25jb2xvZ3kgdGhhdCBhbGxvd3MgcmVzZWFyY2hlcnMgdG8gY291cGxlIFJOQSBxdWFudGlmaWNhdGlvbiBhbmQgb3RoZXIgbW9kYWxpdGllcywgbGlrZSBpbW11bmUgY2VsbCByZWNlcHRvciBwcm9maWxpbmcgYXQgdGhlIGxldmVsIG9mIGFuIGluZGl2aWR1YWwgY2VsbC4gQSBudW1iZXIgb2Ygd29ya2Zsb3dzIGFuZCBzb2Z0d2FyZSBwYWNrYWdlcyBoYXZlIGJlZW4gY3JlYXRlZCB0byBwcm9jZXNzIGFuZCBhbmFseXplIHNpbmdsZS1jZWxsIHRyYW5zY3JpcHRvbWljIGRhdGEuIFRoZXNlIHBhY2thZ2VzIGFsbG93IHVzZXJzIHRvIHRha2UgdGhlIHZhc3QgZGltZW5zaW9uYWxpdHkgb2YgdGhlIGRhdGEgZ2VuZXJhdGVkIGluIHNpbmdsZS1jZWxsLWJhc2VkIGV4cGVyaW1lbnRzIGFuZCBkaXN0aWxsIHRoZSBkYXRhIGludG8gbm92ZWwgaW5zaWdodHMuIFVubGlrZSB0aGUgdHJhbnNjcmlwdG9taWMgZmllbGQsIHRoZXJlIGlzIGEgbGFjayBvZiBvcHRpb25zIGZvciBzb2Z0d2FyZSB0aGF0IGFsbG93IGZvciBzaW5nbGUtY2VsbCBpbW11bmUgcmVjZXB0b3IgcHJvZmlsaW5nLiBFbmFibGluZyB1c2VycyB0byBlYXNpbHkgY29tYmluZSBSTkEgYW5kIGltbXVuZSBwcm9maWxpbmcsIHRoZSBzY1JlcGVydG9pcmUgZnJhbWV3b3JrIHN1cHBvcnRzIHVzZSBvZiAxMHgsIHNpbmdsZS1jZWxsIGNsb25hbCBmb3JtYXRzIGFuZCBpbnRlcmFjdGlvbiB3aXRoIHBvcHVsYXIgUi1iYXNlZCBzaW5nbGUtY2VsbCBkYXRhIHBpcGVsaW5lcy4KCnNjUmVwZXJ0b2lyZSBpcyBkZXNpZ25lZCB0byB0YWtlIGZpbHRlciBjb250aWcgb3V0cHV0cyBmcm9tIHRoZSAxMHggR2Vub21pY3MgQ2VsbCBSYW5nZXIgcGlwZWxpbmUsIHByb2Nlc3MgdGhhdCBkYXRhIHRvIGFzc2lnbiBjbG9ub3R5cGUgYmFzZWQgb24gdHdvIFRDUiBvciBJZyBjaGFpbnMgYW5kIGFuYWx5emUgdGhlIGNsb25vdHlwZSBkeW5hbWljcy4gVGhlIGxhdHRlciBjYW4gYmUgc2VwYXJhdGVkIGludG8gMSkgY2xvbm90eXBlLW9ubHkgYW5hbHlzaXMgZnVuY3Rpb25zLCBzdWNoIGFzIHVuaXF1ZSBjbG9ub3R5cGVzIG9yIGNsb25hbCBzcGFjZSBxdWFudGlmaWNhdGlvbiwgYW5kIDIpIGludGVyYWN0aW9uIHdpdGggbVJOQSBleHByZXNzaW9uIGRhdGEgdXNpbmcgU2V1cmF0IG9yIFNpbmdsZUNlbGxFeHBlcmltZW50IHBhY2thZ2VzLgoKKipSZWZlcmVuY2VzOioqCgotIFtzY1JlcGVydG9pcmUgVmlnbmV0dGVdKGh0dHBzOi8vd3d3LmJpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL3ZpZ25ldHRlcy9zY1JlcGVydG9pcmUvaW5zdC9kb2MvdmlnbmV0dGUuaHRtbCkgIAotIFtCb3JjaC5kZXYgc2NSZXBlcnRvaXJlXShodHRwczovL3d3dy5ib3JjaC5kZXYvdXBsb2Fkcy9zY3JlcGVydG9pcmUvKQoKCgoqKlByZXJlcXVpc2l0ZToqKiBFbnN1cmUgdGhlIGBBbGxfc2FtcGxlc19NZXJnZWRgIFNldXJhdCBvYmplY3QgaXMgbG9hZGVkIGludG8geW91ciBSIGVudmlyb25tZW50IGJlZm9yZSBydW5uaW5nIHRoZSBjaHVua3MgYmVsb3cuCgojIyAxLjEgTG9hZCBsaWJyYXJpZXMKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocm1hcmtkb3duKQpsaWJyYXJ5KHRpbnl0ZXgpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KHByZXN0bykKCiNUQ1IgQW5hbHlzaXMKbGlicmFyeShzY1JlcGVydG9pcmUpCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpCmxpYnJhcnkoY2lyY2xpemUpCmxpYnJhcnkoc2NhbGVzKQpgYGAKCiMjIDEuMiAgTG9hZCBTZXVyYXQgT2JqZWN0CmBgYHtyfQoKI0xvYWQgU2V1cmF0IE9iamVjdCBtZXJnZWQgZnJvbSBjZWxsIGxpbmVzIGFuZCBhIGNvbnRyb2woUEJNQykgYWZ0ZXIgZmlsdHJhdGlvbgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gcmVhZFJEUygiLi4vMC1TZXVyYXRfUkRTX09CSkVDVF9GSU5BTC9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9SZW5hbWVkX0NsdXN0ZXJzX2ZpbmFsLTI2LTEwLTIwMjUucmRzIikKCkFsbF9zYW1wbGVzX01lcmdlZApgYGAKCiMjIDEuMy4gTG9hZCBjb250aWdzCgpzY1JlcGVydG9pcmUgZnVuY3Rpb25zIHVzaW5nIHRoZSBmaWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IG91dHB1dCBmcm9tIHRoZSAxMHggR2Vub21pY3MgQ2VsbCBSYW5nZXIuIFRoaXMgZmlsZSBpcyBsb2NhdGVkIGluIHRoZSAuL291dHMvIGRpcmVjdG9yeSBvZiB0aGUgVkRKIGFsaWdubWVudCBmb2xkZXIuIFRvIGdlbmVyYXRlIGEgbGlzdCBvZiBjb250aWdzIHRvIHVzZSBmb3Igc2NSZXBlcnRvaXJlOgoKKiotICAgbG9hZCB0aGUgZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiBmb3IgZWFjaCBvZiB0aGUgc2FtcGxlcy4qKgoKKiotICAgbWFrZSBhIGxpc3QgaW4gdGhlIFIgZW52aXJvbm1lbnQuKioKCgpgYGB7ciBUQ1IsIGluY2x1ZGU9RkFMU0V9CkwxIDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjE0Mi4xMzEsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhX1NTL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDEvb3V0cy9wZXJfc2FtcGxlX291dHMvTDEvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkwyIDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjE0Mi4xMzEsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhX1NTL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDIvb3V0cy9wZXJfc2FtcGxlX291dHMvTDIvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkwzX0IgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTQyLjEzMSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGFfU1MvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MM19DSVRFX0IvL291dHMvcGVyX3NhbXBsZV9vdXRzL0wzX0NJVEVfQi8vdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkw0X0IgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTQyLjEzMSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGFfU1MvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MNF9CL291dHMvcGVyX3NhbXBsZV9vdXRzL0w0X0IvL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNSA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xNDIuMTMxLHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YV9TUy9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w1L291dHMvcGVyX3NhbXBsZV9vdXRzL0w1L3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNiA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xNDIuMTMxLHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YV9TUy9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w2X0NJVEUvL291dHMvcGVyX3NhbXBsZV9vdXRzL0w2X0NJVEUvL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNyA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xNDIuMTMxLHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YV9TUy9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w3L291dHMvcGVyX3NhbXBsZV9vdXRzL0w3L3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpQQk1DIDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjE0Mi4xMzEsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhX1NTL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvUEJNQy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9QQk1DL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQoKYGBgCgojIyBDcmVhdGUgZGlzcGxheV9zYW1wbGUgY29sdW1uIGZvciB1bmlmb3JtIG5hbWluZwpgYGB7cn0KIyBDcmVhdGUgYSBuZXcgbWV0YWRhdGEgY29sdW1uIGZvciBwbG90dGluZyB3aXRoIHNpbXBsaWZpZWQgc2FtcGxlIG5hbWVzCkFsbF9zYW1wbGVzX01lcmdlZCRkaXNwbGF5X3NhbXBsZSA8LSBBbGxfc2FtcGxlc19NZXJnZWQkb3JpZy5pZGVudAoKIyBSZW5hbWUgTDNfQiBhbmQgTDRfQiB0byBMMyBhbmQgTDQKQWxsX3NhbXBsZXNfTWVyZ2VkJGRpc3BsYXlfc2FtcGxlIDwtIGdzdWIoIl5MM19CJCIsICJMMyIsIEFsbF9zYW1wbGVzX01lcmdlZCRkaXNwbGF5X3NhbXBsZSkKQWxsX3NhbXBsZXNfTWVyZ2VkJGRpc3BsYXlfc2FtcGxlIDwtIGdzdWIoIl5MNF9CJCIsICJMNCIsIEFsbF9zYW1wbGVzX01lcmdlZCRkaXNwbGF5X3NhbXBsZSkKCiMgUmVuYW1lIFBCTUMgdG8gQ0Q0VF9sYWIKQWxsX3NhbXBsZXNfTWVyZ2VkJGRpc3BsYXlfc2FtcGxlIDwtIGdzdWIoIl5QQk1DJCIsICJDRDRUX2xhYiIsIEFsbF9zYW1wbGVzX01lcmdlZCRkaXNwbGF5X3NhbXBsZSkKYGBgCgojICoqMi4gQ29tYmluaW5nIENvbnRpZ3MgaW50byBDbG9uZXMqKgoKVGhlcmUgYXJlIHZhcnlpbmcgZGVmaW5pdGlvbnMgb2YgY2xvbmVzIGluIHRoZSBsaXRlcmF0dXJlLiBGb3IgdGhlIHB1cnBvc2VzIG9mIHNjUmVwZXJ0b2lyZSwgd2UgZGVmaW5lIGEgY2xvbmUgYXMgY2VsbHMgd2l0aCBzaGFyZWQvdHJhY2thYmxlIGNvbXBsZW1lbnRhcml0eS1kZXRlcm1pbmluZyByZWdpb24gMyAoQ0RSMykgc2VxdWVuY2VzLiBXaXRoaW4gdGhpcyBkZWZpbml0aW9uLCBvbmUgbWlnaHQgdXNlIGFtaW5vIGFjaWQgKGFhKSBzZXF1ZW5jZXMgb2Ygb25lIG9yIGJvdGggY2hhaW5zIHRvIGRlZmluZSBhIGNsb25lLiBBbHRlcm5hdGl2ZWx5LCB3ZSBjb3VsZCB1c2UgbnVjbGVvdGlkZSAobnQpIG9yIHRoZSBWKEQpSkMgZ2VuZXMgKGdlbmVzKSB0byBkZWZpbmUgYSBjbG9uZS4gVGhlIGxhdHRlciwgZ2VuZXMsIHdvdWxkIGJlIGEgbW9yZSBwZXJtaXNzaXZlIGRlZmluaXRpb24gb2Yg4oCcY2xvbmVzLOKAnSBhcyBtdWx0aXBsZSBhbWlubyBhY2lkIG9yIG51Y2xlb3RpZGUgc2VxdWVuY2VzIGNhbiByZXN1bHQgZnJvbSB0aGUgc2FtZSBnZW5lIGNvbWJpbmF0aW9uLiBBbm90aGVyIG9wdGlvbiB0byBkZWZpbmUgYSBjbG9uZSBpcyB0aGUgdXNlIG9mIHRoZSBWKEQpSkMgYW5kIG51Y2xlb3RpZGUgc2VxdWVuY2UgKHN0cmljdCkuIHNjUmVwZXJ0b2lyZSBhbGxvd3MgZm9yIHRoZSB1c2Ugb2YgYWxsIHRoZXNlIGRlZmluaXRpb25zIG9mIGNsb25lcyBhbmQgZW5hYmxlcyB1c2VycyB0byBzZWxlY3QgYm90aCBvciBpbmRpdmlkdWFsIGNoYWlucyB0byBleGFtaW5lLgoKIyMgMi4xIENvbWJpbmluZyBDb250aWdzIGludG8gQ2xvbmVzCmBgYHtyIGNvbWJpbmVkVENSLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQoKY29udGlnX2xpc3QgPC0gbGlzdChMMSwgTDIsIEwzX0IsIEw0X0IsTDUsTDYsIEw3KQpjb250aWdfbGlzdF93aXRoX1BCTUMgPC0gbGlzdChMMSwgTDIsIEwzX0IsIEw0X0IsTDUsTDYsIEw3LCBQQk1DKQoKY29tYmluZWQuVENSIDwtIGNvbWJpbmVUQ1IoY29udGlnX2xpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMMSIsICJMMiIsICJMMyIsICJMNCIsICJMNSIsICJMNiIsICJMNyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVOQSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVNdWx0aSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJNdWx0aSA9IEZBTFNFKQoKY29tYmluZWQuVENSX3dpdGhfUEJNQyA8LSBjb21iaW5lVENSKGNvbnRpZ19saXN0X3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMMSIsICJMMiIsICJMMyIsICJMNCIsICJMNSIsICJMNiIsICJMNyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0Q0VF9sYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlTkEgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU11bHRpID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJNdWx0aSA9IEZBTFNFKQoKIGV4cG9ydENsb25lcyhjb21iaW5lZC5UQ1IsCiAgICAgICAgICAgICAgd3JpdGUuZmlsZSA9IFRSVUUsCiAgICAgICAgICAgICAgZGlyID0gIlRDUl9hbmFseXNpcy03LTExLTIwMjUvIiwKICAgICAgICAgICAgIGZpbGUubmFtZSA9ICJjbG9uZXMuY3N2IikKCmV4cG9ydENsb25lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLAogICAgICAgICAgICAgd3JpdGUuZmlsZSA9IFRSVUUsCiAgICAgICAgICAgICBkaXIgPSAiVENSX2FuYWx5c2lzLTctMTEtMjAyNS8iLAogICAgICAgICAgICAgZmlsZS5uYW1lID0gImNsb25lc193aXRoX1BCTUMuY3N2IikKCmhlYWQoY29tYmluZWQuVENSW1sxXV0pCmhlYWQoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tbMV1dKQoKIyBDb21iaW5lIGFsbCBkYXRhIGZyYW1lcyBpbiB0aGUgbGlzdCBpbnRvIGEgc2luZ2xlIGRhdGEgZnJhbWUKY29tYmluZWRfVENSX2RmIDwtIGRvLmNhbGwocmJpbmQsIGNvbWJpbmVkLlRDUikKCiMgV3JpdGUgdGhlIGNvbWJpbmVkIGRhdGEgZnJhbWUgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YoY29tYmluZWRfVENSX2RmLCBmaWxlID0gIlRDUl9hbmFseXNpcy03LTExLTIwMjUvY29tYmluZWRfVENSLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKCiMgQ29tYmluZSBhbGwgZGF0YSBmcmFtZXMgaW4gdGhlIGxpc3QgaW50byBhIHNpbmdsZSBkYXRhIGZyYW1lCmNvbWJpbmVkX1RDUl93aXRoX1BCTUNfZGYgPC0gZG8uY2FsbChyYmluZCwgY29tYmluZWQuVENSX3dpdGhfUEJNQykKCiMgV3JpdGUgdGhlIGNvbWJpbmVkIGRhdGEgZnJhbWUgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YoY29tYmluZWRfVENSX3dpdGhfUEJNQ19kZiwgZmlsZSA9ICJUQ1JfYW5hbHlzaXMtNy0xMS0yMDI1L2NvbWJpbmVkX1RDUl93aXRoX1BCTUMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMgMi4yIFdyaXRlIHRoZSBmYXN0YSBmaWxlIGZvciBwaHlsb2dlbnkKYGBge3IgcGh5bG9nZW5leUZpbGVzLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQoKIyAjIERlZmluZSB0aGUgRkFTVEEgZmlsZSBmb3IgYWxwaGEgY2hhaW5zCiMgYWxwaGFfZmFzdGFfZmlsZSA8LSAiVENSX2FuYWx5c2lzLTctMTEtMjAyNS9QaHlsb2dlbnkvY2RyM19hbHBoYV9zZXF1ZW5jZXMuZmFzdGEiCiMgCiMgIyBPcGVuIGEgY29ubmVjdGlvbiB0byB0aGUgZmlsZQojIGYgPC0gZmlsZShhbHBoYV9mYXN0YV9maWxlLCBvcGVuID0gInciKQojIAojICMgTG9vcCB0aHJvdWdoIHRoZSBkYXRhIGZyYW1lCiMgZm9yIChpIGluIHNlcV9sZW4obnJvdyhjb21iaW5lZF9UQ1Jfd2l0aF9QQk1DX2RmKSkpIHsKIyAgIGlmICghaXMubmEoY29tYmluZWRfVENSX3dpdGhfUEJNQ19kZiRjZHIzX250MVtpXSkpIHsKIyAgICAgIyBXcml0ZSB0aGUgaGVhZGVyIGFuZCBzZXF1ZW5jZQojICAgICB3cml0ZUxpbmVzKHBhc3RlMCgiPiIsIGNvbWJpbmVkX1RDUl9kZiRzYW1wbGVbaV0sICJfYWxwaGEiKSwgZikKIyAgICAgd3JpdGVMaW5lcyhjb21iaW5lZF9UQ1JfZGYkY2RyM19udDFbaV0sIGYpCiMgICB9CiMgfQojIAojICMgQ2xvc2UgdGhlIGNvbm5lY3Rpb24KIyBjbG9zZShmKQojIAojIGNhdCgiQWxwaGEgY2hhaW4gRkFTVEEgZmlsZSBjcmVhdGVkIGF0OiIsIGFscGhhX2Zhc3RhX2ZpbGUsICJcbiIpCiMgCiMgCiMgIyBEZWZpbmUgdGhlIEZBU1RBIGZpbGUgZm9yIGJldGEgY2hhaW5zCiMgYmV0YV9mYXN0YV9maWxlIDwtICJUQ1JfYW5hbHlzaXMtNy0xMS0yMDI1L1BoeWxvZ2VueS9jZHIzX2JldGFfc2VxdWVuY2VzLmZhc3RhIgojIAojICMgT3BlbiBhIGNvbm5lY3Rpb24gdG8gdGhlIGZpbGUKIyBmIDwtIGZpbGUoYmV0YV9mYXN0YV9maWxlLCBvcGVuID0gInciKQojIAojICMgTG9vcCB0aHJvdWdoIHRoZSBkYXRhIGZyYW1lCiMgZm9yIChpIGluIHNlcV9sZW4obnJvdyhjb21iaW5lZF9UQ1Jfd2l0aF9QQk1DX2RmKSkpIHsKIyAgIGlmICghaXMubmEoY29tYmluZWRfVENSX3dpdGhfUEJNQ19kZiRjZHIzX250MltpXSkpIHsKIyAgICAgIyBXcml0ZSB0aGUgaGVhZGVyIGFuZCBzZXF1ZW5jZQojICAgICB3cml0ZUxpbmVzKHBhc3RlMCgiPiIsIGNvbWJpbmVkX1RDUl93aXRoX1BCTUNfZGYkc2FtcGxlW2ldLCAiX2JldGEiKSwgZikKIyAgICAgd3JpdGVMaW5lcyhjb21iaW5lZF9UQ1JfZGYkY2RyM19udDJbaV0sIGYpCiMgICB9CiMgfQojIAojICMgQ2xvc2UgdGhlIGNvbm5lY3Rpb24KIyBjbG9zZShmKQojIAojIGNhdCgiQmV0YSBjaGFpbiBGQVNUQSBmaWxlIGNyZWF0ZWQgYXQ6IiwgYmV0YV9mYXN0YV9maWxlLCAiXG4iKQpgYGAKCgoKIyAqKjMuIEJhc2ljIENsb25hbCBWaXN1YWxpemF0aW9ucyoqCgojIyAzLjEuIGNsb25hbFF1YW50OiBRdWFudGlmeWluZyBVbmlxdWUgQ2xvbmVzCmBgYHtyIENsb25hbC1WaXN1YWxpemF0aW9uLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQojY2xvbmFsUXVhbnQKIGNsb25hbFF1YW50KGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgIGNsb25lQ2FsbD0ic3RyaWN0IiwgCiAgICAgICAgICAgIGNoYWluID0gImJvdGgiLCAKICAgICAgICAgICAgc2NhbGUgPSBUUlVFKQoKCmNsb25hbFF1YW50KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGw9InN0cmljdCIsIAogICAgICAgICAgICBjaGFpbiA9ICJib3RoIiwgCiAgICAgICAgICAgIHNjYWxlID0gVFJVRSkKCiNjbG9uYWxRdWFudAogY2xvbmFsUXVhbnQoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgY2xvbmVDYWxsPSJzdHJpY3QiLCAKICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIsIAogICAgICAgICAgICBzY2FsZSA9IEZBTFNFKQoKCmNsb25hbFF1YW50KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGw9InN0cmljdCIsIAogICAgICAgICAgICBjaGFpbiA9ICJib3RoIiwgCiAgICAgICAgICAgIHNjYWxlID0gRkFMU0UpCmBgYAoKIyMgMy4yIGNsb25hbEFidW5kYW5jZTogRGlzdHJpYnV0aW9uIG9mIENsb25lcyBieSBTaXplCmBgYHtyIFYyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQojY2xvbmFsQWJ1bmRhbmNlCgpjbG9uYWxBYnVuZGFuY2UoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIsICBwYWxldHRlID0gIlppc3NvdSAxIiwKICAgICAgICAgICAgICAgIHNjYWxlID0gRkFMU0UpCiAgCmNsb25hbEFidW5kYW5jZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwgcGFsZXR0ZSA9ICJaaXNzb3UgMSIsCiAgICAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpCgoKCmNsb25hbEFidW5kYW5jZShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiLCAgCiAgICAgICAgICAgICAgICBzY2FsZSA9IEZBTFNFKQogCgpjbG9uYWxBYnVuZGFuY2UoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwgCiAgICAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpCmBgYAojIyAzLjMgY2xvbmFsTGVuZ3RoOiBEaXN0cmlidXRpb24gb2YgU2VxdWVuY2UgTGVuZ3RocwpgYGB7ciBWMywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0KI2Nsb25hbExlbmd0aApjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjbG9uZUNhbGw9Im50IiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJib3RoIikgCgpjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJib3RoIikgCgpjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gImJvdGgiKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIpIAoKCgojVFJBCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJudCIsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJBIiwgIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJBIiwgCiAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpIAoKCiNUUkIKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJudCIsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpIAoKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpIAoKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICBjbG9uZUNhbGw9Im50IiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAgCiAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpIAoKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgIHNjYWxlID0gVFJVRSkgCmBgYAojIyAzLjUgY2xvbmFsQ29tcGFyZTogQ2xvbmFsIER5bmFtaWNzIEJldHdlZW4gQ2F0ZWdvcmljYWwgVmFyaWFibGVzCmBgYHtyIFY0LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQojIGNsb25hbENvbXBhcmUKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDMiLCAiTDQiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDUiLCAiTDYiLCJMNyIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgICAgIHRvcC5jbG9uZXMgPSAxMCwgCiAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMNSIsIkw2IiksIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICAgICAgIGdyYXBoID0gImFsbHV2aWFsIikKCmNsb25hbENvbXBhcmUoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDYiLCJMNyIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpgYGAKCmBgYHtyICwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTZ9CiMgY2xvbmFsQ29tcGFyZQoKCmNsb25hbENvbXBhcmUoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIHRvcC5jbG9uZXMgPSAxMCwgCiAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMMSIsICJMMiIsICJMMyIsICJMNCIsICJMNSIsICJMNiIsICJMNyIsICJDRDRUX2xhYiIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiLCAiTDMiLCAiTDQiLCAiTDUiLCAiTDYiLCAiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQpgYGAKIyMgMy42IGNsb25hbFNjYXR0ZXI6IFNjYXR0ZXJwbG90IG9mIFR3byBWYXJpYWJsZXMKYGBge3IgLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojY2xvbmFsU2NhdHRlcgoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDEiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDIiLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0iZ2VuZSIsIAogICAgICAgICAgICAgIHguYXhpcyA9ICJMMyIsIAogICAgICAgICAgICAgIHkuYXhpcyA9ICJMNCIsCiAgICAgICAgICAgICAgZG90LnNpemUgPSAidG90YWwiLAogICAgICAgICAgICAgIGdyYXBoID0gInByb3BvcnRpb24iKQoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDUiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDYiLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKCmNsb25hbFNjYXR0ZXIoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkw1IiwgCiAgICAgICAgICAgICAgeS5heGlzID0gIkw3IiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDYiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDciLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKYGBgCiMgKio0LiBWaXN1YWxpemluZyBDbG9uYWwgRHluYW1pY3MqKgoKIyMgNC4xIGNsb25hbEhvbWVvc3Rhc2lzOiBFeGFtaW5pbmcgQ2xvbmFsIFNwYWNlCmBgYHtyICwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0KIyBWaXN1YWxpemluZyBDbG9uYWwgRHluYW1pY3MKCiMgY2xvbmFsSG9tZW9zdGFzaXMKCmNsb25hbEhvbWVvc3Rhc2lzKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIikKCgpjbG9uYWxIb21lb3N0YXNpcyhjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIsCiAgICAgICAgICAgICAgICAgIGNsb25lU2l6ZSA9IGMoUmFyZSA9IDAuMDAxLCBTbWFsbCA9IDAuMDEsIE1lZGl1bSA9IDAuMSwgTGFyZ2UgPSAwLjMsIEh5cGVyZXhwYW5kZWQgPTEpKQoKCmNsb25hbEhvbWVvc3Rhc2lzKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwKICAgICAgICAgICAgICAgICAgY2xvbmVTaXplID0gYyhSYXJlID0gMC4xLCBTbWFsbCA9IDEsIE1lZGl1bSA9IDEwLCBMYXJnZSA9IDMwLCBIeXBlcmV4cGFuZGVkID0xMDApKQoKYGBgCiMjIDQuMiBjbG9uYWxQcm9wb3J0aW9uOiBFeGFtaW5pbmcgU3BhY2UgT2NjdXBpZWQgYnkgUmFua3Mgb2YgQ2xvbmVzCmBgYHtyIFN0YXRzLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0yMX0KIyBjbG9uYWxQcm9wb3J0aW9uCgpjbG9uYWxQcm9wb3J0aW9uKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiKSAKCmNsb25hbFByb3BvcnRpb24oY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICAgICAgIGNsb25hbFNwbGl0ID0gYygxLCA1LCAxMCwgMTAwLCAxMDAwLCAxMDAwMCkpIAoKCmNsb25hbFByb3BvcnRpb24oY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICAgICAgIGNsb25hbFNwbGl0ID0gYygxMCwgMTAwLCAxMDAwLCAxMDAwMCwgMzAwMDAsIDEwMDAwMCkpIAoKCmBgYAojICoqNS4gU3VtbWFyaXppbmcgUmVwZXJ0b2lyZXMqKgpgYGB7ciBERSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CiMgU3VtbWFyaXppbmcgUmVwZXJ0b2lyZXMKIyBwZXJjZW50QUEKCnBlcmNlbnRBQShjb21iaW5lZC5UQ1IsIAogICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICBhYS5sZW5ndGggPSAyMCkKCgoKIyBwb3NpdGlvbmFsRW50cm9weQoKcG9zaXRpb25hbEVudHJvcHkoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwKQoKcG9zaXRpb25hbEVudHJvcHkoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCkKCgoKIyBwb3NpdGlvbmFsUHJvcGVydHkKCnBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1JbYygxLDIpXSwgCiAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJhdGNobGV5RmFjdG9ycyIpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQoKCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTR9CiMgcGVyY2VudEdlbmVVc2FnZQp2aXpHZW5lcyhjb21iaW5lZC5UQ1IsIAogICAgICAgICB4LmF4aXMgPSAiVFJCViIsCiAgICAgICAgIHkuYXhpcyA9IE5VTEwsCiAgICAgICAgIHBsb3QgPSAiYmFycGxvdCIsICAKICAgICAgICAgc3VtbWFyeS5mdW4gPSAicHJvcG9ydGlvbiIpCgoKCnZpekdlbmVzKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgeC5heGlzID0gIlRSQVYiLAogICAgICAgIHkuYXhpcyA9IE5VTEwsCiAgICAgICAgcGxvdCA9ICJiYXJwbG90IiwgIAogICAgICAgIHN1bW1hcnkuZnVuID0gInByb3BvcnRpb24iKQoKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9CgoKdml6R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgIHguYXhpcyA9ICJUUkJWIiwKICAgICAgICAgeS5heGlzID0gTlVMTCwKICAgICAgICAgcGxvdCA9ICJiYXJwbG90IiwgIAogICAgICAgICBzdW1tYXJ5LmZ1biA9ICJwcm9wb3J0aW9uIikKCgoKdml6R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgeC5heGlzID0gIlRSQVYiLAogICAgICAgIHkuYXhpcyA9IE5VTEwsCiAgICAgICAgcGxvdCA9ICJiYXJwbG90IiwgIAogICAgICAgIHN1bW1hcnkuZnVuID0gInByb3BvcnRpb24iKQoKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE0fQoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyLDMsNCw1LDYsNyldLCAKICAgICAgICAgeC5heGlzID0gIlRSQlYiLAogICAgICAgICB5LmF4aXMgPSAiVFJCSiIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsICAKICAgICAgICAgIHN1bW1hcnkuZnVuID0gInBlcmNlbnQiKQoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyLDMsNCw1LDYsNyldLCAKICAgICAgICAgeC5heGlzID0gIlRSQVYiLAogICAgICAgICB5LmF4aXMgPSAiVFJBSiIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsICAKICAgICAgICAgIHN1bW1hcnkuZnVuID0gInBlcmNlbnQiKQoKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9Cgp2aXpHZW5lcyhjb21iaW5lZC5UQ1JbYygxLDIpXSwgCiAgICAgICAgIHguYXhpcyA9ICJUUkJWIiwKICAgICAgICAgeS5heGlzID0gIlRSQVYiLAogICAgICAgICBwbG90ID0gImhlYXRtYXAiLCAKICAgICAgICAgIHN1bW1hcnkuZnVuID0gInBlcmNlbnQiKQoKCnZpekdlbmVzKGNvbWJpbmVkLlRDUltjKDMsNCldLCAKICAgICAgICAgeC5heGlzID0gIlRSQlYiLAogICAgICAgICB5LmF4aXMgPSAiVFJBViIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsIAogICAgICAgICAgc3VtbWFyeS5mdW4gPSAicGVyY2VudCIpCgoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoNSw2LDcpXSwgCiAgICAgICAgIHguYXhpcyA9ICJUUkJWIiwKICAgICAgICAgeS5heGlzID0gIlRSQVYiLAogICAgICAgICBwbG90ID0gImhlYXRtYXAiLCAKICAgICAgICAgIHN1bW1hcnkuZnVuID0gInBlcmNlbnQiKQpgYGAKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTZ9CiMgcGVyY2VudEdlbmVzOiBRdWFudGlmeWluZyBTaW5nbGUgR2VuZSBVc2FnZQpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgZ2VuZSA9ICJWZ2VuZSIsCiAgICAgICAgICAgICAgc3VtbWFyeS5mdW4gPSAicGVyY2VudCIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgZ2VuZSA9ICJWZ2VuZSIsCiAgICAgICAgICAgICAgc3VtbWFyeS5mdW4gPSAicGVyY2VudCIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgZ2VuZSA9ICJKZ2VuZSIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgZ2VuZSA9ICJKZ2VuZSIsCiAgICAgICAgICAgICAgc3VtbWFyeS5mdW4gPSAicGVyY2VudCIpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD02fQojIHBlcmNlbnRHZW5lczogUXVhbnRpZnlpbmcgU2luZ2xlIEdlbmUgVXNhZ2UKcGVyY2VudEdlbmVzKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgIGdlbmUgPSAiVmdlbmUiLAogICAgICAgICAgICAgIHN1bW1hcnkuZnVuID0gInBlcmNlbnQiKQoKcGVyY2VudEdlbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJBIiwgCiAgICAgICAgICAgICBnZW5lID0gIlZnZW5lIiwKICAgICAgICAgICAgICBzdW1tYXJ5LmZ1biA9ICJwZXJjZW50IikKCnBlcmNlbnRHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgZ2VuZSA9ICJKZ2VuZSIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIGdlbmUgPSAiSmdlbmUiLAogICAgICAgICAgICAgIHN1bW1hcnkuZnVuID0gInBlcmNlbnQiKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTIwLCBmaWcud2lkdGg9MjR9CiMgcGVyY2VudFZKCiMgUXVhbnRpZnkgdGhlIHByb3BvcnRpb24gb2YgViBhbmQgSiBnZW5lIHVzYWdlIHdpdGggcGVyY2VudFZKKCkuIExpa2UgcGVyY2VudEdlbmVzKCksIHRoaXMgZnVuY3Rpb24gd2lsbCBxdWFudGlmeSB0aGUgcGVyY2VudGFnZSBvZiBWIGFuZCBKIHBhaXJlZCB0b2dldGhlciBhY3Jvc3MgaW5kaXZpZHVhbCByZXBlcnRvaXJlcy4gVGhlIG91dHB1dCBjYW4gYmUgdmlzdWFsaXplZCB1c2luZyBhIGhlYXRtYXAgb3IgYXMgaW5wdXQgZm9yIGZ1cnRoZXIgZGltZW5zaW9uYWwgcmVkdWN0aW9uLgoKcGVyY2VudFZKKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgY2hhaW4gPSAiVFJCIiwKICAgICAgICAgICBzdW1tYXJ5LmZ1biA9ICJwZXJjZW50IikKCnBlcmNlbnRWSihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgIGNoYWluID0gIlRSQSIsCiAgICAgICAgICAgc3VtbWFyeS5mdW4gPSAicGVyY2VudCIpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTZ9CiMgcGVyY2VudEttZXIKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKYGBgCgoKIyAqKjYuIENvbXBhcmluZyBDbG9uYWwgRGl2ZXJzaXR5IGFuZCBPdmVybGFwKioKYGBge3IgY2xvbmFsRGl2ZXJzaXR5LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQoKIyBjbG9uYWxEaXZlcnNpdHkKY2xvbmFsRGl2ZXJzaXR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiKQoKY2xvbmFsRGl2ZXJzaXR5KGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIpCmBgYApgYGB7ciAsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiNjbG9uYWxTaXplRGlzdHJpYnV0aW9uCmNsb25hbFNpemVEaXN0cmlidXRpb24oY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLCAKICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9ICJ3YXJkLkQyIikKCmNsb25hbFNpemVEaXN0cmlidXRpb24oY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLCAKICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9ICJ3YXJkLkQyIikKCiNjbG9uYWxTaXplRGlzdHJpYnV0aW9uCmNsb25hbFNpemVEaXN0cmlidXRpb24oY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImFhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPSAid2FyZC5EMiIpCgpjbG9uYWxTaXplRGlzdHJpYnV0aW9uKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJudCIsIAogICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD0gIndhcmQuRDIiKQpgYGAKCmBgYHtyICwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KCiNjbG9uYWxPdmVybGFwCgpjbG9uYWxPdmVybGFwKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJzdHJpY3QiLCAKICAgICAgICAgICAgICBtZXRob2QgPSAibW9yaXNpdGEiKQoKCmNsb25hbE92ZXJsYXAoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0gInN0cmljdCIsIAogICAgICAgICAgICAgIG1ldGhvZCA9ICJyYXciKQoKI2Nsb25hbE92ZXJsYXAKCmNsb25hbE92ZXJsYXAoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAic3RyaWN0IiwgCiAgICAgICAgICAgICAgbWV0aG9kID0gIm1vcmlzaXRhIikKCgpjbG9uYWxPdmVybGFwKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0gInN0cmljdCIsIAogICAgICAgICAgICAgIG1ldGhvZCA9ICJyYXciKQpgYGAKYGBge3IgY2xvbmFsUmFyZWZhY3Rpb24sIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgpjbG9uYWxSYXJlZmFjdGlvbihjb21iaW5lZC5UQ1IsCiAgICAgICAgICAgICAgICAgIHBsb3QudHlwZSA9IDEsCiAgICAgICAgICAgICAgICAgIGhpbGwubnVtYmVycyA9IDAsCiAgICAgICAgICAgICAgICAgIG4uYm9vdHMgPSAyKQoKY2xvbmFsUmFyZWZhY3Rpb24oY29tYmluZWQuVENSX3dpdGhfUEJNQywKICAgICAgICAgICAgICAgICAgcGxvdC50eXBlID0gMSwKICAgICAgICAgICAgICAgICAgaGlsbC5udW1iZXJzID0gMCwKICAgICAgICAgICAgICAgICAgbi5ib290cyA9IDIpCmBgYApgYGB7ciAsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgpjbG9uYWxSYXJlZmFjdGlvbihjb21iaW5lZC5UQ1IsCiAgICAgICAgICAgICAgICAgIHBsb3QudHlwZSA9IDIsCiAgICAgICAgICAgICAgICAgIGhpbGwubnVtYmVycyA9IDAsCiAgICAgICAgICAgICAgICAgIG4uYm9vdHMgPSAyKQoKY2xvbmFsUmFyZWZhY3Rpb24oY29tYmluZWQuVENSX3dpdGhfUEJNQywKICAgICAgICAgICAgICAgICAgcGxvdC50eXBlID0gMiwKICAgICAgICAgICAgICAgICAgaGlsbC5udW1iZXJzID0gMCwKICAgICAgICAgICAgICAgICAgbi5ib290cyA9IDIpCmBgYAoKYGBge3IgLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQoKY2xvbmFsUmFyZWZhY3Rpb24oY29tYmluZWQuVENSLAogICAgICAgICAgICAgICAgICBwbG90LnR5cGUgPSAzLAogICAgICAgICAgICAgICAgICBoaWxsLm51bWJlcnMgPSAwLAogICAgICAgICAgICAgICAgICBuLmJvb3RzID0gMikKCmNsb25hbFJhcmVmYWN0aW9uKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsCiAgICAgICAgICAgICAgICAgIHBsb3QudHlwZSA9IDMsCiAgICAgICAgICAgICAgICAgIGhpbGwubnVtYmVycyA9IDAsCiAgICAgICAgICAgICAgICAgIG4uYm9vdHMgPSAyKQpgYGAKYGBge3IsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiMgUmFyZWZhY3Rpb24gdXNpbmcgU2hhbm5vbiBEaXZlcnNpdHkgKHEgPSAxKQpjbG9uYWxSYXJlZmFjdGlvbihjb21iaW5lZC5UQ1IsCiAgICAgICAgICAgICAgICAgIHBsb3QudHlwZSA9IDEsCiAgICAgICAgICAgICAgICAgIGhpbGwubnVtYmVycyA9IDEsCiAgICAgICAgICAgICAgICAgIG4uYm9vdHMgPSAyKQoKY2xvbmFsUmFyZWZhY3Rpb24oY29tYmluZWQuVENSX3dpdGhfUEJNQywKICAgICAgICAgICAgICAgICAgcGxvdC50eXBlID0gMSwKICAgICAgICAgICAgICAgICAgaGlsbC5udW1iZXJzID0gMSwKICAgICAgICAgICAgICAgICAgbi5ib290cyA9IDIpCmBgYAoKCg==