Introduction
FastQC/MultiQC (ewels2016?; Andrews_undated-nf?) assessment of raw and fastp
-trimmed sequences of E5 P.evermanni sRNAseq data from 20230515.
This notebook will trim and merge R1 and R2 reads. The max length of 31bp is based on the fastp
insert peak size from previous trimming tests based on the the adapter and polyG trimming results, and previous evaluation of mean read lengths via FastQC
and MultiQC
.
Inputs:
- sRNAseq paired-end FastQs (e.g.
*.fastq.gz
)
Outputs:
FastQC
HTML reports for raw and trimmed reads.
MultiQC
HTML summaries of FastQC
for raw and trimmed reads.
Trimmed and merged reads with final length of 31bp: *.fastp_trim.31bp.fastq.gz
Libraries were prepared and sequenced by Azenta:
Create a Bash variables file
This allows usage of Bash variables across R Markdown chunks.
{
echo "#### Assign Variables ####"
echo ""
echo "# Set maximum read length"
echo 'export max_read_length=31'
echo ""
echo "# Data directories"
echo 'export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive'
echo 'export output_dir_top=${deep_dive_dir}/E-Peve/output/06.2-Peve-sRNAseq-trimming-${max_read_length}bp-fastp-merged'
echo 'export raw_fastqc_dir=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/raw-fastqc'
echo 'export raw_reads_dir=${deep_dive_dir}/E-Peve/data/06-Peve-sRNAseq-trimming/raw-reads'
echo 'export raw_reads_url="https://owl.fish.washington.edu/nightingales/P_evermanni/30-852430235/"'
echo 'export trimmed_fastqc_dir=${output_dir_top}/trimmed-fastqc'
echo 'export trimmed_reads_dir=${output_dir_top}/trimmed-reads'
echo ""
echo "# Paths to programs"
echo 'export fastqc=/home/shared/FastQC-0.12.1/fastqc'
echo 'export fastp=/home/shared/fastp'
echo 'export multiqc=/home/sam/programs/mambaforge/bin/multiqc'
echo ""
echo "# Set FastQ filename patterns"
echo "export fastq_pattern='sRNA*.fastq.gz'"
echo "export R1_fastq_pattern='*_R1_*.fastq.gz'"
echo "export R2_fastq_pattern='*_R2_*.fastq.gz'"
echo ""
echo "# Set number of CPUs to use"
echo 'export threads=40'
echo ""
echo "# Input/output files"
echo 'export fastq_checksums=input_fastq_checksums.md5'
echo 'export trimmed_checksums=trimmed_fastq_checksums.md5'
echo 'export NEB_adapters_fasta=NEB-adapters.fasta'
echo ""
echo "## NEB nebnext-small-rna-library-prep-set-for-illumina adapters"
echo 'export first_adapter="AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC"'
echo 'export second_adapter="GATCGTCGGACTGTAGAACTCTGAACGTGTAGATCTCGGTGGTCGCCGTATCATT"'
echo ""
echo "## Inititalize arrays"
echo 'export fastq_array_R1=()'
echo 'export fastq_array_R2=()'
echo 'export raw_fastqs_array=()'
echo 'export R1_names_array=()'
echo 'export R2_names_array=()'
echo 'export trimmed_fastqs_array=()'
echo ""
echo "# Programs associative array"
echo "declare -A programs_array"
echo "programs_array=("
echo '[fastqc]="${fastqc}" \'
echo '[multiqc]="${multiqc}" \'
echo '[fastp]="${fastp}"'
echo ")"
} > .bashvars
cat .bashvars
#### Assign Variables ####
# Set maximum read length
export max_read_length=31
# Data directories
export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive
export output_dir_top=${deep_dive_dir}/E-Peve/output/06.2-Peve-sRNAseq-trimming-${max_read_length}bp-fastp-merged
export raw_fastqc_dir=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/raw-fastqc
export raw_reads_dir=${deep_dive_dir}/E-Peve/data/06-Peve-sRNAseq-trimming/raw-reads
export raw_reads_url="https://owl.fish.washington.edu/nightingales/P_evermanni/30-852430235/"
export trimmed_fastqc_dir=${output_dir_top}/trimmed-fastqc
export trimmed_reads_dir=${output_dir_top}/trimmed-reads
# Paths to programs
export fastqc=/home/shared/FastQC-0.12.1/fastqc
export fastp=/home/shared/fastp
export multiqc=/home/sam/programs/mambaforge/bin/multiqc
# Set FastQ filename patterns
export fastq_pattern='sRNA*.fastq.gz'
export R1_fastq_pattern='*_R1_*.fastq.gz'
export R2_fastq_pattern='*_R2_*.fastq.gz'
# Set number of CPUs to use
export threads=40
# Input/output files
export fastq_checksums=input_fastq_checksums.md5
export trimmed_checksums=trimmed_fastq_checksums.md5
export NEB_adapters_fasta=NEB-adapters.fasta
## NEB nebnext-small-rna-library-prep-set-for-illumina adapters
export first_adapter="AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC"
export second_adapter="GATCGTCGGACTGTAGAACTCTGAACGTGTAGATCTCGGTGGTCGCCGTATCATT"
## Inititalize arrays
export fastq_array_R1=()
export fastq_array_R2=()
export raw_fastqs_array=()
export R1_names_array=()
export R2_names_array=()
export trimmed_fastqs_array=()
# Programs associative array
declare -A programs_array
programs_array=(
[fastqc]="${fastqc}" \
[multiqc]="${multiqc}" \
[fastp]="${fastp}"
)
Download raw sRNAseq reads
Reads are downloaded from https://owl.fish.washington.edu/nightingales/P_evermanni/30-852430235/
The --cut-dirs 3
command cuts the preceding directory structure (i.e. nightingales/P_evermanni/30-852430235/
) so that we just end up with the reads.
source .bashvars
wget \
--directory-prefix ${raw_reads_dir} \
--recursive \
--no-check-certificate \
--continue \
--cut-dirs 3 \
--no-host-directories \
--no-parent \
--quiet \
--accept "${fastq_pattern},checksums.md5" ${raw_reads_url}
ls -lh "${raw_reads_dir}"/${fastq_pattern}
Verify raw read checksums
source .bashvars
cd "${raw_reads_dir}"
grep "sRNA" checksums.md5 | md5sum --check
sRNA-POR-73-S1-TP2_R1_001.fastq.gz: OK
sRNA-POR-73-S1-TP2_R2_001.fastq.gz: OK
sRNA-POR-79-S1-TP2_R1_001.fastq.gz: OK
sRNA-POR-79-S1-TP2_R2_001.fastq.gz: OK
sRNA-POR-82-S1-TP2_R1_001.fastq.gz: OK
sRNA-POR-82-S1-TP2_R2_001.fastq.gz: OK
Create adapters FastA for use with fastp
trimming
source .bashvars
mkdir --parents "${output_dir_top}"
echo "Creating adapters FastA."
echo ""
adapter_count=0
if [ -f "${output_dir_top}/${NEB_adapters_fasta}" ]; then
echo "${output_dir_top}/${NEB_adapters_fasta} already exists. Nothing to do."
else
for adapter in "${first_adapter}" "${second_adapter}"
do
adapter_count=$((adapter_count + 1))
printf ">%s\n%s\n" "adapter_${adapter_count}" "${adapter}"
done >> "${output_dir_top}/${NEB_adapters_fasta}"
fi
echo ""
echo "Adapters FastA:"
echo ""
cat "${output_dir_top}/${NEB_adapters_fasta}"
echo ""
Creating adapters FastA.
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/NEB-adapters.fasta already exists. Nothing to do.
Adapters FastA:
>adapter_1
AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC
>adapter_2
GATCGTCGGACTGTAGAACTCTGAACGTGTAGATCTCGGTGGTCGCCGTATCATT
FastQC/MultiQC on raw reads
source .bashvars
raw_fastqs_array=(${raw_reads_dir}/${fastq_pattern})
raw_fastqc_list=$(echo "${raw_fastqs_array[*]}")
echo "Beginning FastQC on raw reads..."
echo ""
${programs_array[fastqc]} \
--threads ${threads} \
--outdir ${raw_fastqc_dir} \
--quiet \
${raw_fastqc_list}
echo "FastQC on raw reads complete!"
echo ""
echo "Beginning MultiQC on raw FastQC..."
echo ""
${programs_array[multiqc]} ${raw_fastqc_dir} -o ${raw_fastqc_dir}
echo ""
echo "MultiQC on raw FastQs complete."
echo ""
echo "Removing FastQC zip files."
echo ""
rm ${raw_fastqc_dir}/*.zip
echo "FastQC zip files removed."
echo ""
ls -lh ${raw_fastqc_dir}
Trimming and merging with fastp
source .bashvars
mkdir --parents "${trimmed_reads_dir}"
cd "${raw_reads_dir}"
for fastq in ${R1_fastq_pattern}
do
fastq_array_R1+=("${fastq}")
R1_names_array+=("${fastq%%.*}")
done
for fastq in ${R2_fastq_pattern}
do
fastq_array_R2+=("${fastq}")
R2_names_array+=("${fastq%%.*}")
done
echo "Beginning fastp trimming."
echo ""
time \
for index in "${!fastq_array_R1[@]}"
do
R1_sample_name="${R1_names_array[index]%%_*}"
R2_sample_name="${R2_names_array[index]%%_*}"
${programs_array[fastp]} \
--in1 ${fastq_array_R1[index]} \
--in2 ${fastq_array_R2[index]} \
--adapter_fasta ${output_dir_top}/${NEB_adapters_fasta} \
--trim_poly_g \
--overlap_len_require 17 \
--length_limit 31 \
--merge \
--merged_out ${trimmed_reads_dir}/${R1_sample_name}-fastp-adapters-polyG-${max_read_length}bp-merged.fq.gz \
--thread ${threads} \
--html "${trimmed_reads_dir}/${R1_sample_name}-fastp-adapters-polyG-${max_read_length}bp-merged.html" \
--json "${trimmed_reads_dir}/${R1_sample_name}-fastp-adapters-polyG-${max_read_length}bp-merged.json" \
--report_title "${trimmed_reads_dir}/${R1_sample_name}-fastp-adapters-polyG-${max_read_length}bp-merged"
cd ${trimmed_reads_dir}
{
md5sum "${R1_sample_name}-fastp-adapters-polyG-${max_read_length}bp-merged.fq.gz"
} >> "${trimmed_checksums}"
cd "${raw_reads_dir}"
done
echo ""
echo "fastp trimming complete."
echo ""
echo "Trimmed FastQs MD5 checksums:"
echo ""
cat "${trimmed_reads_dir}/${trimmed_checksums}"
FastQC/MultiQC on trimmed reads
source .bashvars
mkdir --parents "${trimmed_fastqc_dir}"
trimmed_fastqs_array=(${trimmed_reads_dir}/*merged.fq.gz)
trimmed_fastqc_list=$(echo "${trimmed_fastqs_array[*]}")
echo "Beginning FastQC on raw reads..."
echo ""
${programs_array[fastqc]} \
--threads ${threads} \
--outdir ${trimmed_fastqc_dir} \
--quiet \
${trimmed_fastqc_list}
echo "FastQC on trimmed reads complete!"
echo ""
echo "Beginning MultiQC on raw FastQC..."
echo ""
${programs_array[multiqc]} ${trimmed_fastqc_dir} -o ${trimmed_fastqc_dir}
echo ""
echo "MultiQC on trimmed FastQs complete."
echo ""
echo "Removing FastQC zip files."
echo ""
rm ${trimmed_fastqc_dir}/*.zip
echo "FastQC zip files removed."
echo ""
ls -lh ${trimmed_fastqc_dir}
Summary
A quick comparison of raw and trimmed reads to show trimming worked:
- quality is improved
- length is 31bp
- adapters removed
- merged
LS0tCnRpdGxlOiAiMDYuMi1QZXZlLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQiCmF1dGhvcjogIlNhbSBXaGl0ZSIKZGF0ZTogIjIwMjQtMDItMDkiCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCmxpbmstY2l0YXRpb25zOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShkcGx5cikKbGlicmFyeShyZXRpY3VsYXRlKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsICAgICAgICAgIyBEaXNwbGF5IGNvZGUgY2h1bmtzCiAgZXZhbCA9IEZBTFNFLCAgICAgICAgIyBFdmFsdWF0ZSBjb2RlIGNodW5rcwogIHdhcm5pbmcgPSBGQUxTRSwgICAgICMgSGlkZSB3YXJuaW5ncwogIG1lc3NhZ2UgPSBGQUxTRSwgICAgICMgSGlkZSBtZXNzYWdlcwogIGNvbW1lbnQgPSAiIiAgICAgICAgICMgUHJldmVudHMgYXBwZW5kaW5nICcjIycgdG8gYmVnaW5uaW5nIG9mIGxpbmVzIGluIGNvZGUgb3V0cHV0CikKYGBgCgojIEludHJvZHVjdGlvbgoKRmFzdFFDL011bHRpUUMgW0Bld2VsczIwMTY7IEBBbmRyZXdzX3VuZGF0ZWQtbmZdIGFzc2Vzc21lbnQgb2YgcmF3IGFuZCBbYGZhc3RwYF0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5HZW5lL2Zhc3RwKS10cmltbWVkIHNlcXVlbmNlcyBvZiBFNSAqUC5ldmVybWFubmkqIHNSTkFzZXEgZGF0YSBmcm9tIFsyMDIzMDUxNV0oaHR0cHM6Ly9yb2JlcnRzbGFiLmdpdGh1Yi5pby9zYW1zLW5vdGVib29rL3Bvc3RzLzIwMjMvMjAyMy0wNS0xNy1EYXRhLU1hbmFnZW1lbnQtLS1FNS1Db3JhbC1STkEtc2VxLWFuZC1zUk5BLXNlcS1SZW9yZ2FuaXppbmctYW5kLVJlbmFtaW5nLykuCgpUaGlzIG5vdGVib29rIHdpbGwgdHJpbSBhbmQgbWVyZ2UgUjEgYW5kIFIyIHJlYWRzLiBUaGUgbWF4IGxlbmd0aCBvZiAzMWJwIGlzIGJhc2VkIG9uIHRoZSBgZmFzdHBgIGluc2VydCBwZWFrIHNpemUgZnJvbSBwcmV2aW91cyB0cmltbWluZyB0ZXN0cyBiYXNlZCBvbiB0aGUgdGhlIGFkYXB0ZXIgYW5kIHBvbHlHIHRyaW1taW5nIHJlc3VsdHMsIGFuZCBwcmV2aW91cyBldmFsdWF0aW9uIG9mIG1lYW4gcmVhZCBsZW5ndGhzIHZpYSBbYEZhc3RRQ2BdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIGFuZCBbYE11bHRpUUNgXShodHRwczovL211bHRpcWMuaW5mby8pLgoKSW5wdXRzOgoKLSAgIHNSTkFzZXEgcGFpcmVkLWVuZCBGYXN0UXMgKGUuZy4gYCouZmFzdHEuZ3pgKQoKT3V0cHV0czoKCi0gICBbYEZhc3RRQ2BdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIEhUTUwgcmVwb3J0cyBmb3IgcmF3IGFuZCB0cmltbWVkIHJlYWRzLgoKLSAgIFtgTXVsdGlRQ2BdKGh0dHBzOi8vbXVsdGlxYy5pbmZvLykgSFRNTCBzdW1tYXJpZXMgb2YgW2BGYXN0UUNgXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9wcm9qZWN0cy9mYXN0cWMvKSBmb3IgcmF3IGFuZCB0cmltbWVkIHJlYWRzLgoKLSAgIFRyaW1tZWQgYW5kIG1lcmdlZCByZWFkcyB3aXRoIGZpbmFsIGxlbmd0aCBvZiAzMWJwOiBgKi5mYXN0cF90cmltLjMxYnAuZmFzdHEuZ3pgCgpMaWJyYXJpZXMgd2VyZSBwcmVwYXJlZCBhbmQgc2VxdWVuY2VkIGJ5IEF6ZW50YToKCi0gICBMaWJyYXJ5IHByZXA6IFtORUIgbmVibmV4dC1zbWFsbC1ybmEtbGlicmFyeS1wcmVwLXNldC1mb3ItaWxsdW1pbmEga2l0XShodHRwczovL3d3dy5uZWIuY29tL2VuLXVzLy0vbWVkaWEvbmVidXMvZmlsZXMvbWFudWFscy9tYW51YWxlNzMwMF9lNzMzMF9lNzU2MF9lNzU4MC5wZGY/cmV2PWQwOTY0YTJlNjM3ODQzYjFhZmNiOWY3ZDY2NmQwN2IyJmhhc2g9N0FDMEIwRUIwMTI3MDhFRkFCMEU0REJFRUFGMTQ0NkEpIChQREYpCgotICAgU2VxdWVuY2luZzogSWxsdW1pbmEgSGlTZXEgNDAwMCwgMTUwYnAgUEUKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDcmVhdGUgYSBCYXNoIHZhcmlhYmxlcyBmaWxlCgpUaGlzIGFsbG93cyB1c2FnZSBvZiBCYXNoIHZhcmlhYmxlcyBhY3Jvc3MgUiBNYXJrZG93biBjaHVua3MuCgpgYGB7ciBzYXZlLWJhc2gtdmFyaWFibGVzLXRvLXJ2YXJzLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KewplY2hvICIjIyMjIEFzc2lnbiBWYXJpYWJsZXMgIyMjIyIKZWNobyAiIgoKZWNobyAiIyBTZXQgbWF4aW11bSByZWFkIGxlbmd0aCIKZWNobyAnZXhwb3J0IG1heF9yZWFkX2xlbmd0aD0zMScKZWNobyAiIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgZGVlcF9kaXZlX2Rpcj0vaG9tZS9zaGFyZWQvOFRCX0hERF8wMS9zYW0vZ2l0cmVwb3MvZGVlcC1kaXZlJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9JHtkZWVwX2RpdmVfZGlyfS9FLVBldmUvb3V0cHV0LzA2LjItUGV2ZS1zUk5Bc2VxLXRyaW1taW5nLSR7bWF4X3JlYWRfbGVuZ3RofWJwLWZhc3RwLW1lcmdlZCcKZWNobyAnZXhwb3J0IHJhd19mYXN0cWNfZGlyPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wNi1QZXZlLXNSTkFzZXEtdHJpbW1pbmcvcmF3LWZhc3RxYycKZWNobyAnZXhwb3J0IHJhd19yZWFkc19kaXI9JHtkZWVwX2RpdmVfZGlyfS9FLVBldmUvZGF0YS8wNi1QZXZlLXNSTkFzZXEtdHJpbW1pbmcvcmF3LXJlYWRzJwplY2hvICdleHBvcnQgcmF3X3JlYWRzX3VybD0iaHR0cHM6Ly9vd2wuZmlzaC53YXNoaW5ndG9uLmVkdS9uaWdodGluZ2FsZXMvUF9ldmVybWFubmkvMzAtODUyNDMwMjM1LyInCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3RxY19kaXI9JHtvdXRwdXRfZGlyX3RvcH0vdHJpbW1lZC1mYXN0cWMnCmVjaG8gJ2V4cG9ydCB0cmltbWVkX3JlYWRzX2Rpcj0ke291dHB1dF9kaXJfdG9wfS90cmltbWVkLXJlYWRzJwplY2hvICIiCgplY2hvICIjIFBhdGhzIHRvIHByb2dyYW1zIgplY2hvICdleHBvcnQgZmFzdHFjPS9ob21lL3NoYXJlZC9GYXN0UUMtMC4xMi4xL2Zhc3RxYycKZWNobyAnZXhwb3J0IGZhc3RwPS9ob21lL3NoYXJlZC9mYXN0cCcKZWNobyAnZXhwb3J0IG11bHRpcWM9L2hvbWUvc2FtL3Byb2dyYW1zL21hbWJhZm9yZ2UvYmluL211bHRpcWMnCmVjaG8gIiIKCgoKZWNobyAiIyBTZXQgRmFzdFEgZmlsZW5hbWUgcGF0dGVybnMiCmVjaG8gImV4cG9ydCBmYXN0cV9wYXR0ZXJuPSdzUk5BKi5mYXN0cS5neiciCmVjaG8gImV4cG9ydCBSMV9mYXN0cV9wYXR0ZXJuPScqX1IxXyouZmFzdHEuZ3onIgplY2hvICJleHBvcnQgUjJfZmFzdHFfcGF0dGVybj0nKl9SMl8qLmZhc3RxLmd6JyIKZWNobyAiIgoKZWNobyAiIyBTZXQgbnVtYmVyIG9mIENQVXMgdG8gdXNlIgplY2hvICdleHBvcnQgdGhyZWFkcz00MCcKZWNobyAiIgoKCgplY2hvICIjIElucHV0L291dHB1dCBmaWxlcyIKZWNobyAnZXhwb3J0IGZhc3RxX2NoZWNrc3Vtcz1pbnB1dF9mYXN0cV9jaGVja3N1bXMubWQ1JwplY2hvICdleHBvcnQgdHJpbW1lZF9jaGVja3N1bXM9dHJpbW1lZF9mYXN0cV9jaGVja3N1bXMubWQ1JwplY2hvICdleHBvcnQgTkVCX2FkYXB0ZXJzX2Zhc3RhPU5FQi1hZGFwdGVycy5mYXN0YScKZWNobyAiIgoKZWNobyAiIyMgTkVCIG5lYm5leHQtc21hbGwtcm5hLWxpYnJhcnktcHJlcC1zZXQtZm9yLWlsbHVtaW5hIGFkYXB0ZXJzIgplY2hvICdleHBvcnQgZmlyc3RfYWRhcHRlcj0iQUdBVENHR0FBR0FHQ0FDQUNHVENUR0FBQ1RDQ0FHVENBQyInCmVjaG8gJ2V4cG9ydCBzZWNvbmRfYWRhcHRlcj0iR0FUQ0dUQ0dHQUNUR1RBR0FBQ1RDVEdBQUNHVEdUQUdBVENUQ0dHVEdHVENHQ0NHVEFUQ0FUVCInCmVjaG8gIiIKCmVjaG8gIiMjIEluaXRpdGFsaXplIGFycmF5cyIKZWNobyAnZXhwb3J0IGZhc3RxX2FycmF5X1IxPSgpJwplY2hvICdleHBvcnQgZmFzdHFfYXJyYXlfUjI9KCknCmVjaG8gJ2V4cG9ydCByYXdfZmFzdHFzX2FycmF5PSgpJwplY2hvICdleHBvcnQgUjFfbmFtZXNfYXJyYXk9KCknCmVjaG8gJ2V4cG9ydCBSMl9uYW1lc19hcnJheT0oKScKZWNobyAnZXhwb3J0IHRyaW1tZWRfZmFzdHFzX2FycmF5PSgpJwplY2hvICIiCgplY2hvICIjIFByb2dyYW1zIGFzc29jaWF0aXZlIGFycmF5IgplY2hvICJkZWNsYXJlIC1BIHByb2dyYW1zX2FycmF5IgplY2hvICJwcm9ncmFtc19hcnJheT0oIgplY2hvICdbZmFzdHFjXT0iJHtmYXN0cWN9IiBcJwplY2hvICdbbXVsdGlxY109IiR7bXVsdGlxY30iIFwnCmVjaG8gJ1tmYXN0cF09IiR7ZmFzdHB9IicKZWNobyAiKSIKfSA+IC5iYXNodmFycwoKY2F0IC5iYXNodmFycwpgYGAKCiMgRG93bmxvYWQgcmF3IHNSTkFzZXEgcmVhZHMKClJlYWRzIGFyZSBkb3dubG9hZGVkIGZyb20gPGh0dHBzOi8vb3dsLmZpc2gud2FzaGluZ3Rvbi5lZHUvbmlnaHRpbmdhbGVzL1BfZXZlcm1hbm5pLzMwLTg1MjQzMDIzNS8+CgpUaGUgYC0tY3V0LWRpcnMgM2AgY29tbWFuZCBjdXRzIHRoZSBwcmVjZWRpbmcgZGlyZWN0b3J5IHN0cnVjdHVyZSAoaS5lLiBgbmlnaHRpbmdhbGVzL1BfZXZlcm1hbm5pLzMwLTg1MjQzMDIzNS9gKSBzbyB0aGF0IHdlIGp1c3QgZW5kIHVwIHdpdGggdGhlIHJlYWRzLgoKYGBge2Jhc2ggZG93bmxvYWQtcmF3LXJlYWRzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKd2dldCBcCi0tZGlyZWN0b3J5LXByZWZpeCAke3Jhd19yZWFkc19kaXJ9IFwKLS1yZWN1cnNpdmUgXAotLW5vLWNoZWNrLWNlcnRpZmljYXRlIFwKLS1jb250aW51ZSBcCi0tY3V0LWRpcnMgMyBcCi0tbm8taG9zdC1kaXJlY3RvcmllcyBcCi0tbm8tcGFyZW50IFwKLS1xdWlldCBcCi0tYWNjZXB0ICIke2Zhc3RxX3BhdHRlcm59LGNoZWNrc3Vtcy5tZDUiICR7cmF3X3JlYWRzX3VybH0KCmxzIC1saCAiJHtyYXdfcmVhZHNfZGlyfSIvJHtmYXN0cV9wYXR0ZXJufQpgYGAKCiMjIFZlcmlmeSByYXcgcmVhZCBjaGVja3N1bXMKCmBgYHtiYXNoIHZlcmlmeS1yYXctcmVhZC1jaGVja3N1bXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDaGVja3N1bXMgZmlsZSBjb250YWlucyBvdGhlciBmaWxlcywgc28gdGhpcyBqdXN0IGxvb2tzIGZvciB0aGUgc1JOQXNlcSBmaWxlcy4KZ3JlcCAic1JOQSIgY2hlY2tzdW1zLm1kNSB8IG1kNXN1bSAtLWNoZWNrCmBgYAoKIyBDcmVhdGUgYWRhcHRlcnMgRmFzdEEgZm9yIHVzZSB3aXRoIFtgZmFzdHBgXShodHRwczovL2dpdGh1Yi5jb20vT3BlbkdlbmUvZmFzdHApIHRyaW1taW5nCgpgYGB7YmFzaCBjcmVhdGUtRmFzdEEtb2YtYWRhcHRlcnMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCiMgQ3JlYXRlIG91dHB1dCBkaXJlY3RvcnksIGlmIGl0IGRvZXNuJ3QgZXhpc3QKbWtkaXIgLS1wYXJlbnRzICIke291dHB1dF9kaXJfdG9wfSIKCmVjaG8gIkNyZWF0aW5nIGFkYXB0ZXJzIEZhc3RBLiIKZWNobyAiIgphZGFwdGVyX2NvdW50PTAKCiMgQ2hlY2sgZm9yIGFkYXB0ZXJzIGZpbGUgZmlyc3QKIyBUaGVuIGNyZWF0ZSBhZGFwdGVycyBmaWxlIGlmIGRvZXNuJ3QgZXhpc3QKaWYgWyAtZiAiJHtvdXRwdXRfZGlyX3RvcH0vJHtORUJfYWRhcHRlcnNfZmFzdGF9IiBdOyB0aGVuCiAgZWNobyAiJHtvdXRwdXRfZGlyX3RvcH0vJHtORUJfYWRhcHRlcnNfZmFzdGF9IGFscmVhZHkgZXhpc3RzLiBOb3RoaW5nIHRvIGRvLiIKZWxzZQogIGZvciBhZGFwdGVyIGluICIke2ZpcnN0X2FkYXB0ZXJ9IiAiJHtzZWNvbmRfYWRhcHRlcn0iCiAgZG8KICAgIGFkYXB0ZXJfY291bnQ9JCgoYWRhcHRlcl9jb3VudCArIDEpKQogICAgcHJpbnRmICI+JXNcbiVzXG4iICJhZGFwdGVyXyR7YWRhcHRlcl9jb3VudH0iICIke2FkYXB0ZXJ9IgogIGRvbmUgPj4gIiR7b3V0cHV0X2Rpcl90b3B9LyR7TkVCX2FkYXB0ZXJzX2Zhc3RhfSIKZmkKCmVjaG8gIiIKZWNobyAiQWRhcHRlcnMgRmFzdEE6IgplY2hvICIiCmNhdCAiJHtvdXRwdXRfZGlyX3RvcH0vJHtORUJfYWRhcHRlcnNfZmFzdGF9IgplY2hvICIiCmBgYAoKIyBGYXN0UUMvTXVsdGlRQyBvbiByYXcgcmVhZHMKCmBgYHtiYXNoIHJhdy1mYXN0cWMtbXVsdGlxYywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCiMjIyMjIyMjIyMjIyBSVU4gRkFTVFFDICMjIyMjIyMjIyMjIwoKCiMgQ3JlYXRlIGFycmF5IG9mIHRyaW1tZWQgRmFzdFFzCnJhd19mYXN0cXNfYXJyYXk9KCR7cmF3X3JlYWRzX2Rpcn0vJHtmYXN0cV9wYXR0ZXJufSkKCiMgUGFzcyBhcnJheSBjb250ZW50cyB0byBuZXcgdmFyaWFibGUgYXMgc3BhY2UtZGVsaW1pdGVkIGxpc3QKcmF3X2Zhc3RxY19saXN0PSQoZWNobyAiJHtyYXdfZmFzdHFzX2FycmF5WypdfSIpCgplY2hvICJCZWdpbm5pbmcgRmFzdFFDIG9uIHJhdyByZWFkcy4uLiIKZWNobyAiIgoKIyBSdW4gRmFzdFFDCiMjIyBOT1RFOiBEbyBOT1QgcXVvdGUgcmF3X2Zhc3RxY19saXN0CiR7cHJvZ3JhbXNfYXJyYXlbZmFzdHFjXX0gXAotLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0ZGlyICR7cmF3X2Zhc3RxY19kaXJ9IFwKLS1xdWlldCBcCiR7cmF3X2Zhc3RxY19saXN0fQoKZWNobyAiRmFzdFFDIG9uIHJhdyByZWFkcyBjb21wbGV0ZSEiCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIyMjIyMjIyMjIFJVTiBNVUxUSVFDICMjIyMjIyMjIyMjIwplY2hvICJCZWdpbm5pbmcgTXVsdGlRQyBvbiByYXcgRmFzdFFDLi4uIgplY2hvICIiCgoke3Byb2dyYW1zX2FycmF5W211bHRpcWNdfSAke3Jhd19mYXN0cWNfZGlyfSAtbyAke3Jhd19mYXN0cWNfZGlyfQoKZWNobyAiIgplY2hvICJNdWx0aVFDIG9uIHJhdyBGYXN0UXMgY29tcGxldGUuIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIE1VTFRJUUMgIyMjIyMjIyMjIyMjCgplY2hvICJSZW1vdmluZyBGYXN0UUMgemlwIGZpbGVzLiIKZWNobyAiIgpybSAke3Jhd19mYXN0cWNfZGlyfS8qLnppcAplY2hvICJGYXN0UUMgemlwIGZpbGVzIHJlbW92ZWQuIgplY2hvICIiCgojIFZpZXcgZGlyZWN0b3J5IGNvbnRlbnRzCmxzIC1saCAke3Jhd19mYXN0cWNfZGlyfQoKYGBgCgojIFRyaW1taW5nIGFuZCBtZXJnaW5nIHdpdGggZmFzdHAKCmBgYHtiYXNoIGZhc3RwLWFuZC1tZXJnaW5nLCBlbmdpbmU9J2Jhc2gnLCBjYWNoZT1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBDcmVhdGUgb3V0cHV0IGRpcmVjdG9yeSwgaWYgaXQgZG9lc24ndCBleGlzdC4KbWtkaXIgLS1wYXJlbnRzICIke3RyaW1tZWRfcmVhZHNfZGlyfSIKCiMgQ2hhbmdlIHRvIGRpcmVjdG9yeSB3aXRoIHJhdyByZWFkcwpjZCAiJHtyYXdfcmVhZHNfZGlyfSIKCiMgQ3JlYXRlIGFycmF5cyBvZiBGYXN0USBSMSBmaWxlcyBhbmQgc2FtcGxlIG5hbWVzCiMgRG8gTk9UIHF1b3RlIFIxX2Zhc3RxX3BhdHRlcm4gdmFyaWFibGUKZm9yIGZhc3RxIGluICR7UjFfZmFzdHFfcGF0dGVybn0KZG8KICBmYXN0cV9hcnJheV9SMSs9KCIke2Zhc3RxfSIpCgogICMgVXNlIHBhcmFtZXRlciBzdWJzdGl0dXRpb24gdG8gcmVtb3ZlIGFsbCB0ZXh0IHVwIHRvIGFuZCBpbmNsdWRpbmcgbGFzdCAiLiIgZnJvbQogICMgcmlnaHQgc2lkZSBvZiBzdHJpbmcuCiAgUjFfbmFtZXNfYXJyYXkrPSgiJHtmYXN0cSUlLip9IikKZG9uZQoKIyBDcmVhdGUgYXJyYXkgb2YgRmFzdFEgUjIgZmlsZXMKIyBEbyBOT1QgcXVvdGUgUjJfZmFzdHFfcGF0dGVybiB2YXJpYWJsZQpmb3IgZmFzdHEgaW4gJHtSMl9mYXN0cV9wYXR0ZXJufQpkbwogIGZhc3RxX2FycmF5X1IyKz0oIiR7ZmFzdHF9IikKCiAgIyBVc2UgcGFyYW1ldGVyIHN1YnN0aXR1dGlvbiB0byByZW1vdmUgYWxsIHRleHQgdXAgdG8gYW5kIGluY2x1ZGluZyBsYXN0ICIuIiBmcm9tCiAgIyByaWdodCBzaWRlIG9mIHN0cmluZy4KICBSMl9uYW1lc19hcnJheSs9KCIke2Zhc3RxJSUuKn0iKQpkb25lCgojIyMjIyMjIyMjIyMgUlVOIEZBU1RQICMjIyMjIyMjIyMjIwojIFVzZXMgcGFyYW1ldGVyIHN1YnN0aXR1dGlvbiAoZS5nLiAke1IxX3NhbXBsZV9uYW1lJSVfKn0pdG8gcm0gdGhlIF9SWzEyXQojIFVzZXMgTkVCIGFkYXB0ZXIgZmlsZQoKCiMgUnVuIGZhc3RwIG9uIGZpbGVzCmVjaG8gIkJlZ2lubmluZyBmYXN0cCB0cmltbWluZy4iCmVjaG8gIiIKCnRpbWUgXApmb3IgaW5kZXggaW4gIiR7IWZhc3RxX2FycmF5X1IxW0BdfSIKZG8KICAjIEdldCBzYW1wbGUgbmFtZQogIFIxX3NhbXBsZV9uYW1lPSIke1IxX25hbWVzX2FycmF5W2luZGV4XSUlXyp9IgogIFIyX3NhbXBsZV9uYW1lPSIke1IyX25hbWVzX2FycmF5W2luZGV4XSUlXyp9IgoKCiAgIyBCZWdpbiBmYXN0cCB0cmltbWluZwogICR7cHJvZ3JhbXNfYXJyYXlbZmFzdHBdfSBcCiAgLS1pbjEgJHtmYXN0cV9hcnJheV9SMVtpbmRleF19IFwKICAtLWluMiAke2Zhc3RxX2FycmF5X1IyW2luZGV4XX0gXAogIC0tYWRhcHRlcl9mYXN0YSAke291dHB1dF9kaXJfdG9wfS8ke05FQl9hZGFwdGVyc19mYXN0YX0gXAogIC0tdHJpbV9wb2x5X2cgXAogIC0tb3ZlcmxhcF9sZW5fcmVxdWlyZSAxNyBcCiAgLS1sZW5ndGhfbGltaXQgMzEgXAogIC0tbWVyZ2UgXAogIC0tbWVyZ2VkX291dCAke3RyaW1tZWRfcmVhZHNfZGlyfS8ke1IxX3NhbXBsZV9uYW1lfS1mYXN0cC1hZGFwdGVycy1wb2x5Ry0ke21heF9yZWFkX2xlbmd0aH1icC1tZXJnZWQuZnEuZ3ogXAogIC0tdGhyZWFkICR7dGhyZWFkc30gXAogIC0taHRtbCAiJHt0cmltbWVkX3JlYWRzX2Rpcn0vJHtSMV9zYW1wbGVfbmFtZX0tZmFzdHAtYWRhcHRlcnMtcG9seUctJHttYXhfcmVhZF9sZW5ndGh9YnAtbWVyZ2VkLmh0bWwiIFwKICAtLWpzb24gIiR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7UjFfc2FtcGxlX25hbWV9LWZhc3RwLWFkYXB0ZXJzLXBvbHlHLSR7bWF4X3JlYWRfbGVuZ3RofWJwLW1lcmdlZC5qc29uIiBcCiAgLS1yZXBvcnRfdGl0bGUgIiR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7UjFfc2FtcGxlX25hbWV9LWZhc3RwLWFkYXB0ZXJzLXBvbHlHLSR7bWF4X3JlYWRfbGVuZ3RofWJwLW1lcmdlZCIKICAgIAogICMgTW92ZSB0byB0cmltbWVkIGRpcmVjdG9yeQogICMgVGhpcyBpcyBkb25lIHNvIGNoZWNrc3VtcyBmaWxlIGRvZXNuJ3QgaW5jbHVkZSBleGNlc3MgcGF0aAogIGNkICR7dHJpbW1lZF9yZWFkc19kaXJ9CgogICMgR2VuZXJhdGUgbWQ1IGNoZWNrc3VtcyBmb3IgbmV3bHkgdHJpbW1lZCBmaWxlcwogIHsKICAgIG1kNXN1bSAiJHtSMV9zYW1wbGVfbmFtZX0tZmFzdHAtYWRhcHRlcnMtcG9seUctJHttYXhfcmVhZF9sZW5ndGh9YnAtbWVyZ2VkLmZxLmd6IgogIH0gPj4gIiR7dHJpbW1lZF9jaGVja3N1bXN9IgogICAgCiAgIyBDaGFuZ2UgYmFjayB0byB0byByYXcgcmVhZHMgZGlyZWN0b3J5CiAgY2QgIiR7cmF3X3JlYWRzX2Rpcn0iCgpkb25lCgplY2hvICIiCmVjaG8gImZhc3RwIHRyaW1taW5nIGNvbXBsZXRlLiIKZWNobyAiIgoKZWNobyAiVHJpbW1lZCBGYXN0UXMgTUQ1IGNoZWNrc3VtczoiCmVjaG8gIiIKCmNhdCAiJHt0cmltbWVkX3JlYWRzX2Rpcn0vJHt0cmltbWVkX2NoZWNrc3Vtc30iCgojIyMjIyMjIyMjIyMgRU5EIGZhc3RwICMjIyMjIyMjIyMjIwoKYGBgCgojIEZhc3RRQy9NdWx0aVFDIG9uIHRyaW1tZWQgcmVhZHMKCmBgYHtiYXNoIEZhc3RRQy1NdWx0aVFDLXRyaW1tZWQtcmVhZHMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIENyZWF0ZSBvdXRwdXQgZGlyZWN0b3J5LCBpZiBpdCBkb2Vzbid0IGV4aXN0Lgpta2RpciAtLXBhcmVudHMgIiR7dHJpbW1lZF9mYXN0cWNfZGlyfSIKCiMjIyMjIyMjIyMjIyBSVU4gRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIE5PVEU6IERvIE5PVCBxdW90ZSByYXdfZmFzdHFjX2xpc3QKIyBDcmVhdGUgYXJyYXkgb2YgdHJpbW1lZCBGYXN0UXMKdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCR7dHJpbW1lZF9yZWFkc19kaXJ9LyptZXJnZWQuZnEuZ3opCgojIFBhc3MgYXJyYXkgY29udGVudHMgdG8gbmV3IHZhcmlhYmxlIGFzIHNwYWNlLWRlbGltaXRlZCBsaXN0CnRyaW1tZWRfZmFzdHFjX2xpc3Q9JChlY2hvICIke3RyaW1tZWRfZmFzdHFzX2FycmF5WypdfSIpCgplY2hvICJCZWdpbm5pbmcgRmFzdFFDIG9uIHJhdyByZWFkcy4uLiIKZWNobyAiIgoKIyBSdW4gRmFzdFFDCiR7cHJvZ3JhbXNfYXJyYXlbZmFzdHFjXX0gXAotLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0ZGlyICR7dHJpbW1lZF9mYXN0cWNfZGlyfSBcCi0tcXVpZXQgXAoke3RyaW1tZWRfZmFzdHFjX2xpc3R9CgplY2hvICJGYXN0UUMgb24gdHJpbW1lZCByZWFkcyBjb21wbGV0ZSEiCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIyMjIyMjIyMjIFJVTiBNVUxUSVFDICMjIyMjIyMjIyMjIwplY2hvICJCZWdpbm5pbmcgTXVsdGlRQyBvbiByYXcgRmFzdFFDLi4uIgplY2hvICIiCgoke3Byb2dyYW1zX2FycmF5W211bHRpcWNdfSAke3RyaW1tZWRfZmFzdHFjX2Rpcn0gLW8gJHt0cmltbWVkX2Zhc3RxY19kaXJ9CgplY2hvICIiCmVjaG8gIk11bHRpUUMgb24gdHJpbW1lZCBGYXN0UXMgY29tcGxldGUuIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIE1VTFRJUUMgIyMjIyMjIyMjIyMjCgplY2hvICJSZW1vdmluZyBGYXN0UUMgemlwIGZpbGVzLiIKZWNobyAiIgpybSAke3RyaW1tZWRfZmFzdHFjX2Rpcn0vKi56aXAKZWNobyAiRmFzdFFDIHppcCBmaWxlcyByZW1vdmVkLiIKZWNobyAiIgoKIyBWaWV3IGRpcmVjdG9yeSBjb250ZW50cwpscyAtbGggJHt0cmltbWVkX2Zhc3RxY19kaXJ9CgpgYGAKCiMgU3VtbWFyeQoKQSBxdWljayBjb21wYXJpc29uIG9mIHJhdyBhbmQgdHJpbW1lZCByZWFkcyB0byBzaG93IHRyaW1taW5nIHdvcmtlZDoKCi0gICBxdWFsaXR5IGlzIGltcHJvdmVkCi0gICBsZW5ndGggaXMgMzFicAotICAgYWRhcHRlcnMgcmVtb3ZlZAotICAgbWVyZ2VkCgp8IFJBVyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgVFJJTU1FRCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8ICFbUmF3IE11bHRpUUMgcGVyIGJhc2Ugc2VxdWVuY2UgcXVhbGl0eSBwbG90XShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9vdXRwdXQvMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nL3Jhdy1mYXN0cWMvZmFzdHFjX3Blcl9iYXNlX3NlcXVlbmNlX3F1YWxpdHlfcGxvdC5wbmc/cmF3PXRydWUpIHwgIVtUcmltbWVkIE11bHRpUUMgcGVyIGJhc2Ugc2VxdWVuY2UgcXVhbGl0eSBwbG90XShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9vdXRwdXQvMDYuMi1QZXZlLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQvdHJpbW1lZC1mYXN0cWMvZmFzdHFjX3Blcl9iYXNlX3NlcXVlbmNlX3F1YWxpdHlfcGxvdC5wbmc/cmF3PXRydWUpIHwKfCAhW1JhdyBNdWx0aVFDIGFkYXB0ZXIgY29udGVudCBwbG90XShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9vdXRwdXQvMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nL3Jhdy1mYXN0cWMvZmFzdHFjX2FkYXB0ZXJfY29udGVudF9wbG90LnBuZz9yYXc9dHJ1ZSkgICAgICAgICAgICAgICAgICAgICB8ICFbVHJpbW1lZCBNdWx0aVFDIGFkYXB0ZXIgY29udGVudCBwbG90XShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9vdXRwdXQvMDYuMi1QZXZlLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQvdHJpbW1lZC1mYXN0cWMvZmFzdHFjX2FkYXB0ZXJfY29udGVudF9wbG90LnBuZz9yYXc9dHJ1ZSkgICAgICAgICAgICAgICAgICAgICB8CgojIENpdGF0aW9ucw==