FastQC/MultiQC (Ewels et al. 2016; Andrews, n.d.) assessment of raw and flexbar-trimmed (Dodt et al. 2012; Roehr, Dieterich, and Reinert 2017) sequences of E5 P.evermanni sRNAseq data from 20230515.
Inputs:
- sRNAseq gzipped 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 reads with final length of 25bp: *flexbar_trim.25bp.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 "# 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-Peve-sRNAseq-trimming'
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=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-fastqc'
echo 'export trimmed_reads_dir=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads'
echo ""
echo "# Paths to programs"
echo 'export fastqc=/home/shared/FastQC-0.12.1/fastqc'
echo 'export flexbar=/home/shared/flexbar-3.5.0-linux/flexbar'
echo 'export multiqc=/home/sam/programs/mambaforge/bin/multiqc'
echo ""
echo "# Set FastQ filename patterns"
echo "export fastq_pattern='*.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 "# Set maximum read length"
echo 'export max_read_length=25'
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 '[flexbar]="${flexbar}"'
echo ")"
} > .bashvars
cat .bashvars
#### Assign Variables ####
# 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-Peve-sRNAseq-trimming
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=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-fastqc
export trimmed_reads_dir=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads
# Paths to programs
export fastqc=/home/shared/FastQC-0.12.1/fastqc
export flexbar=/home/shared/flexbar-3.5.0-linux/flexbar
export multiqc=/home/sam/programs/mambaforge/bin/multiqc
# Set FastQ filename patterns
export fastq_pattern='*.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
# Set maximum read length
export max_read_length=25
# 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}" \
[flexbar]="${flexbar}"
)
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.
# Load bash variables into memory
source .bashvars
wget \
--directory-prefix ${raw_reads_dir} \
--recursive \
--no-check-certificate \
--continue \
--cut-dirs 3 \
--no-host-directories \
--no-parent \
--quiet \
--accept "sRNA*,checksums.md5" ${raw_reads_url}
ls -lh "${raw_reads_dir}"
total 5.6G
-rw-r--r-- 1 sam sam 798 May 17 11:23 checksums.md5
-rw-r--r-- 1 sam sam 953M May 17 10:46 sRNA-POR-73-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 1.1G May 17 10:47 sRNA-POR-73-S1-TP2_R2_001.fastq.gz
-rw-r--r-- 1 sam sam 899M May 17 10:48 sRNA-POR-79-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 916M May 17 10:49 sRNA-POR-79-S1-TP2_R2_001.fastq.gz
-rw-r--r-- 1 sam sam 934M May 17 10:51 sRNA-POR-82-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 959M May 17 10:52 sRNA-POR-82-S1-TP2_R2_001.fastq.gz
Verify raw read checksums
# Load bash variables into memory
source .bashvars
cd "${raw_reads_dir}"
# Checksums file contains other files, so this just looks for the sRNAseq files.
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 flexbar trimming
# Load bash variables into memory
source .bashvars
echo "Creating adapters FastA."
echo ""
adapter_count=0
# Check for adapters file first
# Then create adapters file if doesn't exist
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-Peve-sRNAseq-trimming/NEB-adapters.fasta already exists. Nothing to do.
Adapters FastA:
>adapter_1
AGATCGGAAGAGCACACGTCTGAACTCCAGTCAC
>adapter_2
GATCGTCGGACTGTAGAACTCTGAACGTGTAGATCTCGGTGGTCGCCGTATCATT
FastQC/MultiQC on raw reads
# Load bash variables into memory
source .bashvars
############ RUN FASTQC ############
# Create array of trimmed FastQs
raw_fastqs_array=(${raw_reads_dir}/${fastq_pattern})
# Pass array contents to new variable as space-delimited list
raw_fastqc_list=$(echo "${raw_fastqs_array[*]}")
echo "Beginning FastQC on raw reads..."
echo ""
# Run FastQC
### NOTE: Do NOT quote raw_fastqc_list
${programs_array[fastqc]} \
--threads ${threads} \
--outdir ${raw_fastqc_dir} \
--quiet \
${raw_fastqc_list}
echo "FastQC on raw reads complete!"
echo ""
############ END FASTQC ############
############ RUN MULTIQC ############
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 ""
############ END MULTIQC ############
echo "Removing FastQC zip files."
echo ""
rm ${raw_fastqc_dir}/*.zip
echo "FastQC zip files removed."
echo ""
# View directory contents
ls -lh ${raw_fastqc_dir}
# Load bash variables into memory
source .bashvars
# Change to directory with raw reads
cd "${raw_reads_dir}"
# Create arrays of FastQ R1 files and sample names
# Do NOT quote R1_fastq_pattern variable
for fastq in ${R1_fastq_pattern}
do
fastq_array_R1+=("${fastq}")
# Use parameter substitution to remove all text up to and including last "." from
# right side of string.
R1_names_array+=("${fastq%%.*}")
done
# Create array of FastQ R2 files
# Do NOT quote R2_fastq_pattern variable
for fastq in ${R2_fastq_pattern}
do
fastq_array_R2+=("${fastq}")
# Use parameter substitution to remove all text up to and including last "." from
# right side of string.
R2_names_array+=("${fastq%%.*}")
done
############ RUN FLEXBAR ############
# Uses parameter substitution (e.g. ${R1_sample_name%%_*})to rm the _R[12]
# Uses NEB adapter file
# --adapter-pair-overlap ON: Recommended by NEB sRNA kit
# --qtrim-threshold 25: Minimum quality
# --qtrim-format i1.8: Sets sequencer as illumina
# --post-trim-length: Trim reads from 3' end to max length
# --target: Sets file naming patterns
# --zip-output GZ: Sets type of compression. GZ = gzip
# Run flexbar on files
echo "Beginning flexbar trimming."
echo ""
time \
for index in "${!fastq_array_R1[@]}"
do
R1_sample_name="${R1_names_array[index]}"
R2_sample_name="${R2_names_array[index]}"
# Begin flexbar trimming
${programs_array[flexbar]} \
--reads ${fastq_array_R1[index]} \
--reads2 ${fastq_array_R2[index]} \
--adapters ${output_dir_top}/${NEB_adapters_fasta} \
--adapter-pair-overlap ON \
--qtrim-format i1.8 \
--qtrim-threshold 25 \
--post-trim-length ${max_read_length} \
--threads ${threads} \
--target "${trimmed_reads_dir}/${R1_sample_name%%_*}.flexbar_trim.${max_read_length}bp" \
--zip-output GZ
# Move to trimmed directory
# This is done so checksums file doesn't include excess path
cd ${trimmed_reads_dir}
# Generate md5 checksums for newly trimmed files
{
md5sum "${R1_sample_name%%_*}.flexbar_trim.${max_read_length}bp_1.fastq.gz"
md5sum "${R2_sample_name%%_*}.flexbar_trim.${max_read_length}bp_2.fastq.gz"
} >> "${trimmed_checksums}"
# Change back to to raw reads directory
cd "${raw_reads_dir}"
done
echo ""
echo "flexbar trimming complete."
echo ""
echo "Trimmed FastQs MD5 checksums:"
echo ""
cat "${trimmed_reads_dir}/${trimmed_checksums}"
############ END FLEXBAR ############
FastQC/MultiQC on trimmed reads
# Load bash variables into memory
source .bashvars
############ RUN FASTQC ############
### NOTE: Do NOT quote raw_fastqc_list
# Create array of trimmed FastQs
trimmed_fastqs_array=(${trimmed_reads_dir}/${fastq_pattern})
# Pass array contents to new variable as space-delimited list
trimmed_fastqc_list=$(echo "${trimmed_fastqs_array[*]}")
echo "Beginning FastQC on raw reads..."
echo ""
# Run FastQC
${programs_array[fastqc]} \
--threads ${threads} \
--outdir ${trimmed_fastqc_dir} \
--quiet \
${trimmed_fastqc_list}
echo "FastQC on trimmed reads complete!"
echo ""
############ END FASTQC ############
############ RUN MULTIQC ############
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 ""
############ END MULTIQC ############
echo "Removing FastQC zip files."
echo ""
rm ${trimmed_fastqc_dir}/*.zip
echo "FastQC zip files removed."
echo ""
# View directory contents
ls -lh ${trimmed_fastqc_dir}
Summary
A quick comparison of raw and trimmed reads to show trimming worked:
- quality is improved
- length is 25bp
- adapters removed
Citations
Andrews, Simon. n.d. “FastQC.” Github.
Dodt, Matthias, Johannes T Roehr, Rina Ahmed, and Christoph Dieterich. 2012. “FLEXBAR-Flexible Barcode and Adapter Processing for Next-Generation Sequencing Platforms.” Biology 1 (3): 895–905.
Ewels, Philip, Måns Magnusson, Sverker Lundin, and Max Käller. 2016.
“MultiQC: Summarize Analysis Results for Multiple Tools and Samples in a Single Report.” Bioinformatics 32 (19): 3047–48.
https://doi.org/10.1093/bioinformatics/btw354.
Roehr, Johannes T, Christoph Dieterich, and Knut Reinert. 2017. “Flexbar 3.0 - SIMD and Multicore Parallelization.” Bioinformatics 33 (18): 2941–42.
LS0tCnRpdGxlOiAiMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nIgphdXRob3I6ICJTYW0gV2hpdGUiCmRhdGU6ICIyMDIzLTExLTE1IgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgZ2l0aHViX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgpsaW5rLWNpdGF0aW9uczogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmV0aWN1bGF0ZSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBGQUxTRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKRmFzdFFDL011bHRpUUMgW0Bld2VsczIwMTY7IEBBbmRyZXdzX3VuZGF0ZWQtbmZdIGFzc2Vzc21lbnQgb2YgcmF3IGFuZCBbZmxleGJhcl0oaHR0cHM6Ly9naXRodWIuY29tL3NlcWFuL2ZsZXhiYXIpLXRyaW1tZWQgW0BEb2R0MjAxMi1ydDsgQFJvZWhyMjAxNy1kcl0gc2VxdWVuY2VzIG9mIEU1ICpQLmV2ZXJtYW5uaSogc1JOQXNlcSBkYXRhIGZyb20gWzIwMjMwNTE1XShodHRwczovL3JvYmVydHNsYWIuZ2l0aHViLmlvL3NhbXMtbm90ZWJvb2svcG9zdHMvMjAyMy8yMDIzLTA1LTE3LURhdGEtTWFuYWdlbWVudC0tLUU1LUNvcmFsLVJOQS1zZXEtYW5kLXNSTkEtc2VxLVJlb3JnYW5pemluZy1hbmQtUmVuYW1pbmcvKS4KCklucHV0czoKCi0gICBzUk5Bc2VxIGd6aXBwZWQgRmFzdFFzIChlLmcuIGAqLmZhc3RxLmd6YCkKCk91dHB1dHM6CgotICAgW2BGYXN0UUNgXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9wcm9qZWN0cy9mYXN0cWMvKSBIVE1MIHJlcG9ydHMgZm9yIHJhdyBhbmQgdHJpbW1lZCByZWFkcy4KCi0gICBbYE11bHRpUUNgXShodHRwczovL211bHRpcWMuaW5mby8pIEhUTUwgc3VtbWFyaWVzIG9mIFtgRmFzdFFDYF0oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjLykgZm9yIHJhdyBhbmQgdHJpbW1lZCByZWFkcy4KCi0gICBUcmltbWVkIHJlYWRzIHdpdGggZmluYWwgbGVuZ3RoIG9mIDI1YnA6IGAqZmxleGJhcl90cmltLjI1YnAuZmFzdHEuZ3pgCgpMaWJyYXJpZXMgd2VyZSBwcmVwYXJlZCBhbmQgc2VxdWVuY2VkIGJ5IEF6ZW50YToKCi0gICBMaWJyYXJ5IHByZXA6IFtORUIgbmVibmV4dC1zbWFsbC1ybmEtbGlicmFyeS1wcmVwLXNldC1mb3ItaWxsdW1pbmEga2l0XShodHRwczovL3d3dy5uZWIuY29tL2VuLXVzLy0vbWVkaWEvbmVidXMvZmlsZXMvbWFudWFscy9tYW51YWxlNzMwMF9lNzMzMF9lNzU2MF9lNzU4MC5wZGY/cmV2PWQwOTY0YTJlNjM3ODQzYjFhZmNiOWY3ZDY2NmQwN2IyJmhhc2g9N0FDMEIwRUIwMTI3MDhFRkFCMEU0REJFRUFGMTQ0NkEpIChQREYpCgotICAgU2VxdWVuY2luZzogSWxsdW1pbmEgSGlTZXEgNDAwMCwgMTUwYnAgUEUKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDcmVhdGUgYSBCYXNoIHZhcmlhYmxlcyBmaWxlCgpUaGlzIGFsbG93cyB1c2FnZSBvZiBCYXNoIHZhcmlhYmxlcyBhY3Jvc3MgUiBNYXJrZG93biBjaHVua3MuCgpgYGB7ciBzYXZlLWJhc2gtdmFyaWFibGVzLXRvLXJ2YXJzLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KewplY2hvICIjIyMjIEFzc2lnbiBWYXJpYWJsZXMgIyMjIyIKZWNobyAiIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgZGVlcF9kaXZlX2Rpcj0vaG9tZS9zaGFyZWQvOFRCX0hERF8wMS9zYW0vZ2l0cmVwb3MvZGVlcC1kaXZlJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9JHtkZWVwX2RpdmVfZGlyfS9FLVBldmUvb3V0cHV0LzA2LVBldmUtc1JOQXNlcS10cmltbWluZycKZWNobyAnZXhwb3J0IHJhd19mYXN0cWNfZGlyPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wNi1QZXZlLXNSTkFzZXEtdHJpbW1pbmcvcmF3LWZhc3RxYycKZWNobyAnZXhwb3J0IHJhd19yZWFkc19kaXI9JHtkZWVwX2RpdmVfZGlyfS9FLVBldmUvZGF0YS8wNi1QZXZlLXNSTkFzZXEtdHJpbW1pbmcvcmF3LXJlYWRzJwplY2hvICdleHBvcnQgcmF3X3JlYWRzX3VybD0iaHR0cHM6Ly9vd2wuZmlzaC53YXNoaW5ndG9uLmVkdS9uaWdodGluZ2FsZXMvUF9ldmVybWFubmkvMzAtODUyNDMwMjM1LyInCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3RxY19kaXI9JHtkZWVwX2RpdmVfZGlyfS9FLVBldmUvb3V0cHV0LzA2LVBldmUtc1JOQXNlcS10cmltbWluZy90cmltbWVkLWZhc3RxYycKZWNobyAnZXhwb3J0IHRyaW1tZWRfcmVhZHNfZGlyPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wNi1QZXZlLXNSTkFzZXEtdHJpbW1pbmcvdHJpbW1lZC1yZWFkcycKZWNobyAiIgoKZWNobyAiIyBQYXRocyB0byBwcm9ncmFtcyIKZWNobyAnZXhwb3J0IGZhc3RxYz0vaG9tZS9zaGFyZWQvRmFzdFFDLTAuMTIuMS9mYXN0cWMnCmVjaG8gJ2V4cG9ydCBmbGV4YmFyPS9ob21lL3NoYXJlZC9mbGV4YmFyLTMuNS4wLWxpbnV4L2ZsZXhiYXInCmVjaG8gJ2V4cG9ydCBtdWx0aXFjPS9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2Jpbi9tdWx0aXFjJwplY2hvICIiCgoKCmVjaG8gIiMgU2V0IEZhc3RRIGZpbGVuYW1lIHBhdHRlcm5zIgplY2hvICJleHBvcnQgZmFzdHFfcGF0dGVybj0nKi5mYXN0cS5neiciCmVjaG8gImV4cG9ydCBSMV9mYXN0cV9wYXR0ZXJuPScqX1IxXyouZmFzdHEuZ3onIgplY2hvICJleHBvcnQgUjJfZmFzdHFfcGF0dGVybj0nKl9SMl8qLmZhc3RxLmd6JyIKZWNobyAiIgoKZWNobyAiIyBTZXQgbnVtYmVyIG9mIENQVXMgdG8gdXNlIgplY2hvICdleHBvcnQgdGhyZWFkcz00MCcKZWNobyAiIgoKZWNobyAiIyBTZXQgbWF4aW11bSByZWFkIGxlbmd0aCIKZWNobyAnZXhwb3J0IG1heF9yZWFkX2xlbmd0aD0yNScKZWNobyAiIgoKZWNobyAiIyBJbnB1dC9vdXRwdXQgZmlsZXMiCmVjaG8gJ2V4cG9ydCBmYXN0cV9jaGVja3N1bXM9aW5wdXRfZmFzdHFfY2hlY2tzdW1zLm1kNScKZWNobyAnZXhwb3J0IHRyaW1tZWRfY2hlY2tzdW1zPXRyaW1tZWRfZmFzdHFfY2hlY2tzdW1zLm1kNScKZWNobyAnZXhwb3J0IE5FQl9hZGFwdGVyc19mYXN0YT1ORUItYWRhcHRlcnMuZmFzdGEnCmVjaG8gIiIKCmVjaG8gIiMjIE5FQiBuZWJuZXh0LXNtYWxsLXJuYS1saWJyYXJ5LXByZXAtc2V0LWZvci1pbGx1bWluYSBhZGFwdGVycyIKZWNobyAnZXhwb3J0IGZpcnN0X2FkYXB0ZXI9IkFHQVRDR0dBQUdBR0NBQ0FDR1RDVEdBQUNUQ0NBR1RDQUMiJwplY2hvICdleHBvcnQgc2Vjb25kX2FkYXB0ZXI9IkdBVENHVENHR0FDVEdUQUdBQUNUQ1RHQUFDR1RHVEFHQVRDVENHR1RHR1RDR0NDR1RBVENBVFQiJwplY2hvICIiCgplY2hvICIjIyBJbml0aXRhbGl6ZSBhcnJheXMiCmVjaG8gJ2V4cG9ydCBmYXN0cV9hcnJheV9SMT0oKScKZWNobyAnZXhwb3J0IGZhc3RxX2FycmF5X1IyPSgpJwplY2hvICdleHBvcnQgcmF3X2Zhc3Rxc19hcnJheT0oKScKZWNobyAnZXhwb3J0IFIxX25hbWVzX2FycmF5PSgpJwplY2hvICdleHBvcnQgUjJfbmFtZXNfYXJyYXk9KCknCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3Rxc19hcnJheT0oKScKZWNobyAiIgoKZWNobyAiIyBQcm9ncmFtcyBhc3NvY2lhdGl2ZSBhcnJheSIKZWNobyAiZGVjbGFyZSAtQSBwcm9ncmFtc19hcnJheSIKZWNobyAicHJvZ3JhbXNfYXJyYXk9KCIKZWNobyAnW2Zhc3RxY109IiR7ZmFzdHFjfSIgXCcKZWNobyAnW211bHRpcWNdPSIke211bHRpcWN9IiBcJwplY2hvICdbZmxleGJhcl09IiR7ZmxleGJhcn0iJwplY2hvICIpIgp9ID4gLmJhc2h2YXJzCgpjYXQgLmJhc2h2YXJzCmBgYAoKIyBEb3dubG9hZCByYXcgc1JOQXNlcSByZWFkcwoKUmVhZHMgYXJlIGRvd25sb2FkZWQgZnJvbSA8aHR0cHM6Ly9vd2wuZmlzaC53YXNoaW5ndG9uLmVkdS9uaWdodGluZ2FsZXMvUF9ldmVybWFubmkvMzAtODUyNDMwMjM1Lz4KClRoZSBgLS1jdXQtZGlycyAzYCBjb21tYW5kIGN1dHMgdGhlIHByZWNlZGluZyBkaXJlY3Rvcnkgc3RydWN0dXJlIChpLmUuIGBuaWdodGluZ2FsZXMvUF9ldmVybWFubmkvMzAtODUyNDMwMjM1L2ApIHNvIHRoYXQgd2UganVzdCBlbmQgdXAgd2l0aCB0aGUgcmVhZHMuCgpgYGB7YmFzaCBkb3dubG9hZC1yYXctcmVhZHMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCndnZXQgXAotLWRpcmVjdG9yeS1wcmVmaXggJHtyYXdfcmVhZHNfZGlyfSBcCi0tcmVjdXJzaXZlIFwKLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSBcCi0tY29udGludWUgXAotLWN1dC1kaXJzIDMgXAotLW5vLWhvc3QtZGlyZWN0b3JpZXMgXAotLW5vLXBhcmVudCBcCi0tcXVpZXQgXAotLWFjY2VwdCAic1JOQSosY2hlY2tzdW1zLm1kNSIgJHtyYXdfcmVhZHNfdXJsfQoKbHMgLWxoICIke3Jhd19yZWFkc19kaXJ9IgpgYGAKCiMjIFZlcmlmeSByYXcgcmVhZCBjaGVja3N1bXMKCmBgYHtiYXNoIHZlcmlmeS1yYXctcmVhZC1jaGVja3N1bXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDaGVja3N1bXMgZmlsZSBjb250YWlucyBvdGhlciBmaWxlcywgc28gdGhpcyBqdXN0IGxvb2tzIGZvciB0aGUgc1JOQXNlcSBmaWxlcy4KZ3JlcCAic1JOQSIgY2hlY2tzdW1zLm1kNSB8IG1kNXN1bSAtLWNoZWNrCmBgYAoKIyBDcmVhdGUgYWRhcHRlcnMgRmFzdEEgZm9yIHVzZSB3aXRoIFtmbGV4YmFyXShodHRwczovL2dpdGh1Yi5jb20vc2VxYW4vZmxleGJhcikgdHJpbW1pbmcKCmBgYHtiYXNoIGNyZWF0ZS1GYXN0QS1vZi1hZGFwdGVycywgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKZWNobyAiQ3JlYXRpbmcgYWRhcHRlcnMgRmFzdEEuIgplY2hvICIiCmFkYXB0ZXJfY291bnQ9MAoKIyBDaGVjayBmb3IgYWRhcHRlcnMgZmlsZSBmaXJzdAojIFRoZW4gY3JlYXRlIGFkYXB0ZXJzIGZpbGUgaWYgZG9lc24ndCBleGlzdAppZiBbIC1mICIke291dHB1dF9kaXJfdG9wfS8ke05FQl9hZGFwdGVyc19mYXN0YX0iIF07IHRoZW4KICBlY2hvICIke291dHB1dF9kaXJfdG9wfS8ke05FQl9hZGFwdGVyc19mYXN0YX0gYWxyZWFkeSBleGlzdHMuIE5vdGhpbmcgdG8gZG8uIgplbHNlCiAgZm9yIGFkYXB0ZXIgaW4gIiR7Zmlyc3RfYWRhcHRlcn0iICIke3NlY29uZF9hZGFwdGVyfSIKICBkbwogICAgYWRhcHRlcl9jb3VudD0kKChhZGFwdGVyX2NvdW50ICsgMSkpCiAgICBwcmludGYgIj4lc1xuJXNcbiIgImFkYXB0ZXJfJHthZGFwdGVyX2NvdW50fSIgIiR7YWRhcHRlcn0iCiAgZG9uZSA+PiAiJHtvdXRwdXRfZGlyX3RvcH0vJHtORUJfYWRhcHRlcnNfZmFzdGF9IgpmaQoKZWNobyAiIgplY2hvICJBZGFwdGVycyBGYXN0QToiCmVjaG8gIiIKY2F0ICIke291dHB1dF9kaXJfdG9wfS8ke05FQl9hZGFwdGVyc19mYXN0YX0iCmVjaG8gIiIKYGBgCgojIEZhc3RRQy9NdWx0aVFDIG9uIHJhdyByZWFkcwoKYGBge2Jhc2ggcmF3LWZhc3RxYy1tdWx0aXFjLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyMjIyMjIyMjIyMjIFJVTiBGQVNUUUMgIyMjIyMjIyMjIyMjCgoKIyBDcmVhdGUgYXJyYXkgb2YgdHJpbW1lZCBGYXN0UXMKcmF3X2Zhc3Rxc19hcnJheT0oJHtyYXdfcmVhZHNfZGlyfS8ke2Zhc3RxX3BhdHRlcm59KQoKIyBQYXNzIGFycmF5IGNvbnRlbnRzIHRvIG5ldyB2YXJpYWJsZSBhcyBzcGFjZS1kZWxpbWl0ZWQgbGlzdApyYXdfZmFzdHFjX2xpc3Q9JChlY2hvICIke3Jhd19mYXN0cXNfYXJyYXlbKl19IikKCmVjaG8gIkJlZ2lubmluZyBGYXN0UUMgb24gcmF3IHJlYWRzLi4uIgplY2hvICIiCgojIFJ1biBGYXN0UUMKIyMjIE5PVEU6IERvIE5PVCBxdW90ZSByYXdfZmFzdHFjX2xpc3QKJHtwcm9ncmFtc19hcnJheVtmYXN0cWNdfSBcCi0tdGhyZWFkcyAke3RocmVhZHN9IFwKLS1vdXRkaXIgJHtyYXdfZmFzdHFjX2Rpcn0gXAotLXF1aWV0IFwKJHtyYXdfZmFzdHFjX2xpc3R9CgplY2hvICJGYXN0UUMgb24gcmF3IHJlYWRzIGNvbXBsZXRlISIKZWNobyAiIgoKIyMjIyMjIyMjIyMjIEVORCBGQVNUUUMgIyMjIyMjIyMjIyMjCgojIyMjIyMjIyMjIyMgUlVOIE1VTFRJUUMgIyMjIyMjIyMjIyMjCmVjaG8gIkJlZ2lubmluZyBNdWx0aVFDIG9uIHJhdyBGYXN0UUMuLi4iCmVjaG8gIiIKCiR7cHJvZ3JhbXNfYXJyYXlbbXVsdGlxY119ICR7cmF3X2Zhc3RxY19kaXJ9IC1vICR7cmF3X2Zhc3RxY19kaXJ9CgplY2hvICIiCmVjaG8gIk11bHRpUUMgb24gcmF3IEZhc3RRcyBjb21wbGV0ZS4iCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgTVVMVElRQyAjIyMjIyMjIyMjIyMKCmVjaG8gIlJlbW92aW5nIEZhc3RRQyB6aXAgZmlsZXMuIgplY2hvICIiCnJtICR7cmF3X2Zhc3RxY19kaXJ9LyouemlwCmVjaG8gIkZhc3RRQyB6aXAgZmlsZXMgcmVtb3ZlZC4iCmVjaG8gIiIKCiMgVmlldyBkaXJlY3RvcnkgY29udGVudHMKbHMgLWxoICR7cmF3X2Zhc3RxY19kaXJ9CgpgYGAKCiMgVHJpbW1pbmcgd2l0aCBbZmxleGJhcl0oaHR0cHM6Ly9naXRodWIuY29tL3NlcWFuL2ZsZXhiYXIpCgpgYGB7YmFzaCBmbGV4YmFyLXRyaW1taW5nLCBlbmdpbmU9J2Jhc2gnLCBjYWNoZT1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBDaGFuZ2UgdG8gZGlyZWN0b3J5IHdpdGggcmF3IHJlYWRzCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDcmVhdGUgYXJyYXlzIG9mIEZhc3RRIFIxIGZpbGVzIGFuZCBzYW1wbGUgbmFtZXMKIyBEbyBOT1QgcXVvdGUgUjFfZmFzdHFfcGF0dGVybiB2YXJpYWJsZQpmb3IgZmFzdHEgaW4gJHtSMV9mYXN0cV9wYXR0ZXJufQpkbwogIGZhc3RxX2FycmF5X1IxKz0oIiR7ZmFzdHF9IikKCiAgIyBVc2UgcGFyYW1ldGVyIHN1YnN0aXR1dGlvbiB0byByZW1vdmUgYWxsIHRleHQgdXAgdG8gYW5kIGluY2x1ZGluZyBsYXN0ICIuIiBmcm9tCiAgIyByaWdodCBzaWRlIG9mIHN0cmluZy4KICBSMV9uYW1lc19hcnJheSs9KCIke2Zhc3RxJSUuKn0iKQpkb25lCgojIENyZWF0ZSBhcnJheSBvZiBGYXN0USBSMiBmaWxlcwojIERvIE5PVCBxdW90ZSBSMl9mYXN0cV9wYXR0ZXJuIHZhcmlhYmxlCmZvciBmYXN0cSBpbiAke1IyX2Zhc3RxX3BhdHRlcm59CmRvCiAgZmFzdHFfYXJyYXlfUjIrPSgiJHtmYXN0cX0iKQoKICAjIFVzZSBwYXJhbWV0ZXIgc3Vic3RpdHV0aW9uIHRvIHJlbW92ZSBhbGwgdGV4dCB1cCB0byBhbmQgaW5jbHVkaW5nIGxhc3QgIi4iIGZyb20KICAjIHJpZ2h0IHNpZGUgb2Ygc3RyaW5nLgogIFIyX25hbWVzX2FycmF5Kz0oIiR7ZmFzdHElJS4qfSIpCmRvbmUKCgojIyMjIyMjIyMjIyMgUlVOIEZMRVhCQVIgIyMjIyMjIyMjIyMjCiMgVXNlcyBwYXJhbWV0ZXIgc3Vic3RpdHV0aW9uIChlLmcuICR7UjFfc2FtcGxlX25hbWUlJV8qfSl0byBybSB0aGUgX1JbMTJdCiMgVXNlcyBORUIgYWRhcHRlciBmaWxlCiMgLS1hZGFwdGVyLXBhaXItb3ZlcmxhcCBPTjogUmVjb21tZW5kZWQgYnkgTkVCIHNSTkEga2l0CiMgLS1xdHJpbS10aHJlc2hvbGQgMjU6IE1pbmltdW0gcXVhbGl0eQojIC0tcXRyaW0tZm9ybWF0IGkxLjg6IFNldHMgc2VxdWVuY2VyIGFzIGlsbHVtaW5hCiMgLS1wb3N0LXRyaW0tbGVuZ3RoOiBUcmltIHJlYWRzIGZyb20gMycgZW5kIHRvIG1heCBsZW5ndGgKIyAtLXRhcmdldDogU2V0cyBmaWxlIG5hbWluZyBwYXR0ZXJucwojIC0temlwLW91dHB1dCBHWjogU2V0cyB0eXBlIG9mIGNvbXByZXNzaW9uLiBHWiA9IGd6aXAKCiMgUnVuIGZsZXhiYXIgb24gZmlsZXMKZWNobyAiQmVnaW5uaW5nIGZsZXhiYXIgdHJpbW1pbmcuIgplY2hvICIiCgp0aW1lIFwKZm9yIGluZGV4IGluICIkeyFmYXN0cV9hcnJheV9SMVtAXX0iCmRvCiAgUjFfc2FtcGxlX25hbWU9IiR7UjFfbmFtZXNfYXJyYXlbaW5kZXhdfSIKICBSMl9zYW1wbGVfbmFtZT0iJHtSMl9uYW1lc19hcnJheVtpbmRleF19IgoKICAjIEJlZ2luIGZsZXhiYXIgdHJpbW1pbmcKICAke3Byb2dyYW1zX2FycmF5W2ZsZXhiYXJdfSBcCiAgLS1yZWFkcyAke2Zhc3RxX2FycmF5X1IxW2luZGV4XX0gXAogIC0tcmVhZHMyICR7ZmFzdHFfYXJyYXlfUjJbaW5kZXhdfSAgXAogIC0tYWRhcHRlcnMgJHtvdXRwdXRfZGlyX3RvcH0vJHtORUJfYWRhcHRlcnNfZmFzdGF9IFwKICAtLWFkYXB0ZXItcGFpci1vdmVybGFwIE9OIFwKICAtLXF0cmltLWZvcm1hdCBpMS44IFwKICAtLXF0cmltLXRocmVzaG9sZCAyNSBcCiAgLS1wb3N0LXRyaW0tbGVuZ3RoICR7bWF4X3JlYWRfbGVuZ3RofSBcCiAgLS10aHJlYWRzICR7dGhyZWFkc30gXAogIC0tdGFyZ2V0ICIke3RyaW1tZWRfcmVhZHNfZGlyfS8ke1IxX3NhbXBsZV9uYW1lJSVfKn0uZmxleGJhcl90cmltLiR7bWF4X3JlYWRfbGVuZ3RofWJwIiBcCiAgLS16aXAtb3V0cHV0IEdaCiAgICAgICAgCiAgICAjIE1vdmUgdG8gdHJpbW1lZCBkaXJlY3RvcnkKICAgICMgVGhpcyBpcyBkb25lIHNvIGNoZWNrc3VtcyBmaWxlIGRvZXNuJ3QgaW5jbHVkZSBleGNlc3MgcGF0aAogICAgY2QgJHt0cmltbWVkX3JlYWRzX2Rpcn0KCiAgICAjIEdlbmVyYXRlIG1kNSBjaGVja3N1bXMgZm9yIG5ld2x5IHRyaW1tZWQgZmlsZXMKICAgIHsKICAgICAgbWQ1c3VtICIke1IxX3NhbXBsZV9uYW1lJSVfKn0uZmxleGJhcl90cmltLiR7bWF4X3JlYWRfbGVuZ3RofWJwXzEuZmFzdHEuZ3oiCiAgICAgIG1kNXN1bSAiJHtSMl9zYW1wbGVfbmFtZSUlXyp9LmZsZXhiYXJfdHJpbS4ke21heF9yZWFkX2xlbmd0aH1icF8yLmZhc3RxLmd6IgogICAgfSA+PiAiJHt0cmltbWVkX2NoZWNrc3Vtc30iCiAgICAKICAgICMgQ2hhbmdlIGJhY2sgdG8gdG8gcmF3IHJlYWRzIGRpcmVjdG9yeQogICAgY2QgIiR7cmF3X3JlYWRzX2Rpcn0iCgpkb25lCgplY2hvICIiCmVjaG8gImZsZXhiYXIgdHJpbW1pbmcgY29tcGxldGUuIgplY2hvICIiCgplY2hvICJUcmltbWVkIEZhc3RRcyBNRDUgY2hlY2tzdW1zOiIKZWNobyAiIgoKY2F0ICIke3RyaW1tZWRfcmVhZHNfZGlyfS8ke3RyaW1tZWRfY2hlY2tzdW1zfSIKCiMjIyMjIyMjIyMjIyBFTkQgRkxFWEJBUiAjIyMjIyMjIyMjIyMKCmBgYAoKIyBGYXN0UUMvTXVsdGlRQyBvbiB0cmltbWVkIHJlYWRzCgpgYGB7YmFzaCBGYXN0UUMtTXVsdGlRQy10cmltbWVkLXJlYWRzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyMjIyMjIyMjIyMjIFJVTiBGQVNUUUMgIyMjIyMjIyMjIyMjCgojIyMgTk9URTogRG8gTk9UIHF1b3RlIHJhd19mYXN0cWNfbGlzdAojIENyZWF0ZSBhcnJheSBvZiB0cmltbWVkIEZhc3RRcwp0cmltbWVkX2Zhc3Rxc19hcnJheT0oJHt0cmltbWVkX3JlYWRzX2Rpcn0vJHtmYXN0cV9wYXR0ZXJufSkKCiMgUGFzcyBhcnJheSBjb250ZW50cyB0byBuZXcgdmFyaWFibGUgYXMgc3BhY2UtZGVsaW1pdGVkIGxpc3QKdHJpbW1lZF9mYXN0cWNfbGlzdD0kKGVjaG8gIiR7dHJpbW1lZF9mYXN0cXNfYXJyYXlbKl19IikKCmVjaG8gIkJlZ2lubmluZyBGYXN0UUMgb24gcmF3IHJlYWRzLi4uIgplY2hvICIiCgojIFJ1biBGYXN0UUMKJHtwcm9ncmFtc19hcnJheVtmYXN0cWNdfSBcCi0tdGhyZWFkcyAke3RocmVhZHN9IFwKLS1vdXRkaXIgJHt0cmltbWVkX2Zhc3RxY19kaXJ9IFwKLS1xdWlldCBcCiR7dHJpbW1lZF9mYXN0cWNfbGlzdH0KCmVjaG8gIkZhc3RRQyBvbiB0cmltbWVkIHJlYWRzIGNvbXBsZXRlISIKZWNobyAiIgoKIyMjIyMjIyMjIyMjIEVORCBGQVNUUUMgIyMjIyMjIyMjIyMjCgojIyMjIyMjIyMjIyMgUlVOIE1VTFRJUUMgIyMjIyMjIyMjIyMjCmVjaG8gIkJlZ2lubmluZyBNdWx0aVFDIG9uIHJhdyBGYXN0UUMuLi4iCmVjaG8gIiIKCiR7cHJvZ3JhbXNfYXJyYXlbbXVsdGlxY119ICR7dHJpbW1lZF9mYXN0cWNfZGlyfSAtbyAke3RyaW1tZWRfZmFzdHFjX2Rpcn0KCmVjaG8gIiIKZWNobyAiTXVsdGlRQyBvbiB0cmltbWVkIEZhc3RRcyBjb21wbGV0ZS4iCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgTVVMVElRQyAjIyMjIyMjIyMjIyMKCmVjaG8gIlJlbW92aW5nIEZhc3RRQyB6aXAgZmlsZXMuIgplY2hvICIiCnJtICR7dHJpbW1lZF9mYXN0cWNfZGlyfS8qLnppcAplY2hvICJGYXN0UUMgemlwIGZpbGVzIHJlbW92ZWQuIgplY2hvICIiCgojIFZpZXcgZGlyZWN0b3J5IGNvbnRlbnRzCmxzIC1saCAke3RyaW1tZWRfZmFzdHFjX2Rpcn0KCmBgYAoKIyBTdW1tYXJ5CgpBIHF1aWNrIGNvbXBhcmlzb24gb2YgcmF3IGFuZCB0cmltbWVkIHJlYWRzIHRvIHNob3cgdHJpbW1pbmcgd29ya2VkOgoKLSAgIHF1YWxpdHkgaXMgaW1wcm92ZWQKLSAgIGxlbmd0aCBpcyAyNWJwCi0gICBhZGFwdGVycyByZW1vdmVkCgp8IFJBVyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgVFJJTU1FRCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8ICFbUmF3IE11bHRpUUMgcGVyIGJhc2Ugc2VxdWVuY2UgcXVhbGl0eSBwbG90XShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9vdXRwdXQvMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nL3Jhdy1mYXN0cWMvZmFzdHFjX3Blcl9iYXNlX3NlcXVlbmNlX3F1YWxpdHlfcGxvdC5wbmc/cmF3PXRydWUpIHwgIVtUcmltbWVkIE11bHRpUUMgcGVyIGJhc2Ugc2VxdWVuY2UgcXVhbGl0eSBwbG90XShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9vdXRwdXQvMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nL3RyaW1tZWQtZmFzdHFjL2Zhc3RxY19wZXJfYmFzZV9zZXF1ZW5jZV9xdWFsaXR5X3Bsb3QucG5nP3Jhdz10cnVlKSB8CnwgIVtSYXcgTXVsdGlRQyBhZGFwdGVyIGNvbnRlbnQgcGxvdF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9FLVBldmUvb3V0cHV0LzA2LVBldmUtc1JOQXNlcS10cmltbWluZy9yYXctZmFzdHFjL2Zhc3RxY19hZGFwdGVyX2NvbnRlbnRfcGxvdC5wbmc/cmF3PXRydWUpICAgICAgICAgICAgICAgICAgICAgfCAhW1RyaW1tZWQgTXVsdGlRQyBhZGFwdGVyIGNvbnRlbnQgcGxvdF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9FLVBldmUvb3V0cHV0LzA2LVBldmUtc1JOQXNlcS10cmltbWluZy90cmltbWVkLWZhc3RxYy9mYXN0cWNfYWRhcHRlcl9jb250ZW50X3Bsb3QucG5nP3Jhdz10cnVlKSAgICAgICAgICAgICAgICAgICAgIHwKCiMgQ2l0YXRpb25zCg==