1 Preprocessing DIA data via the instructions at: http://dia-swath-course.ethz.ch/tutorials2017/

2 Generating a high-res (HCD) spectral search library.

2.1 Reading metadata

In theory, I have figured out how to render a mix of bash and r in multiple blocks. This worksheet will test that theory by copy/pasting out the various sections of bash required to do the processing of this data into blocks labeled ‘bash_runr’.

If I am correct, we will be able then to test and render each piece of this process without having to run the entire thing as a bash script at the end.

The original script which provides the meat of this document is still here in case this fails as dia_invocation_hcd_20180530.sh.

sample_sheet <- "sample_sheets/dda_samples.xlsx"
savefile <- "mzxml_dda_data_201805.rda"

metadata <- openxlsx::read.xlsx(sample_sheet)
keeper_idx <- metadata[["sampledate"]] == "20180420"
metadata <- metadata[keeper_idx, ]

knitr::kable(metadata)
sampleid sampletype condition batch enzyme sampledate rundate runinfo rawfile mzxmlfile note
3 2018_0420Briken01 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken01.mzXML NA
4 2018_0420Briken02 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken02.mzXML NA
5 2018_0420Briken03 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken03.mzXML NA
6 2018_0420Briken04 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken04.mzXML NA
7 2018_0420Briken05 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken05.mzXML NA
8 2018_0420Briken06 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken06.mzXML NA
9 2018_0420Briken07 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken07.raw mzXML/dda_201805_whole/2018_0420Briken07.mzXML NA
10 2018_0420Briken08 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken08.raw mzXML/dda_201805_whole/2018_0420Briken08.mzXML NA
11 2018_0420Briken11 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken11.raw mzXML/dda_201805_cf/2018_0420Briken11.mzXML NA
12 2018_0420Briken12 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken12.raw mzXML/dda_201805_cf/2018_0420Briken12.mzXML NA
13 2018_0420Briken13 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken13.raw mzXML/dda_201805_cf/2018_0420Briken13.mzXML NA
14 2018_0420Briken14 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken14.raw mzXML/dda_201805_cf/2018_0420Briken14.mzXML NA
15 2018_0420Briken15 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken15.raw mzXML/dda_201805_cf/2018_0420Briken15.mzXML NA
16 2018_0420Briken16 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken16.raw mzXML/dda_201805_cf/2018_0420Briken16.mzXML NA
17 2018_0420Briken17 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken17.raw mzXML/dda_201805_cf/2018_0420Briken17.mzXML NA
18 2018_0420Briken18 WT H37Rv Whole Cell Lysate wt e Trypsin 20180420 20180420 High resolution MS2 raw/2018_0420Briken18.raw mzXML/dda_201805_cf/2018_0420Briken18.mzXML NA

2.2 Gather data and plot metrics

if (file.exists(savefile)) {
  load(savefile)
} else {
  mzxml_data <- sm(extract_mzxml_data(metadata,
                                      file_column="mzxmlfile",
                                      savefile=savefile))
}

intensity_boxplot <- sm(plot_mzxml_boxplot(mzxml_data))
pp(file="images/mzxml_intensities.png", image=intensity_boxplot)

retention_boxplot <- sm(plot_mzxml_boxplot(mzxml_data, table="scans", column="peakscount"))
pp(file="images/mzxml_retention.png", image=retention_boxplot)

mz_boxplot <- sm(plot_mzxml_boxplot(mzxml_data, table="scans", column="basepeakmz"))
pp(file="images/mzxml_mzbase.png", image=mz_boxplot)

scanintensity_boxplot <- sm(plot_mzxml_boxplot(mzxml_data, table="scans", column="basepeakintensity"))
pp(file="images/mzxml_scanintensity.png", image=scanintensity_boxplot)

intensity_wrt_mz <- sm(plot_intensity_mz(mzxml_data, x_scale="log", y_scale="log"))
pp(file="images/intensity_wrt_mz_dia.png", image=intensity_wrt_mz$plot)

3 Get DIA metrics

Do not forget that extract_mzxml_data() writes the acquisition window files required for openswathworkflow to run, so do not forget to run it.

3.1 Read dia metadata

sample_sheet <- "sample_sheets/Mtb_dia_samples.xlsx"
savefile <- "mzxml_dia_data_201805.rda"

metadata <- openxlsx::read.xlsx(sample_sheet)
keeper_idx <- metadata[["expt_id"]] == "may2018"
keeper_idx[is.na(keeper_idx)] <- FALSE
metadata <- metadata[keeper_idx, ]
knitr::kable(metadata)

3.2 Plot dia metrics

Now let us plot the dia sample data.

if (file.exists(savefile)) {
  load(savefile)
} else {
  mzxml_data <- sm(extract_mzxml_data(metadata,
                                      file_column="Filename",
                                      savefile=savefile))
}

intensity_boxplot <- plot_mzxml_boxplot(mzxml_data)
pp(file="images/201805_dia_mzxml_intensities.png", image=intensity_boxplot)

retention_boxplot <- plot_mzxml_boxplot(mzxml_data, table="scans", column="peakscount")
pp(file="images/201805_dia_mzxml_retention.png", image=retention_boxplot)

mz_boxplot <- plot_mzxml_boxplot(mzxml_data, table="scans", column="basepeakmz")
pp(file="images/201805_dia_mzxml_mzbase.png", image=mz_boxplot)

scanintensity_boxplot <- plot_mzxml_boxplot(mzxml_data, table="scans", column="basepeakintensity")
pp(file="images/201805_dia_mzxml_scanintensity.png", image=scanintensity_boxplot)

intensity_wrt_mz <- plot_intensity_mz(mzxml_data, x_scale="log", y_scale="log")
pp(file="images/201805_dia_intensity_wrt_mz_dia.png", image=intensity_wrt_mz)

4 Gathering parameters

In this first block, I will set a couple of variables and source a file containing the parameters for the rest of the script.

ls parameters
export VERSION="20180530"
source parameters/20180530_settings.sh
echo "Version is: ${VERSION}"
## Bad Password

4.1 Test that we have the required variables for the rest of the script.

env | grep ${VERSION}

##cd "${START}"
echo $START
## Bad Password

5 Run comet on our DDA data

echo "Starting run of comet using the configuration file:
comet/comet_${DDA_METHOD}_params.txt against ${DDA_INPUTS}."
for comet_input in ${DDA_INPUTS}
do
    echo "The input is: ${comet_input}"
    /cbcb/sw/RedHat-7-x86_64/common/local/tpp/5.1.0/bin/comet \
        "-Pcomet/comet_${DDA_METHOD}_params.txt" \
        "${comet_input}" \
        2>>"comet/comet_${VERSION}.log" 1>&2
done
tail "comet/comet_${VERSION}.log"
## Bad Password

6 Refresh the comet results

Comet does not provide the alternate hits, the following should add them into the comet output files.

echo "Starting refreshparser to hopefully add back the alternate matches dropped by comet."
for refresh_input in ${PEPXML_INPUTS}
do
    echo "The input is: ${refresh_input}."
    RefreshParser \
        "${refresh_input}" \
        "${REFDB}" \
        2>>${refresh_input}.log 1>&2
done
## Bad Password

7 Merge searches

