1 Introduction

We received via a google drive link 3 samples of RNASeq data. They are dissociated_embryo_x6, whole_embryo_x1, and whole_embryo_x3.

I downloaded a copy of the xenopus laevis genome revision 9.1 along with the tropicalis 10.1 as genbank flat files from NCBI and converted them to the requisite gff/genome/CDS/amino acid entries.

Najib suggested we should apply our own trimming methods, though I fully expected the provided trimmed files are perfect.

2 Preprocessing

I will use the following ~ 6 shell blocks to invoke the preprocessing tools which will handle the data from trimming->quantification. Depending on those results, I may add some further analyses.

At the bottom of this document I am going to add some blocks into which I will copy/paste the actual scripts which were invoked on the computers in our cluster. I will just copy/paste one example each for an arbitrarily chosen sample.

2.1 Some re-used settings

I will put a few parameters as environment variables to be reused across invocations.

species="xenopus_laevis_v10.1"
xl_type="gene"
xl_tag="gene"
stranded="no"

2.2 Trimming and QC

I will use a few tools for quick trimming/QC metrics.

2.2.1 Trimomatic

The following for loop is how I do pretty much everything.

cd preprocessing
module add cyoa
start=$(pwd)
for i in $(/bin/ls -d *); do
    cd "${start}/${i}"
    input=$(/bin/ls unprocessed/*.fastq.gz | tr '\n' ':')
    cyoa --method trim --input "${input}"
done
cd "${start}"

2.2.2 Fastqc

cd preprocessing
module add cyoa
start=$(pwd)
for i in $(/bin/ls -d *); do
    cd "${start}/${i}"
    input=$(/bin/ls unprocessed/*.fastq.gz | tr '\n' ':')
    cyoa --method fastqc --input "${input}"
done
cd "${start}"

2.2.3 Fastp

A new tool which performs trimming and QC metrics at the same time is fastp.

cd preprocessing
module add cyoa
start=$(pwd)
for i in $(/bin/ls -d *); do
    cd "${start}/${i}"
    input=$(/bin/ls unprocessed/*.fastq.gz | tr '\n' ':')
    cyoa --method fastp --input "${input}"
done
cd "${start}"

2.3 Gene/Tx quantification

2.3.1 Transcript quantification via salmon

cd preprocessing
module add cyoa
start=$(pwd)
for i in $(/bin/ls -d *); do
    cd "${start}/${i}"
    input=$(/bin/ls outputs/01trimomatic/*-trimmed.fastq.xz | tr '\n' ':')
    cyoa --method salmon --input "${input}" --species "${species}"
done
cd "${start}"

2.3.2 Gene quantification via hisat2

cd preprocessing
module add cyoa
start=$(pwd)
for i in $(/bin/ls -d *); do
    cd "${start}/${i}"
    input=$(/bin/ls outputs/01trimomatic/*-trimmed.fastq.xz | tr '\n' ':')
    cyoa --method hisat --species "${species}" --input "${input}" --gff_type "${xl_type}" \
         --gff_tag "${xl_tag}" --stranded "${stranded}"
done
cd "${start}"

2.4 rRNA Query

cd preprocessing
module add cyoa
start=$(pwd)
for i in $(/bin/ls -d *); do
    cd "${start}/${i}"
    input=$(/bin/ls unprocessed/*.fastq.gz | tr '\n' ':')
    cyoa --method hisat --libtype rRNA --species "${species}"_ --input "${input}" \
         --stranded "${stranded}" --gff_type rRNA --gff_tag gene
done
cd "${start}"

3 Load gene annotations

I will load my annotations from a combination of ensembl and the NCBI gff file; I presume the gene IDs will match up, since the NCBI assembly and ensembl have the same source.

xl_mRNA_annot <- load_gff_annotations("reference/xenopus_laevis_v10.1.gff",
                                      type = "mRNA", id_col = "gene")
## Returning a df with 42 columns and 1007786 rows.
xl_CDS_annot <- load_gff_annotations("reference/xenopus_laevis_v10.1.gff",
                                      type = "CDS", id_col = "gene")
## Returning a df with 42 columns and 956598 rows.
## xl_ens_annot <- load_biomart_annotations(species = "xlaevis", archive = FALSE)

4 Load the salmon transcript counts

This will likely be tricky because salmon has some peculiar rules about gene/transcript IDs which I strongly suspect will not match up with the IDs produced when reading from the gff annotations or biomart. Let us find out! Here are the first few entries of the salmon quant file:

XP_041442323.1_LOC108704873_GeneID:108704873_pepsin_A_isoform_X1 1143 853.109 0.487714 9.000 XP_041442326.1_LOC108704873_GeneID:108704873_pepsin_A_isoform_X2 1035 743.000 0.000000 0.000 XP_018097054.2_LOC108704861_GeneID:108704861_peptidase_inhibitor_16 1656 1364.000 0.000000 0.000 XP_041436388.1_dok1.L_GeneID:444335_docking_protein_1_L_homeolog_isoform_X1 2127 1811.679 6.149833 241.000 NP_001085908.1_dok1.L_GeneID:444335_docking_protein_1_L_homeolog 1782 1476.220 0.000000 0.000 NP_001084645.1_mrps26.L_GeneID:414604_uncharacterized_protein_LOC414604 615 317.758 155.818955 1071.000 XP_018097055.1_LOC108704862_GeneID:108704862_meiosis_1_arrest_protein 1515 1223.000 0.000000 0.000 XP_018097050.2_dqx1.L_GeneID:108704857_LOW_QUALITY_PROTEIN:_ATP-dependent_RNA_helicase_DQX1 2197 1852.495 2.944778 118.000 XP_041442332.1_LOC108704874_GeneID:108704874_matrix_metalloproteinase-21 1857 1565.000 0.000000 0.000

So, yeah, that is going to be annoying.

I usually get all of my genomes/annotations from ensembl, I am now remembering why this is. I do not think it should prove difficult to cross reference my ncbi and ensembl IDs, but we shall see.

The IDs from salmon are:

“{protein_id}{gene}{db_xref}_{product}” with the caveat that all spaces are replaced by underscore.

salmon_annot <- xl_CDS_annot
rownames(salmon_annot) <- make.names(salmon_annot[["protein_id"]], unique = TRUE)
salmon_tx_map <- salmon_annot[, c("protein_id", "gene")]
salmon_tx_map[["protein_id"]] <- gsub(x = salmon_tx_map[["protein_id"]], pattern = "\\.[[:digit:]]+",
                                      replacement = "")

5 Create SummarizedExperiment

I will create one version by tx and one by gene.

tx_se <- create_se("sample_sheets/all_samples.xlsx", gene_info = salmon_annot,
                   file_column = "salmon_quant")
## Reading the sample metadata.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 3 rows(samples) and 4 columns(metadata fields).
## Matched 60687 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final summarized experiment has 60905 rows and 4 columns.
salmon_gene_annot <- salmon_annot
rownames(salmon_gene_annot) <- make.names(salmon_gene_annot[["gene"]], unique = TRUE)
gene_se <- create_se("sample_sheets/all_samples.xlsx", gene_info = salmon_gene_annot,
                  file_column = "salmon_quant", tx_gene_map = salmon_tx_map)
## Reading the sample metadata.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 3 rows(samples) and 4 columns(metadata fields).
## In some cases, (notably salmon) the format of the IDs used by this can be tricky.
## It is likely to require the transcript ID followed by a '.' and the ensembl column:
## 'transcript_version', which is explicitly different than the gene version column.
## If this is not correctly performed, very few genes will be observed
## reading in files with read_tsv
## 1 2 3 
## removing duplicated transcript rows from tx2gene
## transcripts missing from tx2gene: 218
## summarizing abundance
## summarizing counts
## summarizing length
## Matched 34144 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final summarized experiment has 34255 rows and 4 columns.

6 Look at the 3 samples

dim(assay(tx_se))
## [1] 60905     3
plot_libsize(tx_se)
## Library sizes of 3 samples, 
## ranging from 6,088,658 to 14,516,405.

dim(assay(gene_se))
## [1] 34255     3
plot_libsize(gene_se)
## Library sizes of 3 samples, 
## ranging from 6,088,627 to 14,516,358.

plot_nonzero(tx_se)
## The following samples have less than 39588.25 genes.
## [1] "dssctd_m_6" "whl_mbry_1" "whl_mbry_3"
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
## A non-zero genes plot of 3 samples.
## These samples have an average 9.817 CPM coverage and 30216 genes observed, ranging from 28553 to
## 32847.

plot_nonzero(gene_se)
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
## A non-zero genes plot of 3 samples.
## These samples have an average 9.817 CPM coverage and 23806 genes observed, ranging from 22726 to
## 25651.

tx_norm <- normalize(tx_se, convert = "cpm", filter = TRUE, transform = "log2")
## Running normalize_se.
## Removing 41018 low-count genes (19887 remaining).
## transform_counts: Found 2183 values equal to 0, adding 1 to the matrix.
plot_corheat(tx_norm)
## A heatmap of pairwise sample correlations ranging from: 
## 0.736448006840574 to 0.844499630181708.

plot_pca(tx_norm)
## The result of performing a fast_svd dimension reduction.
## The x-axis is PC1 and the y-axis is PC2
## Colors are defined by disociated, whole_one, whole_three
## Shapes are defined by six, one, three.

write_xlsx(excel = "excel/l2_cpm_tx.xlsx", data = assay(tx_norm))
## Deleting the file excel/l2_cpm_tx.xlsx before writing the tables.
## write_xlsx() wrote excel/l2_cpm_tx.xlsx.
## The cursor is on sheet first, row: 19890 column: 5.

7 Example Invocations

7.1 Trimomatic

#!/usr/bin/bash
#SBATCH --export=ALL --mail-type=NONE --open-mode=append
#SBATCH --chdir=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1
#SBATCH --job-name=01trim_XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1 --nice=10
#SBATCH --output=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt.sbatch
#SBATCH --account=cbcb
#SBATCH --partition=cbcb
#SBATCH --qos=medium
#SBATCH --nodes=1 --ntasks=1 --cpus-per-task=4
#SBATCH --time=36:00:00
#SBATCH --mem=6G
startdir=$(pwd)
set -o errexit
set -o errtrace
set -o pipefail
echo "## Started /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/scripts/01trim_XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1.sh at $(date) on $(hostname) with id ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt
function get_sigterm {
  cd "${startdir}"
  echo "A SIGTERM was sent to 01trim_XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1: ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt
  exit 1
}
trap get_sigterm SIGTERM
function get_sigerr {
  cd "${startdir}"
  echo "A SIGERR was sent to 01trim_XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1: ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt
  exit 1
}
trap get_sigerr ERR
mod=$( { type -t module || true; } )
if [[ -z "${mod}" ]]; then
  module() {
  # shellcheck disable=SC2086
    { eval "$(/usr/bin/modulecmd bash $*)" || true; }
  }
  export -f module
fi
module add trimomatic 2>/dev/null 1>&2
## This call to trimomatic removes illumina and epicentre adapters from unprocessed/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1.fastq.gz:unprocessed/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2.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.
mkdir -p outputs/01trimomatic
## Note that trimomatic prints all output and errors to STDERR, so send both to output
trimomatic PE \
  -threads 1 \
  -phred33 \
  unprocessed/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1.fastq.gz unprocessed/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2.fastq.gz \
  outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed_paired.fastq outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed_unpaired.fastq \
  outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed_paired.fastq outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed_unpaired.fastq \
   ILLUMINACLIP:/fs/cbcb-software/RedHat-8-x86_64/local/cyoa/202506/prefix/lib/perl5/auto/share/dist/Bio-Adventure/genome/adapters.fa:2:20:10:2:keepBothReads  \
  SLIDINGWINDOW:4:20 MINLEN:50 \
  1>outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003-trimomatic.stdout \
  2>outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003-trimomatic.stderr
excepted=$( { grep "Exception" "outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003-trimomatic.stdout" || test $? = 1; } )
## 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 \
    unprocessed/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1.fastq.gz unprocessed/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2.fastq.gz \
    outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed_paired.fastq outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed_unpaired.fastq \
    outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed_paired.fastq outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed_unpaired.fastq \
     SLIDINGWINDOW:4:25 MINLEN:50 \
    1>outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003-trimomatic.stdout \
    2>outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003-trimomatic.stderr
fi
sleep 10
mv outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed_paired.fastq outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed.fastq
mv outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed_paired.fastq outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed.fastq

## Recompress the unpaired reads, this should not take long.
xz -9e -f outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed_unpaired.fastq
xz -9e -f outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed_unpaired.fastq
## Recompress the paired reads.
xz -9e -f outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed.fastq
xz -9e -f outputs/01trimomatic/XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed.fastq
ln=$(cd outputs/01trimomatic && ln -sf XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1-trimmed.fastq.xz r1_trimmed.fastq.xz)
ln=$(cd outputs/01trimomatic && ln -sf XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R2-trimmed.fastq.xz r2_trimmed.fastq.xz)



## The following lines give status codes and some logging
## This might not work because it is a little circular.
cd ${startdir}
minutes_used=$(( SECONDS / 60 ))
echo "  $(hostname) Finished ${SLURM_JOBID} 01trim_XNEME_20250520_A00904_IL22367-001_N5UD-F09_L003_R1.sh at $(date), it took ${minutes_used} minutes." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt
if [[ -x "$(command -v sstat)" && -n "${SLURM_JOBID}" ]]; then
  echo "  walltime used by ${SLURM_JOBID} was: ${minutes_used:-null} minutes." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt
  echo "" >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x1/outputs/log.txt
fi
## Note, you can score a bunch more information by running cyoa --method checkjob from the working directory.

7.2 FastQC

#!/usr/bin/bash
#SBATCH --export=ALL --mail-type=NONE --open-mode=append
#SBATCH --chdir=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6
#SBATCH --job-name=01fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed --nice=10
#SBATCH --output=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt.sbatch
#SBATCH --account=nexus
#SBATCH --partition=tron
#SBATCH --qos=medium
#SBATCH --nodes=1 --ntasks=1 --cpus-per-task=8
#SBATCH --time=3:00:00
#SBATCH --mem=20G
startdir=$(pwd)
set -o errexit
set -o errtrace
set -o pipefail
echo "## Started /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/scripts/01fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed.sh at $(date) on $(hostname) with id ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt
function get_sigterm {
  cd "${startdir}"
  echo "A SIGTERM was sent to 01fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed: ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt
  exit 1
}
trap get_sigterm SIGTERM
function get_sigerr {
  cd "${startdir}"
  echo "A SIGERR was sent to 01fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed: ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt
  exit 1
}
trap get_sigerr ERR
mod=$( { type -t module || true; } )
if [[ -z "${mod}" ]]; then
  module() {
  # shellcheck disable=SC2086
    { eval "$(/usr/bin/modulecmd bash $*)" || true; }
  }
  export -f module
fi
module add fastqc 2>/dev/null 1>&2
## This FastQC run is against unfiltered data and is used for
## an initial estimation of the overall sequencing quality.
mkdir -p outputs/01fastqc
which perl 2>outputs/01fastqc/fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed-unfiltered_fastqc.stderr 1>&2
which fastqc 2>>outputs/01fastqc/fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed-unfiltered_fastqc.stderr 1>&2
## Even if fastqc finishes happily using a subshell, it might exit with SIGERR
trap - ERR
finished=$(fastqc --extract \
  -o outputs/01fastqc \
   /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/unprocessed/XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1.fastq.gz  /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/unprocessed/XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R2.fastq.gz  \
  2>>outputs/01fastqc/fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed-unfiltered_fastqc.stderr \
  1>>outputs/01fastqc/fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed-unfiltered_fastqc.stdout || /bin/true)
echo "fastqc finished with $? andor ${finished}."



## The following lines give status codes and some logging
## This might not work because it is a little circular.
cd ${startdir}
minutes_used=$(( SECONDS / 60 ))
echo "  $(hostname) Finished ${SLURM_JOBID} 01fqc_XNEME_20250520_A00904_IL22369-001_N5UD-H09_L003_R1_unprocessed.sh at $(date), it took ${minutes_used} minutes." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt
if [[ -x "$(command -v sstat)" && -n "${SLURM_JOBID}" ]]; then
  echo "  walltime used by ${SLURM_JOBID} was: ${minutes_used:-null} minutes." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt
  echo "" >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/dissociated_embryo_x6/outputs/log.txt
fi
## Note, you can score a bunch more information by running cyoa --method checkjob from the working directory.

7.3 Fastp

#!/usr/bin/bash
#SBATCH --export=ALL --mail-type=NONE --open-mode=append
#SBATCH --chdir=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3
#SBATCH --job-name=12fastp_XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1 --nice=10
#SBATCH --output=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt.sbatch
#SBATCH --account=cbcb
#SBATCH --partition=cbcb
#SBATCH --qos=medium
#SBATCH --nodes=1 --ntasks=1 --cpus-per-task=2
#SBATCH --time=8:00:00
#SBATCH --mem=12G
startdir=$(pwd)
set -o errexit
set -o errtrace
set -o pipefail
echo "## Started /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/scripts/12fastp_XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1.sh at $(date) on $(hostname) with id ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt
function get_sigterm {
  cd "${startdir}"
  echo "A SIGTERM was sent to 12fastp_XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1: ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt
  exit 1
}
trap get_sigterm SIGTERM
function get_sigerr {
  cd "${startdir}"
  echo "A SIGERR was sent to 12fastp_XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1: ${SLURM_JOBID}." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt
  exit 1
}
trap get_sigerr ERR
mod=$( { type -t module || true; } )
if [[ -z "${mod}" ]]; then
  module() {
  # shellcheck disable=SC2086
    { eval "$(/usr/bin/modulecmd bash $*)" || true; }
  }
  export -f module
fi
module add fastp 2>/dev/null 1>&2
## Run fastp on raw data


mkdir -p outputs/12fastp
trimmed=1
{
  /usr/bin/time -v -o outputs/12fastp/stdout.time -a
    fastp   -i /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/unprocessed/XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1.fastq.gz \
  -o outputs/12fastp/XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1-fastp.fastq \
  -I /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/unprocessed/XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R2.fastq.gz \
  -O outputs/12fastp/XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R2-fastp.fastq  \
      -h outputs/12fastp/fastp_report.html \
  -j outputs/12fastp/fastp_report.json  -D  -c  -y  \
      2>outputs/12fastp/stderr \
      1>outputs/12fastp/stdout

xz -9e -f outputs/12fastp/XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1-fastp.fastq
xz -9e -f outputs/12fastp/XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R2-fastp.fastq

} || {
  echo 'fastp failed.' >> outputs/12fastp/stderr
}


## The following lines give status codes and some logging
## This might not work because it is a little circular.
cd ${startdir}
minutes_used=$(( SECONDS / 60 ))
echo "  $(hostname) Finished ${SLURM_JOBID} 12fastp_XNEME_20250520_A00904_IL22368-001_N5UD-G09_L003_R1.sh at $(date), it took ${minutes_used} minutes." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt
if [[ -x "$(command -v sstat)" && -n "${SLURM_JOBID}" ]]; then
  echo "  walltime used by ${SLURM_JOBID} was: ${minutes_used:-null} minutes." >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt
  echo "" >> /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/nemes_2025/preprocessing/whole_embryo_x3/outputs/log.txt
fi
## Note, you can score a bunch more information by running cyoa --method checkjob from the working directory.
pander::pander(sessionInfo())

R version 4.4.2 (2024-10-31)

Platform: x86_64-pc-linux-gnu

locale: LC_CTYPE=en_US.UTF-8, LC_NUMERIC=C, LC_TIME=en_US.UTF-8, LC_COLLATE=en_US.UTF-8, LC_MONETARY=en_US.UTF-8, LC_MESSAGES=en_US.UTF-8, LC_PAPER=en_US.UTF-8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.UTF-8 and LC_IDENTIFICATION=C

attached base packages: stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: tidyr(v.1.3.1), hpgltools(v.1.0), glue(v.1.8.0), forcats(v.1.0.0) and dplyr(v.1.1.4)

loaded via a namespace (and not attached): RColorBrewer(v.1.1-3), jsonlite(v.2.0.0), tximport(v.1.34.0), magrittr(v.2.0.3), rmarkdown(v.2.29), farver(v.2.1.2), fs(v.1.6.6), BiocIO(v.1.16.0), zlibbioc(v.1.52.0), vctrs(v.0.6.5), memoise(v.2.0.1), Rsamtools(v.2.22.0), DelayedMatrixStats(v.1.28.1), RCurl(v.1.98-1.17), htmltools(v.0.5.8.1), S4Arrays(v.1.6.0), curl(v.6.4.0), broom(v.1.0.8), Rhdf5lib(v.1.28.0), SparseArray(v.1.6.2), rhdf5(v.2.50.2), sass(v.0.4.10), bslib(v.0.9.0), htmlwidgets(v.1.6.4), bsseq(v.1.42.0), plyr(v.1.8.9), plotly(v.4.10.4), cachem(v.1.1.0), GenomicAlignments(v.1.42.0), mime(v.0.13), lifecycle(v.1.0.4), iterators(v.1.0.14), pkgconfig(v.2.0.3), Matrix(v.1.7-3), R6(v.2.6.1), fastmap(v.1.2.0), GenomeInfoDbData(v.1.2.13), MatrixGenerics(v.1.18.1), shiny(v.1.11.0), digest(v.0.6.37), colorspace(v.2.1-1), AnnotationDbi(v.1.68.0), S4Vectors(v.0.44.0), DESeq2(v.1.46.0), GenomicRanges(v.1.58.0), RSQLite(v.2.4.1), labeling(v.0.4.3), httr(v.1.4.7), abind(v.1.4-8), compiler(v.4.4.2), pander(v.0.6.6), withr(v.3.0.2), bit64(v.4.6.0-1), backports(v.1.5.0), BiocParallel(v.1.40.2), DBI(v.1.2.3), HDF5Array(v.1.34.0), R.utils(v.2.13.0), DelayedArray(v.0.32.0), corpcor(v.1.6.10), rjson(v.0.2.23), gtools(v.3.9.5), permute(v.0.9-7), tools(v.4.4.2), DSS(v.2.54.0), zip(v.2.3.3), httpuv(v.1.6.16), varhandle(v.2.0.6), restez(v.2.1.5), R.oo(v.1.27.1), restfulr(v.0.0.15), GOSemSim(v.2.32.0), rhdf5filters(v.1.18.1), promises(v.1.3.3), grid(v.4.4.2), reshape2(v.1.4.4), fgsea(v.1.32.4), generics(v.0.1.4), gtable(v.0.3.6), BSgenome(v.1.74.0), tzdb(v.0.5.0), R.methodsS3(v.1.8.2), hms(v.1.1.3), data.table(v.1.17.6), XVector(v.0.46.0), BiocGenerics(v.0.52.0), ggrepel(v.0.9.6), foreach(v.1.5.2), pillar(v.1.10.2), stringr(v.1.5.1), vroom(v.1.6.5), yulab.utils(v.0.2.0), limma(v.3.62.2), later(v.1.4.2), splines(v.4.4.2), lattice(v.0.22-7), rtracklayer(v.1.66.0), bit(v.4.6.0), annotate(v.1.84.0), tidyselect(v.1.2.1), GO.db(v.3.20.0), locfit(v.1.5-9.12), Biostrings(v.2.74.1), knitr(v.1.50.1), IRanges(v.2.40.1), edgeR(v.4.4.2), SummarizedExperiment(v.1.36.0), xfun(v.0.52), stats4(v.4.4.2), Biobase(v.2.66.0), statmod(v.1.5.0), matrixStats(v.1.5.0), stringi(v.1.8.7), UCSC.utils(v.1.2.0), lazyeval(v.0.2.2), yaml(v.2.3.10), evaluate(v.1.0.4), codetools(v.0.2-20), tibble(v.3.3.0), qvalue(v.2.38.0), graph(v.1.84.1), cli(v.3.6.5), xtable(v.1.8-4), jquerylib(v.0.1.4), dichromat(v.2.0-0.1), Rcpp(v.1.0.14), GenomeInfoDb(v.1.42.3), png(v.0.1-8), fastcluster(v.1.3.0), XML(v.3.99-0.18), parallel(v.4.4.2), readr(v.2.1.5), ggplot2(v.3.5.2), blob(v.1.2.4), DOSE(v.4.0.1), sparseMatrixStats(v.1.18.0), bitops(v.1.0-9), viridisLite(v.0.4.2), GSEABase(v.1.68.0), scales(v.1.4.0), openxlsx(v.4.2.8), purrr(v.1.0.4), crayon(v.1.5.3), rlang(v.1.1.6), cowplot(v.1.1.3), fastmatch(v.1.1-6) and KEGGREST(v.1.46.0)

message(paste0("This is hpgltools commit: ", get_git_commit()))
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset cdba1d3cf1448fd60c6a78e7b7b171e0c9a8e47b
## This is hpgltools commit: Thu Jun 5 12:57:42 2025 -0400: cdba1d3cf1448fd60c6a78e7b7b171e0c9a8e47b
message(paste0("Saving to ", savefile))
## Saving to index.rda.xz
##tmp <- sm(saveme(filename = savefile))
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiMyBYZW5vcHVzIGxhZXZpcyBzYW1wbGVzLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmJpYmxpb2dyYXBoeTogL2hvbWUvdHJleS9zY3JhdGNoL3pvdGVyb19saWJyYXJ5L2F0Yi5iaWIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgdGhlbWU6IHJlYWRhYmxlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShnbHVlKQpsaWJyYXJ5KGhwZ2x0b29scykKbGlicmFyeSh0aWR5cikKCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUsIHdpZHRoID0gOTAsIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZXJyb3IgPSBUUlVFLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLnJldGluYSA9IDIsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAicG5nIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSBTeXMuZ2V0ZW52KCJWRVJTSU9OIikKcnVuZGF0ZSA8LSBmb3JtYXQoU3lzLkRhdGUoKSwgZm9ybWF0ID0gIiVZJW0lZCIpCgpybWRfZmlsZSA8LSAiaW5kZXguUm1kIgpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBybWRfZmlsZSkKYGBgCgojIEludHJvZHVjdGlvbgoKV2UgcmVjZWl2ZWQgdmlhIGEgZ29vZ2xlIGRyaXZlIGxpbmsgMyBzYW1wbGVzIG9mIFJOQVNlcSBkYXRhLiAgVGhleQphcmUgIGRpc3NvY2lhdGVkX2VtYnJ5b194Niwgd2hvbGVfZW1icnlvX3gxLCBhbmQgd2hvbGVfZW1icnlvX3gzLgoKSSBkb3dubG9hZGVkIGEgY29weSBvZiB0aGUgeGVub3B1cyBsYWV2aXMgZ2Vub21lIHJldmlzaW9uIDkuMSBhbG9uZwp3aXRoIHRoZSB0cm9waWNhbGlzIDEwLjEgYXMgZ2VuYmFuayBmbGF0IGZpbGVzIGZyb20gTkNCSSBhbmQgY29udmVydGVkCnRoZW0gdG8gdGhlIHJlcXVpc2l0ZSBnZmYvZ2Vub21lL0NEUy9hbWlubyBhY2lkIGVudHJpZXMuCgpOYWppYiBzdWdnZXN0ZWQgd2Ugc2hvdWxkIGFwcGx5IG91ciBvd24gdHJpbW1pbmcgbWV0aG9kcywgdGhvdWdoIEkKZnVsbHkgZXhwZWN0ZWQgdGhlIHByb3ZpZGVkIHRyaW1tZWQgZmlsZXMgYXJlIHBlcmZlY3QuCgojIFByZXByb2Nlc3NpbmcKCkkgd2lsbCB1c2UgdGhlIGZvbGxvd2luZyB+IDYgc2hlbGwgYmxvY2tzIHRvIGludm9rZSB0aGUgcHJlcHJvY2Vzc2luZwp0b29scyB3aGljaCB3aWxsIGhhbmRsZSB0aGUgZGF0YSBmcm9tIHRyaW1taW5nLT5xdWFudGlmaWNhdGlvbi4KRGVwZW5kaW5nIG9uIHRob3NlIHJlc3VsdHMsIEkgbWF5IGFkZCBzb21lIGZ1cnRoZXIgYW5hbHlzZXMuCgpBdCB0aGUgYm90dG9tIG9mIHRoaXMgZG9jdW1lbnQgSSBhbSBnb2luZyB0byBhZGQgc29tZSBibG9ja3MgaW50bwp3aGljaCBJIHdpbGwgY29weS9wYXN0ZSB0aGUgYWN0dWFsIHNjcmlwdHMgd2hpY2ggd2VyZSBpbnZva2VkIG9uIHRoZQpjb21wdXRlcnMgaW4gb3VyIGNsdXN0ZXIuICBJIHdpbGwganVzdCBjb3B5L3Bhc3RlIG9uZSBleGFtcGxlIGVhY2ggZm9yCmFuIGFyYml0cmFyaWx5IGNob3NlbiBzYW1wbGUuCgojIyBTb21lIHJlLXVzZWQgc2V0dGluZ3MKCkkgd2lsbCBwdXQgYSBmZXcgcGFyYW1ldGVycyBhcyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gYmUgcmV1c2VkCmFjcm9zcyBpbnZvY2F0aW9ucy4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzcGVjaWVzPSJ4ZW5vcHVzX2xhZXZpc192MTAuMSIKeGxfdHlwZT0iZ2VuZSIKeGxfdGFnPSJnZW5lIgpzdHJhbmRlZD0ibm8iCmBgYAoKIyMgVHJpbW1pbmcgYW5kIFFDCgpJIHdpbGwgdXNlIGEgZmV3IHRvb2xzIGZvciBxdWljayB0cmltbWluZy9RQyBtZXRyaWNzLgoKIyMjIFRyaW1vbWF0aWMKClRoZSBmb2xsb3dpbmcgZm9yIGxvb3AgaXMgaG93IEkgZG8gcHJldHR5IG11Y2ggZXZlcnl0aGluZy4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCm1vZHVsZSBhZGQgY3lvYQpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kICopOyBkbwogICAgY2QgIiR7c3RhcnR9LyR7aX0iCiAgICBpbnB1dD0kKC9iaW4vbHMgdW5wcm9jZXNzZWQvKi5mYXN0cS5neiB8IHRyICdcbicgJzonKQogICAgY3lvYSAtLW1ldGhvZCB0cmltIC0taW5wdXQgIiR7aW5wdXR9Igpkb25lCmNkICIke3N0YXJ0fSIKYGBgCgojIyMgRmFzdHFjCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KY2QgcHJlcHJvY2Vzc2luZwptb2R1bGUgYWRkIGN5b2EKc3RhcnQ9JChwd2QpCmZvciBpIGluICQoL2Jpbi9scyAtZCAqKTsgZG8KICAgIGNkICIke3N0YXJ0fS8ke2l9IgogICAgaW5wdXQ9JCgvYmluL2xzIHVucHJvY2Vzc2VkLyouZmFzdHEuZ3ogfCB0ciAnXG4nICc6JykKICAgIGN5b2EgLS1tZXRob2QgZmFzdHFjIC0taW5wdXQgIiR7aW5wdXR9Igpkb25lCmNkICIke3N0YXJ0fSIKYGBgCgojIyMgRmFzdHAKCkEgbmV3IHRvb2wgd2hpY2ggcGVyZm9ybXMgdHJpbW1pbmcgYW5kIFFDIG1ldHJpY3MgYXQgdGhlIHNhbWUgdGltZSBpcwpmYXN0cC4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCm1vZHVsZSBhZGQgY3lvYQpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kICopOyBkbwogICAgY2QgIiR7c3RhcnR9LyR7aX0iCiAgICBpbnB1dD0kKC9iaW4vbHMgdW5wcm9jZXNzZWQvKi5mYXN0cS5neiB8IHRyICdcbicgJzonKQogICAgY3lvYSAtLW1ldGhvZCBmYXN0cCAtLWlucHV0ICIke2lucHV0fSIKZG9uZQpjZCAiJHtzdGFydH0iCmBgYAoKIyMgR2VuZS9UeCBxdWFudGlmaWNhdGlvbgoKIyMjIFRyYW5zY3JpcHQgcXVhbnRpZmljYXRpb24gdmlhIHNhbG1vbgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CmNkIHByZXByb2Nlc3NpbmcKbW9kdWxlIGFkZCBjeW9hCnN0YXJ0PSQocHdkKQpmb3IgaSBpbiAkKC9iaW4vbHMgLWQgKik7IGRvCiAgICBjZCAiJHtzdGFydH0vJHtpfSIKICAgIGlucHV0PSQoL2Jpbi9scyBvdXRwdXRzLzAxdHJpbW9tYXRpYy8qLXRyaW1tZWQuZmFzdHEueHogfCB0ciAnXG4nICc6JykKICAgIGN5b2EgLS1tZXRob2Qgc2FsbW9uIC0taW5wdXQgIiR7aW5wdXR9IiAtLXNwZWNpZXMgIiR7c3BlY2llc30iCmRvbmUKY2QgIiR7c3RhcnR9IgpgYGAKCiMjIyBHZW5lIHF1YW50aWZpY2F0aW9uIHZpYSBoaXNhdDIKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCm1vZHVsZSBhZGQgY3lvYQpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kICopOyBkbwogICAgY2QgIiR7c3RhcnR9LyR7aX0iCiAgICBpbnB1dD0kKC9iaW4vbHMgb3V0cHV0cy8wMXRyaW1vbWF0aWMvKi10cmltbWVkLmZhc3RxLnh6IHwgdHIgJ1xuJyAnOicpCiAgICBjeW9hIC0tbWV0aG9kIGhpc2F0IC0tc3BlY2llcyAiJHtzcGVjaWVzfSIgLS1pbnB1dCAiJHtpbnB1dH0iIC0tZ2ZmX3R5cGUgIiR7eGxfdHlwZX0iIFwKICAgICAgICAgLS1nZmZfdGFnICIke3hsX3RhZ30iIC0tc3RyYW5kZWQgIiR7c3RyYW5kZWR9Igpkb25lCmNkICIke3N0YXJ0fSIKYGBgCgojIyByUk5BIFF1ZXJ5CgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KY2QgcHJlcHJvY2Vzc2luZwptb2R1bGUgYWRkIGN5b2EKc3RhcnQ9JChwd2QpCmZvciBpIGluICQoL2Jpbi9scyAtZCAqKTsgZG8KICAgIGNkICIke3N0YXJ0fS8ke2l9IgogICAgaW5wdXQ9JCgvYmluL2xzIHVucHJvY2Vzc2VkLyouZmFzdHEuZ3ogfCB0ciAnXG4nICc6JykKICAgIGN5b2EgLS1tZXRob2QgaGlzYXQgLS1saWJ0eXBlIHJSTkEgLS1zcGVjaWVzICIke3NwZWNpZXN9Il8gLS1pbnB1dCAiJHtpbnB1dH0iIFwKICAgICAgICAgLS1zdHJhbmRlZCAiJHtzdHJhbmRlZH0iIC0tZ2ZmX3R5cGUgclJOQSAtLWdmZl90YWcgZ2VuZQpkb25lCmNkICIke3N0YXJ0fSIKYGBgCgojIExvYWQgZ2VuZSBhbm5vdGF0aW9ucwoKSSB3aWxsIGxvYWQgbXkgYW5ub3RhdGlvbnMgZnJvbSBhIGNvbWJpbmF0aW9uIG9mIGVuc2VtYmwgYW5kIHRoZSBOQ0JJCmdmZiBmaWxlOyBJIHByZXN1bWUgdGhlIGdlbmUgSURzIHdpbGwgbWF0Y2ggdXAsIHNpbmNlIHRoZSBOQ0JJCmFzc2VtYmx5IGFuZCBlbnNlbWJsIGhhdmUgdGhlIHNhbWUgc291cmNlLgoKYGBge3J9CnhsX21STkFfYW5ub3QgPC0gbG9hZF9nZmZfYW5ub3RhdGlvbnMoInJlZmVyZW5jZS94ZW5vcHVzX2xhZXZpc192MTAuMS5nZmYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAibVJOQSIsIGlkX2NvbCA9ICJnZW5lIikKeGxfQ0RTX2Fubm90IDwtIGxvYWRfZ2ZmX2Fubm90YXRpb25zKCJyZWZlcmVuY2UveGVub3B1c19sYWV2aXNfdjEwLjEuZ2ZmIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gIkNEUyIsIGlkX2NvbCA9ICJnZW5lIikKCiMjIHhsX2Vuc19hbm5vdCA8LSBsb2FkX2Jpb21hcnRfYW5ub3RhdGlvbnMoc3BlY2llcyA9ICJ4bGFldmlzIiwgYXJjaGl2ZSA9IEZBTFNFKQpgYGAKCiMgTG9hZCB0aGUgc2FsbW9uIHRyYW5zY3JpcHQgY291bnRzCgpUaGlzIHdpbGwgbGlrZWx5IGJlIHRyaWNreSBiZWNhdXNlIHNhbG1vbiBoYXMgc29tZSBwZWN1bGlhciBydWxlcwphYm91dCBnZW5lL3RyYW5zY3JpcHQgSURzIHdoaWNoIEkgc3Ryb25nbHkgc3VzcGVjdCB3aWxsIG5vdCBtYXRjaCB1cAp3aXRoIHRoZSBJRHMgcHJvZHVjZWQgd2hlbiByZWFkaW5nIGZyb20gdGhlIGdmZiBhbm5vdGF0aW9ucyBvcgpiaW9tYXJ0LiAgTGV0IHVzIGZpbmQgb3V0ISAgSGVyZSBhcmUgdGhlIGZpcnN0IGZldyBlbnRyaWVzIG9mIHRoZQpzYWxtb24gcXVhbnQgZmlsZToKClhQXzA0MTQ0MjMyMy4xX0xPQzEwODcwNDg3M19HZW5lSUQ6MTA4NzA0ODczX3BlcHNpbl9BX2lzb2Zvcm1fWDEgICAgMTE0MyAgICA4NTMuMTA5IDAuNDg3NzE0ICAgIDkuMDAwClhQXzA0MTQ0MjMyNi4xX0xPQzEwODcwNDg3M19HZW5lSUQ6MTA4NzA0ODczX3BlcHNpbl9BX2lzb2Zvcm1fWDIgICAgMTAzNSAgICA3NDMuMDAwIDAuMDAwMDAwICAgIDAuMDAwClhQXzAxODA5NzA1NC4yX0xPQzEwODcwNDg2MV9HZW5lSUQ6MTA4NzA0ODYxX3BlcHRpZGFzZV9pbmhpYml0b3JfMTYgMTY1NiAgICAxMzY0LjAwMCAgICAwLjAwMDAwMCAgICAwLjAwMApYUF8wNDE0MzYzODguMV9kb2sxLkxfR2VuZUlEOjQ0NDMzNV9kb2NraW5nX3Byb3RlaW5fMV9MX2hvbWVvbG9nX2lzb2Zvcm1fWDEgMjEyNyAgICAxODExLjY3OSAgICA2LjE0OTgzMyAgICAyNDEuMDAwCk5QXzAwMTA4NTkwOC4xX2RvazEuTF9HZW5lSUQ6NDQ0MzM1X2RvY2tpbmdfcHJvdGVpbl8xX0xfaG9tZW9sb2cgICAgMTc4MiAgICAxNDc2LjIyMCAgICAwLjAwMDAwMCAgICAwLjAwMApOUF8wMDEwODQ2NDUuMV9tcnBzMjYuTF9HZW5lSUQ6NDE0NjA0X3VuY2hhcmFjdGVyaXplZF9wcm90ZWluX0xPQzQxNDYwNCA2MTUgMzE3Ljc1OCAxNTUuODE4OTU1ICAxMDcxLjAwMApYUF8wMTgwOTcwNTUuMV9MT0MxMDg3MDQ4NjJfR2VuZUlEOjEwODcwNDg2Ml9tZWlvc2lzXzFfYXJyZXN0X3Byb3RlaW4gICAxNTE1ICAgIDEyMjMuMDAwICAgIDAuMDAwMDAwICAgIDAuMDAwClhQXzAxODA5NzA1MC4yX2RxeDEuTF9HZW5lSUQ6MTA4NzA0ODU3X0xPV19RVUFMSVRZX1BST1RFSU46X0FUUC1kZXBlbmRlbnRfUk5BX2hlbGljYXNlX0RRWDEgMjE5NyAgICAxODUyLjQ5NSAgICAyLjk0NDc3OCAgICAxMTguMDAwClhQXzA0MTQ0MjMzMi4xX0xPQzEwODcwNDg3NF9HZW5lSUQ6MTA4NzA0ODc0X21hdHJpeF9tZXRhbGxvcHJvdGVpbmFzZS0yMSAgMTg1NyAgMTU2NS4wMDAgICAgMC4wMDAwMDAgICAgMC4wMDAKClNvLCB5ZWFoLCB0aGF0IGlzIGdvaW5nIHRvIGJlIGFubm95aW5nLgoKSSB1c3VhbGx5IGdldCBhbGwgb2YgbXkgZ2Vub21lcy9hbm5vdGF0aW9ucyBmcm9tIGVuc2VtYmwsIEkgYW0gbm93CnJlbWVtYmVyaW5nIHdoeSB0aGlzIGlzLiAgSSBkbyBub3QgdGhpbmsgaXQgc2hvdWxkIHByb3ZlIGRpZmZpY3VsdCB0bwpjcm9zcyByZWZlcmVuY2UgbXkgbmNiaSBhbmQgZW5zZW1ibCBJRHMsIGJ1dCB3ZSBzaGFsbCBzZWUuCgpUaGUgSURzIGZyb20gc2FsbW9uIGFyZToKCiJ7cHJvdGVpbl9pZH1fe2dlbmV9X3tkYl94cmVmfV97cHJvZHVjdH0iIHdpdGggdGhlIGNhdmVhdCB0aGF0IGFsbApzcGFjZXMgYXJlIHJlcGxhY2VkIGJ5IHVuZGVyc2NvcmUuCgpgYGB7cn0Kc2FsbW9uX2Fubm90IDwtIHhsX0NEU19hbm5vdApyb3duYW1lcyhzYWxtb25fYW5ub3QpIDwtIG1ha2UubmFtZXMoc2FsbW9uX2Fubm90W1sicHJvdGVpbl9pZCJdXSwgdW5pcXVlID0gVFJVRSkKc2FsbW9uX3R4X21hcCA8LSBzYWxtb25fYW5ub3RbLCBjKCJwcm90ZWluX2lkIiwgImdlbmUiKV0Kc2FsbW9uX3R4X21hcFtbInByb3RlaW5faWQiXV0gPC0gZ3N1Yih4ID0gc2FsbW9uX3R4X21hcFtbInByb3RlaW5faWQiXV0sIHBhdHRlcm4gPSAiXFwuW1s6ZGlnaXQ6XV0rIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIiKQpgYGAKCiMgQ3JlYXRlIFN1bW1hcml6ZWRFeHBlcmltZW50CgpJIHdpbGwgY3JlYXRlIG9uZSB2ZXJzaW9uIGJ5IHR4IGFuZCBvbmUgYnkgZ2VuZS4KCmBgYHtyfQp0eF9zZSA8LSBjcmVhdGVfc2UoInNhbXBsZV9zaGVldHMvYWxsX3NhbXBsZXMueGxzeCIsIGdlbmVfaW5mbyA9IHNhbG1vbl9hbm5vdCwKICAgICAgICAgICAgICAgICAgIGZpbGVfY29sdW1uID0gInNhbG1vbl9xdWFudCIpCnNhbG1vbl9nZW5lX2Fubm90IDwtIHNhbG1vbl9hbm5vdApyb3duYW1lcyhzYWxtb25fZ2VuZV9hbm5vdCkgPC0gbWFrZS5uYW1lcyhzYWxtb25fZ2VuZV9hbm5vdFtbImdlbmUiXV0sIHVuaXF1ZSA9IFRSVUUpCmdlbmVfc2UgPC0gY3JlYXRlX3NlKCJzYW1wbGVfc2hlZXRzL2FsbF9zYW1wbGVzLnhsc3giLCBnZW5lX2luZm8gPSBzYWxtb25fZ2VuZV9hbm5vdCwKICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW4gPSAic2FsbW9uX3F1YW50IiwgdHhfZ2VuZV9tYXAgPSBzYWxtb25fdHhfbWFwKQpgYGAKCiMgTG9vayBhdCB0aGUgMyBzYW1wbGVzCgpgYGB7cn0KZGltKGFzc2F5KHR4X3NlKSkKcGxvdF9saWJzaXplKHR4X3NlKQpkaW0oYXNzYXkoZ2VuZV9zZSkpCnBsb3RfbGlic2l6ZShnZW5lX3NlKQpwbG90X25vbnplcm8odHhfc2UpCnBsb3Rfbm9uemVybyhnZW5lX3NlKQpgYGAKCmBgYHtyfQp0eF9ub3JtIDwtIG5vcm1hbGl6ZSh0eF9zZSwgY29udmVydCA9ICJjcG0iLCBmaWx0ZXIgPSBUUlVFLCB0cmFuc2Zvcm0gPSAibG9nMiIpCnBsb3RfY29yaGVhdCh0eF9ub3JtKQpwbG90X3BjYSh0eF9ub3JtKQp3cml0ZV94bHN4KGV4Y2VsID0gImV4Y2VsL2wyX2NwbV90eC54bHN4IiwgZGF0YSA9IGFzc2F5KHR4X25vcm0pKQpgYGAKCiMgRXhhbXBsZSBJbnZvY2F0aW9ucwoKIyMgVHJpbW9tYXRpYwoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CiMhL3Vzci9iaW4vYmFzaAojU0JBVENIIC0tZXhwb3J0PUFMTCAtLW1haWwtdHlwZT1OT05FIC0tb3Blbi1tb2RlPWFwcGVuZAojU0JBVENIIC0tY2hkaXI9L2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gxCiNTQkFUQ0ggLS1qb2ItbmFtZT0wMXRyaW1fWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEgLS1uaWNlPTEwCiNTQkFUQ0ggLS1vdXRwdXQ9L2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gxL291dHB1dHMvbG9nLnR4dC5zYmF0Y2gKI1NCQVRDSCAtLWFjY291bnQ9Y2JjYgojU0JBVENIIC0tcGFydGl0aW9uPWNiY2IKI1NCQVRDSCAtLXFvcz1tZWRpdW0KI1NCQVRDSCAtLW5vZGVzPTEgLS1udGFza3M9MSAtLWNwdXMtcGVyLXRhc2s9NAojU0JBVENIIC0tdGltZT0zNjowMDowMAojU0JBVENIIC0tbWVtPTZHCnN0YXJ0ZGlyPSQocHdkKQpzZXQgLW8gZXJyZXhpdApzZXQgLW8gZXJydHJhY2UKc2V0IC1vIHBpcGVmYWlsCmVjaG8gIiMjIFN0YXJ0ZWQgL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gxL3NjcmlwdHMvMDF0cmltX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzX1IxLnNoIGF0ICQoZGF0ZSkgb24gJChob3N0bmFtZSkgd2l0aCBpZCAke1NMVVJNX0pPQklEfS4iID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL3dob2xlX2VtYnJ5b194MS9vdXRwdXRzL2xvZy50eHQKZnVuY3Rpb24gZ2V0X3NpZ3Rlcm0gewogIGNkICIke3N0YXJ0ZGlyfSIKICBlY2hvICJBIFNJR1RFUk0gd2FzIHNlbnQgdG8gMDF0cmltX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzX1IxOiAke1NMVVJNX0pPQklEfS4iID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL3dob2xlX2VtYnJ5b194MS9vdXRwdXRzL2xvZy50eHQKICBleGl0IDEKfQp0cmFwIGdldF9zaWd0ZXJtIFNJR1RFUk0KZnVuY3Rpb24gZ2V0X3NpZ2VyciB7CiAgY2QgIiR7c3RhcnRkaXJ9IgogIGVjaG8gIkEgU0lHRVJSIHdhcyBzZW50IHRvIDAxdHJpbV9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMTogJHtTTFVSTV9KT0JJRH0uIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDEvb3V0cHV0cy9sb2cudHh0CiAgZXhpdCAxCn0KdHJhcCBnZXRfc2lnZXJyIEVSUgptb2Q9JCggeyB0eXBlIC10IG1vZHVsZSB8fCB0cnVlOyB9ICkKaWYgW1sgLXogIiR7bW9kfSIgXV07IHRoZW4KICBtb2R1bGUoKSB7CiAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDg2CiAgICB7IGV2YWwgIiQoL3Vzci9iaW4vbW9kdWxlY21kIGJhc2ggJCopIiB8fCB0cnVlOyB9CiAgfQogIGV4cG9ydCAtZiBtb2R1bGUKZmkKbW9kdWxlIGFkZCB0cmltb21hdGljIDI+L2Rldi9udWxsIDE+JjIKIyMgVGhpcyBjYWxsIHRvIHRyaW1vbWF0aWMgcmVtb3ZlcyBpbGx1bWluYSBhbmQgZXBpY2VudHJlIGFkYXB0ZXJzIGZyb20gdW5wcm9jZXNzZWQvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEuZmFzdHEuZ3o6dW5wcm9jZXNzZWQvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjIuZmFzdHEuZ3ouCiMjIEl0IGFsc28gcGVyZm9ybXMgYSBzbGlkaW5nIHdpbmRvdyByZW1vdmFsIG9mIGFueXRoaW5nIHdpdGggcXVhbGl0eSA8MjU7CiMjIGN1dGFkYXB0IHByb3ZpZGVzIGFuIGFsdGVybmF0aXZlIHRvIHRoaXMgdG9vbC4KIyMgVGhlIG9yaWdpbmFsIHNlcXVlbmNlIGRhdGEgaXMgcmVjb21wcmVzc2VkIGFuZCBzYXZlZCBpbiB0aGUgc2VxdWVuY2VzLyBkaXJlY3RvcnkuCm1rZGlyIC1wIG91dHB1dHMvMDF0cmltb21hdGljCiMjIE5vdGUgdGhhdCB0cmltb21hdGljIHByaW50cyBhbGwgb3V0cHV0IGFuZCBlcnJvcnMgdG8gU1RERVJSLCBzbyBzZW5kIGJvdGggdG8gb3V0cHV0CnRyaW1vbWF0aWMgUEUgXAogIC10aHJlYWRzIDEgXAogIC1waHJlZDMzIFwKICB1bnByb2Nlc3NlZC9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMS5mYXN0cS5neiB1bnByb2Nlc3NlZC9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMi5mYXN0cS5neiBcCiAgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjItdHJpbW1lZF9wYWlyZWQuZmFzdHEgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjItdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgIElMTFVNSU5BQ0xJUDovZnMvY2JjYi1zb2Z0d2FyZS9SZWRIYXQtOC14ODZfNjQvbG9jYWwvY3lvYS8yMDI1MDYvcHJlZml4L2xpYi9wZXJsNS9hdXRvL3NoYXJlL2Rpc3QvQmlvLUFkdmVudHVyZS9nZW5vbWUvYWRhcHRlcnMuZmE6MjoyMDoxMDoyOmtlZXBCb3RoUmVhZHMgIFwKICBTTElESU5HV0lORE9XOjQ6MjAgTUlOTEVOOjUwIFwKICAxPm91dHB1dHMvMDF0cmltb21hdGljL1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzLXRyaW1vbWF0aWMuc3Rkb3V0IFwKICAyPm91dHB1dHMvMDF0cmltb21hdGljL1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzLXRyaW1vbWF0aWMuc3RkZXJyCmV4Y2VwdGVkPSQoIHsgZ3JlcCAiRXhjZXB0aW9uIiAib3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDMtdHJpbW9tYXRpYy5zdGRvdXQiIHx8IHRlc3QgJD8gPSAxOyB9ICkKIyMgVGhlIGZvbGxvd2luZyBpcyBpbiBjYXNlIHRoZSBpbGx1bWluYSBjbGlwcGluZyBmYWlscywgd2hpY2ggaXQgZG9lcyBpZiB0aGlzIGhhcyBhbHJlYWR5IGJlZW4gcnVuIEkgdGhpbmsuCmlmIFtbICIke2V4Y2VwdGVkfSIgIT0gIiIgXV07IHRoZW4KICB0cmltb21hdGljIFBFIFwKICAgIC10aHJlYWRzIDEgXAogICAgLXBocmVkMzMgXAogICAgdW5wcm9jZXNzZWQvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEuZmFzdHEuZ3ogdW5wcm9jZXNzZWQvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjIuZmFzdHEuZ3ogXAogICAgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgICBvdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMi10cmltbWVkX3BhaXJlZC5mYXN0cSBvdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMi10cmltbWVkX3VucGFpcmVkLmZhc3RxIFwKICAgICBTTElESU5HV0lORE9XOjQ6MjUgTUlOTEVOOjUwIFwKICAgIDE+b3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDMtdHJpbW9tYXRpYy5zdGRvdXQgXAogICAgMj5vdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwMy10cmltb21hdGljLnN0ZGVycgpmaQpzbGVlcCAxMAptdiBvdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMS10cmltbWVkX3BhaXJlZC5mYXN0cSBvdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMS10cmltbWVkLmZhc3RxCm12IG91dHB1dHMvMDF0cmltb21hdGljL1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzX1IyLXRyaW1tZWRfcGFpcmVkLmZhc3RxIG91dHB1dHMvMDF0cmltb21hdGljL1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzX1IyLXRyaW1tZWQuZmFzdHEKCiMjIFJlY29tcHJlc3MgdGhlIHVucGFpcmVkIHJlYWRzLCB0aGlzIHNob3VsZCBub3QgdGFrZSBsb25nLgp4eiAtOWUgLWYgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cQp4eiAtOWUgLWYgb3V0cHV0cy8wMXRyaW1vbWF0aWMvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjItdHJpbW1lZF91bnBhaXJlZC5mYXN0cQojIyBSZWNvbXByZXNzIHRoZSBwYWlyZWQgcmVhZHMuCnh6IC05ZSAtZiBvdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMS10cmltbWVkLmZhc3RxCnh6IC05ZSAtZiBvdXRwdXRzLzAxdHJpbW9tYXRpYy9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMi10cmltbWVkLmZhc3RxCmxuPSQoY2Qgb3V0cHV0cy8wMXRyaW1vbWF0aWMgJiYgbG4gLXNmIFhORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY3LTAwMV9ONVVELUYwOV9MMDAzX1IxLXRyaW1tZWQuZmFzdHEueHogcjFfdHJpbW1lZC5mYXN0cS54eikKbG49JChjZCBvdXRwdXRzLzAxdHJpbW9tYXRpYyAmJiBsbiAtc2YgWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjctMDAxX041VUQtRjA5X0wwMDNfUjItdHJpbW1lZC5mYXN0cS54eiByMl90cmltbWVkLmZhc3RxLnh6KQoKCgojIyBUaGUgZm9sbG93aW5nIGxpbmVzIGdpdmUgc3RhdHVzIGNvZGVzIGFuZCBzb21lIGxvZ2dpbmcKIyMgVGhpcyBtaWdodCBub3Qgd29yayBiZWNhdXNlIGl0IGlzIGEgbGl0dGxlIGNpcmN1bGFyLgpjZCAke3N0YXJ0ZGlyfQptaW51dGVzX3VzZWQ9JCgoIFNFQ09ORFMgLyA2MCApKQplY2hvICIgICQoaG9zdG5hbWUpIEZpbmlzaGVkICR7U0xVUk1fSk9CSUR9IDAxdHJpbV9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2Ny0wMDFfTjVVRC1GMDlfTDAwM19SMS5zaCBhdCAkKGRhdGUpLCBpdCB0b29rICR7bWludXRlc191c2VkfSBtaW51dGVzLiIgPj4gL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gxL291dHB1dHMvbG9nLnR4dAppZiBbWyAteCAiJChjb21tYW5kIC12IHNzdGF0KSIgJiYgLW4gIiR7U0xVUk1fSk9CSUR9IiBdXTsgdGhlbgogIGVjaG8gIiAgd2FsbHRpbWUgdXNlZCBieSAke1NMVVJNX0pPQklEfSB3YXM6ICR7bWludXRlc191c2VkOi1udWxsfSBtaW51dGVzLiIgPj4gL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gxL291dHB1dHMvbG9nLnR4dAogIGVjaG8gIiIgPj4gL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gxL291dHB1dHMvbG9nLnR4dApmaQojIyBOb3RlLCB5b3UgY2FuIHNjb3JlIGEgYnVuY2ggbW9yZSBpbmZvcm1hdGlvbiBieSBydW5uaW5nIGN5b2EgLS1tZXRob2QgY2hlY2tqb2IgZnJvbSB0aGUgd29ya2luZyBkaXJlY3RvcnkuCmBgYAoKIyMgRmFzdFFDCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvdXNyL2Jpbi9iYXNoCiNTQkFUQ0ggLS1leHBvcnQ9QUxMIC0tbWFpbC10eXBlPU5PTkUgLS1vcGVuLW1vZGU9YXBwZW5kCiNTQkFUQ0ggLS1jaGRpcj0vZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy9kaXNzb2NpYXRlZF9lbWJyeW9feDYKI1NCQVRDSCAtLWpvYi1uYW1lPTAxZnFjX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY5LTAwMV9ONVVELUgwOV9MMDAzX1IxX3VucHJvY2Vzc2VkIC0tbmljZT0xMAojU0JBVENIIC0tb3V0cHV0PS9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni9vdXRwdXRzL2xvZy50eHQuc2JhdGNoCiNTQkFUQ0ggLS1hY2NvdW50PW5leHVzCiNTQkFUQ0ggLS1wYXJ0aXRpb249dHJvbgojU0JBVENIIC0tcW9zPW1lZGl1bQojU0JBVENIIC0tbm9kZXM9MSAtLW50YXNrcz0xIC0tY3B1cy1wZXItdGFzaz04CiNTQkFUQ0ggLS10aW1lPTM6MDA6MDAKI1NCQVRDSCAtLW1lbT0yMEcKc3RhcnRkaXI9JChwd2QpCnNldCAtbyBlcnJleGl0CnNldCAtbyBlcnJ0cmFjZQpzZXQgLW8gcGlwZWZhaWwKZWNobyAiIyMgU3RhcnRlZCAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy9kaXNzb2NpYXRlZF9lbWJyeW9feDYvc2NyaXB0cy8wMWZxY19YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OS0wMDFfTjVVRC1IMDlfTDAwM19SMV91bnByb2Nlc3NlZC5zaCBhdCAkKGRhdGUpIG9uICQoaG9zdG5hbWUpIHdpdGggaWQgJHtTTFVSTV9KT0JJRH0uIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy9kaXNzb2NpYXRlZF9lbWJyeW9feDYvb3V0cHV0cy9sb2cudHh0CmZ1bmN0aW9uIGdldF9zaWd0ZXJtIHsKICBjZCAiJHtzdGFydGRpcn0iCiAgZWNobyAiQSBTSUdURVJNIHdhcyBzZW50IHRvIDAxZnFjX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY5LTAwMV9ONVVELUgwOV9MMDAzX1IxX3VucHJvY2Vzc2VkOiAke1NMVVJNX0pPQklEfS4iID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni9vdXRwdXRzL2xvZy50eHQKICBleGl0IDEKfQp0cmFwIGdldF9zaWd0ZXJtIFNJR1RFUk0KZnVuY3Rpb24gZ2V0X3NpZ2VyciB7CiAgY2QgIiR7c3RhcnRkaXJ9IgogIGVjaG8gIkEgU0lHRVJSIHdhcyBzZW50IHRvIDAxZnFjX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY5LTAwMV9ONVVELUgwOV9MMDAzX1IxX3VucHJvY2Vzc2VkOiAke1NMVVJNX0pPQklEfS4iID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni9vdXRwdXRzL2xvZy50eHQKICBleGl0IDEKfQp0cmFwIGdldF9zaWdlcnIgRVJSCm1vZD0kKCB7IHR5cGUgLXQgbW9kdWxlIHx8IHRydWU7IH0gKQppZiBbWyAteiAiJHttb2R9IiBdXTsgdGhlbgogIG1vZHVsZSgpIHsKICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwODYKICAgIHsgZXZhbCAiJCgvdXNyL2Jpbi9tb2R1bGVjbWQgYmFzaCAkKikiIHx8IHRydWU7IH0KICB9CiAgZXhwb3J0IC1mIG1vZHVsZQpmaQptb2R1bGUgYWRkIGZhc3RxYyAyPi9kZXYvbnVsbCAxPiYyCiMjIFRoaXMgRmFzdFFDIHJ1biBpcyBhZ2FpbnN0IHVuZmlsdGVyZWQgZGF0YSBhbmQgaXMgdXNlZCBmb3IKIyMgYW4gaW5pdGlhbCBlc3RpbWF0aW9uIG9mIHRoZSBvdmVyYWxsIHNlcXVlbmNpbmcgcXVhbGl0eS4KbWtkaXIgLXAgb3V0cHV0cy8wMWZhc3RxYwp3aGljaCBwZXJsIDI+b3V0cHV0cy8wMWZhc3RxYy9mcWNfWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjktMDAxX041VUQtSDA5X0wwMDNfUjFfdW5wcm9jZXNzZWQtdW5maWx0ZXJlZF9mYXN0cWMuc3RkZXJyIDE+JjIKd2hpY2ggZmFzdHFjIDI+Pm91dHB1dHMvMDFmYXN0cWMvZnFjX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY5LTAwMV9ONVVELUgwOV9MMDAzX1IxX3VucHJvY2Vzc2VkLXVuZmlsdGVyZWRfZmFzdHFjLnN0ZGVyciAxPiYyCiMjIEV2ZW4gaWYgZmFzdHFjIGZpbmlzaGVzIGhhcHBpbHkgdXNpbmcgYSBzdWJzaGVsbCwgaXQgbWlnaHQgZXhpdCB3aXRoIFNJR0VSUgp0cmFwIC0gRVJSCmZpbmlzaGVkPSQoZmFzdHFjIC0tZXh0cmFjdCBcCiAgLW8gb3V0cHV0cy8wMWZhc3RxYyBcCiAgIC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni91bnByb2Nlc3NlZC9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OS0wMDFfTjVVRC1IMDlfTDAwM19SMS5mYXN0cS5neiAgL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3NpbmcvZGlzc29jaWF0ZWRfZW1icnlvX3g2L3VucHJvY2Vzc2VkL1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY5LTAwMV9ONVVELUgwOV9MMDAzX1IyLmZhc3RxLmd6ICBcCiAgMj4+b3V0cHV0cy8wMWZhc3RxYy9mcWNfWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjktMDAxX041VUQtSDA5X0wwMDNfUjFfdW5wcm9jZXNzZWQtdW5maWx0ZXJlZF9mYXN0cWMuc3RkZXJyIFwKICAxPj5vdXRwdXRzLzAxZmFzdHFjL2ZxY19YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OS0wMDFfTjVVRC1IMDlfTDAwM19SMV91bnByb2Nlc3NlZC11bmZpbHRlcmVkX2Zhc3RxYy5zdGRvdXQgfHwgL2Jpbi90cnVlKQplY2hvICJmYXN0cWMgZmluaXNoZWQgd2l0aCAkPyBhbmRvciAke2ZpbmlzaGVkfS4iCgoKCiMjIFRoZSBmb2xsb3dpbmcgbGluZXMgZ2l2ZSBzdGF0dXMgY29kZXMgYW5kIHNvbWUgbG9nZ2luZwojIyBUaGlzIG1pZ2h0IG5vdCB3b3JrIGJlY2F1c2UgaXQgaXMgYSBsaXR0bGUgY2lyY3VsYXIuCmNkICR7c3RhcnRkaXJ9Cm1pbnV0ZXNfdXNlZD0kKCggU0VDT05EUyAvIDYwICkpCmVjaG8gIiAgJChob3N0bmFtZSkgRmluaXNoZWQgJHtTTFVSTV9KT0JJRH0gMDFmcWNfWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjktMDAxX041VUQtSDA5X0wwMDNfUjFfdW5wcm9jZXNzZWQuc2ggYXQgJChkYXRlKSwgaXQgdG9vayAke21pbnV0ZXNfdXNlZH0gbWludXRlcy4iID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni9vdXRwdXRzL2xvZy50eHQKaWYgW1sgLXggIiQoY29tbWFuZCAtdiBzc3RhdCkiICYmIC1uICIke1NMVVJNX0pPQklEfSIgXV07IHRoZW4KICBlY2hvICIgIHdhbGx0aW1lIHVzZWQgYnkgJHtTTFVSTV9KT0JJRH0gd2FzOiAke21pbnV0ZXNfdXNlZDotbnVsbH0gbWludXRlcy4iID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni9vdXRwdXRzL2xvZy50eHQKICBlY2hvICIiID4+IC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL2Rpc3NvY2lhdGVkX2VtYnJ5b194Ni9vdXRwdXRzL2xvZy50eHQKZmkKIyMgTm90ZSwgeW91IGNhbiBzY29yZSBhIGJ1bmNoIG1vcmUgaW5mb3JtYXRpb24gYnkgcnVubmluZyBjeW9hIC0tbWV0aG9kIGNoZWNram9iIGZyb20gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgpgYGAKCiMjIEZhc3RwCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvdXNyL2Jpbi9iYXNoCiNTQkFUQ0ggLS1leHBvcnQ9QUxMIC0tbWFpbC10eXBlPU5PTkUgLS1vcGVuLW1vZGU9YXBwZW5kCiNTQkFUQ0ggLS1jaGRpcj0vZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMKI1NCQVRDSCAtLWpvYi1uYW1lPTEyZmFzdHBfWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjgtMDAxX041VUQtRzA5X0wwMDNfUjEgLS1uaWNlPTEwCiNTQkFUQ0ggLS1vdXRwdXQ9L2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gzL291dHB1dHMvbG9nLnR4dC5zYmF0Y2gKI1NCQVRDSCAtLWFjY291bnQ9Y2JjYgojU0JBVENIIC0tcGFydGl0aW9uPWNiY2IKI1NCQVRDSCAtLXFvcz1tZWRpdW0KI1NCQVRDSCAtLW5vZGVzPTEgLS1udGFza3M9MSAtLWNwdXMtcGVyLXRhc2s9MgojU0JBVENIIC0tdGltZT04OjAwOjAwCiNTQkFUQ0ggLS1tZW09MTJHCnN0YXJ0ZGlyPSQocHdkKQpzZXQgLW8gZXJyZXhpdApzZXQgLW8gZXJydHJhY2UKc2V0IC1vIHBpcGVmYWlsCmVjaG8gIiMjIFN0YXJ0ZWQgL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gzL3NjcmlwdHMvMTJmYXN0cF9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OC0wMDFfTjVVRC1HMDlfTDAwM19SMS5zaCBhdCAkKGRhdGUpIG9uICQoaG9zdG5hbWUpIHdpdGggaWQgJHtTTFVSTV9KT0JJRH0uIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMvb3V0cHV0cy9sb2cudHh0CmZ1bmN0aW9uIGdldF9zaWd0ZXJtIHsKICBjZCAiJHtzdGFydGRpcn0iCiAgZWNobyAiQSBTSUdURVJNIHdhcyBzZW50IHRvIDEyZmFzdHBfWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjgtMDAxX041VUQtRzA5X0wwMDNfUjE6ICR7U0xVUk1fSk9CSUR9LiIgPj4gL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9uZW1lc18yMDI1L3ByZXByb2Nlc3Npbmcvd2hvbGVfZW1icnlvX3gzL291dHB1dHMvbG9nLnR4dAogIGV4aXQgMQp9CnRyYXAgZ2V0X3NpZ3Rlcm0gU0lHVEVSTQpmdW5jdGlvbiBnZXRfc2lnZXJyIHsKICBjZCAiJHtzdGFydGRpcn0iCiAgZWNobyAiQSBTSUdFUlIgd2FzIHNlbnQgdG8gMTJmYXN0cF9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OC0wMDFfTjVVRC1HMDlfTDAwM19SMTogJHtTTFVSTV9KT0JJRH0uIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMvb3V0cHV0cy9sb2cudHh0CiAgZXhpdCAxCn0KdHJhcCBnZXRfc2lnZXJyIEVSUgptb2Q9JCggeyB0eXBlIC10IG1vZHVsZSB8fCB0cnVlOyB9ICkKaWYgW1sgLXogIiR7bW9kfSIgXV07IHRoZW4KICBtb2R1bGUoKSB7CiAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDg2CiAgICB7IGV2YWwgIiQoL3Vzci9iaW4vbW9kdWxlY21kIGJhc2ggJCopIiB8fCB0cnVlOyB9CiAgfQogIGV4cG9ydCAtZiBtb2R1bGUKZmkKbW9kdWxlIGFkZCBmYXN0cCAyPi9kZXYvbnVsbCAxPiYyCiMjIFJ1biBmYXN0cCBvbiByYXcgZGF0YQoKCm1rZGlyIC1wIG91dHB1dHMvMTJmYXN0cAp0cmltbWVkPTEKewogIC91c3IvYmluL3RpbWUgLXYgLW8gb3V0cHV0cy8xMmZhc3RwL3N0ZG91dC50aW1lIC1hCiAgICBmYXN0cCAgIC1pIC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbmVtZXNfMjAyNS9wcmVwcm9jZXNzaW5nL3dob2xlX2VtYnJ5b194My91bnByb2Nlc3NlZC9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OC0wMDFfTjVVRC1HMDlfTDAwM19SMS5mYXN0cS5neiBcCiAgLW8gb3V0cHV0cy8xMmZhc3RwL1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY4LTAwMV9ONVVELUcwOV9MMDAzX1IxLWZhc3RwLmZhc3RxIFwKICAtSSAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMvdW5wcm9jZXNzZWQvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjgtMDAxX041VUQtRzA5X0wwMDNfUjIuZmFzdHEuZ3ogXAogIC1PIG91dHB1dHMvMTJmYXN0cC9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OC0wMDFfTjVVRC1HMDlfTDAwM19SMi1mYXN0cC5mYXN0cSAgXAogICAgICAtaCBvdXRwdXRzLzEyZmFzdHAvZmFzdHBfcmVwb3J0Lmh0bWwgXAogIC1qIG91dHB1dHMvMTJmYXN0cC9mYXN0cF9yZXBvcnQuanNvbiAgLUQgIC1jICAteSAgXAogICAgICAyPm91dHB1dHMvMTJmYXN0cC9zdGRlcnIgXAogICAgICAxPm91dHB1dHMvMTJmYXN0cC9zdGRvdXQKCnh6IC05ZSAtZiBvdXRwdXRzLzEyZmFzdHAvWE5FTUVfMjAyNTA1MjBfQTAwOTA0X0lMMjIzNjgtMDAxX041VUQtRzA5X0wwMDNfUjEtZmFzdHAuZmFzdHEKeHogLTllIC1mIG91dHB1dHMvMTJmYXN0cC9YTkVNRV8yMDI1MDUyMF9BMDA5MDRfSUwyMjM2OC0wMDFfTjVVRC1HMDlfTDAwM19SMi1mYXN0cC5mYXN0cQoKfSB8fCB7CiAgZWNobyAnZmFzdHAgZmFpbGVkLicgPj4gb3V0cHV0cy8xMmZhc3RwL3N0ZGVycgp9CgoKIyMgVGhlIGZvbGxvd2luZyBsaW5lcyBnaXZlIHN0YXR1cyBjb2RlcyBhbmQgc29tZSBsb2dnaW5nCiMjIFRoaXMgbWlnaHQgbm90IHdvcmsgYmVjYXVzZSBpdCBpcyBhIGxpdHRsZSBjaXJjdWxhci4KY2QgJHtzdGFydGRpcn0KbWludXRlc191c2VkPSQoKCBTRUNPTkRTIC8gNjAgKSkKZWNobyAiICAkKGhvc3RuYW1lKSBGaW5pc2hlZCAke1NMVVJNX0pPQklEfSAxMmZhc3RwX1hORU1FXzIwMjUwNTIwX0EwMDkwNF9JTDIyMzY4LTAwMV9ONVVELUcwOV9MMDAzX1IxLnNoIGF0ICQoZGF0ZSksIGl0IHRvb2sgJHttaW51dGVzX3VzZWR9IG1pbnV0ZXMuIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMvb3V0cHV0cy9sb2cudHh0CmlmIFtbIC14ICIkKGNvbW1hbmQgLXYgc3N0YXQpIiAmJiAtbiAiJHtTTFVSTV9KT0JJRH0iIF1dOyB0aGVuCiAgZWNobyAiICB3YWxsdGltZSB1c2VkIGJ5ICR7U0xVUk1fSk9CSUR9IHdhczogJHttaW51dGVzX3VzZWQ6LW51bGx9IG1pbnV0ZXMuIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMvb3V0cHV0cy9sb2cudHh0CiAgZWNobyAiIiA+PiAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL25lbWVzXzIwMjUvcHJlcHJvY2Vzc2luZy93aG9sZV9lbWJyeW9feDMvb3V0cHV0cy9sb2cudHh0CmZpCiMjIE5vdGUsIHlvdSBjYW4gc2NvcmUgYSBidW5jaCBtb3JlIGluZm9ybWF0aW9uIGJ5IHJ1bm5pbmcgY3lvYSAtLW1ldGhvZCBjaGVja2pvYiBmcm9tIHRoZSB3b3JraW5nIGRpcmVjdG9yeS4KYGBgCgpgYGB7cn0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgc2F2ZWZpbGUpKQojI3RtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWUgPSBzYXZlZmlsZSkpCmBgYAoKYGBge3IgbG9hZG1lX2FmdGVyLCBldmFsPUZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=