Introduction
This document aims to record the tasks performed to re-preprocess the
IPRGC samples of the Speer lab. I have every confidence that Theresa did
everything perfectly, the only reason I wish to redo these tasks lies in
the fact that we reorganized slightly the data to represent the new
files produced by April following a reassessment of the samples in
~202404. It turns out that a small number of samples were misnamed and
therefore it is difficult to ensure with absolute certainty that the
existing state of Theresa’s working tree is representative of the new
state of the samples.
Thus it is worth explaining slightly what I did before starting this
document:
I spent some time with Najib and April in order to create the
sample sheet ‘20240521_speer_consolidated_sample_sheet.xlsx’. This is
mostly identical to Theresa’s with a few caveats:
- There is now a series of columns with the suffix ‘AH’. With Najib’s
help, I reconciled the existing IPRGC IDs created by Theresa with the
extant samples and copied April’s sample sheet information into these
columns. They have the names ‘Project # AH’, ‘Sample # AH’, ‘Rashmi’s
Sample Name AH’, ‘Prep & Clean AH’, ‘Sequencing Run AH’, ‘Read 1
AH’, ‘Read 2 AH’, ‘Reload & Map Again AH’ and comprise columns
AO-AV. These columns are only populated for samples iprgc62-iprgc130,
because these are (I think) the only samples sequenced by April, and
definitely the only samples potentially affected by the file
re-copying.
- Given these new columns, I created a series of columns with the
suffix ‘atb’: ‘genotype_atb’, ‘location_atb’, ‘time_atb’,
‘time_geo_location_source_atb’, and ‘rashmi_code_atb’. These columns are
generally identical to Theresa’s columns of the same information with
potential exceptions in the cases of the files which were
moved/reorganized. The ‘time_geo_location_source’ column is used to
signify where I took the information for the previous columns, e.g. if
it says TAA_meta, then I took the genotype etc classifications from
Theresa’s metadata without any interpretation/modification. When it says
‘AH filename’, then I took that, as one might expect, from April’s newly
provided filenames.
- I later added Column AN when assaying Najib’s raw_data tree for
these samples. Najib had previously not populated his raw directory tree
with any sample >= iprgc_64; so I recorded in this column any actions
I took. These actions fell into three categories: 1. Nothing (the first
2), 2. Almost nothing (the raw files were actually in Najib’s tree, but
he had not yet put them into the ‘unprocessed’ directory. 3. Nothing
existed yet, so I copied the files from my fresh tree (downloaded from
the sequencer earlier in 202405) to the appropriate directories in
Najib’s tree. I then copy/pasted my command into this column so that we
may later double-check them. I probably could have put this information
into this file…
- At this moment I added a column ‘sequence_type_atb’ which is either
‘previous’ or ‘takara’ so that I can record the likely required trimming
process. I am hopeful that this column will not be needed and that I
will be able to use fastp to identically treat all samples old and new.
I hypothesize this is possible after spending a little time reading the
takara cogent package code. It seems to me that their trimming
operations are either close-to or identical to what fastp will perform.
If that is not true, then I will do my default trimomatic/fastp trimming
for the previous samples and the cogent method for the others. It should
also be noted that I am making the assumption that any sample < 2021
is not takara and vice versa (e.g. anything received with a date after
20201221 is takara).
It is hoped that 1c. above has left me in a consistent state and
that I have every sample required in the appropriate location in Najib’s
tree and that they match the modified sample sheet.
Thus I created a fresh working tree named ‘mmusculus_iprgc_2024’
and populated it with empty directories ‘sample_sheets’, ‘reference’,
and ‘preprocessing’.
Populating the raw
data
From this point on, any command run will be performed in this text
document, so you will get to read along as I make my
decisions/mistakes.
I decided I will work using the read-only copies in Najib’s tree.
cd preprocessing
ln -s /fs/cbcb-lab/nelsayed/raw_data/speer/iprgc* .
I now have 129 symlinks in my preprocessing directory with one hole
where a sample got changed and a couple new iprgc IDs due to the changes
introduced by April’s reprocessing.
After staring at the screen for a moment, I decided to split these
samples into subdirectories named after the sequencing year, thus:
mkdir 2019 2020 2022 2023
mv iprgc_0[1-8] 2019
mv iprgc_09 iprgc_1* iprgc_2* iprgc_3* iprgc_4* iprgc_5* iprgc_60 iprgc_61 2020
mv iprgc_6* iprgc_7* iprgc_8[0-4] 2022
mv iprgc* 2023
## haha I was a doofus and moved the 100s into 2020 directory because iprgc_1* matches 100+
mv 2020/iprgc_1[0-9][0-9] 2023
## I later decided to put all the umd sequenced data into the same tree
mkdir umd_sequenced
mv 2022/* umd_sequenced/
mv 2023/* umd_sequenced/
I am doing this because I am guessing there may be relevant
differences in the various rounds of sequencing. In addition I am
reasonably certain all the takara samples are in 2022 and 2023.
Ok, so now I should be able to comfortably process different
sequencing platform data using for-loops without worrying too much about
shenanigans.
Trimming
I am therefore going to take a moment and peek in Theresa’s tree and
see how the early samples were trimmed.
Looking in Theresa’s tree, I see that she likely kept my original
trimmed data using cutadapt Martin (2011)
and also performed a trimomatic Bolger, Lohse,
and Usadel (2014) run. I took a momemt and see that I used
cutadapt because the version of trimomatic at that time did not have the
primers in it for this library type; but that has since been
ameliorated. I therefore assume that I can comfortably trim with either
trimomatic or fastp Chen et al. (2018)
without problems. I will definitely need to use fastqc “S-Andrews/FastQC: A
Quality Control Analysis Tool for High Throughput Sequencing
Data” (n.d.) after trimming and make certain that none of
the weirdo i3/i5(or whatever they are called) adapters remain.
Oh, an important note: I only configured fastp recently in my
pipeline and it defaults to trying to do a UMI extraction, which is
inappropriate for these first samples. I need to remember to tell it not
to do that for these. Also, I do not fully understand UMIs yet.
module add cyoa/202406
cd 2019
start=$(pwd)
for i in $(/bin/ls -d iprgc*); do
echo "Starting $i"
cd $i
inputs=$(/bin/ls unprocessed/*.fastq.gz | tr '\n' ':' | sed 's/:$//g')
echo "The inputs are: ${inputs}"
cyoa --method trim --input "${inputs}" --jprefix 01
cyoa --method fastp --input "${inputs}" --jprefix 01 --do_umi 0
cyoa --method umitools --input "${inputs} --jprefix 01
cd $start
done
cd ../2020
start=$(pwd)
for i in $(/bin/ls -d iprgc*); do
echo "Starting $i"
cd $i
inputs=$(/bin/ls unprocessed/*.fastq.gz | tr '\n' ':' | sed 's/:$//g')
echo "The inputs are: ${inputs}"
cyoa --method trim --input "${inputs}" --jprefix 01
cyoa --method fastp --input "${inputs}" --jprefix 01 --do_umi 0
cd $start
done
Next steps, which will have to wait a few minutes: download a new
musculus assembly and check that my trimming results look like
Theresa’s.
For the 2022/2023 samples, I should at the very least be ready to use
cogent, so let us take a moment and look at Theresa’s tree and recall
how to use it.
Before I went poking through Theresa’s tree, I copy/pasted the
following from April’s report:
- The workflow used in this kit takes advantage of a novel technology
allowing removal of ribosomal cDNA (originating from rRNA) after cDNA
synthesis using probes specific to mammalian rRNA. These R-Probes target
nuclear and mitochondrial rRNA sequences; however, the mitochondrial
R-Probes are derived from the human mitochondrial genome and are
therefore strictly human-specific. The rRNA depletion method used in
this kit makes it especially well-suited for working with very small
quantities of total RNA. Therefore, you will likely see reads mapping to
mouse mitochondrial rRNA.
- This kit adds an 8 nucleotide (nt) unique molecular identifier (UMI)
through the reverse-transcription step to mitigate potential PCR bias as
well as to provide customers with additional information for transcript
quantification, specifically for true variants and rare mutations. This
kit is designed for analysis with Takara Bio’s Cogent NGS Analysis
Pipeline Software, which removes PCR duplicates and errors based on the
UMIs.
- The directionality of the template-switching reaction preserves the
strand orientation of the original RNA, making it possible to obtain
strand-specific sequencing data from the synthesized cDNA. Illustrated
below are the cDNA library construction process and technologies
employed by the kit (Figure 1), and the structural details of final
libraries (Figure 2).
Umi Trimming
The images which follow provide a diagram of the library layout which
I think answers my questions and looks a little like this:
5’-> Read 2 P7 i7 R2start UMI 5’ sequence 3’ sequence <- R1 i5
p5 pppp iii RRRRUUNNNXXX actual sequence data from library……………. RRRRR
iii ppp
R1 is of course the reverse complement of this. Thus I think I can
expect a 8 nt UMI specific to each sample followed by the NNNXXX UMI
which immediately precedes the library sequence. This should be at the
beginning of R2 and end of R1 if I interpret this correctly.
With this in mind, I used the umi_tools in order to perform
deduplication via the following path:
- label each read with its UMI with umi_tools Smith, Heger, and Sudbery (2017)
- mapped the full set of reads with hisat2 Kim
et al. (2019) and the mm39_112 genome “Mus_musculus - Ensembl Genome
Browser 112” (n.d.)
- Sorted/indexed/compressed the alignment with samtools Li et al. (2009)
- Counted the reads/gene via htseq Putri et al.
(2022)
- Invoked umi_tools using the output from #3 to remove reads which
share the same start/end positions and UMI (e.g. the duplicates) but
keeping the first.
- Counted the reads/gene via htseq using the output from #5.
Brief chat with
Colenso on 20240605
I spoke briefly with Colenso today and quickly realized that I was
foolishly chasing the goal of treating samples <2022 identically to
those which are >=2022. They (currently) do not wish to work with any
of those earlier samples, which makes my life considerably easier. As a
result I copied my sample sheet to ‘20240606_speer_samples.xlsx’ and
deleted from it all IDs from iprgc_01 to iprgc_61. This means that every
sample was sequenced identically and all have the same UMI
configuration.
cd preprocessing
cd umd_sequenced
start=$(pwd)
cd $start
for i in $(/bin/ls -d iprgc*); do
cd $i
echo $i
r1_input=$(/bin/ls unprocessed/*R1*.fastq.gz)
r2_input=$(/bin/ls unprocessed/*R2*.fastq.gz)
input="${r1_input}:${r2_input}"
cyoa --method umi --input ${input}
cd $start
done
The previous block serves to remove the UMI prefix of read2 and move
that information to the suffix of the read ID. I would argue that it
should be put in the read comment, but whatever. From that step, we
perform the alignment as per usual, then use umi_tools dedup to exclude
reads with the same ID which map to the same place, then count up the
remaining reads/gene.
I think the previous analysis did not perform the deduplication step,
at least I have not yet found it in the logs. As a result, I am going to
do one round with and one without the deduplication. My hope is that
they will be:
- quite similar to each other
- the without-deduplication result will be nearly identical to the
previous set
- the with-deduplication step will slightly improve the results.
Let’s find out!
Mapping against the
ensembl mus musculus 112 release
Note, I could/should have piped the output of umi_tools directly into
hisat, but I didn’t.
cd preprocessing/umd_sequenced
start=$(pwd)
cd $start
for i in $(/bin/ls -d iprgc*); do
cd $i
echo $i
input="outputs/01umi_tools/r1_extracted.fastq.gz:outputs/01umi_tools/r2_extracted.fastq.gz"
cyoa --method hisat --species mm39_112 --input ${input} --gff_type gene --gff_tag ID \
--stranded reverse
cyoa --method hisat --species mm39_112 --libtype rRNA --gff_type rRNA --gff_tag ID \
--stranded reverse --input ${input}
cd $start
done
Deduplication
A note to self, here are the dedup options:
--output-stats=STATS
Specify location to output stats
Barcode extraction options: –extract-umi-method=GET_UMI_METHOD how is
the read UMI +/ cell barcode encoded? [default=read_id]
–umi-separator=UMI_SEP separator between read id and UMI
–umi-tag=UMI_TAG tag containing umi –umi-tag-split=UMI_TAG_SPLIT split
UMI in tag and take the first element –umi-tag-delimiter=UMI_TAG_DELIM
concatenate UMI in tag separated by delimiter –cell-tag=CELL_TAG tag
containing cell barcode –cell-tag-split=CELL_TAG_SPLIT split cell
barcode in tag and take the firstelement for e.g 10X GEM tags
–cell-tag-delimiter=CELL_TAG_DELIM concatenate cell barcode in tag
separated by delimiter
UMI grouping options: –method=METHOD method to use for umi grouping
[default=directional] –edit-distance-threshold=THRESHOLD Edit distance
theshold at which to join two UMIs when grouping UMIs. [default=1]
–spliced-is-unique Treat a spliced read as different to an unspliced one
[default=False] –soft-clip-threshold=SOFT_CLIP_THRESHOLD number of bases
clipped from 5’ end before read is counted as spliced [default=4]
–read-length use read length in addition to position and UMI to identify
possible duplicates [default=False]
single-cell RNA-Seq options: –per-gene Group/Dedup/Count per gene.
Must combine with either –gene-tag or –per-contig –gene-tag=GENE_TAG
Gene is defined by this bam tag [default=none]
–assigned-status-tag=ASSIGNED_TAG Bam tag describing whether read is
assigned to a gene By defualt, this is set as the same tag as –gene-tag
–skip-tags-regex=SKIP_REGEX Used with –gene-tag. Ignore reads where the
gene-tag matches this regex –per-contig group/dedup/count UMIs per
contig (field 3 in BAM; RNAME), e.g for transcriptome where contig =
gene –gene-transcript-map=GENE_TRANSCRIPT_MAP File mapping transcripts
to genes (tab separated) –per-cell group/dedup/count per cell
group/dedup options: –buffer-whole-contig Read whole contig before
outputting bundles: guarantees that no reads are missed, but increases
memory usage –multimapping-detection-method=DETECTION_METHOD Some
aligners identify multimapping using bam tags. Setting this option to
NH, X0 or XT will use these tags when selecting the best read amongst
reads with the same position and umi [default=none]
SAM/BAM options: –mapping-quality=MAPPING_QUALITY Minimum mapping
quality for a read to be retained [default=0] –ignore-umi Ignore UMI and
dedup only on position –ignore-tlen Option to dedup paired end reads
based solely on read1, whether or not the template length is the same
–chrom=CHROM Restrict to one chromosome –subset=SUBSET Use only a
fraction of reads, specified by subset -i, –in-sam Input file is in sam
format [default=False] –paired paired input BAM. [default=False] -o,
–out-sam Output alignments in sam format [default=False] –no-sort-output
Don’t Sort the output
Dedup and Count SAM/BAM options: –unmapped-reads=UNMAPPED_READS How
to handle unmapped reads. Options are ‘discard’ or ‘use’
[default=discard] –chimeric-pairs=CHIMERIC_PAIRS How to handle chimeric
read pairs. Options are ‘discard’ or ‘use’ [default=use]
–unpaired-reads=UNPAIRED_READS How to handle unpaired reads. Options are
‘discard’or ’use’ [default=use]
input/output options: -I FILE, –stdin=FILE file to read stdin from
[default = stdin]. -L FILE, –log=FILE file with logging information
[default = stdout]. -E FILE, –error=FILE file with error information
[default = stderr]. -S FILE, –stdout=FILE file where output is to go
[default = stdout]. –temp-dir=FILE Directory for temporary files. If not
set, the bash environmental variable TMPDIR is used[default = None].
–log2stderr send logging information to stderr [default = False].
–compresslevel=COMPRESSLEVEL Level of Gzip compression to use. Default
(6) matchesGNU gzip rather than python gzip default (which is 9)
profiling options: –timeit=TIMEIT_FILE store timeing information in
file [none]. –timeit-name=TIMEIT_NAME name in timing file for this class
of jobs [all]. –timeit-header add header for timing information
[none].
common options: -v LOGLEVEL, –verbose=LOGLEVEL loglevel [1]. The
higher, the more output. -h, –help output short help (command line
options only). –help-extended Output full documentation
–random-seed=RANDOM_SEED random seed to initialize number generator with
[none].
umi_tools dedup --output-stats=umi_dedup_stats.txt \
--buffer-whole-contig -I mm39_112_genome.bam \
-L dedup.stdout -E dedup.stderr -S dedup.bam
I added a version of this to cyoa which also re-performs htseq and
should be usable via:
cd preprocessing/umd_sequenced
start=$(pwd)
cd $start
for i in $(/bin/ls -d iprgc*); do
cd $i
echo $i
input="outputs/40hisat_mm39_112/mm39_112_genome.bam"
cyoa --method umidedup --species mm39_112 --input ${input} --gff_type gene --gff_tag ID \
--stranded reverse
cd $start
done
Note that I explicitly mapped against my mm39_112 rRNA database, but
neglected to document how I made it, here are those commands:
Making a mouse rRNA
database
First I copied my full genome fasta and gff to /tmp/ just to make
sure that if I messed up I would not hurt anything
cd /tmp
cp ~/libraries/genome/fasta/mm39* .
cp ~/libraries/genome/gff/mm39* .
## Note, that when typing the following I actually type 'Control-v<tab>'
grep "rRNA\t" mm39_112.gff > mm39_112_rrna.gff
cyoa --method gff2fasta --input mm39_112.fasta --gff mm39_112_rrna.gff --gff_type rRNA --gff_tag ID
The above created a couple of new files which extracted from the full
genome the amino acid and nucleotide sequences of all features in the
gff which matched my requirements (the amino acid sequences were of
course gibberish). So, I copied these new fasta/gff files to my index
tree and indexed them for hisat2:
## Still in /tmp/
mv mm39_112_rrna.gff ~/libraries/rRNA/gff/mm39_112.gff
mv mm39_112_nt_rRNA_ID.fasta ~/libraries/rRNA/fasta/mm39_112.fasta
cyoa --method indexhisat --input ~/libraries/rRNA/fasta/mm39_112.fasta \
--gff ~/libraries/rRNA/gff/mm39_112.gff --libtype rRNA
That last command handles the invocation of the hisat2 indexer to
create for me a mouse-specific rRNA database.
Bibliography
Bolger, Anthony M., Marc Lohse, and Bjoern Usadel. 2014.
“Trimmomatic: A Flexible Trimmer for
Illumina Sequence Data.” Bioinformatics 30
(15): 2114–20.
https://doi.org/10.1093/bioinformatics/btu170.
Chen, Shifu, Yanqing Zhou, Yaru Chen, and Jia Gu. 2018.
“Fastp: An
Ultra-Fast All-in-One FASTQ Preprocessor.”
Bioinformatics 34 (17): i884–90.
https://doi.org/10.1093/bioinformatics/bty560.
Kim, Daehwan, Joseph M. Paggi, Chanhee Park, Christopher Bennett, and
Steven L. Salzberg. 2019.
“Graph-Based Genome Alignment and
Genotyping with HISAT2 and HISAT-genotype.” Nature
Biotechnology 37 (8): 907–15.
https://doi.org/10.1038/s41587-019-0201-4.
Li, Heng, Bob Handsaker, Alec Wysoker, Tim Fennell, Jue Ruan, Nils
Homer, Gabor Marth, Goncalo Abecasis, and Richard Durbin. 2009.
“The Sequence Alignment/Map Format and
SAMtools.” Bioinformatics (Oxford, England)
25 (16): 2078–79.
https://doi.org/10.1093/bioinformatics/btp352.
Martin, Marcel. 2011.
“Cutadapt Removes Adapter Sequences from
High-Throughput Sequencing Reads.” EMBnet.journal 17
(1): 10–12.
https://doi.org/10.14806/ej.17.1.200.
“Mus_musculus - Ensembl Genome Browser 112.”
n.d. http://May2024.archive.ensembl.org/Mus_musculus/Info/Index.
Accessed August 8, 2024.
Putri, Givanna H, Simon Anders, Paul Theodor Pyl, John E Pimanda, and
Fabio Zanini. 2022.
“Analysing High-Throughput Sequencing Data in
Python with HTSeq 2.0.”
Bioinformatics 38 (10): 2943–45.
https://doi.org/10.1093/bioinformatics/btac166.
“S-Andrews/FastQC: A Quality Control
Analysis Tool for High Throughput Sequencing Data.” n.d.
https://github.com/s-andrews/FastQC. Accessed August 8, 2024.
Smith, Tom, Andreas Heger, and Ian Sudbery. 2017.
“UMI-tools: Modeling Sequencing Errors in
Unique Molecular Identifiers to Improve Quantification
Accuracy.” Genome Research 27 (3): 491–99.
https://doi.org/10.1101/gr.209601.116.
LS0tCnRpdGxlOiAiUHJlcHJvY2Vzc2luZyB0aGUgSVBSR0Mgc2FtcGxlcyBkZS1ub3ZvLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKYmlibGlvZ3JhcGh5OiBhdGIuYmliCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICB3aWR0aDogMzAwCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCiAgQmlvY1N0eWxlOjpodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5LCB0ZCB7CiAgZm9udC1zaXplOiAxNnB4Owp9CmNvZGUucnsKICBmb250LXNpemU6IDE2cHg7Cn0KcHJlIHsKICBmb250LXNpemU6IDE2cHgKfQpib2R5IC5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiAxNjAwcHg7Cn0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoaHBnbHRvb2xzKQpsaWJyYXJ5KHJldGljdWxhdGUpCnR0IDwtIHRyeShkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KAogIHByb2dyZXNzID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUsIHdpZHRoID0gOTAsIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZXJyb3IgPSBUUlVFLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLnJldGluYSA9IDIsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAicG5nIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSAiMjAyMzA1IgpwcmV2aW91c19maWxlIDwtICIiCnZlciA8LSBmb3JtYXQoU3lzLkRhdGUoKSwgIiVZJW0lZCIpCgojI3RtcCA8LSBzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkKcm1kX2ZpbGUgPC0gInByZXByb2Nlc3NpbmcuUm1kIgpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGlzIGRvY3VtZW50IGFpbXMgdG8gcmVjb3JkIHRoZSB0YXNrcyBwZXJmb3JtZWQgdG8gcmUtcHJlcHJvY2VzcyB0aGUKSVBSR0Mgc2FtcGxlcyBvZiB0aGUgU3BlZXIgbGFiLiAgSSBoYXZlIGV2ZXJ5IGNvbmZpZGVuY2UgdGhhdCBUaGVyZXNhCmRpZCBldmVyeXRoaW5nIHBlcmZlY3RseSwgdGhlIG9ubHkgcmVhc29uIEkgd2lzaCB0byByZWRvIHRoZXNlIHRhc2tzCmxpZXMgaW4gdGhlIGZhY3QgdGhhdCB3ZSByZW9yZ2FuaXplZCBzbGlnaHRseSB0aGUgZGF0YSB0byByZXByZXNlbnQKdGhlIG5ldyBmaWxlcyBwcm9kdWNlZCBieSBBcHJpbCBmb2xsb3dpbmcgYSByZWFzc2Vzc21lbnQgb2YgdGhlCnNhbXBsZXMgaW4gfjIwMjQwNC4gIEl0IHR1cm5zIG91dCB0aGF0IGEgc21hbGwgbnVtYmVyIG9mIHNhbXBsZXMgd2VyZQptaXNuYW1lZCBhbmQgdGhlcmVmb3JlIGl0IGlzIGRpZmZpY3VsdCB0byBlbnN1cmUgd2l0aCBhYnNvbHV0ZQpjZXJ0YWludHkgdGhhdCB0aGUgZXhpc3Rpbmcgc3RhdGUgb2YgVGhlcmVzYSdzIHdvcmtpbmcgdHJlZSBpcwpyZXByZXNlbnRhdGl2ZSBvZiB0aGUgbmV3IHN0YXRlIG9mIHRoZSBzYW1wbGVzLgoKVGh1cyBpdCBpcyB3b3J0aCBleHBsYWluaW5nIHNsaWdodGx5IHdoYXQgSSBkaWQgYmVmb3JlIHN0YXJ0aW5nIHRoaXMKZG9jdW1lbnQ6CgoxLiAgSSBzcGVudCBzb21lIHRpbWUgd2l0aCBOYWppYiBhbmQgQXByaWwgaW4gb3JkZXIgdG8gY3JlYXRlIHRoZQogICAgc2FtcGxlIHNoZWV0ICcyMDI0MDUyMV9zcGVlcl9jb25zb2xpZGF0ZWRfc2FtcGxlX3NoZWV0Lnhsc3gnLgogICAgVGhpcyBpcyBtb3N0bHkgaWRlbnRpY2FsIHRvIFRoZXJlc2EncyB3aXRoIGEgZmV3IGNhdmVhdHM6CgogICAgYS4gIFRoZXJlIGlzIG5vdyBhIHNlcmllcyBvZiBjb2x1bW5zIHdpdGggdGhlIHN1ZmZpeCAnQUgnLiAgV2l0aAogICAgICAgIE5hamliJ3MgaGVscCwgSSByZWNvbmNpbGVkIHRoZSBleGlzdGluZyBJUFJHQyBJRHMgY3JlYXRlZCBieQogICAgICAgIFRoZXJlc2Egd2l0aCB0aGUgZXh0YW50IHNhbXBsZXMgYW5kIGNvcGllZCBBcHJpbCdzIHNhbXBsZQogICAgICAgIHNoZWV0IGluZm9ybWF0aW9uIGludG8gdGhlc2UgY29sdW1ucy4gIFRoZXkgaGF2ZSB0aGUgbmFtZXMKICAgICAgICAnUHJvamVjdCAjIEFIJywgJ1NhbXBsZSAjIEFIJywgJ1Jhc2htaSdzIFNhbXBsZSBOYW1lIEFIJywKICAgICAgICAnUHJlcCAmIENsZWFuIEFIJywgJ1NlcXVlbmNpbmcgUnVuIEFIJywgJ1JlYWQgMSBBSCcsICdSZWFkIDIKICAgICAgICBBSCcsICdSZWxvYWQgJiBNYXAgQWdhaW4gQUgnIGFuZCBjb21wcmlzZSBjb2x1bW5zIEFPLUFWLgogICAgICAgIFRoZXNlIGNvbHVtbnMgYXJlIG9ubHkgcG9wdWxhdGVkIGZvciBzYW1wbGVzIGlwcmdjNjItaXByZ2MxMzAsCiAgICAgICAgYmVjYXVzZSB0aGVzZSBhcmUgKEkgdGhpbmspIHRoZSBvbmx5IHNhbXBsZXMgc2VxdWVuY2VkIGJ5CiAgICAgICAgQXByaWwsIGFuZCBkZWZpbml0ZWx5IHRoZSBvbmx5IHNhbXBsZXMgcG90ZW50aWFsbHkgYWZmZWN0ZWQgYnkKICAgICAgICB0aGUgZmlsZSByZS1jb3B5aW5nLgogICAgYi4gIEdpdmVuIHRoZXNlIG5ldyBjb2x1bW5zLCBJIGNyZWF0ZWQgYSBzZXJpZXMgb2YgY29sdW1ucyB3aXRoCiAgICAgICAgdGhlIHN1ZmZpeCAnYXRiJzogJ2dlbm90eXBlX2F0YicsICdsb2NhdGlvbl9hdGInLCAndGltZV9hdGInLAogICAgICAgICd0aW1lX2dlb19sb2NhdGlvbl9zb3VyY2VfYXRiJywgYW5kICdyYXNobWlfY29kZV9hdGInLiAgVGhlc2UKICAgICAgICBjb2x1bW5zIGFyZSBnZW5lcmFsbHkgaWRlbnRpY2FsIHRvIFRoZXJlc2EncyBjb2x1bW5zIG9mIHRoZQogICAgICAgIHNhbWUgaW5mb3JtYXRpb24gd2l0aCBwb3RlbnRpYWwgZXhjZXB0aW9ucyBpbiB0aGUgY2FzZXMgb2YgdGhlCiAgICAgICAgZmlsZXMgd2hpY2ggd2VyZSBtb3ZlZC9yZW9yZ2FuaXplZC4gIFRoZQogICAgICAgICd0aW1lX2dlb19sb2NhdGlvbl9zb3VyY2UnIGNvbHVtbiBpcyB1c2VkIHRvIHNpZ25pZnkgd2hlcmUgSQogICAgICAgIHRvb2sgdGhlIGluZm9ybWF0aW9uIGZvciB0aGUgcHJldmlvdXMgY29sdW1ucywgZS5nLiBpZiBpdCBzYXlzCiAgICAgICAgVEFBX21ldGEsIHRoZW4gSSB0b29rIHRoZSBnZW5vdHlwZSBldGMgY2xhc3NpZmljYXRpb25zIGZyb20KICAgICAgICBUaGVyZXNhJ3MgbWV0YWRhdGEgd2l0aG91dCBhbnkgaW50ZXJwcmV0YXRpb24vbW9kaWZpY2F0aW9uLgogICAgICAgIFdoZW4gaXQgc2F5cyAnQUggZmlsZW5hbWUnLCB0aGVuIEkgdG9vayB0aGF0LCBhcyBvbmUgbWlnaHQKICAgICAgICBleHBlY3QsIGZyb20gQXByaWwncyBuZXdseSBwcm92aWRlZCBmaWxlbmFtZXMuCiAgICBjLiAgSSBsYXRlciBhZGRlZCBDb2x1bW4gQU4gd2hlbiBhc3NheWluZyBOYWppYidzIHJhd19kYXRhIHRyZWUKICAgICAgICBmb3IgdGhlc2Ugc2FtcGxlcy4gIE5hamliIGhhZCBwcmV2aW91c2x5IG5vdCBwb3B1bGF0ZWQgaGlzIHJhdwogICAgICAgIGRpcmVjdG9yeSB0cmVlIHdpdGggYW55IHNhbXBsZSA+PSBpcHJnY182NDsgc28gSSByZWNvcmRlZCBpbgogICAgICAgIHRoaXMgY29sdW1uIGFueSBhY3Rpb25zIEkgdG9vay4gIFRoZXNlIGFjdGlvbnMgZmVsbCBpbnRvIHRocmVlCiAgICAgICAgY2F0ZWdvcmllczogIDEuICBOb3RoaW5nICh0aGUgZmlyc3QgMiksIDIuIEFsbW9zdCBub3RoaW5nICh0aGUKICAgICAgICByYXcgZmlsZXMgd2VyZSBhY3R1YWxseSBpbiBOYWppYidzIHRyZWUsIGJ1dCBoZSBoYWQgbm90IHlldAogICAgICAgIHB1dCB0aGVtIGludG8gdGhlICd1bnByb2Nlc3NlZCcgZGlyZWN0b3J5LiAgMy4gIE5vdGhpbmcKICAgICAgICBleGlzdGVkIHlldCwgc28gSSBjb3BpZWQgdGhlIGZpbGVzIGZyb20gbXkgZnJlc2ggdHJlZQogICAgICAgIChkb3dubG9hZGVkIGZyb20gdGhlIHNlcXVlbmNlciBlYXJsaWVyIGluIDIwMjQwNSkgdG8gdGhlCiAgICAgICAgYXBwcm9wcmlhdGUgZGlyZWN0b3JpZXMgaW4gTmFqaWIncyB0cmVlLiAgSSB0aGVuIGNvcHkvcGFzdGVkCiAgICAgICAgbXkgY29tbWFuZCBpbnRvIHRoaXMgY29sdW1uIHNvIHRoYXQgd2UgbWF5IGxhdGVyIGRvdWJsZS1jaGVjawogICAgICAgIHRoZW0uICBJIHByb2JhYmx5IGNvdWxkIGhhdmUgcHV0IHRoaXMgaW5mb3JtYXRpb24gaW50byB0aGlzCiAgICAgICAgZmlsZS4uLgogICAgZC4gIEF0IHRoaXMgbW9tZW50IEkgYWRkZWQgYSBjb2x1bW4gJ3NlcXVlbmNlX3R5cGVfYXRiJyB3aGljaCBpcwogICAgICAgIGVpdGhlciAncHJldmlvdXMnIG9yICd0YWthcmEnIHNvIHRoYXQgSSBjYW4gcmVjb3JkIHRoZSBsaWtlbHkKICAgICAgICByZXF1aXJlZCB0cmltbWluZyBwcm9jZXNzLiAgSSBhbSBob3BlZnVsIHRoYXQgdGhpcyBjb2x1bW4gd2lsbAogICAgICAgIG5vdCBiZSBuZWVkZWQgYW5kIHRoYXQgSSB3aWxsIGJlIGFibGUgdG8gdXNlIGZhc3RwIHRvCiAgICAgICAgaWRlbnRpY2FsbHkgdHJlYXQgYWxsIHNhbXBsZXMgb2xkIGFuZCBuZXcuICBJIGh5cG90aGVzaXplIHRoaXMKICAgICAgICBpcyBwb3NzaWJsZSBhZnRlciBzcGVuZGluZyBhIGxpdHRsZSB0aW1lIHJlYWRpbmcgdGhlIHRha2FyYQogICAgICAgIGNvZ2VudCBwYWNrYWdlIGNvZGUuICBJdCBzZWVtcyB0byBtZSB0aGF0IHRoZWlyIHRyaW1taW5nCiAgICAgICAgb3BlcmF0aW9ucyBhcmUgZWl0aGVyIGNsb3NlLXRvIG9yIGlkZW50aWNhbCB0byB3aGF0IGZhc3RwIHdpbGwKICAgICAgICBwZXJmb3JtLiAgSWYgdGhhdCBpcyBub3QgdHJ1ZSwgdGhlbiBJIHdpbGwgZG8gbXkgZGVmYXVsdAogICAgICAgIHRyaW1vbWF0aWMvZmFzdHAgdHJpbW1pbmcgZm9yIHRoZSBwcmV2aW91cyBzYW1wbGVzIGFuZCB0aGUKICAgICAgICBjb2dlbnQgbWV0aG9kIGZvciB0aGUgb3RoZXJzLiAgSXQgc2hvdWxkIGFsc28gYmUgbm90ZWQgdGhhdCBJCiAgICAgICAgYW0gbWFraW5nIHRoZSBhc3N1bXB0aW9uIHRoYXQgYW55IHNhbXBsZSA8IDIwMjEgaXMgbm90IHRha2FyYQogICAgICAgIGFuZCB2aWNlIHZlcnNhIChlLmcuIGFueXRoaW5nIHJlY2VpdmVkIHdpdGggYSBkYXRlIGFmdGVyCiAgICAgICAgMjAyMDEyMjEgaXMgdGFrYXJhKS4KCjIuICBJdCBpcyBob3BlZCB0aGF0IDFjLiBhYm92ZSBoYXMgbGVmdCBtZSBpbiBhIGNvbnNpc3RlbnQgc3RhdGUgYW5kCiAgICB0aGF0IEkgaGF2ZSBldmVyeSBzYW1wbGUgcmVxdWlyZWQgaW4gdGhlIGFwcHJvcHJpYXRlIGxvY2F0aW9uIGluCiAgICBOYWppYidzIHRyZWUgYW5kIHRoYXQgdGhleSBtYXRjaCB0aGUgbW9kaWZpZWQgc2FtcGxlIHNoZWV0LgozLiAgVGh1cyBJIGNyZWF0ZWQgYSBmcmVzaCB3b3JraW5nIHRyZWUgbmFtZWQgJ21tdXNjdWx1c19pcHJnY18yMDI0JwogICAgYW5kIHBvcHVsYXRlZCBpdCB3aXRoIGVtcHR5IGRpcmVjdG9yaWVzICdzYW1wbGVfc2hlZXRzJywKICAgICdyZWZlcmVuY2UnLCBhbmQgJ3ByZXByb2Nlc3NpbmcnLgoKIyBQb3B1bGF0aW5nIHRoZSByYXcgZGF0YQoKRnJvbSB0aGlzIHBvaW50IG9uLCBhbnkgY29tbWFuZCBydW4gd2lsbCBiZSBwZXJmb3JtZWQgaW4gdGhpcyB0ZXh0CmRvY3VtZW50LCBzbyB5b3Ugd2lsbCBnZXQgdG8gcmVhZCBhbG9uZyBhcyBJIG1ha2UgbXkKZGVjaXNpb25zL21pc3Rha2VzLgoKSSBkZWNpZGVkIEkgd2lsbCB3b3JrIHVzaW5nIHRoZSByZWFkLW9ubHkgY29waWVzIGluIE5hamliJ3MgdHJlZS4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCmxuIC1zIC9mcy9jYmNiLWxhYi9uZWxzYXllZC9yYXdfZGF0YS9zcGVlci9pcHJnYyogLgpgYGAKCkkgbm93IGhhdmUgMTI5IHN5bWxpbmtzIGluIG15IHByZXByb2Nlc3NpbmcgZGlyZWN0b3J5IHdpdGggb25lIGhvbGUKd2hlcmUgYSBzYW1wbGUgZ290IGNoYW5nZWQgYW5kIGEgY291cGxlIG5ldyBpcHJnYyBJRHMgZHVlIHRvIHRoZQpjaGFuZ2VzIGludHJvZHVjZWQgYnkgQXByaWwncyByZXByb2Nlc3NpbmcuCgpBZnRlciBzdGFyaW5nIGF0IHRoZSBzY3JlZW4gZm9yIGEgbW9tZW50LCBJIGRlY2lkZWQgdG8gc3BsaXQgdGhlc2UKc2FtcGxlcyBpbnRvIHN1YmRpcmVjdG9yaWVzIG5hbWVkIGFmdGVyIHRoZSBzZXF1ZW5jaW5nIHllYXIsIHRodXM6CgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbWtkaXIgMjAxOSAyMDIwIDIwMjIgMjAyMwoKbXYgaXByZ2NfMFsxLThdIDIwMTkKCm12IGlwcmdjXzA5IGlwcmdjXzEqIGlwcmdjXzIqIGlwcmdjXzMqIGlwcmdjXzQqIGlwcmdjXzUqIGlwcmdjXzYwIGlwcmdjXzYxIDIwMjAKCm12IGlwcmdjXzYqIGlwcmdjXzcqIGlwcmdjXzhbMC00XSAyMDIyCgptdiBpcHJnYyogMjAyMwoKIyMgaGFoYSBJIHdhcyBhIGRvb2Z1cyBhbmQgbW92ZWQgdGhlIDEwMHMgaW50byAyMDIwIGRpcmVjdG9yeSBiZWNhdXNlIGlwcmdjXzEqIG1hdGNoZXMgMTAwKwptdiAyMDIwL2lwcmdjXzFbMC05XVswLTldIDIwMjMKCiMjIEkgbGF0ZXIgZGVjaWRlZCB0byBwdXQgYWxsIHRoZSB1bWQgc2VxdWVuY2VkIGRhdGEgaW50byB0aGUgc2FtZSB0cmVlCm1rZGlyIHVtZF9zZXF1ZW5jZWQKbXYgMjAyMi8qIHVtZF9zZXF1ZW5jZWQvCm12IDIwMjMvKiB1bWRfc2VxdWVuY2VkLwpgYGAKCkkgYW0gZG9pbmcgdGhpcyBiZWNhdXNlIEkgYW0gZ3Vlc3NpbmcgdGhlcmUgbWF5IGJlIHJlbGV2YW50CmRpZmZlcmVuY2VzIGluIHRoZSB2YXJpb3VzIHJvdW5kcyBvZiBzZXF1ZW5jaW5nLiAgSW4gYWRkaXRpb24gSSBhbQpyZWFzb25hYmx5IGNlcnRhaW4gYWxsIHRoZSB0YWthcmEgc2FtcGxlcyBhcmUgaW4gMjAyMiBhbmQgMjAyMy4KCk9rLCBzbyBub3cgSSBzaG91bGQgYmUgYWJsZSB0byBjb21mb3J0YWJseSBwcm9jZXNzIGRpZmZlcmVudApzZXF1ZW5jaW5nIHBsYXRmb3JtIGRhdGEgdXNpbmcgZm9yLWxvb3BzIHdpdGhvdXQgd29ycnlpbmcgdG9vIG11Y2gKYWJvdXQgc2hlbmFuaWdhbnMuCgojIFRyaW1taW5nCgpJIGFtIHRoZXJlZm9yZSBnb2luZyB0byB0YWtlIGEgbW9tZW50IGFuZCBwZWVrIGluIFRoZXJlc2EncyB0cmVlIGFuZApzZWUgaG93IHRoZSBlYXJseSBzYW1wbGVzIHdlcmUgdHJpbW1lZC4KCkxvb2tpbmcgaW4gVGhlcmVzYSdzIHRyZWUsIEkgc2VlIHRoYXQgc2hlIGxpa2VseSBrZXB0IG15IG9yaWdpbmFsCnRyaW1tZWQgZGF0YSB1c2luZyBjdXRhZGFwdCBAbWFydGluQ3V0YWRhcHRSZW1vdmVzQWRhcHRlcjIwMTFhICBhbmQKYWxzbyBwZXJmb3JtZWQgYSB0cmltb21hdGljIEBib2xnZXJUcmltbW9tYXRpY0ZsZXhpYmxlVHJpbW1lcjIwMTQgcnVuLiAgSQp0b29rIGEgbW9tZW10IGFuZCBzZWUgdGhhdCBJIHVzZWQgY3V0YWRhcHQgYmVjYXVzZSB0aGUgdmVyc2lvbiBvZgp0cmltb21hdGljIGF0IHRoYXQgdGltZSBkaWQgbm90IGhhdmUgdGhlIHByaW1lcnMgaW4gaXQgZm9yIHRoaXMKbGlicmFyeSB0eXBlOyBidXQgdGhhdCBoYXMgc2luY2UgYmVlbiBhbWVsaW9yYXRlZC4gIEkgdGhlcmVmb3JlIGFzc3VtZQp0aGF0IEkgY2FuIGNvbWZvcnRhYmx5IHRyaW0gd2l0aCBlaXRoZXIgdHJpbW9tYXRpYyBvciBmYXN0cApAY2hlbkZhc3RwVWx0cmFmYXN0QWxsaW5vbmUyMDE4IHdpdGhvdXQgcHJvYmxlbXMuICBJIHdpbGwgZGVmaW5pdGVseQpuZWVkIHRvIHVzZSBmYXN0cWMgQFNhbmRyZXdzRmFzdFFDUXVhbGl0eSBhZnRlciB0cmltbWluZyBhbmQgbWFrZQpjZXJ0YWluIHRoYXQgbm9uZSBvZiB0aGUgd2VpcmRvIGkzL2k1KG9yIHdoYXRldmVyIHRoZXkgYXJlIGNhbGxlZCkKYWRhcHRlcnMgcmVtYWluLgoKT2gsIGFuIGltcG9ydGFudCBub3RlOiBJIG9ubHkgY29uZmlndXJlZCBmYXN0cCByZWNlbnRseSBpbiBteSBwaXBlbGluZQphbmQgaXQgZGVmYXVsdHMgdG8gdHJ5aW5nIHRvIGRvIGEgVU1JIGV4dHJhY3Rpb24sIHdoaWNoIGlzCmluYXBwcm9wcmlhdGUgZm9yIHRoZXNlIGZpcnN0IHNhbXBsZXMuICBJIG5lZWQgdG8gcmVtZW1iZXIgdG8gdGVsbCBpdApub3QgdG8gZG8gdGhhdCBmb3IgdGhlc2UuICBBbHNvLCBJIGRvIG5vdCBmdWxseSB1bmRlcnN0YW5kIFVNSXMgeWV0LgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm1vZHVsZSBhZGQgY3lvYS8yMDI0MDYKY2QgMjAxOQpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kIGlwcmdjKik7IGRvCiAgICBlY2hvICJTdGFydGluZyAkaSIKICAgIGNkICRpCiAgICBpbnB1dHM9JCgvYmluL2xzIHVucHJvY2Vzc2VkLyouZmFzdHEuZ3ogfCB0ciAnXG4nICc6JyB8IHNlZCAncy86JC8vZycpCiAgICBlY2hvICJUaGUgaW5wdXRzIGFyZTogJHtpbnB1dHN9IgogICAgY3lvYSAtLW1ldGhvZCB0cmltIC0taW5wdXQgIiR7aW5wdXRzfSIgLS1qcHJlZml4IDAxCiAgICBjeW9hIC0tbWV0aG9kIGZhc3RwIC0taW5wdXQgIiR7aW5wdXRzfSIgLS1qcHJlZml4IDAxIC0tZG9fdW1pIDAKICAgIGN5b2EgLS1tZXRob2QgdW1pdG9vbHMgLS1pbnB1dCAiJHtpbnB1dHN9IC0tanByZWZpeCAwMQogICAgY2QgJHN0YXJ0CmRvbmUKCmNkIC4uLzIwMjAKc3RhcnQ9JChwd2QpCmZvciBpIGluICQoL2Jpbi9scyAtZCBpcHJnYyopOyBkbwogICAgZWNobyAiU3RhcnRpbmcgJGkiCiAgICBjZCAkaQogICAgaW5wdXRzPSQoL2Jpbi9scyB1bnByb2Nlc3NlZC8qLmZhc3RxLmd6IHwgdHIgJ1xuJyAnOicgfCBzZWQgJ3MvOiQvL2cnKQogICAgZWNobyAiVGhlIGlucHV0cyBhcmU6ICR7aW5wdXRzfSIKICAgIGN5b2EgLS1tZXRob2QgdHJpbSAtLWlucHV0ICIke2lucHV0c30iIC0tanByZWZpeCAwMQogICAgY3lvYSAtLW1ldGhvZCBmYXN0cCAtLWlucHV0ICIke2lucHV0c30iIC0tanByZWZpeCAwMSAtLWRvX3VtaSAwCiAgICBjZCAkc3RhcnQKZG9uZQoKYGBgCgpOZXh0IHN0ZXBzLCB3aGljaCB3aWxsIGhhdmUgdG8gd2FpdCBhIGZldyBtaW51dGVzOiBkb3dubG9hZCBhIG5ldwptdXNjdWx1cyBhc3NlbWJseSBhbmQgY2hlY2sgdGhhdCBteSB0cmltbWluZyByZXN1bHRzIGxvb2sgbGlrZQpUaGVyZXNhJ3MuCgpGb3IgdGhlIDIwMjIvMjAyMyBzYW1wbGVzLCBJIHNob3VsZCBhdCB0aGUgdmVyeSBsZWFzdCBiZSByZWFkeSB0byB1c2UKY29nZW50LCBzbyBsZXQgdXMgdGFrZSBhIG1vbWVudCBhbmQgbG9vayBhdCBUaGVyZXNhJ3MgdHJlZSBhbmQgcmVjYWxsCmhvdyB0byB1c2UgaXQuCgpCZWZvcmUgSSB3ZW50IHBva2luZyB0aHJvdWdoIFRoZXJlc2EncyB0cmVlLCBJIGNvcHkvcGFzdGVkIHRoZQpmb2xsb3dpbmcgZnJvbSBBcHJpbCdzIHJlcG9ydDoKCgoqICBUaGUgd29ya2Zsb3cgdXNlZCBpbiB0aGlzIGtpdCB0YWtlcyBhZHZhbnRhZ2Ugb2YgYSBub3ZlbAogICB0ZWNobm9sb2d5IGFsbG93aW5nIHJlbW92YWwgb2Ygcmlib3NvbWFsIGNETkEgKG9yaWdpbmF0aW5nIGZyb20KICAgclJOQSkgYWZ0ZXIgY0ROQSBzeW50aGVzaXMgdXNpbmcgcHJvYmVzIHNwZWNpZmljIHRvIG1hbW1hbGlhbgogICByUk5BLiBUaGVzZSBSLVByb2JlcyB0YXJnZXQgbnVjbGVhciBhbmQgbWl0b2Nob25kcmlhbCByUk5BCiAgIHNlcXVlbmNlczsgaG93ZXZlciwgdGhlIG1pdG9jaG9uZHJpYWwgUi1Qcm9iZXMgYXJlIGRlcml2ZWQgZnJvbQogICB0aGUgaHVtYW4gbWl0b2Nob25kcmlhbCBnZW5vbWUgYW5kIGFyZSB0aGVyZWZvcmUgc3RyaWN0bHkKICAgaHVtYW4tc3BlY2lmaWMuIFRoZSByUk5BIGRlcGxldGlvbiBtZXRob2QgdXNlZCBpbiB0aGlzIGtpdCBtYWtlcwogICBpdCBlc3BlY2lhbGx5IHdlbGwtc3VpdGVkIGZvciB3b3JraW5nIHdpdGggdmVyeSBzbWFsbCBxdWFudGl0aWVzCiAgIG9mIHRvdGFsIFJOQS4gVGhlcmVmb3JlLCB5b3Ugd2lsbCBsaWtlbHkgc2VlIHJlYWRzIG1hcHBpbmcgdG8KICAgbW91c2UgbWl0b2Nob25kcmlhbCByUk5BLgoqICBUaGlzIGtpdCBhZGRzIGFuIDggbnVjbGVvdGlkZSAobnQpIHVuaXF1ZSBtb2xlY3VsYXIgaWRlbnRpZmllcgogICAoVU1JKSB0aHJvdWdoIHRoZSByZXZlcnNlLXRyYW5zY3JpcHRpb24gc3RlcCB0byBtaXRpZ2F0ZQogICBwb3RlbnRpYWwgUENSIGJpYXMgYXMgd2VsbCBhcyB0byBwcm92aWRlIGN1c3RvbWVycyB3aXRoCiAgIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gZm9yIHRyYW5zY3JpcHQgcXVhbnRpZmljYXRpb24sCiAgIHNwZWNpZmljYWxseSBmb3IgdHJ1ZSB2YXJpYW50cyBhbmQgcmFyZSBtdXRhdGlvbnMuIFRoaXMga2l0IGlzCiAgIGRlc2lnbmVkIGZvciBhbmFseXNpcyB3aXRoIFRha2FyYSBCaW/igJlzIENvZ2VudCBOR1MgQW5hbHlzaXMKICAgUGlwZWxpbmUgU29mdHdhcmUsIHdoaWNoIHJlbW92ZXMgUENSIGR1cGxpY2F0ZXMgYW5kIGVycm9ycwogICBiYXNlZCBvbiB0aGUgVU1Jcy4KKiAgVGhlIGRpcmVjdGlvbmFsaXR5IG9mIHRoZSB0ZW1wbGF0ZS1zd2l0Y2hpbmcgcmVhY3Rpb24KICAgcHJlc2VydmVzIHRoZSBzdHJhbmQgb3JpZW50YXRpb24gb2YgdGhlIG9yaWdpbmFsIFJOQSwKICAgbWFraW5nIGl0IHBvc3NpYmxlIHRvIG9idGFpbiBzdHJhbmQtc3BlY2lmaWMgc2VxdWVuY2luZwogICBkYXRhIGZyb20gdGhlIHN5bnRoZXNpemVkIGNETkEuIElsbHVzdHJhdGVkIGJlbG93IGFyZSB0aGUKICAgY0ROQSBsaWJyYXJ5IGNvbnN0cnVjdGlvbiBwcm9jZXNzIGFuZCB0ZWNobm9sb2dpZXMKICAgZW1wbG95ZWQgYnkgdGhlIGtpdCAoRmlndXJlIDEpLCBhbmQgdGhlIHN0cnVjdHVyYWwgZGV0YWlscwogICBvZiBmaW5hbCBsaWJyYXJpZXMgKEZpZ3VyZSAyKS4KCiMgVW1pIFRyaW1taW5nCgpUaGUgaW1hZ2VzIHdoaWNoIGZvbGxvdyBwcm92aWRlIGEgZGlhZ3JhbSBvZiB0aGUgbGlicmFyeSBsYXlvdXQgd2hpY2gKSSB0aGluayBhbnN3ZXJzIG15IHF1ZXN0aW9ucyBhbmQgbG9va3MgYSBsaXR0bGUgbGlrZSB0aGlzOgoKNSctPiBSZWFkIDIKUDcgIGk3ICBSMnN0YXJ0IFVNSSAgIDUnIHNlcXVlbmNlICAgICAgICAgICAgICAgICAgICAgICAgICAgMycgc2VxdWVuY2UgPC0gUjEgIGk1ICBwNQpwcHBwIGlpaSBSUlJSVVVOTk5YWFggYWN0dWFsIHNlcXVlbmNlIGRhdGEgZnJvbSBsaWJyYXJ5Li4uLi4uLi4uLi4uLi4uLiBSUlJSUiBpaWkgcHBwCgpSMSBpcyBvZiBjb3Vyc2UgdGhlIHJldmVyc2UgY29tcGxlbWVudCBvZiB0aGlzLiAgVGh1cyBJIHRoaW5rIEkgY2FuCmV4cGVjdCBhIDggbnQgVU1JIHNwZWNpZmljIHRvIGVhY2ggc2FtcGxlIGZvbGxvd2VkIGJ5IHRoZSBOTk5YWFggVU1JCndoaWNoIGltbWVkaWF0ZWx5IHByZWNlZGVzIHRoZSBsaWJyYXJ5IHNlcXVlbmNlLiAgVGhpcyBzaG91bGQgYmUgYXQKdGhlIGJlZ2lubmluZyBvZiBSMiBhbmQgZW5kIG9mIFIxIGlmIEkgaW50ZXJwcmV0IHRoaXMgY29ycmVjdGx5LgoKV2l0aCB0aGlzIGluIG1pbmQsIEkgdXNlZCB0aGUgdW1pX3Rvb2xzIGluIG9yZGVyIHRvIHBlcmZvcm0KZGVkdXBsaWNhdGlvbiB2aWEgdGhlIGZvbGxvd2luZyBwYXRoOgoKMS4gbGFiZWwgZWFjaCByZWFkIHdpdGggaXRzIFVNSSB3aXRoIHVtaV90b29scwogICBAc21pdGhVTUl0b29sc01vZGVsaW5nU2VxdWVuY2luZzIwMTcKMi4gbWFwcGVkIHRoZSBmdWxsIHNldCBvZiByZWFkcyB3aXRoIGhpc2F0MgogICBAa2ltR3JhcGhiYXNlZEdlbm9tZUFsaWdubWVudDIwMTkgYW5kIHRoZSBtbTM5XzExMiBnZW5vbWUKICAgQE11c19tdXNjdWx1c0Vuc2VtYmxHZW5vbWUKMy4gU29ydGVkL2luZGV4ZWQvY29tcHJlc3NlZCB0aGUgYWxpZ25tZW50IHdpdGggc2FtdG9vbHMKICAgQGxpU2VxdWVuY2VBbGlnbm1lbnRNYXAyMDA5CjQuIENvdW50ZWQgdGhlIHJlYWRzL2dlbmUgdmlhIGh0c2VxIEBwdXRyaUFuYWx5c2luZ0hpZ2h0aHJvdWdocHV0U2VxdWVuY2luZzIwMjIKNS4gSW52b2tlZCB1bWlfdG9vbHMgdXNpbmcgdGhlIG91dHB1dCBmcm9tICMzIHRvIHJlbW92ZSByZWFkcyB3aGljaAogICBzaGFyZSB0aGUgc2FtZSBzdGFydC9lbmQgcG9zaXRpb25zIGFuZCBVTUkgKGUuZy4gdGhlIGR1cGxpY2F0ZXMpCiAgIGJ1dCBrZWVwaW5nIHRoZSBmaXJzdC4KNi4gQ291bnRlZCB0aGUgcmVhZHMvZ2VuZSB2aWEgaHRzZXEgdXNpbmcgdGhlIG91dHB1dCBmcm9tICM1LgoKIyMgQnJpZWYgY2hhdCB3aXRoIENvbGVuc28gb24gMjAyNDA2MDUKCkkgc3Bva2UgYnJpZWZseSB3aXRoIENvbGVuc28gdG9kYXkgYW5kIHF1aWNrbHkgcmVhbGl6ZWQgdGhhdCBJIHdhcwpmb29saXNobHkgY2hhc2luZyB0aGUgZ29hbCBvZiB0cmVhdGluZyBzYW1wbGVzIDwyMDIyIGlkZW50aWNhbGx5IHRvCnRob3NlIHdoaWNoIGFyZSA+PTIwMjIuICBUaGV5IChjdXJyZW50bHkpIGRvIG5vdCB3aXNoIHRvIHdvcmsgd2l0aCBhbnkKb2YgdGhvc2UgZWFybGllciBzYW1wbGVzLCB3aGljaCBtYWtlcyBteSBsaWZlIGNvbnNpZGVyYWJseSBlYXNpZXIuICBBcwphIHJlc3VsdCBJIGNvcGllZCBteSBzYW1wbGUgc2hlZXQgdG8gJzIwMjQwNjA2X3NwZWVyX3NhbXBsZXMueGxzeCcgYW5kCmRlbGV0ZWQgZnJvbSBpdCBhbGwgSURzIGZyb20gaXByZ2NfMDEgdG8gaXByZ2NfNjEuICBUaGlzIG1lYW5zIHRoYXQKZXZlcnkgc2FtcGxlIHdhcyBzZXF1ZW5jZWQgaWRlbnRpY2FsbHkgYW5kIGFsbCBoYXZlIHRoZSBzYW1lIFVNSQpjb25maWd1cmF0aW9uLgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CmNkIHByZXByb2Nlc3NpbmcKY2QgdW1kX3NlcXVlbmNlZApzdGFydD0kKHB3ZCkKY2QgJHN0YXJ0CmZvciBpIGluICQoL2Jpbi9scyAtZCBpcHJnYyopOyBkbwogICAgY2QgJGkKICAgIGVjaG8gJGkKICAgIHIxX2lucHV0PSQoL2Jpbi9scyB1bnByb2Nlc3NlZC8qUjEqLmZhc3RxLmd6KQogICAgcjJfaW5wdXQ9JCgvYmluL2xzIHVucHJvY2Vzc2VkLypSMiouZmFzdHEuZ3opCiAgICBpbnB1dD0iJHtyMV9pbnB1dH06JHtyMl9pbnB1dH0iCiAgICBjeW9hIC0tbWV0aG9kIHVtaSAtLWlucHV0ICR7aW5wdXR9CiAgICBjZCAkc3RhcnQKZG9uZQpgYGAKClRoZSBwcmV2aW91cyBibG9jayBzZXJ2ZXMgdG8gcmVtb3ZlIHRoZSBVTUkgcHJlZml4IG9mIHJlYWQyIGFuZCBtb3ZlCnRoYXQgaW5mb3JtYXRpb24gdG8gdGhlIHN1ZmZpeCBvZiB0aGUgcmVhZCBJRC4gIEkgd291bGQgYXJndWUgdGhhdCBpdApzaG91bGQgYmUgcHV0IGluIHRoZSByZWFkIGNvbW1lbnQsIGJ1dCB3aGF0ZXZlci4gIEZyb20gdGhhdCBzdGVwLCB3ZQpwZXJmb3JtIHRoZSBhbGlnbm1lbnQgYXMgcGVyIHVzdWFsLCB0aGVuIHVzZSB1bWlfdG9vbHMgZGVkdXAgdG8KZXhjbHVkZSByZWFkcyB3aXRoIHRoZSBzYW1lIElEIHdoaWNoIG1hcCB0byB0aGUgc2FtZSBwbGFjZSwgdGhlbiBjb3VudAp1cCB0aGUgcmVtYWluaW5nIHJlYWRzL2dlbmUuCgpJIHRoaW5rIHRoZSBwcmV2aW91cyBhbmFseXNpcyBkaWQgbm90IHBlcmZvcm0gdGhlIGRlZHVwbGljYXRpb24gc3RlcCwKYXQgbGVhc3QgSSBoYXZlIG5vdCB5ZXQgZm91bmQgaXQgaW4gdGhlIGxvZ3MuICBBcyBhIHJlc3VsdCwgSSBhbSBnb2luZwp0byBkbyBvbmUgcm91bmQgd2l0aCBhbmQgb25lIHdpdGhvdXQgdGhlIGRlZHVwbGljYXRpb24uICBNeSBob3BlIGlzCnRoYXQgdGhleSB3aWxsIGJlOgoKYS4gcXVpdGUgc2ltaWxhciB0byBlYWNoIG90aGVyCmIuIHRoZSB3aXRob3V0LWRlZHVwbGljYXRpb24gcmVzdWx0IHdpbGwgYmUgbmVhcmx5IGlkZW50aWNhbCB0byB0aGUKICAgcHJldmlvdXMgc2V0CmMuIHRoZSB3aXRoLWRlZHVwbGljYXRpb24gc3RlcCB3aWxsIHNsaWdodGx5IGltcHJvdmUgdGhlIHJlc3VsdHMuCgpMZXQncyBmaW5kIG91dCEKCiMgTWFwcGluZyBhZ2FpbnN0IHRoZSBlbnNlbWJsIG11cyBtdXNjdWx1cyAxMTIgcmVsZWFzZQoKTm90ZSwgSSBjb3VsZC9zaG91bGQgaGF2ZSBwaXBlZCB0aGUgb3V0cHV0IG9mIHVtaV90b29scyBkaXJlY3RseSBpbnRvCmhpc2F0LCBidXQgSSBkaWRuJ3QuCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KY2QgcHJlcHJvY2Vzc2luZy91bWRfc2VxdWVuY2VkCnN0YXJ0PSQocHdkKQpjZCAkc3RhcnQKZm9yIGkgaW4gJCgvYmluL2xzIC1kIGlwcmdjKik7IGRvCiAgICBjZCAkaQogICAgZWNobyAkaQogICAgaW5wdXQ9Im91dHB1dHMvMDF1bWlfdG9vbHMvcjFfZXh0cmFjdGVkLmZhc3RxLmd6Om91dHB1dHMvMDF1bWlfdG9vbHMvcjJfZXh0cmFjdGVkLmZhc3RxLmd6IgogICAgY3lvYSAtLW1ldGhvZCBoaXNhdCAtLXNwZWNpZXMgbW0zOV8xMTIgLS1pbnB1dCAke2lucHV0fSAtLWdmZl90eXBlIGdlbmUgLS1nZmZfdGFnIElEIFwKICAgICAgICAgLS1zdHJhbmRlZCByZXZlcnNlCiAgICBjeW9hIC0tbWV0aG9kIGhpc2F0IC0tc3BlY2llcyBtbTM5XzExMiAtLWxpYnR5cGUgclJOQSAtLWdmZl90eXBlIHJSTkEgLS1nZmZfdGFnIElEIFwKICAgICAgICAgLS1zdHJhbmRlZCByZXZlcnNlIC0taW5wdXQgJHtpbnB1dH0KICAgIGNkICRzdGFydApkb25lCmBgYAoKIyBEZWR1cGxpY2F0aW9uCgpBIG5vdGUgdG8gc2VsZiwgaGVyZSBhcmUgdGhlIGRlZHVwIG9wdGlvbnM6CgogICAgLS1vdXRwdXQtc3RhdHM9U1RBVFMKICAgICAgICAgICAgICAgICAgICAgICAgU3BlY2lmeSBsb2NhdGlvbiB0byBvdXRwdXQgc3RhdHMKCiAgQmFyY29kZSBleHRyYWN0aW9uIG9wdGlvbnM6CiAgICAtLWV4dHJhY3QtdW1pLW1ldGhvZD1HRVRfVU1JX01FVEhPRAogICAgICAgICAgICAgICAgICAgICAgICBob3cgaXMgdGhlIHJlYWQgVU1JICsvIGNlbGwgYmFyY29kZSBlbmNvZGVkPyBbZGVmYXVsdD1yZWFkX2lkXQogICAgLS11bWktc2VwYXJhdG9yPVVNSV9TRVAKICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yIGJldHdlZW4gcmVhZCBpZCBhbmQgVU1JCiAgICAtLXVtaS10YWc9VU1JX1RBRyAgIHRhZyBjb250YWluaW5nIHVtaQogICAgLS11bWktdGFnLXNwbGl0PVVNSV9UQUdfU1BMSVQKICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXQgVU1JIGluIHRhZyBhbmQgdGFrZSB0aGUgZmlyc3QgZWxlbWVudAogICAgLS11bWktdGFnLWRlbGltaXRlcj1VTUlfVEFHX0RFTElNCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmNhdGVuYXRlIFVNSSBpbiB0YWcgc2VwYXJhdGVkIGJ5IGRlbGltaXRlcgogICAgLS1jZWxsLXRhZz1DRUxMX1RBRwogICAgICAgICAgICAgICAgICAgICAgICB0YWcgY29udGFpbmluZyBjZWxsIGJhcmNvZGUKICAgIC0tY2VsbC10YWctc3BsaXQ9Q0VMTF9UQUdfU1BMSVQKICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXQgY2VsbCBiYXJjb2RlIGluIHRhZyBhbmQgdGFrZSB0aGUgZmlyc3RlbGVtZW50IGZvciBlLmcgMTBYIEdFTSB0YWdzCiAgICAtLWNlbGwtdGFnLWRlbGltaXRlcj1DRUxMX1RBR19ERUxJTQogICAgICAgICAgICAgICAgICAgICAgICBjb25jYXRlbmF0ZSBjZWxsIGJhcmNvZGUgaW4gdGFnIHNlcGFyYXRlZCBieSBkZWxpbWl0ZXIKCiAgVU1JIGdyb3VwaW5nIG9wdGlvbnM6CiAgICAtLW1ldGhvZD1NRVRIT0QgICAgIG1ldGhvZCB0byB1c2UgZm9yIHVtaSBncm91cGluZyBbZGVmYXVsdD1kaXJlY3Rpb25hbF0KICAgIC0tZWRpdC1kaXN0YW5jZS10aHJlc2hvbGQ9VEhSRVNIT0xECiAgICAgICAgICAgICAgICAgICAgICAgIEVkaXQgZGlzdGFuY2UgdGhlc2hvbGQgYXQgd2hpY2ggdG8gam9pbiB0d28gVU1JcyB3aGVuIGdyb3VwaW5nIFVNSXMuIFtkZWZhdWx0PTFdCiAgICAtLXNwbGljZWQtaXMtdW5pcXVlCiAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0IGEgc3BsaWNlZCByZWFkIGFzIGRpZmZlcmVudCB0byBhbiB1bnNwbGljZWQgb25lIFtkZWZhdWx0PUZhbHNlXQogICAgLS1zb2Z0LWNsaXAtdGhyZXNob2xkPVNPRlRfQ0xJUF9USFJFU0hPTEQKICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyIG9mIGJhc2VzIGNsaXBwZWQgZnJvbSA1JyBlbmQgYmVmb3JlIHJlYWQgaXMgY291bnRlZCBhcyBzcGxpY2VkIFtkZWZhdWx0PTRdCiAgICAtLXJlYWQtbGVuZ3RoICAgICAgIHVzZSByZWFkIGxlbmd0aCBpbiBhZGRpdGlvbiB0byBwb3NpdGlvbiBhbmQgVU1JIHRvIGlkZW50aWZ5IHBvc3NpYmxlIGR1cGxpY2F0ZXMgW2RlZmF1bHQ9RmFsc2VdCgogIHNpbmdsZS1jZWxsIFJOQS1TZXEgb3B0aW9uczoKICAgIC0tcGVyLWdlbmUgICAgICAgICAgR3JvdXAvRGVkdXAvQ291bnQgcGVyIGdlbmUuIE11c3QgY29tYmluZSB3aXRoIGVpdGhlciAtLWdlbmUtdGFnIG9yIC0tcGVyLWNvbnRpZwogICAgLS1nZW5lLXRhZz1HRU5FX1RBRwogICAgICAgICAgICAgICAgICAgICAgICBHZW5lIGlzIGRlZmluZWQgYnkgdGhpcyBiYW0gdGFnIFtkZWZhdWx0PW5vbmVdCiAgICAtLWFzc2lnbmVkLXN0YXR1cy10YWc9QVNTSUdORURfVEFHCiAgICAgICAgICAgICAgICAgICAgICAgIEJhbSB0YWcgZGVzY3JpYmluZyB3aGV0aGVyIHJlYWQgaXMgYXNzaWduZWQgdG8gYSBnZW5lIEJ5IGRlZnVhbHQsIHRoaXMgaXMgc2V0IGFzIHRoZSBzYW1lIHRhZyBhcyAtLWdlbmUtdGFnCiAgICAtLXNraXAtdGFncy1yZWdleD1TS0lQX1JFR0VYCiAgICAgICAgICAgICAgICAgICAgICAgIFVzZWQgd2l0aCAtLWdlbmUtdGFnLiBJZ25vcmUgcmVhZHMgd2hlcmUgdGhlIGdlbmUtdGFnIG1hdGNoZXMgdGhpcyByZWdleAogICAgLS1wZXItY29udGlnICAgICAgICBncm91cC9kZWR1cC9jb3VudCBVTUlzIHBlciBjb250aWcgKGZpZWxkIDMgaW4gQkFNOyBSTkFNRSksIGUuZyBmb3IgdHJhbnNjcmlwdG9tZSB3aGVyZSBjb250aWcgPSBnZW5lCiAgICAtLWdlbmUtdHJhbnNjcmlwdC1tYXA9R0VORV9UUkFOU0NSSVBUX01BUAogICAgICAgICAgICAgICAgICAgICAgICBGaWxlIG1hcHBpbmcgdHJhbnNjcmlwdHMgdG8gZ2VuZXMgKHRhYiBzZXBhcmF0ZWQpCiAgICAtLXBlci1jZWxsICAgICAgICAgIGdyb3VwL2RlZHVwL2NvdW50IHBlciBjZWxsCgogIGdyb3VwL2RlZHVwIG9wdGlvbnM6CiAgICAtLWJ1ZmZlci13aG9sZS1jb250aWcKICAgICAgICAgICAgICAgICAgICAgICAgUmVhZCB3aG9sZSBjb250aWcgYmVmb3JlIG91dHB1dHRpbmcgYnVuZGxlczogZ3VhcmFudGVlcyB0aGF0IG5vIHJlYWRzIGFyZSBtaXNzZWQsIGJ1dCBpbmNyZWFzZXMgbWVtb3J5IHVzYWdlCiAgICAtLW11bHRpbWFwcGluZy1kZXRlY3Rpb24tbWV0aG9kPURFVEVDVElPTl9NRVRIT0QKICAgICAgICAgICAgICAgICAgICAgICAgU29tZSBhbGlnbmVycyBpZGVudGlmeSBtdWx0aW1hcHBpbmcgdXNpbmcgYmFtIHRhZ3MuIFNldHRpbmcgdGhpcyBvcHRpb24gdG8gTkgsIFgwIG9yIFhUIHdpbGwgdXNlIHRoZXNlIHRhZ3Mgd2hlbgogICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RpbmcgdGhlIGJlc3QgcmVhZCBhbW9uZ3N0IHJlYWRzIHdpdGggdGhlIHNhbWUgcG9zaXRpb24gYW5kIHVtaSBbZGVmYXVsdD1ub25lXQoKICBTQU0vQkFNIG9wdGlvbnM6CiAgICAtLW1hcHBpbmctcXVhbGl0eT1NQVBQSU5HX1FVQUxJVFkKICAgICAgICAgICAgICAgICAgICAgICAgTWluaW11bSBtYXBwaW5nIHF1YWxpdHkgZm9yIGEgcmVhZCB0byBiZSByZXRhaW5lZCBbZGVmYXVsdD0wXQogICAgLS1pZ25vcmUtdW1pICAgICAgICBJZ25vcmUgVU1JIGFuZCBkZWR1cCBvbmx5IG9uIHBvc2l0aW9uCiAgICAtLWlnbm9yZS10bGVuICAgICAgIE9wdGlvbiB0byBkZWR1cCBwYWlyZWQgZW5kIHJlYWRzIGJhc2VkIHNvbGVseSBvbiByZWFkMSwgd2hldGhlciBvciBub3QgdGhlIHRlbXBsYXRlIGxlbmd0aCBpcyB0aGUgc2FtZQogICAgLS1jaHJvbT1DSFJPTSAgICAgICBSZXN0cmljdCB0byBvbmUgY2hyb21vc29tZQogICAgLS1zdWJzZXQ9U1VCU0VUICAgICBVc2Ugb25seSBhIGZyYWN0aW9uIG9mIHJlYWRzLCBzcGVjaWZpZWQgYnkgc3Vic2V0CiAgICAtaSwgLS1pbi1zYW0gICAgICAgIElucHV0IGZpbGUgaXMgaW4gc2FtIGZvcm1hdCBbZGVmYXVsdD1GYWxzZV0KICAgIC0tcGFpcmVkICAgICAgICAgICAgcGFpcmVkIGlucHV0IEJBTS4gW2RlZmF1bHQ9RmFsc2VdCiAgICAtbywgLS1vdXQtc2FtICAgICAgIE91dHB1dCBhbGlnbm1lbnRzIGluIHNhbSBmb3JtYXQgW2RlZmF1bHQ9RmFsc2VdCiAgICAtLW5vLXNvcnQtb3V0cHV0ICAgIERvbid0IFNvcnQgdGhlIG91dHB1dAoKICBEZWR1cCBhbmQgQ291bnQgU0FNL0JBTSBvcHRpb25zOgogICAgLS11bm1hcHBlZC1yZWFkcz1VTk1BUFBFRF9SRUFEUwogICAgICAgICAgICAgICAgICAgICAgICBIb3cgdG8gaGFuZGxlIHVubWFwcGVkIHJlYWRzLiBPcHRpb25zIGFyZSAnZGlzY2FyZCcgb3IgJ3VzZScgW2RlZmF1bHQ9ZGlzY2FyZF0KICAgIC0tY2hpbWVyaWMtcGFpcnM9Q0hJTUVSSUNfUEFJUlMKICAgICAgICAgICAgICAgICAgICAgICAgSG93IHRvIGhhbmRsZSBjaGltZXJpYyByZWFkIHBhaXJzLiBPcHRpb25zIGFyZSAnZGlzY2FyZCcgb3IgJ3VzZScgIFtkZWZhdWx0PXVzZV0KICAgIC0tdW5wYWlyZWQtcmVhZHM9VU5QQUlSRURfUkVBRFMKICAgICAgICAgICAgICAgICAgICAgICAgSG93IHRvIGhhbmRsZSB1bnBhaXJlZCByZWFkcy4gT3B0aW9ucyBhcmUgJ2Rpc2NhcmQnb3IgJ3VzZScgW2RlZmF1bHQ9dXNlXQoKICBpbnB1dC9vdXRwdXQgb3B0aW9uczoKICAgIC1JIEZJTEUsIC0tc3RkaW49RklMRQogICAgICAgICAgICAgICAgICAgICAgICBmaWxlIHRvIHJlYWQgc3RkaW4gZnJvbSBbZGVmYXVsdCA9IHN0ZGluXS4KICAgIC1MIEZJTEUsIC0tbG9nPUZJTEUKICAgICAgICAgICAgICAgICAgICAgICAgZmlsZSB3aXRoIGxvZ2dpbmcgaW5mb3JtYXRpb24gW2RlZmF1bHQgPSBzdGRvdXRdLgogICAgLUUgRklMRSwgLS1lcnJvcj1GSUxFCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGUgd2l0aCBlcnJvciBpbmZvcm1hdGlvbiBbZGVmYXVsdCA9IHN0ZGVycl0uCiAgICAtUyBGSUxFLCAtLXN0ZG91dD1GSUxFCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGUgd2hlcmUgb3V0cHV0IGlzIHRvIGdvIFtkZWZhdWx0ID0gc3Rkb3V0XS4KICAgIC0tdGVtcC1kaXI9RklMRSAgICAgRGlyZWN0b3J5IGZvciB0ZW1wb3JhcnkgZmlsZXMuIElmIG5vdCBzZXQsIHRoZSBiYXNoIGVudmlyb25tZW50YWwgdmFyaWFibGUgVE1QRElSIGlzIHVzZWRbZGVmYXVsdCA9IE5vbmVdLgogICAgLS1sb2cyc3RkZXJyICAgICAgICBzZW5kIGxvZ2dpbmcgaW5mb3JtYXRpb24gdG8gc3RkZXJyIFtkZWZhdWx0ID0gRmFsc2VdLgogICAgLS1jb21wcmVzc2xldmVsPUNPTVBSRVNTTEVWRUwKICAgICAgICAgICAgICAgICAgICAgICAgTGV2ZWwgb2YgR3ppcCBjb21wcmVzc2lvbiB0byB1c2UuIERlZmF1bHQgKDYpIG1hdGNoZXNHTlUgZ3ppcCByYXRoZXIgdGhhbiBweXRob24gZ3ppcCBkZWZhdWx0ICh3aGljaCBpcyA5KQoKICBwcm9maWxpbmcgb3B0aW9uczoKICAgIC0tdGltZWl0PVRJTUVJVF9GSUxFCiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JlIHRpbWVpbmcgaW5mb3JtYXRpb24gaW4gZmlsZSBbbm9uZV0uCiAgICAtLXRpbWVpdC1uYW1lPVRJTUVJVF9OQU1FCiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgaW4gdGltaW5nIGZpbGUgZm9yIHRoaXMgY2xhc3Mgb2Ygam9icyBbYWxsXS4KICAgIC0tdGltZWl0LWhlYWRlciAgICAgYWRkIGhlYWRlciBmb3IgdGltaW5nIGluZm9ybWF0aW9uIFtub25lXS4KCiAgY29tbW9uIG9wdGlvbnM6CiAgICAtdiBMT0dMRVZFTCwgLS12ZXJib3NlPUxPR0xFVkVMCiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2xldmVsIFsxXS4gVGhlIGhpZ2hlciwgdGhlIG1vcmUgb3V0cHV0LgogICAgLWgsIC0taGVscCAgICAgICAgICBvdXRwdXQgc2hvcnQgaGVscCAoY29tbWFuZCBsaW5lIG9wdGlvbnMgb25seSkuCiAgICAtLWhlbHAtZXh0ZW5kZWQgICAgIE91dHB1dCBmdWxsIGRvY3VtZW50YXRpb24KICAgIC0tcmFuZG9tLXNlZWQ9UkFORE9NX1NFRUQKICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tIHNlZWQgdG8gaW5pdGlhbGl6ZSBudW1iZXIgZ2VuZXJhdG9yIHdpdGggW25vbmVdLgoKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQp1bWlfdG9vbHMgZGVkdXAgLS1vdXRwdXQtc3RhdHM9dW1pX2RlZHVwX3N0YXRzLnR4dCBcCiAgICAgICAgICAtLWJ1ZmZlci13aG9sZS1jb250aWcgLUkgbW0zOV8xMTJfZ2Vub21lLmJhbSBcCiAgICAgICAgICAtTCBkZWR1cC5zdGRvdXQgLUUgZGVkdXAuc3RkZXJyIC1TIGRlZHVwLmJhbQpgYGAKCkkgYWRkZWQgYSB2ZXJzaW9uIG9mIHRoaXMgdG8gY3lvYSB3aGljaCBhbHNvIHJlLXBlcmZvcm1zIGh0c2VxIGFuZCBzaG91bGQgYmUgdXNhYmxlIHZpYToKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nL3VtZF9zZXF1ZW5jZWQKc3RhcnQ9JChwd2QpCmNkICRzdGFydApmb3IgaSBpbiAkKC9iaW4vbHMgLWQgaXByZ2MqKTsgZG8KICAgIGNkICRpCiAgICBlY2hvICRpCiAgICBpbnB1dD0ib3V0cHV0cy80MGhpc2F0X21tMzlfMTEyL21tMzlfMTEyX2dlbm9tZS5iYW0iCiAgICBjeW9hIC0tbWV0aG9kIHVtaWRlZHVwIC0tc3BlY2llcyBtbTM5XzExMiAtLWlucHV0ICR7aW5wdXR9IC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgSUQgXAogICAgICAgICAtLXN0cmFuZGVkIHJldmVyc2UKICAgIGNkICRzdGFydApkb25lCmBgYAoKTm90ZSB0aGF0IEkgZXhwbGljaXRseSBtYXBwZWQgYWdhaW5zdCBteSBtbTM5XzExMiByUk5BIGRhdGFiYXNlLCBidXQKbmVnbGVjdGVkIHRvIGRvY3VtZW50IGhvdyBJIG1hZGUgaXQsIGhlcmUgYXJlIHRob3NlIGNvbW1hbmRzOgoKIyMjIE1ha2luZyBhIG1vdXNlIHJSTkEgZGF0YWJhc2UKCkZpcnN0IEkgY29waWVkIG15IGZ1bGwgZ2Vub21lIGZhc3RhIGFuZCBnZmYgdG8gL3RtcC8ganVzdCB0byBtYWtlIHN1cmUKdGhhdCBpZiBJIG1lc3NlZCB1cCBJIHdvdWxkIG5vdCBodXJ0IGFueXRoaW5nCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KY2QgL3RtcApjcCB+L2xpYnJhcmllcy9nZW5vbWUvZmFzdGEvbW0zOSogLgpjcCB+L2xpYnJhcmllcy9nZW5vbWUvZ2ZmL21tMzkqIC4KIyMgTm90ZSwgdGhhdCB3aGVuIHR5cGluZyB0aGUgZm9sbG93aW5nIEkgYWN0dWFsbHkgdHlwZSAnQ29udHJvbC12PHRhYj4nCmdyZXAgInJSTkFcdCIgbW0zOV8xMTIuZ2ZmID4gbW0zOV8xMTJfcnJuYS5nZmYKY3lvYSAtLW1ldGhvZCBnZmYyZmFzdGEgLS1pbnB1dCBtbTM5XzExMi5mYXN0YSAtLWdmZiBtbTM5XzExMl9ycm5hLmdmZiAtLWdmZl90eXBlIHJSTkEgLS1nZmZfdGFnIElECmBgYAoKVGhlIGFib3ZlIGNyZWF0ZWQgYSBjb3VwbGUgb2YgbmV3IGZpbGVzIHdoaWNoIGV4dHJhY3RlZCBmcm9tIHRoZSBmdWxsCmdlbm9tZSB0aGUgYW1pbm8gYWNpZCBhbmQgbnVjbGVvdGlkZSBzZXF1ZW5jZXMgb2YgYWxsIGZlYXR1cmVzIGluIHRoZQpnZmYgd2hpY2ggbWF0Y2hlZCBteSByZXF1aXJlbWVudHMgKHRoZSBhbWlubyBhY2lkIHNlcXVlbmNlcyB3ZXJlIG9mCmNvdXJzZSBnaWJiZXJpc2gpLiAgU28sIEkgY29waWVkIHRoZXNlIG5ldyBmYXN0YS9nZmYgZmlsZXMgdG8gbXkgaW5kZXgKdHJlZSBhbmQgaW5kZXhlZCB0aGVtIGZvciBoaXNhdDI6CgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyMgU3RpbGwgaW4gL3RtcC8KbXYgbW0zOV8xMTJfcnJuYS5nZmYgfi9saWJyYXJpZXMvclJOQS9nZmYvbW0zOV8xMTIuZ2ZmCm12IG1tMzlfMTEyX250X3JSTkFfSUQuZmFzdGEgfi9saWJyYXJpZXMvclJOQS9mYXN0YS9tbTM5XzExMi5mYXN0YQpjeW9hIC0tbWV0aG9kIGluZGV4aGlzYXQgLS1pbnB1dCB+L2xpYnJhcmllcy9yUk5BL2Zhc3RhL21tMzlfMTEyLmZhc3RhIFwKICAgICAtLWdmZiB+L2xpYnJhcmllcy9yUk5BL2dmZi9tbTM5XzExMi5nZmYgLS1saWJ0eXBlIHJSTkEKYGBgCgpUaGF0IGxhc3QgY29tbWFuZCBoYW5kbGVzIHRoZSBpbnZvY2F0aW9uIG9mIHRoZSBoaXNhdDIgaW5kZXhlciB0bwpjcmVhdGUgZm9yIG1lIGEgbW91c2Utc3BlY2lmaWMgclJOQSBkYXRhYmFzZS4KCiMgQmlibGlvZ3JhcGh5Cg==