echo "Invoking xinteract to merge searches, set decoys, and set up fdr."
mkdir -p "results/fdr_controlled_${VERSION}_${TYPE}"
echo "The input is: ${PEPXML_INPUTS}"
echo "The output is: ${FDR_RESULT}"
xinteract \
    "-d${DECOY_STRING}" \
    -OARPpd \
    -Ow \
    "-N${FDR_RESULT}" \
    "mzXML/dda_${VERSION}_${TYPE}"/*.pep.xml \
    2>>"${FDR_RESULT}.log" 1>&2
tail "${FDR_RESULT}.log"
grep "${TEST}" "${FDR_RESULT}" | head
## Bad Password

8 Combine multiple identifications

echo "Invoking the InterProphetParser to combine multiple identifications of the same peptide."
mkdir -p "results/iprophet_${VERSION}_${TYPE}"
echo "The input is: ${FDR_RESULT}"
echo "The output is: ${IPP_RESULT}"
InterProphetParser \
    "DECOY=${DECOY_STRING}" \
    "${FDR_RESULT}" \
    "${IPP_RESULT}" \
    2>"${IPP_RESULT}.log" 1>&2
tail "${IPP_RESULT}.log"
grep "${TEST}" "${IPP_RESULT}" | head
## Bad Password

9 Mayu

echo "Invoking mayu to standardize the fdr estimates."
mkdir -p "results/mayu_${VERSION}_${TYPE}"
echo "The input is: ${IPP_RESULT}"
Mayu.pl \
    -A "${IPP_RESULT}" \
    -C "${REFDB}" \
    -E "${DECOY_STRING}" \
    -G "${CONFIDENCE_CUTOFF}" \
    -H 101 \
    -I "${CLEAVAGES}" \
    2>"${MAYU_OUT}" 1>&2
head "${MAYU_OUT}"
## Did it work?
## I need to figure out how to include my generated decoys...
mkdir -p mayu
mayu_prefix=$(date +%Y-%m-%d)
mv "${mayu_prefix}"* results/mayu/
## Bad Password

10 Initial libraries spectrast

echo "Creating initial spectral libraries with spectrast."
echo "If a single input was given, make sure to link it to comet.mzXML."
mkdir -p results/spectral_libraries
rm -f "${SPECTRAL_BASENAME}*"
echo "The input is: ${SPECTRAL_BASENAME}"
echo "The output is: ${IPP_RESULT}"
spectrast \
    "-cN${SPECTRAL_BASENAME}" \
    "-cI${DDA_METHOD}" \
    -cf "Protein! ~ ${DECOY_STRING}" \
    "-cP${IPPP}" \
    -c_IRR \
    "${IPP_RESULT}" \
    2>>${IPP_RESULT}.log 1>&2
tail "${IPP_RESULT}.log"
grep "${TEST}" "${SPECTRAL_BASENAME}.sptxt" | head
## Bad Password

11 Initial consensus spectrast

echo "Making initial consensus libraries with spectrast."
echo "The input is: ${SPECTRAL_LIBRARY}"
echo "The output is: ${CONSENSUS}"
mkdir -p results/spectral_consensus
spectrast \
    "-cN${CONSENSUS}" \
    "-cI${DDA_METHOD}" \
    -cAC \
    "${SPECTRAL_LIBRARY}" \
    2>>"${CONSENSUS}.log" 1>&2
tail "${CONSENSUS}.log"
grep "${TEST}" "${CONSENSUS}.sptxt" | head
## Bad Password

12 Converting consensus libraries to tsv for later examination

echo "Make sure you have created an acquisition window file _without_ a header."
echo "There should be some which are just bob.txt in the windows/ directory."
echo "Writing spectrast tsv files with spectrast2tsv."
echo "Making a consensus library specific for ${MZ_WINDOWS} windows."
echo "The input is: ${CONSENSUS}.sptxt"
echo "The output is: ${CONSENSUS}_${MZ_WINDOWS}.tsv"
spectrast2tsv.py \
    -l 350,2000 \
    -s b,y \
    -x 1,2 \
    -o 4 \
    -n 6 \
    -p "${CONFIDENCE_CUTOFF}" \
    -d \
    -e \
    -w "windows/acquisition_${MZ_WINDOWS}.txt" \
    -k openswath \
    -a "${CONSENSUS}_${MZ_WINDOWS}.tsv" \
    "${CONSENSUS}.sptxt" \
    2>>"${CONSENSUS}_spectrast2tsv.log" 1>&2
tail "${CONSENSUS}_spectrast2tsv.log"
grep "${TEST}" "${CONSENSUS}_${MZ_WINDOWS}.tsv" | head
## Bad Password

13 Converting consensus libraries to TraML

echo "Converting spectral libraries to TraML."
rm -f "${CONSENSUS}_${MZ_WINDOWS}.TraML"
echo "The input is: ${CONSENSUS}_${MZ_WINDOWS}.tsv"
echo "The output is: ${CONSENSUS}_${MZ_WINDOWS}.TraML"
TargetedFileConverter \
    -in "${CONSENSUS}_${MZ_WINDOWS}.tsv" \
    -in_type tsv \
    -out "${CONSENSUS}_${MZ_WINDOWS}.TraML" \
    -out_type TraML
## Bad Password

14 Add decoys to the TraML

echo "Adding decoys and optimizing the spectral libraries."
rm -f "${CONSENSUS}_${MZ_WINDOWS}_decoy.TraML"
echo "Generating decoys for ${CONSENSUS}_${MZ_WINDOWS}"
echo "Optimizing the consensus library."
echo "The input is: ${CONSENSUS_TRAML}"
echo "The output is: ${OPTIMIZED_TRAML}"
OpenSwathAssayGenerator \
     -in "${CONSENSUS_TRAML}" \
     -out "${OPTIMIZED_TRAML}" \
     -swath_windows_file "windows/openswath_${MZ_WINDOWS}.txt" \
     -enable_ipf \
     -unimod_file "parameters/unimod.xml" \
     2>>"${OPTIMIZED_TRAML}.log" 1>&2
tail "${OPTIMIZED_TRAML}.log"

echo "Adding decoys."
echo "The input is: ${OPTIMIZED_TRAML}"
echo "The output is: ${DECOY_TRAML}"
OpenSwathDecoyGenerator \
    -in "${OPTIMIZED_TRAML}" \
    -out "${DECOY_TRAML}" \
    -decoy_tag "${DECOY_STRING}" \
    -method shuffle \
    2>>"${DECOY_TRAML}.log" 1>&2
tail "${DECOY_TRAML}.log"
grep "${TEST}" "${CONSENSUS}_${MZ_WINDOWS}_decoy.TraML" | head
## Bad Password

15 Convert back to tsv/pqp

echo "Converting decoy-added libraries back to tsv for examination later."
rm -f "${CONSENSUS}_${MZ_WINDOWS}_decoy.tsv"
echo "The input is: ${DECOY_TRAML}"
echo "The output is: ${TRANSITION_PREFIX}.tsv"
TargetedFileConverter \
    -in "${DECOY_TRAML}" \
    -in_type TraML \
    -out "${TRANSITION_PREFIX}.tsv" \
    -out_type tsv

echo "Converting libraries with decoys for ${TRANSITION_PREFIX} to pqp."
echo "The input is: ${DECOY_TRAML}"
echo "The output is: ${TRANSITION_PREFIX}.pqp"
TargetedFileConverter \
    -in "${TRANSITION_PREFIX}.tsv" \
    -in_type tsv \
    -out_type pqp \
    -out "${TRANSITION_PREFIX}.pqp"
echo "Transition library for openswathworkflow is: ${TRANSITION_PREFIX}.pqp"
grep "${TEST}" "${TRANSITION_PREFIX}.tsv" | head
grep -c "${DECOY_STRING}" "${TRANSITION_PREFIX}.tsv"
## Bad Password

16 OpenSwathWorkflow against our experimental transitions

echo "Invoking the OpenSwathWorkflow."
echo "Checking in, the transition library is: ${TRANSITION_PREFIX}.pqp"
swath_inputs=$(/bin/ls "mzXML/dia_${VERSION}")
echo "Checking in, the inputs are: ${SWATH_INPUTS}"
mkdir -p "${SWATH_OUTDIR}"
for input in ${swath_inputs}
do
    in_mzxml="mzXML/dia_${VERSION}/${input}"
    name=$(basename "${input}" .mzXML)
    echo "Starting openswath run of ${name} using ${MZ_WINDOWS} windows at $(date)."
    swath_output_prefix="${SWATH_OUTDIR}/${name}_vs_${VERSION}_${TYPE}_${DDA_METHOD}_dia"
    echo "Deleting previous swath output file: ${SWATH_OUTPUT_PREFIX}.osw"
    rm -f "${SWATH_OUTPUT_PREFIX}.osw"
    OpenSwathWorkflow \
        -ini "parameters/openms_${VERSION}.ini" \
        -in "${in_mzxml}" \
        -swath_windows_file "windows/openswath_${name}.txt" \
        -tr "${TRANSITON_PREFIX}.pqp" \
        -out_osw "${swath_output_prefix}.osw" \
        2>"${swath_output_prefix}_osw.log" 1>&2

    echo "Scoring individual swath run: ${swath_output_prefix}"
    pyprophet \
        score \
        --level ms1 \
        --in "${swath_output_prefix}.osw" \
        2>>"${swath_output_prefix}_pyprophet_ms1.log" 1>&2

    pyprophet \
        score \
        --level ms2 \
        --in "${swath_output_prefix}.osw" \
        --out "${swath_output_prefix}_scored.osw" \
        2>>"${swath_output_prefix}_pyprophet_ms2.log" 1>&2

    pyprophet \
        protein \
        --in "${swath_output_prefix}_scored.osw" \
        --context run-specific \
        2>>"${swath_output_prefix}_pyprophet_protein.log" 1>&2

    echo "Exporting individual swath run: to ${swath_output_prefix}.tsv"
    pyprophet \
        export \
        --in "${swath_output_prefix}_scored.osw" \
        --out "${swath_output_prefix}_scored.tsv" \
        2>>"${swath_output_prefix}_pyprophet_export.log" 1>&2
done
## Bad Password

17 OpenSwathWorkflow against our the Tuberculist transitions

echo "Invoking the OpenSwathWorkflow using the tuberculist transitions."
swath_inputs=$(/bin/ls "mzXML/dia_${VERSION}")
echo "Checking in, the inputs are: ${swath_inputs}"
mkdir -p "${TUBERCULIST_OUTDIR}"
for input in ${swath_inputs}
do
    in_mzxml="mzXML/dia_${VERSION}/${input}"
    name=$(basename "${input}" .mzXML)
    echo "Starting openswath run of ${name} using ${MZ_WINDOWS} windows at $(date)."
    tb_output_prefix="${TUBERCULIST_OUTDIR}/${name}_vs_${VERSION}_${TYPE}_${DDA_METHOD}_dia"
    echo "Deleting previous swath output file: ${tb_output_prefix}.osw"
    rm -f "${tb_output_prefix}.osw"
    OpenSwathWorkflow \
        -ini "parameters/openms_${VERSION}.ini" \
        -in "${in_mzxml}" \
        -swath_windows_file "windows/openswath_${name}.txt" \
        -tr "${TUBERCULIST_PQP}" \
        -out_osw "${tb_output_prefix}.osw" \
        2>"${tb_output_prefix}_osw.log" 1>&2

    echo "Scoring individual swath run: ${tb_output_prefix}"
    pyprophet \
        score \
        --level ms1 \
        --in "${tb_output_prefix}.osw" \
        2>>"${tb_output_prefix}_pyprophet_ms1.log" 1>&2

    pyprophet \
        score \
        --level ms2 \
        --in "${tb_output_prefix}.osw" \
        --out "${tb_output_prefix}_scored.osw" \
        2>>"${tb_output_prefix}_pyprophet_ms2.log" 1>&2

    pyprophet \
        protein \
        --in "${tb_output_prefix}_scored.osw" \
        --context run-specific \
        2>>"${tb_output_prefix}_pyprophet_protein.log" 1>&2

    echo "Exporting individual swath run: to ${tb_output_prefix}.tsv"
    pyprophet \
        export \
        --in "${tb_output_prefix}_scored.osw" \
        --out "${tb_output_prefix}_scored.tsv" \
        2>>"${tb_output_prefix}_pyprophet_export.log" 1>&2
done
## Bad Password

18 Merging our data with TRIC

feature_alignment.py \
    --force \
    --in "./${SWATH_OUTDIR}/"*.tsv \
    --out "${TRIC_OUTDIR}/${SEARCH_METHOD}_${DDA_METHOD}.tsv" \
    --out_matrix "${TRIC_OUTDIR}/${DDA_METHOD}_outmatrix.tsv" \
    --out_meta "${TRIC_OUTDIR}/${DDA_METHOD}_meta.tsv"
echo "Wrote final output to ${TRIC_OUTDIR}/${SEARCH_METHOD}_${DDA_METHOD}.tsv"
## Bad Password

19 Merging the Tuberculist-derived data with TRIC

tric_tb="${TRIC_OUTDIR}_tb"
feature_alignment.py \
    --force \
    --in "./${SWATH_OUTDIR}/"*.tsv \
    --out "${tric_tb}/${SEARCH_METHOD}_${DDA_METHOD}.tsv" \
    --out_matrix "${tric_tb}/${DDA_METHOD}_outmatrix.tsv" \
    --out_meta "${tric_tb}/${DDA_METHOD}_meta.tsv"
echo "Wrote final output to ${tric_tb}/${SEARCH_METHOD}_${DDA_METHOD}.tsv"
## Bad Password

20 Index version: 20180215

21 TODO

  • 2017-06-14:
if (!isTRUE(get0("skip_load"))) {
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
  message(paste0("Saving to ", this_save))
  tmp <- sm(saveme(filename=this_save))
  pander::pander(sessionInfo())
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 4523f8cfb1df75584e2257a89e1810ee13c56a67
## R> packrat::restore()
## This is hpgltools commit: Tue May 29 16:09:33 2018 -0400: 4523f8cfb1df75584e2257a89e1810ee13c56a67
## Saving to 01_preprocessing_comet_20180508-v20180215.rda.xz

R version 3.3.1 (2016-06-21)

Platform: x86_64-pc-linux-gnu (64-bit)

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

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

other attached packages: runr(v.0.0.8) and hpgltools(v.2017.10)

loaded via a namespace (and not attached): Rcpp(v.0.12.15), knitr(v.1.20), magrittr(v.1.5), BiocGenerics(v.0.20.0), munsell(v.0.4.3), colorspace(v.1.3-2), foreach(v.1.4.3), highr(v.0.6), stringr(v.1.2.0), plyr(v.1.8.4), tools(v.3.3.1), parallel(v.3.3.1), grid(v.3.3.1), Biobase(v.2.34.0), data.table(v.1.10.4), gtable(v.0.2.0), htmltools(v.0.3.5), iterators(v.1.0.8), lazyeval(v.0.2.0), yaml(v.2.1.14), rprojroot(v.1.2), digest(v.0.6.12), tibble(v.1.3.0), ggplot2(v.2.2.1), base64enc(v.0.1-3), codetools(v.0.2-14), evaluate(v.0.10), rmarkdown(v.1.9), openxlsx(v.4.0.17), stringi(v.1.1.3), pander(v.0.6.0), scales(v.0.4.1) and backports(v.1.0.5)

b$stop()
LS0tCnRpdGxlOiAiTS50dWJlcmN1bG9zaXMgMjAxODA1MzA6IFByZXByb2Nlc3NpbmcgRElBIGRhdGEgd2l0aCBhIGNvbWV0IGhpZ2hyZXMgbGlicmFyeSAobW9yZSBzYW1wbGVzKS4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgbGlicmFyeShocGdsdG9vbHMpCiAgbGlicmFyeShydW5yKQogIGIgPC0gcHJvY19iYXNoKHBvcnQ9MjAwMCkKICBzdGFydGVkIDwtIGIkc3RhcnQoKQogIGtuaXRyOjprbml0X2VuZ2luZXMkc2V0KGJhc2hfcnVucj1mdW5jdGlvbihvcHRpb25zKSB7CiAgICBrbml0cjo6OndyYXAoYiRleGVjKG9wdGlvbnMkY29kZSksIG9wdGlvbnMpCiAgfSkKICAjI3R0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQogIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwLAogICAgICAgICAgICAgICAgICAgICAgIGVjaG89VFJVRSkKICBrbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3I9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQ9OCwKICAgICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQogIG9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzPTQsCiAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCiAgZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCiAgdmVyIDwtICIyMDE4MDIxNSIKICBwcmV2aW91c19maWxlIDwtICIwMV9hbm5vdGF0aW9uLlJtZCIKCiAgIyN0bXAgPC0gdHJ5KHNtKGxvYWRtZShmaWxlbmFtZT1wYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXByZXZpb3VzX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikpKSkKICBybWRfZmlsZSA8LSAiMDFfcHJlcHJvY2Vzc2luZ19jb21ldF8yMDE4MDUwOC5SbWQiCn0KYGBgCgpQcmVwcm9jZXNzaW5nIERJQSBkYXRhIHZpYSB0aGUgaW5zdHJ1Y3Rpb25zIGF0OiBodHRwOi8vZGlhLXN3YXRoLWNvdXJzZS5ldGh6LmNoL3R1dG9yaWFsczIwMTcvCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMgR2VuZXJhdGluZyBhIGhpZ2gtcmVzIChIQ0QpIHNwZWN0cmFsIHNlYXJjaCBsaWJyYXJ5LgoKIyMgUmVhZGluZyBtZXRhZGF0YQoKSW4gdGhlb3J5LCBJIGhhdmUgZmlndXJlZCBvdXQgaG93IHRvIHJlbmRlciBhIG1peCBvZiBiYXNoIGFuZCByIGluIG11bHRpcGxlIGJsb2Nrcy4KVGhpcyB3b3Jrc2hlZXQgd2lsbCB0ZXN0IHRoYXQgdGhlb3J5IGJ5IGNvcHkvcGFzdGluZyBvdXQgdGhlIHZhcmlvdXMgc2VjdGlvbnMgb2YgYmFzaApyZXF1aXJlZCB0byBkbyB0aGUgcHJvY2Vzc2luZyBvZiB0aGlzIGRhdGEgaW50byBibG9ja3MgbGFiZWxlZCAnYmFzaF9ydW5yJy4KCklmIEkgYW0gY29ycmVjdCwgd2Ugd2lsbCBiZSBhYmxlIHRoZW4gdG8gdGVzdCBhbmQgcmVuZGVyIGVhY2ggcGllY2Ugb2YgdGhpcwpwcm9jZXNzIHdpdGhvdXQgaGF2aW5nIHRvIHJ1biB0aGUgZW50aXJlIHRoaW5nIGFzIGEgYmFzaCBzY3JpcHQgYXQgdGhlIGVuZC4KClRoZSBvcmlnaW5hbCBzY3JpcHQgd2hpY2ggcHJvdmlkZXMgdGhlIG1lYXQgb2YgdGhpcyBkb2N1bWVudCBpcyBzdGlsbCBoZXJlIGluCmNhc2UgdGhpcyBmYWlscyBhcyBkaWFfaW52b2NhdGlvbl9oY2RfMjAxODA1MzAuc2guCgpgYGB7ciBteV9kZGFfbWV0cmljc30Kc2FtcGxlX3NoZWV0IDwtICJzYW1wbGVfc2hlZXRzL2RkYV9zYW1wbGVzLnhsc3giCnNhdmVmaWxlIDwtICJtenhtbF9kZGFfZGF0YV8yMDE4MDUucmRhIgoKbWV0YWRhdGEgPC0gb3Blbnhsc3g6OnJlYWQueGxzeChzYW1wbGVfc2hlZXQpCmtlZXBlcl9pZHggPC0gbWV0YWRhdGFbWyJzYW1wbGVkYXRlIl1dID09ICIyMDE4MDQyMCIKbWV0YWRhdGEgPC0gbWV0YWRhdGFba2VlcGVyX2lkeCwgXQoKa25pdHI6OmthYmxlKG1ldGFkYXRhKQpgYGAKCiMjIEdhdGhlciBkYXRhIGFuZCBwbG90IG1ldHJpY3MKCmBgYHtyIGRkYV9wbG90cywgZXZhbD1GQUxTRX0KaWYgKGZpbGUuZXhpc3RzKHNhdmVmaWxlKSkgewogIGxvYWQoc2F2ZWZpbGUpCn0gZWxzZSB7CiAgbXp4bWxfZGF0YSA8LSBzbShleHRyYWN0X216eG1sX2RhdGEobWV0YWRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW49Im16eG1sZmlsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZWZpbGU9c2F2ZWZpbGUpKQp9CgppbnRlbnNpdHlfYm94cGxvdCA8LSBzbShwbG90X216eG1sX2JveHBsb3QobXp4bWxfZGF0YSkpCnBwKGZpbGU9ImltYWdlcy9tenhtbF9pbnRlbnNpdGllcy5wbmciLCBpbWFnZT1pbnRlbnNpdHlfYm94cGxvdCkKCnJldGVudGlvbl9ib3hwbG90IDwtIHNtKHBsb3RfbXp4bWxfYm94cGxvdChtenhtbF9kYXRhLCB0YWJsZT0ic2NhbnMiLCBjb2x1bW49InBlYWtzY291bnQiKSkKcHAoZmlsZT0iaW1hZ2VzL216eG1sX3JldGVudGlvbi5wbmciLCBpbWFnZT1yZXRlbnRpb25fYm94cGxvdCkKCm16X2JveHBsb3QgPC0gc20ocGxvdF9tenhtbF9ib3hwbG90KG16eG1sX2RhdGEsIHRhYmxlPSJzY2FucyIsIGNvbHVtbj0iYmFzZXBlYWtteiIpKQpwcChmaWxlPSJpbWFnZXMvbXp4bWxfbXpiYXNlLnBuZyIsIGltYWdlPW16X2JveHBsb3QpCgpzY2FuaW50ZW5zaXR5X2JveHBsb3QgPC0gc20ocGxvdF9tenhtbF9ib3hwbG90KG16eG1sX2RhdGEsIHRhYmxlPSJzY2FucyIsIGNvbHVtbj0iYmFzZXBlYWtpbnRlbnNpdHkiKSkKcHAoZmlsZT0iaW1hZ2VzL216eG1sX3NjYW5pbnRlbnNpdHkucG5nIiwgaW1hZ2U9c2NhbmludGVuc2l0eV9ib3hwbG90KQoKaW50ZW5zaXR5X3dydF9teiA8LSBzbShwbG90X2ludGVuc2l0eV9teihtenhtbF9kYXRhLCB4X3NjYWxlPSJsb2ciLCB5X3NjYWxlPSJsb2ciKSkKcHAoZmlsZT0iaW1hZ2VzL2ludGVuc2l0eV93cnRfbXpfZGlhLnBuZyIsIGltYWdlPWludGVuc2l0eV93cnRfbXokcGxvdCkKYGBgCgojIEdldCBESUEgbWV0cmljcwoKRG8gbm90IGZvcmdldCB0aGF0IGV4dHJhY3RfbXp4bWxfZGF0YSgpIHdyaXRlcyB0aGUgYWNxdWlzaXRpb24gd2luZG93IGZpbGVzCnJlcXVpcmVkIGZvciBvcGVuc3dhdGh3b3JrZmxvdyB0byBydW4sIHNvIGRvIG5vdCBmb3JnZXQgdG8gcnVuIGl0LgoKIyMgUmVhZCBkaWEgbWV0YWRhdGEKCmBgYHtyIGRpYV9tZXRyaWNzLCBldmFsPUZBTFNFfQpzYW1wbGVfc2hlZXQgPC0gInNhbXBsZV9zaGVldHMvTXRiX2RpYV9zYW1wbGVzLnhsc3giCnNhdmVmaWxlIDwtICJtenhtbF9kaWFfZGF0YV8yMDE4MDUucmRhIgoKbWV0YWRhdGEgPC0gb3Blbnhsc3g6OnJlYWQueGxzeChzYW1wbGVfc2hlZXQpCmtlZXBlcl9pZHggPC0gbWV0YWRhdGFbWyJleHB0X2lkIl1dID09ICJtYXkyMDE4IgprZWVwZXJfaWR4W2lzLm5hKGtlZXBlcl9pZHgpXSA8LSBGQUxTRQptZXRhZGF0YSA8LSBtZXRhZGF0YVtrZWVwZXJfaWR4LCBdCmtuaXRyOjprYWJsZShtZXRhZGF0YSkKYGBgCgojIyBQbG90IGRpYSBtZXRyaWNzCgpOb3cgbGV0IHVzIHBsb3QgdGhlIGRpYSBzYW1wbGUgZGF0YS4KCmBgYHtyIGRpYV9wbG90cywgZXZhbD1GQUxTRX0KaWYgKGZpbGUuZXhpc3RzKHNhdmVmaWxlKSkgewogIGxvYWQoc2F2ZWZpbGUpCn0gZWxzZSB7CiAgbXp4bWxfZGF0YSA8LSBzbShleHRyYWN0X216eG1sX2RhdGEobWV0YWRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW49IkZpbGVuYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXZlZmlsZT1zYXZlZmlsZSkpCn0KCmludGVuc2l0eV9ib3hwbG90IDwtIHBsb3RfbXp4bWxfYm94cGxvdChtenhtbF9kYXRhKQpwcChmaWxlPSJpbWFnZXMvMjAxODA1X2RpYV9tenhtbF9pbnRlbnNpdGllcy5wbmciLCBpbWFnZT1pbnRlbnNpdHlfYm94cGxvdCkKCnJldGVudGlvbl9ib3hwbG90IDwtIHBsb3RfbXp4bWxfYm94cGxvdChtenhtbF9kYXRhLCB0YWJsZT0ic2NhbnMiLCBjb2x1bW49InBlYWtzY291bnQiKQpwcChmaWxlPSJpbWFnZXMvMjAxODA1X2RpYV9tenhtbF9yZXRlbnRpb24ucG5nIiwgaW1hZ2U9cmV0ZW50aW9uX2JveHBsb3QpCgptel9ib3hwbG90IDwtIHBsb3RfbXp4bWxfYm94cGxvdChtenhtbF9kYXRhLCB0YWJsZT0ic2NhbnMiLCBjb2x1bW49ImJhc2VwZWFrbXoiKQpwcChmaWxlPSJpbWFnZXMvMjAxODA1X2RpYV9tenhtbF9temJhc2UucG5nIiwgaW1hZ2U9bXpfYm94cGxvdCkKCnNjYW5pbnRlbnNpdHlfYm94cGxvdCA8LSBwbG90X216eG1sX2JveHBsb3QobXp4bWxfZGF0YSwgdGFibGU9InNjYW5zIiwgY29sdW1uPSJiYXNlcGVha2ludGVuc2l0eSIpCnBwKGZpbGU9ImltYWdlcy8yMDE4MDVfZGlhX216eG1sX3NjYW5pbnRlbnNpdHkucG5nIiwgaW1hZ2U9c2NhbmludGVuc2l0eV9ib3hwbG90KQoKaW50ZW5zaXR5X3dydF9teiA8LSBwbG90X2ludGVuc2l0eV9teihtenhtbF9kYXRhLCB4X3NjYWxlPSJsb2ciLCB5X3NjYWxlPSJsb2ciKQpwcChmaWxlPSJpbWFnZXMvMjAxODA1X2RpYV9pbnRlbnNpdHlfd3J0X216X2RpYS5wbmciLCBpbWFnZT1pbnRlbnNpdHlfd3J0X216KQpgYGAKCiMgR2F0aGVyaW5nIHBhcmFtZXRlcnMKCkluIHRoaXMgZmlyc3QgYmxvY2ssIEkgd2lsbCBzZXQgYSBjb3VwbGUgb2YgdmFyaWFibGVzIGFuZCBzb3VyY2UgYSBmaWxlCmNvbnRhaW5pbmcgdGhlIHBhcmFtZXRlcnMgZm9yIHRoZSByZXN0IG9mIHRoZSBzY3JpcHQuCgpgYGB7YmFzaF9ydW5yIHBhcmFtZXRlcnN9CmxzIHBhcmFtZXRlcnMKZXhwb3J0IFZFUlNJT049IjIwMTgwNTMwIgpzb3VyY2UgcGFyYW1ldGVycy8yMDE4MDUzMF9zZXR0aW5ncy5zaAplY2hvICJWZXJzaW9uIGlzOiAke1ZFUlNJT059IgpgYGAKCmBgYHtyIHNsZWVwMSwgaW5jbHVkZT1GQUxTRX0KU3lzLnNsZWVwKDEpCmBgYAoKIyMgVGVzdCB0aGF0IHdlIGhhdmUgdGhlIHJlcXVpcmVkIHZhcmlhYmxlcyBmb3IgdGhlIHJlc3Qgb2YgdGhlIHNjcmlwdC4KCmBgYHtiYXNoX3J1bnIgdGVzdF9wYXJhbXN9CmVudiB8IGdyZXAgJHtWRVJTSU9OfQoKIyNjZCAiJHtTVEFSVH0iCmVjaG8gJFNUQVJUCmBgYAoKYGBge3Igc2xlZXAyLCBpbmNsdWRlPUZBTFNFfQpTeXMuc2xlZXAoMSkKYGBgCgojIFJ1biBjb21ldCBvbiBvdXIgRERBIGRhdGEKCmBgYHtiYXNoX3J1bnIgY29tZXR9CmVjaG8gIlN0YXJ0aW5nIHJ1biBvZiBjb21ldCB1c2luZyB0aGUgY29uZmlndXJhdGlvbiBmaWxlOgpjb21ldC9jb21ldF8ke0REQV9NRVRIT0R9X3BhcmFtcy50eHQgYWdhaW5zdCAke0REQV9JTlBVVFN9LiIKZm9yIGNvbWV0X2lucHV0IGluICR7RERBX0lOUFVUU30KZG8KICAgIGVjaG8gIlRoZSBpbnB1dCBpczogJHtjb21ldF9pbnB1dH0iCiAgICAvY2JjYi9zdy9SZWRIYXQtNy14ODZfNjQvY29tbW9uL2xvY2FsL3RwcC81LjEuMC9iaW4vY29tZXQgXAogICAgICAgICItUGNvbWV0L2NvbWV0XyR7RERBX01FVEhPRH1fcGFyYW1zLnR4dCIgXAogICAgICAgICIke2NvbWV0X2lucHV0fSIgXAogICAgICAgIDI+PiJjb21ldC9jb21ldF8ke1ZFUlNJT059LmxvZyIgMT4mMgpkb25lCnRhaWwgImNvbWV0L2NvbWV0XyR7VkVSU0lPTn0ubG9nIgpgYGAKCmBgYHtyIHNsZWVwMywgaW5jbHVkZT1GQUxTRX0KU3lzLnNsZWVwKDEpCmBgYAoKIyBSZWZyZXNoIHRoZSBjb21ldCByZXN1bHRzCgpDb21ldCBkb2VzIG5vdCBwcm92aWRlIHRoZSBhbHRlcm5hdGUgaGl0cywgdGhlIGZvbGxvd2luZyBzaG91bGQgYWRkIHRoZW0gaW50bwp0aGUgY29tZXQgb3V0cHV0IGZpbGVzLgoKYGBge2Jhc2hfcnVuciBjb21ldF9yZWZyZXNofQplY2hvICJTdGFydGluZyByZWZyZXNocGFyc2VyIHRvIGhvcGVmdWxseSBhZGQgYmFjayB0aGUgYWx0ZXJuYXRlIG1hdGNoZXMgZHJvcHBlZCBieSBjb21ldC4iCmZvciByZWZyZXNoX2lucHV0IGluICR7UEVQWE1MX0lOUFVUU30KZG8KICAgIGVjaG8gIlRoZSBpbnB1dCBpczogJHtyZWZyZXNoX2lucHV0fS4iCiAgICBSZWZyZXNoUGFyc2VyIFwKICAgICAgICAiJHtyZWZyZXNoX2lucHV0fSIgXAogICAgICAgICIke1JFRkRCfSIgXAogICAgICAgIDI+PiR7cmVmcmVzaF9pbnB1dH0ubG9nIDE+JjIKZG9uZQpgYGAKCmBgYHtyIHNsZWVwNCwgaW5jbHVkZT1GQUxTRX0KU3lzLnNsZWVwKDEpCmBgYAoKIyBNZXJnZSBzZWFyY2hlcwoKYGBge2Jhc2hfcnVuciB4aW50ZXJhY3RfbWVyZ2V9CmVjaG8gIkludm9raW5nIHhpbnRlcmFjdCB0byBtZXJnZSBzZWFyY2hlcywgc2V0IGRlY295cywgYW5kIHNldCB1cCBmZHIuIgpta2RpciAtcCAicmVzdWx0cy9mZHJfY29udHJvbGxlZF8ke1ZFUlNJT059XyR7VFlQRX0iCmVjaG8gIlRoZSBpbnB1dCBpczogJHtQRVBYTUxfSU5QVVRTfSIKZWNobyAiVGhlIG91dHB1dCBpczogJHtGRFJfUkVTVUxUfSIKeGludGVyYWN0IFwKICAgICItZCR7REVDT1lfU1RSSU5HfSIgXAogICAgLU9BUlBwZCBcCiAgICAtT3cgXAogICAgIi1OJHtGRFJfUkVTVUxUfSIgXAogICAgIm16WE1ML2RkYV8ke1ZFUlNJT059XyR7VFlQRX0iLyoucGVwLnhtbCBcCiAgICAyPj4iJHtGRFJfUkVTVUxUfS5sb2ciIDE+JjIKdGFpbCAiJHtGRFJfUkVTVUxUfS5sb2ciCmdyZXAgIiR7VEVTVH0iICIke0ZEUl9SRVNVTFR9IiB8IGhlYWQKYGBgCgpgYGB7ciBzbGVlcDUsIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgQ29tYmluZSBtdWx0aXBsZSBpZGVudGlmaWNhdGlvbnMKCmBgYHtiYXNoX3J1bnIgaW50ZXJwcm9waGV0fQplY2hvICJJbnZva2luZyB0aGUgSW50ZXJQcm9waGV0UGFyc2VyIHRvIGNvbWJpbmUgbXVsdGlwbGUgaWRlbnRpZmljYXRpb25zIG9mIHRoZSBzYW1lIHBlcHRpZGUuIgpta2RpciAtcCAicmVzdWx0cy9pcHJvcGhldF8ke1ZFUlNJT059XyR7VFlQRX0iCmVjaG8gIlRoZSBpbnB1dCBpczogJHtGRFJfUkVTVUxUfSIKZWNobyAiVGhlIG91dHB1dCBpczogJHtJUFBfUkVTVUxUfSIKSW50ZXJQcm9waGV0UGFyc2VyIFwKICAgICJERUNPWT0ke0RFQ09ZX1NUUklOR30iIFwKICAgICIke0ZEUl9SRVNVTFR9IiBcCiAgICAiJHtJUFBfUkVTVUxUfSIgXAogICAgMj4iJHtJUFBfUkVTVUxUfS5sb2ciIDE+JjIKdGFpbCAiJHtJUFBfUkVTVUxUfS5sb2ciCmdyZXAgIiR7VEVTVH0iICIke0lQUF9SRVNVTFR9IiB8IGhlYWQKYGBgCgpgYGB7ciBzbGVlcDYsIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgTWF5dQoKYGBge2Jhc2hfcnVuciBtYXl1fQplY2hvICJJbnZva2luZyBtYXl1IHRvIHN0YW5kYXJkaXplIHRoZSBmZHIgZXN0aW1hdGVzLiIKbWtkaXIgLXAgInJlc3VsdHMvbWF5dV8ke1ZFUlNJT059XyR7VFlQRX0iCmVjaG8gIlRoZSBpbnB1dCBpczogJHtJUFBfUkVTVUxUfSIKTWF5dS5wbCBcCiAgICAtQSAiJHtJUFBfUkVTVUxUfSIgXAogICAgLUMgIiR7UkVGREJ9IiBcCiAgICAtRSAiJHtERUNPWV9TVFJJTkd9IiBcCiAgICAtRyAiJHtDT05GSURFTkNFX0NVVE9GRn0iIFwKICAgIC1IIDEwMSBcCiAgICAtSSAiJHtDTEVBVkFHRVN9IiBcCiAgICAyPiIke01BWVVfT1VUfSIgMT4mMgpoZWFkICIke01BWVVfT1VUfSIKIyMgRGlkIGl0IHdvcms/CiMjIEkgbmVlZCB0byBmaWd1cmUgb3V0IGhvdyB0byBpbmNsdWRlIG15IGdlbmVyYXRlZCBkZWNveXMuLi4KbWtkaXIgLXAgbWF5dQptYXl1X3ByZWZpeD0kKGRhdGUgKyVZLSVtLSVkKQptdiAiJHttYXl1X3ByZWZpeH0iKiByZXN1bHRzL21heXUvCmBgYAoKYGBge3Igc2xlZXA3LCBpbmNsdWRlPUZBTFNFfQpTeXMuc2xlZXAoMSkKYGBgCgojIEluaXRpYWwgbGlicmFyaWVzIHNwZWN0cmFzdAoKYGBge2Jhc2hfcnVuciBzcGVjdHJhc3QxfQplY2hvICJDcmVhdGluZyBpbml0aWFsIHNwZWN0cmFsIGxpYnJhcmllcyB3aXRoIHNwZWN0cmFzdC4iCmVjaG8gIklmIGEgc2luZ2xlIGlucHV0IHdhcyBnaXZlbiwgbWFrZSBzdXJlIHRvIGxpbmsgaXQgdG8gY29tZXQubXpYTUwuIgpta2RpciAtcCByZXN1bHRzL3NwZWN0cmFsX2xpYnJhcmllcwpybSAtZiAiJHtTUEVDVFJBTF9CQVNFTkFNRX0qIgplY2hvICJUaGUgaW5wdXQgaXM6ICR7U1BFQ1RSQUxfQkFTRU5BTUV9IgplY2hvICJUaGUgb3V0cHV0IGlzOiAke0lQUF9SRVNVTFR9IgpzcGVjdHJhc3QgXAogICAgIi1jTiR7U1BFQ1RSQUxfQkFTRU5BTUV9IiBcCiAgICAiLWNJJHtEREFfTUVUSE9EfSIgXAogICAgLWNmICJQcm90ZWluISB+ICR7REVDT1lfU1RSSU5HfSIgXAogICAgIi1jUCR7SVBQUH0iIFwKICAgIC1jX0lSUiBcCiAgICAiJHtJUFBfUkVTVUxUfSIgXAogICAgMj4+JHtJUFBfUkVTVUxUfS5sb2cgMT4mMgp0YWlsICIke0lQUF9SRVNVTFR9LmxvZyIKZ3JlcCAiJHtURVNUfSIgIiR7U1BFQ1RSQUxfQkFTRU5BTUV9LnNwdHh0IiB8IGhlYWQKYGBgCgpgYGB7ciBzbGVlcDgsIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgSW5pdGlhbCBjb25zZW5zdXMgc3BlY3RyYXN0CgpgYGB7YmFzaF9ydW5yIHNwZWN0cmFzdDJ9CmVjaG8gIk1ha2luZyBpbml0aWFsIGNvbnNlbnN1cyBsaWJyYXJpZXMgd2l0aCBzcGVjdHJhc3QuIgplY2hvICJUaGUgaW5wdXQgaXM6ICR7U1BFQ1RSQUxfTElCUkFSWX0iCmVjaG8gIlRoZSBvdXRwdXQgaXM6ICR7Q09OU0VOU1VTfSIKbWtkaXIgLXAgcmVzdWx0cy9zcGVjdHJhbF9jb25zZW5zdXMKc3BlY3RyYXN0IFwKICAgICItY04ke0NPTlNFTlNVU30iIFwKICAgICItY0kke0REQV9NRVRIT0R9IiBcCiAgICAtY0FDIFwKICAgICIke1NQRUNUUkFMX0xJQlJBUll9IiBcCiAgICAyPj4iJHtDT05TRU5TVVN9LmxvZyIgMT4mMgp0YWlsICIke0NPTlNFTlNVU30ubG9nIgpncmVwICIke1RFU1R9IiAiJHtDT05TRU5TVVN9LnNwdHh0IiB8IGhlYWQKYGBgCgpgYGB7ciBzbGVlcDksIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgQ29udmVydGluZyBjb25zZW5zdXMgbGlicmFyaWVzIHRvIHRzdiBmb3IgbGF0ZXIgZXhhbWluYXRpb24KCmBgYHtiYXNoX3J1bnIgc3BlY3RyYXN0MnRzdn0KZWNobyAiTWFrZSBzdXJlIHlvdSBoYXZlIGNyZWF0ZWQgYW4gYWNxdWlzaXRpb24gd2luZG93IGZpbGUgX3dpdGhvdXRfIGEgaGVhZGVyLiIKZWNobyAiVGhlcmUgc2hvdWxkIGJlIHNvbWUgd2hpY2ggYXJlIGp1c3QgYm9iLnR4dCBpbiB0aGUgd2luZG93cy8gZGlyZWN0b3J5LiIKZWNobyAiV3JpdGluZyBzcGVjdHJhc3QgdHN2IGZpbGVzIHdpdGggc3BlY3RyYXN0MnRzdi4iCmVjaG8gIk1ha2luZyBhIGNvbnNlbnN1cyBsaWJyYXJ5IHNwZWNpZmljIGZvciAke01aX1dJTkRPV1N9IHdpbmRvd3MuIgplY2hvICJUaGUgaW5wdXQgaXM6ICR7Q09OU0VOU1VTfS5zcHR4dCIKZWNobyAiVGhlIG91dHB1dCBpczogJHtDT05TRU5TVVN9XyR7TVpfV0lORE9XU30udHN2IgpzcGVjdHJhc3QydHN2LnB5IFwKICAgIC1sIDM1MCwyMDAwIFwKICAgIC1zIGIseSBcCiAgICAteCAxLDIgXAogICAgLW8gNCBcCiAgICAtbiA2IFwKICAgIC1wICIke0NPTkZJREVOQ0VfQ1VUT0ZGfSIgXAogICAgLWQgXAogICAgLWUgXAogICAgLXcgIndpbmRvd3MvYWNxdWlzaXRpb25fJHtNWl9XSU5ET1dTfS50eHQiIFwKICAgIC1rIG9wZW5zd2F0aCBcCiAgICAtYSAiJHtDT05TRU5TVVN9XyR7TVpfV0lORE9XU30udHN2IiBcCiAgICAiJHtDT05TRU5TVVN9LnNwdHh0IiBcCiAgICAyPj4iJHtDT05TRU5TVVN9X3NwZWN0cmFzdDJ0c3YubG9nIiAxPiYyCnRhaWwgIiR7Q09OU0VOU1VTfV9zcGVjdHJhc3QydHN2LmxvZyIKZ3JlcCAiJHtURVNUfSIgIiR7Q09OU0VOU1VTfV8ke01aX1dJTkRPV1N9LnRzdiIgfCBoZWFkCmBgYAoKYGBge3Igc2xlZXAxMCwgaW5jbHVkZT1GQUxTRX0KU3lzLnNsZWVwKDEpCmBgYAoKIyBDb252ZXJ0aW5nIGNvbnNlbnN1cyBsaWJyYXJpZXMgdG8gVHJhTUwKCmBgYHtiYXNoX3J1bnIgdG90cmFtbH0KZWNobyAiQ29udmVydGluZyBzcGVjdHJhbCBsaWJyYXJpZXMgdG8gVHJhTUwuIgpybSAtZiAiJHtDT05TRU5TVVN9XyR7TVpfV0lORE9XU30uVHJhTUwiCmVjaG8gIlRoZSBpbnB1dCBpczogJHtDT05TRU5TVVN9XyR7TVpfV0lORE9XU30udHN2IgplY2hvICJUaGUgb3V0cHV0IGlzOiAke0NPTlNFTlNVU31fJHtNWl9XSU5ET1dTfS5UcmFNTCIKVGFyZ2V0ZWRGaWxlQ29udmVydGVyIFwKICAgIC1pbiAiJHtDT05TRU5TVVN9XyR7TVpfV0lORE9XU30udHN2IiBcCiAgICAtaW5fdHlwZSB0c3YgXAogICAgLW91dCAiJHtDT05TRU5TVVN9XyR7TVpfV0lORE9XU30uVHJhTUwiIFwKICAgIC1vdXRfdHlwZSBUcmFNTApgYGAKCmBgYHtyIHNsZWVwMTEsIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgQWRkIGRlY295cyB0byB0aGUgVHJhTUwKCmBgYHtiYXNoX3J1bnIgZGVjb3lfdHJhbWx9CmVjaG8gIkFkZGluZyBkZWNveXMgYW5kIG9wdGltaXppbmcgdGhlIHNwZWN0cmFsIGxpYnJhcmllcy4iCnJtIC1mICIke0NPTlNFTlNVU31fJHtNWl9XSU5ET1dTfV9kZWNveS5UcmFNTCIKZWNobyAiR2VuZXJhdGluZyBkZWNveXMgZm9yICR7Q09OU0VOU1VTfV8ke01aX1dJTkRPV1N9IgplY2hvICJPcHRpbWl6aW5nIHRoZSBjb25zZW5zdXMgbGlicmFyeS4iCmVjaG8gIlRoZSBpbnB1dCBpczogJHtDT05TRU5TVVNfVFJBTUx9IgplY2hvICJUaGUgb3V0cHV0IGlzOiAke09QVElNSVpFRF9UUkFNTH0iCk9wZW5Td2F0aEFzc2F5R2VuZXJhdG9yIFwKICAgICAtaW4gIiR7Q09OU0VOU1VTX1RSQU1MfSIgXAogICAgIC1vdXQgIiR7T1BUSU1JWkVEX1RSQU1MfSIgXAogICAgIC1zd2F0aF93aW5kb3dzX2ZpbGUgIndpbmRvd3Mvb3BlbnN3YXRoXyR7TVpfV0lORE9XU30udHh0IiBcCiAgICAgLWVuYWJsZV9pcGYgXAogICAgIC11bmltb2RfZmlsZSAicGFyYW1ldGVycy91bmltb2QueG1sIiBcCiAgICAgMj4+IiR7T1BUSU1JWkVEX1RSQU1MfS5sb2ciIDE+JjIKdGFpbCAiJHtPUFRJTUlaRURfVFJBTUx9LmxvZyIKCmVjaG8gIkFkZGluZyBkZWNveXMuIgplY2hvICJUaGUgaW5wdXQgaXM6ICR7T1BUSU1JWkVEX1RSQU1MfSIKZWNobyAiVGhlIG91dHB1dCBpczogJHtERUNPWV9UUkFNTH0iCk9wZW5Td2F0aERlY295R2VuZXJhdG9yIFwKICAgIC1pbiAiJHtPUFRJTUlaRURfVFJBTUx9IiBcCiAgICAtb3V0ICIke0RFQ09ZX1RSQU1MfSIgXAogICAgLWRlY295X3RhZyAiJHtERUNPWV9TVFJJTkd9IiBcCiAgICAtbWV0aG9kIHNodWZmbGUgXAogICAgMj4+IiR7REVDT1lfVFJBTUx9LmxvZyIgMT4mMgp0YWlsICIke0RFQ09ZX1RSQU1MfS5sb2ciCmdyZXAgIiR7VEVTVH0iICIke0NPTlNFTlNVU31fJHtNWl9XSU5ET1dTfV9kZWNveS5UcmFNTCIgfCBoZWFkCmBgYAoKYGBge3Igc2xlZXAxMiwgaW5jbHVkZT1GQUxTRX0KU3lzLnNsZWVwKDEpCmBgYAoKIyBDb252ZXJ0IGJhY2sgdG8gdHN2L3BxcAoKYGBge2Jhc2hfcnVuciBjb252ZXJ0X2JhY2t9CmVjaG8gIkNvbnZlcnRpbmcgZGVjb3ktYWRkZWQgbGlicmFyaWVzIGJhY2sgdG8gdHN2IGZvciBleGFtaW5hdGlvbiBsYXRlci4iCnJtIC1mICIke0NPTlNFTlNVU31fJHtNWl9XSU5ET1dTfV9kZWNveS50c3YiCmVjaG8gIlRoZSBpbnB1dCBpczogJHtERUNPWV9UUkFNTH0iCmVjaG8gIlRoZSBvdXRwdXQgaXM6ICR7VFJBTlNJVElPTl9QUkVGSVh9LnRzdiIKVGFyZ2V0ZWRGaWxlQ29udmVydGVyIFwKICAgIC1pbiAiJHtERUNPWV9UUkFNTH0iIFwKICAgIC1pbl90eXBlIFRyYU1MIFwKICAgIC1vdXQgIiR7VFJBTlNJVElPTl9QUkVGSVh9LnRzdiIgXAogICAgLW91dF90eXBlIHRzdgoKZWNobyAiQ29udmVydGluZyBsaWJyYXJpZXMgd2l0aCBkZWNveXMgZm9yICR7VFJBTlNJVElPTl9QUkVGSVh9IHRvIHBxcC4iCmVjaG8gIlRoZSBpbnB1dCBpczogJHtERUNPWV9UUkFNTH0iCmVjaG8gIlRoZSBvdXRwdXQgaXM6ICR7VFJBTlNJVElPTl9QUkVGSVh9LnBxcCIKVGFyZ2V0ZWRGaWxlQ29udmVydGVyIFwKICAgIC1pbiAiJHtUUkFOU0lUSU9OX1BSRUZJWH0udHN2IiBcCiAgICAtaW5fdHlwZSB0c3YgXAogICAgLW91dF90eXBlIHBxcCBcCiAgICAtb3V0ICIke1RSQU5TSVRJT05fUFJFRklYfS5wcXAiCmVjaG8gIlRyYW5zaXRpb24gbGlicmFyeSBmb3Igb3BlbnN3YXRod29ya2Zsb3cgaXM6ICR7VFJBTlNJVElPTl9QUkVGSVh9LnBxcCIKZ3JlcCAiJHtURVNUfSIgIiR7VFJBTlNJVElPTl9QUkVGSVh9LnRzdiIgfCBoZWFkCmdyZXAgLWMgIiR7REVDT1lfU1RSSU5HfSIgIiR7VFJBTlNJVElPTl9QUkVGSVh9LnRzdiIKYGBgCgpgYGB7ciBzbGVlcDEzLCBpbmNsdWRlPUZBTFNFfQpTeXMuc2xlZXAoMSkKYGBgCgojIE9wZW5Td2F0aFdvcmtmbG93IGFnYWluc3Qgb3VyIGV4cGVyaW1lbnRhbCB0cmFuc2l0aW9ucwoKYGBge2Jhc2hfcnVuciBvcGVuc3dhdGhfb3VyfQplY2hvICJJbnZva2luZyB0aGUgT3BlblN3YXRoV29ya2Zsb3cuIgplY2hvICJDaGVja2luZyBpbiwgdGhlIHRyYW5zaXRpb24gbGlicmFyeSBpczogJHtUUkFOU0lUSU9OX1BSRUZJWH0ucHFwIgpzd2F0aF9pbnB1dHM9JCgvYmluL2xzICJtelhNTC9kaWFfJHtWRVJTSU9OfSIpCmVjaG8gIkNoZWNraW5nIGluLCB0aGUgaW5wdXRzIGFyZTogJHtTV0FUSF9JTlBVVFN9Igpta2RpciAtcCAiJHtTV0FUSF9PVVRESVJ9Igpmb3IgaW5wdXQgaW4gJHtzd2F0aF9pbnB1dHN9CmRvCiAgICBpbl9tenhtbD0ibXpYTUwvZGlhXyR7VkVSU0lPTn0vJHtpbnB1dH0iCiAgICBuYW1lPSQoYmFzZW5hbWUgIiR7aW5wdXR9IiAubXpYTUwpCiAgICBlY2hvICJTdGFydGluZyBvcGVuc3dhdGggcnVuIG9mICR7bmFtZX0gdXNpbmcgJHtNWl9XSU5ET1dTfSB3aW5kb3dzIGF0ICQoZGF0ZSkuIgogICAgc3dhdGhfb3V0cHV0X3ByZWZpeD0iJHtTV0FUSF9PVVRESVJ9LyR7bmFtZX1fdnNfJHtWRVJTSU9OfV8ke1RZUEV9XyR7RERBX01FVEhPRH1fZGlhIgogICAgZWNobyAiRGVsZXRpbmcgcHJldmlvdXMgc3dhdGggb3V0cHV0IGZpbGU6ICR7U1dBVEhfT1VUUFVUX1BSRUZJWH0ub3N3IgogICAgcm0gLWYgIiR7U1dBVEhfT1VUUFVUX1BSRUZJWH0ub3N3IgogICAgT3BlblN3YXRoV29ya2Zsb3cgXAogICAgICAgIC1pbmkgInBhcmFtZXRlcnMvb3Blbm1zXyR7VkVSU0lPTn0uaW5pIiBcCiAgICAgICAgLWluICIke2luX216eG1sfSIgXAogICAgICAgIC1zd2F0aF93aW5kb3dzX2ZpbGUgIndpbmRvd3Mvb3BlbnN3YXRoXyR7bmFtZX0udHh0IiBcCiAgICAgICAgLXRyICIke1RSQU5TSVRPTl9QUkVGSVh9LnBxcCIgXAogICAgICAgIC1vdXRfb3N3ICIke3N3YXRoX291dHB1dF9wcmVmaXh9Lm9zdyIgXAogICAgICAgIDI+IiR7c3dhdGhfb3V0cHV0X3ByZWZpeH1fb3N3LmxvZyIgMT4mMgoKICAgIGVjaG8gIlNjb3JpbmcgaW5kaXZpZHVhbCBzd2F0aCBydW46ICR7c3dhdGhfb3V0cHV0X3ByZWZpeH0iCiAgICBweXByb3BoZXQgXAogICAgICAgIHNjb3JlIFwKICAgICAgICAtLWxldmVsIG1zMSBcCiAgICAgICAgLS1pbiAiJHtzd2F0aF9vdXRwdXRfcHJlZml4fS5vc3ciIFwKICAgICAgICAyPj4iJHtzd2F0aF9vdXRwdXRfcHJlZml4fV9weXByb3BoZXRfbXMxLmxvZyIgMT4mMgoKICAgIHB5cHJvcGhldCBcCiAgICAgICAgc2NvcmUgXAogICAgICAgIC0tbGV2ZWwgbXMyIFwKICAgICAgICAtLWluICIke3N3YXRoX291dHB1dF9wcmVmaXh9Lm9zdyIgXAogICAgICAgIC0tb3V0ICIke3N3YXRoX291dHB1dF9wcmVmaXh9X3Njb3JlZC5vc3ciIFwKICAgICAgICAyPj4iJHtzd2F0aF9vdXRwdXRfcHJlZml4fV9weXByb3BoZXRfbXMyLmxvZyIgMT4mMgoKICAgIHB5cHJvcGhldCBcCiAgICAgICAgcHJvdGVpbiBcCiAgICAgICAgLS1pbiAiJHtzd2F0aF9vdXRwdXRfcHJlZml4fV9zY29yZWQub3N3IiBcCiAgICAgICAgLS1jb250ZXh0IHJ1bi1zcGVjaWZpYyBcCiAgICAgICAgMj4+IiR7c3dhdGhfb3V0cHV0X3ByZWZpeH1fcHlwcm9waGV0X3Byb3RlaW4ubG9nIiAxPiYyCgogICAgZWNobyAiRXhwb3J0aW5nIGluZGl2aWR1YWwgc3dhdGggcnVuOiB0byAke3N3YXRoX291dHB1dF9wcmVmaXh9LnRzdiIKICAgIHB5cHJvcGhldCBcCiAgICAgICAgZXhwb3J0IFwKICAgICAgICAtLWluICIke3N3YXRoX291dHB1dF9wcmVmaXh9X3Njb3JlZC5vc3ciIFwKICAgICAgICAtLW91dCAiJHtzd2F0aF9vdXRwdXRfcHJlZml4fV9zY29yZWQudHN2IiBcCiAgICAgICAgMj4+IiR7c3dhdGhfb3V0cHV0X3ByZWZpeH1fcHlwcm9waGV0X2V4cG9ydC5sb2ciIDE+JjIKZG9uZQpgYGAKCmBgYHtyIHNsZWVwMTQsIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgT3BlblN3YXRoV29ya2Zsb3cgYWdhaW5zdCBvdXIgdGhlIFR1YmVyY3VsaXN0IHRyYW5zaXRpb25zCgpgYGB7YmFzaF9ydW5yIG9wZW5zd2F0aF90dWJlcmN1bGlzdH0KZWNobyAiSW52b2tpbmcgdGhlIE9wZW5Td2F0aFdvcmtmbG93IHVzaW5nIHRoZSB0dWJlcmN1bGlzdCB0cmFuc2l0aW9ucy4iCnN3YXRoX2lucHV0cz0kKC9iaW4vbHMgIm16WE1ML2RpYV8ke1ZFUlNJT059IikKZWNobyAiQ2hlY2tpbmcgaW4sIHRoZSBpbnB1dHMgYXJlOiAke3N3YXRoX2lucHV0c30iCm1rZGlyIC1wICIke1RVQkVSQ1VMSVNUX09VVERJUn0iCmZvciBpbnB1dCBpbiAke3N3YXRoX2lucHV0c30KZG8KICAgIGluX216eG1sPSJtelhNTC9kaWFfJHtWRVJTSU9OfS8ke2lucHV0fSIKICAgIG5hbWU9JChiYXNlbmFtZSAiJHtpbnB1dH0iIC5telhNTCkKICAgIGVjaG8gIlN0YXJ0aW5nIG9wZW5zd2F0aCBydW4gb2YgJHtuYW1lfSB1c2luZyAke01aX1dJTkRPV1N9IHdpbmRvd3MgYXQgJChkYXRlKS4iCiAgICB0Yl9vdXRwdXRfcHJlZml4PSIke1RVQkVSQ1VMSVNUX09VVERJUn0vJHtuYW1lfV92c18ke1ZFUlNJT059XyR7VFlQRX1fJHtEREFfTUVUSE9EfV9kaWEiCiAgICBlY2hvICJEZWxldGluZyBwcmV2aW91cyBzd2F0aCBvdXRwdXQgZmlsZTogJHt0Yl9vdXRwdXRfcHJlZml4fS5vc3ciCiAgICBybSAtZiAiJHt0Yl9vdXRwdXRfcHJlZml4fS5vc3ciCiAgICBPcGVuU3dhdGhXb3JrZmxvdyBcCiAgICAgICAgLWluaSAicGFyYW1ldGVycy9vcGVubXNfJHtWRVJTSU9OfS5pbmkiIFwKICAgICAgICAtaW4gIiR7aW5fbXp4bWx9IiBcCiAgICAgICAgLXN3YXRoX3dpbmRvd3NfZmlsZSAid2luZG93cy9vcGVuc3dhdGhfJHtuYW1lfS50eHQiIFwKICAgICAgICAtdHIgIiR7VFVCRVJDVUxJU1RfUFFQfSIgXAogICAgICAgIC1vdXRfb3N3ICIke3RiX291dHB1dF9wcmVmaXh9Lm9zdyIgXAogICAgICAgIDI+IiR7dGJfb3V0cHV0X3ByZWZpeH1fb3N3LmxvZyIgMT4mMgoKICAgIGVjaG8gIlNjb3JpbmcgaW5kaXZpZHVhbCBzd2F0aCBydW46ICR7dGJfb3V0cHV0X3ByZWZpeH0iCiAgICBweXByb3BoZXQgXAogICAgICAgIHNjb3JlIFwKICAgICAgICAtLWxldmVsIG1zMSBcCiAgICAgICAgLS1pbiAiJHt0Yl9vdXRwdXRfcHJlZml4fS5vc3ciIFwKICAgICAgICAyPj4iJHt0Yl9vdXRwdXRfcHJlZml4fV9weXByb3BoZXRfbXMxLmxvZyIgMT4mMgoKICAgIHB5cHJvcGhldCBcCiAgICAgICAgc2NvcmUgXAogICAgICAgIC0tbGV2ZWwgbXMyIFwKICAgICAgICAtLWluICIke3RiX291dHB1dF9wcmVmaXh9Lm9zdyIgXAogICAgICAgIC0tb3V0ICIke3RiX291dHB1dF9wcmVmaXh9X3Njb3JlZC5vc3ciIFwKICAgICAgICAyPj4iJHt0Yl9vdXRwdXRfcHJlZml4fV9weXByb3BoZXRfbXMyLmxvZyIgMT4mMgoKICAgIHB5cHJvcGhldCBcCiAgICAgICAgcHJvdGVpbiBcCiAgICAgICAgLS1pbiAiJHt0Yl9vdXRwdXRfcHJlZml4fV9zY29yZWQub3N3IiBcCiAgICAgICAgLS1jb250ZXh0IHJ1bi1zcGVjaWZpYyBcCiAgICAgICAgMj4+IiR7dGJfb3V0cHV0X3ByZWZpeH1fcHlwcm9waGV0X3Byb3RlaW4ubG9nIiAxPiYyCgogICAgZWNobyAiRXhwb3J0aW5nIGluZGl2aWR1YWwgc3dhdGggcnVuOiB0byAke3RiX291dHB1dF9wcmVmaXh9LnRzdiIKICAgIHB5cHJvcGhldCBcCiAgICAgICAgZXhwb3J0IFwKICAgICAgICAtLWluICIke3RiX291dHB1dF9wcmVmaXh9X3Njb3JlZC5vc3ciIFwKICAgICAgICAtLW91dCAiJHt0Yl9vdXRwdXRfcHJlZml4fV9zY29yZWQudHN2IiBcCiAgICAgICAgMj4+IiR7dGJfb3V0cHV0X3ByZWZpeH1fcHlwcm9waGV0X2V4cG9ydC5sb2ciIDE+JjIKZG9uZQpgYGAKCmBgYHtyIHNsZWVwMTUsIGluY2x1ZGU9RkFMU0V9ClN5cy5zbGVlcCgxKQpgYGAKCiMgTWVyZ2luZyBvdXIgZGF0YSB3aXRoIFRSSUMKCmBgYHtiYXNoX3J1bnJ9CmZlYXR1cmVfYWxpZ25tZW50LnB5IFwKICAgIC0tZm9yY2UgXAogICAgLS1pbiAiLi8ke1NXQVRIX09VVERJUn0vIioudHN2IFwKICAgIC0tb3V0ICIke1RSSUNfT1VURElSfS8ke1NFQVJDSF9NRVRIT0R9XyR7RERBX01FVEhPRH0udHN2IiBcCiAgICAtLW91dF9tYXRyaXggIiR7VFJJQ19PVVRESVJ9LyR7RERBX01FVEhPRH1fb3V0bWF0cml4LnRzdiIgXAogICAgLS1vdXRfbWV0YSAiJHtUUklDX09VVERJUn0vJHtEREFfTUVUSE9EfV9tZXRhLnRzdiIKZWNobyAiV3JvdGUgZmluYWwgb3V0cHV0IHRvICR7VFJJQ19PVVRESVJ9LyR7U0VBUkNIX01FVEhPRH1fJHtEREFfTUVUSE9EfS50c3YiCmBgYAoKYGBge3Igc2xlZXAxNiwgaW5jbHVkZT1GQUxTRX0KU3lzLnNsZWVwKDEpCmBgYAoKIyBNZXJnaW5nIHRoZSBUdWJlcmN1bGlzdC1kZXJpdmVkIGRhdGEgd2l0aCBUUklDCgpgYGB7YmFzaF9ydW5yfQp0cmljX3RiPSIke1RSSUNfT1VURElSfV90YiIKZmVhdHVyZV9hbGlnbm1lbnQucHkgXAogICAgLS1mb3JjZSBcCiAgICAtLWluICIuLyR7U1dBVEhfT1VURElSfS8iKi50c3YgXAogICAgLS1vdXQgIiR7dHJpY190Yn0vJHtTRUFSQ0hfTUVUSE9EfV8ke0REQV9NRVRIT0R9LnRzdiIgXAogICAgLS1vdXRfbWF0cml4ICIke3RyaWNfdGJ9LyR7RERBX01FVEhPRH1fb3V0bWF0cml4LnRzdiIgXAogICAgLS1vdXRfbWV0YSAiJHt0cmljX3RifS8ke0REQV9NRVRIT0R9X21ldGEudHN2IgplY2hvICJXcm90ZSBmaW5hbCBvdXRwdXQgdG8gJHt0cmljX3RifS8ke1NFQVJDSF9NRVRIT0R9XyR7RERBX01FVEhPRH0udHN2IgpgYGAKCiMgSW5kZXggdmVyc2lvbjogYHIgdmVyYAoKIyBUT0RPCgoqIDIwMTctMDYtMTQ6CgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIG1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQogIHRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCiAgbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCB0aGlzX3NhdmUpKQogIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9dGhpc19zYXZlKSkKICBwYW5kZXI6OnBhbmRlcihzZXNzaW9uSW5mbygpKQp9CmIkc3RvcCgpCmBgYAo=