Introduction
FastQC/MultiQC assessment of raw and fastp
-trimmed sequences of E5 P.meandrina sRNAseq data from 20230515.
A 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:
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-adapters-polyG-31bp-merged.fq.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}/F-Pmea/output/08.2-Pmea-sRNAseq-trimming-31bp-fastp-merged'
echo 'export raw_reads_dir=${deep_dive_dir}/F-Pmea/data/sRNAseq-raw_reads'
echo 'export raw_fastqc_dir=${raw_reads_dir}/raw-fastqc'
echo 'export raw_reads_url="https://owl.fish.washington.edu/nightingales/P_meandrina/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*'"
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=31'
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 ####
# Data directories
export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive
export output_dir_top=${deep_dive_dir}/F-Pmea/output/08.2-Pmea-sRNAseq-trimming-31bp-fastp-merged
export raw_reads_dir=${deep_dive_dir}/F-Pmea/data/sRNAseq-raw_reads
export raw_fastqc_dir=${raw_reads_dir}/raw-fastqc
export raw_reads_url="https://owl.fish.washington.edu/nightingales/P_meandrina/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*'
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=31
# 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/A_pulchra/30-852430235/
The --cut-dirs 3
command cuts the preceding directory structure (i.e. nightingales/A_pulchra/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 "${fastq_pattern},checksums.md5" ${raw_reads_url}
ls -lh "${raw_reads_dir}"/${fastq_pattern}
-rw-r--r-- 1 sam sam 347K Feb 16 08:40 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-47-S1-TP2-fastp-adapters-polyG-31bp-merged.html
-rw-r--r-- 1 sam sam 89K Feb 16 08:40 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-47-S1-TP2-fastp-adapters-polyG-31bp-merged.json
-rw-r--r-- 1 sam sam 225K Feb 15 14:38 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-47-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.html
-rw-r--r-- 1 sam sam 55K Feb 15 14:38 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-47-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.json
-rw-r--r-- 1 sam sam 1.2G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-47-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 1.3G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-47-S1-TP2_R2_001.fastq.gz
-rw-r--r-- 1 sam sam 347K Feb 16 08:41 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-48-S1-TP2-fastp-adapters-polyG-31bp-merged.html
-rw-r--r-- 1 sam sam 89K Feb 16 08:41 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-48-S1-TP2-fastp-adapters-polyG-31bp-merged.json
-rw-r--r-- 1 sam sam 225K Feb 15 14:39 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-48-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.html
-rw-r--r-- 1 sam sam 55K Feb 15 14:39 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-48-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.json
-rw-r--r-- 1 sam sam 903M May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-48-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 1.1G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-48-S1-TP2_R2_001.fastq.gz
-rw-r--r-- 1 sam sam 348K Feb 16 08:42 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-50-S1-TP2-fastp-adapters-polyG-31bp-merged.html
-rw-r--r-- 1 sam sam 89K Feb 16 08:42 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-50-S1-TP2-fastp-adapters-polyG-31bp-merged.json
-rw-r--r-- 1 sam sam 225K Feb 15 14:39 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-50-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.html
-rw-r--r-- 1 sam sam 55K Feb 15 14:39 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-50-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.json
-rw-r--r-- 1 sam sam 1.1G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-50-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 1.2G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-50-S1-TP2_R2_001.fastq.gz
-rw-r--r-- 1 sam sam 347K Feb 16 08:43 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-53-S1-TP2-fastp-adapters-polyG-31bp-merged.html
-rw-r--r-- 1 sam sam 89K Feb 16 08:43 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-53-S1-TP2-fastp-adapters-polyG-31bp-merged.json
-rw-r--r-- 1 sam sam 225K Feb 15 14:40 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-53-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.html
-rw-r--r-- 1 sam sam 55K Feb 15 14:40 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-53-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.json
-rw-r--r-- 1 sam sam 1.1G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-53-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 1.2G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-53-S1-TP2_R2_001.fastq.gz
-rw-r--r-- 1 sam sam 347K Feb 16 08:44 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-57-S1-TP2-fastp-adapters-polyG-31bp-merged.html
-rw-r--r-- 1 sam sam 89K Feb 16 08:44 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-57-S1-TP2-fastp-adapters-polyG-31bp-merged.json
-rw-r--r-- 1 sam sam 225K Feb 15 14:41 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-57-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.html
-rw-r--r-- 1 sam sam 55K Feb 15 14:41 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-57-S1-TP2_R1_001.fastp-R1-31bp-auto_adapters-polyG.json
-rw-r--r-- 1 sam sam 1.1G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-57-S1-TP2_R1_001.fastq.gz
-rw-r--r-- 1 sam sam 1.2G May 17 2023 /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/F-Pmea/data/sRNAseq-raw_reads/sRNA-POC-57-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-POC-47-S1-TP2_R1_001.fastq.gz: OK
sRNA-POC-47-S1-TP2_R2_001.fastq.gz: OK
sRNA-POC-48-S1-TP2_R1_001.fastq.gz: OK
sRNA-POC-48-S1-TP2_R2_001.fastq.gz: OK
sRNA-POC-50-S1-TP2_R1_001.fastq.gz: OK
sRNA-POC-50-S1-TP2_R2_001.fastq.gz: OK
sRNA-POC-53-S1-TP2_R1_001.fastq.gz: OK
sRNA-POC-53-S1-TP2_R2_001.fastq.gz: OK
sRNA-POC-57-S1-TP2_R1_001.fastq.gz: OK
sRNA-POC-57-S1-TP2_R2_001.fastq.gz: OK
Create adapters FastA for use with fastp
trimming
# Load bash variables into memory
source .bashvars
mkdir --parents "${output_dir_top}"
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/F-Pmea/output/08.2-Pmea-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
# 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}
Trimming with fastp
# Load bash variables into memory
source .bashvars
# Create output directory, if it doesn't exist.
mkdir --parents "${trimmed_reads_dir}"
# 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 FASTP ############
# Uses parameter substitution (e.g. ${R1_sample_name%%_*})to rm the _R[12]
# Run fastp on files
echo "Beginning fastp trimming."
echo ""
time \
for index in "${!fastq_array_R1[@]}"
do
# Get sample name
R1_sample_name="${R1_names_array[index]%%_*}"
# Set fastp report title
trimmed_fastp_report_title="${R1_sample_name}-fastp-adapters-polyG-${max_read_length}bp-merged"
# Set merged output location and filename
merged_output=${trimmed_reads_dir}/${trimmed_fastp_report_title}.fq.gz
# Begin fastp trimming
${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 ${max_read_length} \
--merge \
--merged_out ${merged_output} \
--thread ${threads} \
--html "${trimmed_fastp_report_title}.html" \
--json "${trimmed_fastp_report_title}.json" \
--report_title "${trimmed_fastp_report_title}"
# 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 "${trimmed_fastp_report_title}.fq.gz"
} >> "${trimmed_checksums}"
# Change back to to raw reads directory
cd "${raw_reads_dir}"
done
echo ""
echo "fastp trimming complete."
echo ""
echo "Trimmed FastQs MD5 checksums:"
echo ""
cat "${trimmed_reads_dir}/${trimmed_checksums}"
############ END fastp ############
FastQC/MultiQC on trimmed reads
# Load bash variables into memory
source .bashvars
# Create output directory, if it doesn't exist.
mkdir --parents "${trimmed_fastqc_dir}"
############ 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 31bp
- adapters removed
Citations
LS0tCnRpdGxlOiAiMDguMi1QbWVhLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQiCmF1dGhvcjogIlNhbSBXaGl0ZSIKZGF0ZTogIjIwMjQtMDItMTUiCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQpsaW5rLWNpdGF0aW9uczogdHJ1ZQotLS0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShkcGx5cikKbGlicmFyeShyZXRpY3VsYXRlKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsICAgICAgICAgIyBEaXNwbGF5IGNvZGUgY2h1bmtzCiAgZXZhbCA9IEZBTFNFLCAgICAgICAgIyBFdmFsdWF0ZSBjb2RlIGNodW5rcwogIHdhcm5pbmcgPSBGQUxTRSwgICAgICMgSGlkZSB3YXJuaW5ncwogIG1lc3NhZ2UgPSBGQUxTRSwgICAgICMgSGlkZSBtZXNzYWdlcwogIGNvbW1lbnQgPSAiIiAgICAgICAgICMgUHJldmVudHMgYXBwZW5kaW5nICcjIycgdG8gYmVnaW5uaW5nIG9mIGxpbmVzIGluIGNvZGUgb3V0cHV0CikKYGBgCgojIEludHJvZHVjdGlvbgoKRmFzdFFDL011bHRpUUMgYXNzZXNzbWVudCBvZiByYXcgYW5kIFtgZmFzdHBgXShodHRwczovL2dpdGh1Yi5jb20vT3BlbkdlbmUvZmFzdHApLXRyaW1tZWQgc2VxdWVuY2VzIG9mIEU1ICpQLm1lYW5kcmluYSogc1JOQXNlcSBkYXRhIGZyb20gWzIwMjMwNTE1XShodHRwczovL3JvYmVydHNsYWIuZ2l0aHViLmlvL3NhbXMtbm90ZWJvb2svcG9zdHMvMjAyMy8yMDIzLTA1LTE3LURhdGEtTWFuYWdlbWVudC0tLUU1LUNvcmFsLVJOQS1zZXEtYW5kLXNSTkEtc2VxLVJlb3JnYW5pemluZy1hbmQtUmVuYW1pbmcvKS4KCkEgbWF4IGxlbmd0aCBvZiAzMWJwIGlzIGJhc2VkIG9uIHRoZSBgZmFzdHBgIGluc2VydCBwZWFrIHNpemUgZnJvbSBwcmV2aW91cyB0cmltbWluZyB0ZXN0cyBiYXNlZCBvbiB0aGUgdGhlIGFkYXB0ZXIgYW5kIHBvbHlHIHRyaW1taW5nIHJlc3VsdHMsIGFuZCBwcmV2aW91cyBldmFsdWF0aW9uIG9mIG1lYW4gcmVhZCBsZW5ndGhzIHZpYSBbYEZhc3RRQ2BdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIGFuZCBbYE11bHRpUUNgXShodHRwczovL211bHRpcWMuaW5mby8pLgoKSW5wdXRzOgoKLSAgIHNSTkFzZXEgcmVhZHMuCgpPdXRwdXRzOgoKLSAgIFtgRmFzdFFDYF0oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjLykgSFRNTCByZXBvcnRzIGZvciByYXcgYW5kIHRyaW1tZWQgcmVhZHMuCgotICAgW2BNdWx0aVFDYF0oaHR0cHM6Ly9tdWx0aXFjLmluZm8vKSBIVE1MIHN1bW1hcmllcyBvZiBbYEZhc3RRQ2BdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIGZvciByYXcgYW5kIHRyaW1tZWQgcmVhZHMuCgotICAgVHJpbW1lZCBhbmQgbWVyZ2VkIHJlYWRzIHdpdGggZmluYWwgbGVuZ3RoIG9mIDMxYnA6IGAqZmFzdHAtYWRhcHRlcnMtcG9seUctMzFicC1tZXJnZWQuZnEuZ3pgCgpMaWJyYXJpZXMgd2VyZSBwcmVwYXJlZCBhbmQgc2VxdWVuY2VkIGJ5IEF6ZW50YToKCi0gICBMaWJyYXJ5IHByZXA6IFtORUIgbmVibmV4dC1zbWFsbC1ybmEtbGlicmFyeS1wcmVwLXNldC1mb3ItaWxsdW1pbmEga2l0XShodHRwczovL3d3dy5uZWIuY29tL2VuLXVzLy0vbWVkaWEvbmVidXMvZmlsZXMvbWFudWFscy9tYW51YWxlNzMwMF9lNzMzMF9lNzU2MF9lNzU4MC5wZGY/cmV2PWQwOTY0YTJlNjM3ODQzYjFhZmNiOWY3ZDY2NmQwN2IyJmhhc2g9N0FDMEIwRUIwMTI3MDhFRkFCMEU0REJFRUFGMTQ0NkEpIChQREYpCgotICAgU2VxdWVuY2luZzogSWxsdW1pbmEgSGlTZXEgNDAwMCwgMTUwYnAgUEUKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDcmVhdGUgYSBCYXNoIHZhcmlhYmxlcyBmaWxlCgpUaGlzIGFsbG93cyB1c2FnZSBvZiBCYXNoIHZhcmlhYmxlcyBhY3Jvc3MgUiBNYXJrZG93biBjaHVua3MuCgpgYGB7ciBzYXZlLWJhc2gtdmFyaWFibGVzLXRvLXJ2YXJzLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KewplY2hvICIjIyMjIEFzc2lnbiBWYXJpYWJsZXMgIyMjIyIKZWNobyAiIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgZGVlcF9kaXZlX2Rpcj0vaG9tZS9zaGFyZWQvOFRCX0hERF8wMS9zYW0vZ2l0cmVwb3MvZGVlcC1kaXZlJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9JHtkZWVwX2RpdmVfZGlyfS9GLVBtZWEvb3V0cHV0LzA4LjItUG1lYS1zUk5Bc2VxLXRyaW1taW5nLTMxYnAtZmFzdHAtbWVyZ2VkJwoKZWNobyAnZXhwb3J0IHJhd19yZWFkc19kaXI9JHtkZWVwX2RpdmVfZGlyfS9GLVBtZWEvZGF0YS9zUk5Bc2VxLXJhd19yZWFkcycKZWNobyAnZXhwb3J0IHJhd19mYXN0cWNfZGlyPSR7cmF3X3JlYWRzX2Rpcn0vcmF3LWZhc3RxYycKZWNobyAnZXhwb3J0IHJhd19yZWFkc191cmw9Imh0dHBzOi8vb3dsLmZpc2gud2FzaGluZ3Rvbi5lZHUvbmlnaHRpbmdhbGVzL1BfbWVhbmRyaW5hLzMwLTg1MjQzMDIzNS8iJwplY2hvICdleHBvcnQgdHJpbW1lZF9mYXN0cWNfZGlyPSR7b3V0cHV0X2Rpcl90b3B9L3RyaW1tZWQtZmFzdHFjJwplY2hvICdleHBvcnQgdHJpbW1lZF9yZWFkc19kaXI9JHtvdXRwdXRfZGlyX3RvcH0vdHJpbW1lZC1yZWFkcycKZWNobyAiIgoKZWNobyAiIyBQYXRocyB0byBwcm9ncmFtcyIKZWNobyAnZXhwb3J0IGZhc3RxYz0vaG9tZS9zaGFyZWQvRmFzdFFDLTAuMTIuMS9mYXN0cWMnCmVjaG8gJ2V4cG9ydCBmYXN0cD0vaG9tZS9zaGFyZWQvZmFzdHAnCmVjaG8gJ2V4cG9ydCBtdWx0aXFjPS9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2Jpbi9tdWx0aXFjJwplY2hvICIiCgoKCmVjaG8gIiMgU2V0IEZhc3RRIGZpbGVuYW1lIHBhdHRlcm5zIgplY2hvICJleHBvcnQgZmFzdHFfcGF0dGVybj0nc1JOQSonIgplY2hvICJleHBvcnQgUjFfZmFzdHFfcGF0dGVybj0nKl9SMV8qLmZhc3RxLmd6JyIKZWNobyAiZXhwb3J0IFIyX2Zhc3RxX3BhdHRlcm49JypfUjJfKi5mYXN0cS5neiciCmVjaG8gIiIKCmVjaG8gIiMgU2V0IG51bWJlciBvZiBDUFVzIHRvIHVzZSIKZWNobyAnZXhwb3J0IHRocmVhZHM9NDAnCmVjaG8gIiIKCmVjaG8gIiMgU2V0IG1heGltdW0gcmVhZCBsZW5ndGgiCmVjaG8gJ2V4cG9ydCBtYXhfcmVhZF9sZW5ndGg9MzEnCmVjaG8gIiIKCmVjaG8gIiMgSW5wdXQvb3V0cHV0IGZpbGVzIgplY2hvICdleHBvcnQgZmFzdHFfY2hlY2tzdW1zPWlucHV0X2Zhc3RxX2NoZWNrc3Vtcy5tZDUnCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2NoZWNrc3Vtcz10cmltbWVkX2Zhc3RxX2NoZWNrc3Vtcy5tZDUnCmVjaG8gJ2V4cG9ydCBORUJfYWRhcHRlcnNfZmFzdGE9TkVCLWFkYXB0ZXJzLmZhc3RhJwplY2hvICIiCgplY2hvICIjIyBORUIgbmVibmV4dC1zbWFsbC1ybmEtbGlicmFyeS1wcmVwLXNldC1mb3ItaWxsdW1pbmEgYWRhcHRlcnMiCmVjaG8gJ2V4cG9ydCBmaXJzdF9hZGFwdGVyPSJBR0FUQ0dHQUFHQUdDQUNBQ0dUQ1RHQUFDVENDQUdUQ0FDIicKZWNobyAnZXhwb3J0IHNlY29uZF9hZGFwdGVyPSJHQVRDR1RDR0dBQ1RHVEFHQUFDVENUR0FBQ0dUR1RBR0FUQ1RDR0dUR0dUQ0dDQ0dUQVRDQVRUIicKZWNobyAiIgoKZWNobyAiIyMgSW5pdGl0YWxpemUgYXJyYXlzIgplY2hvICdleHBvcnQgZmFzdHFfYXJyYXlfUjE9KCknCmVjaG8gJ2V4cG9ydCBmYXN0cV9hcnJheV9SMj0oKScKZWNobyAnZXhwb3J0IHJhd19mYXN0cXNfYXJyYXk9KCknCmVjaG8gJ2V4cG9ydCBSMV9uYW1lc19hcnJheT0oKScKZWNobyAnZXhwb3J0IFIyX25hbWVzX2FycmF5PSgpJwplY2hvICdleHBvcnQgdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCknCmVjaG8gIiIKCmVjaG8gIiMgUHJvZ3JhbXMgYXNzb2NpYXRpdmUgYXJyYXkiCmVjaG8gImRlY2xhcmUgLUEgcHJvZ3JhbXNfYXJyYXkiCmVjaG8gInByb2dyYW1zX2FycmF5PSgiCmVjaG8gJ1tmYXN0cWNdPSIke2Zhc3RxY30iIFwnCmVjaG8gJ1ttdWx0aXFjXT0iJHttdWx0aXFjfSIgXCcKZWNobyAnW2Zhc3RwXT0iJHtmYXN0cH0iJwplY2hvICIpIgp9ID4gLmJhc2h2YXJzCgpjYXQgLmJhc2h2YXJzCmBgYAoKIyBEb3dubG9hZCByYXcgc1JOQXNlcSByZWFkcwoKUmVhZHMgYXJlIGRvd25sb2FkZWQgZnJvbSA8aHR0cHM6Ly9vd2wuZmlzaC53YXNoaW5ndG9uLmVkdS9uaWdodGluZ2FsZXMvQV9wdWxjaHJhLzMwLTg1MjQzMDIzNS8+CgpUaGUgYC0tY3V0LWRpcnMgM2AgY29tbWFuZCBjdXRzIHRoZSBwcmVjZWRpbmcgZGlyZWN0b3J5IHN0cnVjdHVyZSAoaS5lLiBgbmlnaHRpbmdhbGVzL0FfcHVsY2hyYS8zMC04NTI0MzAyMzUvYCkgc28gdGhhdCB3ZSBqdXN0IGVuZCB1cCB3aXRoIHRoZSByZWFkcy4KCmBgYHtiYXNoIGRvd25sb2FkLXJhdy1yZWFkcywgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKd2dldCBcCi0tZGlyZWN0b3J5LXByZWZpeCAke3Jhd19yZWFkc19kaXJ9IFwKLS1yZWN1cnNpdmUgXAotLW5vLWNoZWNrLWNlcnRpZmljYXRlIFwKLS1jb250aW51ZSBcCi0tY3V0LWRpcnMgMyBcCi0tbm8taG9zdC1kaXJlY3RvcmllcyBcCi0tbm8tcGFyZW50IFwKLS1xdWlldCBcCi0tYWNjZXB0ICIke2Zhc3RxX3BhdHRlcm59LGNoZWNrc3Vtcy5tZDUiICR7cmF3X3JlYWRzX3VybH0KCmxzIC1saCAiJHtyYXdfcmVhZHNfZGlyfSIvJHtmYXN0cV9wYXR0ZXJufQpgYGAKCiMjIFZlcmlmeSByYXcgcmVhZCBjaGVja3N1bXMKCmBgYHtiYXNoIHZlcmlmeS1yYXctcmVhZC1jaGVja3N1bXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDaGVja3N1bXMgZmlsZSBjb250YWlucyBvdGhlciBmaWxlcywgc28gdGhpcyBqdXN0IGxvb2tzIGZvciB0aGUgc1JOQXNlcSBmaWxlcy4KZ3JlcCAic1JOQSIgY2hlY2tzdW1zLm1kNSB8IG1kNXN1bSAtLWNoZWNrCmBgYAoKIyBDcmVhdGUgYWRhcHRlcnMgRmFzdEEgZm9yIHVzZSB3aXRoIFtgZmFzdHBgXShodHRwczovL2dpdGh1Yi5jb20vT3BlbkdlbmUvZmFzdHApIHRyaW1taW5nCgpgYGB7YmFzaCBjcmVhdGUtRmFzdEEtb2YtYWRhcHRlcnMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCm1rZGlyIC0tcGFyZW50cyAiJHtvdXRwdXRfZGlyX3RvcH0iCgplY2hvICJDcmVhdGluZyBhZGFwdGVycyBGYXN0QS4iCmVjaG8gIiIKYWRhcHRlcl9jb3VudD0wCgojIENoZWNrIGZvciBhZGFwdGVycyBmaWxlIGZpcnN0CiMgVGhlbiBjcmVhdGUgYWRhcHRlcnMgZmlsZSBpZiBkb2Vzbid0IGV4aXN0CmlmIFsgLWYgIiR7b3V0cHV0X2Rpcl90b3B9LyR7TkVCX2FkYXB0ZXJzX2Zhc3RhfSIgXTsgdGhlbgogIGVjaG8gIiR7b3V0cHV0X2Rpcl90b3B9LyR7TkVCX2FkYXB0ZXJzX2Zhc3RhfSBhbHJlYWR5IGV4aXN0cy4gTm90aGluZyB0byBkby4iCmVsc2UKICBmb3IgYWRhcHRlciBpbiAiJHtmaXJzdF9hZGFwdGVyfSIgIiR7c2Vjb25kX2FkYXB0ZXJ9IgogIGRvCiAgICBhZGFwdGVyX2NvdW50PSQoKGFkYXB0ZXJfY291bnQgKyAxKSkKICAgIHByaW50ZiAiPiVzXG4lc1xuIiAiYWRhcHRlcl8ke2FkYXB0ZXJfY291bnR9IiAiJHthZGFwdGVyfSIKICBkb25lID4+ICIke291dHB1dF9kaXJfdG9wfS8ke05FQl9hZGFwdGVyc19mYXN0YX0iCmZpCgplY2hvICIiCmVjaG8gIkFkYXB0ZXJzIEZhc3RBOiIKZWNobyAiIgpjYXQgIiR7b3V0cHV0X2Rpcl90b3B9LyR7TkVCX2FkYXB0ZXJzX2Zhc3RhfSIKZWNobyAiIgpgYGAKCiMgRmFzdFFDL011bHRpUUMgb24gcmF3IHJlYWRzCgpgYGB7YmFzaCByYXctZmFzdHFjLW11bHRpcWMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIyMjIyMjIyMjIyMgUlVOIEZBU1RRQyAjIyMjIyMjIyMjIyMKCgojIENyZWF0ZSBhcnJheSBvZiB0cmltbWVkIEZhc3RRcwpyYXdfZmFzdHFzX2FycmF5PSgke3Jhd19yZWFkc19kaXJ9LyR7ZmFzdHFfcGF0dGVybn0pCgojIFBhc3MgYXJyYXkgY29udGVudHMgdG8gbmV3IHZhcmlhYmxlIGFzIHNwYWNlLWRlbGltaXRlZCBsaXN0CnJhd19mYXN0cWNfbGlzdD0kKGVjaG8gIiR7cmF3X2Zhc3Rxc19hcnJheVsqXX0iKQoKZWNobyAiQmVnaW5uaW5nIEZhc3RRQyBvbiByYXcgcmVhZHMuLi4iCmVjaG8gIiIKCiMgUnVuIEZhc3RRQwojIyMgTk9URTogRG8gTk9UIHF1b3RlIHJhd19mYXN0cWNfbGlzdAoke3Byb2dyYW1zX2FycmF5W2Zhc3RxY119IFwKLS10aHJlYWRzICR7dGhyZWFkc30gXAotLW91dGRpciAke3Jhd19mYXN0cWNfZGlyfSBcCi0tcXVpZXQgXAoke3Jhd19mYXN0cWNfbGlzdH0KCmVjaG8gIkZhc3RRQyBvbiByYXcgcmVhZHMgY29tcGxldGUhIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIEZBU1RRQyAjIyMjIyMjIyMjIyMKCiMjIyMjIyMjIyMjIyBSVU4gTVVMVElRQyAjIyMjIyMjIyMjIyMKZWNobyAiQmVnaW5uaW5nIE11bHRpUUMgb24gcmF3IEZhc3RRQy4uLiIKZWNobyAiIgoKJHtwcm9ncmFtc19hcnJheVttdWx0aXFjXX0gJHtyYXdfZmFzdHFjX2Rpcn0gLW8gJHtyYXdfZmFzdHFjX2Rpcn0KCmVjaG8gIiIKZWNobyAiTXVsdGlRQyBvbiByYXcgRmFzdFFzIGNvbXBsZXRlLiIKZWNobyAiIgoKIyMjIyMjIyMjIyMjIEVORCBNVUxUSVFDICMjIyMjIyMjIyMjIwoKZWNobyAiUmVtb3ZpbmcgRmFzdFFDIHppcCBmaWxlcy4iCmVjaG8gIiIKcm0gJHtyYXdfZmFzdHFjX2Rpcn0vKi56aXAKZWNobyAiRmFzdFFDIHppcCBmaWxlcyByZW1vdmVkLiIKZWNobyAiIgoKIyBWaWV3IGRpcmVjdG9yeSBjb250ZW50cwpscyAtbGggJHtyYXdfZmFzdHFjX2Rpcn0KCmBgYAoKIyBUcmltbWluZyB3aXRoIGZhc3RwCgpgYGB7YmFzaCBmYXN0cC10cmltbWluZywgZW5naW5lPSdiYXNoJywgY2FjaGU9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCiMgQ3JlYXRlIG91dHB1dCBkaXJlY3RvcnksIGlmIGl0IGRvZXNuJ3QgZXhpc3QuCm1rZGlyIC0tcGFyZW50cyAiJHt0cmltbWVkX3JlYWRzX2Rpcn0iCgojIENoYW5nZSB0byBkaXJlY3Rvcnkgd2l0aCByYXcgcmVhZHMKY2QgIiR7cmF3X3JlYWRzX2Rpcn0iCgojIENyZWF0ZSBhcnJheXMgb2YgRmFzdFEgUjEgZmlsZXMgYW5kIHNhbXBsZSBuYW1lcwojIERvIE5PVCBxdW90ZSBSMV9mYXN0cV9wYXR0ZXJuIHZhcmlhYmxlCmZvciBmYXN0cSBpbiAke1IxX2Zhc3RxX3BhdHRlcm59CmRvCiAgZmFzdHFfYXJyYXlfUjErPSgiJHtmYXN0cX0iKQoKICAjIFVzZSBwYXJhbWV0ZXIgc3Vic3RpdHV0aW9uIHRvIHJlbW92ZSBhbGwgdGV4dCB1cCB0byBhbmQgaW5jbHVkaW5nIGxhc3QgIi4iIGZyb20KICAjIHJpZ2h0IHNpZGUgb2Ygc3RyaW5nLgogIFIxX25hbWVzX2FycmF5Kz0oIiR7ZmFzdHElJS4qfSIpCmRvbmUKCgojIENyZWF0ZSBhcnJheSBvZiBGYXN0USBSMiBmaWxlcwojIERvIE5PVCBxdW90ZSBSMl9mYXN0cV9wYXR0ZXJuIHZhcmlhYmxlCmZvciBmYXN0cSBpbiAke1IyX2Zhc3RxX3BhdHRlcm59CmRvCiAgZmFzdHFfYXJyYXlfUjIrPSgiJHtmYXN0cX0iKQoKICAjIFVzZSBwYXJhbWV0ZXIgc3Vic3RpdHV0aW9uIHRvIHJlbW92ZSBhbGwgdGV4dCB1cCB0byBhbmQgaW5jbHVkaW5nIGxhc3QgIi4iIGZyb20KICAjIHJpZ2h0IHNpZGUgb2Ygc3RyaW5nLgogIFIyX25hbWVzX2FycmF5Kz0oIiR7ZmFzdHElJS4qfSIpCmRvbmUKCgojIyMjIyMjIyMjIyMgUlVOIEZBU1RQICMjIyMjIyMjIyMjIwojIFVzZXMgcGFyYW1ldGVyIHN1YnN0aXR1dGlvbiAoZS5nLiAke1IxX3NhbXBsZV9uYW1lJSVfKn0pdG8gcm0gdGhlIF9SWzEyXQoKIyBSdW4gZmFzdHAgb24gZmlsZXMKZWNobyAiQmVnaW5uaW5nIGZhc3RwIHRyaW1taW5nLiIKZWNobyAiIgoKdGltZSBcCmZvciBpbmRleCBpbiAiJHshZmFzdHFfYXJyYXlfUjFbQF19IgpkbwogICMgR2V0IHNhbXBsZSBuYW1lCiAgUjFfc2FtcGxlX25hbWU9IiR7UjFfbmFtZXNfYXJyYXlbaW5kZXhdJSVfKn0iCgogICMgU2V0IGZhc3RwIHJlcG9ydCB0aXRsZQogIHRyaW1tZWRfZmFzdHBfcmVwb3J0X3RpdGxlPSIke1IxX3NhbXBsZV9uYW1lfS1mYXN0cC1hZGFwdGVycy1wb2x5Ry0ke21heF9yZWFkX2xlbmd0aH1icC1tZXJnZWQiCiAgCiAgIyBTZXQgbWVyZ2VkIG91dHB1dCBsb2NhdGlvbiBhbmQgZmlsZW5hbWUKICBtZXJnZWRfb3V0cHV0PSR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7dHJpbW1lZF9mYXN0cF9yZXBvcnRfdGl0bGV9LmZxLmd6CgogICMgQmVnaW4gZmFzdHAgdHJpbW1pbmcKICAke3Byb2dyYW1zX2FycmF5W2Zhc3RwXX0gXAogIC0taW4xICR7ZmFzdHFfYXJyYXlfUjFbaW5kZXhdfSBcCiAgLS1pbjIgJHtmYXN0cV9hcnJheV9SMltpbmRleF19IFwKICAtLWFkYXB0ZXJfZmFzdGEgJHtvdXRwdXRfZGlyX3RvcH0vJHtORUJfYWRhcHRlcnNfZmFzdGF9IFwKICAtLXRyaW1fcG9seV9nIFwKICAtLW92ZXJsYXBfbGVuX3JlcXVpcmUgMTcgXAogIC0tbGVuZ3RoX2xpbWl0ICR7bWF4X3JlYWRfbGVuZ3RofSBcCiAgLS1tZXJnZSBcCiAgLS1tZXJnZWRfb3V0ICR7bWVyZ2VkX291dHB1dH0gXAogIC0tdGhyZWFkICR7dGhyZWFkc30gXAogIC0taHRtbCAiJHt0cmltbWVkX2Zhc3RwX3JlcG9ydF90aXRsZX0uaHRtbCIgXAogIC0tanNvbiAiJHt0cmltbWVkX2Zhc3RwX3JlcG9ydF90aXRsZX0uanNvbiIgXAogIC0tcmVwb3J0X3RpdGxlICIke3RyaW1tZWRfZmFzdHBfcmVwb3J0X3RpdGxlfSIKICAgIAogICMgTW92ZSB0byB0cmltbWVkIGRpcmVjdG9yeQogICMgVGhpcyBpcyBkb25lIHNvIGNoZWNrc3VtcyBmaWxlIGRvZXNuJ3QgaW5jbHVkZSBleGNlc3MgcGF0aAogIGNkICR7dHJpbW1lZF9yZWFkc19kaXJ9CgogICMgR2VuZXJhdGUgbWQ1IGNoZWNrc3VtcyBmb3IgbmV3bHkgdHJpbW1lZCBmaWxlcwogIHsKICAgIG1kNXN1bSAiJHt0cmltbWVkX2Zhc3RwX3JlcG9ydF90aXRsZX0uZnEuZ3oiCiAgfSA+PiAiJHt0cmltbWVkX2NoZWNrc3Vtc30iCiAgCiAgIyBDaGFuZ2UgYmFjayB0byB0byByYXcgcmVhZHMgZGlyZWN0b3J5CiAgY2QgIiR7cmF3X3JlYWRzX2Rpcn0iCgpkb25lCgplY2hvICIiCmVjaG8gImZhc3RwIHRyaW1taW5nIGNvbXBsZXRlLiIKZWNobyAiIgoKZWNobyAiVHJpbW1lZCBGYXN0UXMgTUQ1IGNoZWNrc3VtczoiCmVjaG8gIiIKCmNhdCAiJHt0cmltbWVkX3JlYWRzX2Rpcn0vJHt0cmltbWVkX2NoZWNrc3Vtc30iCgojIyMjIyMjIyMjIyMgRU5EIGZhc3RwICMjIyMjIyMjIyMjIwoKYGBgCgojIEZhc3RRQy9NdWx0aVFDIG9uIHRyaW1tZWQgcmVhZHMKCmBgYHtiYXNoIEZhc3RRQy1NdWx0aVFDLXRyaW1tZWQtcmVhZHMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIENyZWF0ZSBvdXRwdXQgZGlyZWN0b3J5LCBpZiBpdCBkb2Vzbid0IGV4aXN0Lgpta2RpciAtLXBhcmVudHMgIiR7dHJpbW1lZF9mYXN0cWNfZGlyfSIKCiMjIyMjIyMjIyMjIyBSVU4gRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIE5PVEU6IERvIE5PVCBxdW90ZSByYXdfZmFzdHFjX2xpc3QKIyBDcmVhdGUgYXJyYXkgb2YgdHJpbW1lZCBGYXN0UXMKdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7ZmFzdHFfcGF0dGVybn0pCgojIFBhc3MgYXJyYXkgY29udGVudHMgdG8gbmV3IHZhcmlhYmxlIGFzIHNwYWNlLWRlbGltaXRlZCBsaXN0CnRyaW1tZWRfZmFzdHFjX2xpc3Q9JChlY2hvICIke3RyaW1tZWRfZmFzdHFzX2FycmF5WypdfSIpCgplY2hvICJCZWdpbm5pbmcgRmFzdFFDIG9uIHJhdyByZWFkcy4uLiIKZWNobyAiIgoKIyBSdW4gRmFzdFFDCiR7cHJvZ3JhbXNfYXJyYXlbZmFzdHFjXX0gXAotLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0ZGlyICR7dHJpbW1lZF9mYXN0cWNfZGlyfSBcCi0tcXVpZXQgXAoke3RyaW1tZWRfZmFzdHFjX2xpc3R9CgplY2hvICJGYXN0UUMgb24gdHJpbW1lZCByZWFkcyBjb21wbGV0ZSEiCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIyMjIyMjIyMjIFJVTiBNVUxUSVFDICMjIyMjIyMjIyMjIwplY2hvICJCZWdpbm5pbmcgTXVsdGlRQyBvbiByYXcgRmFzdFFDLi4uIgplY2hvICIiCgoke3Byb2dyYW1zX2FycmF5W211bHRpcWNdfSAke3RyaW1tZWRfZmFzdHFjX2Rpcn0gLW8gJHt0cmltbWVkX2Zhc3RxY19kaXJ9CgplY2hvICIiCmVjaG8gIk11bHRpUUMgb24gdHJpbW1lZCBGYXN0UXMgY29tcGxldGUuIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIE1VTFRJUUMgIyMjIyMjIyMjIyMjCgplY2hvICJSZW1vdmluZyBGYXN0UUMgemlwIGZpbGVzLiIKZWNobyAiIgpybSAke3RyaW1tZWRfZmFzdHFjX2Rpcn0vKi56aXAKZWNobyAiRmFzdFFDIHppcCBmaWxlcyByZW1vdmVkLiIKZWNobyAiIgoKIyBWaWV3IGRpcmVjdG9yeSBjb250ZW50cwpscyAtbGggJHt0cmltbWVkX2Zhc3RxY19kaXJ9CgpgYGAKCiMgU3VtbWFyeQoKQSBxdWljayBjb21wYXJpc29uIG9mIHJhdyBhbmQgdHJpbW1lZCByZWFkcyB0byBzaG93IHRyaW1taW5nIHdvcmtlZDoKCi0gICBxdWFsaXR5IGlzIGltcHJvdmVkCi0gICBsZW5ndGggaXMgMzFicAotICAgYWRhcHRlcnMgcmVtb3ZlZAoKfCBSQVcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFRSSU1NRUQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCAhW1JhdyBNdWx0aVFDIHBlciBiYXNlIHNlcXVlbmNlIHF1YWxpdHkgcGxvdF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9GLVBtZWEvZGF0YS9zUk5Bc2VxLXJhd19yZWFkcy9yYXctZmFzdHFjL2Zhc3RxY19wZXJfYmFzZV9zZXF1ZW5jZV9xdWFsaXR5X3Bsb3QucG5nP3Jhdz10cnVlKSB8ICFbVHJpbW1lZCBNdWx0aVFDIHBlciBiYXNlIHNlcXVlbmNlIHF1YWxpdHkgcGxvdF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9ELUFwdWwvb3V0cHV0LzA4LjItRGFwdWwtc1JOQXNlcS10cmltbWluZy0zMWJwLWZhc3RwLW1lcmdlZC90cmltbWVkLWZhc3RxYy9mYXN0cWNfcGVyX2Jhc2Vfc2VxdWVuY2VfcXVhbGl0eV9wbG90LnBuZz9yYXc9dHJ1ZSkgfAp8ICFbUmF3IE11bHRpUUMgYWRhcHRlciBjb250ZW50IHBsb3RdKGh0dHBzOi8vZ2l0aHViLmNvbS91cm9sLWU1L2RlZXAtZGl2ZS9ibG9iL21haW4vRi1QbWVhL2RhdGEvc1JOQXNlcS1yYXdfcmVhZHMvcmF3LWZhc3RxYy9mYXN0cWNfYWRhcHRlcl9jb250ZW50X3Bsb3QucG5nP3Jhdz10cnVlKSAgICAgICAgICAgICAgICAgICAgIHwgIVtUcmltbWVkIE11bHRpUUMgYWRhcHRlciBjb250ZW50IHBsb3RdKGh0dHBzOi8vZ2l0aHViLmNvbS91cm9sLWU1L2RlZXAtZGl2ZS9ibG9iL21haW4vRC1BcHVsL291dHB1dC8wOC4yLURhcHVsLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQvdHJpbW1lZC1mYXN0cWMvZmFzdHFjX2FkYXB0ZXJfY29udGVudF9wbG90LnBuZz9yYXc9dHJ1ZSkgICAgICAgICAgICAgICAgICAgICB8CgojIENpdGF0aW9ucw==