1 Preprocessing some peculiar samples.

2 Separating samples by hpgl identifier

Najib provided a series of his traditional hpgl identifiers for this data set. I therefore manually copied out the samples by sequence file names in the run0395 and run0396 directories into the appropriate directories. This is therefore an obvious potential source of error. I therefore did this with a second person watching (thanks, Yoann!) and checked each sample 2 times before moving forward.

2.1 New samples

20180402: The folks at the Sacks lab kindly provided a new set of samples, for which Najib provided a fresh set of IDs (HPGL1065-1088). I did the same tasks using the sample sheet he provided me. The source of human error remains, I did double-check my work, but human error in copying remains a possibility.

For each hpgl identifier, I did the following:

  1. Check the sample sheet and copy the files in lane1/lane2 corresponding to the 132* identifier to the corresponding HPGL identifier directory.
  2. cd into each HPGL directory / unprocessed and:
  1. cp 132*_L001_R1* hpglxxxx_forward.fastq.gz
  2. cat 132R1 >> hpglxxxx_forward.fastq.gz (Note I did not do 132R1 as that would be redundant, but instead used tab completion in bash to pick up the correct filenames. I did human error the second directory but happily noticed it immediately and do not think I messed up any thereafter.
  3. cp 132L001_R2 hpglxxxx_reverse.fastq.gz
  4. cat 132R2 >> hpglxxxx_reverse.fastq.gz

Once I finished this, invoked cyoa with options appropriate for trimming/fastqc:

cyoa --task rnaseq --method fastqc --input hpglxxxx_forward.fastq.gz:hpglxxxx_reverse.fastq.gz
cyoa --task rnaseq --method trim --input hpglxxxx_forward.fastq.gz:hpglxxxx_reverse.fastq.gz

3 Preprocessing by sample

The preprocessing of this data happened in two parts and was performed via the cyoa script, which attempts to simplify the creation of jobs on our computer cluster.

I split the preprocessing tasks into two parts, the first part consists of the initial sequencing quality assurance and adapter trimming.

3.1 Part 1

The following is contained in a shell script in preprocessing/ called process_part1.sh

#!/usr/bin/env bash
start=$(pwd)
for i in $(/bin/ls -d hpgl*); do
  cd ${i}
  echo "Starting ${i}"
  cyoa --task rnaseq --method trimom --input ${i}_forward.fastq.gz:${i}_reverse.fastq.gz
  cyoa --task rnaseq --method fastq --input ${i}_forward.fastq.gz:${i}_reverse.fastq.gz
  echo "Finishing ${i}"
  cd ${start}
done

3.2 Part 2

Once the sequence adapters were removed, I perform the set of tasks which depend on the trimmed data. It is worth noting that I tried two (pseudo)aligners for the mouse genome, tophat and kallisto; and two aligners for the parasite genomes, tophat and bowtie2.

In addition, I attempted alignments against L.major and L.amazonensis. My reasoning will become clear soon I think.

#!/usr/bin/env bash
start=$(pwd)
for i in $(/bin/ls -d hpgl084[0-2]); do
  cd "${i}" || exit
  echo "Starting ${i}"
  cyoa --task rnaseq --method biopiece --input "${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz"
  cyoa --task rnaseq --method kallisto --input "${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz" --species mmusculus
  cyoa --task rnaseq --method tophat --input "${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz" --species mmusculus --htseq_type exon --htseq_stranded yes
  cyoa --task rnaseq --method bt2 --input "${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz" --species lamazonensis --htseq_type exon --htseq_stranded yes
  cyoa --task rnaseq --method bt2 --input "${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz" --species lmajor --htseq_type exon --htseq_stranded yes
  cyoa --task rnaseq --method tophat --input "${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz" --species lmajor --htseq_type exon --htseq_stranded yes
  echo "Finishing ${i}"
  cd "${start}" || exit
done

4 What happened in each step?

The cyoa script in turn creates and executes jobs on our torque cluster, I am copy/pasting them below:

Two caveats:

  1. There is a common header and footer for all of these scripts. I will include it for this script, but skip it for the following:
  2. I am going to print here a copy of my script for each step for the first sample and leave as an exercise for the reader the rest.

4.1 Fastqc

The first step in most(all) of our data sets is to make sure that the sequencer provided high-quality data at the expected length(s).

There is only one interesting point in this script, the –extract argument was provided so that a dependent job may be run in order to extract some statistics from the fastqc results.

The following is preprocessing/hpgl0480/scripts/00fqc-hpgl0840.sh

#!/usr/bin/env bash
#PBS -V -S /usr/bin/bash -q workstation
#PBS -d /cbcb/nelsayed-scratch/atb/rnaseq/lmajor_sax/preprocessing/hpgl0840
#PBS -N fqc-hpgl0840 -l mem=6gb -l walltime=10:00:00 -l ncpus=8
#PBS -o /cbcb/nelsayed-scratch/atb/rnaseq/lmajor_sax/preprocessing/hpgl0840/outputs/qsub/fqc-hpgl0840.qsubout -j oe -V -m n
echo "####Started /cbcb/nelsayed-scratch/atb/rnaseq/lmajor_sax/preprocessing/hpgl0840/scripts/00fqc-hpgl0840.sh at $(date)" >> outputs/log.txt
cd /cbcb/nelsayed-scratch/atb/rnaseq/lmajor_sax/preprocessing/hpgl0840 || exit

## This FastQC run is against rnaseq data and is used for
## an initial estimation of the overall sequencing quality.
mkdir -p outputs/fastqc && \
  fastqc --extract -o outputs/fastqc hpgl0840_forward.fastq.gz hpgl0840_reverse.fastq.gz \
  2>outputs/fastqc.out 1>&2

## The following lines give status codes and some logging
echo $? > outputs/status/fqc-hpgl0840.status
echo "###Finished ${PBS_JOBID} 00fqc-hpgl0840.sh at $(date), it took $(( SECONDS / 60 )) minutes." >> outputs/log.txt

walltime=$(qstat -f -t "${PBS_JOBID}" | grep 'resources_used.walltime' | awk -F ' = ' '{print $2}')
echo "####PBS walltime used by ${PBS_JOBID} was: ${walltime:-null}" >> outputs/log.txt
mem=$(qstat -f -t | grep "${PBS_JOBID}" | grep 'resources_used.mem' | awk -F ' = ' '{print $2}')
echo "####PBS memory used by ${PBS_JOBID} was: ${mem:-null}" >> outputs/log.txt
vmmemory=$(qstat -f -t "${PBS_JOBID}" | grep 'resources_used.vmem' | awk -F ' = ' '{print $2}')
echo "####PBS vmemory used by ${PBS_JOBID} was: ${vmmemory:-null}" >> outputs/log.txt
cputime=$(qstat -f -t "${PBS_JOBID}" | grep 'resources_used.cput' | awk -F ' = ' '{print $2}')
echo "####PBS cputime used by ${PBS_JOBID} was: ${cputime:-null}" >> outputs/log.txt
##qstat -f -t ${PBS_JOBID} >> outputs/log.txt

4.1.1 Fastqc statistics

The fastqc statistics are generated separately for the forward/reverse reads.

The following is preprocessing/hpgl0480/scripts/01fqcst_forward-hpgl0840.sh

## This is a stupidly simple job to collect alignment statistics.

if [ ! -r outputs/fastqc_forward_stats.csv ]; then
  echo "name,total_reads,poor_quality,per_quality,per_base_content,per_sequence_gc,per_base_n,per_seq_length,over_rep,adapter_content,kmer_content" > outputs/fastqc_forward_stats.csv
fi
total_reads_tmp=$(grep "^Total Sequences" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
total_reads=${total_reads_tmp:-0}
poor_quality_tmp=$(grep "^Sequences flagged as poor quality" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
poor_quality=${poor_quality_tmp:-0}
per_quality_tmp=$(grep "Per base sequence quality" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
per_quality=${per_quality_tmp:-0}
per_base_content_tmp=$(grep "Per base sequence content" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
per_base_content=${per_base_content_tmp:-0}
per_sequence_gc_tmp=$(grep "Per sequence GC content" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
per_sequence_gc=${per_sequence_gc_tmp:-0}
per_base_n_tmp=$(grep "Per base N content" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
per_base_n=${per_base_n_tmp:-0}
per_seq_length_tmp=$(grep "Sequence Length Distribution" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
per_seq_length=${per_seq_length_tmp:-0}
over_rep_tmp=$(grep "Overrepresented sequences" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
over_rep=${over_rep_tmp:-0}
adapter_content_tmp=$(grep "Adapter Content" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
adapter_content=${adapter_content_tmp:-0}
kmer_content_tmp=$(grep "Kmer Content" outputs/fastqc/hpgl0840_forward.gz_fastqc/fastqc_data.txt | awk -F '\\t' '{print $2}')
kmer_content=${kmer_content_tmp:-0}

stat_string=$(printf "hpgl0840,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" "${total_reads}" "${poor_quality}" "${per_quality}" "${per_base_content}" "${per_sequence_gc}" "${per_base_n}" "${per_seq_length}" "${over_rep}" "${adapter_content}" "${kmer_content}")
echo "$stat_string" >> outputs/fastqc_forward_stats.csv

4.2 Trimomatic

Trimomatic is perhaps the most important step in the process, as it removes the sometimes very abundant sequencing adapters, which if forgotten, would destroy all the following steps.

The following is preprocessing/hpgl0840/scripts/05trim-hpgl0840.sh

This job has a little bit of logic in it in case trimomatic fails.

## This call to trimomatic removes illumina and epicentre adapters from hpgl0840_forward.fastq.gz:hpgl0840_reverse.fastq.gz.
## It also performs a sliding window removal of anything with quality <25;
## cutadapt provides an alternative to this tool.
## The original sequence data is recompressed and saved in the sequences/ directory.

## Trimomatic_Pairwise: In case a trimming needs to be redone...
if [[ ! -r "hpgl0840_forward.fastq.gz" ]]; then
  if [[ -r "sequences/hpgl0840_forward.fastq.xz" ]]; then
    mv sequences/hpgl0840_forward.fastq.xz . && pxz -d hpgl0840_forward.fastq.xz && pigz hpgl0840_forward.fastq &&\
       mv sequences/hpgl0840_reverse.fastq.xz . && pxz -d hpgl0840_reverse.fastq.xz && pigz hpgl0840_reverse.fastq
  else
    echo "Missing files. Did not find hpgl0840_forward.fastq.gz nor sequences/hpgl0840_forward.fastq.xz"
    exit 1
  fi
fi
## Note that trimomatic prints all output and errors to STDERR, so send both to output
trimomatic PE -threads 1 -phred33 hpgl0840_forward.fastq.gz hpgl0840_reverse.fastq.gz hpgl0840_forward-trimmed_paired.fastq.gz hpgl0840_forward-trimmed_unpaired.fastq.gz hpgl0840_reverse-trimmed_paired.fastq.gz hpgl0840_reverse-trimmed_unpaired.fastq.gz \
    ILLUMINACLIP:/cbcbhomes/abelew/libraries/adapters.fa:2:20:4 SLIDINGWINDOW:4:25 \
    1>outputs/hpgl0840-trimomatic.out 2>&1
excepted=$(grep "Exception" outputs/hpgl0840-trimomatic.out)
## The following is in case the illumina clipping fails, which it does if this has already been run I think.
if [[ "${excepted}" != "" ]]; then
  trimomatic PE -threads 1 -phred33 hpgl0840_forward.fastq.gz hpgl0840_reverse.fastq.gz hpgl0840_forward-trimmed_paired.fastq.gz hpgl0840_forward-trimmed_unpaired.fastq.gz hpgl0840_reverse-trimmed_paired.fastq.gz hpgl0840_reverse-trimmed_unpaired.fastq.gz SLIDINGWINDOW:4:25 \
    1>outputs/hpgl0840-trimomatic.out 2>&1
fi
sleep 10
mv hpgl0840_forward-trimmed_paired.fastq.gz hpgl0840_forward-trimmed.fastq.gz && mv hpgl0840_reverse-trimmed_paired.fastq.gz hpgl0840_reverse-trimmed.fastq.gz

4.2.1 Trimomatic statistics

In the same way, the text output of trimomatic is parsed to generate some statistics.

The following is preprocessing/hpgl0840/scripts/06trimst-hpgl0840.sh

## This is a stupidly simple job to collect trimomatic statistics

if [ ! -r outputs/trimomatic_stats.csv ]; then
  echo "total_reads,surviving_both,surviving_forward,surviving_reverse,dropped_reads" > outputs/trimomatic_stats.csv
fi
total_reads_tmp=$(grep "^Input Read Pairs" outputs/hpgl0840-trimomatic.out | awk '{print $4}')
total_reads=${total_reads_tmp:-0}
surviving_both_tmp=$(grep "^Input Read Pairs" outputs/hpgl0840-trimomatic.out | awk '{print $7}')
surviving_both=${surviving_both_tmp:-0}
surviving_forward_tmp=$(grep "^Input Read Pairs" outputs/hpgl0840-trimomatic.out | awk '{print $12}')
surviving_forward=${surviving_forward_tmp:-0}
surviving_reverse_tmp=$(grep "^Input Read Pairs" outputs/hpgl0840-trimomatic.out | awk '{print $17}')
surviving_reverse=${surviving_reverse_tmp:-0}
dropped_reads_tmp=$(grep "^Input Read Pairs" outputs/hpgl0840-trimomatic.out | awk '{print $20}')
dropped_reads=${dropped_reads_tmp:-0}

stat_string=$(printf "hpgl0840,%s,%s,%s,%s,%s" "${total_reads}" "${surviving_both}" "${surviving_forward}" "${surviving_reverse}" "${dropped_reads}")
echo "$stat_string" >> outputs/trimomatic_stats.csv

4.3 Biopieces

Biopieces is an interesting project to provide a suite of simple tools which may be connected to perform interesting tasks. I use it to plot some graphs of the sequencing quality/attributes.

The following is preprocessing/hpgl0840/scripts/02biop-hpgl0840trimmed.sh

## This script uses biopieces to draw some simple graphs of the sequence.

## Do not forget that _only_ the last command in a biopieces string is allowed to have the -x.
mkdir -p outputs/biopieces
less hpgl0840_reverse-trimmed.fastq | read_fastq -i - -e base_33 |\
 plot_scores -T 'Quality Scores' -t svg -o outputs/biopieces/hpgl0840_reverse-trimmed_quality_scores.svg |\
 plot_nucleotide_distribution -T 'NT. Distribution' -t svg -o outputs/biopieces/hpgl0840_reverse-trimmed_ntdist.svg |\
 plot_lendist -T 'Length Distribution' -k SEQ_LEN -t svg -o outputs/biopieces/hpgl0840_reverse-trimmed_lendist.svg |\
 analyze_gc |\
     bin_vals -b 20 -k 'GC%' |\
     plot_distribution -k 'GC%_BIN' -t svg -o outputs/biopieces/hpgl0840_reverse-trimmed_gcdist.svg |\
 analyze_gc |\
     mean_vals -k 'GC%' -o outputs/biopieces/hpgl0840_reverse-trimmed_gc.txt |\
 count_records -o outputs/biopieces/hpgl0840_reverse-trimmed_count.txt -x

4.4 Kallisto Mouse

Kallisto is a super-fast aligner for estimating relative transcript abundance. I increasingly think it is better than tophat.

I added a little logic to simplify its output to provide a count table-like file.

The following is preprocessing/hpgl0840/scripts/30kall_mmusculus-hpgl0840trimmed.sh

## This is a kallisto pseudoalignment of hpgl0840_forward-trimmed.fastq.gz hpgl0840_reverse-trimmed.fastq.gz against
## /cbcbhomes/abelew/libraries/genome/indexes/mmusculus.idx.
## This jobs depended on:
## Other candidates for making a pretty count table include:
##  perl -F'\t' -a -n -e 'print "$F[0] $F[3]\n"' outputs/kallisto_mmusculus/abundance.tsv > outputs/kallisto_mmusculus/abundance.count
##   awk '{printf("%s %s\n", $1, $4)}' outputs/kallisto_mmusculus/abundance.tsv > outputs/kallisto_mmusculus/abundance.count
## because kallisto is so fast

mkdir -p outputs/kallisto_mmusculus && sleep 10 && \
  kallisto quant  --plaintext -b 100 -o outputs/kallisto_mmusculus -i /cbcbhomes/abelew/libraries/genome/indexes/mmusculus.idx \
    hpgl0840_forward-trimmed.fastq.gz hpgl0840_reverse-trimmed.fastq.gz 2>outputs/kallisto_mmusculus/kallisto_mmusculus.stderr 1>outputs/kallisto_mmusculus/kallisto_mmusculus.txt && \
  cut -d "  " -f 1,4 outputs/kallisto_mmusculus/abundance.tsv > outputs/kallisto_mmusculus/abundance.count && \
  gzip outputs/kallisto_mmusculus/abundance.count && xz -9e *.tsv

I currently do not have a job to create kallisto statistics, which is dumb, fix that.

4.5 Tophat Mouse

This step is where I started to see that something is strange in the data. But before I get into a discussion of what is odd, here is a tophat invocation:

Note that the example is actually from hpgl0850 because 840 is promastigote and unlikely to be interesting for the mouse genome (though I did run it for that sample).

There is a little bit of interesting logic in this:

  1. I make sure to sort the accepted_hits.bam because it is annoying to not be able to look at these in IGV.
  2. I take an extra step to extract the perfectly paired aligned reads (The samtools view -b -f 2 line). In the best case scenario, this removes nothing.

The following is preprocessing/hpgl0850/scripts/31th_mmusculus-hpgl0850trimmed.sh

## I still have no clue what I am doing when I use tophat...
## However, I know that -g 1 will allow only 1 hit in the case of multihits, but randomly place it
## From the manual:  "If there are more alignments with the same score than this
## number, TopHat will randomly report only this many alignments"
## -N 1 will discard anything with >1 mismatch (default is 2)
## -r adjusts the allowable mean distance between the paired reads
## --mate-std-dev sets the deviation of -r
## --microexon-search will tell it to search short exons for reads >=50

mkdir -p outputs/tophat_mmusculus && tophat  -g 1 --b2-very-sensitive  \
  -G /cbcbhomes/abelew/libraries/genome/mmusculus.gtf \
  -p 4 -o outputs/tophat_mmusculus \
  /cbcbhomes/abelew/libraries/genome/indexes/mmusculus \
  hpgl0850_forward-trimmed.fastq.gz hpgl0850_reverse-trimmed.fastq.gz 2>outputs/tophat.out 1>&2 && \
 samtools sort -l 9 -n outputs/tophat_mmusculus/accepted_hits.bam outputs/tophat_mmusculus/accepted_sorted && \
 mv outputs/tophat_mmusculus/accepted_sorted.bam outputs/tophat_mmusculus/accepted_hits.bam && \
 samtools index outputs/tophat_mmusculus/accepted_hits.bam && \
 samtools sort -l 9 -n outputs/tophat_mmusculus/unmapped.bam outputs/tophat_mmusculus/unmapped_sorted && \
 mv outputs/tophat_mmusculus/unmapped_sorted.bam outputs/tophat_mmusculus/unmapped.bam && \
 samtools index outputs/tophat_mmusculus/unmapped.bam

if [ -r "outputs/tophat_mmusculus/accepted_hits.bam" ]; then
  samtools view -b -f 2 outputs/tophat_mmusculus/accepted_hits.bam > outputs/tophat_mmusculus/accepted_paired.bam && \
    samtools index outputs/tophat_mmusculus/accepted_paired.bam
fi

For my initial run, I left all the defaults in place and aligned against all reads in the sample. My first moment of worry therefore happened when I looked at the alignment statistics, for hpgl0850 they are:

Keep in mind that hpgl0850 is a 12 hour infected PMN sample, I therefore assumed a significant majority of the full set of reads would map to the mouse genome.

Left reads: Input : 5557510 Mapped : 253591 ( 4.6% of input) of these: 15051 ( 5.9%) have multiple alignments (36717 have >1) Right reads: Input : 5557510 Mapped : 386499 ( 7.0% of input) of these: 15051 ( 3.9%) have multiple alignments (56680 have >1) 5.8% overall read mapping rate.

Aligned pairs: 183046 of these: 15051 ( 8.2%) have multiple alignments 30642 (16.7%) are discordant alignments 2.7% concordant pair alignment rate.

Clearly this is not true, I think I will be able to answer the why in a little bit…

4.5.1 Tophat statistics

I generate a similar csv file for the tophat alignments:

The following is preprocessing/hpgl0850/scripts/33tpstats_mmusculus-hpgl0850trimmed.sh

## This is a stupidly simple job to collect tophat alignment statistics.

if [ ! -r outputs/tophat_stats.csv ]; then
  echo "basename,species,original_reads,aligned_reads,failed_reads,rpm,count_table" > outputs/tophat_stats.csv
fi
bamtools stats < outputs/tophat_mmusculus/accepted_hits.bam 2>outputs/tophat_mmusculus/accepted_hits.bam.stats 1>&2 && bamtools stats < outputs/tophat_mmusculus/unmapped.bam 2>outputs/tophat_mmusculus/unmapped.bam.stats 1>&2
original_reads_tmp=$(grep "^Input Reads" outputs/hpgl0850-trimmed-trimomatic.out | awk '{print $3}' | sed 's/ //g')
original_reads=${original_reads_tmp:-0}
reads_tmp=$(grep "^reads_in " outputs/tophat_mmusculus/prep_reads.info | awk -F= '{print $2}' | sed 's/ //g')
reads=${reads_tmp:-0}
aligned_tmp=$(grep "^Total reads" outputs/tophat_mmusculus/accepted_hits.bam.stats | awk '{print $3}' | sed 's/ .*//g')
aligned=${aligned_tmp:-0}
failed_tmp=$(grep "^Total reads" outputs/tophat_mmusculus/unmapped.bam.stats | awk '{print $3}' | sed 's/ .*//g')
failed=${failed_tmp:-0}
rpm_tmp=$(perl -e "printf(1000000 / ${aligned})" 2>/dev/null)
rpm=${rpm_tmp:-0}
stat_string=$(printf "hpgl0850-trimmed,mmusculus,%s,%s,%s,%s,%s,accepted_hits.count.xz" "${original_reads}" "${reads}" "${aligned}" "${failed}" "$rpm")
echo "$stat_string" >> outputs/tophat_stats.csv

4.5.2 HTSeq for tophat in M.musculus

I usually use htseq’s default parameters against the perfectly paired reads when making count tables from tophat mappings, in this data set, that might be a bad choice.

It is worth noting that when possible (as it is for the mouse genome), I do separate countings for the following feature types: 3’ UTRs, 5’ UTRs, exons, rRNA, snRNA, snoRNA, pseudogenes, lincRNA, miRNA, NMD targets, introns, antisense transcripts, retained introns, exons, genes, and all.

But I will show only the all script, as in most cases that is all we care about.

The following is preprocessing/hpgl0850/scripts/32htall_mmusculus-hpgl0840trimmed.sh

## Counting the number of hits in outputs/tophat_mmusculus/accepted_paired.bam for each feature found in /cbcbhomes/abelew/libraries/genome/mmusculus_all.gtf
## Is this stranded? yes.  The defaults of htseq are:
##  --order=name --idattr=gene_id --minaqual=10 --type=exon --stranded=yes --mode=union

htseq-count -q -f bam -s yes -i ID  -t exon \
  outputs/tophat_mmusculus/accepted_paired.bam /cbcbhomes/abelew/libraries/genome/mmusculus_all.gtf \
  1>outputs/htseq/accepted_paired_all.count 2>outputs/tophat_mmusculus/accepted_paired_htseq.err && \
    xz -f -9e outputs/htseq/accepted_paired_all.count

4.6 Tophat L.major

This is the same as above, but using my indexes/genome for Leishmania major from the TriTrypDb version 27.

4.7 Bowtie2 L.major

Here is where things get interesting and I started to figure out what is wrong.

I did a little reading and found the following about how bowtie2 scores multi-hit reads:

Taken from: http://biofinysics.blogspot.com/2014/05/how-does-bowtie2-assign-mapq-scores.html#bt2expt

“In bowtie2, the best a true multiread (AS=XS) can get is MAPQ=1 regardless of how low or high its multiplicity. This occurs when there are 0 or 1 mismatches over perfect base calls in the read, or when AS=XS goes down to -6. When there are 2-5 mismatches over perfect base calls (or the AS=XS <= -12 —- i.e. -12 to -30.6), the MAPQ becomes 0.

If someone wanted to exclude “true multireads” from their data set, using MAPQ >= 2 would work. This would also exclude any uniquely mapping reads with >=4 mismatches over high quality bases. In terms of high quality bases and unireads, MAPQ >= 3 allows up to 3 mismatches, MAPQ >= 23 allows up to 2 mismatches, MAPQ >= 40 allows up to 1 mismatch, and MAPQ >= 42 allows 0 mismatches. There will also be other “maxireads” in most or all of these sets."

This is relevant because of the following gem in the newest version of the htseq-count documentation:

http://www-huber.embl.de/HTSeq/doc/count.html

“skip all reads with alignment quality lower than the given minimum value (default: 10 — Note: the default used to be 0 until version 0.5.4.)”

With that in mind, take a look at the bowtie2 script, The following is preprocessing/scripts/hpgl0850/15bt2_lmajor-hpgl0850trimmed.sh

## This is a bowtie2 alignment of  -1 hpgl0850_forward-trimmed.fastq -2 hpgl0850_reverse-trimmed.fastq  against
## /cbcbhomes/abelew/libraries/genome/indexes/lmajor using arguments:  --very-sensitive .
## This jobs depended on: 1319885.cbcbsrv.umiacs.umd.edu

mkdir -p outputs/bowtie2_lmajor && sleep 10 && bowtie2 -x /cbcbhomes/abelew/libraries/genome/indexes/lmajor  --very-sensitive  \
  -p 1 \
  -q   -1 hpgl0850_forward-trimmed.fastq -2 hpgl0850_reverse-trimmed.fastq  \
  --un outputs/bowtie2_lmajor/hpgl0850-trimmed_unaligned_lmajor.fastq \
  --al outputs/bowtie2_lmajor/hpgl0850-trimmed_aligned_lmajor.fastq \
  -S outputs/bowtie2_lmajor/hpgl0850-trimmed.sam \
  2>outputs/bowtie2_lmajor/hpgl0850-trimmed.err \
  1>outputs/bowtie2_lmajor/hpgl0850-trimmed.out

4.7.1 Converting to an indexed sorted bam alignment

I hate sam files, so I immediately convert them before counting:

Just like with tophat, I have an extra step to extract the properly paired aligned reads.

The following is preprocessing/scripts/hpgl0850/19s2b_bt2_lmajor-hpgl0850trimmed.shell

## Converting the text sam to a compressed, sorted, indexed bamfile.
## Also printing alignment statistics to outputs/bowtie2_lmajor/hpgl0840-trimmed.bam.stats
## This job depended on: 1323883.cbcbsrv.umiacs.umd.edu
samtools view -u -t /cbcbhomes/abelew/libraries/genome/lmajor.fasta \
  -S outputs/bowtie2_lmajor/hpgl0840-trimmed.sam -o outputs/bowtie2_lmajor/hpgl0840-trimmed.bam 1>outputs/bowtie2_lmajor/hpgl0840-trimmed.bam.out 2>&1
samtools sort -l 9 outputs/bowtie2_lmajor/hpgl0840-trimmed.bam -o outputs/bowtie2_lmajor/hpgl0840-trimmed-sorted.bam 2>outputs/bowtie2_lmajor/hpgl0840-trimmed-sorted.bam.out 1>&2 && \
  rm outputs/bowtie2_lmajor/hpgl0840-trimmed.bam && \
  rm outputs/bowtie2_lmajor/hpgl0840-trimmed.sam && \
  mv outputs/bowtie2_lmajor/hpgl0840-trimmed-sorted.bam outputs/bowtie2_lmajor/hpgl0840-trimmed.bam && \
  samtools index outputs/bowtie2_lmajor/hpgl0840-trimmed.bam && \
  samtools view -b -f 2 -o outputs/bowtie2_lmajor/hpgl0840-trimmed.bam_paired.bam outputs/bowtie2_lmajor/hpgl0840-trimmed.bam && \
  samtools index outputs/bowtie2_lmajor/hpgl0840-trimmed.bam_paired.bam
bamtools stats -in outputs/bowtie2_lmajor/hpgl0840-trimmed.bam 2>outputs/bowtie2_lmajor/hpgl0840-trimmed.bam.stats 1>&2 && \
  bamtools stats -in outputs/bowtie2_lmajor/hpgl0840-trimmed.bam_paired.bam 2>outputs/bowtie2_lmajor/hpgl0840-trimmed.bam_paired.bam.stats 1>&2

4.7.2 Counting the bowtie2 results

In the following block, I am actually going to print my test data set’s script. In the test data, I took just the first 25,000 reads. I will follow that up with a small section of the count table generated from it.

I think this will show where the wheels fell off the car.

There is an important caveat related to the note I pasted above. In the following script I added the ‘-a 1’ argument, which tells htseq to count all pairs with alignment qualities >= 1 rather than the default of 10.

## Counting the number of hits in outputs/bowtie2_lmajor/test-trimmed.bam for each feature found in /cbcbhomes/abelew/libraries/genome/lmajor.gff
## Is this stranded? yes.  The defaults of htseq are:
##  --order=name --idattr=gene_id --minaqual=10 --type=exon --stranded=yes --mode=union

htseq-count -q -f bam -s yes  -i ID  -t exon -a 1 \
  outputs/bowtie2_lmajor/test-trimmed.bam /cbcbhomes/abelew/libraries/genome/lmajor.gff \
  1>outputs/bowtie2_lmajor/test-trimmed.count 2>outputs/bowtie2_lmajor/test-trimmed_htseq.err && \
    xz -f -9e outputs/bowtie2_lmajor/test-trimmed.count

Here are a few representative lines from the resulting count table, the main thing to recall is that in most of our data sets, the L. major rRNA genes are mostly excluded, and the genes surrounding the rRNA loci are usually 3-10x higher in counts:

exon_LmjF.27.2590-1     1
exon_LmjF.27.2600-1     0
exon_LmjF.27.2610-1     0
exon_LmjF.27.2620-1     0
exon_LmjF.27.2630-1     0
exon_LmjF.27.2640-1     0
exon_LmjF.27.2650-1     0
exon_LmjF.27.2660-1     0
exon_LmjF.27.ncRNA1-1   0
exon_LmjF.27.rRNA.01-1  1298
exon_LmjF.27.rRNA.02-1  1388
exon_LmjF.27.rRNA.03-1  1365
exon_LmjF.27.rRNA.04-1  1437
exon_LmjF.27.rRNA.05-1  1343
exon_LmjF.27.rRNA.06-1  1410

Oh crap. I did not see these in my first run because htseq is dropping them all as (I think) many of them are multi-hitting to a significant subset of the 52 tandem rRNA loci in the L. major genome.

LS0tCnRpdGxlOiAiTC5tYWpvciAyMDE4OiBNb3VzZSBQTU4gcHJlcHJvY2Vzc2luZy4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgbGlicmFyeShocGdsdG9vbHMpCiAgdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCiAga25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9OTAsCiAgICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQogIGtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD04LAogICAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCiAgb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKICBnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEwKSkKICB2ZXIgPC0gIjIwMTgwNDAyIgogIHByZXZpb3VzX2ZpbGUgPC0gImluZGV4LlJtZCIKCiAgdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkpCiAgcm1kX2ZpbGUgPC0gImluZGV4LlJtZCIKfQpgYGAKClByZXByb2Nlc3Npbmcgc29tZSBwZWN1bGlhciBzYW1wbGVzLgo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMgU2VwYXJhdGluZyBzYW1wbGVzIGJ5IGhwZ2wgaWRlbnRpZmllcgoKTmFqaWIgcHJvdmlkZWQgYSBzZXJpZXMgb2YgaGlzIHRyYWRpdGlvbmFsIGhwZ2wgaWRlbnRpZmllcnMgZm9yIHRoaXMgZGF0YSBzZXQuCkkgdGhlcmVmb3JlIG1hbnVhbGx5IGNvcGllZCBvdXQgdGhlIHNhbXBsZXMgYnkgc2VxdWVuY2UgZmlsZSBuYW1lcyBpbiB0aGUKcnVuMDM5NSBhbmQgcnVuMDM5NiBkaXJlY3RvcmllcyBpbnRvIHRoZSBhcHByb3ByaWF0ZSBkaXJlY3Rvcmllcy4gIFRoaXMgaXMKdGhlcmVmb3JlIGFuIG9idmlvdXMgcG90ZW50aWFsIHNvdXJjZSBvZiBlcnJvci4gIEkgdGhlcmVmb3JlIGRpZCB0aGlzIHdpdGggYQpzZWNvbmQgcGVyc29uIHdhdGNoaW5nICh0aGFua3MsIFlvYW5uISkgYW5kIGNoZWNrZWQgZWFjaCBzYW1wbGUgMiB0aW1lcyBiZWZvcmUKbW92aW5nIGZvcndhcmQuCgojIyBOZXcgc2FtcGxlcwoKMjAxODA0MDI6ICBUaGUgZm9sa3MgYXQgdGhlIFNhY2tzIGxhYiBraW5kbHkgcHJvdmlkZWQgYSBuZXcgc2V0IG9mIHNhbXBsZXMsIGZvcgp3aGljaCBOYWppYiBwcm92aWRlZCBhIGZyZXNoIHNldCBvZiBJRHMgKEhQR0wxMDY1LTEwODgpLiAgSSBkaWQgdGhlIHNhbWUgdGFza3MKdXNpbmcgdGhlIHNhbXBsZSBzaGVldCBoZSBwcm92aWRlZCBtZS4gIFRoZSBzb3VyY2Ugb2YgaHVtYW4gZXJyb3IgcmVtYWlucywgSSBkaWQKZG91YmxlLWNoZWNrIG15IHdvcmssIGJ1dCBodW1hbiBlcnJvciBpbiBjb3B5aW5nIHJlbWFpbnMgYSBwb3NzaWJpbGl0eS4KCkZvciBlYWNoIGhwZ2wgaWRlbnRpZmllciwgSSBkaWQgdGhlIGZvbGxvd2luZzoKCjEuICBDaGVjayB0aGUgc2FtcGxlIHNoZWV0IGFuZCBjb3B5IHRoZSBmaWxlcyBpbiBsYW5lMS9sYW5lMiBjb3JyZXNwb25kaW5nIHRvCiAgICB0aGUgMTMyKiBpZGVudGlmaWVyIHRvIHRoZSBjb3JyZXNwb25kaW5nIEhQR0wgaWRlbnRpZmllciBkaXJlY3RvcnkuCjIuICBjZCBpbnRvIGVhY2ggSFBHTCBkaXJlY3RvcnkgLyB1bnByb2Nlc3NlZCBhbmQ6CiAgIGEuICBjcCAxMzIqX0wwMDFfUjEqIGhwZ2x4eHh4X2ZvcndhcmQuZmFzdHEuZ3oKICAgYi4gIGNhdCAxMzIqUjEqID4+IGhwZ2x4eHh4X2ZvcndhcmQuZmFzdHEuZ3ogKE5vdGUgSSBkaWQgbm90IGRvIDEzMipSMSogYXMKICAgdGhhdCB3b3VsZCBiZSByZWR1bmRhbnQsIGJ1dCBpbnN0ZWFkIHVzZWQgdGFiIGNvbXBsZXRpb24gaW4gYmFzaCB0byBwaWNrIHVwCiAgIHRoZSBjb3JyZWN0IGZpbGVuYW1lcy4gIEkgZGlkIGh1bWFuIGVycm9yIHRoZSBzZWNvbmQgZGlyZWN0b3J5IGJ1dCBoYXBwaWx5CiAgIG5vdGljZWQgaXQgaW1tZWRpYXRlbHkgYW5kIGRvIG5vdCB0aGluayBJIG1lc3NlZCB1cCBhbnkgdGhlcmVhZnRlci4KICAgYy4gIGNwIDEzMipMMDAxX1IyKiBocGdseHh4eF9yZXZlcnNlLmZhc3RxLmd6CiAgIGQuICBjYXQgMTMyKlIyKiA+PiBocGdseHh4eF9yZXZlcnNlLmZhc3RxLmd6CgpPbmNlIEkgZmluaXNoZWQgdGhpcywgaW52b2tlZCBjeW9hIHdpdGggb3B0aW9ucyBhcHByb3ByaWF0ZSBmb3IgdHJpbW1pbmcvZmFzdHFjOgoKYGBge2Jhc2ggY29weWluZywgZXZhbD1GQUxTRX0KY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIGZhc3RxYyAtLWlucHV0IGhwZ2x4eHh4X2ZvcndhcmQuZmFzdHEuZ3o6aHBnbHh4eHhfcmV2ZXJzZS5mYXN0cS5negpjeW9hIC0tdGFzayBybmFzZXEgLS1tZXRob2QgdHJpbSAtLWlucHV0IGhwZ2x4eHh4X2ZvcndhcmQuZmFzdHEuZ3o6aHBnbHh4eHhfcmV2ZXJzZS5mYXN0cS5negpgYGAKCiMgUHJlcHJvY2Vzc2luZyBieSBzYW1wbGUKClRoZSBwcmVwcm9jZXNzaW5nIG9mIHRoaXMgZGF0YSBoYXBwZW5lZCBpbiB0d28gcGFydHMgYW5kIHdhcyBwZXJmb3JtZWQgdmlhIHRoZQpjeW9hIHNjcmlwdCwgd2hpY2ggYXR0ZW1wdHMgdG8gc2ltcGxpZnkgdGhlIGNyZWF0aW9uIG9mIGpvYnMgb24gb3VyIGNvbXB1dGVyCmNsdXN0ZXIuCgpJIHNwbGl0IHRoZSBwcmVwcm9jZXNzaW5nIHRhc2tzIGludG8gdHdvIHBhcnRzLCB0aGUgZmlyc3QgcGFydCBjb25zaXN0cyBvZiB0aGUKaW5pdGlhbCBzZXF1ZW5jaW5nIHF1YWxpdHkgYXNzdXJhbmNlIGFuZCBhZGFwdGVyIHRyaW1taW5nLgoKIyMgUGFydCAxCgpUaGUgZm9sbG93aW5nIGlzIGNvbnRhaW5lZCBpbiBhIHNoZWxsIHNjcmlwdCBpbiBwcmVwcm9jZXNzaW5nLyBjYWxsZWQgcHJvY2Vzc19wYXJ0MS5zaAoKYGBge3IgcGFydDEsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMhL3Vzci9iaW4vZW52IGJhc2gKc3RhcnQ9JChwd2QpCmZvciBpIGluICQoL2Jpbi9scyAtZCBocGdsKik7IGRvCiAgY2QgJHtpfQogIGVjaG8gIlN0YXJ0aW5nICR7aX0iCiAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIHRyaW1vbSAtLWlucHV0ICR7aX1fZm9yd2FyZC5mYXN0cS5nejoke2l9X3JldmVyc2UuZmFzdHEuZ3oKICBjeW9hIC0tdGFzayBybmFzZXEgLS1tZXRob2QgZmFzdHEgLS1pbnB1dCAke2l9X2ZvcndhcmQuZmFzdHEuZ3o6JHtpfV9yZXZlcnNlLmZhc3RxLmd6CiAgZWNobyAiRmluaXNoaW5nICR7aX0iCiAgY2QgJHtzdGFydH0KZG9uZQpgYGAKCiMjIFBhcnQgMgoKT25jZSB0aGUgc2VxdWVuY2UgYWRhcHRlcnMgd2VyZSByZW1vdmVkLCBJIHBlcmZvcm0gdGhlIHNldCBvZiB0YXNrcyB3aGljaCBkZXBlbmQKb24gdGhlIHRyaW1tZWQgZGF0YS4gIEl0IGlzIHdvcnRoIG5vdGluZyB0aGF0IEkgdHJpZWQgdHdvIChwc2V1ZG8pYWxpZ25lcnMgZm9yCnRoZSBtb3VzZSBnZW5vbWUsIHRvcGhhdCBhbmQga2FsbGlzdG87IGFuZCB0d28gYWxpZ25lcnMgZm9yIHRoZSBwYXJhc2l0ZQpnZW5vbWVzLCB0b3BoYXQgYW5kIGJvd3RpZTIuCgpJbiBhZGRpdGlvbiwgSSBhdHRlbXB0ZWQgYWxpZ25tZW50cyBhZ2FpbnN0IEwubWFqb3IgYW5kIEwuYW1hem9uZW5zaXMuICBNeQpyZWFzb25pbmcgd2lsbCBiZWNvbWUgY2xlYXIgc29vbiBJIHRoaW5rLgoKYGBge3IgcGFydDIsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMhL3Vzci9iaW4vZW52IGJhc2gKc3RhcnQ9JChwd2QpCmZvciBpIGluICQoL2Jpbi9scyAtZCBocGdsMDg0WzAtMl0pOyBkbwogIGNkICIke2l9IiB8fCBleGl0CiAgZWNobyAiU3RhcnRpbmcgJHtpfSIKICBjeW9hIC0tdGFzayBybmFzZXEgLS1tZXRob2QgYmlvcGllY2UgLS1pbnB1dCAiJHtpfV9mb3J3YXJkLXRyaW1tZWQuZmFzdHEuZ3o6JHtpfV9yZXZlcnNlLXRyaW1tZWQuZmFzdHEuZ3oiCiAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIGthbGxpc3RvIC0taW5wdXQgIiR7aX1fZm9yd2FyZC10cmltbWVkLmZhc3RxLmd6OiR7aX1fcmV2ZXJzZS10cmltbWVkLmZhc3RxLmd6IiAtLXNwZWNpZXMgbW11c2N1bHVzCiAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIHRvcGhhdCAtLWlucHV0ICIke2l9X2ZvcndhcmQtdHJpbW1lZC5mYXN0cS5nejoke2l9X3JldmVyc2UtdHJpbW1lZC5mYXN0cS5neiIgLS1zcGVjaWVzIG1tdXNjdWx1cyAtLWh0c2VxX3R5cGUgZXhvbiAtLWh0c2VxX3N0cmFuZGVkIHllcwogIGN5b2EgLS10YXNrIHJuYXNlcSAtLW1ldGhvZCBidDIgLS1pbnB1dCAiJHtpfV9mb3J3YXJkLXRyaW1tZWQuZmFzdHEuZ3o6JHtpfV9yZXZlcnNlLXRyaW1tZWQuZmFzdHEuZ3oiIC0tc3BlY2llcyBsYW1hem9uZW5zaXMgLS1odHNlcV90eXBlIGV4b24gLS1odHNlcV9zdHJhbmRlZCB5ZXMKICBjeW9hIC0tdGFzayBybmFzZXEgLS1tZXRob2QgYnQyIC0taW5wdXQgIiR7aX1fZm9yd2FyZC10cmltbWVkLmZhc3RxLmd6OiR7aX1fcmV2ZXJzZS10cmltbWVkLmZhc3RxLmd6IiAtLXNwZWNpZXMgbG1ham9yIC0taHRzZXFfdHlwZSBleG9uIC0taHRzZXFfc3RyYW5kZWQgeWVzCiAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIHRvcGhhdCAtLWlucHV0ICIke2l9X2ZvcndhcmQtdHJpbW1lZC5mYXN0cS5nejoke2l9X3JldmVyc2UtdHJpbW1lZC5mYXN0cS5neiIgLS1zcGVjaWVzIGxtYWpvciAtLWh0c2VxX3R5cGUgZXhvbiAtLWh0c2VxX3N0cmFuZGVkIHllcwogIGVjaG8gIkZpbmlzaGluZyAke2l9IgogIGNkICIke3N0YXJ0fSIgfHwgZXhpdApkb25lCmBgYAoKIyBXaGF0IGhhcHBlbmVkIGluIGVhY2ggc3RlcD8KClRoZSBjeW9hIHNjcmlwdCBpbiB0dXJuIGNyZWF0ZXMgYW5kIGV4ZWN1dGVzIGpvYnMgb24gb3VyIHRvcnF1ZSBjbHVzdGVyLCBJIGFtCmNvcHkvcGFzdGluZyB0aGVtIGJlbG93OgoKVHdvIGNhdmVhdHM6CgoxLiAgVGhlcmUgaXMgYSBjb21tb24gaGVhZGVyIGFuZCBmb290ZXIgZm9yIGFsbCBvZiB0aGVzZSBzY3JpcHRzLiAgSSB3aWxsCiAgICBpbmNsdWRlIGl0IGZvciB0aGlzIHNjcmlwdCwgYnV0IHNraXAgaXQgZm9yIHRoZSBmb2xsb3dpbmc6CjIuICBJIGFtIGdvaW5nIHRvIHByaW50IGhlcmUgYSBjb3B5IG9mIG15IHNjcmlwdCBmb3IgZWFjaCBzdGVwIGZvciB0aGUgZmlyc3QKICAgIHNhbXBsZSBhbmQgbGVhdmUgYXMgYW4gZXhlcmNpc2UgZm9yIHRoZSByZWFkZXIgdGhlIHJlc3QuCgojIyBGYXN0cWMKClRoZSBmaXJzdCBzdGVwIGluIG1vc3QoYWxsKSBvZiBvdXIgZGF0YSBzZXRzIGlzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBzZXF1ZW5jZXIKcHJvdmlkZWQgaGlnaC1xdWFsaXR5IGRhdGEgYXQgdGhlIGV4cGVjdGVkIGxlbmd0aChzKS4KClRoZXJlIGlzIG9ubHkgb25lIGludGVyZXN0aW5nIHBvaW50IGluIHRoaXMgc2NyaXB0LCB0aGUgLS1leHRyYWN0IGFyZ3VtZW50IHdhcwpwcm92aWRlZCBzbyB0aGF0IGEgZGVwZW5kZW50IGpvYiBtYXkgYmUgcnVuIGluIG9yZGVyIHRvIGV4dHJhY3Qgc29tZSBzdGF0aXN0aWNzCmZyb20gdGhlIGZhc3RxYyByZXN1bHRzLgoKVGhlIGZvbGxvd2luZyBpcyBwcmVwcm9jZXNzaW5nL2hwZ2wwNDgwL3NjcmlwdHMvMDBmcWMtaHBnbDA4NDAuc2gKCmBgYHtyIGZhc3RxYywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyEvdXNyL2Jpbi9lbnYgYmFzaAojUEJTIC1WIC1TIC91c3IvYmluL2Jhc2ggLXEgd29ya3N0YXRpb24KI1BCUyAtZCAvY2JjYi9uZWxzYXllZC1zY3JhdGNoL2F0Yi9ybmFzZXEvbG1ham9yX3NheC9wcmVwcm9jZXNzaW5nL2hwZ2wwODQwCiNQQlMgLU4gZnFjLWhwZ2wwODQwIC1sIG1lbT02Z2IgLWwgd2FsbHRpbWU9MTA6MDA6MDAgLWwgbmNwdXM9OAojUEJTIC1vIC9jYmNiL25lbHNheWVkLXNjcmF0Y2gvYXRiL3JuYXNlcS9sbWFqb3Jfc2F4L3ByZXByb2Nlc3NpbmcvaHBnbDA4NDAvb3V0cHV0cy9xc3ViL2ZxYy1ocGdsMDg0MC5xc3Vib3V0IC1qIG9lIC1WIC1tIG4KZWNobyAiIyMjI1N0YXJ0ZWQgL2NiY2IvbmVsc2F5ZWQtc2NyYXRjaC9hdGIvcm5hc2VxL2xtYWpvcl9zYXgvcHJlcHJvY2Vzc2luZy9ocGdsMDg0MC9zY3JpcHRzLzAwZnFjLWhwZ2wwODQwLnNoIGF0ICQoZGF0ZSkiID4+IG91dHB1dHMvbG9nLnR4dApjZCAvY2JjYi9uZWxzYXllZC1zY3JhdGNoL2F0Yi9ybmFzZXEvbG1ham9yX3NheC9wcmVwcm9jZXNzaW5nL2hwZ2wwODQwIHx8IGV4aXQKCiMjIFRoaXMgRmFzdFFDIHJ1biBpcyBhZ2FpbnN0IHJuYXNlcSBkYXRhIGFuZCBpcyB1c2VkIGZvcgojIyBhbiBpbml0aWFsIGVzdGltYXRpb24gb2YgdGhlIG92ZXJhbGwgc2VxdWVuY2luZyBxdWFsaXR5Lgpta2RpciAtcCBvdXRwdXRzL2Zhc3RxYyAmJiBcCiAgZmFzdHFjIC0tZXh0cmFjdCAtbyBvdXRwdXRzL2Zhc3RxYyBocGdsMDg0MF9mb3J3YXJkLmZhc3RxLmd6IGhwZ2wwODQwX3JldmVyc2UuZmFzdHEuZ3ogXAogIDI+b3V0cHV0cy9mYXN0cWMub3V0IDE+JjIKCiMjIFRoZSBmb2xsb3dpbmcgbGluZXMgZ2l2ZSBzdGF0dXMgY29kZXMgYW5kIHNvbWUgbG9nZ2luZwplY2hvICQ/ID4gb3V0cHV0cy9zdGF0dXMvZnFjLWhwZ2wwODQwLnN0YXR1cwplY2hvICIjIyNGaW5pc2hlZCAke1BCU19KT0JJRH0gMDBmcWMtaHBnbDA4NDAuc2ggYXQgJChkYXRlKSwgaXQgdG9vayAkKCggU0VDT05EUyAvIDYwICkpIG1pbnV0ZXMuIiA+PiBvdXRwdXRzL2xvZy50eHQKCndhbGx0aW1lPSQocXN0YXQgLWYgLXQgIiR7UEJTX0pPQklEfSIgfCBncmVwICdyZXNvdXJjZXNfdXNlZC53YWxsdGltZScgfCBhd2sgLUYgJyA9ICcgJ3twcmludCAkMn0nKQplY2hvICIjIyMjUEJTIHdhbGx0aW1lIHVzZWQgYnkgJHtQQlNfSk9CSUR9IHdhczogJHt3YWxsdGltZTotbnVsbH0iID4+IG91dHB1dHMvbG9nLnR4dAptZW09JChxc3RhdCAtZiAtdCB8IGdyZXAgIiR7UEJTX0pPQklEfSIgfCBncmVwICdyZXNvdXJjZXNfdXNlZC5tZW0nIHwgYXdrIC1GICcgPSAnICd7cHJpbnQgJDJ9JykKZWNobyAiIyMjI1BCUyBtZW1vcnkgdXNlZCBieSAke1BCU19KT0JJRH0gd2FzOiAke21lbTotbnVsbH0iID4+IG91dHB1dHMvbG9nLnR4dAp2bW1lbW9yeT0kKHFzdGF0IC1mIC10ICIke1BCU19KT0JJRH0iIHwgZ3JlcCAncmVzb3VyY2VzX3VzZWQudm1lbScgfCBhd2sgLUYgJyA9ICcgJ3twcmludCAkMn0nKQplY2hvICIjIyMjUEJTIHZtZW1vcnkgdXNlZCBieSAke1BCU19KT0JJRH0gd2FzOiAke3ZtbWVtb3J5Oi1udWxsfSIgPj4gb3V0cHV0cy9sb2cudHh0CmNwdXRpbWU9JChxc3RhdCAtZiAtdCAiJHtQQlNfSk9CSUR9IiB8IGdyZXAgJ3Jlc291cmNlc191c2VkLmNwdXQnIHwgYXdrIC1GICcgPSAnICd7cHJpbnQgJDJ9JykKZWNobyAiIyMjI1BCUyBjcHV0aW1lIHVzZWQgYnkgJHtQQlNfSk9CSUR9IHdhczogJHtjcHV0aW1lOi1udWxsfSIgPj4gb3V0cHV0cy9sb2cudHh0CiMjcXN0YXQgLWYgLXQgJHtQQlNfSk9CSUR9ID4+IG91dHB1dHMvbG9nLnR4dApgYGAKCiMjIyBGYXN0cWMgc3RhdGlzdGljcwoKVGhlIGZhc3RxYyBzdGF0aXN0aWNzIGFyZSBnZW5lcmF0ZWQgc2VwYXJhdGVseSBmb3IgdGhlIGZvcndhcmQvcmV2ZXJzZSByZWFkcy4KClRoZSBmb2xsb3dpbmcgaXMgcHJlcHJvY2Vzc2luZy9ocGdsMDQ4MC9zY3JpcHRzLzAxZnFjc3RfZm9yd2FyZC1ocGdsMDg0MC5zaAoKYGBge3IgZmFzdHFjX3N0YXRzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIyBUaGlzIGlzIGEgc3R1cGlkbHkgc2ltcGxlIGpvYiB0byBjb2xsZWN0IGFsaWdubWVudCBzdGF0aXN0aWNzLgoKaWYgWyAhIC1yIG91dHB1dHMvZmFzdHFjX2ZvcndhcmRfc3RhdHMuY3N2IF07IHRoZW4KICBlY2hvICJuYW1lLHRvdGFsX3JlYWRzLHBvb3JfcXVhbGl0eSxwZXJfcXVhbGl0eSxwZXJfYmFzZV9jb250ZW50LHBlcl9zZXF1ZW5jZV9nYyxwZXJfYmFzZV9uLHBlcl9zZXFfbGVuZ3RoLG92ZXJfcmVwLGFkYXB0ZXJfY29udGVudCxrbWVyX2NvbnRlbnQiID4gb3V0cHV0cy9mYXN0cWNfZm9yd2FyZF9zdGF0cy5jc3YKZmkKdG90YWxfcmVhZHNfdG1wPSQoZ3JlcCAiXlRvdGFsIFNlcXVlbmNlcyIgb3V0cHV0cy9mYXN0cWMvaHBnbDA4NDBfZm9yd2FyZC5nel9mYXN0cWMvZmFzdHFjX2RhdGEudHh0IHwgYXdrIC1GICdcXHQnICd7cHJpbnQgJDJ9JykKdG90YWxfcmVhZHM9JHt0b3RhbF9yZWFkc190bXA6LTB9CnBvb3JfcXVhbGl0eV90bXA9JChncmVwICJeU2VxdWVuY2VzIGZsYWdnZWQgYXMgcG9vciBxdWFsaXR5IiBvdXRwdXRzL2Zhc3RxYy9ocGdsMDg0MF9mb3J3YXJkLmd6X2Zhc3RxYy9mYXN0cWNfZGF0YS50eHQgfCBhd2sgLUYgJ1xcdCcgJ3twcmludCAkMn0nKQpwb29yX3F1YWxpdHk9JHtwb29yX3F1YWxpdHlfdG1wOi0wfQpwZXJfcXVhbGl0eV90bXA9JChncmVwICJQZXIgYmFzZSBzZXF1ZW5jZSBxdWFsaXR5IiBvdXRwdXRzL2Zhc3RxYy9ocGdsMDg0MF9mb3J3YXJkLmd6X2Zhc3RxYy9mYXN0cWNfZGF0YS50eHQgfCBhd2sgLUYgJ1xcdCcgJ3twcmludCAkMn0nKQpwZXJfcXVhbGl0eT0ke3Blcl9xdWFsaXR5X3RtcDotMH0KcGVyX2Jhc2VfY29udGVudF90bXA9JChncmVwICJQZXIgYmFzZSBzZXF1ZW5jZSBjb250ZW50IiBvdXRwdXRzL2Zhc3RxYy9ocGdsMDg0MF9mb3J3YXJkLmd6X2Zhc3RxYy9mYXN0cWNfZGF0YS50eHQgfCBhd2sgLUYgJ1xcdCcgJ3twcmludCAkMn0nKQpwZXJfYmFzZV9jb250ZW50PSR7cGVyX2Jhc2VfY29udGVudF90bXA6LTB9CnBlcl9zZXF1ZW5jZV9nY190bXA9JChncmVwICJQZXIgc2VxdWVuY2UgR0MgY29udGVudCIgb3V0cHV0cy9mYXN0cWMvaHBnbDA4NDBfZm9yd2FyZC5nel9mYXN0cWMvZmFzdHFjX2RhdGEudHh0IHwgYXdrIC1GICdcXHQnICd7cHJpbnQgJDJ9JykKcGVyX3NlcXVlbmNlX2djPSR7cGVyX3NlcXVlbmNlX2djX3RtcDotMH0KcGVyX2Jhc2Vfbl90bXA9JChncmVwICJQZXIgYmFzZSBOIGNvbnRlbnQiIG91dHB1dHMvZmFzdHFjL2hwZ2wwODQwX2ZvcndhcmQuZ3pfZmFzdHFjL2Zhc3RxY19kYXRhLnR4dCB8IGF3ayAtRiAnXFx0JyAne3ByaW50ICQyfScpCnBlcl9iYXNlX249JHtwZXJfYmFzZV9uX3RtcDotMH0KcGVyX3NlcV9sZW5ndGhfdG1wPSQoZ3JlcCAiU2VxdWVuY2UgTGVuZ3RoIERpc3RyaWJ1dGlvbiIgb3V0cHV0cy9mYXN0cWMvaHBnbDA4NDBfZm9yd2FyZC5nel9mYXN0cWMvZmFzdHFjX2RhdGEudHh0IHwgYXdrIC1GICdcXHQnICd7cHJpbnQgJDJ9JykKcGVyX3NlcV9sZW5ndGg9JHtwZXJfc2VxX2xlbmd0aF90bXA6LTB9Cm92ZXJfcmVwX3RtcD0kKGdyZXAgIk92ZXJyZXByZXNlbnRlZCBzZXF1ZW5jZXMiIG91dHB1dHMvZmFzdHFjL2hwZ2wwODQwX2ZvcndhcmQuZ3pfZmFzdHFjL2Zhc3RxY19kYXRhLnR4dCB8IGF3ayAtRiAnXFx0JyAne3ByaW50ICQyfScpCm92ZXJfcmVwPSR7b3Zlcl9yZXBfdG1wOi0wfQphZGFwdGVyX2NvbnRlbnRfdG1wPSQoZ3JlcCAiQWRhcHRlciBDb250ZW50IiBvdXRwdXRzL2Zhc3RxYy9ocGdsMDg0MF9mb3J3YXJkLmd6X2Zhc3RxYy9mYXN0cWNfZGF0YS50eHQgfCBhd2sgLUYgJ1xcdCcgJ3twcmludCAkMn0nKQphZGFwdGVyX2NvbnRlbnQ9JHthZGFwdGVyX2NvbnRlbnRfdG1wOi0wfQprbWVyX2NvbnRlbnRfdG1wPSQoZ3JlcCAiS21lciBDb250ZW50IiBvdXRwdXRzL2Zhc3RxYy9ocGdsMDg0MF9mb3J3YXJkLmd6X2Zhc3RxYy9mYXN0cWNfZGF0YS50eHQgfCBhd2sgLUYgJ1xcdCcgJ3twcmludCAkMn0nKQprbWVyX2NvbnRlbnQ9JHtrbWVyX2NvbnRlbnRfdG1wOi0wfQoKc3RhdF9zdHJpbmc9JChwcmludGYgImhwZ2wwODQwLCVzLCVzLCVzLCVzLCVzLCVzLCVzLCVzLCVzLCVzIiAiJHt0b3RhbF9yZWFkc30iICIke3Bvb3JfcXVhbGl0eX0iICIke3Blcl9xdWFsaXR5fSIgIiR7cGVyX2Jhc2VfY29udGVudH0iICIke3Blcl9zZXF1ZW5jZV9nY30iICIke3Blcl9iYXNlX259IiAiJHtwZXJfc2VxX2xlbmd0aH0iICIke292ZXJfcmVwfSIgIiR7YWRhcHRlcl9jb250ZW50fSIgIiR7a21lcl9jb250ZW50fSIpCmVjaG8gIiRzdGF0X3N0cmluZyIgPj4gb3V0cHV0cy9mYXN0cWNfZm9yd2FyZF9zdGF0cy5jc3YKYGBgCgojIyBUcmltb21hdGljCgpUcmltb21hdGljIGlzIHBlcmhhcHMgdGhlIG1vc3QgaW1wb3J0YW50IHN0ZXAgaW4gdGhlIHByb2Nlc3MsIGFzIGl0IHJlbW92ZXMgdGhlCnNvbWV0aW1lcyB2ZXJ5IGFidW5kYW50IHNlcXVlbmNpbmcgYWRhcHRlcnMsIHdoaWNoIGlmIGZvcmdvdHRlbiwgd291bGQgZGVzdHJveQphbGwgdGhlIGZvbGxvd2luZyBzdGVwcy4KClRoZSBmb2xsb3dpbmcgaXMgcHJlcHJvY2Vzc2luZy9ocGdsMDg0MC9zY3JpcHRzLzA1dHJpbS1ocGdsMDg0MC5zaAoKVGhpcyBqb2IgaGFzIGEgbGl0dGxlIGJpdCBvZiBsb2dpYyBpbiBpdCBpbiBjYXNlIHRyaW1vbWF0aWMgZmFpbHMuCgpgYGB7ciB0cmltb21hdGljLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIyBUaGlzIGNhbGwgdG8gdHJpbW9tYXRpYyByZW1vdmVzIGlsbHVtaW5hIGFuZCBlcGljZW50cmUgYWRhcHRlcnMgZnJvbSBocGdsMDg0MF9mb3J3YXJkLmZhc3RxLmd6OmhwZ2wwODQwX3JldmVyc2UuZmFzdHEuZ3ouCiMjIEl0IGFsc28gcGVyZm9ybXMgYSBzbGlkaW5nIHdpbmRvdyByZW1vdmFsIG9mIGFueXRoaW5nIHdpdGggcXVhbGl0eSA8MjU7CiMjIGN1dGFkYXB0IHByb3ZpZGVzIGFuIGFsdGVybmF0aXZlIHRvIHRoaXMgdG9vbC4KIyMgVGhlIG9yaWdpbmFsIHNlcXVlbmNlIGRhdGEgaXMgcmVjb21wcmVzc2VkIGFuZCBzYXZlZCBpbiB0aGUgc2VxdWVuY2VzLyBkaXJlY3RvcnkuCgojIyBUcmltb21hdGljX1BhaXJ3aXNlOiBJbiBjYXNlIGEgdHJpbW1pbmcgbmVlZHMgdG8gYmUgcmVkb25lLi4uCmlmIFtbICEgLXIgImhwZ2wwODQwX2ZvcndhcmQuZmFzdHEuZ3oiIF1dOyB0aGVuCiAgaWYgW1sgLXIgInNlcXVlbmNlcy9ocGdsMDg0MF9mb3J3YXJkLmZhc3RxLnh6IiBdXTsgdGhlbgogICAgbXYgc2VxdWVuY2VzL2hwZ2wwODQwX2ZvcndhcmQuZmFzdHEueHogLiAmJiBweHogLWQgaHBnbDA4NDBfZm9yd2FyZC5mYXN0cS54eiAmJiBwaWd6IGhwZ2wwODQwX2ZvcndhcmQuZmFzdHEgJiZcCiAgICAgICBtdiBzZXF1ZW5jZXMvaHBnbDA4NDBfcmV2ZXJzZS5mYXN0cS54eiAuICYmIHB4eiAtZCBocGdsMDg0MF9yZXZlcnNlLmZhc3RxLnh6ICYmIHBpZ3ogaHBnbDA4NDBfcmV2ZXJzZS5mYXN0cQogIGVsc2UKICAgIGVjaG8gIk1pc3NpbmcgZmlsZXMuIERpZCBub3QgZmluZCBocGdsMDg0MF9mb3J3YXJkLmZhc3RxLmd6IG5vciBzZXF1ZW5jZXMvaHBnbDA4NDBfZm9yd2FyZC5mYXN0cS54eiIKICAgIGV4aXQgMQogIGZpCmZpCiMjIE5vdGUgdGhhdCB0cmltb21hdGljIHByaW50cyBhbGwgb3V0cHV0IGFuZCBlcnJvcnMgdG8gU1RERVJSLCBzbyBzZW5kIGJvdGggdG8gb3V0cHV0CnRyaW1vbWF0aWMgUEUgLXRocmVhZHMgMSAtcGhyZWQzMyBocGdsMDg0MF9mb3J3YXJkLmZhc3RxLmd6IGhwZ2wwODQwX3JldmVyc2UuZmFzdHEuZ3ogaHBnbDA4NDBfZm9yd2FyZC10cmltbWVkX3BhaXJlZC5mYXN0cS5neiBocGdsMDg0MF9mb3J3YXJkLXRyaW1tZWRfdW5wYWlyZWQuZmFzdHEuZ3ogaHBnbDA4NDBfcmV2ZXJzZS10cmltbWVkX3BhaXJlZC5mYXN0cS5neiBocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWRfdW5wYWlyZWQuZmFzdHEuZ3ogXAogICAgSUxMVU1JTkFDTElQOi9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9hZGFwdGVycy5mYToyOjIwOjQgU0xJRElOR1dJTkRPVzo0OjI1IFwKICAgIDE+b3V0cHV0cy9ocGdsMDg0MC10cmltb21hdGljLm91dCAyPiYxCmV4Y2VwdGVkPSQoZ3JlcCAiRXhjZXB0aW9uIiBvdXRwdXRzL2hwZ2wwODQwLXRyaW1vbWF0aWMub3V0KQojIyBUaGUgZm9sbG93aW5nIGlzIGluIGNhc2UgdGhlIGlsbHVtaW5hIGNsaXBwaW5nIGZhaWxzLCB3aGljaCBpdCBkb2VzIGlmIHRoaXMgaGFzIGFscmVhZHkgYmVlbiBydW4gSSB0aGluay4KaWYgW1sgIiR7ZXhjZXB0ZWR9IiAhPSAiIiBdXTsgdGhlbgogIHRyaW1vbWF0aWMgUEUgLXRocmVhZHMgMSAtcGhyZWQzMyBocGdsMDg0MF9mb3J3YXJkLmZhc3RxLmd6IGhwZ2wwODQwX3JldmVyc2UuZmFzdHEuZ3ogaHBnbDA4NDBfZm9yd2FyZC10cmltbWVkX3BhaXJlZC5mYXN0cS5neiBocGdsMDg0MF9mb3J3YXJkLXRyaW1tZWRfdW5wYWlyZWQuZmFzdHEuZ3ogaHBnbDA4NDBfcmV2ZXJzZS10cmltbWVkX3BhaXJlZC5mYXN0cS5neiBocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWRfdW5wYWlyZWQuZmFzdHEuZ3ogU0xJRElOR1dJTkRPVzo0OjI1IFwKICAgIDE+b3V0cHV0cy9ocGdsMDg0MC10cmltb21hdGljLm91dCAyPiYxCmZpCnNsZWVwIDEwCm12IGhwZ2wwODQwX2ZvcndhcmQtdHJpbW1lZF9wYWlyZWQuZmFzdHEuZ3ogaHBnbDA4NDBfZm9yd2FyZC10cmltbWVkLmZhc3RxLmd6ICYmIG12IGhwZ2wwODQwX3JldmVyc2UtdHJpbW1lZF9wYWlyZWQuZmFzdHEuZ3ogaHBnbDA4NDBfcmV2ZXJzZS10cmltbWVkLmZhc3RxLmd6CmBgYAoKIyMjIFRyaW1vbWF0aWMgc3RhdGlzdGljcwoKSW4gdGhlIHNhbWUgd2F5LCB0aGUgdGV4dCBvdXRwdXQgb2YgdHJpbW9tYXRpYyBpcyBwYXJzZWQgdG8gZ2VuZXJhdGUgc29tZQpzdGF0aXN0aWNzLgoKVGhlIGZvbGxvd2luZyBpcyBwcmVwcm9jZXNzaW5nL2hwZ2wwODQwL3NjcmlwdHMvMDZ0cmltc3QtaHBnbDA4NDAuc2gKCmBgYHtyIHRyaW1vbWF0aWNfc3RhdHMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIFRoaXMgaXMgYSBzdHVwaWRseSBzaW1wbGUgam9iIHRvIGNvbGxlY3QgdHJpbW9tYXRpYyBzdGF0aXN0aWNzCgppZiBbICEgLXIgb3V0cHV0cy90cmltb21hdGljX3N0YXRzLmNzdiBdOyB0aGVuCiAgZWNobyAidG90YWxfcmVhZHMsc3Vydml2aW5nX2JvdGgsc3Vydml2aW5nX2ZvcndhcmQsc3Vydml2aW5nX3JldmVyc2UsZHJvcHBlZF9yZWFkcyIgPiBvdXRwdXRzL3RyaW1vbWF0aWNfc3RhdHMuY3N2CmZpCnRvdGFsX3JlYWRzX3RtcD0kKGdyZXAgIl5JbnB1dCBSZWFkIFBhaXJzIiBvdXRwdXRzL2hwZ2wwODQwLXRyaW1vbWF0aWMub3V0IHwgYXdrICd7cHJpbnQgJDR9JykKdG90YWxfcmVhZHM9JHt0b3RhbF9yZWFkc190bXA6LTB9CnN1cnZpdmluZ19ib3RoX3RtcD0kKGdyZXAgIl5JbnB1dCBSZWFkIFBhaXJzIiBvdXRwdXRzL2hwZ2wwODQwLXRyaW1vbWF0aWMub3V0IHwgYXdrICd7cHJpbnQgJDd9JykKc3Vydml2aW5nX2JvdGg9JHtzdXJ2aXZpbmdfYm90aF90bXA6LTB9CnN1cnZpdmluZ19mb3J3YXJkX3RtcD0kKGdyZXAgIl5JbnB1dCBSZWFkIFBhaXJzIiBvdXRwdXRzL2hwZ2wwODQwLXRyaW1vbWF0aWMub3V0IHwgYXdrICd7cHJpbnQgJDEyfScpCnN1cnZpdmluZ19mb3J3YXJkPSR7c3Vydml2aW5nX2ZvcndhcmRfdG1wOi0wfQpzdXJ2aXZpbmdfcmV2ZXJzZV90bXA9JChncmVwICJeSW5wdXQgUmVhZCBQYWlycyIgb3V0cHV0cy9ocGdsMDg0MC10cmltb21hdGljLm91dCB8IGF3ayAne3ByaW50ICQxN30nKQpzdXJ2aXZpbmdfcmV2ZXJzZT0ke3N1cnZpdmluZ19yZXZlcnNlX3RtcDotMH0KZHJvcHBlZF9yZWFkc190bXA9JChncmVwICJeSW5wdXQgUmVhZCBQYWlycyIgb3V0cHV0cy9ocGdsMDg0MC10cmltb21hdGljLm91dCB8IGF3ayAne3ByaW50ICQyMH0nKQpkcm9wcGVkX3JlYWRzPSR7ZHJvcHBlZF9yZWFkc190bXA6LTB9CgpzdGF0X3N0cmluZz0kKHByaW50ZiAiaHBnbDA4NDAsJXMsJXMsJXMsJXMsJXMiICIke3RvdGFsX3JlYWRzfSIgIiR7c3Vydml2aW5nX2JvdGh9IiAiJHtzdXJ2aXZpbmdfZm9yd2FyZH0iICIke3N1cnZpdmluZ19yZXZlcnNlfSIgIiR7ZHJvcHBlZF9yZWFkc30iKQplY2hvICIkc3RhdF9zdHJpbmciID4+IG91dHB1dHMvdHJpbW9tYXRpY19zdGF0cy5jc3YKYGBgCgojIyBCaW9waWVjZXMKCkJpb3BpZWNlcyBpcyBhbiBpbnRlcmVzdGluZyBwcm9qZWN0IHRvIHByb3ZpZGUgYSBzdWl0ZSBvZiBzaW1wbGUgdG9vbHMgd2hpY2ggbWF5CmJlIGNvbm5lY3RlZCB0byBwZXJmb3JtIGludGVyZXN0aW5nIHRhc2tzLiAgSSB1c2UgaXQgdG8gcGxvdCBzb21lIGdyYXBocyBvZiB0aGUKc2VxdWVuY2luZyBxdWFsaXR5L2F0dHJpYnV0ZXMuCgpUaGUgZm9sbG93aW5nIGlzIHByZXByb2Nlc3NpbmcvaHBnbDA4NDAvc2NyaXB0cy8wMmJpb3AtaHBnbDA4NDB0cmltbWVkLnNoCgpgYGB7ciBiaW9waWVjZXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIFRoaXMgc2NyaXB0IHVzZXMgYmlvcGllY2VzIHRvIGRyYXcgc29tZSBzaW1wbGUgZ3JhcGhzIG9mIHRoZSBzZXF1ZW5jZS4KCiMjIERvIG5vdCBmb3JnZXQgdGhhdCBfb25seV8gdGhlIGxhc3QgY29tbWFuZCBpbiBhIGJpb3BpZWNlcyBzdHJpbmcgaXMgYWxsb3dlZCB0byBoYXZlIHRoZSAteC4KbWtkaXIgLXAgb3V0cHV0cy9iaW9waWVjZXMKbGVzcyBocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWQuZmFzdHEgfCByZWFkX2Zhc3RxIC1pIC0gLWUgYmFzZV8zMyB8XAogcGxvdF9zY29yZXMgLVQgJ1F1YWxpdHkgU2NvcmVzJyAtdCBzdmcgLW8gb3V0cHV0cy9iaW9waWVjZXMvaHBnbDA4NDBfcmV2ZXJzZS10cmltbWVkX3F1YWxpdHlfc2NvcmVzLnN2ZyB8XAogcGxvdF9udWNsZW90aWRlX2Rpc3RyaWJ1dGlvbiAtVCAnTlQuIERpc3RyaWJ1dGlvbicgLXQgc3ZnIC1vIG91dHB1dHMvYmlvcGllY2VzL2hwZ2wwODQwX3JldmVyc2UtdHJpbW1lZF9udGRpc3Quc3ZnIHxcCiBwbG90X2xlbmRpc3QgLVQgJ0xlbmd0aCBEaXN0cmlidXRpb24nIC1rIFNFUV9MRU4gLXQgc3ZnIC1vIG91dHB1dHMvYmlvcGllY2VzL2hwZ2wwODQwX3JldmVyc2UtdHJpbW1lZF9sZW5kaXN0LnN2ZyB8XAogYW5hbHl6ZV9nYyB8XAogICAgIGJpbl92YWxzIC1iIDIwIC1rICdHQyUnIHxcCiAgICAgcGxvdF9kaXN0cmlidXRpb24gLWsgJ0dDJV9CSU4nIC10IHN2ZyAtbyBvdXRwdXRzL2Jpb3BpZWNlcy9ocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWRfZ2NkaXN0LnN2ZyB8XAogYW5hbHl6ZV9nYyB8XAogICAgIG1lYW5fdmFscyAtayAnR0MlJyAtbyBvdXRwdXRzL2Jpb3BpZWNlcy9ocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWRfZ2MudHh0IHxcCiBjb3VudF9yZWNvcmRzIC1vIG91dHB1dHMvYmlvcGllY2VzL2hwZ2wwODQwX3JldmVyc2UtdHJpbW1lZF9jb3VudC50eHQgLXgKYGBgCgojIyBLYWxsaXN0byBNb3VzZQoKS2FsbGlzdG8gaXMgYSBzdXBlci1mYXN0IGFsaWduZXIgZm9yIGVzdGltYXRpbmcgcmVsYXRpdmUgdHJhbnNjcmlwdCBhYnVuZGFuY2UuCkkgaW5jcmVhc2luZ2x5IHRoaW5rIGl0IGlzIGJldHRlciB0aGFuIHRvcGhhdC4KCkkgYWRkZWQgYSBsaXR0bGUgbG9naWMgdG8gc2ltcGxpZnkgaXRzIG91dHB1dCB0byBwcm92aWRlIGEgY291bnQgdGFibGUtbGlrZSBmaWxlLgoKVGhlIGZvbGxvd2luZyBpcyBwcmVwcm9jZXNzaW5nL2hwZ2wwODQwL3NjcmlwdHMvMzBrYWxsX21tdXNjdWx1cy1ocGdsMDg0MHRyaW1tZWQuc2gKCmBgYHtyIGthbGxpc3RvLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIyBUaGlzIGlzIGEga2FsbGlzdG8gcHNldWRvYWxpZ25tZW50IG9mIGhwZ2wwODQwX2ZvcndhcmQtdHJpbW1lZC5mYXN0cS5neiBocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWQuZmFzdHEuZ3ogYWdhaW5zdAojIyAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2luZGV4ZXMvbW11c2N1bHVzLmlkeC4KIyMgVGhpcyBqb2JzIGRlcGVuZGVkIG9uOgojIyBPdGhlciBjYW5kaWRhdGVzIGZvciBtYWtpbmcgYSBwcmV0dHkgY291bnQgdGFibGUgaW5jbHVkZToKIyMgIHBlcmwgLUYnXHQnIC1hIC1uIC1lICdwcmludCAiJEZbMF0gJEZbM11cbiInIG91dHB1dHMva2FsbGlzdG9fbW11c2N1bHVzL2FidW5kYW5jZS50c3YgPiBvdXRwdXRzL2thbGxpc3RvX21tdXNjdWx1cy9hYnVuZGFuY2UuY291bnQKIyMgICBhd2sgJ3twcmludGYoIiVzICVzXG4iLCAkMSwgJDQpfScgb3V0cHV0cy9rYWxsaXN0b19tbXVzY3VsdXMvYWJ1bmRhbmNlLnRzdiA+IG91dHB1dHMva2FsbGlzdG9fbW11c2N1bHVzL2FidW5kYW5jZS5jb3VudAojIyBiZWNhdXNlIGthbGxpc3RvIGlzIHNvIGZhc3QKCm1rZGlyIC1wIG91dHB1dHMva2FsbGlzdG9fbW11c2N1bHVzICYmIHNsZWVwIDEwICYmIFwKICBrYWxsaXN0byBxdWFudCAgLS1wbGFpbnRleHQgLWIgMTAwIC1vIG91dHB1dHMva2FsbGlzdG9fbW11c2N1bHVzIC1pIC9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9nZW5vbWUvaW5kZXhlcy9tbXVzY3VsdXMuaWR4IFwKICAgIGhwZ2wwODQwX2ZvcndhcmQtdHJpbW1lZC5mYXN0cS5neiBocGdsMDg0MF9yZXZlcnNlLXRyaW1tZWQuZmFzdHEuZ3ogMj5vdXRwdXRzL2thbGxpc3RvX21tdXNjdWx1cy9rYWxsaXN0b19tbXVzY3VsdXMuc3RkZXJyIDE+b3V0cHV0cy9rYWxsaXN0b19tbXVzY3VsdXMva2FsbGlzdG9fbW11c2N1bHVzLnR4dCAmJiBcCiAgY3V0IC1kICIJIiAtZiAxLDQgb3V0cHV0cy9rYWxsaXN0b19tbXVzY3VsdXMvYWJ1bmRhbmNlLnRzdiA+IG91dHB1dHMva2FsbGlzdG9fbW11c2N1bHVzL2FidW5kYW5jZS5jb3VudCAmJiBcCiAgZ3ppcCBvdXRwdXRzL2thbGxpc3RvX21tdXNjdWx1cy9hYnVuZGFuY2UuY291bnQgJiYgeHogLTllICoudHN2CmBgYAoKSSBjdXJyZW50bHkgZG8gbm90IGhhdmUgYSBqb2IgdG8gY3JlYXRlIGthbGxpc3RvIHN0YXRpc3RpY3MsIHdoaWNoIGlzIGR1bWIsIGZpeCB0aGF0LgoKIyMgVG9waGF0IE1vdXNlCgpUaGlzIHN0ZXAgaXMgd2hlcmUgSSBzdGFydGVkIHRvIHNlZSB0aGF0IHNvbWV0aGluZyBpcyBzdHJhbmdlIGluIHRoZSBkYXRhLgpCdXQgYmVmb3JlIEkgZ2V0IGludG8gYSBkaXNjdXNzaW9uIG9mIHdoYXQgaXMgb2RkLCBoZXJlIGlzIGEgdG9waGF0IGludm9jYXRpb246CgpOb3RlIHRoYXQgdGhlIGV4YW1wbGUgaXMgYWN0dWFsbHkgZnJvbSBocGdsMDg1MCBiZWNhdXNlIDg0MCBpcyBwcm9tYXN0aWdvdGUgYW5kCnVubGlrZWx5IHRvIGJlIGludGVyZXN0aW5nIGZvciB0aGUgbW91c2UgZ2Vub21lICh0aG91Z2ggSSBkaWQgcnVuIGl0IGZvciB0aGF0IHNhbXBsZSkuCgpUaGVyZSBpcyBhIGxpdHRsZSBiaXQgb2YgaW50ZXJlc3RpbmcgbG9naWMgaW4gdGhpczoKCjEuICBJIG1ha2Ugc3VyZSB0byBzb3J0IHRoZSBhY2NlcHRlZF9oaXRzLmJhbSBiZWNhdXNlIGl0IGlzIGFubm95aW5nIHRvIG5vdCBiZQogICAgYWJsZSB0byBsb29rIGF0IHRoZXNlIGluIElHVi4KMi4gIEkgdGFrZSBhbiBleHRyYSBzdGVwIHRvIGV4dHJhY3QgdGhlIHBlcmZlY3RseSBwYWlyZWQgYWxpZ25lZCByZWFkcyAoVGhlCiAgICBzYW10b29scyB2aWV3IC1iIC1mIDIgbGluZSkuICBJbiB0aGUgYmVzdCBjYXNlIHNjZW5hcmlvLCB0aGlzIHJlbW92ZXMgbm90aGluZy4KClRoZSBmb2xsb3dpbmcgaXMgcHJlcHJvY2Vzc2luZy9ocGdsMDg1MC9zY3JpcHRzLzMxdGhfbW11c2N1bHVzLWhwZ2wwODUwdHJpbW1lZC5zaAoKYGBge3IgdG9waGF0X21vdXNlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIyBJIHN0aWxsIGhhdmUgbm8gY2x1ZSB3aGF0IEkgYW0gZG9pbmcgd2hlbiBJIHVzZSB0b3BoYXQuLi4KIyMgSG93ZXZlciwgSSBrbm93IHRoYXQgLWcgMSB3aWxsIGFsbG93IG9ubHkgMSBoaXQgaW4gdGhlIGNhc2Ugb2YgbXVsdGloaXRzLCBidXQgcmFuZG9tbHkgcGxhY2UgaXQKIyMgRnJvbSB0aGUgbWFudWFsOiAgIklmIHRoZXJlIGFyZSBtb3JlIGFsaWdubWVudHMgd2l0aCB0aGUgc2FtZSBzY29yZSB0aGFuIHRoaXMKIyMgbnVtYmVyLCBUb3BIYXQgd2lsbCByYW5kb21seSByZXBvcnQgb25seSB0aGlzIG1hbnkgYWxpZ25tZW50cyIKIyMgLU4gMSB3aWxsIGRpc2NhcmQgYW55dGhpbmcgd2l0aCA+MSBtaXNtYXRjaCAoZGVmYXVsdCBpcyAyKQojIyAtciBhZGp1c3RzIHRoZSBhbGxvd2FibGUgbWVhbiBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBwYWlyZWQgcmVhZHMKIyMgLS1tYXRlLXN0ZC1kZXYgc2V0cyB0aGUgZGV2aWF0aW9uIG9mIC1yCiMjIC0tbWljcm9leG9uLXNlYXJjaCB3aWxsIHRlbGwgaXQgdG8gc2VhcmNoIHNob3J0IGV4b25zIGZvciByZWFkcyA+PTUwCgpta2RpciAtcCBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMgJiYgdG9waGF0ICAtZyAxIC0tYjItdmVyeS1zZW5zaXRpdmUgIFwKICAtRyAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL21tdXNjdWx1cy5ndGYgXAogIC1wIDQgLW8gb3V0cHV0cy90b3BoYXRfbW11c2N1bHVzIFwKICAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2luZGV4ZXMvbW11c2N1bHVzIFwKICBocGdsMDg1MF9mb3J3YXJkLXRyaW1tZWQuZmFzdHEuZ3ogaHBnbDA4NTBfcmV2ZXJzZS10cmltbWVkLmZhc3RxLmd6IDI+b3V0cHV0cy90b3BoYXQub3V0IDE+JjIgJiYgXAogc2FtdG9vbHMgc29ydCAtbCA5IC1uIG91dHB1dHMvdG9waGF0X21tdXNjdWx1cy9hY2NlcHRlZF9oaXRzLmJhbSBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfc29ydGVkICYmIFwKIG12IG91dHB1dHMvdG9waGF0X21tdXNjdWx1cy9hY2NlcHRlZF9zb3J0ZWQuYmFtIG91dHB1dHMvdG9waGF0X21tdXNjdWx1cy9hY2NlcHRlZF9oaXRzLmJhbSAmJiBcCiBzYW10b29scyBpbmRleCBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfaGl0cy5iYW0gJiYgXAogc2FtdG9vbHMgc29ydCAtbCA5IC1uIG91dHB1dHMvdG9waGF0X21tdXNjdWx1cy91bm1hcHBlZC5iYW0gb3V0cHV0cy90b3BoYXRfbW11c2N1bHVzL3VubWFwcGVkX3NvcnRlZCAmJiBcCiBtdiBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvdW5tYXBwZWRfc29ydGVkLmJhbSBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvdW5tYXBwZWQuYmFtICYmIFwKIHNhbXRvb2xzIGluZGV4IG91dHB1dHMvdG9waGF0X21tdXNjdWx1cy91bm1hcHBlZC5iYW0KCmlmIFsgLXIgIm91dHB1dHMvdG9waGF0X21tdXNjdWx1cy9hY2NlcHRlZF9oaXRzLmJhbSIgXTsgdGhlbgogIHNhbXRvb2xzIHZpZXcgLWIgLWYgMiBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfaGl0cy5iYW0gPiBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfcGFpcmVkLmJhbSAmJiBcCiAgICBzYW10b29scyBpbmRleCBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfcGFpcmVkLmJhbQpmaQpgYGAKCkZvciBteSBpbml0aWFsIHJ1biwgSSBsZWZ0IGFsbCB0aGUgZGVmYXVsdHMgaW4gcGxhY2UgYW5kIGFsaWduZWQgYWdhaW5zdCBhbGwKcmVhZHMgaW4gdGhlIHNhbXBsZS4gIE15IGZpcnN0IG1vbWVudCBvZiB3b3JyeSB0aGVyZWZvcmUgaGFwcGVuZWQgd2hlbiBJIGxvb2tlZAphdCB0aGUgYWxpZ25tZW50IHN0YXRpc3RpY3MsIGZvciBocGdsMDg1MCB0aGV5IGFyZToKCktlZXAgaW4gbWluZCB0aGF0IGhwZ2wwODUwIGlzIGEgMTIgaG91ciBpbmZlY3RlZCBQTU4gc2FtcGxlLCBJIHRoZXJlZm9yZSBhc3N1bWVkCmEgc2lnbmlmaWNhbnQgbWFqb3JpdHkgb2YgdGhlIGZ1bGwgc2V0IG9mIHJlYWRzIHdvdWxkIG1hcCB0byB0aGUgbW91c2UgZ2Vub21lLgoKTGVmdCByZWFkczoKICAgICAgICAgIElucHV0ICAgICA6ICAgNTU1NzUxMAogICAgICAgICAgIE1hcHBlZCAgIDogICAgMjUzNTkxICggNC42JSBvZiBpbnB1dCkKICAgICAgICAgICAgb2YgdGhlc2U6ICAgICAxNTA1MSAoIDUuOSUpIGhhdmUgbXVsdGlwbGUgYWxpZ25tZW50cyAoMzY3MTcgaGF2ZSA+MSkKUmlnaHQgcmVhZHM6CiAgICAgICAgICBJbnB1dCAgICAgOiAgIDU1NTc1MTAKICAgICAgICAgICBNYXBwZWQgICA6ICAgIDM4NjQ5OSAoIDcuMCUgb2YgaW5wdXQpCiAgICAgICAgICAgIG9mIHRoZXNlOiAgICAgMTUwNTEgKCAzLjklKSBoYXZlIG11bHRpcGxlIGFsaWdubWVudHMgKDU2NjgwIGhhdmUgPjEpCiA1LjglIG92ZXJhbGwgcmVhZCBtYXBwaW5nIHJhdGUuCgpBbGlnbmVkIHBhaXJzOiAgICAxODMwNDYKICAgICBvZiB0aGVzZTogICAgIDE1MDUxICggOC4yJSkgaGF2ZSBtdWx0aXBsZSBhbGlnbm1lbnRzCiAgICAgICAgICAgICAgICAgICAzMDY0MiAoMTYuNyUpIGFyZSBkaXNjb3JkYW50IGFsaWdubWVudHMKIDIuNyUgY29uY29yZGFudCBwYWlyIGFsaWdubWVudCByYXRlLgoKQ2xlYXJseSB0aGlzIGlzIG5vdCB0cnVlLCBJIHRoaW5rIEkgd2lsbCBiZSBhYmxlIHRvIGFuc3dlciB0aGUgd2h5IGluIGEgbGl0dGxlIGJpdC4uLgoKIyMjIFRvcGhhdCBzdGF0aXN0aWNzCgpJIGdlbmVyYXRlIGEgc2ltaWxhciBjc3YgZmlsZSBmb3IgdGhlIHRvcGhhdCBhbGlnbm1lbnRzOgoKVGhlIGZvbGxvd2luZyBpcyBwcmVwcm9jZXNzaW5nL2hwZ2wwODUwL3NjcmlwdHMvMzN0cHN0YXRzX21tdXNjdWx1cy1ocGdsMDg1MHRyaW1tZWQuc2gKCmBgYHtyIHN0YXRzX3RvcGhhdF9tbXVzY3VsdXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIFRoaXMgaXMgYSBzdHVwaWRseSBzaW1wbGUgam9iIHRvIGNvbGxlY3QgdG9waGF0IGFsaWdubWVudCBzdGF0aXN0aWNzLgoKaWYgWyAhIC1yIG91dHB1dHMvdG9waGF0X3N0YXRzLmNzdiBdOyB0aGVuCiAgZWNobyAiYmFzZW5hbWUsc3BlY2llcyxvcmlnaW5hbF9yZWFkcyxhbGlnbmVkX3JlYWRzLGZhaWxlZF9yZWFkcyxycG0sY291bnRfdGFibGUiID4gb3V0cHV0cy90b3BoYXRfc3RhdHMuY3N2CmZpCmJhbXRvb2xzIHN0YXRzIDwgb3V0cHV0cy90b3BoYXRfbW11c2N1bHVzL2FjY2VwdGVkX2hpdHMuYmFtIDI+b3V0cHV0cy90b3BoYXRfbW11c2N1bHVzL2FjY2VwdGVkX2hpdHMuYmFtLnN0YXRzIDE+JjIgJiYgYmFtdG9vbHMgc3RhdHMgPCBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvdW5tYXBwZWQuYmFtIDI+b3V0cHV0cy90b3BoYXRfbW11c2N1bHVzL3VubWFwcGVkLmJhbS5zdGF0cyAxPiYyCm9yaWdpbmFsX3JlYWRzX3RtcD0kKGdyZXAgIl5JbnB1dCBSZWFkcyIgb3V0cHV0cy9ocGdsMDg1MC10cmltbWVkLXRyaW1vbWF0aWMub3V0IHwgYXdrICd7cHJpbnQgJDN9JyB8IHNlZCAncy8gLy9nJykKb3JpZ2luYWxfcmVhZHM9JHtvcmlnaW5hbF9yZWFkc190bXA6LTB9CnJlYWRzX3RtcD0kKGdyZXAgIl5yZWFkc19pbiAiIG91dHB1dHMvdG9waGF0X21tdXNjdWx1cy9wcmVwX3JlYWRzLmluZm8gfCBhd2sgLUY9ICd7cHJpbnQgJDJ9JyB8IHNlZCAncy8gLy9nJykKcmVhZHM9JHtyZWFkc190bXA6LTB9CmFsaWduZWRfdG1wPSQoZ3JlcCAiXlRvdGFsIHJlYWRzIiBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfaGl0cy5iYW0uc3RhdHMgfCBhd2sgJ3twcmludCAkM30nIHwgc2VkICdzLyAuKi8vZycpCmFsaWduZWQ9JHthbGlnbmVkX3RtcDotMH0KZmFpbGVkX3RtcD0kKGdyZXAgIl5Ub3RhbCByZWFkcyIgb3V0cHV0cy90b3BoYXRfbW11c2N1bHVzL3VubWFwcGVkLmJhbS5zdGF0cyB8IGF3ayAne3ByaW50ICQzfScgfCBzZWQgJ3MvIC4qLy9nJykKZmFpbGVkPSR7ZmFpbGVkX3RtcDotMH0KcnBtX3RtcD0kKHBlcmwgLWUgInByaW50ZigxMDAwMDAwIC8gJHthbGlnbmVkfSkiIDI+L2Rldi9udWxsKQpycG09JHtycG1fdG1wOi0wfQpzdGF0X3N0cmluZz0kKHByaW50ZiAiaHBnbDA4NTAtdHJpbW1lZCxtbXVzY3VsdXMsJXMsJXMsJXMsJXMsJXMsYWNjZXB0ZWRfaGl0cy5jb3VudC54eiIgIiR7b3JpZ2luYWxfcmVhZHN9IiAiJHtyZWFkc30iICIke2FsaWduZWR9IiAiJHtmYWlsZWR9IiAiJHJwbSIpCmVjaG8gIiRzdGF0X3N0cmluZyIgPj4gb3V0cHV0cy90b3BoYXRfc3RhdHMuY3N2CmBgYAoKIyMjIEhUU2VxIGZvciB0b3BoYXQgaW4gTS5tdXNjdWx1cwoKSSB1c3VhbGx5IHVzZSBodHNlcSdzIGRlZmF1bHQgcGFyYW1ldGVycyBhZ2FpbnN0IHRoZSBwZXJmZWN0bHkgcGFpcmVkIHJlYWRzIHdoZW4KbWFraW5nIGNvdW50IHRhYmxlcyBmcm9tIHRvcGhhdCBtYXBwaW5ncywgaW4gdGhpcyBkYXRhIHNldCwgdGhhdCBtaWdodCBiZSBhIGJhZCBjaG9pY2UuCgpJdCBpcyB3b3J0aCBub3RpbmcgdGhhdCB3aGVuIHBvc3NpYmxlIChhcyBpdCBpcyBmb3IgdGhlIG1vdXNlIGdlbm9tZSksIEkgZG8Kc2VwYXJhdGUgY291bnRpbmdzIGZvciB0aGUgZm9sbG93aW5nIGZlYXR1cmUgdHlwZXM6CjMnIFVUUnMsIDUnIFVUUnMsIGV4b25zLCByUk5BLCBzblJOQSwgc25vUk5BLCBwc2V1ZG9nZW5lcywgbGluY1JOQSwgbWlSTkEsIE5NRAp0YXJnZXRzLCBpbnRyb25zLCBhbnRpc2Vuc2UgdHJhbnNjcmlwdHMsIHJldGFpbmVkIGludHJvbnMsIGV4b25zLCBnZW5lcywgYW5kCmFsbC4KCkJ1dCBJIHdpbGwgc2hvdyBvbmx5IHRoZSBhbGwgc2NyaXB0LCBhcyBpbiBtb3N0IGNhc2VzIHRoYXQgaXMgYWxsIHdlIGNhcmUgYWJvdXQuCgpUaGUgZm9sbG93aW5nIGlzIHByZXByb2Nlc3NpbmcvaHBnbDA4NTAvc2NyaXB0cy8zMmh0YWxsX21tdXNjdWx1cy1ocGdsMDg0MHRyaW1tZWQuc2gKCmBgYHtyIGh0c2VxX3RvcGhhdF9tbXVzY3VsdXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIENvdW50aW5nIHRoZSBudW1iZXIgb2YgaGl0cyBpbiBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfcGFpcmVkLmJhbSBmb3IgZWFjaCBmZWF0dXJlIGZvdW5kIGluIC9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9nZW5vbWUvbW11c2N1bHVzX2FsbC5ndGYKIyMgSXMgdGhpcyBzdHJhbmRlZD8geWVzLiAgVGhlIGRlZmF1bHRzIG9mIGh0c2VxIGFyZToKIyMgIC0tb3JkZXI9bmFtZSAtLWlkYXR0cj1nZW5lX2lkIC0tbWluYXF1YWw9MTAgLS10eXBlPWV4b24gLS1zdHJhbmRlZD15ZXMgLS1tb2RlPXVuaW9uCgpodHNlcS1jb3VudCAtcSAtZiBiYW0gLXMgeWVzIC1pIElEICAtdCBleG9uIFwKICBvdXRwdXRzL3RvcGhhdF9tbXVzY3VsdXMvYWNjZXB0ZWRfcGFpcmVkLmJhbSAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL21tdXNjdWx1c19hbGwuZ3RmIFwKICAxPm91dHB1dHMvaHRzZXEvYWNjZXB0ZWRfcGFpcmVkX2FsbC5jb3VudCAyPm91dHB1dHMvdG9waGF0X21tdXNjdWx1cy9hY2NlcHRlZF9wYWlyZWRfaHRzZXEuZXJyICYmIFwKICAgIHh6IC1mIC05ZSBvdXRwdXRzL2h0c2VxL2FjY2VwdGVkX3BhaXJlZF9hbGwuY291bnQKYGBgCgojIyBUb3BoYXQgTC5tYWpvcgoKVGhpcyBpcyB0aGUgc2FtZSBhcyBhYm92ZSwgYnV0IHVzaW5nIG15IGluZGV4ZXMvZ2Vub21lIGZvciBMZWlzaG1hbmlhIG1ham9yIGZyb20KdGhlIFRyaVRyeXBEYiB2ZXJzaW9uIDI3LgoKIyMgQm93dGllMiBMLm1ham9yCgpIZXJlIGlzIHdoZXJlIHRoaW5ncyBnZXQgaW50ZXJlc3RpbmcgYW5kIEkgc3RhcnRlZCB0byBmaWd1cmUgb3V0IHdoYXQgaXMgd3JvbmcuCgpJIGRpZCBhIGxpdHRsZSByZWFkaW5nIGFuZCBmb3VuZCB0aGUgZm9sbG93aW5nIGFib3V0IGhvdyBib3d0aWUyIHNjb3JlcwptdWx0aS1oaXQgcmVhZHM6CgpUYWtlbiBmcm9tOgpbaHR0cDovL2Jpb2ZpbnlzaWNzLmJsb2dzcG90LmNvbS8yMDE0LzA1L2hvdy1kb2VzLWJvd3RpZTItYXNzaWduLW1hcHEtc2NvcmVzLmh0bWwjYnQyZXhwdF0oaHR0cDovL2Jpb2ZpbnlzaWNzLmJsb2dzcG90LmNvbS8yMDE0LzA1L2hvdy1kb2VzLWJvd3RpZTItYXNzaWduLW1hcHEtc2NvcmVzLmh0bWwjYnQyZXhwdCkKCiJJbiBib3d0aWUyLCB0aGUgYmVzdCBhIHRydWUgbXVsdGlyZWFkIChBUz1YUykgY2FuIGdldCBpcyBNQVBRPTEgcmVnYXJkbGVzcyBvZgpob3cgbG93IG9yIGhpZ2ggaXRzIG11bHRpcGxpY2l0eS4gVGhpcyBvY2N1cnMgd2hlbiB0aGVyZSBhcmUgMCBvciAxIG1pc21hdGNoZXMKb3ZlciBwZXJmZWN0IGJhc2UgY2FsbHMgaW4gdGhlIHJlYWQsIG9yIHdoZW4gQVM9WFMgZ29lcyBkb3duIHRvIC02LiBXaGVuIHRoZXJlCmFyZSAyLTUgbWlzbWF0Y2hlcyBvdmVyIHBlcmZlY3QgYmFzZSBjYWxscyAob3IgdGhlIEFTPVhTIDw9IC0xMiAtLS0tIGkuZS4gLTEyIHRvCi0zMC42KSwgdGhlIE1BUFEgYmVjb21lcyAwLgoKSWYgc29tZW9uZSB3YW50ZWQgdG8gZXhjbHVkZSAidHJ1ZSBtdWx0aXJlYWRzIiBmcm9tIHRoZWlyIGRhdGEgc2V0LCB1c2luZyBNQVBRCj49IDIgd291bGQgd29yay4gVGhpcyB3b3VsZCBhbHNvIGV4Y2x1ZGUgYW55IHVuaXF1ZWx5IG1hcHBpbmcgcmVhZHMgd2l0aCA+PTQKbWlzbWF0Y2hlcyBvdmVyIGhpZ2ggcXVhbGl0eSBiYXNlcy4gSW4gdGVybXMgb2YgaGlnaCBxdWFsaXR5IGJhc2VzIGFuZCB1bmlyZWFkcywKTUFQUSA+PSAzIGFsbG93cyB1cCB0byAzIG1pc21hdGNoZXMsIE1BUFEgPj0gMjMgYWxsb3dzIHVwIHRvIDIgbWlzbWF0Y2hlcywgTUFQUQo+PSA0MCBhbGxvd3MgdXAgdG8gMSBtaXNtYXRjaCwgYW5kIE1BUFEgPj0gNDIgYWxsb3dzIDAgbWlzbWF0Y2hlcy4gVGhlcmUgd2lsbAphbHNvIGJlIG90aGVyICJtYXhpcmVhZHMiIGluIG1vc3Qgb3IgYWxsIG9mIHRoZXNlIHNldHMuIgoKVGhpcyBpcyByZWxldmFudCBiZWNhdXNlIG9mIHRoZSBmb2xsb3dpbmcgZ2VtIGluIHRoZSBuZXdlc3QgdmVyc2lvbiBvZiB0aGUKaHRzZXEtY291bnQgZG9jdW1lbnRhdGlvbjoKCltodHRwOi8vd3d3LWh1YmVyLmVtYmwuZGUvSFRTZXEvZG9jL2NvdW50Lmh0bWxdKGh0dHA6Ly93d3ctaHViZXIuZW1ibC5kZS9IVFNlcS9kb2MvY291bnQuaHRtbCkKCiJza2lwIGFsbCByZWFkcyB3aXRoIGFsaWdubWVudCBxdWFsaXR5IGxvd2VyIHRoYW4gdGhlIGdpdmVuIG1pbmltdW0gdmFsdWUKKGRlZmF1bHQ6IDEwIOKAlCBOb3RlOiB0aGUgZGVmYXVsdCB1c2VkIHRvIGJlIDAgdW50aWwgdmVyc2lvbiAwLjUuNC4pIgoKV2l0aCB0aGF0IGluIG1pbmQsIHRha2UgYSBsb29rIGF0IHRoZSBib3d0aWUyIHNjcmlwdCwKVGhlIGZvbGxvd2luZyBpcyBwcmVwcm9jZXNzaW5nL3NjcmlwdHMvaHBnbDA4NTAvMTVidDJfbG1ham9yLWhwZ2wwODUwdHJpbW1lZC5zaAoKYGBge3IgYnQyX2xtYWpvciwgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyMgVGhpcyBpcyBhIGJvd3RpZTIgYWxpZ25tZW50IG9mICAtMSBocGdsMDg1MF9mb3J3YXJkLXRyaW1tZWQuZmFzdHEgLTIgaHBnbDA4NTBfcmV2ZXJzZS10cmltbWVkLmZhc3RxICBhZ2FpbnN0CiMjIC9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9nZW5vbWUvaW5kZXhlcy9sbWFqb3IgdXNpbmcgYXJndW1lbnRzOiAgLS12ZXJ5LXNlbnNpdGl2ZSAuCiMjIFRoaXMgam9icyBkZXBlbmRlZCBvbjogMTMxOTg4NS5jYmNic3J2LnVtaWFjcy51bWQuZWR1Cgpta2RpciAtcCBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yICYmIHNsZWVwIDEwICYmIGJvd3RpZTIgLXggL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9pbmRleGVzL2xtYWpvciAgLS12ZXJ5LXNlbnNpdGl2ZSAgXAogIC1wIDEgXAogIC1xICAgLTEgaHBnbDA4NTBfZm9yd2FyZC10cmltbWVkLmZhc3RxIC0yIGhwZ2wwODUwX3JldmVyc2UtdHJpbW1lZC5mYXN0cSAgXAogIC0tdW4gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg1MC10cmltbWVkX3VuYWxpZ25lZF9sbWFqb3IuZmFzdHEgXAogIC0tYWwgb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg1MC10cmltbWVkX2FsaWduZWRfbG1ham9yLmZhc3RxIFwKICAtUyBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODUwLXRyaW1tZWQuc2FtIFwKICAyPm91dHB1dHMvYm93dGllMl9sbWFqb3IvaHBnbDA4NTAtdHJpbW1lZC5lcnIgXAogIDE+b3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg1MC10cmltbWVkLm91dApgYGAKCiMjIyBDb252ZXJ0aW5nIHRvIGFuIGluZGV4ZWQgc29ydGVkIGJhbSBhbGlnbm1lbnQKCkkgaGF0ZSBzYW0gZmlsZXMsIHNvIEkgaW1tZWRpYXRlbHkgY29udmVydCB0aGVtIGJlZm9yZSBjb3VudGluZzoKCkp1c3QgbGlrZSB3aXRoIHRvcGhhdCwgSSBoYXZlIGFuIGV4dHJhIHN0ZXAgdG8gZXh0cmFjdCB0aGUgcHJvcGVybHkgcGFpcmVkCmFsaWduZWQgcmVhZHMuCgpUaGUgZm9sbG93aW5nIGlzCnByZXByb2Nlc3Npbmcvc2NyaXB0cy9ocGdsMDg1MC8xOXMyYl9idDJfbG1ham9yLWhwZ2wwODUwdHJpbW1lZC5zaGVsbAoKYGBge3IgYnQyX3MyYl9sbWFqb3IsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIENvbnZlcnRpbmcgdGhlIHRleHQgc2FtIHRvIGEgY29tcHJlc3NlZCwgc29ydGVkLCBpbmRleGVkIGJhbWZpbGUuCiMjIEFsc28gcHJpbnRpbmcgYWxpZ25tZW50IHN0YXRpc3RpY3MgdG8gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLmJhbS5zdGF0cwojIyBUaGlzIGpvYiBkZXBlbmRlZCBvbjogMTMyMzg4My5jYmNic3J2LnVtaWFjcy51bWQuZWR1CnNhbXRvb2xzIHZpZXcgLXUgLXQgL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9sbWFqb3IuZmFzdGEgXAogIC1TIG91dHB1dHMvYm93dGllMl9sbWFqb3IvaHBnbDA4NDAtdHJpbW1lZC5zYW0gLW8gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLmJhbSAxPm91dHB1dHMvYm93dGllMl9sbWFqb3IvaHBnbDA4NDAtdHJpbW1lZC5iYW0ub3V0IDI+JjEKc2FtdG9vbHMgc29ydCAtbCA5IG91dHB1dHMvYm93dGllMl9sbWFqb3IvaHBnbDA4NDAtdHJpbW1lZC5iYW0gLW8gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLXNvcnRlZC5iYW0gMj5vdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODQwLXRyaW1tZWQtc29ydGVkLmJhbS5vdXQgMT4mMiAmJiBcCiAgcm0gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLmJhbSAmJiBcCiAgcm0gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLnNhbSAmJiBcCiAgbXYgb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLXNvcnRlZC5iYW0gb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLmJhbSAmJiBcCiAgc2FtdG9vbHMgaW5kZXggb3V0cHV0cy9ib3d0aWUyX2xtYWpvci9ocGdsMDg0MC10cmltbWVkLmJhbSAmJiBcCiAgc2FtdG9vbHMgdmlldyAtYiAtZiAyIC1vIG91dHB1dHMvYm93dGllMl9sbWFqb3IvaHBnbDA4NDAtdHJpbW1lZC5iYW1fcGFpcmVkLmJhbSBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODQwLXRyaW1tZWQuYmFtICYmIFwKICBzYW10b29scyBpbmRleCBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODQwLXRyaW1tZWQuYmFtX3BhaXJlZC5iYW0KYmFtdG9vbHMgc3RhdHMgLWluIG91dHB1dHMvYm93dGllMl9sbWFqb3IvaHBnbDA4NDAtdHJpbW1lZC5iYW0gMj5vdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODQwLXRyaW1tZWQuYmFtLnN0YXRzIDE+JjIgJiYgXAogIGJhbXRvb2xzIHN0YXRzIC1pbiBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODQwLXRyaW1tZWQuYmFtX3BhaXJlZC5iYW0gMj5vdXRwdXRzL2Jvd3RpZTJfbG1ham9yL2hwZ2wwODQwLXRyaW1tZWQuYmFtX3BhaXJlZC5iYW0uc3RhdHMgMT4mMgpgYGAKCiMjIyBDb3VudGluZyB0aGUgYm93dGllMiByZXN1bHRzCgpJbiB0aGUgZm9sbG93aW5nIGJsb2NrLCBJIGFtIGFjdHVhbGx5IGdvaW5nIHRvIHByaW50IG15IHRlc3QgZGF0YSBzZXQncyBzY3JpcHQuCkluIHRoZSB0ZXN0IGRhdGEsIEkgdG9vayBqdXN0IHRoZSBmaXJzdCAyNSwwMDAgcmVhZHMuICBJIHdpbGwgZm9sbG93IHRoYXQgdXAKd2l0aCBhIHNtYWxsIHNlY3Rpb24gb2YgdGhlIGNvdW50IHRhYmxlIGdlbmVyYXRlZCBmcm9tIGl0LgoKSSB0aGluayB0aGlzIHdpbGwgc2hvdyB3aGVyZSB0aGUgd2hlZWxzIGZlbGwgb2ZmIHRoZSBjYXIuCgpUaGVyZSBpcyBhbiBpbXBvcnRhbnQgY2F2ZWF0IHJlbGF0ZWQgdG8gdGhlIG5vdGUgSSBwYXN0ZWQgYWJvdmUuICBJbiB0aGUKZm9sbG93aW5nIHNjcmlwdCBJIGFkZGVkIHRoZSAnLWEgMScgYXJndW1lbnQsIHdoaWNoIHRlbGxzIGh0c2VxIHRvIGNvdW50IGFsbApwYWlycyB3aXRoIGFsaWdubWVudCBxdWFsaXRpZXMgPj0gMSByYXRoZXIgdGhhbiB0aGUgZGVmYXVsdCBvZiAxMC4KCmBgYHtyIGJ0Ml9odHNlcV9sbWFqb3IsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIENvdW50aW5nIHRoZSBudW1iZXIgb2YgaGl0cyBpbiBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL3Rlc3QtdHJpbW1lZC5iYW0gZm9yIGVhY2ggZmVhdHVyZSBmb3VuZCBpbiAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2xtYWpvci5nZmYKIyMgSXMgdGhpcyBzdHJhbmRlZD8geWVzLiAgVGhlIGRlZmF1bHRzIG9mIGh0c2VxIGFyZToKIyMgIC0tb3JkZXI9bmFtZSAtLWlkYXR0cj1nZW5lX2lkIC0tbWluYXF1YWw9MTAgLS10eXBlPWV4b24gLS1zdHJhbmRlZD15ZXMgLS1tb2RlPXVuaW9uCgpodHNlcS1jb3VudCAtcSAtZiBiYW0gLXMgeWVzICAtaSBJRCAgLXQgZXhvbiAtYSAxIFwKICBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL3Rlc3QtdHJpbW1lZC5iYW0gL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9sbWFqb3IuZ2ZmIFwKICAxPm91dHB1dHMvYm93dGllMl9sbWFqb3IvdGVzdC10cmltbWVkLmNvdW50IDI+b3V0cHV0cy9ib3d0aWUyX2xtYWpvci90ZXN0LXRyaW1tZWRfaHRzZXEuZXJyICYmIFwKICAgIHh6IC1mIC05ZSBvdXRwdXRzL2Jvd3RpZTJfbG1ham9yL3Rlc3QtdHJpbW1lZC5jb3VudApgYGAKCkhlcmUgYXJlIGEgZmV3IHJlcHJlc2VudGF0aXZlIGxpbmVzIGZyb20gdGhlIHJlc3VsdGluZyBjb3VudCB0YWJsZSwgdGhlIG1haW4KdGhpbmcgdG8gcmVjYWxsIGlzIHRoYXQgaW4gbW9zdCBvZiBvdXIgZGF0YSBzZXRzLCB0aGUgTC4gbWFqb3IgclJOQSBnZW5lcyBhcmUKbW9zdGx5IGV4Y2x1ZGVkLCBhbmQgdGhlIGdlbmVzIHN1cnJvdW5kaW5nIHRoZSByUk5BIGxvY2kgYXJlIHVzdWFsbHkgMy0xMHgKaGlnaGVyIGluIGNvdW50czoKCjxwcmU+CmV4b25fTG1qRi4yNy4yNTkwLTEgICAgIDEKZXhvbl9MbWpGLjI3LjI2MDAtMSAgICAgMApleG9uX0xtakYuMjcuMjYxMC0xICAgICAwCmV4b25fTG1qRi4yNy4yNjIwLTEgICAgIDAKZXhvbl9MbWpGLjI3LjI2MzAtMSAgICAgMApleG9uX0xtakYuMjcuMjY0MC0xICAgICAwCmV4b25fTG1qRi4yNy4yNjUwLTEgICAgIDAKZXhvbl9MbWpGLjI3LjI2NjAtMSAgICAgMApleG9uX0xtakYuMjcubmNSTkExLTEgICAwCmV4b25fTG1qRi4yNy5yUk5BLjAxLTEgIDEyOTgKZXhvbl9MbWpGLjI3LnJSTkEuMDItMSAgMTM4OApleG9uX0xtakYuMjcuclJOQS4wMy0xICAxMzY1CmV4b25fTG1qRi4yNy5yUk5BLjA0LTEgIDE0MzcKZXhvbl9MbWpGLjI3LnJSTkEuMDUtMSAgMTM0MwpleG9uX0xtakYuMjcuclJOQS4wNi0xICAxNDEwCjwvcHJlPgoKT2ggY3JhcC4gIEkgZGlkIG5vdCBzZWUgdGhlc2UgaW4gbXkgZmlyc3QgcnVuIGJlY2F1c2UgaHRzZXEgaXMgZHJvcHBpbmcgdGhlbSBhbGwKYXMgKEkgdGhpbmspIG1hbnkgb2YgdGhlbSBhcmUgbXVsdGktaGl0dGluZyB0byBhIHNpZ25pZmljYW50IHN1YnNldCBvZiB0aGUgNTIKdGFuZGVtIHJSTkEgbG9jaSBpbiB0aGUgTC4gbWFqb3IgZ2Vub21lLgo=