R Notebook: Provides reproducible analysis for metagenome (MG) data in the following manuscript:

Citation: Romanowicz, KJ, Crump, BC, Kling, GW. (2021) Rainfall alters permafrost soil redox conditions, but meta-omics show divergent microbial community responses by tundra type in the arctic. Soil Systems 5(1): 17. https://doi.org/10.3390/soilsystems5010017

GitHub Repository: https://github.com/kromanowicz/2021-Romanowicz-SoilSystems

NCBI BioProject: https://www.ncbi.nlm.nih.gov/bioproject/PRJNA666429

Accepted for Publication: Soil Systems 10 March 2021

Experiment

This R Notebook provides complete reproducibility of the data analysis in “Rainfall alters permafrost soil redox conditions, but meta-omics show divergent microbial community responses by tundra type in the Arctic” by Romanowicz, Crump, and Kling. In this experiment, mesocosms containing soil from the active layer of two dominant tundra types were subjected to simulated rainfall to alter redox conditions. The microbial functional potential (metagenomics) and gene expression (metatranscriptomics) patterns were measured during saturated anoxic redox conditions prior to rainfall and at multiple time points following the simulated rainfall event. Other measurements include soil properties as well as microbial respiration (CO2) and methane (CH4) production from soil subsamples collected at each sampling time point. The purpose was to determine if rainfall, as a form of soil oxidation, is sufficient to alter the anoxic redox conditions in arctic tundra and enhance the microbial degradation of organic carbon and CH4 to CO2.

Conceptual Figure. A total of 12 tundra mesocosms (3 replicates x 2 tundra types x 2 sets of response cores) were acclimated initially under anoxic redox conditions to mimic field conditions (T0). Dissolved oxygen was supplied to soils through the downward flow of oxygenated water during a simulated rainfall event. Dissolved oxygen will likely change the redox gradient directly following rainfall (T4) as a short-term effect. Anoxic conditions will likely be re-established after 24 hours (T24) as the pulse of oxygen is consumed through abiotic and biotic soil processes. Under anoxic redox conditions (T0), microorganisms likely degrade organic carbon through anaerobic and fermentation pathways, producing CH4 and reducing Fe(III) to Fe(II). Rainfall-induced soil oxidation (T4) should stimulate heterotrophic microorganisms that degrade organic carbon and CH4 through aerobic metabolic pathways, releasing CO2. Soil oxidation should also stimulate aerobic autotrophic iron oxidizing bacteria that oxidize Fe(II) to Fe(III) and convert CO2 into microbial biomass. The long-term response (T24) will likely be a combination of aerobic and anaerobic metabolism as well as a combination of reduction and oxidation iron reactions as dissolved oxygen is consumed. The predicted redox conditions and predicted redox reactions for coupled Fe(II)/Fe(III) cycling, as well as the microbial-induced release of CO2 or CH4 at each time point are based on the predicted availability of dissolved oxygen entering tundra soils through simulated rainfall.

Soil Sampling for Microbial Gene Expression

An initial soil sampling event for microbial activity was conducted at the end of the anoxic acclimation period (4-7 days) in all mesocosm replicates, representing sampling time point T0. Mesocosms were then flushed to simulate a rainfall event. Additional soil sampling events were conducted at T4 (4-hrs) and T24 (24-hrs) following the rainfall event to determine the temporal extent of microbial gene expression. Soil cores (2.54 cm diameter, 30 cm length) were extracted in duplicate from each mesocosm replicate at each sampling time point and homogenized by depth in 10-cm increments. The 10-20 cm soil increment, composed of organic soil in all mesocosm replicates, was chosen for microbial gene expression analysis and preserved in RNAlater Stabilization Reagent in sterile tubes at 4°C for 18 hours and then stored at -80°C until extraction.

Field Experiment. Tundra soil cores were collected from field sites in August 2017 (top left) and placed in buckets to establish the mesocosm experiment (bottom left). Tussock tundra cores were composed of an organic soil layer overlying a mineral soil layer (top middle) while wet sedge tundra cores were composed entirely of organic soil (bottom middle). Soil subsampling for microbial activity was taken from the 10-20 cm depth of duplicate soil cores in Tussock (top right) and Wet Sedge (bottom right).

# Make a vector of required packages
required.packages <- c("ape","cowplot","data.table","devtools","dplyr","DT","ggplot2","ggpubr","grid","gridExtra","kableExtra","knitr","pheatmap","png","RColorBrewer","reshape","rstatix","statmod","stringr","tibble","tidyr","tidyverse","vegan","yaml")

# Load required packages
lapply(required.packages, library, character.only = TRUE)

Metagenomes

1. DNA Sequencing

Extracted DNA was sequenced on the Illumina HiSeq 4000 platform (150bp paired-end reads) at the University of Michigan Advanced Genomics Core.

SeqCore DNA sample submission to Illumina HiSeq platform
ID Sample Concentration (ng/ul) Volume (uL) Fragment Length i7 i5 Barcode i7 Barcode i5
S107104 WS1_T0 10 40 500 N701 S517 TAAGGCGA TCTTACGC
S107105 WS2_T0 10 40 500 N702 S517 CGTACTAG TCTTACGC
S107106 WS3_T0 10 40 500 N703 S517 AGGCAGAA TCTTACGC
S107107 Tuss1_T0 10 40 500 N704 S517 TCCTGAGC TCTTACGC
S107108 Tuss2_T0 10 40 500 N705 S517 GGACTCCT TCTTACGC
S107110 WS1_T4 10 40 500 N701 S502 TAAGGCGA ATAGAGAG
S107111 WS2_T4 10 40 500 N702 S502 CGTACTAG ATAGAGAG
S107112 WS3_T4 10 40 500 N703 S502 AGGCAGAA ATAGAGAG
S107113 WS1_T24 10 40 500 N704 S502 TCCTGAGC ATAGAGAG
S107114 WS2_T24 10 40 500 N705 S502 GGACTCCT ATAGAGAG
S107115 WS3_T24 10 40 500 N706 S502 TAGGCATG ATAGAGAG
S107116 Tuss1_T4 10 40 500 N701 S503 TAAGGCGA AGAGGATA
S107117 Tuss2_T4 10 40 500 N702 S503 CGTACTAG AGAGGATA
S107119 Tuss1_T24 10 40 500 N704 S503 TCCTGAGC AGAGGATA
S107121 Tuss3_T24 10 40 500 N706 S503 TAGGCATG AGAGGATA
S107109 Tuss3_T0 10 40 500 N706 S517 TAGGCATG TCTTACGC
S107118 Tuss3_T4 10 40 500 N703 S503 AGGCAGAA AGAGGATA
S107120 Tuss2_T24 10 40 500 N705 S503 GGACTCCT AGAGGATA

NOTE: DNA Samples in RED were excluded from sequencing

2. DNA Bioinformatics

2.1. Raw Reads

Prep the Raw Reads (Hein: Comics – Omics Prep)

Use the comics container to prep the raw reads.

{Terminal}
cd /DNA_data/work
comics -- omics prep /DNA_data/Sample_1071*

DNA.data.raw.prep.pbs (“/DNA_data/work/”) 00:19 (hr:min)

  • Rename the sample folders newly created in the “DNA_data/work” directory as “Sample_107104”, etc.
  • Rename the .fastq files within each sample folder in the “DNA_data/work” directory as “Sample_107104_fwd.fastq”, “Sample_107104_rev.fastq”, etc.

2.2. QC Raw Reads

QC the Raw Reads (Smith: BBMap_QC)

  • The “bbmap_qc.sh” script was provided but needed to be edited internally to reference the correct directories and parser files (see “bbmap_qc.sh” in the “SCRIPTS” section for all internal coding)
  • Place the “bbmap_qc.sh” script file in the “DNA_data/work” directory
  • Run the “bbmap_qc.sh” script and specify a “.log” file output
{Terminal}
cd /DNA_data/work
bash bbmap_qc.sh > qc.log

DNA.data.bbmap.qc.pbs (“/DNA_data/work/”) 05:32 (hr:min)

2.3. Co-Assemble QC Reads

Co-Assemble the QC Reads (Smith: MegaHit)

  • Create a new directory within “DNA_data/work” named “DNA_data/work/co_assembly”

2.3.1 Concatenate the QC’d sample reads into a single fwd and rev file

  • Concatenate the QC’d sample reads into a single fwd and rev file
  • Move the "**_adtrim_clean_qtrim_fwd.derep.fastq" and "_adtrim_clean_qtrim_rev.derep.fastq**" files from each sample to the “co_assembly” directory
  • Concatonate the "**_adtrim_clean_qtrim_fwd.derep.fastq**" file from all samples into a single “1071_fwd.derep.fastq” prior to co-assembling
  • Concatonate the "**_adtrim_clean_qtrim_rev.derep.fastq**" file from all samples into a single “1071_rev.derep.fastq” prior to co-assembling
{Terminal}
cd /DNA_data/work/co_assembly
cat *_adtrim_clean_qtrim_fwd.derep.fastq > 1071_DNA_data_fwd.derep.fastq
cat *_adtrim_clean_qtrim_rev.derep.fastq > 1071_DNA_data_rev.derep.fastq

DNA.data.qc.read.concatonate.pbs (“/DNA_data/work/”) 03:40 (hr:min)

2.3.2 Normalize Reads to 20X Coverage Prior to Assembly

  • Normalize all kmers in the combined read dataset to 20X coverage (NOTE: This is kmer coverage, not read coverage)
  • Also remove any kmers below 5X coverage (if the coverage is this low after pooling all samples then it is probably due to sequencing error or a very rare organism that won’t assemble completely anyway)
{Terminal}
cd /DNA_data/work/co_assembly
comics bbnorm in=1071_DNA_data_fwd.derep.fastq in2=1071_DNA_data_rev.derep.fastq out=1071_DNA_data_bbnorm_fwd.derep.fastq out2=1071_DNA_data_bbnorm_rev.derep.fastq target=20 mindepth=5 threads=20 -Xmx425g &> bbnorm.log

DNA.data.bbnorm.pbs (“/DNA_data/work/”) 03:44 (hr:min)

2.3.3 Run the Assembly Module to Co-Assemble Contigs (Comics MegaHit)

  • Run the assembly module on QC/Pre-Processed (bbmap) reads to build contigs
  • Use the MEGAHIT assembler to assemble reads into contigs
  • Generally, the more iterations, the longer the process takes and the better the assembly
    • For MEGAHIT: k=255 is the maximum, which, with a step size of 6 or 8, is recommended unless severely limited by computational resources
{Terminal}
cd /DNA_data/work/co_assembly
megahit --k-min 21 --k-max 255 --k-step 8 -1 1071_DNA_data_bbnorm_fwd.derep.fastq -2 1071_DNA_data_bbnorm_rev.derep.fastq -o ./megahit_out_bbnorm

DNA.data.bbnorm.megahit.coassembly.k255.pbs (“/DNA_data/work/”) 38:15 (hr:min)

2.3.4 Re-Format the Contigs File from the MegaHit Co-Assembly

  • The contig headers in the “final.contigs.fa” file from MEGAHIT contained complex characters and spaces that were re-formatted prior to mapping
    • This was essential so that the names of the contigs in the BAM files (generated from the mapper) matched those in the “final.contigs.fa” file PRIOR to importing into Anvi’o
{Terminal}
cd /DNA_data/work/co_assembly/megahit_out_bbnorm

head final.contigs.fa

>k255_1 flag=1 multi=24.0000 len=301
CATGCCCTGGCGCTGCAGCGGATCTGGCAGCTGACGCCGGAACCGCAGCGGCCGGAGATCCGCGCGCGTCTGCAGGCGCTCTACCCGCGGCTGGTCAAGTGGCATCGCTATCTCGCCACCCAGCGCGACCCCGAGGCATCGGGACTGGTCACCGTATACCACCCGTGGGAGAGCACGGACAACTCCCCGCGCTGGGACCGCTCGCTGGCACGCATCGAGGTGGTCAAGCCCCGCCCGTACACCCGCCTGGACACCCGTCAGGTGCGGGACCCGTCGCAGCGGCCCACCGACTGGGACTACG
  • Numbers, letters, and underscores were OK in sequence names but any other characters cause trouble in Anvi’o
  • The following commands reformatted the “final.contigs.fa” file by replacing spaces and “=” signs with "_"
{Terminal}
cd /DNA_data/work/co_assembly/megahit_out_bbnorm
sed -e 's/\s/_/g' final.contigs.fa > final.contigs.fixed.bbnorm.fa
sed -e 's/=/_/g' final.contigs.fixed.bbnorm.fa > final.contigs.fixed2.bbnorm.fa
mv final.contigs.fixed2.bbnorm.fa final.contigs.fixed.bbnorm.fa

head final.contigs.fixed.bbnorm.fa

>k255_1_flag_1_multi_24.0000_len_301
CATGCCCTGGCGCTGCAGCGGATCTGGCAGCTGACGCCGGAACCGCAGCGGCCGGAGATCCGCGCGCGTCTGCAGGCGCTCTACCCGCGGCTGGTCAAGTGGCATCGCTATCTCGCCACCCAGCGCGACCCCGAGGCATCGGGACTGGTCACCGTATACCACCCGTGGGAGAGCACGGACAACTCCCCGCGCTGGGACCGCTCGCTGGCACGCATCGAGGTGGTCAAGCCCCGCCCGTACACCCGCCTGGACACCCGTCAGGTGCGGGACCCGTCGCAGCGGCCCACCGACTGGGACTACG

2.4. Index Contigs and Map

Index the Co-Assembled Contigs and Map (Hein: Omics Mapping)

  • Once the sequence headers in the contigs file were cleaned up, the co-assembly was indexed as follows:
{Terminal}
cd /DNA_data/work/co_assembly/megahit_out_bbnorm
comics -- omics mapping -a final.contigs.fixed.bbnorm.fa --index-only

DNA.data.bbnorm.index.contigs.pbs (“/DNA_data/work/”) 00:46 (hr:min)

  • The output was a directory called “/bowtie2-index”
  • Rename as “/bowtie2-index_bbnorm”

2.4.1 Map Short Reads from Each Sample to the Contigs

  • Create a “/DNA_data/work/mapping” directory and move the “/bowtie2-index_bbnorm” directory into it
  • Move the “/co_assembly/megahit_out_bbnorm/final.contigs.fixed.bbnorm.fa” file to the “/work/co_assembly” directory
  • Individually map the short reads from each sample to the contigs, which will create separate output directories for each sample containing the mapping result files
{Terminal}
cd /DNA_data/work/co_assembly
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107104_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107104_adtrim_clean_qtrim_rev.derep.fastq -o 107104_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107105_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107105_adtrim_clean_qtrim_rev.derep.fastq -o 107105_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107106_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107106_adtrim_clean_qtrim_rev.derep.fastq -o 107106_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107107_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107107_adtrim_clean_qtrim_rev.derep.fastq -o 107107_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107108_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107108_adtrim_clean_qtrim_rev.derep.fastq -o 107108_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107110_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107110_adtrim_clean_qtrim_rev.derep.fastq -o 107110_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107111_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107111_adtrim_clean_qtrim_rev.derep.fastq -o 107111_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107112_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107112_adtrim_clean_qtrim_rev.derep.fastq -o 107112_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107113_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107113_adtrim_clean_qtrim_rev.derep.fastq -o 107113_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107114_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107114_adtrim_clean_qtrim_rev.derep.fastq -o 107114_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107115_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107115_adtrim_clean_qtrim_rev.derep.fastq -o 107115_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107116_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107116_adtrim_clean_qtrim_rev.derep.fastq -o 107116_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107117_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107117_adtrim_clean_qtrim_rev.derep.fastq -o 107117_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107119_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107119_adtrim_clean_qtrim_rev.derep.fastq -o 107119_bbnorm_mapped_reads
comics -- omics mapping --index-dir /DNA_data/work/mapping/bowtie2-index_bbnorm/ -a final.contigs.fixed.bbnorm.fa -f Sample_107121_adtrim_clean_qtrim_fwd.derep.fastq -r Sample_107121_adtrim_clean_qtrim_rev.derep.fastq -o 107121_bbnorm_mapped_reads

DNA.data.bbnorm.short.read.mapping.pbs (“/DNA_data/work/”) 11:51 (hr:min)

  • The results for each individual sample were a mapping directory containing the following files: “/DNA_data/work/co_assembly/*bbnorm_mapped_reads” (replace * with SampleID) “final.contigs.fixed.bbnorm.cov” tab-delimited file of the average coverage of each contig in the assembly “final.contigs.fixed.bbnorm.bam” contains the mapping information “final.contigs.fixed.bbnorm.sorted.bam” contains the mapping information sorted by position “final.contigs.fixed.bbnorm.sorted.bam.bai” a companion file to the sorted.bam file, which contains the index
  • Move all of the “/DNA_data/work/co_assembly/*bbnorm_mapped_reads” folders to the “/DNA_data/work/mapping” directory
  • Re-name each file with the sample number as the prefix: “Sample_107104.final.contigs.fixed.bbnorm.cov”, etc.

2.5. Create Anvi’o Database

Create Anvi’o Database and Profiles (Smith: Anvi’o)

  • Create an Anvi’o contigs database from the co-assembly and profile the abundance (coverage) information from the .bam files into an Anvi’o profile
  • Create a merged profile of all samples
{Terminal}
cd /DNA_data/work/co_assembly
anvi-gen-contigs-database -f final.contigs.fixed.bbnorm.fa -o DNA.data.bbnorm.anvio.contigs.db -n DNA_data_bbnorm --split-length 10000 --kmer-size 4

DNA.data.bbnorm.anvio.contigs.database.pbs (“/DNA_data/work/”) 05:00 (hr:min)

  • Create the Anvi’o contigs database “DNA_data_bbnorm_anvio_contigs.db” file in the “/DNA_data/work/co_assembly” directory
  • The “DNA_data_bbnorm_anvio_contigs.db” database contains contig sequences, splitting contigs larger than 10kb into splits of 10kb or less
  • Default kmer-size is “kmer-size 4”

2.5.1 Annotate Contigs Database – HMMS

  • Annotate contigs database with the start and stop sites of single-copy house-keeping genes and rRNA genes
  • Necessary to get bin completeness and contamination metrics along with rRNA annotations in real time as bins will be manually refined in subsequent steps
{Terminal}
cd /DNA_data/work/co_assembly
anvi-run-hmms -c DNA_data_bbnorm_anvio_contigs.db --num-threads 20

DNA.data.bbnorm.anvio.contigs.hmms.pbs (“/DNA_data/work/”) 16:52 (hr:min)

2.5.2 Annotate Contigs Database – GhostKoala

  • Annotate the Anvi’o gene calls with taxonomy and functional annotations from KEGG GhostKoala’s online database

2.5.2.1 First, exporte the amino acid sequences of the Anvi’o gene calls:

{Terminal}
cd /DNA_data/work/co_assembly
anvi-get-sequences-for-gene-calls -c DNA_data_bbnorm_anvio_contigs.db -o DNA_data_bbnorm_anvio_gene_calls.faa --get-aa-sequences

DNA.data.bbnorm.anvio.export.aa.seqs.pbs (“/DNA_data/work/”) 00:10 (hr:min)

2.5.2.2 GhostKoala cannot accept gene IDs that start with numbers, so the prefix “genecall” was added to all AA sequences as follows:

{Terminal}
sed 's/>/>genecall_/g' DNA_data_bbnorm_anvio_gene_calls.faa > DNA_data_bbnorm_anvio_gene_calls_edited.faa
mv DNA_data_bbnorm_anvio_gene_calls_edited.faa DNA_data_bbnorm_anvio_gene_calls.faa

#EXAMPLE
[co_assembly]$ head DNA_data_bbnorm_anvio_gene_calls.faa
>genecall_0
HALALQRIWQLTPEPQRPEIRARLQALYPRLVKWHRYLATQRDPEASGLVTVYHPWESTDNSPRWDRSLARIEVVKPRPYTRLDTRQVRDPSQRPTDWDY

2.5.2.3 Check the “DNA_data_bbnorm_anvio_gene_calls.faa” file for empty sequences and remove them prior to submitting to GhostKoala for annotation

  • NOTE: Empty sequences are often found at the end of the “*.faa” file (use “tail” command to view the last 20 lines)
{Terminal}
cd /DNA_data/work/co_assembly
tail DNA_data_bbnorm_anvio_gene_calls.faa

#EXAMPLE
[co_assembly]$ tail DNA_subset_anvio_gene_calls.faa
genecall_3917613
MRVXSXLRVNAGGVDKSCKSRGPARATGRRGSNTXVRPLXSGIASRKVGXFPIVPQGXRFFALGAACVVSASWXGNGLPRLRRLGELRGXPPPMELRHGPYSYGRLQTRIFRNGRKSDGA
TPRDRXSASVRKDLLSGTKFIDGTRXIRGSXLCASRSGNTEAPSITRNHWAXRVSRRPYXSLVKSVGSTCGLRGKRYGSRAXEVHGTHGGGVKSVDIMGNTKGEGNALVRSXRSNTKARV
ANGIRYPGSPGPQRCSLVLRSIDPLXDXANAVSEPPGXYDRKIKTQRNRRGLAQAVDYAAXFVGKRRTLPRLEIQLHPTXKGRSLRGCWTGDAWSSSVRGLNCSLQWGNERNPRCLLPIW
PGETAPSRERKVGMTPDQHVPLIPWAARIIQWSVQQVAMPXGGANPYKTDPSTDXGLQPTSXSRNRXXSRVSQTGVNTFSSLVLTARQVKGVGGARRTASRSTTANSMTRTKSXQGTGSG
SCSWNIS
>genecall_3917614

>genecall_3917615
  • Use the following script to remove all empty sequences from the “DNA_data_bbnorm_anvio_gene_calls.faa” file:
{Terminal}
sed '/^>/ {N; /\n$/d}' DNA_data_bbnorm_anvio_gene_calls.faa > DNA_data_bbnorm_anvio_gene_calls_clean.faa
mv DNA_data_bbnorm_anvio_gene_calls_clean.faa DNA_data_bbnorm_anvio_gene_calls.faa

#EXAMPLE
[co_assembly]$ tail DNA_data_bbnorm_anvio_gene_calls.faa
>genecall_2337739
AHLTRLETRTKEFNMRASRWDEKPAGRVKASHSVTLCIGEIPSLVRKHEPGASPAHHKLTWLWWSLSVHVETRKMVNYAWAGXSQGKLWWRSVAILTCKSIVXPGYRGERLIEPSSSWFP
PKFPSGXLALGNAVLPGKANDXRPWGRNDLNLFSNFKWVRSPACLNAKLKSGRWIRAPSGPLLVSRTGAVGXTERXVMAPDETLMRSQKRCWLLXTAGRWPWKSEPAKECVTTHLPKQLA
LKMDGARASGLYSAVAAVNKXNSHAATSRRVAAVASKAYGREPGWSRRRCRSWWXXQILKREPXGLKWRRVPCEQQLNMGQSILRYRRKPFRSGVDSVIYWRWLLXLASRLFRSIPPHLP
KGNRVNIPEPGIGYDAGGGRAHLRHSCRATNAATQMNSETLTRALERVVFSSXGTGSLESDHPAIGRWCPXSTAVLAVSGAHVSVLETPRESVIFVPDRTHIRSRSPRXIASRPLEACRX
GKSAKWICNFGKKIGSEGWAGRAAVGSCRGFGGGPVLWLWSRRESAVYCGRARTSAGAXQWTAVAALPRGVFSVSATSFGAXQPTQNWHGPGESDCLIKTKHCDGWXSVLTQCDFCPVLX
MSKXRNSTKRGXTAGVTMTLLRXPNASSSNXXRAXMDQRDSHCPYLLSSETTAKGTGLAESAGKEDPVELDSSLTRXGDMRGVAXVGGSASCRQXNTTTFIVSLLIQXCGVWLLVARKNR
GAATILALTRTDLFRPRIRSDDSVRRGVXLGRYICQTVTQVSXGKLSEDRNLAXSKRAKACLILIFSTNTDRESVAYRSFXLXEFXARGVRKVTTGITGLWRPSVHSDVAFXSFDVGSSY
HCDAAVAKRRIVHPLIGNVSWVXTVVRQVSFTLLM
>genecall_2337745
QANKCMWWMPWRSQAMKDVVACEKSRGASKRALIREYPNGETRPARVTPGXIHRLGRANSVNXNISVTEGTEINRDSGSSGERTRSSQQVLALLLAKRSGKAGQSGXXPRTQKQWCGTRP
ATSRAGHVKSCLKMGGPSSKAKYSXSTDSEPVPXGKGEKNPGRGVKXILKPHAYKKSEPLLYXSSRVLSRSDARAARLKRLIDEIDPLVASLTXKIRVVLGIDDRSVGDALRVAQCGNTA
SLSRASKPXGLRSEGQXSRGDGVPFVXWVSDLHSVASLSESAGAGKPSPNRANELLGVDPKPDDLLMARMKVRXHALEVRTHXCXKIRGXAVGRGERLNKSGNSWFSPKTIXVVPHVLLL
GVEHCYGXGVMATYQTIANSEYWQVXAWETVTGCXRPVSRGKQPGPPAKVPKYSXVGNEVGRRKQSGGWLRSSHPLKKAXXLTDRVVLRGRCNGAQTRHRSXGC

2.5.2.4 GhostKoala also has a max file size limit of 300 MB, so files larger than the max file size were split into smaller files and the annotations were run in batches with the results concatenated prior to being added into Anvi’o.

To split the data into smaller files:

  • Download “DNA_datat_bbnorm_anvio_gene_calls.faa” (724,306,331 bytes) to local directory and open with text editor (BBEdit preferred)
  • Select a third of the data to cut from the file (⌘X) – Ensure that a gene sequence is NOT cut in half – Start with a “genecall_*”
  • Open a new text file and paste (⌘V) the cut data from the original file (repeated with the second third of data and with the final third of data).
  • Renam the three files as follows:
    • DNA_data_bbnorm_anvio_gene_calls_1.faa” 237,613,185 (237.6 MB)
    • DNA_data_bbnorm_anvio_gene_calls_2.faa” 246,043,256 (246.0 MB)
    • DNA_data_bbnorm_anvio_gene_calls_3.faa” 240,649,888 (240.7 MB)
  • Check that all files were less than 300 MB in size

2.5.2.5 Submit the amino acid files for both functional and taxonomic annotation in KEGG GhostKoala

  • Only ONE “.faa” file can be submitted at a time for annotation
  • Use “genus_prokaryotes + family_eukaryotes” annotation option
    • DNA_data_bbnorm_anvio_gene_calls_1.faa” (237.6 MB)
      • Upload time to GhostKoala 0:10 (hr:min) – Processing time at GhostKoala 42:24 (hr:min)
    • DNA_data_bbnorm_anvio_gene_calls_2.faa” (246.0 MB)
      • Upload time to GhostKoala 0:10 (hr:min) – Processing time at GhostKoala 46:30 (hr:min)
    • DNA_data_bbnorm_anvio_gene_calls_3.faa” (240.7 MB)
      • Upload time to GhostKoala 0:14 (hr:min) – Processing time at GhostKoala 33:33 (hr:min)
  • Result files were as follows:
    • user_ko.txt” Functional annotations file
    • user.out.top” Taxonomic annotations file

2.5.3 Import Functional & Taxonomic Annotations into the Contigs Database

  • Add the concatenated annotation files from GhostKoala to the “/DNA_data/work/co_assembly” directory
    • user_ko.txt
    • user.out.top
  • Copy the following files into the “/DNA_data/work/co_assembly” directory
  • No changes were needed to be made to the internal python scripts – They were run as written
    • KEGG-to-anvio
    • KO_Orthology_ko00001.txt
    • GhostKOALA-taxonomy-to-anvio

2.5.3.1 Parse the functional annotations into a format readable by Anvi’o

{Terminal}
cd /DNA_data/work/co_assembly
python2 KEGG-to-anvio --KeggDB KO_Orthology_ko00001.txt -i user_ko.txt -o KeggAnnotations.txt

2.5.3.2 Import the functional annotations into the contigs database:

{Terminal}
cd /DNA_data/work/co_assembly
anvi-import-functions -c DNA_data_bbnorm_anvio_contigs.db -i KeggAnnotations.txt

#Output
Gene functions ...............................: 1389518 function calls from 1 sources for 1389518 unique gene calls has been added to the contigs database.

2.5.3.3 Parse the taxonomy annotations into a format readable by Anvi’o

{Terminal}
cd /DNA_subset/work/co_assembly
python GhostKOALA-taxonomy-to-anvio user.out.top KeggTaxonomy.txt

2.5.3.4 Import the taxonomic annotations into the contigs database

{Terminal}
cd /DNA_data/work/co_assembly
anvi-import-taxonomy-for-genes -c DNA_data_bbnorm_anvio_contigs.db -p default_matrix -i KeggTaxonomy.txt

#Output
Total num hits found .........................: 3,908,828
Num gene caller ids in the db ................: 3,917,616                       
Num gene caller ids in the incoming data .....: 3,908,828
Taxon names table ............................: Updated with 1672 unique taxon names
Genes taxonomy table .........................: Taxonomy stored for 3908828 gene calls
Splits taxonomy ..............................: Input data from "default_matrix" annotated 2458900 of 2492445 splits (98.7%) with taxonomy.

2.5.4 Import Sample Mapping Information into an Anvi’o Profile

  • Import the mapping information from the “Sample_*.final.contigs.fixed.sorted.bam” into an Anvi’o profile
  • The BAM files are already sorted and indexed (i.e., for each “.bam” file there is also a “.bam.bai” file in the same directory) – Skip the initializing step and create an Anvi’o profile for the samples

2.5.4.1 Move the following files to the “/DNA_data/work/mapping” directory

  • "/DNA_data/work/mapping/*_mapped_reads/"
    • Sample_*.final.contigs.fixed.bbnorm.sorted.bam
    • Sample_*.final.contigs.fixed.bbnorm.sorted.bam.bai
  • Repeat for all samples

2.5.4.2 Import the mapping information (per Sample) into separate (per Sample) Anvi’o profiles

{Terminal}
cd /DNA_data/work/mapping
anvi-profile -i Sample_107104.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107104_profile/ --sample-name Profile_107104 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107105.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107105_profile/ --sample-name Profile_107105 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107106.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107106_profile/ --sample-name Profile_107106 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107107.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107107_profile/ --sample-name Profile_107107 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107108.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107108_profile/ --sample-name Profile_107108 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107110.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107110_profile/ --sample-name Profile_107110 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107111.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107111_profile/ --sample-name Profile_107111 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107112.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107112_profile/ --sample-name Profile_107112 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107113.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107113_profile/ --sample-name Profile_107113 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107114.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107114_profile/ --sample-name Profile_107114 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107115.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107115_profile/ --sample-name Profile_107115 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107116.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107116_profile/ --sample-name Profile_107116 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107117.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107117_profile/ --sample-name Profile_107117 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107119.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107119_profile/ --sample-name Profile_107119 --min-contig-length 2500 --num-threads 20
anvi-profile -i Sample_107121.final.contigs.fixed.bbnorm.sorted.bam -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o anvio_107121_profile/ --sample-name Profile_107121 --min-contig-length 2500 --num-threads 20

DNA.data.bbnorm.anvio.mapping.profile.pbs (“/DNA_data/work/”) 05:16:51 (day:hr:min)

2.5.4.3 Merge the Sample profiles into a single Anvi’o profile database

  • Rename the “PROFILE.db” within each "anvio_*_profile" directory to include the SampleID
    • “/DNA_data/work/mapping/anvio_107104_profile/”
      • PROFILE_107104.db
    • “/DNA_data/work/mapping/anvio_107105_profile/”
      • PROFILE_107105.db
{Terminal}
cd /DNA_data/work/mapping
anvi-merge anvio_107104_profile/PROFILE_107104.db anvio_107105_profile/PROFILE_107105.db anvio_107106_profile/PROFILE_107106.db anvio_107107_profile/PROFILE_107107.db anvio_107108_profile/PROFILE_107108.db anvio_107110_profile/PROFILE_107110.db anvio_107111_profile/PROFILE_107111.db anvio_107112_profile/PROFILE_107112.db anvio_107113_profile/PROFILE_107113.db anvio_107114_profile/PROFILE_107114.db anvio_107115_profile/PROFILE_107115.db anvio_107116_profile/PROFILE_107116.db anvio_107117_profile/PROFILE_107117.db anvio_107119_profile/PROFILE_107119.db anvio_107121_profile/PROFILE_107121.db -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -o merged_profile/

DNA.data.bbnorm.anvio.mapping.profile.merge.pbs (“/DNA_data/work/”) 01:45 (hr:min)

NOTE: After the profiles were merged, Anvi’o automatically started binning the contigs using CONCOCT. It also attempted to cluster the contigs using its own hierarchical clustering algorithm, but it did NOT generate bins from this clustering information; they were manually drawn later. The clustering algorithm was limited to datasets with 20,000 splits or fewer (which disqualifies most complex assemblies).

  • Results were in a new directory (“DNA_data/work/mapping/merged_profile”) with the following files:
    • AUXILIARY-DATA.db
    • PROFILE.dbThis is the merged profile database
    • RUNLOG.txt

2.6. Binning MAGs

Binning Using Multiple Binning Software Algorithms (Smith: CONCOCT, MetaBAT, DASTool)

The next step is to export the split sequences and their differential coverage across all samples from the merged profile and use these splits in a series of binning algorithms external to Anvi’o.

  • The benefit to doing this is that some algorithm strategies work better for certain organisms over others and there does NOT appear to be a perfect strategy that works best for every organism
  • MetaBAT instructions are ncluded here and supplement the bins derived from CONCOCT through Anvi’o
  • DASTool is then used to chose the best set of non-redundant bins from the multiple binning algorithms

2.6.1 Export Split Sequences and Differential Coverage Data for Binning

  • Use Anvi’o to export the split sequences and differential coverage data necessary for external binners
{Terminal}
cd /DNA_data/work/mapping
anvi-export-splits-and-coverages -p merged_profile/PROFILE.db -o merged_profile/ -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -O DNA_data_bbnorm_assembly --splits-mode

00:05 (hr:min)

  • The following two files will be generated in the “DNA_data/work/mapping/merged_profile” directory:
    • DNA_data_bbnorm_assembly-SPLITS.faContains the split sequences
    • DNA_data_bbnorm_assembly-COVs.txtTab-delimited file containing the average coverage of each split in each sample

2.6.2 Binning Splits with MetaBAT

{Terminal}
cd /DNA_data/work/mapping/merged_profile
comics -- metabat -i DNA_data_bbnorm_assembly-SPLITS.fa -o Bin -a DNA_data_bbnorm_assembly-COVs.txt --minContig 2500 --cvExt -t 20 --saveCls --onlyLabel -v

00:22 (hr:min)

  • The output of MetaBAT will be a “Bin.*” file for each bin that contains a list of the splits assigned to that bin
    • NO bin fasta files are generated – all splits are already saved in the Anvi’o contigs database
  • Create a new directory “DNA_data/work/binning” and within create a MetaBAT directory “DNA_data/work/binning/metabat”
  • Move all “Bin.*” files from the “DNA_data/work/mapping/merged_profile” directory to the “DNA_data/work/binning/metabat” directory

2.6.2.1 Now make the “Metabat_binning_results.txt” file from the MetaBAT output to save it as a collection in Anvi’o

  • Invoking the following shell script in the directory containing the MetaBAT output:
{Terminal}
cd /DNA_data/work/binning/metabat
sh /DNA_data/work/Metabat_to_anvio_parser.sh

00:01 (hr:min)

  • The output will be a tab-delimited text file named “Metabat_binning_results.txt” containing the split names and the bins they have been assigned to

2.6.2.2 Next, import this information into Anvi’o, saving it as the MetaBAT bin collection:

{Terminal}
cd /DNA_data/work/binning/metabat
anvi-import-collection -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -p /DNA_data/work/mapping/merged_profile/PROFILE.db -C METABAT Metabat_binning_results.txt

#Output
Item names in input ..........................: 112,957
Num bins in input ............................: 165
Items in profile database ....................: 131,074
Item names shared between input and db .......: 112,957

WARNING
===============================================
18117 item(s) that were in the database, but were not in the input file, will
not be described by any bin in the collection METABAT. That is totally fine, but
anvi'o hopes that you are aware of that. This means you have more things in your
database than the number of things your input file describes. Here is an example
of something that is in your database but not in any bin in your input file:
k255_691935_flag_1_multi_13.0000_len_2643_split_00001.

Collections ..................................: The collection "METABAT" that describes 112,957 splits and 165 bins has been successfully added to the database at "/DNA_data/work/mapping/merged_profile/PROFILE.db". Here is a list of the first 50 bin names in this collection: Bin_1,Bin_10,Bin_100,Bin_101,Bin_102,Bin_103,Bin_104,Bin_105,Bin_106,Bin_107,Bin_108,Bin_109,Bin_11,Bin_110,Bin_111,Bin_112,Bin_113,Bin_114,Bin_115,Bin_116,Bin_117,Bin_118,Bin_119,Bin_12,Bin_120,Bin_121,Bin_122,Bin_123,Bin_124,Bin_125,Bin_126,Bin_127,Bin_128,Bin_129,Bin_13,Bin_130,Bin_131,Bin_132,Bin_133,Bin_134,Bin_135,Bin_136,Bin_137,Bin_138,Bin_139,Bin_14,Bin_140,Bin_141,Bin_142,Bin_143

00:01 (hr:min)

  • Now there are two bin collections saved in one profile database, preventing redundant copying of sequence data and storing everything in one central location that is easily accessed

2.6.3 Enter this command to view the different collections in the profile database:

{Terminal}
cd /DNA_data/work/mapping/merged_profile
anvi-show-collections-and-bins -p PROFILE.db

#Output
Collection: "CONCOCT"
===============================================
Collection ID ................................: CONCOCT
Number of bins ...............................: 74
Number of splits described ...................: 131,074
Bin names ....................................: Bin_1, Bin_10, Bin_11, Bin_12, Bin_13, Bin_14, Bin_15, Bin_16, Bin_17, Bin_18, Bin_19, Bin_2, Bin_20, Bin_21, Bin_22, Bin_23, Bin_24, Bin_25, Bin_26, Bin_27, Bin_28, Bin_29, Bin_3, Bin_30, Bin_31, Bin_32, Bin_33, Bin_34, Bin_35, Bin_36, Bin_37, Bin_38, Bin_39, Bin_4, Bin_40, Bin_41, Bin_42, Bin_43, Bin_44, Bin_45, Bin_46, Bin_47, Bin_48, Bin_49, Bin_5, Bin_50, Bin_51, Bin_52, Bin_53, Bin_54, Bin_55, Bin_56, Bin_57, Bin_58, Bin_59, Bin_6, Bin_60, Bin_61, Bin_62, Bin_63, Bin_64, Bin_65, Bin_66, Bin_67, Bin_68, Bin_69, Bin_7, Bin_70, Bin_71, Bin_72, Bin_73, Bin_74, Bin_8, Bin_9



Collection: "METABAT"
===============================================
Collection ID ................................: METABAT
Number of bins ...............................: 165
Number of splits described ...................: 112,957
Bin names ....................................: Bin_1, Bin_10, Bin_100, Bin_101, Bin_102, Bin_103, Bin_104, Bin_105, Bin_106, Bin_107, Bin_108, Bin_109, Bin_11, Bin_110, Bin_111, Bin_112, Bin_113, Bin_114, Bin_115, Bin_116, Bin_117, Bin_118, Bin_119, Bin_12, Bin_120, Bin_121, Bin_122, Bin_123, Bin_124, Bin_125, Bin_126, Bin_127, Bin_128, Bin_129, Bin_13, Bin_130, Bin_131, Bin_132, Bin_133, Bin_134, Bin_135, Bin_136, Bin_137, Bin_138, Bin_139, Bin_14, Bin_140, Bin_141, Bin_142, Bin_143, Bin_144, Bin_145, Bin_146, Bin_147, Bin_148, Bin_149, Bin_15, Bin_150, Bin_151, Bin_152, Bin_153, Bin_154, Bin_155, Bin_156, Bin_157, Bin_158, Bin_159, Bin_16, Bin_160, Bin_161, Bin_162, Bin_163, Bin_164, Bin_165, Bin_17, Bin_18, Bin_19, Bin_2, Bin_20, Bin_21, Bin_22, Bin_23, Bin_24, Bin_25, Bin_26, Bin_27, Bin_28, Bin_29, Bin_3, Bin_30, Bin_31, Bin_32, Bin_33, Bin_34, Bin_35, Bin_36, Bin_37, Bin_38, Bin_39, Bin_4, Bin_40, Bin_41, Bin_42, Bin_43, Bin_44, Bin_45, Bin_46, Bin_47, Bin_48, Bin_49, Bin_5, Bin_50, Bin_51, Bin_52, Bin_53, Bin_54, Bin_55, Bin_56, Bin_57, Bin_58, Bin_59, Bin_6, Bin_60, Bin_61, Bin_62, Bin_63, Bin_64, Bin_65, Bin_66, Bin_67, Bin_68, Bin_69, Bin_7, Bin_70, Bin_71, Bin_72, Bin_73, Bin_74, Bin_75, Bin_76, Bin_77, Bin_78, Bin_79, Bin_8, Bin_80, Bin_81, Bin_82, Bin_83, Bin_84, Bin_85, Bin_86, Bin_87, Bin_88, Bin_89, Bin_9, Bin_90, Bin_91, Bin_92, Bin_93, Bin_94, Bin_95, Bin_96, Bin_97, Bin_98, Bin_99
  • Should see a list of bins in two collections, one named “CONCOCT” and another named “METABAT”

2.6.4 DASTools

  • Decide which bins are the best from the two redundant bin datasets (generated with multiple binning algorithms) and dereplicate the bins into a final bin dataset using DASTool
    • The input for DAStool are the same binning results files used to import bin collections into the Anvi’o profile database
  • Get the binning results file for CONCOCT by exporting the information from anvio:
{Terminal}
cd /DNA_data/work/binning/concoct
anvi-export-collection -p /DNA_data/work/mapping/merged_profile/PROFILE.db -C CONCOCT -O CONCOCT_binning_results
  • Create a “DNA_subset/work/binning/dastool” directory
  • Move the CONCOCT and MetaBAT summary text files into the “/dastool” directory
    • CONCOCT_binning_results.txt
    • Metabat_binning_results.txt
  • Now, invoke DASTool
{Terminal}
cd /DNA_data/work/binning/dastool
comics das-tool -i CONCOCT_binning_results.txt,Metabat_binning_results.txt -l concoct,metabat -c /DNA_data/work/mapping/merged_profile/DNA_data_bbnorm_assembly-SPLITS.fa -o DASTool_bins --search_engine blast --threads 20

00:20 (hr:min)

  • The output needed is the “DASTool_bins_DASTool_scaffolds2bin.txt” file (same file structure as previous "*_binning_results.txt" files)
  • Just like before, use the DASTool binning results file to import the DASTool bins as a collection into Anvi’o, but first change some periods to undescores in DASTool bin names (Anvi’o doesn’t like periods):
{Terminal}
sed 's/results\./results_/g' DASTool_bins_DASTool_scaffolds2bin.txt > DASTool_binning_results.txt
sed 's/updated\./updated_/g' DASTool_binning_results.txt > DASTool_binning_results2.txt
mv DASTool_binning_results2.txt DASTool_binning_results.txt
  • Now import the DASTool bin collection into the merged_profile database:
{Terminal}
cd /DNA_data/work/binning/dastool
anvi-import-collection -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -p /DNA_data/work/mapping/merged_profile/PROFILE.db -C DASTool DASTool_binning_results.txt

#Output DASTool
Item names in input ..........................: 31,479
Num bins in input ............................: 58
Items in profile database ....................: 131,074
Item names shared between input and db .......: 31,479

WARNING
===============================================
99595 item(s) that were in the database, but were not in the input file, will
not be described by any bin in the collection DASTool. That is totally fine, but
anvi'o hopes that you are aware of that. This means you have more things in your
database than the number of things your input file describes. Here is an example
of something that is in your database but not in any bin in your input file:
k255_2221878_flag_1_multi_9.0000_len_4003_split_00001.

Collections ..................................: The collection "DASTool" that describes 31,479 splits and 58 bins has been successfully added to the database at "/DNA_data/work/mapping/merged_profile/PROFILE.db". Here is a list of the first 50 bin names in this collection: Metabat_binning_results_011,Metabat_binning_results_090,Metabat_binning_results_136,Metabat_binning_results_071,Metabat_binning_results_027,Metabat_binning_results_163,Metabat_binning_results_142,Metabat_binning_results_074,Metabat_binning_results_031,Metabat_binning_results_106,Metabat_binning_results_056,Metabat_binning_results_089,Metabat_binning_results_078,CONCOCT_binning_results_070,Metabat_binning_results_046,CONCOCT_binning_results_062,Metabat_binning_results_064,Metabat_binning_results_110,Metabat_binning_results_083,Metabat_binning_results_159,Metabat_binning_results_132,Metabat_binning_results_055,Metabat_binning_results_073,Metabat_binning_results_080,Metabat_binning_results_160,Metabat_binning_results_081,CONCOCT_binning_results_023,Metabat_binning_results_044,Metabat_binning_results_153,CONCOCT_binning_results_060,Metabat_binning_results_161,Metabat_binning_results_148,Metabat_binning_results_060,Metabat_binning_results_068,Metabat_binning_results_137,Metabat_binning_results_032,Metabat_binning_results_145,Metabat_binning_results_033,Metabat_binning_results_165,CONCOCT_binning_results_053,CONCOCT_binning_results_055,Metabat_binning_results_029,Metabat_binning_results_036,Metabat_binning_results_088,Metabat_binning_results_069,CONCOCT_binning_results_056,Metabat_binning_results_014,Metabat_binning_results_024,Metabat_binning_results_023,CONCOCT_binning_results_071.
  • The final step is to export the bin stats summary file for DASTools
{Terminal}
cd /DNA_data/work/binning/dastool
anvi-script-get-collection-info -c /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db -p /DNA_data/work/mapping/merged_profile/PROFILE.db -C DASTool -o DNA_data_bbnorm_DASTool_summary.txt

#Output
Contigs DB ...................................: Initialized: /DNA_data/work/co_assembly/DNA_data_bbnorm_anvio_contigs.db (v. 12)

* Completion and redundancy estimates. PC: Percent completion; PR: Percent
redundancy; N: Number of splits; L: Length (total number of nucleotides); D:
Domain for single-copy core genes; C: Domain confidence.


Bins in collection "DASTool"
===============================================
Metabat_binning_results_011 :: PC: 93.53%, PR: 3.60%, N: 352, L: 3,138,665, D: bacteria (C: 0.90)
Metabat_binning_results_090 :: PC: 98.56%, PR: 6.47%, N: 1,023, L: 6,681,655, D: bacteria (C: 0.92)

Metabat_binning_results_136 :: PC: 91.36%, PR: 10.49%, N: 221, L: 1,613,215, D: archaea (C: 0.81)

Metabat_binning_results_071 :: PC: 97.12%, PR: 0.72%, N: 378, L: 2,723,137, D: bacteria (C: 0.96)
Metabat_binning_results_027 :: PC: 88.49%, PR: 3.60%, N: 382, L: 2,641,710, D: bacteria (C: 0.85)
Metabat_binning_results_163 :: PC: 89.93%, PR: 6.47%, N: 1,093, L: 5,731,451, D: bacteria (C: 0.83)
Metabat_binning_results_142 :: PC: 80.58%, PR: 3.60%, N: 575, L: 3,918,295, D: bacteria (C: 0.77)

Metabat_binning_results_074 :: PC: 89.93%, PR: 10.07%, N: 758, L: 3,672,582, D: bacteria (C: 0.80)

Metabat_binning_results_031 :: PC: 92.81%, PR: 9.35%, N: 540, L: 2,714,627, D: bacteria (C: 0.83)
Metabat_binning_results_106 :: PC: 87.77%, PR: 2.16%, N: 426, L: 2,639,223, D: bacteria (C: 0.86)
Metabat_binning_results_056 :: PC: 90.65%, PR: 3.60%, N: 295, L: 2,133,681, D: bacteria (C: 0.87)
Metabat_binning_results_089 :: PC: 95.68%, PR: 2.88%, N: 622, L: 4,758,373, D: bacteria (C: 0.93)
Metabat_binning_results_078 :: PC: 84.89%, PR: 5.76%, N: 463, L: 3,046,540, D: bacteria (C: 0.79)
CONCOCT_binning_results_070 :: PC: 82.73%, PR: 2.16%, N: 286, L: 1,851,259, D: bacteria (C: 0.81)
Metabat_binning_results_046 :: PC: 88.89%, PR: 9.26%, N: 206, L: 1,536,975, D: archaea (C: 0.80)
CONCOCT_binning_results_062 :: PC: 82.01%, PR: 0.72%, N: 160, L: 1,468,490, D: bacteria (C: 0.81)
Metabat_binning_results_064 :: PC: 94.96%, PR: 5.04%, N: 537, L: 3,258,934, D: bacteria (C: 0.90)
Metabat_binning_results_110 :: PC: 74.82%, PR: 7.91%, N: 298, L: 1,408,896, D: bacteria (C: 0.67)
Metabat_binning_results_083 :: PC: 82.01%, PR: 6.47%, N: 331, L: 2,095,666, D: bacteria (C: 0.76)
Metabat_binning_results_159 :: PC: 90.65%, PR: 9.35%, N: 967, L: 5,724,953, D: bacteria (C: 0.81)
Metabat_binning_results_132 :: PC: 85.61%, PR: 5.04%, N: 939, L: 6,046,501, D: bacteria (C: 0.81)

Metabat_binning_results_055 :: PC: 83.45%, PR: 10.07%, N: 882, L: 6,560,778, D: bacteria (C: 0.73)

Metabat_binning_results_073 :: PC: 76.98%, PR: 5.04%, N: 375, L: 2,246,106, D: bacteria (C: 0.72)
Metabat_binning_results_080 :: PC: 71.94%, PR: 3.60%, N: 425, L: 2,414,552, D: bacteria (C: 0.68)

Metabat_binning_results_160 :: PC: 81.29%, PR: 12.95%, N: 1,198, L: 6,308,300, D: bacteria (C: 0.68)
Metabat_binning_results_081 :: PC: 92.09%, PR: 28.78%, N: 410, L: 2,897,091, D: bacteria (C: 0.63)

CONCOCT_binning_results_023 :: PC: 82.01%, PR: 4.32%, N: 251, L: 2,614,541, D: bacteria (C: 0.78)
Metabat_binning_results_044 :: PC: 74.10%, PR: 5.04%, N: 921, L: 4,823,662, D: bacteria (C: 0.69)

Metabat_binning_results_153 :: PC: 95.68%, PR: 23.02%, N: 500, L: 4,519,044, D: bacteria (C: 0.73)

CONCOCT_binning_results_060 :: PC: 64.03%, PR: 3.60%, N: 1,040, L: 6,178,783, D: bacteria (C: 0.60)

Metabat_binning_results_161 :: PC: 74.82%, PR: 7.19%, N: 578, L: 2,580,286, D: bacteria (C: 0.68)
Metabat_binning_results_148 :: PC: 74.10%, PR: 2.16%, N: 629, L: 2,786,980, D: bacteria (C: 0.72)
Metabat_binning_results_060 :: PC: 74.82%, PR: 10.79%, N: 1,144, L: 7,848,862, D: bacteria (C: 0.64)
Metabat_binning_results_068 :: PC: 95.68%, PR: 20.14%, N: 315, L: 2,011,285, D: bacteria (C: 0.76)
Metabat_binning_results_137 :: PC: 78.42%, PR: 5.04%, N: 627, L: 2,870,570, D: bacteria (C: 0.73)
Metabat_binning_results_032 :: PC: 83.45%, PR: 11.51%, N: 403, L: 2,158,177, D: bacteria (C: 0.72)
Metabat_binning_results_145 :: PC: 61.15%, PR: 0.72%, N: 292, L: 1,433,337, D: bacteria (C: 0.60)
Metabat_binning_results_033 :: PC: 65.47%, PR: 12.23%, N: 447, L: 1,848,022, D: bacteria (C: 0.53)
Metabat_binning_results_165 :: PC: 84.17%, PR: 9.35%, N: 742, L: 5,587,269, D: bacteria (C: 0.75)
CONCOCT_binning_results_053 :: PC: 76.26%, PR: 5.04%, N: 690, L: 3,224,356, D: bacteria (C: 0.71)
CONCOCT_binning_results_055 :: PC: 51.08%, PR: 1.44%, N: 639, L: 2,558,984, D: bacteria (C: 0.50)
Metabat_binning_results_029 :: PC: 72.66%, PR: 5.04%, N: 431, L: 2,187,888, D: bacteria (C: 0.68)
Metabat_binning_results_036 :: PC: 97.12%, PR: 28.06%, N: 940, L: 5,554,480, D: bacteria (C: 0.69)
Metabat_binning_results_088 :: PC: 47.48%, PR: 0.72%, N: 137, L: 581,347, D: bacteria (C: 0.47)
Metabat_binning_results_069 :: PC: 55.40%, PR: 0.00%, N: 208, L: 1,986,284, D: bacteria (C: 0.55)
CONCOCT_binning_results_056 :: PC: 69.06%, PR: 5.04%, N: 1,111, L: 5,337,967, D: bacteria (C: 0.64)
Metabat_binning_results_014 :: PC: 65.47%, PR: 5.76%, N: 445, L: 1,921,245, D: bacteria (C: 0.60)
Metabat_binning_results_024 :: PC: 61.15%, PR: 4.32%, N: 623, L: 2,618,168, D: bacteria (C: 0.57)
Metabat_binning_results_023 :: PC: 56.12%, PR: 2.16%, N: 441, L: 2,195,523, D: bacteria (C: 0.54)
CONCOCT_binning_results_071 :: PC: 54.68%, PR: 4.32%, N: 228, L: 1,652,688, D: bacteria (C: 0.50)
Metabat_binning_results_070 :: PC: 62.59%, PR: 2.88%, N: 435, L: 1,788,235, D: bacteria (C: 0.60)
Metabat_binning_results_098 :: PC: 37.41%, PR: 2.88%, N: 536, L: 1,991,384, D: bacteria (C: 0.35)
Metabat_binning_results_051 :: PC: 83.45%, PR: 7.91%, N: 248, L: 1,789,108, D: bacteria (C: 0.76)
Metabat_binning_results_164 :: PC: 60.43%, PR: 1.44%, N: 338, L: 1,807,394, D: bacteria (C: 0.59)
Metabat_binning_results_012 :: PC: 43.88%, PR: 5.76%, N: 173, L: 774,389, D: bacteria (C: 0.38)
Metabat_binning_results_155 :: PC: 49.64%, PR: 3.60%, N: 671, L: 2,670,480, D: bacteria (C: 0.46)
Metabat_binning_results_043 :: PC: 38.85%, PR: 2.16%, N: 474, L: 1,863,523, D: bacteria (C: 0.37)
Metabat_binning_results_085 :: PC: 66.19%, PR: 10.79%, N: 680, L: 4,255,822, D: bacteria (C: 0.55)

Output .......................................: DNA_data_bbnorm_DASTool_summary.txt
  • Now, select only those bins that are > 70% complete and < 10% redundant as the final Metagenome Assembled Genomes (MAGs) dataset
{Terminal}
Bins in collection "DASTool" to keep (PC > 70% | PR < 10%) -- 30 Bins
==========================================================
Metabat_binning_results_011 :: PC: 93.53%, PR: 3.60%, N: 352, L: 3,138,665, D: bacteria (C: 0.90)
Metabat_binning_results_090 :: PC: 98.56%, PR: 6.47%, N: 1,023, L: 6,681,655, D: bacteria (C: 0.92)
Metabat_binning_results_071 :: PC: 97.12%, PR: 0.72%, N: 378, L: 2,723,137, D: bacteria (C: 0.96)
Metabat_binning_results_027 :: PC: 88.49%, PR: 3.60%, N: 382, L: 2,641,710, D: bacteria (C: 0.85)
Metabat_binning_results_163 :: PC: 89.93%, PR: 6.47%, N: 1,093, L: 5,731,451, D: bacteria (C: 0.83)
Metabat_binning_results_142 :: PC: 80.58%, PR: 3.60%, N: 575, L: 3,918,295, D: bacteria (C: 0.77)
Metabat_binning_results_031 :: PC: 92.81%, PR: 9.35%, N: 540, L: 2,714,627, D: bacteria (C: 0.83)
Metabat_binning_results_106 :: PC: 87.77%, PR: 2.16%, N: 426, L: 2,639,223, D: bacteria (C: 0.86)
Metabat_binning_results_056 :: PC: 90.65%, PR: 3.60%, N: 295, L: 2,133,681, D: bacteria (C: 0.87)
Metabat_binning_results_089 :: PC: 95.68%, PR: 2.88%, N: 622, L: 4,758,373, D: bacteria (C: 0.93)
Metabat_binning_results_078 :: PC: 84.89%, PR: 5.76%, N: 463, L: 3,046,540, D: bacteria (C: 0.79)
CONCOCT_binning_results_070 :: PC: 82.73%, PR: 2.16%, N: 286, L: 1,851,259, D: bacteria (C: 0.81)
Metabat_binning_results_046 :: PC: 88.89%, PR: 9.26%, N: 206, L: 1,536,975, D: archaea (C: 0.80)
CONCOCT_binning_results_062 :: PC: 82.01%, PR: 0.72%, N: 160, L: 1,468,490, D: bacteria (C: 0.81)
Metabat_binning_results_064 :: PC: 94.96%, PR: 5.04%, N: 537, L: 3,258,934, D: bacteria (C: 0.90)
Metabat_binning_results_110 :: PC: 74.82%, PR: 7.91%, N: 298, L: 1,408,896, D: bacteria (C: 0.67)
Metabat_binning_results_083 :: PC: 82.01%, PR: 6.47%, N: 331, L: 2,095,666, D: bacteria (C: 0.76)
Metabat_binning_results_159 :: PC: 90.65%, PR: 9.35%, N: 967, L: 5,724,953, D: bacteria (C: 0.81)
Metabat_binning_results_132 :: PC: 85.61%, PR: 5.04%, N: 939, L: 6,046,501, D: bacteria (C: 0.81)
Metabat_binning_results_073 :: PC: 76.98%, PR: 5.04%, N: 375, L: 2,246,106, D: bacteria (C: 0.72)
Metabat_binning_results_080 :: PC: 71.94%, PR: 3.60%, N: 425, L: 2,414,552, D: bacteria (C: 0.68)
CONCOCT_binning_results_023 :: PC: 82.01%, PR: 4.32%, N: 251, L: 2,614,541, D: bacteria (C: 0.78)
Metabat_binning_results_044 :: PC: 74.10%, PR: 5.04%, N: 921, L: 4,823,662, D: bacteria (C: 0.69)
Metabat_binning_results_161 :: PC: 74.82%, PR: 7.19%, N: 578, L: 2,580,286, D: bacteria (C: 0.68)
Metabat_binning_results_148 :: PC: 74.10%, PR: 2.16%, N: 629, L: 2,786,980, D: bacteria (C: 0.72)
Metabat_binning_results_137 :: PC: 78.42%, PR: 5.04%, N: 627, L: 2,870,570, D: bacteria (C: 0.73)
Metabat_binning_results_165 :: PC: 84.17%, PR: 9.35%, N: 742, L: 5,587,269, D: bacteria (C: 0.75)
CONCOCT_binning_results_053 :: PC: 76.26%, PR: 5.04%, N: 690, L: 3,224,356, D: bacteria (C: 0.71)
Metabat_binning_results_029 :: PC: 72.66%, PR: 5.04%, N: 431, L: 2,187,888, D: bacteria (C: 0.68)
Metabat_binning_results_051 :: PC: 83.45%, PR: 7.91%, N: 248, L: 1,789,108, D: bacteria (C: 0.76)

2.6.5 DASTools MAGs Taxonomy

  • Now that we’ve generated the DASTools MAGS collection, our final steps involve assigning taxonomy to each MAG and calculating the relative abundance of each MAG in each metagenome sample. The following commands only work with Anvio v6.2.
{Terminal}
# Downloading taxonomy search databases (only need to do once)
anvi-setup-scg-databases

# Update contigs database from v12 to v14 (necessary for assigning taxonomy)
anvi-migrate /2017_Redox/MAGs_DNA/DNA_data_bbnorm_anvio_contigs.db

# Update profile from v30 to v31 (necessary for assigning taxonomy)
anvi-migrate /2017_Redox/MAGs_DNA/PROFILE.db

# Populate tables with HMM hits (since they will be removed when updating the contigs db from v12 to v14 -- see above)
anvi-run-hmms -c /2017_Redox/MAGs_DNA/DNA_data_bbnorm_anvio_contigs.db

# Populating contigs db with SCG taxonomy
anvi-run-scg-taxonomy -c /2017_Redox/MAGs_DNA/DNA_data_bbnorm_anvio_contigs.db

# Estimate taxonomy based on single-copy core genes (SCG) within each MAG
anvi-estimate-scg-taxonomy -c /2017_Redox/MAGs_DNA/DNA_data_bbnorm_anvio_contigs.db \
                           -p /2017_Redox/MAGs_DNA/PROFILE.db \
                           -C DASTool \
                           --compute-scg-coverages \
                           --output-file /MAGs.taxa.output.txt
                           
### Output
Contigs DB ...................................: /gpfs/accounts/gwk_root/gwk1/kjromano/2017_Redox/MAGs_DNA/DNA_data_bbnorm_anvio_contigs.db                                                                                                      
Profile DB ...................................: /gpfs/accounts/gwk_root/gwk1/kjromano/2017_Redox/MAGs_DNA/PROFILE.db
Metagenome mode ..............................: False
                                                                                                                                                                                                                                                
WARNING
===============================================
Please note that anvi'o found 2,464,202 splits in your contigs database. But
only 131,074 of them appeared to be in the profile database. As a result, anvi'o
will now remove the 2,333,128 splits that occur only in the contigs db from all
downstream analyses here (if you didn't use the flag `--compute-scg-coverages`
this wouldn't have been necessary, but with the current settings this is really
the best for everyone). Where is this difference coming from though? Well. This
is often the case because the 'minimum contig length parameter' set during the
`anvi-profile` step can exclude many contigs from downstream analyses (often for
good reasons, too). For instance, in your case the minimum contig length goes as
low as 256 nts in your contigs database. Yet, the minimum contig length set in
the profile databaes is 2,500 nts. Hence the difference. Anvi'o hopes that this
explaines some things.

                                                                                                                                                                                                                                                
* 31,479 split names associated with 58 bins of in collection 'DASTool' have been
successfully recovered 🎊
                                                                                                                                                                                                                                                
* Anvi'o will now attempt to recover SCG coverages in GENOME MODE from the profile
database, which contains 15 samples.

                                                                                                                                                                                                                                                
FRIENDLY REMINDER
===============================================
Anvi'o has just finished recovering SCG coverages from the profile database to
estimate the average coverage of your bins across your samples. Please note that
anvi'o SCG taxonomy framework is using only %d SCGs to estimate taxonomy. Which
means, even a highly complete bin may be missing all of them. In which case, the
coverage of that bin will be `None` across all your samples. The best way to
prevent any misleading insights is take these results with a huge grain of salt,
and use the `anvi-summarize` output for critical applications.

                                                                                                                                                                                                                                                
Estimated taxonomy for collection "DASTool"
===============================================

Output file ..................................: /MAGs.taxa.output.txt

✓ anvi-estimate-scg-taxonomy took 0:02:23.726746

2.7. MG Read Summary

The following table is a summary of the DNA reads by sample and includes QC Reads, Mapped Reads, and Average Read Length (bp). All values were derived from the “Sample_*.final.contigs.fixed.bbnorm.sorted.bam” files using samtools stats.

Summary statistics for DNA-based metagenomic sequencing dataset
ID Tundra Time Replicate QC Reads Mapped Reads Average Length (bp)
S107107 Tussock T0 1 65,667,254 19,628,380 141
S107108 Tussock T0 2 43,020,594 12,528,861 141
S107116 Tussock T4 1 12,312,448 3,372,508 141
S107117 Tussock T4 2 36,565,234 10,628,986 141
S107119 Tussock T24 1 47,853,114 11,451,168 141
S107121 Tussock T24 3 27,632,452 4,767,927 141
S107104 Wet Sedge T0 1 34,568,010 15,458,362 139
S107105 Wet Sedge T0 2 24,408,724 12,419,993 140
S107106 Wet Sedge T0 3 25,734,316 7,180,169 141
S107110 Wet Sedge T4 1 29,338,238 13,910,613 140
S107111 Wet Sedge T4 2 41,991,856 17,433,511 141
S107112 Wet Sedge T4 3 35,302,148 8,871,426 141
S107113 Wet Sedge T24 1 36,956,594 14,967,853 141
S107114 Wet Sedge T24 2 33,190,654 15,997,334 140
S107115 Wet Sedge T24 3 57,805,778 12,782,304 141

3. Gene Annotations

Following all Data Bioinformatics steps above, quality-controlled metagenome reads were extracted using BBMap to generate pile-up files (average read depth per gene), and SAMtools was used to extract counts and CDS lengths from the BBMap output.

3.1. Import Gene Counts

In this section, all DNA.pileup files are imported into the R environment and combined into the first FULL dataset to be further formatted for downstream statistical analysis.

3.1.1. DNA PileUp Files

The following DNA.pileup files (average read depth per gene) for each metagenome sample were generated via the BBMap module.

#S107104 -- WS_T0_R1
pileup_107104<-read.table("Pileup.Data/DNA.Pileup/Sample_107104_DNA.pileup", header = TRUE)
pileup_107104$S107104 <- pileup_107104$Plus_reads + pileup_107104$Minus_reads

#S107105 -- WS_T0_R2
pileup_107105<-read.table("Pileup.Data/DNA.Pileup/Sample_107105_DNA.pileup", header = TRUE)
pileup_107105$S107105 <- pileup_107105$Plus_reads + pileup_107105$Minus_reads

#S107106 -- WS_T0_R3
pileup_107106<-read.table("Pileup.Data/DNA.Pileup/Sample_107106_DNA.pileup", header = TRUE)
pileup_107106$S107106 <- pileup_107106$Plus_reads + pileup_107106$Minus_reads

#S107110 -- WS_T4_R1
pileup_107110<-read.table("Pileup.Data/DNA.Pileup/Sample_107110_DNA.pileup", header = TRUE)
pileup_107110$S107110 <- pileup_107110$Plus_reads + pileup_107110$Minus_reads

#S107111 -- WS_T4_R2
pileup_107111<-read.table("Pileup.Data/DNA.Pileup/Sample_107111_DNA.pileup", header = TRUE)
pileup_107111$S107111 <- pileup_107111$Plus_reads + pileup_107111$Minus_reads

#S107112 -- WS_T4_R3
pileup_107112<-read.table("Pileup.Data/DNA.Pileup/Sample_107112_DNA.pileup", header = TRUE)
pileup_107112$S107112 <- pileup_107112$Plus_reads + pileup_107112$Minus_reads

#S107113 -- WS_T24_R1
pileup_107113<-read.table("Pileup.Data/DNA.Pileup/Sample_107113_DNA.pileup", header = TRUE)
pileup_107113$S107113 <- pileup_107113$Plus_reads + pileup_107113$Minus_reads

#S107114 -- WS_T24_R2
pileup_107114<-read.table("Pileup.Data/DNA.Pileup/Sample_107114_DNA.pileup", header = TRUE)
pileup_107114$S107114 <- pileup_107114$Plus_reads + pileup_107114$Minus_reads

#S107115 -- WS_T24_R3
pileup_107115<-read.table("Pileup.Data/DNA.Pileup/Sample_107115_DNA.pileup", header = TRUE)
pileup_107115$S107115 <- pileup_107115$Plus_reads + pileup_107115$Minus_reads

#S107107 -- Tuss_T0_R1
pileup_107107<-read.table("Pileup.Data/DNA.Pileup/Sample_107107_DNA.pileup", header = TRUE)
pileup_107107$S107107 <- pileup_107107$Plus_reads + pileup_107107$Minus_reads

#S107108 -- Tuss_T0_R2
pileup_107108<-read.table("Pileup.Data/DNA.Pileup/Sample_107108_DNA.pileup", header = TRUE)
pileup_107108$S107108 <- pileup_107108$Plus_reads + pileup_107108$Minus_reads

#S107116 -- Tuss_T4_R1
pileup_107116<-read.table("Pileup.Data/DNA.Pileup/Sample_107116_DNA.pileup", header = TRUE)
pileup_107116$S107116 <- pileup_107116$Plus_reads + pileup_107116$Minus_reads

#S107117 -- Tuss_T4_R2
pileup_107117<-read.table("Pileup.Data/DNA.Pileup/Sample_107117_DNA.pileup", header = TRUE)
pileup_107117$S107117 <- pileup_107117$Plus_reads + pileup_107117$Minus_reads

#S107119 -- Tuss_T24_R1
pileup_107119<-read.table("Pileup.Data/DNA.Pileup/Sample_107119_DNA.pileup", header = TRUE)
pileup_107119$S107119 <- pileup_107119$Plus_reads + pileup_107119$Minus_reads

#S107121 -- Tuss_T24_R3
pileup_107121<-read.table("Pileup.Data/DNA.Pileup/Sample_107121_DNA.pileup", header = TRUE)
pileup_107121$S107121 <- pileup_107121$Plus_reads + pileup_107121$Minus_reads

3.1.2. Full DNA Dataset

In the previous step, each DNA.pileup file was imported and an additional column was added that summed the “Plus_reads” and the Minus_reads. The sum column in each DNA.pileup file was named after the DNA.pileup sample name (e.g. “S108379”). All DNA.pileup files contain identical genecalls in an identical order allowing us to extract the genecall ID and genecall Length columns from a single sample (S107104), along with the summed count column of each sample, to create a new dataframe that represents the initial, FULL dataset for downstream analyses:

cts_dna_all <- data.frame(pileup_107104$ID, pileup_107104$Length, pileup_107104$S107104, pileup_107105$S107105, pileup_107106$S107106, pileup_107110$S107110, pileup_107111$S107111, pileup_107112$S107112, pileup_107113$S107113, pileup_107114$S107114, pileup_107115$S107115, pileup_107107$S107107, pileup_107108$S107108, pileup_107116$S107116, pileup_107117$S107117, pileup_107119$S107119, pileup_107121$S107121)

names(cts_dna_all) <- c("ID", "Length", "S107104", "S107105", "S107106", "S107110", "S107111", "S107112", "S107113", "S107114", "S107115", "S107107", "S107108", "S107116", "S107117", "S107119", "S107121")

3.2. Import Gene Annotations

The KEGG Functions file (GhostKoala) and KEGG Taxonomy file (GhostKoala) were imported and the functional and taxonomic annotations were matched to their corresponding genecall ID.

3.2.1. KEGG Reference

First, a KEGG reference file was imported with additional KEGG Tier pathways that provide additional, useful, functional categories for downstream analyses. The Tier II, III, and IV categories were merged to the GhostKoala KEGG functional annotations in subsequent steps.

# Import KO_Orthology.txt reference file
KO_ref<-read.table(file='Annotations.Data/KO_Orthology.txt', sep='\t', quote="", fill=TRUE, header = FALSE)

# Rename column headers
names(KO_ref)<-c("Tier_II","Tier_III","Tier_IV","KEGG")

# Separate "KEGG" column into "KO" and "Annotation" columns
KO_ref<-KO_ref %>% separate(KEGG, c("KO_Accession","Annotation"), " ", extra="merge")

# Further separatae "Annotation" column into "Symbol" and "Function" columns
KO_ref<-KO_ref %>% separate(Annotation, c("KO_Symbol","KO_Function"), "; ", extra="merge")

3.2.2. KEGG Functions

There are 3,917,616 total unique DNA-based genecalls in the metagenomic dataset. The GhostKOALA KEGG functional annotations file (“DNA_data_bbnorm_anvio_contigs_annotations.tsv”) contains annotations for 1,389,518 unique DNA-based genecalls. This indicates that 35.5% of the total unique DNA-based genecalls can be functionally annotated. That also means that 64.5% of unique DNA-based genecalls cannot be annotated and will not be included in downstream analyses. Here, the unique genecall functional annotations will be matched to the same unique genecalls in the DNA-based metagenomic dataset.

# Import the KEGG Functional Annotations file that was exported from the Anvi'o DNA contigs database
KeggAnvio<-read.table(file='Annotations.Data/DNA_data_bbnorm_anvio_contigs_annotations.tsv', sep='\t', quote = "", fill = TRUE, header = TRUE)

# Rename column headers
names(KeggAnvio)<-c("ID","Source","Accession","Function","e-value")

# Separate "Function" column into "Symbol" and "Function" columns
KeggAnvio<-KeggAnvio %>% separate(Function, c("Symbol","Function"), "; ", extra="merge")

# Add "genecall_" to the beginning of each gene ID value to match with downstream analyses
KeggAnvio$ID <- paste("genecall", KeggAnvio$ID, sep="_")

# Add "KO_Symbol" category to the dataset, matched by KO's between the KO_ref file and KeggAnvio
KeggAnvio$KO_Symbol = KO_ref[match(KeggAnvio$Accession, KO_ref$KO_Accession), "KO_Symbol"]

# Add "KO_Function" category to the dataset, matched by KO's between the KO_ref file and KeggAnvio
KeggAnvio$KO_Function = KO_ref[match(KeggAnvio$Accession, KO_ref$KO_Accession), "KO_Function"]

# Add "Tier_II" category to the dataset, matched by KO's between the KO_ref file and KeggAnvio
KeggAnvio$Tier_II = KO_ref[match(KeggAnvio$Accession, KO_ref$KO_Accession), "Tier_II"]

# Add "Tier_III" category to the dataset, matched by KO's between the KO_ref file and KeggAnvio
KeggAnvio$Tier_III = KO_ref[match(KeggAnvio$Accession, KO_ref$KO_Accession), "Tier_III"]

# Add "Tier_IV" category to the dataset, matched by KO's between the KO_ref file and KeggAnvio
KeggAnvio$Tier_IV = KO_ref[match(KeggAnvio$Accession, KO_ref$KO_Accession), "Tier_IV"]

# Keep the Function category from the KO Reference file to potentially fill in gaps in KeggAnvio annotations (many KO's labeled as "None", but the KO should match a known function from the reference file).
KeggFunction<-data.frame(KeggAnvio$ID,KeggAnvio$Accession,KeggAnvio$Symbol,KeggAnvio$KO_Function,KeggAnvio$Tier_II,KeggAnvio$Tier_III,KeggAnvio$Tier_IV)
names(KeggFunction)<-c("ID","KO","Symbol","Function","Tier_II","Tier_III","Tier_IV")
  
# Merge the KO, Symbol, Function, and all Tier columns into single "Combined" column for some downstream analyses
KeggFunction$Combined<-paste(KeggFunction$KO, ":", KeggFunction$Symbol, ":", KeggFunction$Function, ":", KeggFunction$Tier_II, ":", KeggFunction$Tier_III, ":", KeggFunction$Tier_IV)

# Keep just "ID" and "Combined" columns for use with some downstream analyses
KeggData<-data.frame(KeggFunction$ID, KeggFunction$Combined)
names(KeggData)<-c("ID","KEGG")

3.2.3. KEGG Taxonomy

There are 3,917,616 total unique DNA-based genecalls in the metagenomic dataset. The GhostKoala KEGG taxonomy file (“KeggTaxonomy.txt”) contains annotations for 3,912,253 unique DNA-based genecalls. This indicates that 99.9% of the total unique DNA-based genecalls can be taxonomically annotated. Here, the unique genecall taxonomic annotations will be matched to the same unique genecalls in the DNA-based metagenomic dataset.

#Import KeggTaxonomy.txt from GhostKoala
KeggTaxa<-read.table("Annotations.Data/KeggTaxonomy.txt", header = TRUE, fill = TRUE)
names(KeggTaxa)<-c("ID","Domain","Phylum","Class","Order","Family","Genus","Species")

# Merge the taxonomic classes into a single column
KeggTaxa$Taxonomy <- paste(KeggTaxa$Domain, ":", KeggTaxa$Phylum, ":", KeggTaxa$Class, ":", KeggTaxa$Order, ":", KeggTaxa$Family, ":", KeggTaxa$Genus, ":", KeggTaxa$Species)

# Now keep just "ID" and "Taxonomy"
KeggTaxa <- data.frame(KeggTaxa$ID, KeggTaxa$Taxonomy)
names(KeggTaxa)<-c("ID","Taxonomy")

# Add "genecall_" to the beginning of each gene ID value to match with downstream analyses
KeggTaxa$ID<-paste("genecall", KeggTaxa$ID, sep="_")

4. Gene Filtering

The FULL DNA CTS dataset was assembled as a single dataframe (columns: [1] genecall, [2] length, [3-14] metagenome Samples; rows: 3,917,616 unique “genecalls”). Now, retain only those genecalls with a value greater than zero in any single sample. This indicates that these genes were present under at least ONE treatment in the experiment (i.e., potential expression).

4.1. Potential Genes

Subsample the unique genecalls that have greater than zero raw read counts (“Potential Genes”) across all samples.

#cts_dna_potential
cts_dna_potential <- subset(cts_dna_all, S107104 > 0 | S107105 > 0 | S107106 > 0 | S107110 > 0 | S107111 > 0 | S107112 > 0 | S107113 > 0 | S107114 > 0 | S107115 > 0 | S107107 > 0 | S107108 > 0 | S107116 > 0 | S107117 > 0 | S107119 > 0 | S107121 > 0, select=c(ID,Length,S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115,S107107,S107108,S107116,S107117,S107119,S107121))

Add functional and taxonomic annotations to each unique genecall within the “Potential” subdata.

# Potential Genes Functional and Taxonomic Annotations
cts_dna_potential$KEGG = KeggData[match(cts_dna_potential$ID, KeggData$ID), "KEGG"]
cts_dna_potential$Taxonomy = KeggTaxa[match(cts_dna_potential$ID, KeggTaxa$ID), "Taxonomy"]

# Potential Annotated Genes
cts_dna_pot_ann<-na.omit(cts_dna_potential, cols="KEGG")

4.2. Potential Annotated Genes

From this point, we retain only those genecalls that were potentially expressed and have a KEGG functional annotation. Start by separating the KEGG categories into unique columns. Remove any genecall whose symbol annotation is “None”. Further remove any genecall annotated as Tier II “Organismal Systems” or “Human Diseases”.

# Separate "KEGG" column into "KO", "Symbol", "Function", "Tier_II", "Tier_III", and "Tier_IV" columns
cts_dna_pot_ann<-cts_dna_pot_ann %>% separate(KEGG, c("KO","Symbol","Function","Tier_II","Tier_III","Tier_IV"), ": ", extra="merge")

# Remove KO's with "None" as the "Symbol" annotation
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("None", cts_dna_pot_ann$Symbol),]

# Remove KO's with Tier II category "Organismal Systems"
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("Organismal Systems ", cts_dna_pot_ann$Tier_II),]

# Remove KO's with Tier II category "Human Diseases"
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("Human Diseases ", cts_dna_pot_ann$Tier_II),]

Separate the Taxonomy categories into unique columns. Remove any genecall whose taxonomy is outside of “Archaea”, “Bacteria”, or “Fungi”.

# Separate "Taxonomy" column into "Kingdom", "Phylum", "Class", "Order", "Family", "Genus", and "Species" columns
cts_dna_pot_ann<-cts_dna_pot_ann %>% separate(Taxonomy, c("Kingdom","Phylum","Class","Order","Family","Genus","Species"), ": ", extra="merge")

# Remove KO's with "ag" as the "Kingdom" annotation
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("ag", cts_dna_pot_ann$Kingdom),]

# Remove KO's with "Animals" as the "Kingdom" annotation
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("Animals", cts_dna_pot_ann$Kingdom),]

# Remove KO's with "Plants" as the "Kingdom" annotation
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("Plants", cts_dna_pot_ann$Kingdom),]

# Remove KO's with "Protists" as the "Kingdom" annotation
cts_dna_pot_ann<-cts_dna_pot_ann[!grepl("Protists", cts_dna_pot_ann$Kingdom),]

#Re-merge the Taxonomy columns for downstream analysis
cts_dna_pot_ann$Taxonomy <- paste(cts_dna_pot_ann$Kingdom, ":", cts_dna_pot_ann$Phylum, ":", cts_dna_pot_ann$Class, ":", cts_dna_pot_ann$Order, ":", cts_dna_pot_ann$Family, ":", cts_dna_pot_ann$Genus, ":", cts_dna_pot_ann$Species)

5. Gene Normalization

GPM Normalization: Converts raw DNA gene counts to Genes per Million. GPM follows the same methds as TPM (Transcripts per Million) described by Wagner et al. 2012 and used to normalize RNA gene counts in the metatranscriptomes section below.

  1. Calculate Tg: Tg = Read Count x Average Read Length / Gene Length
    • Read Count: number of reads mapped to each unique genecall
    • Average Read Length: Average read length (between 139-141 bp) within each sample from sequences that passed QC
    • Gene Length: Length of each unique genecall
  2. Convert Tg into GPM by sample: GPM = Tg x 1e+06 / sum(Tg)
    • The sum of GPM values in each sample will equal 1,000,000

5.1. Calculate Tg Values

Calculate Tg values by multiplying the read count of each genecall by the average read length within each sample, then divide by the gene length of each genecall.

cts_dna_pot_ann$S107104_Tg<-(cts_dna_pot_ann$S107104 * 139) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107105_Tg<-(cts_dna_pot_ann$S107105 * 140) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107106_Tg<-(cts_dna_pot_ann$S107106 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107110_Tg<-(cts_dna_pot_ann$S107110 * 140) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107111_Tg<-(cts_dna_pot_ann$S107111 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107112_Tg<-(cts_dna_pot_ann$S107112 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107113_Tg<-(cts_dna_pot_ann$S107113 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107114_Tg<-(cts_dna_pot_ann$S107114 * 140) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107115_Tg<-(cts_dna_pot_ann$S107115 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107107_Tg<-(cts_dna_pot_ann$S107107 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107108_Tg<-(cts_dna_pot_ann$S107108 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107116_Tg<-(cts_dna_pot_ann$S107116 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107117_Tg<-(cts_dna_pot_ann$S107117 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107119_Tg<-(cts_dna_pot_ann$S107119 * 141) / cts_dna_pot_ann$Length
cts_dna_pot_ann$S107121_Tg<-(cts_dna_pot_ann$S107121 * 141) / cts_dna_pot_ann$Length

5.2. Calculate GPM Values

Now multiple each Tg value within a sample by 1e+06 and divide by the sum of Tg values for that sample to determine GPM.

cts_dna_pot_ann$S107104_GPM<-(cts_dna_pot_ann$S107104_Tg * 1000000) / sum(cts_dna_pot_ann$S107104_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107105_GPM<-(cts_dna_pot_ann$S107105_Tg * 1000000) / sum(cts_dna_pot_ann$S107105_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107106_GPM<-(cts_dna_pot_ann$S107106_Tg * 1000000) / sum(cts_dna_pot_ann$S107106_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107110_GPM<-(cts_dna_pot_ann$S107110_Tg * 1000000) / sum(cts_dna_pot_ann$S107110_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107111_GPM<-(cts_dna_pot_ann$S107111_Tg * 1000000) / sum(cts_dna_pot_ann$S107111_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107112_GPM<-(cts_dna_pot_ann$S107112_Tg * 1000000) / sum(cts_dna_pot_ann$S107112_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107113_GPM<-(cts_dna_pot_ann$S107113_Tg * 1000000) / sum(cts_dna_pot_ann$S107113_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107114_GPM<-(cts_dna_pot_ann$S107114_Tg * 1000000) / sum(cts_dna_pot_ann$S107114_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107115_GPM<-(cts_dna_pot_ann$S107115_Tg * 1000000) / sum(cts_dna_pot_ann$S107115_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107107_GPM<-(cts_dna_pot_ann$S107107_Tg * 1000000) / sum(cts_dna_pot_ann$S107107_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107108_GPM<-(cts_dna_pot_ann$S107108_Tg * 1000000) / sum(cts_dna_pot_ann$S107108_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107116_GPM<-(cts_dna_pot_ann$S107116_Tg * 1000000) / sum(cts_dna_pot_ann$S107116_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107117_GPM<-(cts_dna_pot_ann$S107117_Tg * 1000000) / sum(cts_dna_pot_ann$S107117_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107119_GPM<-(cts_dna_pot_ann$S107119_Tg * 1000000) / sum(cts_dna_pot_ann$S107119_Tg,na.rm=TRUE)
cts_dna_pot_ann$S107121_GPM<-(cts_dna_pot_ann$S107121_Tg * 1000000) / sum(cts_dna_pot_ann$S107121_Tg,na.rm=TRUE)

5.3. Create GPM Dataframe

Create the GPM dataframe by subsetting columns of interest from the cts_dna_pot_ann dataframe.

gpm_all<-data.frame(cts_dna_pot_ann$ID,cts_dna_pot_ann$S107104_GPM,cts_dna_pot_ann$S107105_GPM,cts_dna_pot_ann$S107106_GPM,cts_dna_pot_ann$S107110_GPM,cts_dna_pot_ann$S107111_GPM,cts_dna_pot_ann$S107112_GPM,cts_dna_pot_ann$S107113_GPM,cts_dna_pot_ann$S107114_GPM,cts_dna_pot_ann$S107115_GPM,cts_dna_pot_ann$S107107_GPM,cts_dna_pot_ann$S107108_GPM,cts_dna_pot_ann$S107116_GPM,cts_dna_pot_ann$S107117_GPM,cts_dna_pot_ann$S107119_GPM,cts_dna_pot_ann$S107121_GPM,cts_dna_pot_ann$KO,cts_dna_pot_ann$Symbol,cts_dna_pot_ann$Function,cts_dna_pot_ann$Tier_II,cts_dna_pot_ann$Tier_III,cts_dna_pot_ann$Tier_IV,cts_dna_pot_ann$Taxonomy)

names(gpm_all)<-c("ID","S107104_GPM","S107105_GPM","S107106_GPM","S107110_GPM","S107111_GPM","S107112_GPM","S107113_GPM","S107114_GPM","S107115_GPM","S107107_GPM","S107108_GPM","S107116_GPM","S107117_GPM","S107119_GPM","S107121_GPM","KO","Symbol","Function","Tier_II","Tier_III","Tier_IV","Taxonomy")

6. Gene Datasets

Now, we further separate the normalized potential annotated DNA subdata into their experimental treatments in order to analyze statistical differences in potential gene expression patterns between experimental treatments. Pairwise similarities among metagenomces will be calculated using Bray-Curtis similarity values, with differences between treatments assessed via PERMANOVA.

6.1. Tussock Gene Data

Separate the Tussock samples into their own dataset. Keep only those unique genecalls that have potential expression in at least 1 Tuss sample.

# Subset the TUSS GPM Normalized Potential Annotated subdata
gpm_tuss <- subset(gpm_all, select=c(ID,S107107_GPM,S107108_GPM,S107116_GPM,S107117_GPM,S107119_GPM,S107121_GPM,KO,Symbol,Function,Tier_II,Tier_III,Tier_IV, Taxonomy))

names(gpm_tuss)<-c("ID","Tuss1_T0","Tuss2_T0","Tuss1_T4","Tuss2_T4","Tuss1_T24","Tuss3_T24","KO","Symbol","Function","Tier_II","Tier_III","Tier_IV","Taxonomy")

# Remove any non-expressed genes from the Tussock samples
gpm_tuss_potential <- subset(gpm_tuss, Tuss1_T0 > 0 | Tuss2_T0 > 0 | Tuss1_T4 > 0 | Tuss2_T4 > 0 | Tuss1_T24 > 0 | Tuss3_T24 > 0, select=c(ID,Tuss1_T0,Tuss2_T0,Tuss1_T4,Tuss2_T4,Tuss1_T24,Tuss3_T24,KO,Symbol,Function,Tier_II,Tier_III,Tier_IV,Taxonomy))

6.2. Wet Sedge Gene Data

Separate the Wet Sedge samples into their own dataset. Keep only those unique genecalls that have potential expression in at least 1 WS sample.

# Subset the WS GPM Normalized Potential Annotated subdata
gpm_ws <- subset(gpm_all, select=c(ID,S107104_GPM,S107105_GPM,S107106_GPM,S107110_GPM,S107111_GPM,S107112_GPM,S107113_GPM,S107114_GPM,S107115_GPM,KO,Symbol,Function,Tier_II,Tier_III,Tier_IV,Taxonomy))
names(gpm_ws)<-c("ID","WS1_T0","WS2_T0","WS3_T0","WS1_T4","WS2_T4","WS3_T4","WS1_T24","WS2_T24","WS3_T24","KO","Symbol","Function","Tier_II","Tier_III","Tier_IV","Taxonomy")

# Remove any non-expressed genes from the Wet Sedge samples
gpm_ws_potential <- subset(gpm_ws, WS1_T0 > 0 | WS2_T0 > 0 | WS3_T0 > 0 | WS1_T4 > 0 | WS2_T4 > 0 | WS3_T4 > 0 | WS1_T24 > 0 | WS2_T24 > 0 | WS3_T24 > 0, select=c(ID,WS1_T0,WS2_T0,WS3_T0,WS1_T4,WS2_T4,WS3_T4,WS1_T24,WS2_T24,WS3_T24,KO,Symbol,Function,Tier_II,Tier_III,Tier_IV,Taxonomy))

6.3. All Gene Data

We also need the full TUSS and WS Potential Annotated data together to make comparisons between ecosystems within each sampling timepoint. Reformat the gpm_all table and separate the “KEGG” column into all of its functional categories for downstream use.

# Make a new object for the rpm_all table so that you don't overwrite the original
gpm_all_pot_ann<-gpm_all

names(gpm_all_pot_ann)<-c("ID","S107104","S107105","S107106","S107110","S107111","S107112","S107113","S107114","S107115","S107107","S107108","S107116","S107117","S107119","S107121","KO","Symbol","Function","Tier_II","Tier_III","Tier_IV","Taxonomy")

7. Gene Analysis

7.1. Taxonomy

Here, we determine the taxonomic composition of the microbial community by analyzing the relative abundance of potential genes for KEGG tier IV “Ribosomes” (03010 Ribosome PATH: ko03010). Within the “Ribosome” category, there are annotations for “small subunit ribosomal protein” (ssu) and “large subunit ribosomal protein” (lsu). For Bacteria and Archaea, we use the ssu annotations (similar to 16S ssu rRNA targeted analysis). For Fungi, we use both the ssu (18S ssu rRNA) and lsu (28S lsu rRNA) annotations.

7.1.1. Bacteria/Archaea SSU

The first analysis pulls out all gene expression for “Ribosomes” and removes lsu annotations such that only ssu annotations are used for determining relative expression of Bacteria and Archaea at each sampling time point in both tussock and wet sedge tundra.

# Subset all unique genecalls whose annotation matches "Ribosomes"
taxa_ribo_dna_all<- gpm_all_pot_ann[ which(gpm_all_pot_ann$Tier_IV=='03010 Ribosome [PATH:ko03010]'),]
# Make copy of Ribosome dataset to manipulate
taxa_ribo_dna_ssu<-taxa_ribo_dna_all

# Remove "large subunit ribosomal protein" from dataset
taxa_ribo_dna_ssu<-taxa_ribo_dna_ssu[!grepl("large subunit ribosomal protein", taxa_ribo_dna_ssu$Function),]

# Write data to file for Alpha Diversity statistics
write.csv(taxa_ribo_dna_ssu, 'Ribo.Results/ALPHA.taxa.dna.ssu.csv')

# Remove "Fungi" from dataset
taxa_ribo_dna_ssu<-taxa_ribo_dna_ssu[!grepl("Fungi", taxa_ribo_dna_ssu$Taxonomy),]

# Separate "Taxonomy" column into all subdivisions
taxa_ribo_dna_ssu<-taxa_ribo_dna_ssu %>% separate(Taxonomy, c("Kingdom","Phylum","Class","Order","Family","Genus","Species"), ": ", extra="merge")

# Keep "Kingdom" and "Phylum"
taxa_ribo_dna_ssu <- data.frame(taxa_ribo_dna_ssu$Kingdom,taxa_ribo_dna_ssu$Phylum, taxa_ribo_dna_ssu$S107104,taxa_ribo_dna_ssu$S107105,taxa_ribo_dna_ssu$S107106,taxa_ribo_dna_ssu$S107110,taxa_ribo_dna_ssu$S107111,taxa_ribo_dna_ssu$S107112,taxa_ribo_dna_ssu$S107113,taxa_ribo_dna_ssu$S107114,taxa_ribo_dna_ssu$S107115,taxa_ribo_dna_ssu$S107107,taxa_ribo_dna_ssu$S107108,taxa_ribo_dna_ssu$S107116,taxa_ribo_dna_ssu$S107117,taxa_ribo_dna_ssu$S107119,taxa_ribo_dna_ssu$S107121)
names(taxa_ribo_dna_ssu)<-c("Kingdom","Phylum","ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24")

# Remove "Unclassified" taxa otherwise it will clump unclassified Archaea with unclassified Bacteria (not what we want)
taxa_ribo_dna_ssu<-taxa_ribo_dna_ssu[!grepl("Unclassified", taxa_ribo_dna_ssu$Phylum),]

# Remove "Other" taxa otherwise it will clump "other" Archaea with "other" Bacteria (not what we want)
taxa_ribo_dna_ssu<-taxa_ribo_dna_ssu[!grepl("Other", taxa_ribo_dna_ssu$Phylum),]

# Sort data by Kingdom alphabetically
taxa_ribo_dna_ssu<-taxa_ribo_dna_ssu[order(taxa_ribo_dna_ssu$Kingdom,taxa_ribo_dna_ssu$Phylum),]

# Sum each column by unique Phylum
taxa_ribo_dna_ssu_sum<-taxa_ribo_dna_ssu %>% group_by(Phylum) %>% summarise_at(vars("ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24"), sum)
taxa_ribo_dna_ssu_sum<-taxa_ribo_dna_ssu_sum %>% mutate_at(vars('ws1-T0','ws2-T0','ws3-T0','ws1-T4','ws2-T4','ws3-T4','ws1-T24','ws2-T24','ws3-T24','tuss1-T0','tuss2-T0','tuss1-T4','tuss2-T4','tuss1-T24','tuss3-T24'), funs(round(., 0)))
taxa_ribo_dna_ssu_sum<-as.data.frame(taxa_ribo_dna_ssu_sum)

taxa_ribo_dna_ssu_sum

Repeat the same “Ribosome” analysis as above (at Phylum level), but this time keep all the taxonomy information.

# Make copy of taxa_ribo_all to manipulate
taxa_ribo_dna_ssu2<-taxa_ribo_dna_all

# Keep "Taxonomy" column
taxa_ribo_dna_ssu2 <- data.frame(taxa_ribo_dna_ssu2$Function,taxa_ribo_dna_ssu2$Taxonomy,taxa_ribo_dna_ssu2$S107104,taxa_ribo_dna_ssu2$S107105,taxa_ribo_dna_ssu2$S107106,taxa_ribo_dna_ssu2$S107110,taxa_ribo_dna_ssu2$S107111,taxa_ribo_dna_ssu2$S107112,taxa_ribo_dna_ssu2$S107113,taxa_ribo_dna_ssu2$S107114,taxa_ribo_dna_ssu2$S107115,taxa_ribo_dna_ssu2$S107107,taxa_ribo_dna_ssu2$S107108,taxa_ribo_dna_ssu2$S107116,taxa_ribo_dna_ssu2$S107117,taxa_ribo_dna_ssu2$S107119,taxa_ribo_dna_ssu2$S107121)
names(taxa_ribo_dna_ssu2)<-c("Function","Taxonomy","ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24")

# Remove "large subunit ribosomal protein" from dataset
taxa_ribo_dna_ssu2<-taxa_ribo_dna_ssu2[!grepl("large subunit ribosomal protein", taxa_ribo_dna_ssu2$Function),]

# Remove "Fungi" from dataset
taxa_ribo_dna_ssu2<-taxa_ribo_dna_ssu2[!grepl("Fungi", taxa_ribo_dna_ssu2$Taxonomy),]
# Sort data by Kingdom alphabetically
taxa_ribo_dna_ssu2<-taxa_ribo_dna_ssu2[order(taxa_ribo_dna_ssu2$Function,taxa_ribo_dna_ssu2$Taxonomy),]

# Sum each column by unique Taxonomy
taxa_ribo_dna_ssu2_sum<-taxa_ribo_dna_ssu2 %>% group_by(Taxonomy) %>% summarise_at(vars("ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24"), sum)
taxa_ribo_dna_ssu2_sum<-taxa_ribo_dna_ssu2_sum %>% mutate_at(vars('ws1-T0','ws2-T0','ws3-T0','ws1-T4','ws2-T4','ws3-T4','ws1-T24','ws2-T24','ws3-T24','tuss1-T0','tuss2-T0','tuss1-T4','tuss2-T4','tuss1-T24','tuss3-T24'), funs(round(., 0)))
taxa_ribo_dna_ssu2_sum<-as.data.frame(taxa_ribo_dna_ssu2_sum)

taxa_ribo_dna_ssu2_sum

7.1.2. Fungi SSU/LSU

The second analysis pulls out all gene expression for “Ribosomes” and removes Bacteria and Archaea annotations while retaining just Fungi with both ssu and lsu annotations to determine relative expression of Fungi at each sampling time point in both tussock and wet sedge tundra.

# Make copy of Ribosome dataset to manipulate
taxa_ribo_dna_fungi<-taxa_ribo_dna_all

# Remove "Bacteria" from dataset
taxa_ribo_dna_fungi<-taxa_ribo_dna_fungi[!grepl("Bacteria", taxa_ribo_dna_fungi$Taxonomy),]

# Remove "Archaea" from dataset
taxa_ribo_dna_fungi<-taxa_ribo_dna_fungi[!grepl("Archaea", taxa_ribo_dna_fungi$Taxonomy),]

# Separate "Taxonomy" column into all subdivisions
taxa_ribo_dna_fungi<-taxa_ribo_dna_fungi %>% separate(Taxonomy, c("Kingdom","Phylum","Class","Order","Family","Genus","Species"), ": ", extra="merge")

# Keep "Kingdom" and "Phylum"
taxa_ribo_dna_fungi <- data.frame(taxa_ribo_dna_fungi$Kingdom,taxa_ribo_dna_fungi$Phylum, taxa_ribo_dna_fungi$S107104,taxa_ribo_dna_fungi$S107105,taxa_ribo_dna_fungi$S107106,taxa_ribo_dna_fungi$S107110,taxa_ribo_dna_fungi$S107111,taxa_ribo_dna_fungi$S107112,taxa_ribo_dna_fungi$S107113,taxa_ribo_dna_fungi$S107114,taxa_ribo_dna_fungi$S107115,taxa_ribo_dna_fungi$S107107,taxa_ribo_dna_fungi$S107108,taxa_ribo_dna_fungi$S107116,taxa_ribo_dna_fungi$S107117,taxa_ribo_dna_fungi$S107119,taxa_ribo_dna_fungi$S107121)
names(taxa_ribo_dna_fungi)<-c("Kingdom","Phylum","ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24")

# Remove "Unclassified" taxa
taxa_ribo_dna_fungi<-taxa_ribo_dna_fungi[!grepl("Unclassified", taxa_ribo_dna_fungi$Phylum),]

# Remove "Other" taxa
taxa_ribo_dna_fungi<-taxa_ribo_dna_fungi[!grepl("Other", taxa_ribo_dna_fungi$Phylum),]

# Sort data by Kingdom alphabetically
taxa_ribo_dna_fungi<-taxa_ribo_dna_fungi[order(taxa_ribo_dna_fungi$Kingdom,taxa_ribo_dna_fungi$Phylum),]

# Sum each column by unique Phylum
taxa_ribo_dna_fungi_sum<-taxa_ribo_dna_fungi %>% group_by(Phylum) %>% summarise_at(vars("ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24"), sum)
taxa_ribo_dna_fungi_sum<-taxa_ribo_dna_fungi_sum %>% mutate_at(vars('ws1-T0','ws2-T0','ws3-T0','ws1-T4','ws2-T4','ws3-T4','ws1-T24','ws2-T24','ws3-T24','tuss1-T0','tuss2-T0','tuss1-T4','tuss2-T4','tuss1-T24','tuss3-T24'), funs(round(., 0)))
taxa_ribo_dna_fungi_sum<-as.data.frame(taxa_ribo_dna_fungi_sum)

taxa_ribo_dna_fungi_sum

Repeat the same “Ribosome” analysis as above (at Phylum level), but this time keep all the taxonomy information.

# Make copy of taxa_ribo_all to manipulate
taxa_ribo_dna_fungi2<-taxa_ribo_dna_all

# Keep "Taxonomy" column
taxa_ribo_dna_fungi2 <- data.frame(taxa_ribo_dna_fungi2$Function,taxa_ribo_dna_fungi2$Taxonomy,taxa_ribo_dna_fungi2$S107104,taxa_ribo_dna_fungi2$S107105,taxa_ribo_dna_fungi2$S107106,taxa_ribo_dna_fungi2$S107110,taxa_ribo_dna_fungi2$S107111,taxa_ribo_dna_fungi2$S107112,taxa_ribo_dna_fungi2$S107113,taxa_ribo_dna_fungi2$S107114,taxa_ribo_dna_fungi2$S107115,taxa_ribo_dna_fungi2$S107107,taxa_ribo_dna_fungi2$S107108,taxa_ribo_dna_fungi2$S107116,taxa_ribo_dna_fungi2$S107117,taxa_ribo_dna_fungi2$S107119,taxa_ribo_dna_fungi2$S107121)
names(taxa_ribo_dna_fungi2)<-c("Function","Taxonomy","ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24")

# Remove "Bacteria" from dataset
taxa_ribo_dna_fungi2<-taxa_ribo_dna_fungi2[!grepl("Bacteria", taxa_ribo_dna_fungi2$Taxonomy),]

# Remove "Archaea" from dataset
taxa_ribo_dna_fungi2<-taxa_ribo_dna_fungi2[!grepl("Archaea", taxa_ribo_dna_fungi2$Taxonomy),]
# Sort data by Kingdom alphabetically
taxa_ribo_dna_fungi2<-taxa_ribo_dna_fungi2[order(taxa_ribo_dna_fungi2$Function,taxa_ribo_dna_fungi2$Taxonomy),]

# Sum each column by unique Taxonomy
taxa_ribo_dna_fungi2_sum<-taxa_ribo_dna_fungi2 %>% group_by(Taxonomy) %>% summarise_at(vars("ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss3-T24"), sum)
taxa_ribo_dna_fungi2_sum<-taxa_ribo_dna_fungi2_sum %>% mutate_at(vars('ws1-T0','ws2-T0','ws3-T0','ws1-T4','ws2-T4','ws3-T4','ws1-T24','ws2-T24','ws3-T24','tuss1-T0','tuss2-T0','tuss1-T4','tuss2-T4','tuss1-T24','tuss3-T24'), funs(round(., 0)))
taxa_ribo_dna_fungi2_sum<-as.data.frame(taxa_ribo_dna_fungi2_sum)

taxa_ribo_dna_fungi2_sum

7.1.3. Plotting Taxonomy

Plot the relative abundance of taxa by all replicates within tussock and wet sedge tundra as a stackplot.

# Place taxa in order for plotting
taxa.MG.all.chart$Species<-factor(taxa.MG.all.chart$Species,levels = c("Acidobacteria","Actinobacteria","Alphaproteobacteria","Betaproteobacteria","Deltaproteobacteria","Gammaproteobacteria","Proteobacteria Unclassified","Bacteroidetes","Chloroflexi","Firmicutes","Planctomycetes","Verrucomicrobia","Bacteria Unclassified","Bacteria Other","Archaea","Fungi"))

taxa.MG.all.chart$Species<-fct_rev(taxa.MG.all.chart$Species)

taxa.MG.all.chart$Sample<-factor(taxa.MG.all.chart$Sample,levels = c("Tuss1-MG-T0","Tuss2-MG-T0","Tuss1-MG-T4","Tuss2-MG-T4","Tuss1-MG-T24","Tuss3-MG-T24","WS1-MG-T0","WS2-MG-T0","WS3-MG-T0","WS1-MG-T4","WS2-MG-T4","WS3-MG-T4","WS1-MG-T24","WS2-MG-T24","WS3-MG-T24"))
colourCount = length(unique(taxa.MG.all.chart$Species))
getPalette = colorRampPalette(brewer.pal(12, "Paired"))

taxa.MG.all.plot<-ggplot(taxa.MG.all.chart, aes(fill=Species, y=Value, x=Sample)) + geom_bar(position = "stack", stat="identity", color="black") + ylab(expression(atop("Relative Taxon", paste("Expression (%)")))) + theme_minimal() + theme(axis.text=element_text(size=10),axis.title=element_text(size=12),axis.title.x=element_blank()) + theme(legend.position = "right", legend.title=element_blank(), legend.text=element_text(size=8), legend.key.size = unit(0.75,"line"), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), panel.border = element_blank()) + scale_x_discrete(labels = function(Sample) str_wrap(Sample, width = 8)) + scale_size(guide=FALSE) + scale_fill_manual(values = rev(getPalette(colourCount))) + scale_x_discrete(labels = function(Sample) str_wrap(Sample, width = 15)) + theme(axis.text.x = element_text(angle = 270, hjust=0)) 
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing
scale.
taxa.MG.all.plot

4.2.2 Mean Time Point

Plot the mean relative abundance of taxa by sampling time point within tussock and wet sedge tundra as a stackplot.

# Place taxa in order for plotting
taxa.MG.time.mean.chart$Species<-factor(taxa.MG.time.mean.chart$Species,levels = c("Acidobacteria","Actinobacteria","Alphaproteobacteria","Betaproteobacteria","Deltaproteobacteria","Gammaproteobacteria","Proteobacteria Unclassified","Bacteroidetes","Chloroflexi","Firmicutes","Planctomycetes","Verrucomicrobia","Bacteria Unclassified","Bacteria Other","Archaea","Fungi"))

taxa.MG.time.mean.chart$Species<-fct_rev(taxa.MG.time.mean.chart$Species)

taxa.MG.time.mean.chart$Sample<-factor(taxa.MG.time.mean.chart$Sample,levels = c("Tuss-MG-T0","Tuss-MG-T4","Tuss-MG-T24","WS-MG-T0","WS-MG-T4","WS-MG-T24"))
colourCount = length(unique(taxa.MG.time.mean.chart$Species))
getPalette = colorRampPalette(brewer.pal(12, "Paired"))

taxa.MG.time.mean.plot<-ggplot(taxa.MG.time.mean.chart, aes(fill=Species, y=Value, x=Sample)) + geom_bar(position = "stack", stat="identity", color="black") + ylab(expression(atop("Relative Taxon", paste("Expression (%)")))) + theme_minimal() + theme(axis.text=element_text(size=10),axis.title=element_text(size=12),axis.title.x=element_blank()) + theme(legend.position = "right", legend.title=element_blank(), legend.text=element_text(size=8), legend.key.size = unit(0.75,"line"), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), panel.border = element_blank()) + scale_x_discrete(labels = function(Sample) str_wrap(Sample, width = 8)) + scale_size(guide=FALSE) + scale_fill_manual(values = rev(getPalette(colourCount))) + scale_x_discrete(labels = function(Sample) str_wrap(Sample, width = 15)) + theme(axis.text.x = element_text(angle = 270, hjust=0)) 
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing
scale.
taxa.MG.time.mean.plot

4.2.3 Mean Tundra

Plot the mean relative abundance of taxa by within tussock and wet sedge tundra as a stackplot.

# Place taxa in order for plotting
taxa.MG.tundra.mean.chart$Species<-factor(taxa.MG.tundra.mean.chart$Species,levels = c("Acidobacteria","Actinobacteria","Alphaproteobacteria","Betaproteobacteria","Deltaproteobacteria","Gammaproteobacteria","Proteobacteria Unclassified","Bacteroidetes","Chloroflexi","Firmicutes","Planctomycetes","Verrucomicrobia","Bacteria Unclassified","Bacteria Other","Archaea","Fungi"))

taxa.MG.tundra.mean.chart$Species<-fct_rev(taxa.MG.tundra.mean.chart$Species)

taxa.MG.tundra.mean.chart$Sample<-factor(taxa.MG.tundra.mean.chart$Sample,levels = c("Tuss-MG","WS-MG"))
colourCount = length(unique(taxa.MG.tundra.mean.chart$Species))
getPalette = colorRampPalette(brewer.pal(12, "Paired"))

taxa.MG.tundra.mean.plot<-ggplot(taxa.MG.tundra.mean.chart, aes(fill=Species, y=Value, x=Sample)) + geom_bar(position = "stack", stat="identity", color="black") + ylab(expression(atop("Relative Taxon", paste("Expression (%)")))) + theme_minimal() + theme(axis.text=element_text(size=10),axis.title=element_text(size=12),axis.title.x=element_blank()) + theme(legend.position = "right", legend.title=element_blank(), legend.text=element_text(size=8), legend.key.size = unit(0.75,"line"), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), panel.border = element_blank()) + scale_x_discrete(labels = function(Sample) str_wrap(Sample, width = 8)) + scale_size(guide=FALSE) + scale_fill_manual(values = rev(getPalette(colourCount))) + scale_x_discrete(labels = function(Sample) str_wrap(Sample, width = 15)) + theme(axis.text.x = element_text(angle = 270, hjust=0)) 
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing
scale.
taxa.MG.tundra.mean.plot

Plot the relative expression of ribosomes as a stackplot with the MEAN of samples by time point

# Place taxa in order for plotting
taxa.tuss.dna.mean.ribo.chart$Species<-factor(taxa.tuss.dna.mean.ribo.chart$Species,levels = c("Acidobacteria","Actinobacteria","Alphaproteobacteria","Betaproteobacteria","Deltaproteobacteria","Gammaproteobacteria","Proteobacteria Unclassified","Bacteroidetes","Chloroflexi","Firmicutes","Planctomycetes","Verrucomicrobia","Bacteria Unclassified","Bacteria Other","Archaea","Fungi"))

taxa.tuss.dna.mean.ribo.chart$Species<-fct_rev(taxa.tuss.dna.mean.ribo.chart$Species)

taxa.tuss.dna.mean.ribo.chart$Sample<-factor(taxa.tuss.dna.mean.ribo.chart$Sample,levels = c("Tuss-MG-T0","Tuss-MG-T4","Tuss-MG-T24"))
colourCount = length(unique(taxa.tuss.dna.mean.ribo.chart$Species))
getPalette = colorRampPalette(brewer.pal(12, "Paired"))

taxa.tuss.dna.mean.ribo.plot<-ggplot(taxa.tuss.dna.mean.ribo.chart, aes(fill=Species, y=Value, x=Sample)) + geom_bar(position = "stack", stat="identity", color="black") + ylab(expression(atop("Community Composition", paste("Relative Abundance (%)")))) + scale_fill_manual(values = rev(getPalette(colourCount)), guide=guide_legend(reverse=FALSE)) + theme_classic() + theme(axis.title.x=element_blank(), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), axis.ticks = element_blank(), axis.text.x = element_text(angle = 270, hjust=0), axis.text=element_text(size=10), axis.title=element_text(size=12), legend.position = "none", legend.title=element_blank(), legend.text=element_text(size=8)) + scale_y_continuous(expand = c(0, 0), limits = c(0, 101))
taxa.tuss.dna.mean.ribo.plot

Plot the relative expression of ribosomes as a stackplot with the MEAN of samples by time point

# Place taxa in order for plotting
taxa.ws.dna.mean.ribo.chart$Species<-factor(taxa.ws.dna.mean.ribo.chart$Species,levels = c("Acidobacteria","Actinobacteria","Alphaproteobacteria","Betaproteobacteria","Deltaproteobacteria","Gammaproteobacteria","Proteobacteria Unclassified","Bacteroidetes","Chloroflexi","Firmicutes","Planctomycetes","Verrucomicrobia","Bacteria Unclassified","Bacteria Other","Archaea","Fungi"))

taxa.ws.dna.mean.ribo.chart$Species<-fct_rev(taxa.ws.dna.mean.ribo.chart$Species)

taxa.ws.dna.mean.ribo.chart$Sample<-factor(taxa.ws.dna.mean.ribo.chart$Sample,levels = c("WS-MG-T0","WS-MG-T4","WS-MG-T24"))
colourCount = length(unique(taxa.ws.dna.mean.ribo.chart$Species))
getPalette = colorRampPalette(brewer.pal(12, "Paired"))

taxa.ws.dna.mean.ribo.plot<-ggplot(taxa.ws.dna.mean.ribo.chart, aes(fill=Species, y=Value, x=Sample)) + geom_bar(position = "stack", stat="identity", color="black") + ylab(expression(atop("Community Composition", paste("Relative Abundance (%)")))) + scale_fill_manual(values = rev(getPalette(colourCount)), guide=guide_legend(reverse=FALSE)) + theme_classic() + theme(axis.title.x=element_blank(), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), axis.ticks = element_blank(), axis.text.x = element_text(angle = 270, hjust=0), axis.text=element_text(size=10), axis.title=element_text(size=12), legend.position = "right", legend.title=element_blank(), legend.text=element_text(size=8), legend.key.size = unit(0.75,"line")) + scale_y_continuous(expand = c(0, 0), limits = c(0, 101))
taxa.ws.dna.mean.ribo.plot

7.1.4. Taxonomy Statistics

To determine if there are significant differences in mean relative abundance of dominant taxa between tundra ecosystems, we calculate the mean (SD) of each phylum (dominant phylum; >1%) within tussock tundra and within wet sedge tundra throughout the experiment and compare to each other.

# Rename column headings
colnames(taxa.dna.table)<-c("Taxonomy","Tuss Relative Abundance (%)","WS Relative Abundance (%)","Mean Difference", "Paired t-test (p-value)")

kable(taxa.dna.table, caption = "Relative abundance (mean (SD)) of microbial taxa within tussock tundra and wet sedge tundra with mean difference (%) and significance (p-value).", format.args = list(big.mark = ","), align = "l") %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Relative abundance (mean (SD)) of microbial taxa within tussock tundra and wet sedge tundra with mean difference (%) and significance (p-value).
Taxonomy Tuss Relative Abundance (%) WS Relative Abundance (%) Mean Difference Paired t-test (p-value)
Actinobacteria 24 (6) 27 (2) 3% N.S.
Acidobacteria 34 (5) 10 (0) 24% 0.011
Alphaproteobacteria 15 (4) 8 (1) 7% N.S.
Betaproteobacteria 2 (1) 6 (1) 4% 0.002
Deltaproteobacteria 4 (0) 13 (0) 9% 0.002
Gammaproteobacteria 11 (0) 2 (0) 9% < 0.001
Bacteroidetes 0 (0) 2 (1) 2% N.S.
Chloroflexi 0 (0) 8 (0) 8% < 0.001
Firmicutes 4 (1) 15 (2) 11% 0.007
Euryarchaeota 0 (0) 2 (0) 2% 0.013
Ascomycetes 1 (0) 0 (0) 1% 0.013

Test for differences in mean relative abundance of dominant phyla between tundra ecosystems.

# Pairwise comparisons between tundra ecosystems for each microbial taxonomic class
taxa.dna.phylum.t.test.stats <- taxa.dna.phylum.t.test %>%
  group_by(Phylum) %>%
  pairwise_t_test(
    Abundance ~ Tundra, paired = TRUE, 
    p.adjust.method = "bonferroni"
    ) %>%
  select(-.y., -n1, -n2, -df, -statistic, -p) # Remove details
taxa.dna.phylum.t.test.stats

Alpha Diversity: We also test for significant differences in the diversity of microbial taxa between tundra ecosystems.

# Richness: Sum up the number of non-zero entries per row
alpha.dna.taxa.rich <- apply(alpha.dna.taxa>0,1,sum)
write.csv(alpha.dna.taxa.rich, 'Ribo.Results/alpha.dna.taxa.rich.csv')
alpha.dna.taxa.rich
   ws1-T0    ws2-T0    ws3-T0    ws1-T4    ws2-T4    ws3-T4   ws1-T24   ws2-T24   ws3-T24  tuss1-T0 
     7741      6717      6841      7331      7427      7007      7810      7226      7535      5491 
 tuss2-T0  tuss1-T4  tuss2-T4 tuss1-T24 tuss2-T24 
     4729      3094      4452      5122      4494 
# Abundance: sum up the number of non-zero entries per row (1)
alpha.dna.taxa.abund <- apply(alpha.dna.taxa,1,sum)
write.csv(alpha.dna.taxa.abund, 'Ribo.Results/alpha.dna.taxa.abund.csv')
alpha.dna.taxa.abund
   ws1-T0    ws2-T0    ws3-T0    ws1-T4    ws2-T4    ws3-T4   ws1-T24   ws2-T24   ws3-T24  tuss1-T0 
 17376.57  16882.94  17885.92  16825.84  18317.26  18251.95  18054.30  16834.71  18324.59  18125.41 
 tuss2-T0  tuss1-T4  tuss2-T4 tuss1-T24 tuss2-T24 
 18296.25  18493.72  18746.65  18811.87  20381.91 
# Diversity: Shannon-Wiener Index (H')
alpha.dna.taxa.div <- diversity(alpha.dna.taxa, index="shannon")
write.csv(alpha.dna.taxa.div, 'Ribo.Results/alpha.dna.taxa.div.csv')
alpha.dna.taxa.div
   ws1-T0    ws2-T0    ws3-T0    ws1-T4    ws2-T4    ws3-T4   ws1-T24   ws2-T24   ws3-T24  tuss1-T0 
 8.575538  8.318133  8.537789  8.496218  8.447123  8.541090  8.601345  8.379233  8.521386  8.158248 
 tuss2-T0  tuss1-T4  tuss2-T4 tuss1-T24 tuss2-T24 
 7.984487  7.665960  8.030042  8.123260  7.936642 

Run paired t-test to determine significance for Shannon Diversity.

t.test(alpha.dna.taxa.t.test$Tuss,alpha.dna.taxa.t.test$WS,paired=TRUE)

    Paired t-test

data:  alpha.dna.taxa.t.test$Tuss and alpha.dna.taxa.t.test$WS
t = -5.9292, df = 5, p-value = 0.001947
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.7208950 -0.2848555
sample estimates:
mean of the differences 
             -0.5028752 

Beta Diversity

Calculate the Bray-Curtis dissimilarity matrix to use with adonis

# Make dna_taxa_gpm_all_groups object
beta.dna.taxa_sample<-c("ws1-T0","ws2-T0","ws3-T0","ws1-T4","ws2-T4","ws3-T4","ws1-T24","ws2-T24","ws3-T24","tuss1-T0","tuss2-T0","tuss1-T4","tuss2-T4","tuss1-T24","tuss2-T24")
beta.dna.taxa_veg<-c("WS","WS","WS","WS","WS","WS","WS","WS","WS","TUSS","TUSS","TUSS","TUSS","TUSS","TUSS")
beta.dna.taxa_time<-c("T0","T0","T0","T4","T4","T4","T24","T24","T24","T0","T0","T4","T4","T24","T24")
beta.dna.taxa_groups<-data.frame(beta.dna.taxa_sample,beta.dna.taxa_veg,beta.dna.taxa_time)

# Convert the values in Column 1 ("beta.dna.taxa_sample") into row names
rownames(beta.dna.taxa_groups)<-beta.dna.taxa_groups[,1]
beta.dna.taxa_groups<-beta.dna.taxa_groups[,-1]
# Bray-Curtis Dissimilarity Matrix for tpm_all_taxa_beta
dna.tpm.taxa.bc.dist<-vegdist(beta.dna.taxa, method = "bray")

Run PERMANOVA using adonis function of the Vegan package

PERMANOVA - MG-GPM-Taxa - Bray-Curtis

adonis(dna.tpm.taxa.bc.dist~beta.dna.taxa_veg*beta.dna.taxa_time, data=beta.dna.taxa_groups)

Call:
adonis(formula = dna.tpm.taxa.bc.dist ~ beta.dna.taxa_veg * beta.dna.taxa_time,      data = beta.dna.taxa_groups) 

Permutation: free
Number of permutations: 999

Terms added sequentially (first to last)

                                     Df SumsOfSqs MeanSqs F.Model      R2 Pr(>F)    
beta.dna.taxa_veg                     1    2.3500 2.35005 18.7557 0.61547  0.001 ***
beta.dna.taxa_time                    2    0.1675 0.08376  0.6685 0.04387  0.736    
beta.dna.taxa_veg:beta.dna.taxa_time  2    0.1731 0.08654  0.6907 0.04533  0.630    
Residuals                             9    1.1277 0.12530         0.29533           
Total                                14    3.8183                 1.00000           
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

7.2. Gene Diversity

Alpha diversity of each potential, annotated metagenome was assessed by the Shannon index. For beta diversity, pairwise similarities among metagenomes were calculated using Bray-Curtis similarity values and visualized with principle coordinates analysis. The difference between treatments was assessed with PERMANOVA.

7.2.1. Alpha Diversity

We calculated alpha diversity based on raw gene counts. Measurements include Richness, Abundance, and Shannon-Wiener Diversity Index (H’).

# Subset the rpm_all_exp_ann file to prepare for alpha diversity analysis
cts_dna_all_alpha<-subset(cts_dna_pot_ann, select=c(S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115,S107107,S107108,S107116,S107117,S107119,S107121))
names(cts_dna_all_alpha)<-c("WS1-T0","WS2-T0","WS3-T0","WS1-T4","WS2-T4","WS3-T4","WS1-T24","WS2-T24","WS3-T24","Tuss1-T0","Tuss2-T0","Tuss1-T4","Tuss2-T4","Tuss1-T24","Tuss3-T24")

# Transpose all but the first column ("ID")
cts_dna_all_alpha<-as.data.frame(t(cts_dna_all_alpha))

Richness: Determine the number of unique genecalls that have more than one count recorded within each sample.

# Sum up the number of non-zero entries per row
apply(cts_dna_all_alpha>0,1,sum)
   WS1-T0    WS2-T0    WS3-T0    WS1-T4    WS2-T4    WS3-T4   WS1-T24   WS2-T24   WS3-T24  Tuss1-T0 
   498790    449289    446055    480455    476840    449096    493473    476967    470771    353537 
 Tuss2-T0  Tuss1-T4  Tuss2-T4 Tuss1-T24 Tuss3-T24 
   303729    207538    286227    320923    266596 

Abundance: Determine the total abundance of individual genecalls

# sum up the number of non-zero entries per row (1)
apply(cts_dna_all_alpha,1,sum)
   WS1-T0    WS2-T0    WS3-T0    WS1-T4    WS2-T4    WS3-T4   WS1-T24   WS2-T24   WS3-T24  Tuss1-T0 
  4797267   3727362   2610321   4125347   5342266   3147324   4491751   4779012   4997299   5797561 
 Tuss2-T0  Tuss1-T4  Tuss2-T4 Tuss1-T24 Tuss3-T24 
  3638615    960585   3147090   3535500   1996760 

Shannon-Wiener Diversity Index (H’): An information index that quantifies the uncertainty associated with predicting the identity of a new genecall given the total number of genecalls and the evenness in count abundances within each genecall.

diversity(cts_dna_all_alpha, index="shannon")
   WS1-T0    WS2-T0    WS3-T0    WS1-T4    WS2-T4    WS3-T4   WS1-T24   WS2-T24   WS3-T24  Tuss1-T0 
 12.48649  12.28717  12.48400  12.41941  12.33807  12.47050  12.45966  12.31243  12.39459  11.98654 
 Tuss2-T0  Tuss1-T4  Tuss2-T4 Tuss1-T24 Tuss3-T24 
 11.75993  11.69615  11.89319  11.95821  11.61855 

The following table is a summary of the Alpha Diversity on the raw gene counts for the Potential Annotated Genes (potential annotated genes for downstream analyses) by sample.

Alpha Diversity for Potential Annotated Genecalls in the DNA-based metagenomic sequencing dataset
ID Tundra Time Replicate Gene Richness Gene Abundance Gene Diversity (H')
S107107 Tussock T0 1 353,537 5,797,561 11.98654
S107108 Tussock T0 2 303,729 3,638,615 11.75993
S107116 Tussock T4 1 207,538 960,585 11.69615
S107117 Tussock T4 2 286,227 3,147,090 11.89319
S107119 Tussock T24 1 320,923 3,535,500 11.95821
S107121 Tussock T24 3 266,596 1,996,760 11.61855
S107104 Wet Sedge T0 1 498,790 4,797,267 12.48649
S107105 Wet Sedge T0 2 449,289 3,727,362 12.28717
S107106 Wet Sedge T0 3 446,055 2,610,321 12.48400
S107110 Wet Sedge T4 1 480,455 4,125,347 12.41941
S107111 Wet Sedge T4 2 476,840 5,342,266 12.33807
S107112 Wet Sedge T4 3 449,096 3,147,324 12.47050
S107113 Wet Sedge T24 1 493,473 4,491,751 12.45966
S107114 Wet Sedge T24 2 476,967 4,779,012 12.31243
S107115 Wet Sedge T24 3 470,771 4,997,299 12.39459

Run paired t-test to determine significance.

t.test(alpha.dna.t.test$Tuss,alpha.dna.t.test$WS,paired=TRUE)

    Paired t-test

data:  alpha.dna.t.test$Tuss and alpha.dna.t.test$WS
t = -7.9613, df = 5, p-value = 0.0005042
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.7877932 -0.4032302
sample estimates:
mean of the differences 
             -0.5955117 

Plot the Alpha Diversity summary.

# Re-arrange samples for plotting PCoA
alpha.dna$Tundra <- factor(alpha.dna$Tundra, levels=c("Tuss-MG-T0","Tuss-MG-T4","Tuss-MG-T24","WS-MG-T0","WS-MG-T4","WS-MG-T24"))

alpha.dna.boxplot<-ggplot(alpha.dna, aes(x=Tundra, y=H, fill=Tundra)) + 
    geom_boxplot() + ylab(expression(atop("Shannon-Wiener", paste("Diversity Index (H')")))) + theme_classic() + theme(axis.title.x=element_blank(), axis.text=element_text(size=10), axis.text.x = element_text(angle = 270, hjust=0, vjust=0.5), axis.title=element_text(size=12), legend.position = "none", legend.title=element_blank(), legend.text=element_text(size=10)) + ylim(11.5,13) + annotate(geom="text", x=3.5, y=13, label="Paired t-test") + annotate("text", x=3.5, y=12.9, size=3, label = "Tundra~(italic(p) < 0.001)", parse = TRUE) + scale_fill_manual(values=c("gray83", "gray83", "gray83", "black", "black", "black"), breaks=c("Tuss-MG-T0", "WS-MG-T0", "Tuss-MG-T4", "WS-MG-T4", "Tuss-MG-T24", "WS-MG-T24"), labels=c("Tuss-MG-T0", "WS-MG-T0", "Tuss-MG-T4", "WS-MG-T4", "Tuss-MG-T24", "WS-MG-T24"))
alpha.dna.boxplot

7.2.2. Beta Diversity

We calculated beta diversity as the variation in gene potential between our two tundra ecosystems using Bray-Curtis similarity values.

7.2.2.1. Subset Data

First, subset the columns of interest from the gpm_all_pot_ann object (ID and all samples) to analyze the beta diversity of both ecosystems together. Create a gpm_groups object with columns for sample ID, vegetation type, and timepoint to be used for calculating pairwise similiarities among samples via PERMANOVA (adonis from Vegan package)

# Subset the gpm_all_pot_ann file to prepare for beta diversity analysis
gpm_all_beta<-subset(gpm_all_pot_ann, select=c(ID,S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115,S107107,S107108,S107116,S107117,S107119,S107121))
names(gpm_all_beta)<-c("ID","WS1-T0","WS2-T0","WS3-T0","WS1-T4","WS2-T4","WS3-T4","WS1-T24","WS2-T24","WS3-T24","Tuss1-T0","Tuss2-T0","Tuss1-T4","Tuss2-T4","Tuss1-T24","Tuss3-T24")

# Remember "ID" column as non-numeric values
gpm_all_beta_ID<-gpm_all_beta$ID

# Transpose all but the first column ("ID")
gpm_all_beta<-as.data.frame(t(gpm_all_beta[,-1]))
colnames(gpm_all_beta)<-gpm_all_beta_ID

# Make gpm_all_groups object
gpm_all_sample<-c("WS1-T0","WS2-T0","WS3-T0","WS1-T4","WS2-T4","WS3-T4","WS1-T24","WS2-T24","WS3-T24","Tuss1-T0","Tuss2-T0","Tuss1-T4","Tuss2-T4","Tuss1-T24","Tuss3-T24")
gpm_all_veg<-c("WS","WS","WS","WS","WS","WS","WS","WS","WS","TUSS","TUSS","TUSS","TUSS","TUSS","TUSS")
gpm_all_time<-c("T0","T0","T0","T4","T4","T4","T24","T24","T24","T0","T0","T4","T4","T24","T24")
gpm_all_groups<-data.frame(gpm_all_sample,gpm_all_veg,gpm_all_time)

# Convert the values in Column 1 ("gpm_sample") into row names
rownames(gpm_all_groups)<-gpm_all_groups[,1]
gpm_all_groups<-gpm_all_groups[,-1]

Second, subset the columns of interest from the gpm_all_pot_ann object (ID and all samples) to analyze the beta diversity of the Wet Sedge ecosystem

# Subset the gpm_ws_exp_ann file to prepare for beta diversity analysis
gpm_ws_beta<-subset(gpm_all_pot_ann, select=c(ID,S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115))
names(gpm_ws_beta)<-c("ID","WS1-T0","WS2-T0","WS3-T0","WS1-T4","WS2-T4","WS3-T4","WS1-T24","WS2-T24","WS3-T24")

# Remember "ID" column as non-numeric values
gpm_ws_beta_ID<-gpm_ws_beta$ID

# Transpose all but the first column ("ID")
gpm_ws_beta<-as.data.frame(t(gpm_ws_beta[,-1]))
colnames(gpm_ws_beta)<-gpm_ws_beta_ID

# Make gpm_ws_groups object
gpm_ws_sample<-c("WS1-T0","WS2-T0","WS3-T0","WS1-T4","WS2-T4","WS3-T4","WS1-T24","WS2-T24","WS3-T24")
gpm_ws_veg<-c("WS","WS","WS","WS","WS","WS","WS","WS","WS")
gpm_ws_time<-c("T0","T0","T0","T4","T4","T4","T24","T24","T24")
gpm_ws_groups<-data.frame(gpm_ws_sample,gpm_ws_veg,gpm_ws_time)

# Convert the values in Column 1 ("gpm_sample") into row names
rownames(gpm_ws_groups)<-gpm_ws_groups[,1]
gpm_ws_groups<-gpm_ws_groups[,-1]

Third, subset the columns of interest from the gpm_all_pot_ann object (ID and all samples) to analyze the beta diversity of the Tussock ecosystem

# Subset the gpm_tuss_exp_ann file to prepare for beta diversity analysis
gpm_tuss_beta<-subset(gpm_all_pot_ann, select=c(ID,S107107,S107108,S107116,S107117,S107119,S107121))
names(gpm_tuss_beta)<-c("ID","Tuss1-T0","Tuss2-T0","Tuss1-T4","Tuss2-T4","Tuss1-T24","Tuss3-T24")

# Remember "ID" column as non-numeric values
gpm_tuss_beta_ID<-gpm_tuss_beta$ID

# Transpose all but the first column ("ID")
gpm_tuss_beta<-as.data.frame(t(gpm_tuss_beta[,-1]))
colnames(gpm_tuss_beta)<-gpm_tuss_beta_ID

# Make gpm_tuss_groups object
gpm_tuss_sample<-c("Tuss1-T0","Tuss2-T0","Tuss1-T4","Tuss2-T4","Tuss1-T24","Tuss3-T24")
gpm_tuss_veg<-c("TUSS","TUSS","TUSS","TUSS","TUSS","TUSS")
gpm_tuss_time<-c("T0","T0","T4","T4","T24","T24")
gpm_tuss_groups<-data.frame(gpm_tuss_sample,gpm_tuss_veg,gpm_tuss_time)

# Convert the values in Column 1 ("gpm_sample") into row names
rownames(gpm_tuss_groups)<-gpm_tuss_groups[,1]
gpm_tuss_groups<-gpm_tuss_groups[,-1]
7.2.2.2. Bray-Curtis

Calculate the Bray-Curtis dissimilarity matrix to use with adonis

# Bray-Curtis Dissimilarity Matrix for gpm_all_beta
gpm.all.bc.dist<-vegdist(gpm_all_beta, method = "bray")

# Bray-Curtis Dissimilarity Matrix for gpm_ws_beta
gpm.ws.bc.dist<-vegdist(gpm_ws_beta, method = "bray")

# Bray-Curtis Dissimilarity Matrix for gpm_tuss_beta
gpm.tuss.bc.dist<-vegdist(gpm_tuss_beta, method = "bray")
7.2.2.3. PCoA Plots

Principal coordinates analysis (PCoA, also known as metric multidimensional scaling) attempts to represent the distances between samples in a low-dimensional, Euclidean space. In particular, it maximizes the linear correlation between the distances in the distance matrix, and the distances in a space of low dimension (typically, 2 or 3 axes are selected).

The first step of a PCoA is the construction of a (dis)similarity matrix. While PCA (principal component analysis) is based on Euclidean distances, PCoA can handle (dis)similarity matrices calculated from quantitative, semi-quantitative, qualitative, and mixed variables. As always, the choice of (dis)similarity measure is critical and must be suitable to the data in question. For count data, Bray-Curtis distance is recommended. You can use Jaccard index for presence/absence data. When the distance metric is Euclidean, PCoA is equivalent to PCA.

The first PCoA compares similarity between tundra ecosystems by incorporating the combined dataset.

# Run PCoA analysis on the Bray-Curtis dissimilarity matrix
gpm.all.bc.pcoa<-pcoa(gpm.all.bc.dist)

Extract the eigenvalues and calculate the variation explained by each axis.

pcoa.dna.all<-cmdscale(gpm.all.bc.dist, eig=TRUE, k=2)
pcoa.dna.all
$points
                [,1]        [,2]
WS1-T0    -0.3547752  0.04884660
WS2-T0    -0.3522181  0.22900408
WS3-T0    -0.3024513 -0.22952916
WS1-T4    -0.3580691  0.05718926
WS2-T4    -0.3473847  0.23428604
WS3-T4    -0.2826346 -0.29264205
WS1-T24   -0.3549740  0.06112501
WS2-T24   -0.3450039  0.18226438
WS3-T24   -0.2466910 -0.35532682
Tuss1-T0   0.5215337  0.03092877
Tuss2-T0   0.4996903  0.03380238
Tuss1-T4   0.5016452  0.03720668
Tuss2-T4   0.5235905  0.04159448
Tuss1-T24  0.5119603  0.01237679
Tuss3-T24  0.3857819 -0.09112643

$eig
 [1] 2.434476e+00 4.281970e-01 2.090461e-01 1.589313e-01 1.498846e-01 8.520537e-02 7.310245e-02
 [8] 6.279407e-02 5.962779e-02 5.071524e-02 4.608667e-02 4.261096e-02 4.030625e-02 3.946897e-02
[15] 5.789029e-17

$x
NULL

$ac
[1] 0

$GOF
[1] 0.7377163 0.7377163
# Calculate the percent variation explained by Axis 1
pcoa.dna.all.exp.var1<-round(pcoa.dna.all$eig[1] / sum(pcoa.dna.all$eig), 2) * 100
pcoa.dna.all.exp.var1
[1] 63
# Calculate the percent variation explained by Axis 2
pcoa.dna.all.exp.var2<-round(pcoa.dna.all$eig[2] / sum(pcoa.dna.all$eig), 2) * 100
pcoa.dna.all.exp.var2
[1] 11
# Sum the percent variation explained by both axes
pcoa.dna.all.sum.eig<-sum(pcoa.dna.all.exp.var1, pcoa.dna.all.exp.var2)
pcoa.dna.all.sum.eig
[1] 74

Plot the PCoA.

# Extract the plot scores from first two PCoA axes
gpm.all.bc.pcoa.axes <- gpm.all.bc.pcoa$vectors[,c(1,2)]

# Create new object with PCoA axes
all.dna.bc.pcoa<-data.frame(gpm.all.bc.pcoa.axes)

# Add Timepoint variable to the dataframe
all.dna.timepoint<-c('WS-MG-T0','WS-MG-T0','WS-MG-T0','WS-MG-T4','WS-MG-T4','WS-MG-T4','WS-MG-T24','WS-MG-T24','WS-MG-T24','Tuss-MG-T0','Tuss-MG-T0','Tuss-MG-T4','Tuss-MG-T4','Tuss-MG-T24','Tuss-MG-T24')
all.dna.pcoa.1<-all.dna.bc.pcoa$Axis.1
all.dna.pcoa.2<-all.dna.bc.pcoa$Axis.2
all.dna.bc.pcoa<-data.frame(all.dna.timepoint,all.dna.pcoa.1,all.dna.pcoa.2)

# Rename column headings
colnames(all.dna.bc.pcoa)<-c("Timepoint","PCoA_1","PCoA_2")

# Re-arrange samples for plotting PCoA
all.dna.bc.pcoa$Timepoint <- factor(all.dna.bc.pcoa$Timepoint, levels=c("Tuss-MG-T0","WS-MG-T0","Tuss-MG-T4","WS-MG-T4","Tuss-MG-T24","WS-MG-T24"))

# Plot the PCoA
all.dna.pcoa<-ggplot(data=all.dna.bc.pcoa, aes(x=PCoA_1, y=PCoA_2, group=Timepoint, color=Timepoint)) + geom_point(aes(shape=Timepoint, size=0.75, fill=Timepoint)) + scale_fill_manual(values=c("gray83", "black", "gray83", "black", "gray83", "black")) + scale_shape_manual(values=c(21,21,22,22,24,24)) + scale_color_manual(values=c("black", "black", "black", "black", "black", "black")) + xlab("PCoA 1 (63%)") + ylab("PCoA 2 (11%)") + theme_classic() + theme(axis.text=element_text(size=10), axis.title=element_text(size=12), legend.position = "bottom", legend.title=element_blank(), legend.text=element_text(size=10)) + guides(shape = guide_legend(override.aes = list(size = 3))) + scale_size(guide="none") + geom_hline(aes(yintercept = 0), color="gray", linetype="dashed") + geom_vline(aes(xintercept=0), color="gray", linetype="dashed") + ylim(-0.6,0.6) + xlim(-0.6,0.6) + annotate(geom="text", x=0.0, y=0.59, label="PERMANOVA")   + annotate("text", x = 0, y = 0.52, size=3, label = "Tundra~(italic(p) == 0.001)", parse = TRUE) + annotate("text", x = 0, y = 0.45, size=3, label = "Time~Point~(italic(p) == 0.755)", parse = TRUE) + annotate("text", x = 0, y = 0.38, size=3, label = "Tundra:Time~Point~(italic(p) == 0.622)", parse = TRUE)
all.dna.pcoa

The second PCoA compares similarity between sampling time points within the Tussock tundra ecosystem.

# Run PCoA analysis on the Bray-Curtis dissimilarity matrix
gpm.tuss.bc.pcoa<-pcoa(gpm.tuss.bc.dist)

Extract the eigenvalues and calculate the variation explained by each axis.

pcoa.dna.tuss<-cmdscale(gpm.tuss.bc.dist, eig=TRUE, k=2)
pcoa.dna.tuss
$points
                 [,1]         [,2]
Tuss1-T0  -0.07908183 -0.007909558
Tuss2-T0  -0.10503550  0.223722911
Tuss1-T4  -0.08734384 -0.288993333
Tuss2-T4  -0.12372951  0.110993812
Tuss1-T24 -0.03580132 -0.059260114
Tuss3-T24  0.43099199  0.021446282

$eig
[1]  2.272602e-01  1.499230e-01  8.571933e-02  5.982460e-02  3.952645e-02 -5.141230e-18

$x
NULL

$ac
[1] 0

$GOF
[1] 0.6708418 0.6708418
# Calculate the percent variation explained by Axis 1
pcoa.dna.tuss.exp.var1<-round(pcoa.dna.tuss$eig[1] / sum(pcoa.dna.tuss$eig), 2) * 100
pcoa.dna.tuss.exp.var1
[1] 40
# Calculate the percent variation explained by Axis 2
pcoa.dna.tuss.exp.var2<-round(pcoa.dna.tuss$eig[2] / sum(pcoa.dna.tuss$eig), 2) * 100
pcoa.dna.tuss.exp.var2
[1] 27
# Sum the percent variation explained by both axes
pcoa.dna.tuss.sum.eig<-sum(pcoa.dna.tuss.exp.var1, pcoa.dna.tuss.exp.var2)
pcoa.dna.tuss.sum.eig
[1] 67

Plot the PCoA.

# Extract the plot scores from first two PCoA axes
gpm.tuss.bc.pcoa.axes <- gpm.tuss.bc.pcoa$vectors[,c(1,2)]

# Create new object with PCoA axes
tuss.dna.bc.pcoa<-data.frame(gpm.tuss.bc.pcoa.axes)

# Add Timepoint variable to the dataframe
tuss.dna.timepoint<-c('Tuss-T0','Tuss-T0','Tuss-T4','Tuss-T4','Tuss-T24','Tuss-T24')
tuss.dna.pcoa.1<-tuss.dna.bc.pcoa$Axis.1
tuss.dna.pcoa.2<-tuss.dna.bc.pcoa$Axis.2
tuss.dna.bc.pcoa<-data.frame(tuss.dna.timepoint,tuss.dna.pcoa.1,tuss.dna.pcoa.2)

# Rename column headings
colnames(tuss.dna.bc.pcoa)<-c("Timepoint","PCoA_1","PCoA_2")
#tuss.dna.bc.pcoa

# Re-arrange samples for plotting PCoA
tuss.dna.bc.pcoa$Timepoint<-factor(tuss.dna.bc.pcoa$Timepoint, levels=c("Tuss-T0","Tuss-T4","Tuss-T24"))

# Plot the PCoA
tuss.dna.pcoa<-ggplot(data=tuss.dna.bc.pcoa, aes(x=PCoA_1, y=PCoA_2, group=Timepoint, color=Timepoint)) + geom_point(aes(shape=Timepoint, size=0.75, fill=Timepoint)) + scale_fill_manual(values=c("palegreen","green3","darkgreen")) + scale_shape_manual(values=c(21,24,22)) + scale_color_manual(values=c("black","black","black")) + xlab("PCoA 1 (40%)") + ylab("PCoA 2 (27%)") + theme_minimal() + theme(axis.text=element_text(size=12),axis.title=element_text(size=14))+ theme(legend.position = "bottom", legend.title=element_blank(), legend.text=element_text(size=12), panel.background = element_blank(), panel.grid.major=element_blank(), panel.grid.minor = element_blank(), axis.line = element_line(colour = "gray"), panel.border = element_rect(colour = "gray", fill=NA, size=1)) + scale_size(guide=FALSE) + guides(shape = guide_legend(override.aes = list(size = 3))) + geom_hline(aes(yintercept = 0), color="gray", linetype="dashed") + geom_vline(aes(xintercept=0), color="gray", linetype="dashed") + ylim(-0.5,0.5) + xlim(-0.5,0.5) + annotate(geom="text", x=0.0, y=0.49, label="PERMANOVA") + annotate("text", x = 0, y = 0.42, size=3, label = "Time~Point~(italic(p) == 0.400)", parse = TRUE)
tuss.dna.pcoa

The third PCoA compares similarity between sampling time points within the Wet Sedge tundra ecosystem.

# Run PCoA analysis on the Bray-Curtis dissimilarity matrix
gpm.ws.bc.pcoa<-pcoa(gpm.ws.bc.dist)

Extract the eigenvalues and calculate the variation explained by each axis.

pcoa.dna.ws<-cmdscale(gpm.ws.bc.dist, eig=TRUE, k=2)
pcoa.dna.ws
$points
               [,1]        [,2]
WS1-T0   0.06162191  0.18032456
WS2-T0   0.23783608 -0.09068283
WS3-T0  -0.22544893 -0.01858857
WS1-T4   0.06996095  0.17149145
WS2-T4   0.24251872 -0.11274994
WS3-T4  -0.29156305 -0.04368470
WS1-T24  0.07316666  0.18451007
WS2-T24  0.19088361 -0.18508676
WS3-T24 -0.35897595 -0.08553329

$eig
[1] 4.305630e-01 1.607331e-01 7.319049e-02 6.280428e-02 5.078482e-02 4.656522e-02 4.263403e-02
[8] 4.031109e-02 2.654107e-17

$x
NULL

$ac
[1] 0

$GOF
[1] 0.6515042 0.6515042
# Calculate the percent variation explained by Axis 1
pcoa.dna.ws.exp.var1<-round(pcoa.dna.ws$eig[1] / sum(pcoa.dna.ws$eig), 2) * 100
pcoa.dna.ws.exp.var1
[1] 47
# Calculate the percent variation explained by Axis 2
pcoa.dna.ws.exp.var2<-round(pcoa.dna.ws$eig[2] / sum(pcoa.dna.ws$eig), 2) * 100
pcoa.dna.ws.exp.var2
[1] 18
# Sum the percent variation explained by both axes
pcoa.dna.ws.sum.eig<-sum(pcoa.dna.ws.exp.var1, pcoa.dna.ws.exp.var2)
pcoa.dna.ws.sum.eig
[1] 65

Plot the PCoA.

# Extract the plot scores from first two PCoA axes
gpm.ws.bc.pcoa.axes <- gpm.ws.bc.pcoa$vectors[,c(1,2)]

# Create new object with PCoA axes
ws.dna.bc.pcoa<-data.frame(gpm.ws.bc.pcoa.axes)

# Add Timepoint variable to the dataframe
ws.dna.timepoint<-c('WS-T0','WS-T0','WS-T0','WS-T4','WS-T4','WS-T4','WS-T24','WS-T24','WS-T24')
ws.dna.pcoa.1<-ws.dna.bc.pcoa$Axis.1
ws.dna.pcoa.2<-ws.dna.bc.pcoa$Axis.2
ws.dna.bc.pcoa<-data.frame(ws.dna.timepoint,ws.dna.pcoa.1,ws.dna.pcoa.2)

# Rename column headings
colnames(ws.dna.bc.pcoa)<-c("Timepoint","PCoA_1","PCoA_2")
#ws.dna.bc.pcoa

# Re-arrange samples for plotting PCoA
ws.dna.bc.pcoa$Timepoint<-factor(ws.dna.bc.pcoa$Timepoint, levels=c("WS-T0","WS-T4","WS-T24"))

# Plot the PCoA
ws.dna.pcoa<-ggplot(data=ws.dna.bc.pcoa, aes(x=PCoA_1, y=PCoA_2, group=Timepoint, color=Timepoint)) + geom_point(aes(shape=Timepoint, size=0.75, fill=Timepoint)) + scale_fill_manual(values=c("black","black","black")) + scale_shape_manual(values=c(21,24,22)) + scale_color_manual(values=c("gray83","gray83","gray83")) + xlab("PCoA 1 (47%)") + ylab("PCoA 2 (18%)") + theme_minimal() + theme(axis.text=element_text(size=12),axis.title=element_text(size=14))+ theme(legend.position = "bottom", legend.title=element_blank(), legend.text=element_text(size=12), panel.background = element_blank(), panel.grid.major=element_blank(), panel.grid.minor = element_blank(), axis.line = element_line(colour = "gray"), panel.border = element_rect(colour = "gray", fill=NA, size=1)) + scale_size(guide=FALSE) + guides(shape = guide_legend(override.aes = list(size = 3))) + geom_hline(aes(yintercept = 0), color="gray", linetype="dashed") + geom_vline(aes(xintercept=0), color="gray", linetype="dashed") + ylim(-0.5,0.5) + xlim(-0.5,0.5) + annotate(geom="text", x=0.0, y=0.49, label="PERMANOVA") + annotate("text", x = 0, y = 0.42, size=3, label = "Time~Point~(italic(p) == 0.916)", parse = TRUE)
ws.dna.pcoa

7.2.2.4. PERMANOVA
  • Run PERMANOVA using adonis function of the Vegan package

PERMANOVA - GPM-All - Bray-Curtis

adonis(gpm.all.bc.dist~gpm_all_veg*gpm_all_time, data=gpm_all_groups)

Call:
adonis(formula = gpm.all.bc.dist ~ gpm_all_veg * gpm_all_time,      data = gpm_all_groups) 

Permutation: free
Number of permutations: 999

Terms added sequentially (first to last)

                         Df SumsOfSqs MeanSqs F.Model      R2 Pr(>F)    
gpm_all_veg               1    2.4106 2.41061 19.2740 0.62122  0.001 ***
gpm_all_time              2    0.1639 0.08197  0.6554 0.04225  0.766    
gpm_all_veg:gpm_all_time  2    0.1803 0.09014  0.7207 0.04646  0.613    
Residuals                 9    1.1256 0.12507         0.29008           
Total                    14    3.8805                 1.00000           
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

PERMANOVA - GPM-Tuss - Bray-Curtis

adonis(gpm.tuss.bc.dist~gpm_tuss_time, data=gpm_tuss_groups)
'nperm' >= set of all permutations: complete enumeration.
Set of permutations < 'minperm'. Generating entire set.

Call:
adonis(formula = gpm.tuss.bc.dist ~ gpm_tuss_time, data = gpm_tuss_groups) 

Permutation: free
Number of permutations: 719

Terms added sequentially (first to last)

              Df SumsOfSqs MeanSqs F.Model      R2 Pr(>F)
gpm_tuss_time  2   0.23188 0.11594  1.0528 0.41241    0.4
Residuals      3   0.33037 0.11013         0.58759       
Total          5   0.56225                 1.00000       

PERMANOVA - GPM-WS - Bray-Curtis

adonis(gpm.ws.bc.dist~gpm_ws_time, data=gpm_ws_groups)

Call:
adonis(formula = gpm.ws.bc.dist ~ gpm_ws_time, data = gpm_ws_groups) 

Permutation: free
Number of permutations: 999

Terms added sequentially (first to last)

            Df SumsOfSqs  MeanSqs F.Model      R2 Pr(>F)
gpm_ws_time  2   0.11233 0.056163 0.42373 0.12376  0.917
Residuals    6   0.79526 0.132543         0.87624       
Total        8   0.90759                  1.00000       

7.3. KEGG Tier Patterns

Look for differences in gene expression at multiple KEGG tier levels (II-IV) using GPM-normalized values.

7.3.1. Tussock Tundra

Look at differences in gene expression patterns for multiple Tier levels within the Tussock tundra between sampling time points.

7.3.1.1. Tier II Expression
# Calculate GPM-normalized gene count sums for each Tuss sample in each Tier II category
tuss_dna_tII_sum<-gpm_all_pot_ann %>% group_by(Tier_II) %>% summarise_at(vars("S107107","S107108","S107116","S107117","S107119","S107121"), sum)

tuss_dna_tII_sum<-tuss_dna_tII_sum %>% mutate_at(vars(S107107,S107108,S107116,S107117,S107119,S107121), funs(round(., 0)))

tuss_dna_tII_sum<-as.data.frame(tuss_dna_tII_sum)

tuss_dna_tII_sum<-tuss_dna_tII_sum[order(-tuss_dna_tII_sum$S107107),]

Heatmap for Tier II categories by sampling timepoints

# Create copy of "ws_tII_sum" object to prep for heatmap
tuss_dna_tII_heatmap<-tuss_dna_tII_sum

# Convert the first column (Tier categories) into rownames
rownames(tuss_dna_tII_heatmap) <- tuss_dna_tII_heatmap$Tier_II
tuss_dna_tII_heatmap<-as.data.frame(tuss_dna_tII_heatmap[-1])

# Rename columns to sample IDs
colnames(tuss_dna_tII_heatmap)<-c("Tuss1-T0","Tuss2-T0","Tuss1-T4","Tuss2-T4","Tuss1-T24","Tuss3-T24")

# Remove rows for "Organismal Systems" and "Human Diseases"
#tuss_dna_tII_heatmap <- tuss_dna_tII_heatmap[-c(5,6),]

# Convert dataframe into a matrix for heatmap
tuss_dna_tII_heatmap<-as.matrix(tuss_dna_tII_heatmap)

# Scale matrix values to generate Z-scores
tuss_dna_tII_heatmap<-scale(t(tuss_dna_tII_heatmap))

tuss_dna_tII_heatmap<-t(tuss_dna_tII_heatmap)

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)

# Pheatmap
pheatmap(tuss_dna_tII_heatmap, treeheight_row = 0, treeheight_col = 0,cluster_rows = FALSE, cluster_cols = FALSE)

Summed values by replicate for each KEGG tier II category.

Tussock Tier II KEGG category summary by sample.
Tier_II S107107 S107108 S107116 S107117 S107119 S107121
4 Metabolism 696,177 697,050 691,198 696,295 690,674 673,053
3 Genetic Information Processing 154,049 153,683 156,607 153,035 156,642 155,088
2 Environmental Information Processing 105,480 103,922 106,705 106,132 107,735 121,853
1 Cellular Processes 44,293 45,345 45,489 44,538 44,949 50,006

Calculate mean values from the replicate sums

# Calculate mean values from the replicate sums
tuss_dna_tII_sum$meantuss_T0<-apply(tuss_dna_tII_sum[,2:3], 1, mean)
tuss_dna_tII_sum$meantuss_T4<-apply(tuss_dna_tII_sum[,4:5], 1, mean)
tuss_dna_tII_sum$meantuss_T24<-apply(tuss_dna_tII_sum[,6:7], 1, mean)
tuss_dna_tII_sum<-tuss_dna_tII_sum %>% mutate_at(vars(meantuss_T0,meantuss_T4,meantuss_T24), funs(round(., 0)))

# Calculate sd values from the replicate sums
tuss_dna_tII_sum$sdtuss_T0<-apply(tuss_dna_tII_sum[,2:3], 1, sd)
tuss_dna_tII_sum$sdtuss_T4<-apply(tuss_dna_tII_sum[,4:5], 1, sd)
tuss_dna_tII_sum$sdtuss_T24<-apply(tuss_dna_tII_sum[,6:7], 1, sd)
tuss_dna_tII_sum<-tuss_dna_tII_sum %>% mutate_at(vars(sdtuss_T0,sdtuss_T4,sdtuss_T24), funs(round(., 0)))

# Subset Mean values
tuss_dna_tII_mean<-subset(tuss_dna_tII_sum, select=c(Tier_II,meantuss_T0,meantuss_T4,meantuss_T24))
names(tuss_dna_tII_mean)<-c("Tier II", "Tuss-T0", "Tuss-T4", "Tuss-T24")

# Subset SD values
tuss_dna_tII_sd<-subset(tuss_dna_tII_sum, select=c(Tier_II,sdtuss_T0,sdtuss_T4,sdtuss_T24))
names(tuss_dna_tII_sd)<-c("Tier II", "Tuss-T0", "Tuss-T4", "Tuss-T24")

# Remember "Tier II" as non-numeric values
tuss_dna_tII_mean_TierII<-tuss_dna_tII_mean$`Tier II`
tuss_dna_tII_sd_TierII<-tuss_dna_tII_sd$`Tier II`

# Transpose all but first column (Tier II)
tuss_dna_tII_mean<-as.data.frame(t(tuss_dna_tII_mean[,-1]))
colnames(tuss_dna_tII_mean)<-tuss_dna_tII_mean_TierII
tuss_dna_tII_sd<-as.data.frame(t(tuss_dna_tII_sd[,-1]))
colnames(tuss_dna_tII_sd)<-tuss_dna_tII_sd_TierII

# Combine mean and sd into single column with ± divider
tuss_dna_tII_table<-as.data.frame(do.call(cbind, lapply(1:ncol(tuss_dna_tII_mean), function(i) paste0(tuss_dna_tII_mean[ , i], " ± ", tuss_dna_tII_sd[ , i]))))

# Transpose the table back
tuss_dna_tII_table<-t(tuss_dna_tII_table)

# Rename columns to Sites
colnames(tuss_dna_tII_table)<-c("Tussock (T0)", "Tussock (T4)", "Tussock (T24)")

rownames(tuss_dna_tII_table)<-tuss_dna_tII_mean_TierII

kable(tuss_dna_tII_table, caption = "Tussock Tier II KEGG category averages (± standard deviation) by sample for Metagenomes.", format.args = list(big.mark=","), align = "l") %>% kable_styling(bootstrap_options = c("striped","hover","condensed"))
Tussock Tier II KEGG category averages (± standard deviation) by sample for Metagenomes.
Tussock (T0) Tussock (T4) Tussock (T24)
Metabolism 696614 ± 617 693746 ± 3604 681864 ± 12460
Genetic Information Processing 153866 ± 259 154821 ± 2526 155865 ± 1099
Environmental Information Processing 104701 ± 1102 106418 ± 405 114794 ± 9983
Cellular Processes 44819 ± 744 45014 ± 672 47478 ± 3576

Run statistical tests to determine if significant differences exist between sampling timepoints for each Tier KEGG category in the metagenome. Click on the Show/Hide button to see the statistics.

# Subset the "sum" values for each sample
tuss_dna_tII_stats<-subset(tuss_dna_tII_sum, select=c(Tier_II,S107107,S107108,S107116,S107117,S107119,S107121))

rownames(tuss_dna_tII_stats) <- tuss_dna_tII_stats$Tier_II
tuss_dna_tII_stats<-as.data.frame(t(tuss_dna_tII_stats[-1]))

# Create a column with timepoint variable names
Timepoint<-c("T0","T0","T4","T4","T24","T24")
Timepoint<-data.frame(Timepoint)

# Add the timepoint column to the sum table
tuss_dna_tII_stats<-data.frame(Timepoint,tuss_dna_tII_stats)

# Subset response variables for MANOVA
tuss_dna_tII_stats$response <- as.matrix(tuss_dna_tII_stats[, 2:5])

# MANOVA test
tuss_dna_tII_manova <- manova(response ~ Timepoint, data=tuss_dna_tII_stats)
summary.aov(tuss_dna_tII_manova)
 Response Metabolism. :
            Df    Sum Sq   Mean Sq F value Pr(>F)
Timepoint    2 244658585 122329293  2.1764 0.2606
Residuals    3 168620589  56206863               

 Response Genetic.Information.Processing. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 3998641 1999321  0.7836 0.5323
Residuals    3 7654028 2551343               

 Response Environmental.Information.Processing. :
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint    2 116644970 58322485  1.7317 0.3162
Residuals    3 101036809 33678936               

 Response Cellular.Processes. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  8784499 4392249  0.9554 0.4775
Residuals    3 13792177 4597392               

Run ANOVA for each category of interest (significant in MANOVA)

# Metabolism
tuss_dna_tII_aov1<-aov(Metabolism.~Timepoint,data=tuss_dna_tII_stats)
summary.aov(tuss_dna_tII_aov1)
            Df    Sum Sq   Mean Sq F value Pr(>F)
Timepoint    2 244658585 122329293   2.176  0.261
Residuals    3 168620589  56206863               
TukeyHSD(tuss_dna_tII_aov1)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Metabolism. ~ Timepoint, data = tuss_dna_tII_stats)

$Timepoint
         diff      lwr     upr     p adj
T24-T0 -14750 -46078.7 16578.7 0.2664497
T4-T0   -2867 -34195.7 28461.7 0.9245050
T4-T24  11883 -19445.7 43211.7 0.3760893
# Genetic Information Processing
tuss_dna_tII_aov2<-aov(Genetic.Information.Processing.~Timepoint,data=tuss_dna_tII_stats)
summary.aov(tuss_dna_tII_aov2)
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 3998641 1999321   0.784  0.532
Residuals    3 7654028 2551343               
TukeyHSD(tuss_dna_tII_aov2)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Genetic.Information.Processing. ~ Timepoint, data = tuss_dna_tII_stats)

$Timepoint
        diff       lwr      upr     p adj
T24-T0  1999 -4675.706 8673.706 0.5065378
T4-T0    955 -5719.706 7629.706 0.8311240
T4-T24 -1044 -7718.706 5630.706 0.8037170
# Environmental Information Processing
tuss_dna_tII_aov3<-aov(Environmental.Information.Processing.~Timepoint,data=tuss_dna_tII_stats)
summary.aov(tuss_dna_tII_aov3)
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint    2 116644970 58322485   1.732  0.316
Residuals    3 101036809 33678936               
TukeyHSD(tuss_dna_tII_aov3)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Environmental.Information.Processing. ~ Timepoint, data = tuss_dna_tII_stats)

$Timepoint
          diff       lwr      upr     p adj
T24-T0 10093.0 -14157.85 34343.85 0.3271200
T4-T0   1717.5 -22533.35 25968.35 0.9535973
T4-T24 -8375.5 -32626.35 15875.35 0.4273774
# Cellular Processing
tuss_dna_tII_aov4<-aov(Cellular.Processes.~Timepoint,data=tuss_dna_tII_stats)
summary.aov(tuss_dna_tII_aov4)
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  8784499 4392249   0.955  0.477
Residuals    3 13792177 4597392               
TukeyHSD(tuss_dna_tII_aov4)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Cellular.Processes. ~ Timepoint, data = tuss_dna_tII_stats)

$Timepoint
          diff        lwr       upr     p adj
T24-T0  2658.5  -6301.407 11618.407 0.5116856
T4-T0    194.5  -8765.407  9154.407 0.9954805
T4-T24 -2464.0 -11423.907  6495.907 0.5532109

Plot the KEGG tier II categories as a barchart.

# Place the KEGG tier II categories in the preferred order for plotting
tuss_dna_tII_bardata$Tier.II <- factor(tuss_dna_tII_bardata$Tier.II,levels = c("Metabolism", "Genetic Information Processing", "Environmental Information Processing", "Cellular Processes"))

tuss_dna_tII_bardata$Sample <- factor(tuss_dna_tII_bardata$Sample,levels=c("Tuss-T0","Tuss-T4","Tuss-T24"))

tuss_dna_tII_barplot<-ggplot(tuss_dna_tII_bardata, aes(x = Tier.II, y = Mean, fill = Sample)) + geom_bar(stat = "identity", position = "dodge", color="black") + geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2, position = position_dodge(0.9)) + ylab(expression(atop("KEGG Tier II Categories", paste("Gene Counts (GPM)")))) + theme_minimal() + theme(axis.text=element_text(size=10), axis.title=element_text(size=12), axis.title.x=element_blank()) + theme(legend.position = "bottom", legend.title=element_blank(), legend.text=element_text(size=10), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_line(colour = "gray"), panel.border = element_rect(colour = "gray", fill=NA, size=1)) + scale_size(guide=FALSE) + scale_fill_manual(values=c("palegreen", "green3", "darkgreen")) + scale_x_discrete(labels = function(Tier.II) str_wrap(Tier.II, width = 10)) + ylim(0,800000) + annotate(geom="text", x=1.0, y=777500, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=2.0, y=250000, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=3.0, y=200000, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=4.0, y=150000, label="italic(N.S.)", parse=TRUE)
tuss_dna_tII_barplot

7.3.1.2. Tier III Expression

Calculate GPM-normalized gene count sums for each Tuss sample in each Tier III category.

# Calculate GPM-normalized gene count sums for each Tuss sample in each Tier III category
tuss_dna_tIII_sum<-gpm_all_pot_ann %>% group_by(Tier_III) %>% summarise_at(vars("S107107","S107108","S107116","S107117","S107119","S107121"), sum)
tuss_dna_tIII_sum<-tuss_dna_tIII_sum %>% mutate_at(vars(S107107,S107108,S107116,S107117,S107119,S107121), funs(round(., 0)))
tuss_dna_tIII_sum<-as.data.frame(tuss_dna_tIII_sum)
tuss_dna_tIII_sum<-tuss_dna_tIII_sum[order(-tuss_dna_tIII_sum$S107107),]
# Calculate mean values from the replicate sums
tuss_dna_tIII_sum$meantuss_T0<-apply(tuss_dna_tIII_sum[,2:3], 1, mean)
tuss_dna_tIII_sum$meantuss_T4<-apply(tuss_dna_tIII_sum[,4:5], 1, mean)
tuss_dna_tIII_sum$meantuss_T24<-apply(tuss_dna_tIII_sum[,6:7], 1, mean)
tuss_dna_tIII_sum<-tuss_dna_tIII_sum %>% mutate_at(vars(meantuss_T0,meantuss_T4,meantuss_T24), funs(round(., 0)))

# Calculate sd values from the replicate sums
tuss_dna_tIII_sum$sdtuss_T0<-apply(tuss_dna_tIII_sum[,2:3], 1, sd)
tuss_dna_tIII_sum$sdtuss_T4<-apply(tuss_dna_tIII_sum[,4:5], 1, sd)
tuss_dna_tIII_sum$sdtuss_T24<-apply(tuss_dna_tIII_sum[,6:7], 1, sd)
tuss_dna_tIII_sum<-tuss_dna_tIII_sum %>% mutate_at(vars(sdtuss_T0,sdtuss_T4,sdtuss_T24), funs(round(., 0)))

# Write data to .csv file
write.csv(tuss_dna_tIII_sum, 'Norm.Results/tuss.dna.tIII.mean.sd.csv')

# Subset Mean values
tuss_dna_tIII_mean<-subset(tuss_dna_tIII_sum, select=c(Tier_III,meantuss_T0,meantuss_T4,meantuss_T24))
names(tuss_dna_tIII_mean)<-c("Tier III", "Tuss-T0", "Tuss-T4", "Tuss-T24")

# Subset SD values
tuss_dna_tIII_sd<-subset(tuss_dna_tIII_sum, select=c(Tier_III,sdtuss_T0,sdtuss_T4,sdtuss_T24))
names(tuss_dna_tIII_sd)<-c("Tier III", "Tuss-T0", "Tuss-T4", "Tuss-T24")

# Remember "Tier III" as non-numeric values
tuss_dna_tIII_mean_TierIII<-tuss_dna_tIII_mean$`Tier III`
tuss_dna_tIII_sd_TierIII<-tuss_dna_tIII_sd$`Tier III`

# Transpose all but first column (Tier II)
tuss_dna_tIII_mean<-as.data.frame(t(tuss_dna_tIII_mean[,-1]))
colnames(tuss_dna_tIII_mean)<-tuss_dna_tIII_mean_TierIII
tuss_dna_tIII_sd<-as.data.frame(t(tuss_dna_tIII_sd[,-1]))
colnames(tuss_dna_tIII_sd)<-tuss_dna_tIII_sd_TierIII

# Combine mean and sd into single column with ± divider
tuss_dna_tIII_table<-as.data.frame(do.call(cbind, lapply(1:ncol(tuss_dna_tIII_mean), function(i) paste0(tuss_dna_tIII_mean[ , i], " ± ", tuss_dna_tIII_sd[ , i]))))

# Transpose the table back
tuss_dna_tIII_table<-t(tuss_dna_tIII_table)

# Rename columns to Sites
colnames(tuss_dna_tIII_table)<-c("Tussock (T0)", "Tussock (T4)", "Tussock (T24)")

rownames(tuss_dna_tIII_table)<-tuss_dna_tIII_mean_TierIII

#tuss_dna_tIII_table

Run statistical tests to determine if significant differences exist between sampling timepoints for each Tier KEGG category. Click on the Show/Hide button to see the statistics.

# Subset the "sum" values for each sample
tuss_dna_tIII_stats<-subset(tuss_dna_tIII_sum, select=c(Tier_III,S107107,S107108,S107116,S107117,S107119,S107121))

rownames(tuss_dna_tIII_stats) <- tuss_dna_tIII_stats$Tier_III
tuss_dna_tIII_stats<-as.data.frame(t(tuss_dna_tIII_stats[-1]))

# Add the timepoint column to the sum table
tuss_dna_tIII_stats<-data.frame(Timepoint,tuss_dna_tIII_stats)

# Subset response variables for MANOVA
tuss_dna_tIII_stats$response <- as.matrix(tuss_dna_tIII_stats[, 2:26])

# MANOVA test
tuss_dna_tIII_manova <- manova(response ~ Timepoint, data=tuss_dna_tIII_stats)
summary.aov(tuss_dna_tIII_manova)
 Response Overview. :
            Df   Sum Sq  Mean Sq F value Pr(>F)
Timepoint    2 42034360 21017180  2.0957 0.2694
Residuals    3 30085634 10028545               

 Response Carbohydrate.metabolism. :
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint    2 132577817 66288909    1.79 0.3079
Residuals    3 111100140 37033380               

 Response Nucleotide.metabolism. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 959180  479590  1.5945 0.3375
Residuals    3 902320  300773               

 Response Translation. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 7360526 3680263  3.1084 0.1857
Residuals    3 3551926 1183975               

 Response Metabolism.of.cofactors.and.vitamins. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 17149824 8574912  3.2617 0.1768
Residuals    3  7886993 2628998               

 Response Energy.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 9711847 4855923  3.4007 0.1693
Residuals    3 4283807 1427936               

 Response Membrane.transport. :
            Df   Sum Sq  Mean Sq F value Pr(>F)
Timepoint    2 69812216 34906108  1.2894 0.3943
Residuals    3 81213631 27071210               

 Response Amino.acid.metabolism. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  8808313 4404157  1.2648 0.3996
Residuals    3 10445923 3481974               

 Response Signal.transduction. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 7370262 3685131  3.5366 0.1625
Residuals    3 3125969 1041990               

 Response Replication.and.repair. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 1372254  686127  0.8732 0.5025
Residuals    3 2357335  785778               

 Response Folding..sorting.and.degradation. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  773563  386782  0.7449 0.5462
Residuals    3 1557649  519216               

 Response Lipid.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 2805296 1402648  1.0812  0.443
Residuals    3 3891903 1297301               

 Response Cellular.community...prokaryotes. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 190170   95085  0.3855 0.7096
Residuals    3 740006  246669               

 Response Metabolism.of.other.amino.acids. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 240681  120341  0.7848 0.5319
Residuals    3 459990  153330               

 Response Glycan.biosynthesis.and.metabolism. :
            Df  Sum Sq Mean Sq F value  Pr(>F)  
Timepoint    2 4081272 2040636  8.3617 0.05932 .
Residuals    3  732135  244045                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

 Response Metabolism.of.terpenoids.and.polyketides. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 1271419  635710  1.2821 0.3959
Residuals    3 1487561  495854               

 Response Cell.growth.and.death. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 1813585  906793   5.382 0.1018
Residuals    3  505460  168487               

 Response Xenobiotics.biodegradation.and.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 1582225  791113   2.958 0.1952
Residuals    3  802351  267450               

 Response Cell.motility. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  3494712 1747356  0.4893 0.6548
Residuals    3 10714089 3571363               

 Response Biosynthesis.of.other.secondary.metabolites. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  21589   10794  0.4887 0.6551
Residuals    3  66267   22089               

 Response Transport.and.catabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  332473  166236  0.2627  0.785
Residuals    3 1898500  632834               

 Response Transcription. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  25944   12972  0.0646 0.9387
Residuals    3 602335  200778               

 Response Cellular.community...eukaryotes. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2  2670.3  1335.2  0.3781 0.7137
Residuals    3 10592.5  3530.8               

 Response Signaling.molecules.and.interaction. :
            Df Sum Sq Mean Sq F value  Pr(>F)  
Timepoint    2 3502.3 1751.17  6.2803 0.08465 .
Residuals    3  836.5  278.83                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

 Response Enzyme.families. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint    2 0.33333 0.16667       1 0.4648
Residuals    3 0.50000 0.16667               
7.3.1.3. Tier IV Expression

Calculate GPM-normalized gene count sums for each Tuss sample in each Tier IV category.

# Calculate GPM-normalized gene count sums for each Tuss sample in each Tier III category
tuss_dna_tIV_sum<-gpm_all_pot_ann %>% group_by(Tier_IV) %>% summarise_at(vars("S107107","S107108","S107116","S107117","S107119","S107121"), sum)
tuss_dna_tIV_sum<-tuss_dna_tIV_sum %>% mutate_at(vars(S107107,S107108,S107116,S107117,S107119,S107121), funs(round(., 0)))
tuss_dna_tIV_sum<-as.data.frame(tuss_dna_tIV_sum)
tuss_dna_tIV_sum<-tuss_dna_tIV_sum[order(-tuss_dna_tIV_sum$S107107),]
# Calculate mean values from the replicate sums
tuss_dna_tIV_sum$meantuss_T0<-apply(tuss_dna_tIV_sum[,2:3], 1, mean)
tuss_dna_tIV_sum$meantuss_T4<-apply(tuss_dna_tIV_sum[,4:5], 1, mean)
tuss_dna_tIV_sum$meantuss_T24<-apply(tuss_dna_tIV_sum[,6:7], 1, mean)
tuss_dna_tIV_sum<-tuss_dna_tIV_sum %>% mutate_at(vars(meantuss_T0,meantuss_T4,meantuss_T24), funs(round(., 0)))

# Calculate sd values from the replicate sums
tuss_dna_tIV_sum$sdtuss_T0<-apply(tuss_dna_tIV_sum[,2:3], 1, sd)
tuss_dna_tIV_sum$sdtuss_T4<-apply(tuss_dna_tIV_sum[,4:5], 1, sd)
tuss_dna_tIV_sum$sdtuss_T24<-apply(tuss_dna_tIV_sum[,6:7], 1, sd)
tuss_dna_tIV_sum<-tuss_dna_tIV_sum %>% mutate_at(vars(sdtuss_T0,sdtuss_T4,sdtuss_T24), funs(round(., 0)))

# Write data to .csv file
write.csv(tuss_dna_tIV_sum, 'Norm.Results/tuss.dna.tIV.mean.sd.csv')

# Subset Mean values
tuss_dna_tIV_mean<-subset(tuss_dna_tIV_sum, select=c(Tier_IV,meantuss_T0,meantuss_T4,meantuss_T24))
names(tuss_dna_tIV_mean)<-c("Tier IV", "Tuss-T0", "Tuss-T4", "Tuss-T24")

# Subset SD values
tuss_dna_tIV_sd<-subset(tuss_dna_tIV_sum, select=c(Tier_IV,sdtuss_T0,sdtuss_T4,sdtuss_T24))
names(tuss_dna_tIV_sd)<-c("Tier IV", "Tuss-T0", "Tuss-T4", "Tuss-T24")

# Remember "Tier IV" as non-numeric values
tuss_dna_tIV_mean_TierIV<-tuss_dna_tIV_mean$`Tier IV`
tuss_dna_tIV_sd_TierIV<-tuss_dna_tIV_sd$`Tier IV`

# Transpose all but first column (Tier IV)
tuss_dna_tIV_mean<-as.data.frame(t(tuss_dna_tIV_mean[,-1]))
colnames(tuss_dna_tIV_mean)<-tuss_dna_tIV_mean_TierIV
tuss_dna_tIV_sd<-as.data.frame(t(tuss_dna_tIV_sd[,-1]))
colnames(tuss_dna_tIV_sd)<-tuss_dna_tIV_sd_TierIV

# Combine mean and sd into single column with ± divider
tuss_dna_tIV_table<-as.data.frame(do.call(cbind, lapply(1:ncol(tuss_dna_tIV_mean), function(i) paste0(tuss_dna_tIV_mean[ , i], " ± ", tuss_dna_tIV_sd[ , i]))))

# Transpose the table back
tuss_dna_tIV_table<-t(tuss_dna_tIV_table)

# Rename columns to Sites
colnames(tuss_dna_tIV_table)<-c("Tussock (T0)", "Tussock (T4)", "Tussock (T24)")

rownames(tuss_dna_tIV_table)<-tuss_dna_tIV_mean_TierIV

#tuss_dna_tIV_table

7.3.2. Wet Sedge Tundra

Look at differences in gene expression patterns for multiple Tier levels within the Wet Sedge tundra between sampling time points.

7.3.2.1. Tier II Expression

Calculate GPM-normalized gene count sums for each WS sample in each Tier II category.

# Calculate GPM-normalized gene count sums for each WS sample in each Tier II category
ws_dna_tII_sum<-gpm_all_pot_ann %>% group_by(Tier_II) %>% summarise_at(vars("S107104","S107105","S107106","S107110","S107111","S107112","S107113","S107114","S107115"), sum)

ws_dna_tII_sum<-ws_dna_tII_sum %>% mutate_at(vars(S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115), funs(round(., 0)))

ws_dna_tII_sum<-as.data.frame(ws_dna_tII_sum)

ws_dna_tII_sum<-ws_dna_tII_sum[order(-ws_dna_tII_sum$S107104),]
Wet Sedge Tier II KEGG category summary by sample in Metagenome.
Tier_II S107104 S107105 S107106 S107110 S107111 S107112 S107113 S107114 S107115
4 Metabolism 677,998 686,740 677,310 681,200 680,806 673,076 677,516 684,991 672,620
3 Genetic Information Processing 155,404 160,237 154,265 154,519 163,874 152,048 158,868 156,958 150,296
2 Environmental Information Processing 129,666 120,135 129,311 128,094 122,601 134,332 127,419 124,235 135,459
1 Cellular Processes 36,931 32,888 39,114 36,187 32,719 40,544 36,197 33,816 41,626

Heatmap for Tier II categories by sampling timepoints

# Create copy of "ws_dna_tII_sum" object to prep for heatmap
ws_dna_tII_heatmap<-ws_dna_tII_sum

# Convert the first column (Tier categories) into rownames
rownames(ws_dna_tII_heatmap) <- ws_dna_tII_heatmap$Tier_II
ws_dna_tII_heatmap<-as.data.frame(ws_dna_tII_heatmap[-1])

# Rename columns to sample IDs
colnames(ws_dna_tII_heatmap)<-c("WS1-T0","WS2-T0","WS3-T0","WS1-T4","WS2-T4","WS3-T4","WS1-T24","WS2-T24","WS3-T24")

# Remove rows for "Organismal Systems" and "Human Diseases"
#ws_dna_tII_heatmap <- ws_dna_tII_heatmap[-c(5,6),]

# Convert dataframe into a matrix for heatmap
ws_dna_tII_heatmap<-as.matrix(ws_dna_tII_heatmap)

# Scale matrix values to generate Z-scores
ws_dna_tII_heatmap<-scale(t(ws_dna_tII_heatmap))

ws_dna_tII_heatmap<-t(ws_dna_tII_heatmap)

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)

# Pheatmap
pheatmap(ws_dna_tII_heatmap, treeheight_row = 0, treeheight_col = 0,cluster_rows = FALSE, cluster_cols = FALSE)

Calculate mean values from the replicate sums.

# Calculate mean values from the replicate sums
ws_dna_tII_sum$meanWS_T0<-apply(ws_dna_tII_sum[,2:4], 1, mean)
ws_dna_tII_sum$meanWS_T4<-apply(ws_dna_tII_sum[,5:7], 1, mean)
ws_dna_tII_sum$meanWS_T24<-apply(ws_dna_tII_sum[,8:10], 1, mean)
ws_dna_tII_sum<-ws_dna_tII_sum %>% mutate_at(vars(meanWS_T0,meanWS_T4,meanWS_T24), funs(round(., 0)))

# Calculate sd values from the replicate sums
ws_dna_tII_sum$sdWS_T0<-apply(ws_dna_tII_sum[,2:4], 1, sd)
ws_dna_tII_sum$sdWS_T4<-apply(ws_dna_tII_sum[,5:7], 1, sd)
ws_dna_tII_sum$sdWS_T24<-apply(ws_dna_tII_sum[,8:10], 1, sd)
ws_dna_tII_sum<-ws_dna_tII_sum %>% mutate_at(vars(sdWS_T0,sdWS_T4,sdWS_T24), funs(round(., 0)))

# Subset Mean values
ws_dna_tII_mean<-subset(ws_dna_tII_sum, select=c(Tier_II,meanWS_T0,meanWS_T4,meanWS_T24))
names(ws_dna_tII_mean)<-c("Tier II", "WS - T0", "WS - T4", "WS - T24")

# Subset SD values
ws_dna_tII_sd<-subset(ws_dna_tII_sum, select=c(Tier_II,sdWS_T0,sdWS_T4,sdWS_T24))
names(ws_dna_tII_sd)<-c("Tier II", "WS - T0", "WS - T4", "WS - T24")

# Remember "Tier II" as non-numeric values
ws_dna_tII_mean_TierII<-ws_dna_tII_mean$`Tier II`
ws_dna_tII_sd_TierII<-ws_dna_tII_sd$`Tier II`

# Transpose all but first column (Tier II)
ws_dna_tII_mean<-as.data.frame(t(ws_dna_tII_mean[,-1]))
colnames(ws_dna_tII_mean)<-ws_dna_tII_mean_TierII
ws_dna_tII_sd<-as.data.frame(t(ws_dna_tII_sd[,-1]))
colnames(ws_dna_tII_sd)<-ws_dna_tII_sd_TierII

# Combine mean and sd into single column with ± divider
ws_dna_tII_table<-as.data.frame(do.call(cbind, lapply(1:ncol(ws_dna_tII_mean), function(i) paste0(ws_dna_tII_mean[ , i], " ± ", ws_dna_tII_sd[ , i]))))

# Transpose the table back
ws_dna_tII_table<-t(ws_dna_tII_table)

# Rename columns to Sites
colnames(ws_dna_tII_table)<-c("Wet Sedge (T0)", "Wet Sedge (T4)", "Wet Sedge (T24)")

rownames(ws_dna_tII_table)<-ws_dna_tII_mean_TierII

kable(ws_dna_tII_table, caption = "Wet Sedge Tier II KEGG category averages (± standard deviation) by sample.", format.args = list(big.mark=","), align = "l") %>% kable_styling(bootstrap_options = c("striped","hover","condensed"))
Wet Sedge Tier II KEGG category averages (± standard deviation) by sample.
Wet Sedge (T0) Wet Sedge (T4) Wet Sedge (T24)
Metabolism 680683 ± 5257 678361 ± 4581 678376 ± 6230
Genetic Information Processing 156635 ± 3171 156814 ± 6238 155374 ± 4500
Environmental Information Processing 126371 ± 5403 128342 ± 5869 129038 ± 5784
Cellular Processes 36311 ± 3159 36483 ± 3921 37213 ± 4003

Run statistical tests to determine if significant differences exist between sampling timepoints for each Tier KEGG category. Click on the Show/Hide button to see the statistics.

# Subset the "sum" values for each sample
ws_dna_tII_stats<-subset(ws_dna_tII_sum, select=c(Tier_II,S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115))

rownames(ws_dna_tII_stats) <- ws_dna_tII_stats$Tier_II
ws_dna_tII_stats<-as.data.frame(t(ws_dna_tII_stats[-1]))

# Create Timepoint object for WS_DNA (9 samples)
Timepoint2<-c("T0","T0","T0","T4","T4","T4","T24","T24","T24")
Timepoint2<-data.frame(Timepoint2)

# Add the timepoint column to the sum table
ws_dna_tII_stats<-data.frame(Timepoint2,ws_dna_tII_stats)

# Subset response variables for MANOVA
ws_dna_tII_stats$response <- as.matrix(ws_dna_tII_stats[, 2:5])

# MANOVA test
ws_dna_tII_manova <- manova(response ~ Timepoint2, data=ws_dna_tII_stats)
summary.aov(ws_dna_tII_manova)
 Response Metabolism. :
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2  10714158  5357079  0.1838 0.8366
Residuals    6 174872134 29145356               

 Response Genetic.Information.Processing. :
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2   3695405  1847702  0.0801  0.924
Residuals    6 138435221 23072537               

 Response Environmental.Information.Processing. :
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2  11483847  5741923  0.1774 0.8417
Residuals    6 194208216 32368036               

 Response Cellular.Processes. :
            Df   Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2  1375716   687858  0.0499 0.9517
Residuals    6 82751605 13791934               

Plot a barchart for Tier II categories by sampling timepoints.

# Place Tier II categories in the preferred order for plotting
ws_dna_tII_bardata$Tier.II <- factor(ws_dna_tII_bardata$Tier.II,levels = c("Metabolism", "Genetic Information Processing", "Environmental Information Processing", "Cellular Processes"))

ws_dna_tII_bardata$Sample <- factor(ws_dna_tII_bardata$Sample,levels=c("WS-T0","WS-T4","WS-T24"))

ws_dna_tII_barplot<-ggplot(ws_dna_tII_bardata, aes(x = Tier.II, y = Mean, fill = Sample)) + geom_bar(stat = "identity", position = "dodge", color="black") + geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2, position = position_dodge(0.9)) + ylab(expression(atop("KEGG Tier II Categories", paste("Gene Counts (GPM)")))) + theme_minimal() + theme(axis.text=element_text(size=10), axis.title=element_text(size=12), axis.title.x=element_blank()) + theme(legend.position = "bottom", legend.title=element_blank(), legend.text=element_text(size=10), panel.background = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_line(colour = "gray"), panel.border = element_rect(colour = "gray", fill=NA, size=1)) + scale_size(guide=FALSE) + scale_fill_manual(values=c("lightskyblue1","dodgerblue1","midnightblue")) +
  scale_x_discrete(labels = function(Tier.II) str_wrap(Tier.II, width = 10)) + ylim(0,800000) + annotate(geom="text", x=1.0, y=750000, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=2.0, y=250000, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=3.0, y=200000, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=4.0, y=150000, label="italic(N.S.)", parse=TRUE)
ws_dna_tII_barplot

7.3.2.2. Tier III Expression

Calculate GPM-normalized gene count sums for each WS sample in each Tier III category.

# Calculate GPM-normalized gene count sums for each WS sample in each Tier III category
ws_dna_tIII_sum<-gpm_all_pot_ann %>% group_by(Tier_III) %>% summarise_at(vars("S107104","S107105","S107106","S107110","S107111","S107112","S107113","S107114","S107115"), sum)
ws_dna_tIII_sum<-ws_dna_tIII_sum %>% mutate_at(vars(S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115), funs(round(., 0)))
ws_dna_tIII_sum<-as.data.frame(ws_dna_tIII_sum)
ws_dna_tIII_sum<-ws_dna_tIII_sum[order(-ws_dna_tIII_sum$S107104),]
# Calculate mean values from the replicate sums
ws_dna_tIII_sum$meanWS_T0<-apply(ws_dna_tIII_sum[,2:4], 1, mean)
ws_dna_tIII_sum$meanWS_T4<-apply(ws_dna_tIII_sum[,5:7], 1, mean)
ws_dna_tIII_sum$meanWS_T24<-apply(ws_dna_tIII_sum[,8:10], 1, mean)
ws_dna_tIII_sum<-ws_dna_tIII_sum %>% mutate_at(vars(meanWS_T0,meanWS_T4,meanWS_T24), funs(round(., 0)))

# Calculate sd values from the replicate sums
ws_dna_tIII_sum$sdWS_T0<-apply(ws_dna_tIII_sum[,2:4], 1, sd)
ws_dna_tIII_sum$sdWS_T4<-apply(ws_dna_tIII_sum[,5:7], 1, sd)
ws_dna_tIII_sum$sdWS_T24<-apply(ws_dna_tIII_sum[,8:10], 1, sd)
ws_dna_tIII_sum<-ws_dna_tIII_sum %>% mutate_at(vars(sdWS_T0,sdWS_T4,sdWS_T24), funs(round(., 0)))

# Write data to .csv file
write.csv(ws_dna_tIII_sum, 'Norm.Results/ws.dna.tIII.mean.sd.csv')

# Subset Mean values
ws_dna_tIII_mean<-subset(ws_dna_tIII_sum, select=c(Tier_III,meanWS_T0,meanWS_T4,meanWS_T24))
names(ws_dna_tIII_mean)<-c("Tier III", "WS - T0", "WS - T4", "WS - T24")

# Subset SD values
ws_dna_tIII_sd<-subset(ws_dna_tIII_sum, select=c(Tier_III,sdWS_T0,sdWS_T4,sdWS_T24))
names(ws_dna_tIII_sd)<-c("Tier III", "WS - T0", "WS - T4", "WS - T24")

# Remember "Tier III" as non-numeric values
ws_dna_tIII_mean_TierIII<-ws_dna_tIII_mean$`Tier III`
ws_dna_tIII_sd_TierIII<-ws_dna_tIII_sd$`Tier III`

# Transpose all but first column (Tier II)
ws_dna_tIII_mean<-as.data.frame(t(ws_dna_tIII_mean[,-1]))
colnames(ws_dna_tIII_mean)<-ws_dna_tIII_mean_TierIII
ws_dna_tIII_sd<-as.data.frame(t(ws_dna_tIII_sd[,-1]))
colnames(ws_dna_tIII_sd)<-ws_dna_tIII_sd_TierIII

# Combine mean and sd into single column with ± divider
ws_dna_tIII_table<-as.data.frame(do.call(cbind, lapply(1:ncol(ws_dna_tIII_mean), function(i) paste0(ws_dna_tIII_mean[ , i], " ± ", ws_dna_tIII_sd[ , i]))))

# Transpose the table back
ws_dna_tIII_table<-t(ws_dna_tIII_table)

# Rename columns to Sites
colnames(ws_dna_tIII_table)<-c("Wet Sedge (T0)", "Wet Sedge (T4)", "Wet Sedge (T24)")

rownames(ws_dna_tIII_table)<-ws_dna_tIII_mean_TierIII

#ws_dna_tIII_table

Run statistical tests to determine if significant differences exist between sampling timepoints for each Tier KEGG category. Click on the Show/Hide button to see the statistics.

# Subset the "sum" values for each sample
ws_dna_tIII_stats<-subset(ws_dna_tIII_sum, select=c(Tier_III,S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115))

rownames(ws_dna_tIII_stats) <- ws_dna_tIII_stats$Tier_III
ws_dna_tIII_stats<-as.data.frame(t(ws_dna_tIII_stats[-1]))

# Add the timepoint column to the sum table
ws_dna_tIII_stats<-data.frame(Timepoint2,ws_dna_tIII_stats)

# Subset response variables for MANOVA
ws_dna_tIII_stats$response <- as.matrix(ws_dna_tIII_stats[, 2:26])

# MANOVA test
ws_dna_tIII_manova <- manova(response ~ Timepoint2, data=ws_dna_tIII_stats)
summary.aov(ws_dna_tIII_manova)
 Response Overview. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2 11592649 5796324  1.7561  0.251
Residuals    6 19803697 3300616               

 Response Carbohydrate.metabolism. :
            Df   Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2  1502651   751325   0.067 0.9359
Residuals    6 67264565 11210761               

 Response Membrane.transport. :
            Df    Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2   4254406  2127203  0.1071 0.9001
Residuals    6 119152955 19858826               

 Response Nucleotide.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2 1612242  806121  0.8835  0.461
Residuals    6 5474222  912370               

 Response Translation. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2   574673  287336  0.0443  0.957
Residuals    6 38927135 6487856               

 Response Energy.metabolism. :
            Df   Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2  4006349  2003174    0.17 0.8476
Residuals    6 70700867 11783478               

 Response Metabolism.of.cofactors.and.vitamins. :
            Df   Sum Sq  Mean Sq F value Pr(>F)
Timepoint2   2  1523417   761708  0.0481 0.9534
Residuals    6 94921883 15820314               

 Response Amino.acid.metabolism. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2   888100  444050  0.1359 0.8755
Residuals    6 19604963 3267494               

 Response Replication.and.repair. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  1456087  728043  0.1421 0.8703
Residuals    6 30732394 5122066               

 Response Signal.transduction. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  2916123 1458061  0.6633 0.5492
Residuals    6 13188454 2198076               

 Response Folding..sorting.and.degradation. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  268229  134114  0.5365 0.6104
Residuals    6 1499881  249980               

 Response Lipid.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  628289  314144  0.8499 0.4732
Residuals    6 2217703  369617               

 Response Glycan.biosynthesis.and.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  895363  447681  0.3709 0.7049
Residuals    6 7241176 1206863               

 Response Cellular.community...prokaryotes. :
            Df   Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  1030745  515372  0.0731 0.9303
Residuals    6 42304933 7050822               

 Response Metabolism.of.other.amino.acids. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2 193273   96636  0.7342 0.5185
Residuals    6 789719  131620               

 Response Metabolism.of.terpenoids.and.polyketides. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  120644   60322  0.0982 0.9079
Residuals    6 3686720  614453               

 Response Cell.growth.and.death. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2    1454     727  0.0028 0.9972
Residuals    6 1541959  256993               

 Response Xenobiotics.biodegradation.and.metabolism. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  246889  123444  0.1748 0.8437
Residuals    6 4236271  706045               

 Response Cell.motility. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  156680   78340  0.1733 0.8449
Residuals    6 2711909  451985               

 Response Biosynthesis.of.other.secondary.metabolites. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2   8076  4038.1  0.2206 0.8083
Residuals    6 109827 18304.6               

 Response Transport.and.catabolism. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2   3354    1677   0.593 0.5821
Residuals    6  16968    2828               

 Response Transcription. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  10122    5061  0.1253 0.8845
Residuals    6 242390   40398               

 Response Signaling.molecules.and.interaction. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  505.56  252.78  0.4969 0.6314
Residuals    6 3052.00  508.67               

 Response Cellular.community...eukaryotes. :
            Df Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2 108.22  54.111  0.3796 0.6995
Residuals    6 855.33 142.556               

 Response Enzyme.families. :
            Df  Sum Sq Mean Sq F value Pr(>F)
Timepoint2   2  0.6667  0.3333  0.1034 0.9033
Residuals    6 19.3333  3.2222               
7.3.2.3. Tier IV Expression

Calculate GPM-normalized gene count sums for each WS sample in each Tier IV category.

# Calculate GPM-normalized gene count sums for each WS sample in each Tier IV category
ws_dna_tIV_sum<-gpm_all_pot_ann %>% group_by(Tier_IV) %>% summarise_at(vars("S107104","S107105","S107106","S107110","S107111","S107112","S107113","S107114","S107115"), sum)
ws_dna_tIV_sum<-ws_dna_tIV_sum %>% mutate_at(vars(S107104,S107105,S107106,S107110,S107111,S107112,S107113,S107114,S107115), funs(round(., 0)))
ws_dna_tIV_sum<-as.data.frame(ws_dna_tIV_sum)
ws_dna_tIV_sum<-ws_dna_tIV_sum[order(-ws_dna_tIV_sum$S107104),]
# Calculate mean values from the replicate sums
ws_dna_tIV_sum$meanWS_T0<-apply(ws_dna_tIV_sum[,2:4], 1, mean)
ws_dna_tIV_sum$meanWS_T4<-apply(ws_dna_tIV_sum[,5:7], 1, mean)
ws_dna_tIV_sum$meanWS_T24<-apply(ws_dna_tIV_sum[,8:10], 1, mean)
ws_dna_tIV_sum<-ws_dna_tIV_sum %>% mutate_at(vars(meanWS_T0,meanWS_T4,meanWS_T24), funs(round(., 0)))

# Calculate sd values from the replicate sums
ws_dna_tIV_sum$sdWS_T0<-apply(ws_dna_tIV_sum[,2:4], 1, sd)
ws_dna_tIV_sum$sdWS_T4<-apply(ws_dna_tIV_sum[,5:7], 1, sd)
ws_dna_tIV_sum$sdWS_T24<-apply(ws_dna_tIV_sum[,8:10], 1, sd)
ws_dna_tIV_sum<-ws_dna_tIV_sum %>% mutate_at(vars(sdWS_T0,sdWS_T4,sdWS_T24), funs(round(., 0)))

# Write data to .csv file
write.csv(ws_dna_tIV_sum, 'Norm.Results/ws.dna.tIV.mean.sd.csv')

# Subset Mean values
ws_dna_tIV_mean<-subset(ws_dna_tIV_sum, select=c(Tier_IV,meanWS_T0,meanWS_T4,meanWS_T24))
names(ws_dna_tIV_mean)<-c("Tier IV", "WS - T0", "WS - T4", "WS - T24")

# Subset SD values
ws_dna_tIV_sd<-subset(ws_dna_tIV_sum, select=c(Tier_IV,sdWS_T0,sdWS_T4,sdWS_T24))
names(ws_dna_tIV_sd)<-c("Tier IV", "WS - T0", "WS - T4", "WS - T24")

# Remember "Tier IV" as non-numeric values
ws_dna_tIV_mean_TierIV<-ws_dna_tIV_mean$`Tier IV`
ws_dna_tIV_sd_TierIV<-ws_dna_tIV_sd$`Tier IV`

# Transpose all but first column (Tier IV)
ws_dna_tIV_mean<-as.data.frame(t(ws_dna_tIV_mean[,-1]))
colnames(ws_dna_tIV_mean)<-ws_dna_tIV_mean_TierIV
ws_dna_tIV_sd<-as.data.frame(t(ws_dna_tIV_sd[,-1]))
colnames(ws_dna_tIV_sd)<-ws_dna_tIV_sd_TierIV

# Combine mean and sd into single column with ± divider
ws_dna_tIV_table<-as.data.frame(do.call(cbind, lapply(1:ncol(ws_dna_tIV_mean), function(i) paste0(ws_dna_tIV_mean[ , i], " ± ", ws_dna_tIV_sd[ , i]))))

# Transpose the table back
ws_dna_tIV_table<-t(ws_dna_tIV_table)

# Rename columns to Sites
colnames(ws_dna_tIV_table)<-c("Wet Sedge (T0)", "Wet Sedge (T4)", "Wet Sedge (T24)")

rownames(ws_dna_tIV_table)<-ws_dna_tIV_mean_TierIV

#ws_dna_tIV_table

7.4. Tundra MG Differences

Evaluate differences in metagenome abundance between tussock and wet sedge tundra ecosystems.

7.4.1 Tundra MG Barplots

Plot the combined Tuss-MG and WS-MG KEGG tier II categories as a barchart.

# Place the KEGG tier II categories in the preferred order for plotting
tuss_ws_dna_tII_bardata$Tier.II <- factor(tuss_ws_dna_tII_bardata$Tier.II,levels = c("Metabolism", "Genetic Information Processing", "Environmental Information Processing", "Cellular Processes"))

tuss_ws_dna_tII_bardata$Sample <- factor(tuss_ws_dna_tII_bardata$Sample,levels=c("Tuss-MG","WS-MG"))

tuss_ws_dna_tII_barplot<-ggplot(tuss_ws_dna_tII_bardata, aes(x = Tier.II, y = Mean, fill = Sample)) + geom_bar(stat = "identity", position = "dodge", color="black") + geom_errorbar(aes(ymin = Mean - SD, ymax = Mean + SD), width = 0.2, position = position_dodge(0.9)) + ylab(expression(atop("KEGG Tier II Categories", paste("Gene Counts")))) + theme_classic() + theme(axis.text=element_text(size=10), axis.title=element_text(size=12), axis.title.x=element_blank()) + theme(legend.position = "bottom", legend.title=element_blank(), legend.text=element_text(size=10)) + scale_size(guide=FALSE) + scale_fill_manual(values=c("gray83","black")) + scale_x_discrete(labels = function(Tier.II) str_wrap(Tier.II, width = 10)) + scale_y_continuous(expand = c(0, 0), limits = c(0, 800000)) + annotate(geom="text", x=1, y=750000, size=3, label="italic(p)==0.007", parse=TRUE) + annotate(geom="text", x=2, y=225000, size=3, label="italic(N.S.)", parse=TRUE) + annotate(geom="text", x=3, y=200000, size=3, label="italic(p)==0.001", parse=TRUE) + annotate(geom="text", x=4, y=110000, size=3, label="italic(p)==0.001", parse=TRUE) + annotate(geom="text", x=2.5, y=780000, label="Paired t-test")
tuss_ws_dna_tII_barplot

Run paired t-tests to determine significance.

# Metabolism
t.test(tuss.ws.dna.tII.t.test$Tuss.Meta,tuss.ws.dna.tII.t.test$WS.Meta,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tII.t.test$Tuss.Meta and tuss.ws.dna.tII.t.test$WS.Meta
t = 4.3494, df = 5, p-value = 0.007363
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
  4588.552 17850.448
sample estimates:
mean of the differences 
                11219.5 
# Genetic Information Processing
t.test(tuss.ws.dna.tII.t.test$Tuss.Gene,tuss.ws.dna.tII.t.test$WS.Gene,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tII.t.test$Tuss.Gene and tuss.ws.dna.tII.t.test$WS.Gene
t = -1.0645, df = 5, p-value = 0.3358
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -6398.692  2651.025
sample estimates:
mean of the differences 
              -1873.833 
# Environmental Information Processing
t.test(tuss.ws.dna.tII.t.test$Tuss.Env,tuss.ws.dna.tII.t.test$WS.Env,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tII.t.test$Tuss.Env and tuss.ws.dna.tII.t.test$WS.Env
t = -9.5367, df = 5, p-value = 0.0002145
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -23764.20 -13673.14
sample estimates:
mean of the differences 
              -18718.67 
# Cellular Processes
t.test(tuss.ws.dna.tII.t.test$Tuss.Cell,tuss.ws.dna.tII.t.test$WS.Cell,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tII.t.test$Tuss.Cell and tuss.ws.dna.tII.t.test$WS.Cell
t = 9.1097, df = 5, p-value = 0.0002669
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
  6728.004 12017.662
sample estimates:
mean of the differences 
               9372.833 

Plot the combined Tuss-MG and WS-MG KEGG tier III categories as a single barchart.

tuss_ws_dna_tIII_all_barplot

Run statistical tests to determine if significant differences exist between tundra communities for each KEGG Tier III category. Click on the Show/Hide button to see the statistics.

Run paired t-tests to determine significance.

# Amino acid metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.AA,tuss.ws.dna.tIII.t.test$WS.AA,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.AA and tuss.ws.dna.tIII.t.test$WS.AA
t = 8.4482, df = 2, p-value = 0.01372
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
  4414.838 13579.162
sample estimates:
mean of the differences 
                   8997 
# Other amino acid metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.OAA,tuss.ws.dna.tIII.t.test$WS.OAA,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.OAA and tuss.ws.dna.tIII.t.test$WS.OAA
t = 16.813, df = 2, p-value = 0.003519
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1905.621 3216.379
sample estimates:
mean of the differences 
                   2561 
# Carbohydrate metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Carb,tuss.ws.dna.tIII.t.test$WS.Carb,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Carb and tuss.ws.dna.tIII.t.test$WS.Carb
t = 4.3053, df = 2, p-value = 0.04994
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
     7.982796 26376.683871
sample estimates:
mean of the differences 
               13192.33 
# Energy metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Ener,tuss.ws.dna.tIII.t.test$WS.Ener,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Ener and tuss.ws.dna.tIII.t.test$WS.Ener
t = -6.629, df = 2, p-value = 0.02201
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -6218.057 -1323.276
sample estimates:
mean of the differences 
              -3770.667 
# Glycan metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Gly,tuss.ws.dna.tIII.t.test$WS.Gly,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Gly and tuss.ws.dna.tIII.t.test$WS.Gly
t = 1.2961, df = 2, p-value = 0.3244
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1153.687  2148.353
sample estimates:
mean of the differences 
               497.3333 
# Lipid metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Lip,tuss.ws.dna.tIII.t.test$WS.Lip,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Lip and tuss.ws.dna.tIII.t.test$WS.Lip
t = 1.5228, df = 2, p-value = 0.2673
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1860.803  3899.469
sample estimates:
mean of the differences 
               1019.333 
# Cofactor metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Cofac,tuss.ws.dna.tIII.t.test$WS.Cofac,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Cofac and tuss.ws.dna.tIII.t.test$WS.Cofac
t = -0.87232, df = 2, p-value = 0.475
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -4769.66  3161.66
sample estimates:
mean of the differences 
                   -804 
# Terpenoids metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Terp,tuss.ws.dna.tIII.t.test$WS.Terp,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Terp and tuss.ws.dna.tIII.t.test$WS.Terp
t = 3.5014, df = 2, p-value = 0.07278
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -246.9969 2405.6636
sample estimates:
mean of the differences 
               1079.333 
# Nucleotide metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Nucleo,tuss.ws.dna.tIII.t.test$WS.Nucleo,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Nucleo and tuss.ws.dna.tIII.t.test$WS.Nucleo
t = 8.7308, df = 2, p-value = 0.01287
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1189.181 3500.152
sample estimates:
mean of the differences 
               2344.667 
# Secondary metabolites metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.SecMet,tuss.ws.dna.tIII.t.test$WS.SecMet,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.SecMet and tuss.ws.dna.tIII.t.test$WS.SecMet
t = 7.88, df = 2, p-value = 0.01573
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 180.6841 615.3159
sample estimates:
mean of the differences 
                    398 
# Xenobiotics metabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Xeno,tuss.ws.dna.tIII.t.test$WS.Xeno,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Xeno and tuss.ws.dna.tIII.t.test$WS.Xeno
t = 11.21, df = 2, p-value = 0.007864
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 3004.829 6748.504
sample estimates:
mean of the differences 
               4876.667 
# Folding, sorting, and degradation
t.test(tuss.ws.dna.tIII.t.test$Tuss.Fold,tuss.ws.dna.tIII.t.test$WS.Fold,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Fold and tuss.ws.dna.tIII.t.test$WS.Fold
t = 4.7816, df = 2, p-value = 0.04106
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
  173.5249 3291.1418
sample estimates:
mean of the differences 
               1732.333 
# Replication
t.test(tuss.ws.dna.tIII.t.test$Tuss.Replic,tuss.ws.dna.tIII.t.test$WS.Replic,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Replic and tuss.ws.dna.tIII.t.test$WS.Replic
t = -1.5683, df = 2, p-value = 0.2574
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1915.4712   892.1378
sample estimates:
mean of the differences 
              -511.6667 
# Transcription
t.test(tuss.ws.dna.tIII.t.test$Tuss.Transc,tuss.ws.dna.tIII.t.test$WS.Transc,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Transc and tuss.ws.dna.tIII.t.test$WS.Transc
t = 5.9916, df = 2, p-value = 0.02674
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
  65.0223 396.3110
sample estimates:
mean of the differences 
               230.6667 
# Translation
t.test(tuss.ws.dna.tIII.t.test$Tuss.Transl,tuss.ws.dna.tIII.t.test$WS.Transl,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Transl and tuss.ws.dna.tIII.t.test$WS.Transl
t = -3.5065, df = 2, p-value = 0.07259
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -6401.9956   652.6622
sample estimates:
mean of the differences 
              -2874.667 
# Membrane Transport
t.test(tuss.ws.dna.tIII.t.test$Tuss.MembTrans,tuss.ws.dna.tIII.t.test$WS.MembTrans,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.MembTrans and tuss.ws.dna.tIII.t.test$WS.MembTrans
t = -11.1, df = 2, p-value = 0.008018
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -30140.37 -13301.63
sample estimates:
mean of the differences 
                 -21721 
# Signal Transduction
t.test(tuss.ws.dna.tIII.t.test$Tuss.SignTrans,tuss.ws.dna.tIII.t.test$WS.SignTrans,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.SignTrans and tuss.ws.dna.tIII.t.test$WS.SignTrans
t = 4.367, df = 2, p-value = 0.04864
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
   36.98839 4981.01161
sample estimates:
mean of the differences 
                   2509 
# Signaling Molecules
t.test(tuss.ws.dna.tIII.t.test$Tuss.SignMol,tuss.ws.dna.tIII.t.test$WS.SignMol,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.SignMol and tuss.ws.dna.tIII.t.test$WS.SignMol
t = -3.8253, df = 2, p-value = 0.06205
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -144.485628    8.485628
sample estimates:
mean of the differences 
                    -68 
# Cellular Community
t.test(tuss.ws.dna.tIII.t.test$Tuss.CellComm,tuss.ws.dna.tIII.t.test$WS.CellComm,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.CellComm and tuss.ws.dna.tIII.t.test$WS.CellComm
t = 17.098, df = 2, p-value = 0.003403
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1849.176 3092.824
sample estimates:
mean of the differences 
                   2471 
# Cellular Growth
t.test(tuss.ws.dna.tIII.t.test$Tuss.CellGrow,tuss.ws.dna.tIII.t.test$WS.CellGrow,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.CellGrow and tuss.ws.dna.tIII.t.test$WS.CellGrow
t = 3.5329, df = 2, p-value = 0.07162
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -302.0716 3074.7382
sample estimates:
mean of the differences 
               1386.333 
# Cellular Motility
t.test(tuss.ws.dna.tIII.t.test$Tuss.CellMot,tuss.ws.dna.tIII.t.test$WS.CellMot,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.CellMot and tuss.ws.dna.tIII.t.test$WS.CellMot
t = 8.0641, df = 2, p-value = 0.01503
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1984.396 6524.270
sample estimates:
mean of the differences 
               4254.333 
# Transport and Catabolism
t.test(tuss.ws.dna.tIII.t.test$Tuss.Transp,tuss.ws.dna.tIII.t.test$WS.Transp,paired=TRUE)

    Paired t-test

data:  tuss.ws.dna.tIII.t.test$Tuss.Transp and tuss.ws.dna.tIII.t.test$WS.Transp
t = 5.3064, df = 2, p-value = 0.03373
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
  176.7351 1691.9315
sample estimates:
mean of the differences 
               934.3333 

7.4.2 Tundra MG Heatmap

Heatmap for MG Tier III categories by sampling timepoints

# Create a vector with categories in the desired order
tuss_ws_dna_tIII_x <- c("Amino acid metabolism ",
                        "Metabolism of other amino acids ",
                        "Carbohydrate metabolism ",
                        "Energy metabolism ",
                        "Glycan biosynthesis and metabolism ",
                        "Lipid metabolism ",
                        "Metabolism of cofactors and vitamins ",
                        "Metabolism of terpenoids and polyketides ",
                        "Nucleotide metabolism ",
                        "Biosynthesis of other secondary metabolites ",
                        "Xenobiotics biodegradation and metabolism ",
                        "Folding, sorting and degradation ",
                        "Replication and repair ",
                        "Transcription ",
                        "Translation ",
                        "Membrane transport ",
                        "Signal transduction ",
                        "Signaling molecules and interaction ",
                        "Cellular community - prokaryotes ",
                        "Cell growth and death ",
                        "Cell motility ",
                        "Transport and catabolism ")

# Re-sort the data in the desired order
tuss_ws_dna_tIII_heatmap<-tuss_ws_dna_tIII_heatmap %>%
  slice(match(tuss_ws_dna_tIII_x, Tier_III))

# Convert the first column (Tier categories) into rownames
rownames(tuss_ws_dna_tIII_heatmap) <- tuss_ws_dna_tIII_heatmap$Tier_III
tuss_ws_dna_tIII_heatmap<-as.data.frame(tuss_ws_dna_tIII_heatmap[-1])

# Rename columns to sample IDs (This includes T24 replicates)
colnames(tuss_ws_dna_tIII_heatmap)<-c("Tuss-MG-T0","Tuss-MG-T4","Tuss-MG-T24","WS-MG-T0","WS-MG-T4","WS-MG-T24")

# Convert dataframe into a matrix for heatmap
tuss_ws_dna_tIII_heatmap-as.matrix(tuss_ws_dna_tIII_heatmap)

# Scale matrix values to generate Z-scores
tuss_ws_dna_tIII_heatmap<-scale(t(tuss_ws_dna_tIII_heatmap))

tuss_ws_dna_tIII_heatmap<-t(tuss_ws_dna_tIII_heatmap)

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)

### Saving as .eps file with R Viewer
# Re-size the viewer to the following dimensions before saving as .eps file
# In Console, type "tuss_ws_dna_tIII_pheatmap"
# In Plot Viewer, click "Export" --> "Save as Image"
# Width: 550  Height: 650
# Click "Update Preview" --> save as "EPS" file type --> rename as Fig.2.Heat

# Pheatmap
tuss_ws_dna_tIII_pheatmap<-pheatmap(tuss_ws_dna_tIII_heatmap, treeheight_row = 0, treeheight_col = 0, cluster_rows = FALSE, cluster_cols = FALSE)

7.5. Fe Gene Expression

Potential gene expression related to iron acquisition, iron redox cycling, and iron storage in the metagenomes were determined using FeGenie (Garber et al. 2020). FeGenie provides a comprehensive database of hidden Markov models (HMMs) based on genes related to iron acquisition, storage, and oxidation/reduction in Bacteria and Archaea, which are generally not annotated as such by established gene annotation pipelines, such as GhostKOALA, which was used to annotate the metagenomes (and metatranscriptomes) presented in this study.

Here, the quality-controlled sequencing reads for each metagenome sample were assembled by tundra ecosystem using MEGAHIT to generate a tundra-specific contigs file. The metagenome contigs files were used as input for FeGenie, which first predicted open-reading frames (ORFs) using Prodigal and then queried them against a custom library of HMMs using hmmsearch, with custom bit score cutoffs for each HMM. Results from FeGenie included all identified putative iron-related genes, their functional category, bit score, number of canonical heme-binding motifs, amino acid sequence, and closest homolog. Counts within each iron gene category were summarized as their relative abundance against all identified iron genes.

Assemble QC’d metagenome samples by tundra ecosystem for use in FeGenie

{Terminal}
module load Bioinformatics megahit/1.2.8
cat *_adtrim_clean_qtrim_fwd.derep.fastq > Tuss_DNA_data_fwd.qc.fastq
cat *_adtrim_clean_qtrim_rev.derep.fastq > Tuss_DNA_data_rev.qc.fastq
megahit --k-min 21 --k-max 141 --k-step 12 -1 Tuss_DNA_data_fwd.qc.fastq -2 Tuss_DNA_data_rev.qc.fastq -o ./megahit_tuss_dna_out
cd /gpfs/accounts/gwk_root/gwk1/kjromano/DNA_assembly/WS_DNA
cat *_adtrim_clean_qtrim_fwd.derep.fastq > WS_DNA_data_fwd.qc.fastq
cat *_adtrim_clean_qtrim_rev.derep.fastq > WS_DNA_data_rev.qc.fastq
megahit --k-min 21 --k-max 141 --k-step 12 -1 WS_DNA_data_fwd.qc.fastq -2 WS_DNA_data_rev.qc.fastq -o ./megahit_ws_dna_out

7.5.1. FeGenie Summary

FeGenie is a python script with dependencies that can be downloaded from Arkadiy-Garber GitHub.

Start by loading prerequisite modules

{Terminal}
module load python3.6-anaconda Bioinformatics hmmer prodigal ncbi-blast R

Run the FeGenie python script

{Terminal}
tuss_dna_run.sh

# This is what's inside the "tuss_dna_run.sh" script
FeGenie.py -bin_dir /gpfs/accounts/gwk_root/gwk1/kjromano/DNA_assembly/Tuss_DNA/megahit_tuss_dna_out/ -bin_ext fa -out tuss_dna_out

ws_dna_run.sh

# This is what's inside the "ws_dna_run.sh" script
FeGenie.py -bin_dir /DNA_assembly/WS_DNA/megahit_ws_dna_out/ -bin_ext fa -out WS_dna_out

Summary table of the relative abundance of iron gene categories from the METAGENOMES of Tuss and WS tundra ecosystems.

incomplete final line found by readTableHeader on 'Table.Data/FeGenie.DNA.csv'

Reproducibility

The session information is provided for full reproducibility.

devtools::session_info()
─ Session info ─────────────────────────────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.1.2 (2021-11-01)
 os       macOS Big Sur 10.16
 system   x86_64, darwin17.0
 ui       RStudio
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       America/Los_Angeles
 date     2022-01-24
 rstudio  1.4.1106 Tiger Daylily (desktop)
 pandoc   2.11.4 @ /Applications/RStudio.app/Contents/MacOS/pandoc/ (via rmarkdown)

─ Packages ─────────────────────────────────────────────────────────────────────────────────────────
 package      * version date (UTC) lib source
 abind          1.4-5   2016-07-21 [1] CRAN (R 4.1.0)
 ape          * 5.6-1   2022-01-07 [1] CRAN (R 4.1.2)
 assertthat     0.2.1   2019-03-21 [1] CRAN (R 4.1.0)
 backports      1.4.1   2021-12-13 [1] CRAN (R 4.1.0)
 brio           1.1.3   2021-11-30 [1] CRAN (R 4.1.0)
 broom          0.7.11  2022-01-03 [1] CRAN (R 4.1.2)
 cachem         1.0.6   2021-08-19 [1] CRAN (R 4.1.0)
 callr          3.7.0   2021-04-20 [1] CRAN (R 4.1.0)
 car            3.0-12  2021-11-06 [1] CRAN (R 4.1.0)
 carData        3.0-5   2022-01-06 [1] CRAN (R 4.1.2)
 cellranger     1.1.0   2016-07-27 [1] CRAN (R 4.1.0)
 cli            3.1.1   2022-01-20 [1] CRAN (R 4.1.2)
 cluster        2.1.2   2021-04-17 [1] CRAN (R 4.1.2)
 colorspace     2.0-2   2021-06-24 [1] CRAN (R 4.1.0)
 cowplot      * 1.1.1   2020-12-30 [1] CRAN (R 4.1.0)
 crayon         1.4.2   2021-10-29 [1] CRAN (R 4.1.0)
 data.table   * 1.14.2  2021-09-27 [1] CRAN (R 4.1.0)
 DBI            1.1.2   2021-12-20 [1] CRAN (R 4.1.0)
 dbplyr         2.1.1   2021-04-06 [1] CRAN (R 4.1.0)
 desc           1.4.0   2021-09-28 [1] CRAN (R 4.1.0)
 devtools     * 2.4.3   2021-11-30 [1] CRAN (R 4.1.0)
 digest         0.6.29  2021-12-01 [1] CRAN (R 4.1.0)
 dplyr        * 1.0.7   2021-06-18 [1] CRAN (R 4.1.0)
 DT           * 0.20    2021-11-15 [1] CRAN (R 4.1.0)
 ellipsis       0.3.2   2021-04-29 [1] CRAN (R 4.1.0)
 evaluate       0.14    2019-05-28 [1] CRAN (R 4.1.0)
 fansi          1.0.2   2022-01-14 [1] CRAN (R 4.1.2)
 farver         2.1.0   2021-02-28 [1] CRAN (R 4.1.0)
 fastmap        1.1.0   2021-01-25 [1] CRAN (R 4.1.0)
 forcats      * 0.5.1   2021-01-27 [1] CRAN (R 4.1.0)
 fs             1.5.2   2021-12-08 [1] CRAN (R 4.1.0)
 generics       0.1.1   2021-10-25 [1] CRAN (R 4.1.0)
 ggplot2      * 3.3.5   2021-06-25 [1] CRAN (R 4.1.0)
 ggpubr       * 0.4.0   2020-06-27 [1] CRAN (R 4.1.0)
 ggsignif       0.6.3   2021-09-09 [1] CRAN (R 4.1.0)
 glue           1.6.0   2021-12-17 [1] CRAN (R 4.1.0)
 gridExtra    * 2.3     2017-09-09 [1] CRAN (R 4.1.0)
 gtable         0.3.0   2019-03-25 [1] CRAN (R 4.1.0)
 haven          2.4.3   2021-08-04 [1] CRAN (R 4.1.0)
 highr          0.9     2021-04-16 [1] CRAN (R 4.1.0)
 hms            1.1.1   2021-09-26 [1] CRAN (R 4.1.0)
 htmltools      0.5.2   2021-08-25 [1] CRAN (R 4.1.0)
 htmlwidgets    1.5.4   2021-09-08 [1] CRAN (R 4.1.0)
 httr           1.4.2   2020-07-20 [1] CRAN (R 4.1.0)
 jquerylib      0.1.4   2021-04-26 [1] CRAN (R 4.1.0)
 jsonlite       1.7.3   2022-01-17 [1] CRAN (R 4.1.2)
 kableExtra   * 1.3.4   2021-02-20 [1] CRAN (R 4.1.0)
 knitr        * 1.37    2021-12-16 [1] CRAN (R 4.1.0)
 labeling       0.4.2   2020-10-20 [1] CRAN (R 4.1.0)
 lattice      * 0.20-45 2021-09-22 [1] CRAN (R 4.1.2)
 lifecycle      1.0.1   2021-09-24 [1] CRAN (R 4.1.0)
 lubridate      1.8.0   2021-10-07 [1] CRAN (R 4.1.0)
 magrittr       2.0.1   2020-11-17 [1] CRAN (R 4.1.0)
 MASS           7.3-55  2022-01-13 [1] CRAN (R 4.1.2)
 Matrix         1.4-0   2021-12-08 [1] CRAN (R 4.1.0)
 memoise        2.0.1   2021-11-26 [1] CRAN (R 4.1.0)
 mgcv           1.8-38  2021-10-06 [1] CRAN (R 4.1.2)
 modelr         0.1.8   2020-05-19 [1] CRAN (R 4.1.0)
 munsell        0.5.0   2018-06-12 [1] CRAN (R 4.1.0)
 nlme           3.1-155 2022-01-13 [1] CRAN (R 4.1.2)
 permute      * 0.9-5   2019-03-12 [1] CRAN (R 4.1.0)
 pheatmap     * 1.0.12  2019-01-04 [1] CRAN (R 4.1.0)
 pillar         1.6.4   2021-10-18 [1] CRAN (R 4.1.0)
 pkgbuild       1.3.1   2021-12-20 [1] CRAN (R 4.1.0)
 pkgconfig      2.0.3   2019-09-22 [1] CRAN (R 4.1.0)
 pkgload        1.2.4   2021-11-30 [1] CRAN (R 4.1.0)
 plyr           1.8.6   2020-03-03 [1] CRAN (R 4.1.0)
 png          * 0.1-7   2013-12-03 [1] CRAN (R 4.1.0)
 prettyunits    1.1.1   2020-01-24 [1] CRAN (R 4.1.0)
 processx       3.5.2   2021-04-30 [1] CRAN (R 4.1.0)
 ps             1.6.0   2021-02-28 [1] CRAN (R 4.1.0)
 purrr        * 0.3.4   2020-04-17 [1] CRAN (R 4.1.0)
 R6             2.5.1   2021-08-19 [1] CRAN (R 4.1.0)
 RColorBrewer * 1.1-2   2014-12-07 [1] CRAN (R 4.1.0)
 Rcpp           1.0.8   2022-01-13 [1] CRAN (R 4.1.2)
 readr        * 2.1.1   2021-11-30 [1] CRAN (R 4.1.0)
 readxl         1.3.1   2019-03-13 [1] CRAN (R 4.1.0)
 remotes        2.4.2   2021-11-30 [1] CRAN (R 4.1.0)
 reprex         2.0.1   2021-08-05 [1] CRAN (R 4.1.0)
 reshape      * 0.8.8   2018-10-23 [1] CRAN (R 4.1.0)
 rlang          0.4.12  2021-10-18 [1] CRAN (R 4.1.0)
 rmarkdown      2.11    2021-09-14 [1] CRAN (R 4.1.0)
 rprojroot      2.0.2   2020-11-15 [1] CRAN (R 4.1.0)
 rsconnect      0.8.25  2021-11-19 [1] CRAN (R 4.1.0)
 rstatix      * 0.7.0   2021-02-13 [1] CRAN (R 4.1.0)
 rstudioapi     0.13    2020-11-12 [1] CRAN (R 4.1.0)
 rvest          1.0.2   2021-10-16 [1] CRAN (R 4.1.0)
 scales         1.1.1   2020-05-11 [1] CRAN (R 4.1.0)
 sessioninfo    1.2.2   2021-12-06 [1] CRAN (R 4.1.0)
 statmod      * 1.4.36  2021-05-10 [1] CRAN (R 4.1.0)
 stringi        1.7.6   2021-11-29 [1] CRAN (R 4.1.0)
 stringr      * 1.4.0   2019-02-10 [1] CRAN (R 4.1.0)
 svglite        2.0.0   2021-02-20 [1] CRAN (R 4.1.0)
 systemfonts    1.0.3   2021-10-13 [1] CRAN (R 4.1.2)
 testthat       3.1.2   2022-01-20 [1] CRAN (R 4.1.2)
 tibble       * 3.1.6   2021-11-07 [1] CRAN (R 4.1.0)
 tidyr        * 1.1.4   2021-09-27 [1] CRAN (R 4.1.0)
 tidyselect     1.1.1   2021-04-30 [1] CRAN (R 4.1.0)
 tidyverse    * 1.3.1   2021-04-15 [1] CRAN (R 4.1.0)
 tinytex        0.36    2021-12-19 [1] CRAN (R 4.1.0)
 tzdb           0.2.0   2021-10-27 [1] CRAN (R 4.1.0)
 usethis      * 2.1.5   2021-12-09 [1] CRAN (R 4.1.0)
 utf8           1.2.2   2021-07-24 [1] CRAN (R 4.1.0)
 vctrs          0.3.8   2021-04-29 [1] CRAN (R 4.1.0)
 vegan        * 2.5-7   2020-11-28 [1] CRAN (R 4.1.0)
 viridisLite    0.4.0   2021-04-13 [1] CRAN (R 4.1.0)
 webshot        0.5.2   2019-11-22 [1] CRAN (R 4.1.0)
 withr          2.4.3   2021-11-30 [1] CRAN (R 4.1.0)
 xfun           0.29    2021-12-14 [1] CRAN (R 4.1.0)
 xml2           1.3.3   2021-11-30 [1] CRAN (R 4.1.0)
 yaml         * 2.2.1   2020-02-01 [1] CRAN (R 4.1.0)

 [1] /Library/Frameworks/R.framework/Versions/4.1/Resources/library

────────────────────────────────────────────────────────────────────────────────────────────────────
LS0tCnRpdGxlOiAiTWljcm9iaWFsIFJlc3BvbnNlIHRvIFJhaW5mYWxsIC0tIE1ldGFnZW5vbWUgQW5hbHlzaXMiCmF1dGhvcjogJ0F1dGhvcnM6IFtLYXJsIEouIFJvbWFub3dpY3pdKGh0dHBzOi8vbHNhLnVtaWNoLmVkdS9lZWIvcGVvcGxlL2dyYWR1YXRlLXN0dWRlbnRzL2tqcm9tYW5vLmh0bWwpLAogIEJ5cm9uIEMuIENydW1wLCBHZW9yZ2UgVy4gS2xpbmcnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IHNwYWNlbGFiCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCiAgICAgIHNtb290aF9zY3JvbGw6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnNScKICAgIGRmX3ByaW50OiBwYWdlZAogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICc1JwotLS0KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCgoqKlIgTm90ZWJvb2s6KiogUHJvdmlkZXMgcmVwcm9kdWNpYmxlIGFuYWx5c2lzIGZvciBtZXRhZ2Vub21lIChNRykgZGF0YSBpbiB0aGUgZm9sbG93aW5nIG1hbnVzY3JpcHQ6CgoqKkNpdGF0aW9uOioqIFJvbWFub3dpY3osIEtKLCBDcnVtcCwgQkMsIEtsaW5nLCBHVy4gKDIwMjEpIFJhaW5mYWxsIGFsdGVycyBwZXJtYWZyb3N0IHNvaWwgcmVkb3ggY29uZGl0aW9ucywgYnV0IG1ldGEtb21pY3Mgc2hvdyBkaXZlcmdlbnQgbWljcm9iaWFsIGNvbW11bml0eSByZXNwb25zZXMgYnkgdHVuZHJhIHR5cGUgaW4gdGhlIGFyY3RpYy4gU29pbCBTeXN0ZW1zIDUoMSk6IDE3LiBbaHR0cHM6Ly9kb2kub3JnLzEwLjMzOTAvc29pbHN5c3RlbXM1MDEwMDE3XShodHRwczovL2RvaS5vcmcvMTAuMzM5MC9zb2lsc3lzdGVtczUwMTAwMTcpCgoqKkdpdEh1YiBSZXBvc2l0b3J5OioqIFtodHRwczovL2dpdGh1Yi5jb20va3JvbWFub3dpY3ovMjAyMS1Sb21hbm93aWN6LVNvaWxTeXN0ZW1zXShodHRwczovL2dpdGh1Yi5jb20va3JvbWFub3dpY3ovMjAyMS1Sb21hbm93aWN6LVNvaWxTeXN0ZW1zKQoKKipOQ0JJIEJpb1Byb2plY3Q6KiogW2h0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvYmlvcHJvamVjdC9QUkpOQTY2NjQyOV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9iaW9wcm9qZWN0L1BSSk5BNjY2NDI5KQoKKipBY2NlcHRlZCBmb3IgUHVibGljYXRpb246KiogKlNvaWwgU3lzdGVtcyogMTAgTWFyY2ggMjAyMQoKIyBFeHBlcmltZW50CgpUaGlzIFIgTm90ZWJvb2sgcHJvdmlkZXMgY29tcGxldGUgcmVwcm9kdWNpYmlsaXR5IG9mIHRoZSBkYXRhIGFuYWx5c2lzIGluICoqKiJSYWluZmFsbCBhbHRlcnMgcGVybWFmcm9zdCBzb2lsIHJlZG94IGNvbmRpdGlvbnMsIGJ1dCBtZXRhLW9taWNzIHNob3cgZGl2ZXJnZW50IG1pY3JvYmlhbCBjb21tdW5pdHkgcmVzcG9uc2VzIGJ5IHR1bmRyYSB0eXBlIGluIHRoZSBBcmN0aWMgIioqKiBieSBSb21hbm93aWN6LCBDcnVtcCwgYW5kIEtsaW5nLiBJbiB0aGlzIGV4cGVyaW1lbnQsIG1lc29jb3NtcyBjb250YWluaW5nIHNvaWwgZnJvbSB0aGUgYWN0aXZlIGxheWVyIG9mIHR3byBkb21pbmFudCB0dW5kcmEgdHlwZXMgd2VyZSBzdWJqZWN0ZWQgdG8gc2ltdWxhdGVkIHJhaW5mYWxsIHRvIGFsdGVyIHJlZG94IGNvbmRpdGlvbnMuICBUaGUgbWljcm9iaWFsIGZ1bmN0aW9uYWwgcG90ZW50aWFsIChtZXRhZ2Vub21pY3MpIGFuZCBnZW5lIGV4cHJlc3Npb24gKG1ldGF0cmFuc2NyaXB0b21pY3MpIHBhdHRlcm5zIHdlcmUgbWVhc3VyZWQgZHVyaW5nIHNhdHVyYXRlZCBhbm94aWMgcmVkb3ggY29uZGl0aW9ucyBwcmlvciB0byByYWluZmFsbCBhbmQgYXQgbXVsdGlwbGUgdGltZSBwb2ludHMgZm9sbG93aW5nIHRoZSBzaW11bGF0ZWQgcmFpbmZhbGwgZXZlbnQuIE90aGVyIG1lYXN1cmVtZW50cyBpbmNsdWRlIHNvaWwgcHJvcGVydGllcyBhcyB3ZWxsIGFzIG1pY3JvYmlhbCByZXNwaXJhdGlvbiAoQ09+Mn4pIGFuZCBtZXRoYW5lIChDSH40fikgcHJvZHVjdGlvbiBmcm9tIHNvaWwgc3Vic2FtcGxlcyBjb2xsZWN0ZWQgYXQgZWFjaCBzYW1wbGluZyB0aW1lIHBvaW50LiBUaGUgcHVycG9zZSB3YXMgdG8gZGV0ZXJtaW5lIGlmIHJhaW5mYWxsLCBhcyBhIGZvcm0gb2Ygc29pbCBveGlkYXRpb24sIGlzIHN1ZmZpY2llbnQgdG8gYWx0ZXIgdGhlIGFub3hpYyByZWRveCBjb25kaXRpb25zIGluIGFyY3RpYyB0dW5kcmEgYW5kIGVuaGFuY2UgdGhlIG1pY3JvYmlhbCBkZWdyYWRhdGlvbiBvZiBvcmdhbmljIGNhcmJvbiBhbmQgQ0h+NH4gdG8gQ09+Mn4uCgo8IS0tIERpc3BsYXkgRmlndXJlIDEgLS0+CiFbXShSLkltYWdlcy9Db25jZXB0MS5wbmcpCioqQ29uY2VwdHVhbCBGaWd1cmUuKiogIEEgdG90YWwgb2YgMTIgdHVuZHJhIG1lc29jb3NtcyAoMyByZXBsaWNhdGVzIHggMiB0dW5kcmEgdHlwZXMgeCAyIHNldHMgb2YgcmVzcG9uc2UgY29yZXMpIHdlcmUgYWNjbGltYXRlZCBpbml0aWFsbHkgdW5kZXIgYW5veGljIHJlZG94IGNvbmRpdGlvbnMgdG8gbWltaWMgZmllbGQgY29uZGl0aW9ucyAoVDApLiAgRGlzc29sdmVkIG94eWdlbiB3YXMgc3VwcGxpZWQgdG8gc29pbHMgdGhyb3VnaCB0aGUgZG93bndhcmQgZmxvdyBvZiBveHlnZW5hdGVkIHdhdGVyIGR1cmluZyBhIHNpbXVsYXRlZCByYWluZmFsbCBldmVudC4gIERpc3NvbHZlZCBveHlnZW4gd2lsbCBsaWtlbHkgY2hhbmdlIHRoZSByZWRveCBncmFkaWVudCBkaXJlY3RseSBmb2xsb3dpbmcgcmFpbmZhbGwgKFQ0KSBhcyBhIHNob3J0LXRlcm0gZWZmZWN0LiAgQW5veGljIGNvbmRpdGlvbnMgd2lsbCBsaWtlbHkgYmUgcmUtZXN0YWJsaXNoZWQgYWZ0ZXIgMjQgaG91cnMgKFQyNCkgYXMgdGhlIHB1bHNlIG9mIG94eWdlbiBpcyBjb25zdW1lZCB0aHJvdWdoIGFiaW90aWMgYW5kIGJpb3RpYyBzb2lsIHByb2Nlc3Nlcy4gIFVuZGVyIGFub3hpYyByZWRveCBjb25kaXRpb25zIChUMCksIG1pY3Jvb3JnYW5pc21zIGxpa2VseSBkZWdyYWRlIG9yZ2FuaWMgY2FyYm9uIHRocm91Z2ggYW5hZXJvYmljIGFuZCBmZXJtZW50YXRpb24gcGF0aHdheXMsIHByb2R1Y2luZyBDSH40fiBhbmQgcmVkdWNpbmcgRmUoSUlJKSB0byBGZShJSSkuICBSYWluZmFsbC1pbmR1Y2VkIHNvaWwgb3hpZGF0aW9uIChUNCkgc2hvdWxkIHN0aW11bGF0ZSBoZXRlcm90cm9waGljIG1pY3Jvb3JnYW5pc21zIHRoYXQgZGVncmFkZSBvcmdhbmljIGNhcmJvbiBhbmQgQ0h+NH4gdGhyb3VnaCBhZXJvYmljIG1ldGFib2xpYyBwYXRod2F5cywgcmVsZWFzaW5nIENPfjJ+LiBTb2lsIG94aWRhdGlvbiBzaG91bGQgYWxzbyBzdGltdWxhdGUgYWVyb2JpYyBhdXRvdHJvcGhpYyBpcm9uIG94aWRpemluZyBiYWN0ZXJpYSB0aGF0IG94aWRpemUgRmUoSUkpIHRvIEZlKElJSSkgYW5kIGNvbnZlcnQgQ09+Mn4gaW50byBtaWNyb2JpYWwgYmlvbWFzcy4gIFRoZSBsb25nLXRlcm0gcmVzcG9uc2UgKFQyNCkgd2lsbCBsaWtlbHkgYmUgYSBjb21iaW5hdGlvbiBvZiBhZXJvYmljIGFuZCBhbmFlcm9iaWMgbWV0YWJvbGlzbSBhcyB3ZWxsIGFzIGEgY29tYmluYXRpb24gb2YgcmVkdWN0aW9uIGFuZCBveGlkYXRpb24gaXJvbiByZWFjdGlvbnMgYXMgZGlzc29sdmVkIG94eWdlbiBpcyBjb25zdW1lZC4gIFRoZSBwcmVkaWN0ZWQgcmVkb3ggY29uZGl0aW9ucyBhbmQgcHJlZGljdGVkIHJlZG94IHJlYWN0aW9ucyBmb3IgY291cGxlZCBGZShJSSkvRmUoSUlJKSBjeWNsaW5nLCBhcyB3ZWxsIGFzIHRoZSBtaWNyb2JpYWwtaW5kdWNlZCByZWxlYXNlIG9mIENPfjJ+IG9yIENIfjR+IGF0IGVhY2ggdGltZSBwb2ludCBhcmUgYmFzZWQgb24gdGhlIHByZWRpY3RlZCBhdmFpbGFiaWxpdHkgb2YgZGlzc29sdmVkIG94eWdlbiBlbnRlcmluZyB0dW5kcmEgc29pbHMgdGhyb3VnaCBzaW11bGF0ZWQgcmFpbmZhbGwuCgo8Zm9udCBjb2xvcj0iYmx1ZSI+KipTb2lsIFNhbXBsaW5nIGZvciBNaWNyb2JpYWwgR2VuZSBFeHByZXNzaW9uKio8L2ZvbnQ+CgpBbiBpbml0aWFsIHNvaWwgc2FtcGxpbmcgZXZlbnQgZm9yIG1pY3JvYmlhbCBhY3Rpdml0eSB3YXMgY29uZHVjdGVkIGF0IHRoZSBlbmQgb2YgdGhlIGFub3hpYyBhY2NsaW1hdGlvbiBwZXJpb2QgKDQtNyBkYXlzKSBpbiBhbGwgbWVzb2Nvc20gcmVwbGljYXRlcywgcmVwcmVzZW50aW5nIHNhbXBsaW5nIHRpbWUgcG9pbnQgKipUMCoqLiAgTWVzb2Nvc21zIHdlcmUgdGhlbiBmbHVzaGVkIHRvIHNpbXVsYXRlIGEgcmFpbmZhbGwgZXZlbnQuICBBZGRpdGlvbmFsIHNvaWwgc2FtcGxpbmcgZXZlbnRzIHdlcmUgY29uZHVjdGVkIGF0ICoqVDQqKiAoNC1ocnMpIGFuZCAqKlQyNCoqICgyNC1ocnMpIGZvbGxvd2luZyB0aGUgcmFpbmZhbGwgZXZlbnQgdG8gZGV0ZXJtaW5lIHRoZSB0ZW1wb3JhbCBleHRlbnQgb2YgbWljcm9iaWFsIGdlbmUgZXhwcmVzc2lvbi4gIFNvaWwgY29yZXMgKDIuNTQgY20gZGlhbWV0ZXIsIDMwIGNtIGxlbmd0aCkgd2VyZSBleHRyYWN0ZWQgaW4gZHVwbGljYXRlIGZyb20gZWFjaCBtZXNvY29zbSByZXBsaWNhdGUgYXQgZWFjaCBzYW1wbGluZyB0aW1lIHBvaW50IGFuZCBob21vZ2VuaXplZCBieSBkZXB0aCBpbiAxMC1jbSBpbmNyZW1lbnRzLiAgVGhlIDEwLTIwIGNtIHNvaWwgaW5jcmVtZW50LCBjb21wb3NlZCBvZiBvcmdhbmljIHNvaWwgaW4gYWxsIG1lc29jb3NtIHJlcGxpY2F0ZXMsIHdhcyBjaG9zZW4gZm9yIG1pY3JvYmlhbCBnZW5lIGV4cHJlc3Npb24gYW5hbHlzaXMgYW5kIHByZXNlcnZlZCBpbiBSTkFsYXRlciBTdGFiaWxpemF0aW9uIFJlYWdlbnQgaW4gc3RlcmlsZSB0dWJlcyBhdCA0JmRlZztDIGZvciAxOCBob3VycyBhbmQgdGhlbiBzdG9yZWQgYXQgLTgwJmRlZztDIHVudGlsIGV4dHJhY3Rpb24uCgohW10oUi5JbWFnZXMvQnVja2V0cy5wbmcpCgoqKkZpZWxkIEV4cGVyaW1lbnQuKiogVHVuZHJhIHNvaWwgY29yZXMgd2VyZSBjb2xsZWN0ZWQgZnJvbSBmaWVsZCBzaXRlcyBpbiBBdWd1c3QgMjAxNyAodG9wIGxlZnQpIGFuZCBwbGFjZWQgaW4gYnVja2V0cyB0byBlc3RhYmxpc2ggdGhlIG1lc29jb3NtIGV4cGVyaW1lbnQgKGJvdHRvbSBsZWZ0KS4gIFR1c3NvY2sgdHVuZHJhIGNvcmVzIHdlcmUgY29tcG9zZWQgb2YgYW4gb3JnYW5pYyBzb2lsIGxheWVyIG92ZXJseWluZyBhIG1pbmVyYWwgc29pbCBsYXllciAodG9wIG1pZGRsZSkgd2hpbGUgd2V0IHNlZGdlIHR1bmRyYSBjb3JlcyB3ZXJlIGNvbXBvc2VkIGVudGlyZWx5IG9mIG9yZ2FuaWMgc29pbCAoYm90dG9tIG1pZGRsZSkuICBTb2lsIHN1YnNhbXBsaW5nIGZvciBtaWNyb2JpYWwgYWN0aXZpdHkgd2FzIHRha2VuIGZyb20gdGhlIDEwLTIwIGNtIGRlcHRoIG9mIGR1cGxpY2F0ZSBzb2lsIGNvcmVzIGluIFR1c3NvY2sgKHRvcCByaWdodCkgYW5kIFdldCBTZWRnZSAoYm90dG9tIHJpZ2h0KS4KCmBgYHtyIGVjaG89RkFMU0V9CiMgU2V0IGdsb2JhbCBvcHRpb25zIGZvciBub3RlYm9vawprbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9IG5vcm1hbGl6ZVBhdGgoIn4vRGVza3RvcC9SYWluU2ltMjAxNyIpKQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTgsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZScsIHdhcm5pbmc9RkFMU0V9CiMgTWFrZSBhIHZlY3RvciBvZiByZXF1aXJlZCBwYWNrYWdlcwpyZXF1aXJlZC5wYWNrYWdlcyA8LSBjKCJhcGUiLCJjb3dwbG90IiwiZGF0YS50YWJsZSIsImRldnRvb2xzIiwiZHBseXIiLCJEVCIsImdncGxvdDIiLCJnZ3B1YnIiLCJncmlkIiwiZ3JpZEV4dHJhIiwia2FibGVFeHRyYSIsImtuaXRyIiwicGhlYXRtYXAiLCJwbmciLCJSQ29sb3JCcmV3ZXIiLCJyZXNoYXBlIiwicnN0YXRpeCIsInN0YXRtb2QiLCJzdHJpbmdyIiwidGliYmxlIiwidGlkeXIiLCJ0aWR5dmVyc2UiLCJ2ZWdhbiIsInlhbWwiKQoKIyBMb2FkIHJlcXVpcmVkIHBhY2thZ2VzCmxhcHBseShyZXF1aXJlZC5wYWNrYWdlcywgbGlicmFyeSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQpgYGAKCiMgTWV0YWdlbm9tZXMKCiMjIDEuIEROQSBTZXF1ZW5jaW5nCgpFeHRyYWN0ZWQgRE5BIHdhcyBzZXF1ZW5jZWQgb24gdGhlIElsbHVtaW5hIEhpU2VxIDQwMDAgcGxhdGZvcm0gKDE1MGJwIHBhaXJlZC1lbmQgcmVhZHMpIGF0IHRoZSBVbml2ZXJzaXR5IG9mIE1pY2hpZ2FuIEFkdmFuY2VkIEdlbm9taWNzIENvcmUuCgpgYGB7ciBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KZG5hLnNlcWNvcmUgPC1yZWFkLnRhYmxlKCJUYWJsZS5EYXRhL2RuYS5zZXFjb3JlLmFsbC50YWJsZS50eHQiLHNlcD0nXHQnLCBxdW90ZT0iIiwgZmlsbD1UUlVFLGhlYWRlciA9IFRSVUUpCm5hbWVzKGRuYS5zZXFjb3JlKTwtIGMoIklEIiwgIlNhbXBsZSIsICJDb25jZW50cmF0aW9uIChuZy91bCkiLCAiVm9sdW1lICh1TCkiLCAiRnJhZ21lbnQgTGVuZ3RoIiwgImk3IiwgImk1IiwgIkJhcmNvZGUgaTciLCAiQmFyY29kZSBpNSIpCmthYmxlKGRuYS5zZXFjb3JlLCBjYXB0aW9uID0gIlNlcUNvcmUgRE5BIHNhbXBsZSBzdWJtaXNzaW9uIHRvIElsbHVtaW5hIEhpU2VxIHBsYXRmb3JtIiwgYWxpZ24gPSAiYyIpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkgJT4lCiAgcm93X3NwZWMoMTY6MTgsIGJvbGQgPSBULCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiI0Q3MjYxRSIpCmBgYAoqKk5PVEU6KiogRE5BIFNhbXBsZXMgaW4gPGZvbnQgY29sb3I9InJlZCI+UkVEPC9mb250PiB3ZXJlIGV4Y2x1ZGVkIGZyb20gc2VxdWVuY2luZwoKIyMgMi4gRE5BIEJpb2luZm9ybWF0aWNzCgojIyMgMi4xLiBSYXcgUmVhZHMKCioqKlByZXAgdGhlIFJhdyBSZWFkcyAoSGVpbjogQ29taWNzIC0tIE9taWNzIFByZXApKioqCgpVc2UgdGhlIGBjb21pY3NgIGNvbnRhaW5lciB0byBwcmVwIHRoZSByYXcgcmVhZHMuCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yawpjb21pY3MgLS0gb21pY3MgcHJlcCAvRE5BX2RhdGEvU2FtcGxlXzEwNzEqCmBgYGAKKipETkEuZGF0YS5yYXcucHJlcC5wYnMqKiA8Zm9udCBjb2xvcj0iZ3JlZW4iPigiL0ROQV9kYXRhL3dvcmsvIik8L2ZvbnQ+IDAwOjE5IChocjptaW4pCgotIFJlbmFtZSB0aGUgc2FtcGxlIGZvbGRlcnMgbmV3bHkgY3JlYXRlZCBpbiB0aGUgPGZvbnQgY29sb3I9ImdyZWVuIj4iRE5BX2RhdGEvd29yayI8L2ZvbnQ+IGRpcmVjdG9yeSBhcyAiKipTYW1wbGVfMTA3MTA0KioiLCBldGMuCi0gUmVuYW1lIHRoZSBgLmZhc3RxYCBmaWxlcyB3aXRoaW4gZWFjaCBzYW1wbGUgZm9sZGVyIGluIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiJETkFfZGF0YS93b3JrIjwvZm9udD4gZGlyZWN0b3J5IGFzICIqKlNhbXBsZV8xMDcxMDRfZndkLmZhc3RxKioiLCAiKipTYW1wbGVfMTA3MTA0X3Jldi5mYXN0cSoqIiwgZXRjLgoKIyMjIDIuMi4gUUMgUmF3IFJlYWRzCgoqKipRQyB0aGUgUmF3IFJlYWRzIChTbWl0aDogQkJNYXBfUUMpKioqCgotIFRoZSAiKipiYm1hcF9xYy5zaCoqIiBzY3JpcHQgd2FzIHByb3ZpZGVkIGJ1dCBuZWVkZWQgdG8gYmUgZWRpdGVkIGludGVybmFsbHkgdG8gcmVmZXJlbmNlIHRoZSBjb3JyZWN0IGRpcmVjdG9yaWVzIGFuZCBwYXJzZXIgZmlsZXMgKCpzZWUgIioqYmJtYXBfcWMuc2gqKiIgaW4gdGhlICIqKlNDUklQVFMqKiIgc2VjdGlvbiBmb3IgYWxsIGludGVybmFsIGNvZGluZyopCi0gUGxhY2UgdGhlICIqKmJibWFwX3FjLnNoKioiIHNjcmlwdCBmaWxlIGluIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiJETkFfZGF0YS93b3JrIjwvZm9udD4gZGlyZWN0b3J5Ci0gUnVuIHRoZSAiKipiYm1hcF9xYy5zaCoqIiBzY3JpcHQgYW5kIHNwZWNpZnkgYSAiKioubG9nKioiIGZpbGUgb3V0cHV0CgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yawpiYXNoIGJibWFwX3FjLnNoID4gcWMubG9nCmBgYGAKKipETkEuZGF0YS5iYm1hcC5xYy5wYnMqKiA8Zm9udCBjb2xvcj0iZ3JlZW4iPigiL0ROQV9kYXRhL3dvcmsvIik8L2ZvbnQ+IDA1OjMyIChocjptaW4pCgojIyMgMi4zLiBDby1Bc3NlbWJsZSBRQyBSZWFkcwoKKioqQ28tQXNzZW1ibGUgdGhlIFFDIFJlYWRzIChTbWl0aDogTWVnYUhpdCkqKioKCi0gQ3JlYXRlIGEgbmV3IGRpcmVjdG9yeSB3aXRoaW4gPGZvbnQgY29sb3I9ImdyZWVuIj4iRE5BX2RhdGEvd29yayI8L2ZvbnQ+IG5hbWVkIDxmb250IGNvbG9yPSJncmVlbiI+IkROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkiPC9mb250PgoKPGZvbnQgY29sb3I9ImJsdWUiPioqMi4zLjEqKjwvZm9udD4gQ29uY2F0ZW5hdGUgdGhlIFFDJ2Qgc2FtcGxlIHJlYWRzIGludG8gYSBzaW5nbGUgZndkIGFuZCByZXYgZmlsZQoKLSBDb25jYXRlbmF0ZSB0aGUgUUMnZCBzYW1wbGUgcmVhZHMgaW50byBhIHNpbmdsZSBmd2QgYW5kIHJldiBmaWxlCi0gTW92ZSB0aGUgIioqX2FkdHJpbV9jbGVhbl9xdHJpbV9md2QuZGVyZXAuZmFzdHEqKiIgYW5kICIqKl9hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxKioiIGZpbGVzIGZyb20gZWFjaCBzYW1wbGUgdG8gdGhlIDxmb250IGNvbG9yPSJncmVlbiI+ImNvX2Fzc2VtYmx5IjwvZm9udD4gZGlyZWN0b3J5Ci0gQ29uY2F0b25hdGUgdGhlICIqKl9hZHRyaW1fY2xlYW5fcXRyaW1fZndkLmRlcmVwLmZhc3RxKioiIGZpbGUgZnJvbSBhbGwgc2FtcGxlcyBpbnRvIGEgc2luZ2xlICIqKjEwNzFfZndkLmRlcmVwLmZhc3RxKioiIHByaW9yIHRvIGNvLWFzc2VtYmxpbmcKLSBDb25jYXRvbmF0ZSB0aGUgIioqX2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEqKiIgZmlsZSBmcm9tIGFsbCBzYW1wbGVzIGludG8gYSBzaW5nbGUgIioqMTA3MV9yZXYuZGVyZXAuZmFzdHEqKiIgcHJpb3IgdG8gY28tYXNzZW1ibGluZwoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkKY2F0ICpfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSA+IDEwNzFfRE5BX2RhdGFfZndkLmRlcmVwLmZhc3RxCmNhdCAqX2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgPiAxMDcxX0ROQV9kYXRhX3Jldi5kZXJlcC5mYXN0cQpgYGBgCioqRE5BLmRhdGEucWMucmVhZC5jb25jYXRvbmF0ZS5wYnMqKiA8Zm9udCBjb2xvcj0iZ3JlZW4iPigiL0ROQV9kYXRhL3dvcmsvIik8L2ZvbnQ+IDAzOjQwIChocjptaW4pCgo8Zm9udCBjb2xvcj0iYmx1ZSI+KioyLjMuMioqPC9mb250PiBOb3JtYWxpemUgUmVhZHMgdG8gMjBYIENvdmVyYWdlIFByaW9yIHRvIEFzc2VtYmx5CgotIE5vcm1hbGl6ZSBhbGwga21lcnMgaW4gdGhlIGNvbWJpbmVkIHJlYWQgZGF0YXNldCB0byAyMFggY292ZXJhZ2UgKCoqKk5PVEU6KioqICpUaGlzIGlzIGttZXIgY292ZXJhZ2UsIG5vdCByZWFkIGNvdmVyYWdlKikKLSBBbHNvIHJlbW92ZSBhbnkga21lcnMgYmVsb3cgNVggY292ZXJhZ2UgKCppZiB0aGUgY292ZXJhZ2UgaXMgdGhpcyBsb3cgYWZ0ZXIgcG9vbGluZyBhbGwgc2FtcGxlcyB0aGVuIGl0IGlzIHByb2JhYmx5IGR1ZSB0byBzZXF1ZW5jaW5nIGVycm9yIG9yIGEgdmVyeSByYXJlIG9yZ2FuaXNtIHRoYXQgd29u4oCZdCBhc3NlbWJsZSBjb21wbGV0ZWx5IGFueXdheSopCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseQpjb21pY3MgYmJub3JtIGluPTEwNzFfRE5BX2RhdGFfZndkLmRlcmVwLmZhc3RxIGluMj0xMDcxX0ROQV9kYXRhX3Jldi5kZXJlcC5mYXN0cSBvdXQ9MTA3MV9ETkFfZGF0YV9iYm5vcm1fZndkLmRlcmVwLmZhc3RxIG91dDI9MTA3MV9ETkFfZGF0YV9iYm5vcm1fcmV2LmRlcmVwLmZhc3RxIHRhcmdldD0yMCBtaW5kZXB0aD01IHRocmVhZHM9MjAgLVhteDQyNWcgJj4gYmJub3JtLmxvZwpgYGBgCioqRE5BLmRhdGEuYmJub3JtLnBicyoqIDxmb250IGNvbG9yPSJncmVlbiI+KCIvRE5BX2RhdGEvd29yay8iKTwvZm9udD4gMDM6NDQgKGhyOm1pbikKCjxmb250IGNvbG9yPSJibHVlIj4qKjIuMy4zKio8L2ZvbnQ+IFJ1biB0aGUgQXNzZW1ibHkgTW9kdWxlIHRvIENvLUFzc2VtYmxlIENvbnRpZ3MgKENvbWljcyBNZWdhSGl0KQoKLSBSdW4gdGhlIGFzc2VtYmx5IG1vZHVsZSBvbiBRQy9QcmUtUHJvY2Vzc2VkIChiYm1hcCkgcmVhZHMgdG8gYnVpbGQgY29udGlncwotIFVzZSB0aGUgYE1FR0FISVRgIGFzc2VtYmxlciB0byBhc3NlbWJsZSByZWFkcyBpbnRvIGNvbnRpZ3MKLSAqR2VuZXJhbGx5LCB0aGUgbW9yZSBpdGVyYXRpb25zLCB0aGUgbG9uZ2VyIHRoZSBwcm9jZXNzIHRha2VzIGFuZCB0aGUgYmV0dGVyIHRoZSBhc3NlbWJseSoKICAtIEZvciBgTUVHQUhJVGA6IGs9MjU1IGlzIHRoZSBtYXhpbXVtLCB3aGljaCwgd2l0aCBhIHN0ZXAgc2l6ZSBvZiA2IG9yIDgsIGlzIHJlY29tbWVuZGVkIHVubGVzcyBzZXZlcmVseSBsaW1pdGVkIGJ5IGNvbXB1dGF0aW9uYWwgcmVzb3VyY2VzCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseQptZWdhaGl0IC0tay1taW4gMjEgLS1rLW1heCAyNTUgLS1rLXN0ZXAgOCAtMSAxMDcxX0ROQV9kYXRhX2Jibm9ybV9md2QuZGVyZXAuZmFzdHEgLTIgMTA3MV9ETkFfZGF0YV9iYm5vcm1fcmV2LmRlcmVwLmZhc3RxIC1vIC4vbWVnYWhpdF9vdXRfYmJub3JtCmBgYGAKKipETkEuZGF0YS5iYm5vcm0ubWVnYWhpdC5jb2Fzc2VtYmx5LmsyNTUucGJzKiogPGZvbnQgY29sb3I9ImdyZWVuIj4oIi9ETkFfZGF0YS93b3JrLyIpPC9mb250PiAzODoxNSAoaHI6bWluKQoKPGZvbnQgY29sb3I9ImJsdWUiPioqMi4zLjQqKjwvZm9udD4gUmUtRm9ybWF0IHRoZSBDb250aWdzIEZpbGUgZnJvbSB0aGUgTWVnYUhpdCBDby1Bc3NlbWJseQoKLSBUaGUgY29udGlnIGhlYWRlcnMgaW4gdGhlICIqKmZpbmFsLmNvbnRpZ3MuZmEqKiIgZmlsZSBmcm9tIGBNRUdBSElUYCBjb250YWluZWQgY29tcGxleCBjaGFyYWN0ZXJzIGFuZCBzcGFjZXMgdGhhdCB3ZXJlIHJlLWZvcm1hdHRlZCBwcmlvciB0byBtYXBwaW5nCiAgLSBUaGlzIHdhcyBlc3NlbnRpYWwgc28gdGhhdCB0aGUgbmFtZXMgb2YgdGhlIGNvbnRpZ3MgaW4gdGhlIGBCQU1gIGZpbGVzICgqZ2VuZXJhdGVkIGZyb20gdGhlIG1hcHBlciopIG1hdGNoZWQgdGhvc2UgaW4gdGhlICIqKmZpbmFsLmNvbnRpZ3MuZmEqKiIgZmlsZSAqKlBSSU9SKiogdG8gaW1wb3J0aW5nIGludG8gQW52aSdvCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9tZWdhaGl0X291dF9iYm5vcm0KCmhlYWQgZmluYWwuY29udGlncy5mYQoKPmsyNTVfMSBmbGFnPTEgbXVsdGk9MjQuMDAwMCBsZW49MzAxCkNBVEdDQ0NUR0dDR0NUR0NBR0NHR0FUQ1RHR0NBR0NUR0FDR0NDR0dBQUNDR0NBR0NHR0NDR0dBR0FUQ0NHQ0dDR0NHVENUR0NBR0dDR0NUQ1RBQ0NDR0NHR0NUR0dUQ0FBR1RHR0NBVENHQ1RBVENUQ0dDQ0FDQ0NBR0NHQ0dBQ0NDQ0dBR0dDQVRDR0dHQUNUR0dUQ0FDQ0dUQVRBQ0NBQ0NDR1RHR0dBR0FHQ0FDR0dBQ0FBQ1RDQ0NDR0NHQ1RHR0dBQ0NHQ1RDR0NUR0dDQUNHQ0FUQ0dBR0dUR0dUQ0FBR0NDQ0NHQ0NDR1RBQ0FDQ0NHQ0NUR0dBQ0FDQ0NHVENBR0dUR0NHR0dBQ0NDR1RDR0NBR0NHR0NDQ0FDQ0dBQ1RHR0dBQ1RBQ0cKYGBgYAoKLSBOdW1iZXJzLCBsZXR0ZXJzLCBhbmQgdW5kZXJzY29yZXMgd2VyZSBPSyBpbiBzZXF1ZW5jZSBuYW1lcyBidXQgYW55IG90aGVyIGNoYXJhY3RlcnMgY2F1c2UgdHJvdWJsZSBpbiBBbnZpJ28KLSBUaGUgZm9sbG93aW5nIGNvbW1hbmRzIHJlZm9ybWF0dGVkIHRoZSAiKipmaW5hbC5jb250aWdzLmZhKioiIGZpbGUgYnkgcmVwbGFjaW5nIHNwYWNlcyBhbmQgIj0iIHNpZ25zIHdpdGggIl8iCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9tZWdhaGl0X291dF9iYm5vcm0Kc2VkIC1lICdzL1xzL18vZycgZmluYWwuY29udGlncy5mYSA+IGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhCnNlZCAtZSAncy89L18vZycgZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uZmEgPiBmaW5hbC5jb250aWdzLmZpeGVkMi5iYm5vcm0uZmEKbXYgZmluYWwuY29udGlncy5maXhlZDIuYmJub3JtLmZhIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhCgpoZWFkIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhCgo+azI1NV8xX2ZsYWdfMV9tdWx0aV8yNC4wMDAwX2xlbl8zMDEKQ0FUR0NDQ1RHR0NHQ1RHQ0FHQ0dHQVRDVEdHQ0FHQ1RHQUNHQ0NHR0FBQ0NHQ0FHQ0dHQ0NHR0FHQVRDQ0dDR0NHQ0dUQ1RHQ0FHR0NHQ1RDVEFDQ0NHQ0dHQ1RHR1RDQUFHVEdHQ0FUQ0dDVEFUQ1RDR0NDQUNDQ0FHQ0dDR0FDQ0NDR0FHR0NBVENHR0dBQ1RHR1RDQUNDR1RBVEFDQ0FDQ0NHVEdHR0FHQUdDQUNHR0FDQUFDVENDQ0NHQ0dDVEdHR0FDQ0dDVENHQ1RHR0NBQ0dDQVRDR0FHR1RHR1RDQUFHQ0NDQ0dDQ0NHVEFDQUNDQ0dDQ1RHR0FDQUNDQ0dUQ0FHR1RHQ0dHR0FDQ0NHVENHQ0FHQ0dHQ0NDQUNDR0FDVEdHR0FDVEFDRwpgYGBgCgojIyMgMi40LiBJbmRleCBDb250aWdzIGFuZCBNYXAKCioqKkluZGV4IHRoZSBDby1Bc3NlbWJsZWQgQ29udGlncyBhbmQgTWFwIChIZWluOiBPbWljcyBNYXBwaW5nKSoqKgoKLSBPbmNlIHRoZSBzZXF1ZW5jZSBoZWFkZXJzIGluIHRoZSBjb250aWdzIGZpbGUgd2VyZSBjbGVhbmVkIHVwLCB0aGUgY28tYXNzZW1ibHkgd2FzIGluZGV4ZWQgYXMgZm9sbG93czoKCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9CmNkIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L21lZ2FoaXRfb3V0X2Jibm9ybQpjb21pY3MgLS0gb21pY3MgbWFwcGluZyAtYSBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtLWluZGV4LW9ubHkKYGBgYAoqKkROQS5kYXRhLmJibm9ybS5pbmRleC5jb250aWdzLnBicyoqIDxmb250IGNvbG9yPSJncmVlbiI+KCIvRE5BX2RhdGEvd29yay8iKTwvZm9udD4gMDA6NDYgKGhyOm1pbikKCi0gVGhlIG91dHB1dCB3YXMgYSBkaXJlY3RvcnkgY2FsbGVkIDxmb250IGNvbG9yPSJncmVlbiI+Ii9ib3d0aWUyLWluZGV4IjwvZm9udD4KLSBSZW5hbWUgYXMgPGZvbnQgY29sb3I9ImdyZWVuIj4iL2Jvd3RpZTItaW5kZXhfYmJub3JtIjwvZm9udD4KCjxmb250IGNvbG9yPSJibHVlIj4qKjIuNC4xKio8L2ZvbnQ+IE1hcCBTaG9ydCBSZWFkcyBmcm9tIEVhY2ggU2FtcGxlIHRvIHRoZSBDb250aWdzCgotIENyZWF0ZSBhIDxmb250IGNvbG9yPSJncmVlbiI+Ii9ETkFfZGF0YS93b3JrL21hcHBpbmciPC9mb250PiBkaXJlY3RvcnkgYW5kIG1vdmUgdGhlIDxmb250IGNvbG9yPSJncmVlbiI+Ii9ib3d0aWUyLWluZGV4X2Jibm9ybSI8L2ZvbnQ+IGRpcmVjdG9yeSBpbnRvIGl0Ci0gTW92ZSB0aGUgIioqL2NvX2Fzc2VtYmx5L21lZ2FoaXRfb3V0X2Jibm9ybS9maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSoqIiBmaWxlIHRvIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvd29yay9jb19hc3NlbWJseSI8L2ZvbnQ+IGRpcmVjdG9yeQotIEluZGl2aWR1YWxseSBtYXAgdGhlIHNob3J0IHJlYWRzIGZyb20gZWFjaCBzYW1wbGUgdG8gdGhlIGNvbnRpZ3MsIHdoaWNoIHdpbGwgY3JlYXRlIHNlcGFyYXRlIG91dHB1dCBkaXJlY3RvcmllcyBmb3IgZWFjaCBzYW1wbGUgY29udGFpbmluZyB0aGUgbWFwcGluZyByZXN1bHQgZmlsZXMKCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9CmNkIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5CmNvbWljcyAtLSBvbWljcyBtYXBwaW5nIC0taW5kZXgtZGlyIC9ETkFfZGF0YS93b3JrL21hcHBpbmcvYm93dGllMi1pbmRleF9iYm5vcm0vIC1hIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhIC1mIFNhbXBsZV8xMDcxMDRfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSAtciBTYW1wbGVfMTA3MTA0X2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgLW8gMTA3MTA0X2Jibm9ybV9tYXBwZWRfcmVhZHMKY29taWNzIC0tIG9taWNzIG1hcHBpbmcgLS1pbmRleC1kaXIgL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9ib3d0aWUyLWluZGV4X2Jibm9ybS8gLWEgZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uZmEgLWYgU2FtcGxlXzEwNzEwNV9hZHRyaW1fY2xlYW5fcXRyaW1fZndkLmRlcmVwLmZhc3RxIC1yIFNhbXBsZV8xMDcxMDVfYWR0cmltX2NsZWFuX3F0cmltX3Jldi5kZXJlcC5mYXN0cSAtbyAxMDcxMDVfYmJub3JtX21hcHBlZF9yZWFkcwpjb21pY3MgLS0gb21pY3MgbWFwcGluZyAtLWluZGV4LWRpciAvRE5BX2RhdGEvd29yay9tYXBwaW5nL2Jvd3RpZTItaW5kZXhfYmJub3JtLyAtYSBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtZiBTYW1wbGVfMTA3MTA2X2FkdHJpbV9jbGVhbl9xdHJpbV9md2QuZGVyZXAuZmFzdHEgLXIgU2FtcGxlXzEwNzEwNl9hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxIC1vIDEwNzEwNl9iYm5vcm1fbWFwcGVkX3JlYWRzCmNvbWljcyAtLSBvbWljcyBtYXBwaW5nIC0taW5kZXgtZGlyIC9ETkFfZGF0YS93b3JrL21hcHBpbmcvYm93dGllMi1pbmRleF9iYm5vcm0vIC1hIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhIC1mIFNhbXBsZV8xMDcxMDdfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSAtciBTYW1wbGVfMTA3MTA3X2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgLW8gMTA3MTA3X2Jibm9ybV9tYXBwZWRfcmVhZHMKY29taWNzIC0tIG9taWNzIG1hcHBpbmcgLS1pbmRleC1kaXIgL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9ib3d0aWUyLWluZGV4X2Jibm9ybS8gLWEgZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uZmEgLWYgU2FtcGxlXzEwNzEwOF9hZHRyaW1fY2xlYW5fcXRyaW1fZndkLmRlcmVwLmZhc3RxIC1yIFNhbXBsZV8xMDcxMDhfYWR0cmltX2NsZWFuX3F0cmltX3Jldi5kZXJlcC5mYXN0cSAtbyAxMDcxMDhfYmJub3JtX21hcHBlZF9yZWFkcwpjb21pY3MgLS0gb21pY3MgbWFwcGluZyAtLWluZGV4LWRpciAvRE5BX2RhdGEvd29yay9tYXBwaW5nL2Jvd3RpZTItaW5kZXhfYmJub3JtLyAtYSBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtZiBTYW1wbGVfMTA3MTEwX2FkdHJpbV9jbGVhbl9xdHJpbV9md2QuZGVyZXAuZmFzdHEgLXIgU2FtcGxlXzEwNzExMF9hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxIC1vIDEwNzExMF9iYm5vcm1fbWFwcGVkX3JlYWRzCmNvbWljcyAtLSBvbWljcyBtYXBwaW5nIC0taW5kZXgtZGlyIC9ETkFfZGF0YS93b3JrL21hcHBpbmcvYm93dGllMi1pbmRleF9iYm5vcm0vIC1hIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhIC1mIFNhbXBsZV8xMDcxMTFfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSAtciBTYW1wbGVfMTA3MTExX2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgLW8gMTA3MTExX2Jibm9ybV9tYXBwZWRfcmVhZHMKY29taWNzIC0tIG9taWNzIG1hcHBpbmcgLS1pbmRleC1kaXIgL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9ib3d0aWUyLWluZGV4X2Jibm9ybS8gLWEgZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uZmEgLWYgU2FtcGxlXzEwNzExMl9hZHRyaW1fY2xlYW5fcXRyaW1fZndkLmRlcmVwLmZhc3RxIC1yIFNhbXBsZV8xMDcxMTJfYWR0cmltX2NsZWFuX3F0cmltX3Jldi5kZXJlcC5mYXN0cSAtbyAxMDcxMTJfYmJub3JtX21hcHBlZF9yZWFkcwpjb21pY3MgLS0gb21pY3MgbWFwcGluZyAtLWluZGV4LWRpciAvRE5BX2RhdGEvd29yay9tYXBwaW5nL2Jvd3RpZTItaW5kZXhfYmJub3JtLyAtYSBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtZiBTYW1wbGVfMTA3MTEzX2FkdHJpbV9jbGVhbl9xdHJpbV9md2QuZGVyZXAuZmFzdHEgLXIgU2FtcGxlXzEwNzExM19hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxIC1vIDEwNzExM19iYm5vcm1fbWFwcGVkX3JlYWRzCmNvbWljcyAtLSBvbWljcyBtYXBwaW5nIC0taW5kZXgtZGlyIC9ETkFfZGF0YS93b3JrL21hcHBpbmcvYm93dGllMi1pbmRleF9iYm5vcm0vIC1hIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhIC1mIFNhbXBsZV8xMDcxMTRfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSAtciBTYW1wbGVfMTA3MTE0X2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgLW8gMTA3MTE0X2Jibm9ybV9tYXBwZWRfcmVhZHMKY29taWNzIC0tIG9taWNzIG1hcHBpbmcgLS1pbmRleC1kaXIgL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9ib3d0aWUyLWluZGV4X2Jibm9ybS8gLWEgZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uZmEgLWYgU2FtcGxlXzEwNzExNV9hZHRyaW1fY2xlYW5fcXRyaW1fZndkLmRlcmVwLmZhc3RxIC1yIFNhbXBsZV8xMDcxMTVfYWR0cmltX2NsZWFuX3F0cmltX3Jldi5kZXJlcC5mYXN0cSAtbyAxMDcxMTVfYmJub3JtX21hcHBlZF9yZWFkcwpjb21pY3MgLS0gb21pY3MgbWFwcGluZyAtLWluZGV4LWRpciAvRE5BX2RhdGEvd29yay9tYXBwaW5nL2Jvd3RpZTItaW5kZXhfYmJub3JtLyAtYSBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtZiBTYW1wbGVfMTA3MTE2X2FkdHJpbV9jbGVhbl9xdHJpbV9md2QuZGVyZXAuZmFzdHEgLXIgU2FtcGxlXzEwNzExNl9hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxIC1vIDEwNzExNl9iYm5vcm1fbWFwcGVkX3JlYWRzCmNvbWljcyAtLSBvbWljcyBtYXBwaW5nIC0taW5kZXgtZGlyIC9ETkFfZGF0YS93b3JrL21hcHBpbmcvYm93dGllMi1pbmRleF9iYm5vcm0vIC1hIGZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmZhIC1mIFNhbXBsZV8xMDcxMTdfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSAtciBTYW1wbGVfMTA3MTE3X2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgLW8gMTA3MTE3X2Jibm9ybV9tYXBwZWRfcmVhZHMKY29taWNzIC0tIG9taWNzIG1hcHBpbmcgLS1pbmRleC1kaXIgL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9ib3d0aWUyLWluZGV4X2Jibm9ybS8gLWEgZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uZmEgLWYgU2FtcGxlXzEwNzExOV9hZHRyaW1fY2xlYW5fcXRyaW1fZndkLmRlcmVwLmZhc3RxIC1yIFNhbXBsZV8xMDcxMTlfYWR0cmltX2NsZWFuX3F0cmltX3Jldi5kZXJlcC5mYXN0cSAtbyAxMDcxMTlfYmJub3JtX21hcHBlZF9yZWFkcwpjb21pY3MgLS0gb21pY3MgbWFwcGluZyAtLWluZGV4LWRpciAvRE5BX2RhdGEvd29yay9tYXBwaW5nL2Jvd3RpZTItaW5kZXhfYmJub3JtLyAtYSBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtZiBTYW1wbGVfMTA3MTIxX2FkdHJpbV9jbGVhbl9xdHJpbV9md2QuZGVyZXAuZmFzdHEgLXIgU2FtcGxlXzEwNzEyMV9hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxIC1vIDEwNzEyMV9iYm5vcm1fbWFwcGVkX3JlYWRzCmBgYGAKKipETkEuZGF0YS5iYm5vcm0uc2hvcnQucmVhZC5tYXBwaW5nLnBicyoqIDxmb250IGNvbG9yPSJncmVlbiI+KCIvRE5BX2RhdGEvd29yay8iKTwvZm9udD4gMTE6NTEgKGhyOm1pbikKCi0gVGhlIHJlc3VsdHMgZm9yIGVhY2ggaW5kaXZpZHVhbCBzYW1wbGUgd2VyZSBhIG1hcHBpbmcgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGZvbGxvd2luZyBmaWxlczoKIioqL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvXCpiYm5vcm1fbWFwcGVkX3JlYWRzKioiIChyZXBsYWNlIFwqIHdpdGggU2FtcGxlSUQpCiIqKmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmNvdioqIiB0YWItZGVsaW1pdGVkIGZpbGUgb2YgdGhlIGF2ZXJhZ2UgY292ZXJhZ2Ugb2YgZWFjaCBjb250aWcgaW4gdGhlIGFzc2VtYmx5CiIqKmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmJhbSoqIiBjb250YWlucyB0aGUgbWFwcGluZyBpbmZvcm1hdGlvbgoiKipmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtKioiIGNvbnRhaW5zIHRoZSBtYXBwaW5nIGluZm9ybWF0aW9uIHNvcnRlZCBieSBwb3NpdGlvbgoiKipmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtLmJhaSoqIiBhIGNvbXBhbmlvbiBmaWxlIHRvIHRoZSBgc29ydGVkLmJhbWAgZmlsZSwgd2hpY2ggY29udGFpbnMgdGhlIGluZGV4Ci0gTW92ZSBhbGwgb2YgdGhlICIqKi9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L1wqYmJub3JtX21hcHBlZF9yZWFkcyoqIiBmb2xkZXJzIHRvIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvRE5BX2RhdGEvd29yay9tYXBwaW5nIjwvZm9udD4gZGlyZWN0b3J5Ci0gUmUtbmFtZSBlYWNoIGZpbGUgd2l0aCB0aGUgc2FtcGxlIG51bWJlciBhcyB0aGUgcHJlZml4OiAiKipTYW1wbGVfMTA3MTA0LmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLmNvdioqIiwgZXRjLgoKIyMjIDIuNS4gQ3JlYXRlIEFudmknbyBEYXRhYmFzZQoKKioqQ3JlYXRlIEFudmknbyBEYXRhYmFzZSBhbmQgUHJvZmlsZXMgKFNtaXRoOiBBbnZpJ28pKioqCgotIENyZWF0ZSBhbiBBbnZpJ28gY29udGlncyBkYXRhYmFzZSBmcm9tIHRoZSBjby1hc3NlbWJseSBhbmQgcHJvZmlsZSB0aGUgYWJ1bmRhbmNlIChjb3ZlcmFnZSkgaW5mb3JtYXRpb24gZnJvbSB0aGUgYC5iYW1gIGZpbGVzIGludG8gYW4gQW52aSdvIHByb2ZpbGUKLSBDcmVhdGUgYSBtZXJnZWQgcHJvZmlsZSBvZiBhbGwgc2FtcGxlcwoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkKYW52aS1nZW4tY29udGlncy1kYXRhYmFzZSAtZiBmaW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5mYSAtbyBETkEuZGF0YS5iYm5vcm0uYW52aW8uY29udGlncy5kYiAtbiBETkFfZGF0YV9iYm5vcm0gLS1zcGxpdC1sZW5ndGggMTAwMDAgLS1rbWVyLXNpemUgNApgYGBgCioqRE5BLmRhdGEuYmJub3JtLmFudmlvLmNvbnRpZ3MuZGF0YWJhc2UucGJzKiogPGZvbnQgY29sb3I9ImdyZWVuIj4oIi9ETkFfZGF0YS93b3JrLyIpPC9mb250PiAwNTowMCAoaHI6bWluKQoKLSBDcmVhdGUgdGhlIEFudmknbyBjb250aWdzIGRhdGFiYXNlICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiKioiIGZpbGUgaW4gdGhlIDxmb250IGNvbG9yPSJncmVlbiI+Ii9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5IjwvZm9udD4gZGlyZWN0b3J5Ci0gVGhlICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiKioiIGRhdGFiYXNlIGNvbnRhaW5zIGNvbnRpZyBzZXF1ZW5jZXMsIHNwbGl0dGluZyBjb250aWdzIGxhcmdlciB0aGFuIDEwa2IgaW50byBzcGxpdHMgb2YgMTBrYiBvciBsZXNzCi0gRGVmYXVsdCBrbWVyLXNpemUgaXMgImttZXItc2l6ZSA0IgoKPGZvbnQgY29sb3I9ImJsdWUiPioqMi41LjEqKjwvZm9udD4gQW5ub3RhdGUgQ29udGlncyBEYXRhYmFzZSAtLSBITU1TCgotIEFubm90YXRlIGNvbnRpZ3MgZGF0YWJhc2Ugd2l0aCB0aGUgc3RhcnQgYW5kIHN0b3Agc2l0ZXMgb2Ygc2luZ2xlLWNvcHkgaG91c2Uta2VlcGluZyBnZW5lcyBhbmQgclJOQSBnZW5lcwotICoqKk5lY2Vzc2FyeSB0byBnZXQgYmluIGNvbXBsZXRlbmVzcyBhbmQgY29udGFtaW5hdGlvbiBtZXRyaWNzIGFsb25nIHdpdGggclJOQSBhbm5vdGF0aW9ucyBpbiByZWFsIHRpbWUgYXMgYmlucyB3aWxsIGJlIG1hbnVhbGx5IHJlZmluZWQgaW4gc3Vic2VxdWVudCBzdGVwcyoqKgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkKYW52aS1ydW4taG1tcyAtYyBETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtLW51bS10aHJlYWRzIDIwCmBgYGAKKipETkEuZGF0YS5iYm5vcm0uYW52aW8uY29udGlncy5obW1zLnBicyoqIDxmb250IGNvbG9yPSJncmVlbiI+KCIvRE5BX2RhdGEvd29yay8iKTwvZm9udD4gMTY6NTIgKGhyOm1pbikKCjxmb250IGNvbG9yPSJibHVlIj4qKjIuNS4yKio8L2ZvbnQ+IEFubm90YXRlIENvbnRpZ3MgRGF0YWJhc2UgLS0gR2hvc3RLb2FsYQoKLSBBbm5vdGF0ZSB0aGUgQW52aSdvIGdlbmUgY2FsbHMgd2l0aCB0YXhvbm9teSBhbmQgZnVuY3Rpb25hbCBhbm5vdGF0aW9ucyBmcm9tIEtFR0cgR2hvc3RLb2FsYSdzIG9ubGluZSBkYXRhYmFzZQoKPGZvbnQgY29sb3I9ImJsdWUiPioqKjIuNS4yLjEqKio8L2ZvbnQ+IEZpcnN0LCBleHBvcnRlIHRoZSBhbWlubyBhY2lkIHNlcXVlbmNlcyBvZiB0aGUgQW52aSdvIGdlbmUgY2FsbHM6CgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseQphbnZpLWdldC1zZXF1ZW5jZXMtZm9yLWdlbmUtY2FsbHMgLWMgRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLW8gRE5BX2RhdGFfYmJub3JtX2FudmlvX2dlbmVfY2FsbHMuZmFhIC0tZ2V0LWFhLXNlcXVlbmNlcwpgYGBgCioqRE5BLmRhdGEuYmJub3JtLmFudmlvLmV4cG9ydC5hYS5zZXFzLnBicyoqIDxmb250IGNvbG9yPSJncmVlbiI+KCIvRE5BX2RhdGEvd29yay8iKTwvZm9udD4gMDA6MTAgKGhyOm1pbikKCjxmb250IGNvbG9yPSJibHVlIj4qKioyLjUuMi4yKioqPC9mb250PiBHaG9zdEtvYWxhIGNhbm5vdCBhY2NlcHQgZ2VuZSBJRHMgdGhhdCBzdGFydCB3aXRoIG51bWJlcnMsIHNvIHRoZSBwcmVmaXggIioqZ2VuZWNhbGwqKiIgd2FzIGFkZGVkIHRvIGFsbCBBQSBzZXF1ZW5jZXMgYXMgZm9sbG93czoKCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9CnNlZCAncy8+Lz5nZW5lY2FsbF8vZycgRE5BX2RhdGFfYmJub3JtX2FudmlvX2dlbmVfY2FsbHMuZmFhID4gRE5BX2RhdGFfYmJub3JtX2FudmlvX2dlbmVfY2FsbHNfZWRpdGVkLmZhYQptdiBETkFfZGF0YV9iYm5vcm1fYW52aW9fZ2VuZV9jYWxsc19lZGl0ZWQuZmFhIEROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzLmZhYQoKI0VYQU1QTEUKW2NvX2Fzc2VtYmx5XSQgaGVhZCBETkFfZGF0YV9iYm5vcm1fYW52aW9fZ2VuZV9jYWxscy5mYWEKPmdlbmVjYWxsXzAKSEFMQUxRUklXUUxUUEVQUVJQRUlSQVJMUUFMWVBSTFZLV0hSWUxBVFFSRFBFQVNHTFZUVllIUFdFU1RETlNQUldEUlNMQVJJRVZWS1BSUFlUUkxEVFJRVlJEUFNRUlBURFdEWQpgYGBgCgo8Zm9udCBjb2xvcj0iYmx1ZSI+KioqMi41LjIuMyoqKjwvZm9udD4gQ2hlY2sgdGhlICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzLmZhYSoqIiBmaWxlIGZvciBlbXB0eSBzZXF1ZW5jZXMgYW5kIHJlbW92ZSB0aGVtIHByaW9yIHRvIHN1Ym1pdHRpbmcgdG8gR2hvc3RLb2FsYSBmb3IgYW5ub3RhdGlvbgoKICAtICoqKk5PVEU6KioqICpFbXB0eSBzZXF1ZW5jZXMgYXJlIG9mdGVuIGZvdW5kIGF0IHRoZSBlbmQgb2YgdGhlICIqKlwqLmZhYSoqIiBmaWxlICh1c2UgInRhaWwiIGNvbW1hbmQgdG8gdmlldyB0aGUgbGFzdCAyMCBsaW5lcykqCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseQp0YWlsIEROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzLmZhYQoKI0VYQU1QTEUKW2NvX2Fzc2VtYmx5XSQgdGFpbCBETkFfc3Vic2V0X2FudmlvX2dlbmVfY2FsbHMuZmFhCmdlbmVjYWxsXzM5MTc2MTMKTVJWWFNYTFJWTkFHR1ZES1NDS1NSR1BBUkFUR1JSR1NOVFhWUlBMWFNHSUFTUktWR1hGUElWUFFHWFJGRkFMR0FBQ1ZWU0FTV1hHTkdMUFJMUlJMR0VMUkdYUFBQTUVMUkhHUFlTWUdSTFFUUklGUk5HUktTREdBClRQUkRSWFNBU1ZSS0RMTFNHVEtGSURHVFJYSVJHU1hMQ0FTUlNHTlRFQVBTSVRSTkhXQVhSVlNSUlBZWFNMVktTVkdTVENHTFJHS1JZR1NSQVhFVkhHVEhHR0dWS1NWRElNR05US0dFR05BTFZSU1hSU05US0FSVgpBTkdJUllQR1NQR1BRUkNTTFZMUlNJRFBMWERYQU5BVlNFUFBHWFlEUktJS1RRUk5SUkdMQVFBVkRZQUFYRlZHS1JSVExQUkxFSVFMSFBUWEtHUlNMUkdDV1RHREFXU1NTVlJHTE5DU0xRV0dORVJOUFJDTExQSVcKUEdFVEFQU1JFUktWR01UUERRSFZQTElQV0FBUklJUVdTVlFRVkFNUFhHR0FOUFlLVERQU1REWEdMUVBUU1hTUk5SWFhTUlZTUVRHVk5URlNTTFZMVEFSUVZLR1ZHR0FSUlRBU1JTVFRBTlNNVFJUS1NYUUdUR1NHClNDU1dOSVMKPmdlbmVjYWxsXzM5MTc2MTQKCj5nZW5lY2FsbF8zOTE3NjE1CmBgYGAKCi0gVXNlIHRoZSBmb2xsb3dpbmcgc2NyaXB0IHRvIHJlbW92ZSBhbGwgZW1wdHkgc2VxdWVuY2VzIGZyb20gdGhlICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzLmZhYSoqIiBmaWxlOgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0Kc2VkICcvXj4vIHtOOyAvXG4kL2R9JyBETkFfZGF0YV9iYm5vcm1fYW52aW9fZ2VuZV9jYWxscy5mYWEgPiBETkFfZGF0YV9iYm5vcm1fYW52aW9fZ2VuZV9jYWxsc19jbGVhbi5mYWEKbXYgRE5BX2RhdGFfYmJub3JtX2FudmlvX2dlbmVfY2FsbHNfY2xlYW4uZmFhIEROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzLmZhYQoKI0VYQU1QTEUKW2NvX2Fzc2VtYmx5XSQgdGFpbCBETkFfZGF0YV9iYm5vcm1fYW52aW9fZ2VuZV9jYWxscy5mYWEKPmdlbmVjYWxsXzIzMzc3MzkKQUhMVFJMRVRSVEtFRk5NUkFTUldERUtQQUdSVktBU0hTVlRMQ0lHRUlQU0xWUktIRVBHQVNQQUhIS0xUV0xXV1NMU1ZIVkVUUktNVk5ZQVdBR1hTUUdLTFdXUlNWQUlMVENLU0lWWFBHWVJHRVJMSUVQU1NTV0ZQClBLRlBTR1hMQUxHTkFWTFBHS0FORFhSUFdHUk5ETE5MRlNORktXVlJTUEFDTE5BS0xLU0dSV0lSQVBTR1BMTFZTUlRHQVZHWFRFUlhWTUFQREVUTE1SU1FLUkNXTExYVEFHUldQV0tTRVBBS0VDVlRUSExQS1FMQQpMS01ER0FSQVNHTFlTQVZBQVZOS1hOU0hBQVRTUlJWQUFWQVNLQVlHUkVQR1dTUlJSQ1JTV1dYWFFJTEtSRVBYR0xLV1JSVlBDRVFRTE5NR1FTSUxSWVJSS1BGUlNHVkRTVklZV1JXTExYTEFTUkxGUlNJUFBITFAKS0dOUlZOSVBFUEdJR1lEQUdHR1JBSExSSFNDUkFUTkFBVFFNTlNFVExUUkFMRVJWVkZTU1hHVEdTTEVTREhQQUlHUldDUFhTVEFWTEFWU0dBSFZTVkxFVFBSRVNWSUZWUERSVEhJUlNSU1BSWElBU1JQTEVBQ1JYCkdLU0FLV0lDTkZHS0tJR1NFR1dBR1JBQVZHU0NSR0ZHR0dQVkxXTFdTUlJFU0FWWUNHUkFSVFNBR0FYUVdUQVZBQUxQUkdWRlNWU0FUU0ZHQVhRUFRRTldIR1BHRVNEQ0xJS1RLSENER1dYU1ZMVFFDREZDUFZMWApNU0tYUk5TVEtSR1hUQUdWVE1UTExSWFBOQVNTU05YWFJBWE1EUVJEU0hDUFlMTFNTRVRUQUtHVEdMQUVTQUdLRURQVkVMRFNTTFRSWEdETVJHVkFYVkdHU0FTQ1JRWE5UVFRGSVZTTExJUVhDR1ZXTExWQVJLTlIKR0FBVElMQUxUUlRETEZSUFJJUlNERFNWUlJHVlhMR1JZSUNRVFZUUVZTWEdLTFNFRFJOTEFYU0tSQUtBQ0xJTElGU1ROVERSRVNWQVlSU0ZYTFhFRlhBUkdWUktWVFRHSVRHTFdSUFNWSFNEVkFGWFNGRFZHU1NZCkhDREFBVkFLUlJJVkhQTElHTlZTV1ZYVFZWUlFWU0ZUTExNCj5nZW5lY2FsbF8yMzM3NzQ1ClFBTktDTVdXTVBXUlNRQU1LRFZWQUNFS1NSR0FTS1JBTElSRVlQTkdFVFJQQVJWVFBHWElIUkxHUkFOU1ZOWE5JU1ZURUdURUlOUkRTR1NTR0VSVFJTU1FRVkxBTExMQUtSU0dLQUdRU0dYWFBSVFFLUVdDR1RSUApBVFNSQUdIVktTQ0xLTUdHUFNTS0FLWVNYU1REU0VQVlBYR0tHRUtOUEdSR1ZLWElMS1BIQVlLS1NFUExMWVhTU1JWTFNSU0RBUkFBUkxLUkxJREVJRFBMVkFTTFRYS0lSVlZMR0lERFJTVkdEQUxSVkFRQ0dOVEEKU0xTUkFTS1BYR0xSU0VHUVhTUkdER1ZQRlZYV1ZTRExIU1ZBU0xTRVNBR0FHS1BTUE5SQU5FTExHVkRQS1BERExMTUFSTUtWUlhIQUxFVlJUSFhDWEtJUkdYQVZHUkdFUkxOS1NHTlNXRlNQS1RJWFZWUEhWTExMCkdWRUhDWUdYR1ZNQVRZUVRJQU5TRVlXUVZYQVdFVFZUR0NYUlBWU1JHS1FQR1BQQUtWUEtZU1hWR05FVkdSUktRU0dHV0xSU1NIUExLS0FYWExURFJWVkxSR1JDTkdBUVRSSFJTWEdDCmBgYGAKCjxmb250IGNvbG9yPSJibHVlIj4qKioyLjUuMi40KioqPC9mb250PiBHaG9zdEtvYWxhIGFsc28gaGFzIGEgbWF4IGZpbGUgc2l6ZSBsaW1pdCBvZiAzMDAgTUIsIHNvIGZpbGVzIGxhcmdlciB0aGFuIHRoZSBtYXggZmlsZSBzaXplIHdlcmUgc3BsaXQgaW50byBzbWFsbGVyIGZpbGVzIGFuZCB0aGUgYW5ub3RhdGlvbnMgd2VyZSBydW4gaW4gYmF0Y2hlcyB3aXRoIHRoZSByZXN1bHRzIGNvbmNhdGVuYXRlZCBwcmlvciB0byBiZWluZyBhZGRlZCBpbnRvIEFudmknby4KClRvIHNwbGl0IHRoZSBkYXRhIGludG8gc21hbGxlciBmaWxlczoKCi0gRG93bmxvYWQgIioqRE5BX2RhdGF0X2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzLmZhYSoqIiAoNzI0LDMwNiwzMzEgYnl0ZXMpIHRvIGxvY2FsIGRpcmVjdG9yeSBhbmQgb3BlbiB3aXRoIHRleHQgZWRpdG9yICgqQkJFZGl0IHByZWZlcnJlZCopCi0gU2VsZWN0IGEgdGhpcmQgb2YgdGhlIGRhdGEgdG8gY3V0IGZyb20gdGhlIGZpbGUgKOKMmFgpIC0tICpFbnN1cmUgdGhhdCBhIGdlbmUgc2VxdWVuY2UgaXMgTk9UIGN1dCBpbiBoYWxmKiAtLSBTdGFydCB3aXRoIGEgKioiZ2VuZWNhbGxfXCoiKioKLSBPcGVuIGEgbmV3IHRleHQgZmlsZSBhbmQgcGFzdGUgKOKMmFYpIHRoZSBjdXQgZGF0YSBmcm9tIHRoZSBvcmlnaW5hbCBmaWxlICgqcmVwZWF0ZWQgd2l0aCB0aGUgc2Vjb25kIHRoaXJkIG9mIGRhdGEgYW5kIHdpdGggdGhlIGZpbmFsIHRoaXJkIG9mIGRhdGEqKS4KLSBSZW5hbSB0aGUgdGhyZWUgZmlsZXMgYXMgZm9sbG93czoKICAtICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzXzEuZmFhKioiIDIzNyw2MTMsMTg1ICgyMzcuNiBNQikKICAtICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzXzIuZmFhKioiIDI0NiwwNDMsMjU2ICgyNDYuMCBNQikKICAtICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzXzMuZmFhKioiIDI0MCw2NDksODg4ICgyNDAuNyBNQikKLSBDaGVjayB0aGF0IGFsbCBmaWxlcyB3ZXJlIGxlc3MgdGhhbiAzMDAgTUIgaW4gc2l6ZQogIAo8Zm9udCBjb2xvcj0iYmx1ZSI+KioqMi41LjIuNSoqKjwvZm9udD4gU3VibWl0IHRoZSBhbWlubyBhY2lkIGZpbGVzIGZvciBib3RoIGZ1bmN0aW9uYWwgYW5kIHRheG9ub21pYyBhbm5vdGF0aW9uIGluIFtLRUdHIEdob3N0S29hbGFdKGh0dHBzOi8vd3d3LmtlZ2cuanAvZ2hvc3Rrb2FsYS8pCgotIE9ubHkgT05FICIqKi5mYWEqKiIgZmlsZSBjYW4gYmUgc3VibWl0dGVkIGF0IGEgdGltZSBmb3IgYW5ub3RhdGlvbgotIFVzZSAiKipnZW51c19wcm9rYXJ5b3RlcyArIGZhbWlseV9ldWthcnlvdGVzKioiIGFubm90YXRpb24gb3B0aW9uCiAgLSAiKipETkFfZGF0YV9iYm5vcm1fYW52aW9fZ2VuZV9jYWxsc18xLmZhYSoqIiAoMjM3LjYgTUIpCiAgICAtIFVwbG9hZCB0aW1lIHRvIEdob3N0S29hbGEgMDoxMCAoaHI6bWluKSAtLSBQcm9jZXNzaW5nIHRpbWUgYXQgR2hvc3RLb2FsYSA0MjoyNCAoaHI6bWluKQogIC0gIioqRE5BX2RhdGFfYmJub3JtX2FudmlvX2dlbmVfY2FsbHNfMi5mYWEqKiIgKDI0Ni4wIE1CKQogICAgLSBVcGxvYWQgdGltZSB0byBHaG9zdEtvYWxhIDA6MTAgKGhyOm1pbikgLS0gUHJvY2Vzc2luZyB0aW1lIGF0IEdob3N0S29hbGEgNDY6MzAgKGhyOm1pbikKICAtICIqKkROQV9kYXRhX2Jibm9ybV9hbnZpb19nZW5lX2NhbGxzXzMuZmFhKioiICgyNDAuNyBNQikKICAgIC0gVXBsb2FkIHRpbWUgdG8gR2hvc3RLb2FsYSAwOjE0IChocjptaW4pIC0tIFByb2Nlc3NpbmcgdGltZSBhdCBHaG9zdEtvYWxhIDMzOjMzIChocjptaW4pCi0gUmVzdWx0IGZpbGVzIHdlcmUgYXMgZm9sbG93czoKICAtICIqKnVzZXJfa28udHh0KioiIEZ1bmN0aW9uYWwgYW5ub3RhdGlvbnMgZmlsZQogIC0gIioqdXNlci5vdXQudG9wKioiIFRheG9ub21pYyBhbm5vdGF0aW9ucyBmaWxlCgo8Zm9udCBjb2xvcj0iYmx1ZSI+KioyLjUuMyoqPC9mb250PiBJbXBvcnQgRnVuY3Rpb25hbCAmIFRheG9ub21pYyBBbm5vdGF0aW9ucyBpbnRvIHRoZSBDb250aWdzIERhdGFiYXNlCgotIEFkZCB0aGUgY29uY2F0ZW5hdGVkIGFubm90YXRpb24gZmlsZXMgZnJvbSBHaG9zdEtvYWxhIHRvIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseSI8L2ZvbnQ+IGRpcmVjdG9yeQogIC0gIioqdXNlcl9rby50eHQqKiIKICAtICIqKnVzZXIub3V0LnRvcCoqIgotIENvcHkgdGhlIGZvbGxvd2luZyBmaWxlcyBpbnRvIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseSI8L2ZvbnQ+IGRpcmVjdG9yeQotIE5vIGNoYW5nZXMgd2VyZSBuZWVkZWQgdG8gYmUgbWFkZSB0byB0aGUgaW50ZXJuYWwgcHl0aG9uIHNjcmlwdHMgLS0gVGhleSB3ZXJlIHJ1biBhcyB3cml0dGVuCiAgLSAiKipLRUdHLXRvLWFudmlvKioiCiAgLSAiKipLT19PcnRob2xvZ3lfa28wMDAwMS50eHQqKiIKICAtICIqKkdob3N0S09BTEEtdGF4b25vbXktdG8tYW52aW8qKiIKCjxmb250IGNvbG9yPSJibHVlIj4qKioyLjUuMy4xKioqPC9mb250PiBQYXJzZSB0aGUgZnVuY3Rpb25hbCBhbm5vdGF0aW9ucyBpbnRvIGEgZm9ybWF0IHJlYWRhYmxlIGJ5IEFudmknbwoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkKcHl0aG9uMiBLRUdHLXRvLWFudmlvIC0tS2VnZ0RCIEtPX09ydGhvbG9neV9rbzAwMDAxLnR4dCAtaSB1c2VyX2tvLnR4dCAtbyBLZWdnQW5ub3RhdGlvbnMudHh0CmBgYGAKCjxmb250IGNvbG9yPSJibHVlIj4qKioyLjUuMy4yKioqPC9mb250PiBJbXBvcnQgdGhlIGZ1bmN0aW9uYWwgYW5ub3RhdGlvbnMgaW50byB0aGUgY29udGlncyBkYXRhYmFzZToKCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9CmNkIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5CmFudmktaW1wb3J0LWZ1bmN0aW9ucyAtYyBETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtaSBLZWdnQW5ub3RhdGlvbnMudHh0CgojT3V0cHV0CkdlbmUgZnVuY3Rpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IDEzODk1MTggZnVuY3Rpb24gY2FsbHMgZnJvbSAxIHNvdXJjZXMgZm9yIDEzODk1MTggdW5pcXVlIGdlbmUgY2FsbHMgaGFzIGJlZW4gYWRkZWQgdG8gdGhlIGNvbnRpZ3MgZGF0YWJhc2UuCmBgYGAKCjxmb250IGNvbG9yPSJibHVlIj4qKioyLjUuMy4zKioqPC9mb250PiBQYXJzZSB0aGUgdGF4b25vbXkgYW5ub3RhdGlvbnMgaW50byBhIGZvcm1hdCByZWFkYWJsZSBieSBBbnZpJ28KCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9CmNkIC9ETkFfc3Vic2V0L3dvcmsvY29fYXNzZW1ibHkKcHl0aG9uIEdob3N0S09BTEEtdGF4b25vbXktdG8tYW52aW8gdXNlci5vdXQudG9wIEtlZ2dUYXhvbm9teS50eHQKYGBgYAoKPGZvbnQgY29sb3I9ImJsdWUiPioqKjIuNS4zLjQqKio8L2ZvbnQ+IEltcG9ydCB0aGUgdGF4b25vbWljIGFubm90YXRpb25zIGludG8gdGhlIGNvbnRpZ3MgZGF0YWJhc2UKCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9CmNkIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5CmFudmktaW1wb3J0LXRheG9ub215LWZvci1nZW5lcyAtYyBETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtcCBkZWZhdWx0X21hdHJpeCAtaSBLZWdnVGF4b25vbXkudHh0CgojT3V0cHV0ClRvdGFsIG51bSBoaXRzIGZvdW5kIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IDMsOTA4LDgyOApOdW0gZ2VuZSBjYWxsZXIgaWRzIGluIHRoZSBkYiAuLi4uLi4uLi4uLi4uLi4uOiAzLDkxNyw2MTYgICAgICAgICAgICAgICAgICAgICAgIApOdW0gZ2VuZSBjYWxsZXIgaWRzIGluIHRoZSBpbmNvbWluZyBkYXRhIC4uLi4uOiAzLDkwOCw4MjgKVGF4b24gbmFtZXMgdGFibGUgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogVXBkYXRlZCB3aXRoIDE2NzIgdW5pcXVlIHRheG9uIG5hbWVzCkdlbmVzIHRheG9ub215IHRhYmxlIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IFRheG9ub215IHN0b3JlZCBmb3IgMzkwODgyOCBnZW5lIGNhbGxzClNwbGl0cyB0YXhvbm9teSAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IElucHV0IGRhdGEgZnJvbSAiZGVmYXVsdF9tYXRyaXgiIGFubm90YXRlZCAyNDU4OTAwIG9mIDI0OTI0NDUgc3BsaXRzICg5OC43JSkgd2l0aCB0YXhvbm9teS4KYGBgYAoKPGZvbnQgY29sb3I9ImJsdWUiPioqMi41LjQqKjwvZm9udD4gSW1wb3J0IFNhbXBsZSBNYXBwaW5nIEluZm9ybWF0aW9uIGludG8gYW4gQW52aSdvIFByb2ZpbGUKCi0gSW1wb3J0IHRoZSBtYXBwaW5nIGluZm9ybWF0aW9uIGZyb20gdGhlICIqKlNhbXBsZV9cKi5maW5hbC5jb250aWdzLmZpeGVkLnNvcnRlZC5iYW0qKiIgaW50byBhbiBBbnZpJ28gcHJvZmlsZQotIFRoZSBgQkFNYCBmaWxlcyBhcmUgYWxyZWFkeSBzb3J0ZWQgYW5kIGluZGV4ZWQgKCppLmUuLCBmb3IgZWFjaCAiLmJhbSIgZmlsZSB0aGVyZSBpcyBhbHNvIGEgIioqLmJhbS5iYWkqKiIgZmlsZSBpbiB0aGUgc2FtZSBkaXJlY3RvcnkqKSAtLSBTa2lwIHRoZSBpbml0aWFsaXppbmcgc3RlcCBhbmQgY3JlYXRlIGFuIEFudmnigJlvIHByb2ZpbGUgZm9yIHRoZSBzYW1wbGVzCgo8Zm9udCBjb2xvcj0iYmx1ZSI+KioqMi41LjQuMSoqKjwvZm9udD4gTW92ZSB0aGUgZm9sbG93aW5nIGZpbGVzIHRvIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvRE5BX2RhdGEvd29yay9tYXBwaW5nIjwvZm9udD4gZGlyZWN0b3J5CiAgCiAgLSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvRE5BX2RhdGEvd29yay9tYXBwaW5nLypfbWFwcGVkX3JlYWRzLyI8L2ZvbnQ+CiAgICAtICIqKlNhbXBsZV9cKi5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtKioiIAogICAgLSAiKipTYW1wbGVfXCouZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uc29ydGVkLmJhbS5iYWkqKiIKICAtIFJlcGVhdCBmb3IgYWxsIHNhbXBsZXMKCjxmb250IGNvbG9yPSJibHVlIj4qKioyLjUuNC4yKioqPC9mb250PiBJbXBvcnQgdGhlIG1hcHBpbmcgaW5mb3JtYXRpb24gKHBlciBTYW1wbGUpIGludG8gc2VwYXJhdGUgKHBlciBTYW1wbGUpIEFudmknbyBwcm9maWxlcwoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvbWFwcGluZwphbnZpLXByb2ZpbGUgLWkgU2FtcGxlXzEwNzEwNC5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtIC1jIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiIC1vIGFudmlvXzEwNzEwNF9wcm9maWxlLyAtLXNhbXBsZS1uYW1lIFByb2ZpbGVfMTA3MTA0IC0tbWluLWNvbnRpZy1sZW5ndGggMjUwMCAtLW51bS10aHJlYWRzIDIwCmFudmktcHJvZmlsZSAtaSBTYW1wbGVfMTA3MTA1LmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLnNvcnRlZC5iYW0gLWMgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLW8gYW52aW9fMTA3MTA1X3Byb2ZpbGUvIC0tc2FtcGxlLW5hbWUgUHJvZmlsZV8xMDcxMDUgLS1taW4tY29udGlnLWxlbmd0aCAyNTAwIC0tbnVtLXRocmVhZHMgMjAKYW52aS1wcm9maWxlIC1pIFNhbXBsZV8xMDcxMDYuZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uc29ydGVkLmJhbSAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtbyBhbnZpb18xMDcxMDZfcHJvZmlsZS8gLS1zYW1wbGUtbmFtZSBQcm9maWxlXzEwNzEwNiAtLW1pbi1jb250aWctbGVuZ3RoIDI1MDAgLS1udW0tdGhyZWFkcyAyMAphbnZpLXByb2ZpbGUgLWkgU2FtcGxlXzEwNzEwNy5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtIC1jIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiIC1vIGFudmlvXzEwNzEwN19wcm9maWxlLyAtLXNhbXBsZS1uYW1lIFByb2ZpbGVfMTA3MTA3IC0tbWluLWNvbnRpZy1sZW5ndGggMjUwMCAtLW51bS10aHJlYWRzIDIwCmFudmktcHJvZmlsZSAtaSBTYW1wbGVfMTA3MTA4LmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLnNvcnRlZC5iYW0gLWMgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLW8gYW52aW9fMTA3MTA4X3Byb2ZpbGUvIC0tc2FtcGxlLW5hbWUgUHJvZmlsZV8xMDcxMDggLS1taW4tY29udGlnLWxlbmd0aCAyNTAwIC0tbnVtLXRocmVhZHMgMjAKYW52aS1wcm9maWxlIC1pIFNhbXBsZV8xMDcxMTAuZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uc29ydGVkLmJhbSAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtbyBhbnZpb18xMDcxMTBfcHJvZmlsZS8gLS1zYW1wbGUtbmFtZSBQcm9maWxlXzEwNzExMCAtLW1pbi1jb250aWctbGVuZ3RoIDI1MDAgLS1udW0tdGhyZWFkcyAyMAphbnZpLXByb2ZpbGUgLWkgU2FtcGxlXzEwNzExMS5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtIC1jIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiIC1vIGFudmlvXzEwNzExMV9wcm9maWxlLyAtLXNhbXBsZS1uYW1lIFByb2ZpbGVfMTA3MTExIC0tbWluLWNvbnRpZy1sZW5ndGggMjUwMCAtLW51bS10aHJlYWRzIDIwCmFudmktcHJvZmlsZSAtaSBTYW1wbGVfMTA3MTEyLmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLnNvcnRlZC5iYW0gLWMgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLW8gYW52aW9fMTA3MTEyX3Byb2ZpbGUvIC0tc2FtcGxlLW5hbWUgUHJvZmlsZV8xMDcxMTIgLS1taW4tY29udGlnLWxlbmd0aCAyNTAwIC0tbnVtLXRocmVhZHMgMjAKYW52aS1wcm9maWxlIC1pIFNhbXBsZV8xMDcxMTMuZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uc29ydGVkLmJhbSAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtbyBhbnZpb18xMDcxMTNfcHJvZmlsZS8gLS1zYW1wbGUtbmFtZSBQcm9maWxlXzEwNzExMyAtLW1pbi1jb250aWctbGVuZ3RoIDI1MDAgLS1udW0tdGhyZWFkcyAyMAphbnZpLXByb2ZpbGUgLWkgU2FtcGxlXzEwNzExNC5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtIC1jIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiIC1vIGFudmlvXzEwNzExNF9wcm9maWxlLyAtLXNhbXBsZS1uYW1lIFByb2ZpbGVfMTA3MTE0IC0tbWluLWNvbnRpZy1sZW5ndGggMjUwMCAtLW51bS10aHJlYWRzIDIwCmFudmktcHJvZmlsZSAtaSBTYW1wbGVfMTA3MTE1LmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLnNvcnRlZC5iYW0gLWMgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLW8gYW52aW9fMTA3MTE1X3Byb2ZpbGUvIC0tc2FtcGxlLW5hbWUgUHJvZmlsZV8xMDcxMTUgLS1taW4tY29udGlnLWxlbmd0aCAyNTAwIC0tbnVtLXRocmVhZHMgMjAKYW52aS1wcm9maWxlIC1pIFNhbXBsZV8xMDcxMTYuZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uc29ydGVkLmJhbSAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtbyBhbnZpb18xMDcxMTZfcHJvZmlsZS8gLS1zYW1wbGUtbmFtZSBQcm9maWxlXzEwNzExNiAtLW1pbi1jb250aWctbGVuZ3RoIDI1MDAgLS1udW0tdGhyZWFkcyAyMAphbnZpLXByb2ZpbGUgLWkgU2FtcGxlXzEwNzExNy5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtIC1jIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiIC1vIGFudmlvXzEwNzExN19wcm9maWxlLyAtLXNhbXBsZS1uYW1lIFByb2ZpbGVfMTA3MTE3IC0tbWluLWNvbnRpZy1sZW5ndGggMjUwMCAtLW51bS10aHJlYWRzIDIwCmFudmktcHJvZmlsZSAtaSBTYW1wbGVfMTA3MTE5LmZpbmFsLmNvbnRpZ3MuZml4ZWQuYmJub3JtLnNvcnRlZC5iYW0gLWMgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLW8gYW52aW9fMTA3MTE5X3Byb2ZpbGUvIC0tc2FtcGxlLW5hbWUgUHJvZmlsZV8xMDcxMTkgLS1taW4tY29udGlnLWxlbmd0aCAyNTAwIC0tbnVtLXRocmVhZHMgMjAKYW52aS1wcm9maWxlIC1pIFNhbXBsZV8xMDcxMjEuZmluYWwuY29udGlncy5maXhlZC5iYm5vcm0uc29ydGVkLmJhbSAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtbyBhbnZpb18xMDcxMjFfcHJvZmlsZS8gLS1zYW1wbGUtbmFtZSBQcm9maWxlXzEwNzEyMSAtLW1pbi1jb250aWctbGVuZ3RoIDI1MDAgLS1udW0tdGhyZWFkcyAyMApgYGBgCioqRE5BLmRhdGEuYmJub3JtLmFudmlvLm1hcHBpbmcucHJvZmlsZS5wYnMqKiA8Zm9udCBjb2xvcj0iZ3JlZW4iPigiL0ROQV9kYXRhL3dvcmsvIik8L2ZvbnQ+IDA1OjE2OjUxIChkYXk6aHI6bWluKQoKPGZvbnQgY29sb3I9ImJsdWUiPioqKjIuNS40LjMqKio8L2ZvbnQ+IE1lcmdlIHRoZSBTYW1wbGUgcHJvZmlsZXMgaW50byBhIHNpbmdsZSBBbnZpJ28gcHJvZmlsZSBkYXRhYmFzZQoKLSBSZW5hbWUgdGhlICIqKlBST0ZJTEUuZGIqKiIgd2l0aGluIGVhY2ggPGZvbnQgY29sb3I9ImdyZWVuIj4iYW52aW9fXCpfcHJvZmlsZSI8L2ZvbnQ+IGRpcmVjdG9yeSB0byBpbmNsdWRlIHRoZSBTYW1wbGVJRAogIC0gPGZvbnQgY29sb3I9ImdyZWVuIj4iL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9hbnZpb18xMDcxMDRfcHJvZmlsZS8iPC9mb250PgogICAgLSAiKipQUk9GSUxFXzEwNzEwNC5kYioqIgogIC0gPGZvbnQgY29sb3I9ImdyZWVuIj4iL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9hbnZpb18xMDcxMDVfcHJvZmlsZS8iPC9mb250PgogICAgLSAiKipQUk9GSUxFXzEwNzEwNS5kYioqIgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvbWFwcGluZwphbnZpLW1lcmdlIGFudmlvXzEwNzEwNF9wcm9maWxlL1BST0ZJTEVfMTA3MTA0LmRiIGFudmlvXzEwNzEwNV9wcm9maWxlL1BST0ZJTEVfMTA3MTA1LmRiIGFudmlvXzEwNzEwNl9wcm9maWxlL1BST0ZJTEVfMTA3MTA2LmRiIGFudmlvXzEwNzEwN19wcm9maWxlL1BST0ZJTEVfMTA3MTA3LmRiIGFudmlvXzEwNzEwOF9wcm9maWxlL1BST0ZJTEVfMTA3MTA4LmRiIGFudmlvXzEwNzExMF9wcm9maWxlL1BST0ZJTEVfMTA3MTEwLmRiIGFudmlvXzEwNzExMV9wcm9maWxlL1BST0ZJTEVfMTA3MTExLmRiIGFudmlvXzEwNzExMl9wcm9maWxlL1BST0ZJTEVfMTA3MTEyLmRiIGFudmlvXzEwNzExM19wcm9maWxlL1BST0ZJTEVfMTA3MTEzLmRiIGFudmlvXzEwNzExNF9wcm9maWxlL1BST0ZJTEVfMTA3MTE0LmRiIGFudmlvXzEwNzExNV9wcm9maWxlL1BST0ZJTEVfMTA3MTE1LmRiIGFudmlvXzEwNzExNl9wcm9maWxlL1BST0ZJTEVfMTA3MTE2LmRiIGFudmlvXzEwNzExN19wcm9maWxlL1BST0ZJTEVfMTA3MTE3LmRiIGFudmlvXzEwNzExOV9wcm9maWxlL1BST0ZJTEVfMTA3MTE5LmRiIGFudmlvXzEwNzEyMV9wcm9maWxlL1BST0ZJTEVfMTA3MTIxLmRiIC1jIC9ETkFfZGF0YS93b3JrL2NvX2Fzc2VtYmx5L0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiIC1vIG1lcmdlZF9wcm9maWxlLwpgYGBgCioqRE5BLmRhdGEuYmJub3JtLmFudmlvLm1hcHBpbmcucHJvZmlsZS5tZXJnZS5wYnMqKiA8Zm9udCBjb2xvcj0iZ3JlZW4iPigiL0ROQV9kYXRhL3dvcmsvIik8L2ZvbnQ+IDAxOjQ1IChocjptaW4pCgoqKipOT1RFOioqKiAqQWZ0ZXIgdGhlIHByb2ZpbGVzIHdlcmUgbWVyZ2VkLCBBbnZpJ28gYXV0b21hdGljYWxseSBzdGFydGVkIGJpbm5pbmcgdGhlIGNvbnRpZ3MgdXNpbmcgQ09OQ09DVC4gIEl0IGFsc28gYXR0ZW1wdGVkIHRvIGNsdXN0ZXIgdGhlIGNvbnRpZ3MgdXNpbmcgaXRzIG93biBoaWVyYXJjaGljYWwgY2x1c3RlcmluZyBhbGdvcml0aG0sIGJ1dCBpdCBkaWQgTk9UIGdlbmVyYXRlIGJpbnMgZnJvbSB0aGlzIGNsdXN0ZXJpbmcgaW5mb3JtYXRpb247IHRoZXkgd2VyZSBtYW51YWxseSBkcmF3biBsYXRlci4gVGhlIGNsdXN0ZXJpbmcgYWxnb3JpdGhtIHdhcyBsaW1pdGVkIHRvIGRhdGFzZXRzIHdpdGggMjAsMDAwIHNwbGl0cyBvciBmZXdlciAod2hpY2ggZGlzcXVhbGlmaWVzIG1vc3QgY29tcGxleCBhc3NlbWJsaWVzKS4qCgotIFJlc3VsdHMgd2VyZSBpbiBhIG5ldyBkaXJlY3RvcnkgKDxmb250IGNvbG9yPSJncmVlbiI+IkROQV9kYXRhL3dvcmsvbWFwcGluZy9tZXJnZWRfcHJvZmlsZSI8L2ZvbnQ+KSB3aXRoIHRoZSBmb2xsb3dpbmcgZmlsZXM6CiAgLSAiKipBVVhJTElBUlktREFUQS5kYioqIgogIC0gIioqUFJPRklMRS5kYioqIiAqVGhpcyBpcyB0aGUgbWVyZ2VkIHByb2ZpbGUgZGF0YWJhc2UqCiAgLSAiKipSVU5MT0cudHh0KioiCgojIyMgMi42LiBCaW5uaW5nIE1BR3MKCioqKkJpbm5pbmcgVXNpbmcgTXVsdGlwbGUgQmlubmluZyBTb2Z0d2FyZSBBbGdvcml0aG1zIChTbWl0aDogQ09OQ09DVCwgTWV0YUJBVCwgREFTVG9vbCkqKioKClRoZSBuZXh0IHN0ZXAgaXMgdG8gZXhwb3J0IHRoZSBzcGxpdCBzZXF1ZW5jZXMgYW5kIHRoZWlyIGRpZmZlcmVudGlhbCBjb3ZlcmFnZSBhY3Jvc3MgYWxsIHNhbXBsZXMgZnJvbSB0aGUgbWVyZ2VkIHByb2ZpbGUgYW5kIHVzZSB0aGVzZSBzcGxpdHMgaW4gYSBzZXJpZXMgb2YgYmlubmluZyBhbGdvcml0aG1zIGV4dGVybmFsIHRvIEFudmknby4KCi0gVGhlIGJlbmVmaXQgdG8gZG9pbmcgdGhpcyBpcyB0aGF0IHNvbWUgYWxnb3JpdGhtIHN0cmF0ZWdpZXMgd29yayBiZXR0ZXIgZm9yIGNlcnRhaW4gb3JnYW5pc21zIG92ZXIgb3RoZXJzIGFuZCB0aGVyZSBkb2VzICoqTk9UKiogYXBwZWFyIHRvIGJlIGEgcGVyZmVjdCBzdHJhdGVneSB0aGF0IHdvcmtzICpiZXN0KiBmb3IgZXZlcnkgb3JnYW5pc20KLSBNZXRhQkFUIGluc3RydWN0aW9ucyBhcmUgbmNsdWRlZCBoZXJlIGFuZCBzdXBwbGVtZW50IHRoZSBiaW5zIGRlcml2ZWQgZnJvbSBDT05DT0NUIHRocm91Z2ggQW52aSdvCi0gREFTVG9vbCBpcyB0aGVuIHVzZWQgdG8gY2hvc2UgdGhlIGJlc3Qgc2V0IG9mIG5vbi1yZWR1bmRhbnQgYmlucyBmcm9tIHRoZSBtdWx0aXBsZSBiaW5uaW5nIGFsZ29yaXRobXMKCjxmb250IGNvbG9yPSJibHVlIj4qKjIuNi4xKio8L2ZvbnQ+IEV4cG9ydCBTcGxpdCBTZXF1ZW5jZXMgYW5kIERpZmZlcmVudGlhbCBDb3ZlcmFnZSBEYXRhIGZvciBCaW5uaW5nCgotIFVzZSBBbnZpJ28gdG8gZXhwb3J0IHRoZSBzcGxpdCBzZXF1ZW5jZXMgYW5kIGRpZmZlcmVudGlhbCBjb3ZlcmFnZSBkYXRhIG5lY2Vzc2FyeSBmb3IgZXh0ZXJuYWwgYmlubmVycwoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvbWFwcGluZwphbnZpLWV4cG9ydC1zcGxpdHMtYW5kLWNvdmVyYWdlcyAtcCBtZXJnZWRfcHJvZmlsZS9QUk9GSUxFLmRiIC1vIG1lcmdlZF9wcm9maWxlLyAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtTyBETkFfZGF0YV9iYm5vcm1fYXNzZW1ibHkgLS1zcGxpdHMtbW9kZQpgYGBgCjAwOjA1IChocjptaW4pCgotIFRoZSBmb2xsb3dpbmcgdHdvIGZpbGVzIHdpbGwgYmUgZ2VuZXJhdGVkIGluIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiJETkFfZGF0YS93b3JrL21hcHBpbmcvbWVyZ2VkX3Byb2ZpbGUiPC9mb250PiBkaXJlY3Rvcnk6CiAgLSAiKipETkFfZGF0YV9iYm5vcm1fYXNzZW1ibHktU1BMSVRTLmZhKioiICpDb250YWlucyB0aGUgc3BsaXQgc2VxdWVuY2VzKgogIC0gIioqRE5BX2RhdGFfYmJub3JtX2Fzc2VtYmx5LUNPVnMudHh0KioiICpUYWItZGVsaW1pdGVkIGZpbGUgY29udGFpbmluZyB0aGUgYXZlcmFnZSBjb3ZlcmFnZSBvZiBlYWNoIHNwbGl0IGluIGVhY2ggc2FtcGxlKgoKPGZvbnQgY29sb3I9ImJsdWUiPioqMi42LjIqKjwvZm9udD4gQmlubmluZyBTcGxpdHMgd2l0aCBNZXRhQkFUCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlCmNvbWljcyAtLSBtZXRhYmF0IC1pIEROQV9kYXRhX2Jibm9ybV9hc3NlbWJseS1TUExJVFMuZmEgLW8gQmluIC1hIEROQV9kYXRhX2Jibm9ybV9hc3NlbWJseS1DT1ZzLnR4dCAtLW1pbkNvbnRpZyAyNTAwIC0tY3ZFeHQgLXQgMjAgLS1zYXZlQ2xzIC0tb25seUxhYmVsIC12CmBgYGAKMDA6MjIgKGhyOm1pbikKCi0gVGhlIG91dHB1dCBvZiBNZXRhQkFUIHdpbGwgYmUgYSAiQmluLlwqIiBmaWxlIGZvciBlYWNoIGJpbiB0aGF0IGNvbnRhaW5zIGEgbGlzdCBvZiB0aGUgc3BsaXRzIGFzc2lnbmVkIHRvIHRoYXQgYmluCiAgLSAqKk5PKiogYmluIGZhc3RhIGZpbGVzIGFyZSBnZW5lcmF0ZWQgLS0gYWxsIHNwbGl0cyBhcmUgYWxyZWFkeSBzYXZlZCBpbiB0aGUgQW52aSdvIGNvbnRpZ3MgZGF0YWJhc2UKCi0gQ3JlYXRlIGEgbmV3IGRpcmVjdG9yeSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiJETkFfZGF0YS93b3JrL2Jpbm5pbmciPC9mb250PiBhbmQgd2l0aGluIGNyZWF0ZSBhIE1ldGFCQVQgZGlyZWN0b3J5IDxmb250IGNvbG9yPSJncmVlbiI+IkROQV9kYXRhL3dvcmsvYmlubmluZy9tZXRhYmF0IjwvZm9udD4KLSBNb3ZlIGFsbCAiQmluLlwqIiBmaWxlcyBmcm9tIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiJETkFfZGF0YS93b3JrL21hcHBpbmcvbWVyZ2VkX3Byb2ZpbGUiPC9mb250PiBkaXJlY3RvcnkgdG8gdGhlIDxmb250IGNvbG9yPSJncmVlbiI+IkROQV9kYXRhL3dvcmsvYmlubmluZy9tZXRhYmF0IjwvZm9udD4gZGlyZWN0b3J5Cgo8Zm9udCBjb2xvcj0iYmx1ZSI+KioqMi42LjIuMSoqKjwvZm9udD4gTm93IG1ha2UgdGhlICoqIk1ldGFiYXRfYmlubmluZ19yZXN1bHRzLnR4dCIqKiBmaWxlIGZyb20gdGhlIE1ldGFCQVQgb3V0cHV0IHRvIHNhdmUgaXQgYXMgYSBjb2xsZWN0aW9uIGluIEFudmknbwoKLSBJbnZva2luZyB0aGUgZm9sbG93aW5nIHNoZWxsIHNjcmlwdCBpbiB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIE1ldGFCQVQgb3V0cHV0OgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvYmlubmluZy9tZXRhYmF0CnNoIC9ETkFfZGF0YS93b3JrL01ldGFiYXRfdG9fYW52aW9fcGFyc2VyLnNoCmBgYGAKMDA6MDEgKGhyOm1pbikKCi0gVGhlIG91dHB1dCB3aWxsIGJlIGEgdGFiLWRlbGltaXRlZCB0ZXh0IGZpbGUgbmFtZWQgIioqTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHMudHh0KioiIGNvbnRhaW5pbmcgdGhlIHNwbGl0IG5hbWVzIGFuZCB0aGUgYmlucyB0aGV5IGhhdmUgYmVlbiBhc3NpZ25lZCB0bwoKPGZvbnQgY29sb3I9ImJsdWUiPioqKjIuNi4yLjIqKio8L2ZvbnQ+IE5leHQsIGltcG9ydCB0aGlzIGluZm9ybWF0aW9uIGludG8gQW52aSdvLCBzYXZpbmcgaXQgYXMgdGhlIE1ldGFCQVQgYmluIGNvbGxlY3Rpb246CgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9iaW5uaW5nL21ldGFiYXQKYW52aS1pbXBvcnQtY29sbGVjdGlvbiAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtcCAvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlL1BST0ZJTEUuZGIgLUMgTUVUQUJBVCBNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0cy50eHQKCiNPdXRwdXQKSXRlbSBuYW1lcyBpbiBpbnB1dCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogMTEyLDk1NwpOdW0gYmlucyBpbiBpbnB1dCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uOiAxNjUKSXRlbXMgaW4gcHJvZmlsZSBkYXRhYmFzZSAuLi4uLi4uLi4uLi4uLi4uLi4uLjogMTMxLDA3NApJdGVtIG5hbWVzIHNoYXJlZCBiZXR3ZWVuIGlucHV0IGFuZCBkYiAuLi4uLi4uOiAxMTIsOTU3CgpXQVJOSU5HCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CjE4MTE3IGl0ZW0ocykgdGhhdCB3ZXJlIGluIHRoZSBkYXRhYmFzZSwgYnV0IHdlcmUgbm90IGluIHRoZSBpbnB1dCBmaWxlLCB3aWxsCm5vdCBiZSBkZXNjcmliZWQgYnkgYW55IGJpbiBpbiB0aGUgY29sbGVjdGlvbiBNRVRBQkFULiBUaGF0IGlzIHRvdGFsbHkgZmluZSwgYnV0CmFudmknbyBob3BlcyB0aGF0IHlvdSBhcmUgYXdhcmUgb2YgdGhhdC4gVGhpcyBtZWFucyB5b3UgaGF2ZSBtb3JlIHRoaW5ncyBpbiB5b3VyCmRhdGFiYXNlIHRoYW4gdGhlIG51bWJlciBvZiB0aGluZ3MgeW91ciBpbnB1dCBmaWxlIGRlc2NyaWJlcy4gSGVyZSBpcyBhbiBleGFtcGxlCm9mIHNvbWV0aGluZyB0aGF0IGlzIGluIHlvdXIgZGF0YWJhc2UgYnV0IG5vdCBpbiBhbnkgYmluIGluIHlvdXIgaW5wdXQgZmlsZToKazI1NV82OTE5MzVfZmxhZ18xX211bHRpXzEzLjAwMDBfbGVuXzI2NDNfc3BsaXRfMDAwMDEuCgpDb2xsZWN0aW9ucyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uOiBUaGUgY29sbGVjdGlvbiAiTUVUQUJBVCIgdGhhdCBkZXNjcmliZXMgMTEyLDk1NyBzcGxpdHMgYW5kIDE2NSBiaW5zIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBhZGRlZCB0byB0aGUgZGF0YWJhc2UgYXQgIi9ETkFfZGF0YS93b3JrL21hcHBpbmcvbWVyZ2VkX3Byb2ZpbGUvUFJPRklMRS5kYiIuIEhlcmUgaXMgYSBsaXN0IG9mIHRoZSBmaXJzdCA1MCBiaW4gbmFtZXMgaW4gdGhpcyBjb2xsZWN0aW9uOiBCaW5fMSxCaW5fMTAsQmluXzEwMCxCaW5fMTAxLEJpbl8xMDIsQmluXzEwMyxCaW5fMTA0LEJpbl8xMDUsQmluXzEwNixCaW5fMTA3LEJpbl8xMDgsQmluXzEwOSxCaW5fMTEsQmluXzExMCxCaW5fMTExLEJpbl8xMTIsQmluXzExMyxCaW5fMTE0LEJpbl8xMTUsQmluXzExNixCaW5fMTE3LEJpbl8xMTgsQmluXzExOSxCaW5fMTIsQmluXzEyMCxCaW5fMTIxLEJpbl8xMjIsQmluXzEyMyxCaW5fMTI0LEJpbl8xMjUsQmluXzEyNixCaW5fMTI3LEJpbl8xMjgsQmluXzEyOSxCaW5fMTMsQmluXzEzMCxCaW5fMTMxLEJpbl8xMzIsQmluXzEzMyxCaW5fMTM0LEJpbl8xMzUsQmluXzEzNixCaW5fMTM3LEJpbl8xMzgsQmluXzEzOSxCaW5fMTQsQmluXzE0MCxCaW5fMTQxLEJpbl8xNDIsQmluXzE0MwpgYGBgCjAwOjAxIChocjptaW4pCgotIE5vdyB0aGVyZSBhcmUgdHdvIGJpbiBjb2xsZWN0aW9ucyBzYXZlZCBpbiBvbmUgcHJvZmlsZSBkYXRhYmFzZSwgcHJldmVudGluZyByZWR1bmRhbnQgY29weWluZyBvZiBzZXF1ZW5jZSBkYXRhIGFuZCBzdG9yaW5nIGV2ZXJ5dGhpbmcgaW4gb25lIGNlbnRyYWwgbG9jYXRpb24gdGhhdCBpcyBlYXNpbHkgYWNjZXNzZWQKCjxmb250IGNvbG9yPSJibHVlIj4qKjIuNi4zKio8L2ZvbnQ+IEVudGVyIHRoaXMgY29tbWFuZCB0byB2aWV3IHRoZSBkaWZmZXJlbnQgY29sbGVjdGlvbnMgaW4gdGhlIHByb2ZpbGUgZGF0YWJhc2U6CgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlCmFudmktc2hvdy1jb2xsZWN0aW9ucy1hbmQtYmlucyAtcCBQUk9GSUxFLmRiCgojT3V0cHV0CkNvbGxlY3Rpb246ICJDT05DT0NUIgo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpDb2xsZWN0aW9uIElEIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uOiBDT05DT0NUCk51bWJlciBvZiBiaW5zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IDc0Ck51bWJlciBvZiBzcGxpdHMgZGVzY3JpYmVkIC4uLi4uLi4uLi4uLi4uLi4uLi46IDEzMSwwNzQKQmluIG5hbWVzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogQmluXzEsIEJpbl8xMCwgQmluXzExLCBCaW5fMTIsIEJpbl8xMywgQmluXzE0LCBCaW5fMTUsIEJpbl8xNiwgQmluXzE3LCBCaW5fMTgsIEJpbl8xOSwgQmluXzIsIEJpbl8yMCwgQmluXzIxLCBCaW5fMjIsIEJpbl8yMywgQmluXzI0LCBCaW5fMjUsIEJpbl8yNiwgQmluXzI3LCBCaW5fMjgsIEJpbl8yOSwgQmluXzMsIEJpbl8zMCwgQmluXzMxLCBCaW5fMzIsIEJpbl8zMywgQmluXzM0LCBCaW5fMzUsIEJpbl8zNiwgQmluXzM3LCBCaW5fMzgsIEJpbl8zOSwgQmluXzQsIEJpbl80MCwgQmluXzQxLCBCaW5fNDIsIEJpbl80MywgQmluXzQ0LCBCaW5fNDUsIEJpbl80NiwgQmluXzQ3LCBCaW5fNDgsIEJpbl80OSwgQmluXzUsIEJpbl81MCwgQmluXzUxLCBCaW5fNTIsIEJpbl81MywgQmluXzU0LCBCaW5fNTUsIEJpbl81NiwgQmluXzU3LCBCaW5fNTgsIEJpbl81OSwgQmluXzYsIEJpbl82MCwgQmluXzYxLCBCaW5fNjIsIEJpbl82MywgQmluXzY0LCBCaW5fNjUsIEJpbl82NiwgQmluXzY3LCBCaW5fNjgsIEJpbl82OSwgQmluXzcsIEJpbl83MCwgQmluXzcxLCBCaW5fNzIsIEJpbl83MywgQmluXzc0LCBCaW5fOCwgQmluXzkKCgoKQ29sbGVjdGlvbjogIk1FVEFCQVQiCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CkNvbGxlY3Rpb24gSUQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IE1FVEFCQVQKTnVtYmVyIG9mIGJpbnMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogMTY1Ck51bWJlciBvZiBzcGxpdHMgZGVzY3JpYmVkIC4uLi4uLi4uLi4uLi4uLi4uLi46IDExMiw5NTcKQmluIG5hbWVzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogQmluXzEsIEJpbl8xMCwgQmluXzEwMCwgQmluXzEwMSwgQmluXzEwMiwgQmluXzEwMywgQmluXzEwNCwgQmluXzEwNSwgQmluXzEwNiwgQmluXzEwNywgQmluXzEwOCwgQmluXzEwOSwgQmluXzExLCBCaW5fMTEwLCBCaW5fMTExLCBCaW5fMTEyLCBCaW5fMTEzLCBCaW5fMTE0LCBCaW5fMTE1LCBCaW5fMTE2LCBCaW5fMTE3LCBCaW5fMTE4LCBCaW5fMTE5LCBCaW5fMTIsIEJpbl8xMjAsIEJpbl8xMjEsIEJpbl8xMjIsIEJpbl8xMjMsIEJpbl8xMjQsIEJpbl8xMjUsIEJpbl8xMjYsIEJpbl8xMjcsIEJpbl8xMjgsIEJpbl8xMjksIEJpbl8xMywgQmluXzEzMCwgQmluXzEzMSwgQmluXzEzMiwgQmluXzEzMywgQmluXzEzNCwgQmluXzEzNSwgQmluXzEzNiwgQmluXzEzNywgQmluXzEzOCwgQmluXzEzOSwgQmluXzE0LCBCaW5fMTQwLCBCaW5fMTQxLCBCaW5fMTQyLCBCaW5fMTQzLCBCaW5fMTQ0LCBCaW5fMTQ1LCBCaW5fMTQ2LCBCaW5fMTQ3LCBCaW5fMTQ4LCBCaW5fMTQ5LCBCaW5fMTUsIEJpbl8xNTAsIEJpbl8xNTEsIEJpbl8xNTIsIEJpbl8xNTMsIEJpbl8xNTQsIEJpbl8xNTUsIEJpbl8xNTYsIEJpbl8xNTcsIEJpbl8xNTgsIEJpbl8xNTksIEJpbl8xNiwgQmluXzE2MCwgQmluXzE2MSwgQmluXzE2MiwgQmluXzE2MywgQmluXzE2NCwgQmluXzE2NSwgQmluXzE3LCBCaW5fMTgsIEJpbl8xOSwgQmluXzIsIEJpbl8yMCwgQmluXzIxLCBCaW5fMjIsIEJpbl8yMywgQmluXzI0LCBCaW5fMjUsIEJpbl8yNiwgQmluXzI3LCBCaW5fMjgsIEJpbl8yOSwgQmluXzMsIEJpbl8zMCwgQmluXzMxLCBCaW5fMzIsIEJpbl8zMywgQmluXzM0LCBCaW5fMzUsIEJpbl8zNiwgQmluXzM3LCBCaW5fMzgsIEJpbl8zOSwgQmluXzQsIEJpbl80MCwgQmluXzQxLCBCaW5fNDIsIEJpbl80MywgQmluXzQ0LCBCaW5fNDUsIEJpbl80NiwgQmluXzQ3LCBCaW5fNDgsIEJpbl80OSwgQmluXzUsIEJpbl81MCwgQmluXzUxLCBCaW5fNTIsIEJpbl81MywgQmluXzU0LCBCaW5fNTUsIEJpbl81NiwgQmluXzU3LCBCaW5fNTgsIEJpbl81OSwgQmluXzYsIEJpbl82MCwgQmluXzYxLCBCaW5fNjIsIEJpbl82MywgQmluXzY0LCBCaW5fNjUsIEJpbl82NiwgQmluXzY3LCBCaW5fNjgsIEJpbl82OSwgQmluXzcsIEJpbl83MCwgQmluXzcxLCBCaW5fNzIsIEJpbl83MywgQmluXzc0LCBCaW5fNzUsIEJpbl83NiwgQmluXzc3LCBCaW5fNzgsIEJpbl83OSwgQmluXzgsIEJpbl84MCwgQmluXzgxLCBCaW5fODIsIEJpbl84MywgQmluXzg0LCBCaW5fODUsIEJpbl84NiwgQmluXzg3LCBCaW5fODgsIEJpbl84OSwgQmluXzksIEJpbl85MCwgQmluXzkxLCBCaW5fOTIsIEJpbl85MywgQmluXzk0LCBCaW5fOTUsIEJpbl85NiwgQmluXzk3LCBCaW5fOTgsIEJpbl85OQpgYGBgCgotIFNob3VsZCBzZWUgYSBsaXN0IG9mIGJpbnMgaW4gdHdvIGNvbGxlY3Rpb25zLCBvbmUgbmFtZWQg4oCcQ09OQ09DVOKAnSBhbmQgYW5vdGhlciBuYW1lZCDigJxNRVRBQkFU4oCdCgo8Zm9udCBjb2xvcj0iYmx1ZSI+KioyLjYuNCoqPC9mb250PiBEQVNUb29scwoKLSBEZWNpZGUgd2hpY2ggYmlucyBhcmUgdGhlIGJlc3QgZnJvbSB0aGUgdHdvIHJlZHVuZGFudCBiaW4gZGF0YXNldHMgKGdlbmVyYXRlZCB3aXRoIG11bHRpcGxlIGJpbm5pbmcgYWxnb3JpdGhtcykgYW5kIGRlcmVwbGljYXRlIHRoZSBiaW5zIGludG8gYSBmaW5hbCBiaW4gZGF0YXNldCB1c2luZyBEQVNUb29sCiAgLSBUaGUgaW5wdXQgZm9yIERBU3Rvb2wgYXJlIHRoZSBzYW1lIGJpbm5pbmcgcmVzdWx0cyBmaWxlcyB1c2VkIHRvIGltcG9ydCBiaW4gY29sbGVjdGlvbnMgaW50byB0aGUgQW52aSdvIHByb2ZpbGUgZGF0YWJhc2UKCi0gR2V0IHRoZSBiaW5uaW5nIHJlc3VsdHMgZmlsZSBmb3IgQ09OQ09DVCBieSBleHBvcnRpbmcgdGhlIGluZm9ybWF0aW9uIGZyb20gYW52aW86CgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9iaW5uaW5nL2NvbmNvY3QKYW52aS1leHBvcnQtY29sbGVjdGlvbiAtcCAvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlL1BST0ZJTEUuZGIgLUMgQ09OQ09DVCAtTyBDT05DT0NUX2Jpbm5pbmdfcmVzdWx0cwpgYGBgCgotIENyZWF0ZSBhIDxmb250IGNvbG9yPSJncmVlbiI+IkROQV9zdWJzZXQvd29yay9iaW5uaW5nL2Rhc3Rvb2wiPC9mb250PiBkaXJlY3RvcnkKLSBNb3ZlIHRoZSBDT05DT0NUIGFuZCBNZXRhQkFUIHN1bW1hcnkgdGV4dCBmaWxlcyBpbnRvIHRoZSA8Zm9udCBjb2xvcj0iZ3JlZW4iPiIvZGFzdG9vbCI8L2ZvbnQ+IGRpcmVjdG9yeQogIC0gIioqQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHMudHh0KioiCiAgLSAiKipNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0cy50eHQqKiIKCi0gTm93LCBpbnZva2UgREFTVG9vbAoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvYmlubmluZy9kYXN0b29sCmNvbWljcyBkYXMtdG9vbCAtaSBDT05DT0NUX2Jpbm5pbmdfcmVzdWx0cy50eHQsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHMudHh0IC1sIGNvbmNvY3QsbWV0YWJhdCAtYyAvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlL0ROQV9kYXRhX2Jibm9ybV9hc3NlbWJseS1TUExJVFMuZmEgLW8gREFTVG9vbF9iaW5zIC0tc2VhcmNoX2VuZ2luZSBibGFzdCAtLXRocmVhZHMgMjAKYGBgYAowMDoyMCAoaHI6bWluKQoKLSBUaGUgb3V0cHV0IG5lZWRlZCBpcyB0aGUgIioqREFTVG9vbF9iaW5zX0RBU1Rvb2xfc2NhZmZvbGRzMmJpbi50eHQqKiIgZmlsZSAoc2FtZSBmaWxlIHN0cnVjdHVyZSBhcyBwcmV2aW91cyAiXCpfYmlubmluZ19yZXN1bHRzLnR4dCIgZmlsZXMpCi0gSnVzdCBsaWtlIGJlZm9yZSwgdXNlIHRoZSBEQVNUb29sIGJpbm5pbmcgcmVzdWx0cyBmaWxlIHRvIGltcG9ydCB0aGUgREFTVG9vbCBiaW5zIGFzIGEgY29sbGVjdGlvbiBpbnRvIEFudmknbywgYnV0IGZpcnN0IGNoYW5nZSBzb21lIHBlcmlvZHMgdG8gdW5kZXNjb3JlcyBpbiBEQVNUb29sIGJpbiBuYW1lcyAoQW52aSdvIGRvZXNu4oCZdCBsaWtlIHBlcmlvZHMpOgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0Kc2VkICdzL3Jlc3VsdHNcLi9yZXN1bHRzXy9nJyBEQVNUb29sX2JpbnNfREFTVG9vbF9zY2FmZm9sZHMyYmluLnR4dCA+IERBU1Rvb2xfYmlubmluZ19yZXN1bHRzLnR4dApzZWQgJ3MvdXBkYXRlZFwuL3VwZGF0ZWRfL2cnIERBU1Rvb2xfYmlubmluZ19yZXN1bHRzLnR4dCA+IERBU1Rvb2xfYmlubmluZ19yZXN1bHRzMi50eHQKbXYgREFTVG9vbF9iaW5uaW5nX3Jlc3VsdHMyLnR4dCBEQVNUb29sX2Jpbm5pbmdfcmVzdWx0cy50eHQKYGBgYAoKLSBOb3cgaW1wb3J0IHRoZSBEQVNUb29sIGJpbiBjb2xsZWN0aW9uIGludG8gdGhlIG1lcmdlZF9wcm9maWxlIGRhdGFiYXNlOgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KY2QgL0ROQV9kYXRhL3dvcmsvYmlubmluZy9kYXN0b29sCmFudmktaW1wb3J0LWNvbGxlY3Rpb24gLWMgL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgLXAgL0ROQV9kYXRhL3dvcmsvbWFwcGluZy9tZXJnZWRfcHJvZmlsZS9QUk9GSUxFLmRiIC1DIERBU1Rvb2wgREFTVG9vbF9iaW5uaW5nX3Jlc3VsdHMudHh0CgojT3V0cHV0IERBU1Rvb2wKSXRlbSBuYW1lcyBpbiBpbnB1dCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogMzEsNDc5Ck51bSBiaW5zIGluIGlucHV0IC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IDU4Ckl0ZW1zIGluIHByb2ZpbGUgZGF0YWJhc2UgLi4uLi4uLi4uLi4uLi4uLi4uLi46IDEzMSwwNzQKSXRlbSBuYW1lcyBzaGFyZWQgYmV0d2VlbiBpbnB1dCBhbmQgZGIgLi4uLi4uLjogMzEsNDc5CgpXQVJOSU5HCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cjk5NTk1IGl0ZW0ocykgdGhhdCB3ZXJlIGluIHRoZSBkYXRhYmFzZSwgYnV0IHdlcmUgbm90IGluIHRoZSBpbnB1dCBmaWxlLCB3aWxsCm5vdCBiZSBkZXNjcmliZWQgYnkgYW55IGJpbiBpbiB0aGUgY29sbGVjdGlvbiBEQVNUb29sLiBUaGF0IGlzIHRvdGFsbHkgZmluZSwgYnV0CmFudmknbyBob3BlcyB0aGF0IHlvdSBhcmUgYXdhcmUgb2YgdGhhdC4gVGhpcyBtZWFucyB5b3UgaGF2ZSBtb3JlIHRoaW5ncyBpbiB5b3VyCmRhdGFiYXNlIHRoYW4gdGhlIG51bWJlciBvZiB0aGluZ3MgeW91ciBpbnB1dCBmaWxlIGRlc2NyaWJlcy4gSGVyZSBpcyBhbiBleGFtcGxlCm9mIHNvbWV0aGluZyB0aGF0IGlzIGluIHlvdXIgZGF0YWJhc2UgYnV0IG5vdCBpbiBhbnkgYmluIGluIHlvdXIgaW5wdXQgZmlsZToKazI1NV8yMjIxODc4X2ZsYWdfMV9tdWx0aV85LjAwMDBfbGVuXzQwMDNfc3BsaXRfMDAwMDEuCgpDb2xsZWN0aW9ucyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uOiBUaGUgY29sbGVjdGlvbiAiREFTVG9vbCIgdGhhdCBkZXNjcmliZXMgMzEsNDc5IHNwbGl0cyBhbmQgNTggYmlucyBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhlIGRhdGFiYXNlIGF0ICIvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlL1BST0ZJTEUuZGIiLiBIZXJlIGlzIGEgbGlzdCBvZiB0aGUgZmlyc3QgNTAgYmluIG5hbWVzIGluIHRoaXMgY29sbGVjdGlvbjogTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDExLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA5MCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xMzYsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDcxLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAyNyxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xNjMsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTQyLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA3NCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMzEsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTA2LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA1NixNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wODksTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDc4LENPTkNPQ1RfYmlubmluZ19yZXN1bHRzXzA3MCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNDYsQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDYyLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA2NCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xMTAsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDgzLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE1OSxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xMzIsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDU1LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA3MyxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wODAsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTYwLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA4MSxDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wMjMsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDQ0LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE1MyxDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNjAsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTYxLE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE0OCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNjAsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDY4LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzEzNyxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMzIsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTQ1LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAzMyxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xNjUsQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDUzLENPTkNPQ1RfYmlubmluZ19yZXN1bHRzXzA1NSxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMjksTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDM2LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA4OCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNjksQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDU2LE1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAxNCxNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMjQsTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDIzLENPTkNPQ1RfYmlubmluZ19yZXN1bHRzXzA3MS4KYGBgYAoKLSBUaGUgZmluYWwgc3RlcCBpcyB0byBleHBvcnQgdGhlIGJpbiBzdGF0cyBzdW1tYXJ5IGZpbGUgZm9yIERBU1Rvb2xzCgpgYGBgbWFya2Rvd24KYHIgJydge1Rlcm1pbmFsfQpjZCAvRE5BX2RhdGEvd29yay9iaW5uaW5nL2Rhc3Rvb2wKYW52aS1zY3JpcHQtZ2V0LWNvbGxlY3Rpb24taW5mbyAtYyAvRE5BX2RhdGEvd29yay9jb19hc3NlbWJseS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYiAtcCAvRE5BX2RhdGEvd29yay9tYXBwaW5nL21lcmdlZF9wcm9maWxlL1BST0ZJTEUuZGIgLUMgREFTVG9vbCAtbyBETkFfZGF0YV9iYm5vcm1fREFTVG9vbF9zdW1tYXJ5LnR4dAoKI091dHB1dApDb250aWdzIERCIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uOiBJbml0aWFsaXplZDogL0ROQV9kYXRhL3dvcmsvY29fYXNzZW1ibHkvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgKHYuIDEyKQoKKiBDb21wbGV0aW9uIGFuZCByZWR1bmRhbmN5IGVzdGltYXRlcy4gUEM6IFBlcmNlbnQgY29tcGxldGlvbjsgUFI6IFBlcmNlbnQKcmVkdW5kYW5jeTsgTjogTnVtYmVyIG9mIHNwbGl0czsgTDogTGVuZ3RoICh0b3RhbCBudW1iZXIgb2YgbnVjbGVvdGlkZXMpOyBEOgpEb21haW4gZm9yIHNpbmdsZS1jb3B5IGNvcmUgZ2VuZXM7IEM6IERvbWFpbiBjb25maWRlbmNlLgoKCkJpbnMgaW4gY29sbGVjdGlvbiAiREFTVG9vbCIKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDExIDo6IFBDOiA5My41MyUsIFBSOiAzLjYwJSwgTjogMzUyLCBMOiAzLDEzOCw2NjUsIEQ6IGJhY3RlcmlhIChDOiAwLjkwKQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wOTAgOjogUEM6IDk4LjU2JSwgUFI6IDYuNDclLCBOOiAxLDAyMywgTDogNiw2ODEsNjU1LCBEOiBiYWN0ZXJpYSAoQzogMC45MikKCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzEzNiA6OiBQQzogOTEuMzYlLCBQUjogMTAuNDklLCBOOiAyMjEsIEw6IDEsNjEzLDIxNSwgRDogYXJjaGFlYSAoQzogMC44MSkKCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA3MSA6OiBQQzogOTcuMTIlLCBQUjogMC43MiUsIE46IDM3OCwgTDogMiw3MjMsMTM3LCBEOiBiYWN0ZXJpYSAoQzogMC45NikKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDI3IDo6IFBDOiA4OC40OSUsIFBSOiAzLjYwJSwgTjogMzgyLCBMOiAyLDY0MSw3MTAsIEQ6IGJhY3RlcmlhIChDOiAwLjg1KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xNjMgOjogUEM6IDg5LjkzJSwgUFI6IDYuNDclLCBOOiAxLDA5MywgTDogNSw3MzEsNDUxLCBEOiBiYWN0ZXJpYSAoQzogMC44MykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTQyIDo6IFBDOiA4MC41OCUsIFBSOiAzLjYwJSwgTjogNTc1LCBMOiAzLDkxOCwyOTUsIEQ6IGJhY3RlcmlhIChDOiAwLjc3KQoKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDc0IDo6IFBDOiA4OS45MyUsIFBSOiAxMC4wNyUsIE46IDc1OCwgTDogMyw2NzIsNTgyLCBEOiBiYWN0ZXJpYSAoQzogMC44MCkKCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAzMSA6OiBQQzogOTIuODElLCBQUjogOS4zNSUsIE46IDU0MCwgTDogMiw3MTQsNjI3LCBEOiBiYWN0ZXJpYSAoQzogMC44MykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTA2IDo6IFBDOiA4Ny43NyUsIFBSOiAyLjE2JSwgTjogNDI2LCBMOiAyLDYzOSwyMjMsIEQ6IGJhY3RlcmlhIChDOiAwLjg2KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNTYgOjogUEM6IDkwLjY1JSwgUFI6IDMuNjAlLCBOOiAyOTUsIEw6IDIsMTMzLDY4MSwgRDogYmFjdGVyaWEgKEM6IDAuODcpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA4OSA6OiBQQzogOTUuNjglLCBQUjogMi44OCUsIE46IDYyMiwgTDogNCw3NTgsMzczLCBEOiBiYWN0ZXJpYSAoQzogMC45MykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDc4IDo6IFBDOiA4NC44OSUsIFBSOiA1Ljc2JSwgTjogNDYzLCBMOiAzLDA0Niw1NDAsIEQ6IGJhY3RlcmlhIChDOiAwLjc5KQpDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNzAgOjogUEM6IDgyLjczJSwgUFI6IDIuMTYlLCBOOiAyODYsIEw6IDEsODUxLDI1OSwgRDogYmFjdGVyaWEgKEM6IDAuODEpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA0NiA6OiBQQzogODguODklLCBQUjogOS4yNiUsIE46IDIwNiwgTDogMSw1MzYsOTc1LCBEOiBhcmNoYWVhIChDOiAwLjgwKQpDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNjIgOjogUEM6IDgyLjAxJSwgUFI6IDAuNzIlLCBOOiAxNjAsIEw6IDEsNDY4LDQ5MCwgRDogYmFjdGVyaWEgKEM6IDAuODEpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA2NCA6OiBQQzogOTQuOTYlLCBQUjogNS4wNCUsIE46IDUzNywgTDogMywyNTgsOTM0LCBEOiBiYWN0ZXJpYSAoQzogMC45MCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTEwIDo6IFBDOiA3NC44MiUsIFBSOiA3LjkxJSwgTjogMjk4LCBMOiAxLDQwOCw4OTYsIEQ6IGJhY3RlcmlhIChDOiAwLjY3KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wODMgOjogUEM6IDgyLjAxJSwgUFI6IDYuNDclLCBOOiAzMzEsIEw6IDIsMDk1LDY2NiwgRDogYmFjdGVyaWEgKEM6IDAuNzYpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE1OSA6OiBQQzogOTAuNjUlLCBQUjogOS4zNSUsIE46IDk2NywgTDogNSw3MjQsOTUzLCBEOiBiYWN0ZXJpYSAoQzogMC44MSkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTMyIDo6IFBDOiA4NS42MSUsIFBSOiA1LjA0JSwgTjogOTM5LCBMOiA2LDA0Niw1MDEsIEQ6IGJhY3RlcmlhIChDOiAwLjgxKQoKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDU1IDo6IFBDOiA4My40NSUsIFBSOiAxMC4wNyUsIE46IDg4MiwgTDogNiw1NjAsNzc4LCBEOiBiYWN0ZXJpYSAoQzogMC43MykKCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA3MyA6OiBQQzogNzYuOTglLCBQUjogNS4wNCUsIE46IDM3NSwgTDogMiwyNDYsMTA2LCBEOiBiYWN0ZXJpYSAoQzogMC43MikKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDgwIDo6IFBDOiA3MS45NCUsIFBSOiAzLjYwJSwgTjogNDI1LCBMOiAyLDQxNCw1NTIsIEQ6IGJhY3RlcmlhIChDOiAwLjY4KQoKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTYwIDo6IFBDOiA4MS4yOSUsIFBSOiAxMi45NSUsIE46IDEsMTk4LCBMOiA2LDMwOCwzMDAsIEQ6IGJhY3RlcmlhIChDOiAwLjY4KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wODEgOjogUEM6IDkyLjA5JSwgUFI6IDI4Ljc4JSwgTjogNDEwLCBMOiAyLDg5NywwOTEsIEQ6IGJhY3RlcmlhIChDOiAwLjYzKQoKQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDIzIDo6IFBDOiA4Mi4wMSUsIFBSOiA0LjMyJSwgTjogMjUxLCBMOiAyLDYxNCw1NDEsIEQ6IGJhY3RlcmlhIChDOiAwLjc4KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNDQgOjogUEM6IDc0LjEwJSwgUFI6IDUuMDQlLCBOOiA5MjEsIEw6IDQsODIzLDY2MiwgRDogYmFjdGVyaWEgKEM6IDAuNjkpCgpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xNTMgOjogUEM6IDk1LjY4JSwgUFI6IDIzLjAyJSwgTjogNTAwLCBMOiA0LDUxOSwwNDQsIEQ6IGJhY3RlcmlhIChDOiAwLjczKQoKQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDYwIDo6IFBDOiA2NC4wMyUsIFBSOiAzLjYwJSwgTjogMSwwNDAsIEw6IDYsMTc4LDc4MywgRDogYmFjdGVyaWEgKEM6IDAuNjApCgpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xNjEgOjogUEM6IDc0LjgyJSwgUFI6IDcuMTklLCBOOiA1NzgsIEw6IDIsNTgwLDI4NiwgRDogYmFjdGVyaWEgKEM6IDAuNjgpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE0OCA6OiBQQzogNzQuMTAlLCBQUjogMi4xNiUsIE46IDYyOSwgTDogMiw3ODYsOTgwLCBEOiBiYWN0ZXJpYSAoQzogMC43MikKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDYwIDo6IFBDOiA3NC44MiUsIFBSOiAxMC43OSUsIE46IDEsMTQ0LCBMOiA3LDg0OCw4NjIsIEQ6IGJhY3RlcmlhIChDOiAwLjY0KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNjggOjogUEM6IDk1LjY4JSwgUFI6IDIwLjE0JSwgTjogMzE1LCBMOiAyLDAxMSwyODUsIEQ6IGJhY3RlcmlhIChDOiAwLjc2KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xMzcgOjogUEM6IDc4LjQyJSwgUFI6IDUuMDQlLCBOOiA2MjcsIEw6IDIsODcwLDU3MCwgRDogYmFjdGVyaWEgKEM6IDAuNzMpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAzMiA6OiBQQzogODMuNDUlLCBQUjogMTEuNTElLCBOOiA0MDMsIEw6IDIsMTU4LDE3NywgRDogYmFjdGVyaWEgKEM6IDAuNzIpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE0NSA6OiBQQzogNjEuMTUlLCBQUjogMC43MiUsIE46IDI5MiwgTDogMSw0MzMsMzM3LCBEOiBiYWN0ZXJpYSAoQzogMC42MCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDMzIDo6IFBDOiA2NS40NyUsIFBSOiAxMi4yMyUsIE46IDQ0NywgTDogMSw4NDgsMDIyLCBEOiBiYWN0ZXJpYSAoQzogMC41MykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTY1IDo6IFBDOiA4NC4xNyUsIFBSOiA5LjM1JSwgTjogNzQyLCBMOiA1LDU4NywyNjksIEQ6IGJhY3RlcmlhIChDOiAwLjc1KQpDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNTMgOjogUEM6IDc2LjI2JSwgUFI6IDUuMDQlLCBOOiA2OTAsIEw6IDMsMjI0LDM1NiwgRDogYmFjdGVyaWEgKEM6IDAuNzEpCkNPTkNPQ1RfYmlubmluZ19yZXN1bHRzXzA1NSA6OiBQQzogNTEuMDglLCBQUjogMS40NCUsIE46IDYzOSwgTDogMiw1NTgsOTg0LCBEOiBiYWN0ZXJpYSAoQzogMC41MCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDI5IDo6IFBDOiA3Mi42NiUsIFBSOiA1LjA0JSwgTjogNDMxLCBMOiAyLDE4Nyw4ODgsIEQ6IGJhY3RlcmlhIChDOiAwLjY4KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMzYgOjogUEM6IDk3LjEyJSwgUFI6IDI4LjA2JSwgTjogOTQwLCBMOiA1LDU1NCw0ODAsIEQ6IGJhY3RlcmlhIChDOiAwLjY5KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wODggOjogUEM6IDQ3LjQ4JSwgUFI6IDAuNzIlLCBOOiAxMzcsIEw6IDU4MSwzNDcsIEQ6IGJhY3RlcmlhIChDOiAwLjQ3KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNjkgOjogUEM6IDU1LjQwJSwgUFI6IDAuMDAlLCBOOiAyMDgsIEw6IDEsOTg2LDI4NCwgRDogYmFjdGVyaWEgKEM6IDAuNTUpCkNPTkNPQ1RfYmlubmluZ19yZXN1bHRzXzA1NiA6OiBQQzogNjkuMDYlLCBQUjogNS4wNCUsIE46IDEsMTExLCBMOiA1LDMzNyw5NjcsIEQ6IGJhY3RlcmlhIChDOiAwLjY0KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMTQgOjogUEM6IDY1LjQ3JSwgUFI6IDUuNzYlLCBOOiA0NDUsIEw6IDEsOTIxLDI0NSwgRDogYmFjdGVyaWEgKEM6IDAuNjApCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAyNCA6OiBQQzogNjEuMTUlLCBQUjogNC4zMiUsIE46IDYyMywgTDogMiw2MTgsMTY4LCBEOiBiYWN0ZXJpYSAoQzogMC41NykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDIzIDo6IFBDOiA1Ni4xMiUsIFBSOiAyLjE2JSwgTjogNDQxLCBMOiAyLDE5NSw1MjMsIEQ6IGJhY3RlcmlhIChDOiAwLjU0KQpDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNzEgOjogUEM6IDU0LjY4JSwgUFI6IDQuMzIlLCBOOiAyMjgsIEw6IDEsNjUyLDY4OCwgRDogYmFjdGVyaWEgKEM6IDAuNTApCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA3MCA6OiBQQzogNjIuNTklLCBQUjogMi44OCUsIE46IDQzNSwgTDogMSw3ODgsMjM1LCBEOiBiYWN0ZXJpYSAoQzogMC42MCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDk4IDo6IFBDOiAzNy40MSUsIFBSOiAyLjg4JSwgTjogNTM2LCBMOiAxLDk5MSwzODQsIEQ6IGJhY3RlcmlhIChDOiAwLjM1KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNTEgOjogUEM6IDgzLjQ1JSwgUFI6IDcuOTElLCBOOiAyNDgsIEw6IDEsNzg5LDEwOCwgRDogYmFjdGVyaWEgKEM6IDAuNzYpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE2NCA6OiBQQzogNjAuNDMlLCBQUjogMS40NCUsIE46IDMzOCwgTDogMSw4MDcsMzk0LCBEOiBiYWN0ZXJpYSAoQzogMC41OSkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDEyIDo6IFBDOiA0My44OCUsIFBSOiA1Ljc2JSwgTjogMTczLCBMOiA3NzQsMzg5LCBEOiBiYWN0ZXJpYSAoQzogMC4zOCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTU1IDo6IFBDOiA0OS42NCUsIFBSOiAzLjYwJSwgTjogNjcxLCBMOiAyLDY3MCw0ODAsIEQ6IGJhY3RlcmlhIChDOiAwLjQ2KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNDMgOjogUEM6IDM4Ljg1JSwgUFI6IDIuMTYlLCBOOiA0NzQsIEw6IDEsODYzLDUyMywgRDogYmFjdGVyaWEgKEM6IDAuMzcpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA4NSA6OiBQQzogNjYuMTklLCBQUjogMTAuNzklLCBOOiA2ODAsIEw6IDQsMjU1LDgyMiwgRDogYmFjdGVyaWEgKEM6IDAuNTUpCgpPdXRwdXQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uOiBETkFfZGF0YV9iYm5vcm1fREFTVG9vbF9zdW1tYXJ5LnR4dApgYGBgCgotIE5vdywgc2VsZWN0IG9ubHkgdGhvc2UgYmlucyB0aGF0IGFyZSA+IDcwJSBjb21wbGV0ZSBhbmQgPCAxMCUgcmVkdW5kYW50IGFzIHRoZSBmaW5hbCAqKk1ldGFnZW5vbWUgQXNzZW1ibGVkIEdlbm9tZXMqKiAoTUFHcykgZGF0YXNldAoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KQmlucyBpbiBjb2xsZWN0aW9uICJEQVNUb29sIiB0byBrZWVwIChQQyA+IDcwJSB8IFBSIDwgMTAlKSAtLSAzMCBCaW5zCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDExIDo6IFBDOiA5My41MyUsIFBSOiAzLjYwJSwgTjogMzUyLCBMOiAzLDEzOCw2NjUsIEQ6IGJhY3RlcmlhIChDOiAwLjkwKQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wOTAgOjogUEM6IDk4LjU2JSwgUFI6IDYuNDclLCBOOiAxLDAyMywgTDogNiw2ODEsNjU1LCBEOiBiYWN0ZXJpYSAoQzogMC45MikKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDcxIDo6IFBDOiA5Ny4xMiUsIFBSOiAwLjcyJSwgTjogMzc4LCBMOiAyLDcyMywxMzcsIEQ6IGJhY3RlcmlhIChDOiAwLjk2KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMjcgOjogUEM6IDg4LjQ5JSwgUFI6IDMuNjAlLCBOOiAzODIsIEw6IDIsNjQxLDcxMCwgRDogYmFjdGVyaWEgKEM6IDAuODUpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE2MyA6OiBQQzogODkuOTMlLCBQUjogNi40NyUsIE46IDEsMDkzLCBMOiA1LDczMSw0NTEsIEQ6IGJhY3RlcmlhIChDOiAwLjgzKQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xNDIgOjogUEM6IDgwLjU4JSwgUFI6IDMuNjAlLCBOOiA1NzUsIEw6IDMsOTE4LDI5NSwgRDogYmFjdGVyaWEgKEM6IDAuNzcpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzAzMSA6OiBQQzogOTIuODElLCBQUjogOS4zNSUsIE46IDU0MCwgTDogMiw3MTQsNjI3LCBEOiBiYWN0ZXJpYSAoQzogMC44MykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTA2IDo6IFBDOiA4Ny43NyUsIFBSOiAyLjE2JSwgTjogNDI2LCBMOiAyLDYzOSwyMjMsIEQ6IGJhY3RlcmlhIChDOiAwLjg2KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNTYgOjogUEM6IDkwLjY1JSwgUFI6IDMuNjAlLCBOOiAyOTUsIEw6IDIsMTMzLDY4MSwgRDogYmFjdGVyaWEgKEM6IDAuODcpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA4OSA6OiBQQzogOTUuNjglLCBQUjogMi44OCUsIE46IDYyMiwgTDogNCw3NTgsMzczLCBEOiBiYWN0ZXJpYSAoQzogMC45MykKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMDc4IDo6IFBDOiA4NC44OSUsIFBSOiA1Ljc2JSwgTjogNDYzLCBMOiAzLDA0Niw1NDAsIEQ6IGJhY3RlcmlhIChDOiAwLjc5KQpDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNzAgOjogUEM6IDgyLjczJSwgUFI6IDIuMTYlLCBOOiAyODYsIEw6IDEsODUxLDI1OSwgRDogYmFjdGVyaWEgKEM6IDAuODEpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA0NiA6OiBQQzogODguODklLCBQUjogOS4yNiUsIE46IDIwNiwgTDogMSw1MzYsOTc1LCBEOiBhcmNoYWVhIChDOiAwLjgwKQpDT05DT0NUX2Jpbm5pbmdfcmVzdWx0c18wNjIgOjogUEM6IDgyLjAxJSwgUFI6IDAuNzIlLCBOOiAxNjAsIEw6IDEsNDY4LDQ5MCwgRDogYmFjdGVyaWEgKEM6IDAuODEpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA2NCA6OiBQQzogOTQuOTYlLCBQUjogNS4wNCUsIE46IDUzNywgTDogMywyNTgsOTM0LCBEOiBiYWN0ZXJpYSAoQzogMC45MCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTEwIDo6IFBDOiA3NC44MiUsIFBSOiA3LjkxJSwgTjogMjk4LCBMOiAxLDQwOCw4OTYsIEQ6IGJhY3RlcmlhIChDOiAwLjY3KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wODMgOjogUEM6IDgyLjAxJSwgUFI6IDYuNDclLCBOOiAzMzEsIEw6IDIsMDk1LDY2NiwgRDogYmFjdGVyaWEgKEM6IDAuNzYpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE1OSA6OiBQQzogOTAuNjUlLCBQUjogOS4zNSUsIE46IDk2NywgTDogNSw3MjQsOTUzLCBEOiBiYWN0ZXJpYSAoQzogMC44MSkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTMyIDo6IFBDOiA4NS42MSUsIFBSOiA1LjA0JSwgTjogOTM5LCBMOiA2LDA0Niw1MDEsIEQ6IGJhY3RlcmlhIChDOiAwLjgxKQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNzMgOjogUEM6IDc2Ljk4JSwgUFI6IDUuMDQlLCBOOiAzNzUsIEw6IDIsMjQ2LDEwNiwgRDogYmFjdGVyaWEgKEM6IDAuNzIpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA4MCA6OiBQQzogNzEuOTQlLCBQUjogMy42MCUsIE46IDQyNSwgTDogMiw0MTQsNTUyLCBEOiBiYWN0ZXJpYSAoQzogMC42OCkKQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDIzIDo6IFBDOiA4Mi4wMSUsIFBSOiA0LjMyJSwgTjogMjUxLCBMOiAyLDYxNCw1NDEsIEQ6IGJhY3RlcmlhIChDOiAwLjc4KQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wNDQgOjogUEM6IDc0LjEwJSwgUFI6IDUuMDQlLCBOOiA5MjEsIEw6IDQsODIzLDY2MiwgRDogYmFjdGVyaWEgKEM6IDAuNjkpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE2MSA6OiBQQzogNzQuODIlLCBQUjogNy4xOSUsIE46IDU3OCwgTDogMiw1ODAsMjg2LCBEOiBiYWN0ZXJpYSAoQzogMC42OCkKTWV0YWJhdF9iaW5uaW5nX3Jlc3VsdHNfMTQ4IDo6IFBDOiA3NC4xMCUsIFBSOiAyLjE2JSwgTjogNjI5LCBMOiAyLDc4Niw5ODAsIEQ6IGJhY3RlcmlhIChDOiAwLjcyKQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18xMzcgOjogUEM6IDc4LjQyJSwgUFI6IDUuMDQlLCBOOiA2MjcsIEw6IDIsODcwLDU3MCwgRDogYmFjdGVyaWEgKEM6IDAuNzMpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzE2NSA6OiBQQzogODQuMTclLCBQUjogOS4zNSUsIE46IDc0MiwgTDogNSw1ODcsMjY5LCBEOiBiYWN0ZXJpYSAoQzogMC43NSkKQ09OQ09DVF9iaW5uaW5nX3Jlc3VsdHNfMDUzIDo6IFBDOiA3Ni4yNiUsIFBSOiA1LjA0JSwgTjogNjkwLCBMOiAzLDIyNCwzNTYsIEQ6IGJhY3RlcmlhIChDOiAwLjcxKQpNZXRhYmF0X2Jpbm5pbmdfcmVzdWx0c18wMjkgOjogUEM6IDcyLjY2JSwgUFI6IDUuMDQlLCBOOiA0MzEsIEw6IDIsMTg3LDg4OCwgRDogYmFjdGVyaWEgKEM6IDAuNjgpCk1ldGFiYXRfYmlubmluZ19yZXN1bHRzXzA1MSA6OiBQQzogODMuNDUlLCBQUjogNy45MSUsIE46IDI0OCwgTDogMSw3ODksMTA4LCBEOiBiYWN0ZXJpYSAoQzogMC43NikKYGBgYAoKPGZvbnQgY29sb3I9ImJsdWUiPioqMi42LjUqKjwvZm9udD4gREFTVG9vbHMgTUFHcyBUYXhvbm9teQoKLSBOb3cgdGhhdCB3ZSd2ZSBnZW5lcmF0ZWQgdGhlIERBU1Rvb2xzIE1BR1MgY29sbGVjdGlvbiwgb3VyIGZpbmFsIHN0ZXBzIGludm9sdmUgYXNzaWduaW5nIHRheG9ub215IHRvIGVhY2ggTUFHIGFuZCBjYWxjdWxhdGluZyB0aGUgcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIGVhY2ggTUFHIGluIGVhY2ggbWV0YWdlbm9tZSBzYW1wbGUuICAqKlRoZSBmb2xsb3dpbmcgY29tbWFuZHMgb25seSB3b3JrIHdpdGggQW52aW8gdjYuMi4qKgoKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KIyBEb3dubG9hZGluZyB0YXhvbm9teSBzZWFyY2ggZGF0YWJhc2VzIChvbmx5IG5lZWQgdG8gZG8gb25jZSkKYW52aS1zZXR1cC1zY2ctZGF0YWJhc2VzCgojIFVwZGF0ZSBjb250aWdzIGRhdGFiYXNlIGZyb20gdjEyIHRvIHYxNCAobmVjZXNzYXJ5IGZvciBhc3NpZ25pbmcgdGF4b25vbXkpCmFudmktbWlncmF0ZSAvMjAxN19SZWRveC9NQUdzX0ROQS9ETkFfZGF0YV9iYm5vcm1fYW52aW9fY29udGlncy5kYgoKIyBVcGRhdGUgcHJvZmlsZSBmcm9tIHYzMCB0byB2MzEgKG5lY2Vzc2FyeSBmb3IgYXNzaWduaW5nIHRheG9ub215KQphbnZpLW1pZ3JhdGUgLzIwMTdfUmVkb3gvTUFHc19ETkEvUFJPRklMRS5kYgoKIyBQb3B1bGF0ZSB0YWJsZXMgd2l0aCBITU0gaGl0cyAoc2luY2UgdGhleSB3aWxsIGJlIHJlbW92ZWQgd2hlbiB1cGRhdGluZyB0aGUgY29udGlncyBkYiBmcm9tIHYxMiB0byB2MTQgLS0gc2VlIGFib3ZlKQphbnZpLXJ1bi1obW1zIC1jIC8yMDE3X1JlZG94L01BR3NfRE5BL0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiCgojIFBvcHVsYXRpbmcgY29udGlncyBkYiB3aXRoIFNDRyB0YXhvbm9teQphbnZpLXJ1bi1zY2ctdGF4b25vbXkgLWMgLzIwMTdfUmVkb3gvTUFHc19ETkEvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIKCiMgRXN0aW1hdGUgdGF4b25vbXkgYmFzZWQgb24gc2luZ2xlLWNvcHkgY29yZSBnZW5lcyAoU0NHKSB3aXRoaW4gZWFjaCBNQUcKYW52aS1lc3RpbWF0ZS1zY2ctdGF4b25vbXkgLWMgLzIwMTdfUmVkb3gvTUFHc19ETkEvRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3MuZGIgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAtcCAvMjAxN19SZWRveC9NQUdzX0ROQS9QUk9GSUxFLmRiIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLUMgREFTVG9vbCBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tY29tcHV0ZS1zY2ctY292ZXJhZ2VzIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLS1vdXRwdXQtZmlsZSAvTUFHcy50YXhhLm91dHB1dC50eHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgCiMjIyBPdXRwdXQKQ29udGlncyBEQiAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogL2dwZnMvYWNjb3VudHMvZ3drX3Jvb3QvZ3drMS9ranJvbWFuby8yMDE3X1JlZG94L01BR3NfRE5BL0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzLmRiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgClByb2ZpbGUgREIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IC9ncGZzL2FjY291bnRzL2d3a19yb290L2d3azEva2pyb21hbm8vMjAxN19SZWRveC9NQUdzX0ROQS9QUk9GSUxFLmRiCk1ldGFnZW5vbWUgbW9kZSAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi46IEZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIApXQVJOSU5HCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ClBsZWFzZSBub3RlIHRoYXQgYW52aSdvIGZvdW5kIDIsNDY0LDIwMiBzcGxpdHMgaW4geW91ciBjb250aWdzIGRhdGFiYXNlLiBCdXQKb25seSAxMzEsMDc0IG9mIHRoZW0gYXBwZWFyZWQgdG8gYmUgaW4gdGhlIHByb2ZpbGUgZGF0YWJhc2UuIEFzIGEgcmVzdWx0LCBhbnZpJ28Kd2lsbCBub3cgcmVtb3ZlIHRoZSAyLDMzMywxMjggc3BsaXRzIHRoYXQgb2NjdXIgb25seSBpbiB0aGUgY29udGlncyBkYiBmcm9tIGFsbApkb3duc3RyZWFtIGFuYWx5c2VzIGhlcmUgKGlmIHlvdSBkaWRuJ3QgdXNlIHRoZSBmbGFnIGAtLWNvbXB1dGUtc2NnLWNvdmVyYWdlc2AKdGhpcyB3b3VsZG4ndCBoYXZlIGJlZW4gbmVjZXNzYXJ5LCBidXQgd2l0aCB0aGUgY3VycmVudCBzZXR0aW5ncyB0aGlzIGlzIHJlYWxseQp0aGUgYmVzdCBmb3IgZXZlcnlvbmUpLiBXaGVyZSBpcyB0aGlzIGRpZmZlcmVuY2UgY29taW5nIGZyb20gdGhvdWdoPyBXZWxsLiBUaGlzCmlzIG9mdGVuIHRoZSBjYXNlIGJlY2F1c2UgdGhlICdtaW5pbXVtIGNvbnRpZyBsZW5ndGggcGFyYW1ldGVyJyBzZXQgZHVyaW5nIHRoZQpgYW52aS1wcm9maWxlYCBzdGVwIGNhbiBleGNsdWRlIG1hbnkgY29udGlncyBmcm9tIGRvd25zdHJlYW0gYW5hbHlzZXMgKG9mdGVuIGZvcgpnb29kIHJlYXNvbnMsIHRvbykuIEZvciBpbnN0YW5jZSwgaW4geW91ciBjYXNlIHRoZSBtaW5pbXVtIGNvbnRpZyBsZW5ndGggZ29lcyBhcwpsb3cgYXMgMjU2IG50cyBpbiB5b3VyIGNvbnRpZ3MgZGF0YWJhc2UuIFlldCwgdGhlIG1pbmltdW0gY29udGlnIGxlbmd0aCBzZXQgaW4KdGhlIHByb2ZpbGUgZGF0YWJhZXMgaXMgMiw1MDAgbnRzLiBIZW5jZSB0aGUgZGlmZmVyZW5jZS4gQW52aSdvIGhvcGVzIHRoYXQgdGhpcwpleHBsYWluZXMgc29tZSB0aGluZ3MuCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKKiAzMSw0Nzkgc3BsaXQgbmFtZXMgYXNzb2NpYXRlZCB3aXRoIDU4IGJpbnMgb2YgaW4gY29sbGVjdGlvbiAnREFTVG9vbCcgaGF2ZSBiZWVuCnN1Y2Nlc3NmdWxseSByZWNvdmVyZWQg8J+OigogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKKiBBbnZpJ28gd2lsbCBub3cgYXR0ZW1wdCB0byByZWNvdmVyIFNDRyBjb3ZlcmFnZXMgaW4gR0VOT01FIE1PREUgZnJvbSB0aGUgcHJvZmlsZQpkYXRhYmFzZSwgd2hpY2ggY29udGFpbnMgMTUgc2FtcGxlcy4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIApGUklFTkRMWSBSRU1JTkRFUgo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpBbnZpJ28gaGFzIGp1c3QgZmluaXNoZWQgcmVjb3ZlcmluZyBTQ0cgY292ZXJhZ2VzIGZyb20gdGhlIHByb2ZpbGUgZGF0YWJhc2UgdG8KZXN0aW1hdGUgdGhlIGF2ZXJhZ2UgY292ZXJhZ2Ugb2YgeW91ciBiaW5zIGFjcm9zcyB5b3VyIHNhbXBsZXMuIFBsZWFzZSBub3RlIHRoYXQKYW52aSdvIFNDRyB0YXhvbm9teSBmcmFtZXdvcmsgaXMgdXNpbmcgb25seSAlZCBTQ0dzIHRvIGVzdGltYXRlIHRheG9ub215LiBXaGljaAptZWFucywgZXZlbiBhIGhpZ2hseSBjb21wbGV0ZSBiaW4gbWF5IGJlIG1pc3NpbmcgYWxsIG9mIHRoZW0uIEluIHdoaWNoIGNhc2UsIHRoZQpjb3ZlcmFnZSBvZiB0aGF0IGJpbiB3aWxsIGJlIGBOb25lYCBhY3Jvc3MgYWxsIHlvdXIgc2FtcGxlcy4gVGhlIGJlc3Qgd2F5IHRvCnByZXZlbnQgYW55IG1pc2xlYWRpbmcgaW5zaWdodHMgaXMgdGFrZSB0aGVzZSByZXN1bHRzIHdpdGggYSBodWdlIGdyYWluIG9mIHNhbHQsCmFuZCB1c2UgdGhlIGBhbnZpLXN1bW1hcml6ZWAgb3V0cHV0IGZvciBjcml0aWNhbCBhcHBsaWNhdGlvbnMuCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKRXN0aW1hdGVkIHRheG9ub215IGZvciBjb2xsZWN0aW9uICJEQVNUb29sIgo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKT3V0cHV0IGZpbGUgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjogL01BR3MudGF4YS5vdXRwdXQudHh0CgrinJMgYW52aS1lc3RpbWF0ZS1zY2ctdGF4b25vbXkgdG9vayAwOjAyOjIzLjcyNjc0NgpgYGBgCgoKIyMjIDIuNy4gTUcgUmVhZCBTdW1tYXJ5CgpUaGUgZm9sbG93aW5nIHRhYmxlIGlzIGEgc3VtbWFyeSBvZiB0aGUgRE5BIHJlYWRzIGJ5IHNhbXBsZSBhbmQgaW5jbHVkZXMgKipRQyBSZWFkcyoqLCAqKk1hcHBlZCBSZWFkcyoqLCBhbmQgKipBdmVyYWdlIFJlYWQgTGVuZ3RoIChicCkqKi4gIEFsbCB2YWx1ZXMgd2VyZSBkZXJpdmVkIGZyb20gdGhlICIqKlNhbXBsZV9cKi5maW5hbC5jb250aWdzLmZpeGVkLmJibm9ybS5zb3J0ZWQuYmFtKioiIGZpbGVzIHVzaW5nIGBzYW10b29scyBzdGF0c2AuCmBgYHtyIGVjaG89RkFMU0V9CmRuYS5pbmZvcm1hdGljczwtcmVhZC50YWJsZSgiVGFibGUuRGF0YS9kbmEuYmlvaW5mb3JtYXRpY3MudGFibGUudHh0IixzZXA9J1x0JywgcXVvdGU9IiIsIGZpbGw9VFJVRSxoZWFkZXIgPSBUUlVFKQpuYW1lcyhkbmEuaW5mb3JtYXRpY3MpPC1jKCJJRCIsICJUdW5kcmEiLCAiVGltZSIsICJSZXBsaWNhdGUiLCAiUUMgUmVhZHMiLCAiTWFwcGVkIFJlYWRzIiwgIkF2ZXJhZ2UgTGVuZ3RoIChicCkiKQprYWJsZShkbmEuaW5mb3JtYXRpY3MsIGNhcHRpb24gPSAiU3VtbWFyeSBzdGF0aXN0aWNzIGZvciBETkEtYmFzZWQgbWV0YWdlbm9taWMgc2VxdWVuY2luZyBkYXRhc2V0IiwgZm9ybWF0LmFyZ3MgPSBsaXN0KGJpZy5tYXJrID0gIiwiKSwgYWxpZ24gPSAiYyIpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkKYGBgCgojIyAzLiBHZW5lIEFubm90YXRpb25zCgpGb2xsb3dpbmcgYWxsICoqRGF0YSBCaW9pbmZvcm1hdGljcyoqIHN0ZXBzIGFib3ZlLCBxdWFsaXR5LWNvbnRyb2xsZWQgbWV0YWdlbm9tZSByZWFkcyB3ZXJlIGV4dHJhY3RlZCB1c2luZyBCQk1hcCB0byBnZW5lcmF0ZSBwaWxlLXVwIGZpbGVzIChhdmVyYWdlIHJlYWQgZGVwdGggcGVyIGdlbmUpLCBhbmQgU0FNdG9vbHMgd2FzIHVzZWQgdG8gZXh0cmFjdCBjb3VudHMgYW5kIENEUyBsZW5ndGhzIGZyb20gdGhlIEJCTWFwIG91dHB1dC4KCiMjIyAzLjEuIEltcG9ydCBHZW5lIENvdW50cwpJbiB0aGlzIHNlY3Rpb24sIGFsbCBgRE5BLnBpbGV1cGAgZmlsZXMgYXJlIGltcG9ydGVkIGludG8gdGhlIFIgZW52aXJvbm1lbnQgYW5kIGNvbWJpbmVkIGludG8gdGhlIGZpcnN0ICoqRlVMTCoqIGRhdGFzZXQgdG8gYmUgZnVydGhlciBmb3JtYXR0ZWQgZm9yIGRvd25zdHJlYW0gc3RhdGlzdGljYWwgYW5hbHlzaXMuCgojIyMjIDMuMS4xLiBETkEgUGlsZVVwIEZpbGVzClRoZSBmb2xsb3dpbmcgYEROQS5waWxldXBgIGZpbGVzIChhdmVyYWdlIHJlYWQgZGVwdGggcGVyIGdlbmUpIGZvciBlYWNoIG1ldGFnZW5vbWUgc2FtcGxlIHdlcmUgZ2VuZXJhdGVkIHZpYSB0aGUgQkJNYXAgbW9kdWxlLgoKYGBge3J9CiNTMTA3MTA0IC0tIFdTX1QwX1IxCnBpbGV1cF8xMDcxMDQ8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzEwNF9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzEwNCRTMTA3MTA0IDwtIHBpbGV1cF8xMDcxMDQkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMDQkTWludXNfcmVhZHMKCiNTMTA3MTA1IC0tIFdTX1QwX1IyCnBpbGV1cF8xMDcxMDU8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzEwNV9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzEwNSRTMTA3MTA1IDwtIHBpbGV1cF8xMDcxMDUkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMDUkTWludXNfcmVhZHMKCiNTMTA3MTA2IC0tIFdTX1QwX1IzCnBpbGV1cF8xMDcxMDY8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzEwNl9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzEwNiRTMTA3MTA2IDwtIHBpbGV1cF8xMDcxMDYkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMDYkTWludXNfcmVhZHMKCiNTMTA3MTEwIC0tIFdTX1Q0X1IxCnBpbGV1cF8xMDcxMTA8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzExMF9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzExMCRTMTA3MTEwIDwtIHBpbGV1cF8xMDcxMTAkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMTAkTWludXNfcmVhZHMKCiNTMTA3MTExIC0tIFdTX1Q0X1IyCnBpbGV1cF8xMDcxMTE8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzExMV9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzExMSRTMTA3MTExIDwtIHBpbGV1cF8xMDcxMTEkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMTEkTWludXNfcmVhZHMKCiNTMTA3MTEyIC0tIFdTX1Q0X1IzCnBpbGV1cF8xMDcxMTI8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzExMl9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzExMiRTMTA3MTEyIDwtIHBpbGV1cF8xMDcxMTIkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMTIkTWludXNfcmVhZHMKCiNTMTA3MTEzIC0tIFdTX1QyNF9SMQpwaWxldXBfMTA3MTEzPC1yZWFkLnRhYmxlKCJQaWxldXAuRGF0YS9ETkEuUGlsZXVwL1NhbXBsZV8xMDcxMTNfRE5BLnBpbGV1cCIsIGhlYWRlciA9IFRSVUUpCnBpbGV1cF8xMDcxMTMkUzEwNzExMyA8LSBwaWxldXBfMTA3MTEzJFBsdXNfcmVhZHMgKyBwaWxldXBfMTA3MTEzJE1pbnVzX3JlYWRzCgojUzEwNzExNCAtLSBXU19UMjRfUjIKcGlsZXVwXzEwNzExNDwtcmVhZC50YWJsZSgiUGlsZXVwLkRhdGEvRE5BLlBpbGV1cC9TYW1wbGVfMTA3MTE0X0ROQS5waWxldXAiLCBoZWFkZXIgPSBUUlVFKQpwaWxldXBfMTA3MTE0JFMxMDcxMTQgPC0gcGlsZXVwXzEwNzExNCRQbHVzX3JlYWRzICsgcGlsZXVwXzEwNzExNCRNaW51c19yZWFkcwoKI1MxMDcxMTUgLS0gV1NfVDI0X1IzCnBpbGV1cF8xMDcxMTU8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzExNV9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzExNSRTMTA3MTE1IDwtIHBpbGV1cF8xMDcxMTUkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMTUkTWludXNfcmVhZHMKCiNTMTA3MTA3IC0tIFR1c3NfVDBfUjEKcGlsZXVwXzEwNzEwNzwtcmVhZC50YWJsZSgiUGlsZXVwLkRhdGEvRE5BLlBpbGV1cC9TYW1wbGVfMTA3MTA3X0ROQS5waWxldXAiLCBoZWFkZXIgPSBUUlVFKQpwaWxldXBfMTA3MTA3JFMxMDcxMDcgPC0gcGlsZXVwXzEwNzEwNyRQbHVzX3JlYWRzICsgcGlsZXVwXzEwNzEwNyRNaW51c19yZWFkcwoKI1MxMDcxMDggLS0gVHVzc19UMF9SMgpwaWxldXBfMTA3MTA4PC1yZWFkLnRhYmxlKCJQaWxldXAuRGF0YS9ETkEuUGlsZXVwL1NhbXBsZV8xMDcxMDhfRE5BLnBpbGV1cCIsIGhlYWRlciA9IFRSVUUpCnBpbGV1cF8xMDcxMDgkUzEwNzEwOCA8LSBwaWxldXBfMTA3MTA4JFBsdXNfcmVhZHMgKyBwaWxldXBfMTA3MTA4JE1pbnVzX3JlYWRzCgojUzEwNzExNiAtLSBUdXNzX1Q0X1IxCnBpbGV1cF8xMDcxMTY8LXJlYWQudGFibGUoIlBpbGV1cC5EYXRhL0ROQS5QaWxldXAvU2FtcGxlXzEwNzExNl9ETkEucGlsZXVwIiwgaGVhZGVyID0gVFJVRSkKcGlsZXVwXzEwNzExNiRTMTA3MTE2IDwtIHBpbGV1cF8xMDcxMTYkUGx1c19yZWFkcyArIHBpbGV1cF8xMDcxMTYkTWludXNfcmVhZHMKCiNTMTA3MTE3IC0tIFR1c3NfVDRfUjIKcGlsZXVwXzEwNzExNzwtcmVhZC50YWJsZSgiUGlsZXVwLkRhdGEvRE5BLlBpbGV1cC9TYW1wbGVfMTA3MTE3X0ROQS5waWxldXAiLCBoZWFkZXIgPSBUUlVFKQpwaWxldXBfMTA3MTE3JFMxMDcxMTcgPC0gcGlsZXVwXzEwNzExNyRQbHVzX3JlYWRzICsgcGlsZXVwXzEwNzExNyRNaW51c19yZWFkcwoKI1MxMDcxMTkgLS0gVHVzc19UMjRfUjEKcGlsZXVwXzEwNzExOTwtcmVhZC50YWJsZSgiUGlsZXVwLkRhdGEvRE5BLlBpbGV1cC9TYW1wbGVfMTA3MTE5X0ROQS5waWxldXAiLCBoZWFkZXIgPSBUUlVFKQpwaWxldXBfMTA3MTE5JFMxMDcxMTkgPC0gcGlsZXVwXzEwNzExOSRQbHVzX3JlYWRzICsgcGlsZXVwXzEwNzExOSRNaW51c19yZWFkcwoKI1MxMDcxMjEgLS0gVHVzc19UMjRfUjMKcGlsZXVwXzEwNzEyMTwtcmVhZC50YWJsZSgiUGlsZXVwLkRhdGEvRE5BLlBpbGV1cC9TYW1wbGVfMTA3MTIxX0ROQS5waWxldXAiLCBoZWFkZXIgPSBUUlVFKQpwaWxldXBfMTA3MTIxJFMxMDcxMjEgPC0gcGlsZXVwXzEwNzEyMSRQbHVzX3JlYWRzICsgcGlsZXVwXzEwNzEyMSRNaW51c19yZWFkcwpgYGAKCiMjIyMgMy4xLjIuIEZ1bGwgRE5BIERhdGFzZXQKCkluIHRoZSBwcmV2aW91cyBzdGVwLCBlYWNoIGBETkEucGlsZXVwYCBmaWxlIHdhcyBpbXBvcnRlZCBhbmQgYW4gYWRkaXRpb25hbCBjb2x1bW4gd2FzIGFkZGVkIHRoYXQgc3VtbWVkIHRoZSAqKiJQbHVzX3JlYWRzIioqIGFuZCB0aGUgKipNaW51c19yZWFkcyoqLiBUaGUgc3VtIGNvbHVtbiBpbiBlYWNoIGBETkEucGlsZXVwYCBmaWxlIHdhcyBuYW1lZCBhZnRlciB0aGUgYEROQS5waWxldXBgIHNhbXBsZSBuYW1lIChlLmcuICoqIlMxMDgzNzkiKiopLiBBbGwgYEROQS5waWxldXBgIGZpbGVzIGNvbnRhaW4gaWRlbnRpY2FsIGdlbmVjYWxscyBpbiBhbiBpZGVudGljYWwgb3JkZXIgYWxsb3dpbmcgdXMgdG8gZXh0cmFjdCB0aGUgZ2VuZWNhbGwgSUQgYW5kIGdlbmVjYWxsIExlbmd0aCBjb2x1bW5zIGZyb20gYSBzaW5nbGUgc2FtcGxlICgqKlMxMDcxMDQqKiksIGFsb25nIHdpdGggdGhlIHN1bW1lZCBjb3VudCBjb2x1bW4gb2YgZWFjaCBzYW1wbGUsIHRvIGNyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgdGhhdCByZXByZXNlbnRzIHRoZSBpbml0aWFsLCAqKkZVTEwqKiBkYXRhc2V0IGZvciBkb3duc3RyZWFtIGFuYWx5c2VzOgoKYGBge3J9CmN0c19kbmFfYWxsIDwtIGRhdGEuZnJhbWUocGlsZXVwXzEwNzEwNCRJRCwgcGlsZXVwXzEwNzEwNCRMZW5ndGgsIHBpbGV1cF8xMDcxMDQkUzEwNzEwNCwgcGlsZXVwXzEwNzEwNSRTMTA3MTA1LCBwaWxldXBfMTA3MTA2JFMxMDcxMDYsIHBpbGV1cF8xMDcxMTAkUzEwNzExMCwgcGlsZXVwXzEwNzExMSRTMTA3MTExLCBwaWxldXBfMTA3MTEyJFMxMDcxMTIsIHBpbGV1cF8xMDcxMTMkUzEwNzExMywgcGlsZXVwXzEwNzExNCRTMTA3MTE0LCBwaWxldXBfMTA3MTE1JFMxMDcxMTUsIHBpbGV1cF8xMDcxMDckUzEwNzEwNywgcGlsZXVwXzEwNzEwOCRTMTA3MTA4LCBwaWxldXBfMTA3MTE2JFMxMDcxMTYsIHBpbGV1cF8xMDcxMTckUzEwNzExNywgcGlsZXVwXzEwNzExOSRTMTA3MTE5LCBwaWxldXBfMTA3MTIxJFMxMDcxMjEpCgpuYW1lcyhjdHNfZG5hX2FsbCkgPC0gYygiSUQiLCAiTGVuZ3RoIiwgIlMxMDcxMDQiLCAiUzEwNzEwNSIsICJTMTA3MTA2IiwgIlMxMDcxMTAiLCAiUzEwNzExMSIsICJTMTA3MTEyIiwgIlMxMDcxMTMiLCAiUzEwNzExNCIsICJTMTA3MTE1IiwgIlMxMDcxMDciLCAiUzEwNzEwOCIsICJTMTA3MTE2IiwgIlMxMDcxMTciLCAiUzEwNzExOSIsICJTMTA3MTIxIikKYGBgCgojIyMgMy4yLiBJbXBvcnQgR2VuZSBBbm5vdGF0aW9ucwpUaGUgS0VHRyBGdW5jdGlvbnMgZmlsZSAoR2hvc3RLb2FsYSkgYW5kIEtFR0cgVGF4b25vbXkgZmlsZSAoR2hvc3RLb2FsYSkgd2VyZSBpbXBvcnRlZCBhbmQgdGhlIGZ1bmN0aW9uYWwgYW5kIHRheG9ub21pYyBhbm5vdGF0aW9ucyB3ZXJlIG1hdGNoZWQgdG8gdGhlaXIgY29ycmVzcG9uZGluZyBnZW5lY2FsbCBJRC4KCiMjIyMgMy4yLjEuIEtFR0cgUmVmZXJlbmNlCkZpcnN0LCBhIEtFR0cgcmVmZXJlbmNlIGZpbGUgd2FzIGltcG9ydGVkIHdpdGggYWRkaXRpb25hbCBLRUdHIFRpZXIgcGF0aHdheXMgdGhhdCBwcm92aWRlIGFkZGl0aW9uYWwsIHVzZWZ1bCwgZnVuY3Rpb25hbCBjYXRlZ29yaWVzIGZvciBkb3duc3RyZWFtIGFuYWx5c2VzLiAgVGhlIFRpZXIgSUksIElJSSwgYW5kIElWIGNhdGVnb3JpZXMgd2VyZSBtZXJnZWQgdG8gdGhlIEdob3N0S29hbGEgS0VHRyBmdW5jdGlvbmFsIGFubm90YXRpb25zIGluIHN1YnNlcXVlbnQgc3RlcHMuCgpgYGB7cn0KIyBJbXBvcnQgS09fT3J0aG9sb2d5LnR4dCByZWZlcmVuY2UgZmlsZQpLT19yZWY8LXJlYWQudGFibGUoZmlsZT0nQW5ub3RhdGlvbnMuRGF0YS9LT19PcnRob2xvZ3kudHh0Jywgc2VwPSdcdCcsIHF1b3RlPSIiLCBmaWxsPVRSVUUsIGhlYWRlciA9IEZBTFNFKQoKIyBSZW5hbWUgY29sdW1uIGhlYWRlcnMKbmFtZXMoS09fcmVmKTwtYygiVGllcl9JSSIsIlRpZXJfSUlJIiwiVGllcl9JViIsIktFR0ciKQoKIyBTZXBhcmF0ZSAiS0VHRyIgY29sdW1uIGludG8gIktPIiBhbmQgIkFubm90YXRpb24iIGNvbHVtbnMKS09fcmVmPC1LT19yZWYgJT4lIHNlcGFyYXRlKEtFR0csIGMoIktPX0FjY2Vzc2lvbiIsIkFubm90YXRpb24iKSwgIiAiLCBleHRyYT0ibWVyZ2UiKQoKIyBGdXJ0aGVyIHNlcGFyYXRhZSAiQW5ub3RhdGlvbiIgY29sdW1uIGludG8gIlN5bWJvbCIgYW5kICJGdW5jdGlvbiIgY29sdW1ucwpLT19yZWY8LUtPX3JlZiAlPiUgc2VwYXJhdGUoQW5ub3RhdGlvbiwgYygiS09fU3ltYm9sIiwiS09fRnVuY3Rpb24iKSwgIjsgIiwgZXh0cmE9Im1lcmdlIikKYGBgCgojIyMjIDMuMi4yLiBLRUdHIEZ1bmN0aW9ucwoKVGhlcmUgYXJlIDMsOTE3LDYxNiB0b3RhbCB1bmlxdWUgRE5BLWJhc2VkIGdlbmVjYWxscyBpbiB0aGUgbWV0YWdlbm9taWMgZGF0YXNldC4gIFRoZSBHaG9zdEtPQUxBIEtFR0cgZnVuY3Rpb25hbCBhbm5vdGF0aW9ucyBmaWxlICAoIioqRE5BX2RhdGFfYmJub3JtX2FudmlvX2NvbnRpZ3NfYW5ub3RhdGlvbnMudHN2KioiKSBjb250YWlucyBhbm5vdGF0aW9ucyBmb3IgMSwzODksNTE4IHVuaXF1ZSBETkEtYmFzZWQgZ2VuZWNhbGxzLiAgVGhpcyBpbmRpY2F0ZXMgdGhhdCAqKjM1LjUlKiogb2YgdGhlIHRvdGFsIHVuaXF1ZSBETkEtYmFzZWQgZ2VuZWNhbGxzIGNhbiBiZSBmdW5jdGlvbmFsbHkgYW5ub3RhdGVkLiAgVGhhdCBhbHNvIG1lYW5zIHRoYXQgKio2NC41JSoqIG9mIHVuaXF1ZSBETkEtYmFzZWQgZ2VuZWNhbGxzIGNhbm5vdCBiZSBhbm5vdGF0ZWQgYW5kIHdpbGwgbm90IGJlIGluY2x1ZGVkIGluIGRvd25zdHJlYW0gYW5hbHlzZXMuIEhlcmUsIHRoZSB1bmlxdWUgZ2VuZWNhbGwgZnVuY3Rpb25hbCBhbm5vdGF0aW9ucyB3aWxsIGJlIG1hdGNoZWQgdG8gdGhlIHNhbWUgdW5pcXVlIGdlbmVjYWxscyBpbiB0aGUgRE5BLWJhc2VkIG1ldGFnZW5vbWljIGRhdGFzZXQuCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIEltcG9ydCB0aGUgS0VHRyBGdW5jdGlvbmFsIEFubm90YXRpb25zIGZpbGUgdGhhdCB3YXMgZXhwb3J0ZWQgZnJvbSB0aGUgQW52aSdvIEROQSBjb250aWdzIGRhdGFiYXNlCktlZ2dBbnZpbzwtcmVhZC50YWJsZShmaWxlPSdBbm5vdGF0aW9ucy5EYXRhL0ROQV9kYXRhX2Jibm9ybV9hbnZpb19jb250aWdzX2Fubm90YXRpb25zLnRzdicsIHNlcD0nXHQnLCBxdW90ZSA9ICIiLCBmaWxsID0gVFJVRSwgaGVhZGVyID0gVFJVRSkKCiMgUmVuYW1lIGNvbHVtbiBoZWFkZXJzCm5hbWVzKEtlZ2dBbnZpbyk8LWMoIklEIiwiU291cmNlIiwiQWNjZXNzaW9uIiwiRnVuY3Rpb24iLCJlLXZhbHVlIikKCiMgU2VwYXJhdGUgIkZ1bmN0aW9uIiBjb2x1bW4gaW50byAiU3ltYm9sIiBhbmQgIkZ1bmN0aW9uIiBjb2x1bW5zCktlZ2dBbnZpbzwtS2VnZ0FudmlvICU+JSBzZXBhcmF0ZShGdW5jdGlvbiwgYygiU3ltYm9sIiwiRnVuY3Rpb24iKSwgIjsgIiwgZXh0cmE9Im1lcmdlIikKCiMgQWRkICJnZW5lY2FsbF8iIHRvIHRoZSBiZWdpbm5pbmcgb2YgZWFjaCBnZW5lIElEIHZhbHVlIHRvIG1hdGNoIHdpdGggZG93bnN0cmVhbSBhbmFseXNlcwpLZWdnQW52aW8kSUQgPC0gcGFzdGUoImdlbmVjYWxsIiwgS2VnZ0FudmlvJElELCBzZXA9Il8iKQoKIyBBZGQgIktPX1N5bWJvbCIgY2F0ZWdvcnkgdG8gdGhlIGRhdGFzZXQsIG1hdGNoZWQgYnkgS08ncyBiZXR3ZWVuIHRoZSBLT19yZWYgZmlsZSBhbmQgS2VnZ0FudmlvCktlZ2dBbnZpbyRLT19TeW1ib2wgPSBLT19yZWZbbWF0Y2goS2VnZ0FudmlvJEFjY2Vzc2lvbiwgS09fcmVmJEtPX0FjY2Vzc2lvbiksICJLT19TeW1ib2wiXQoKIyBBZGQgIktPX0Z1bmN0aW9uIiBjYXRlZ29yeSB0byB0aGUgZGF0YXNldCwgbWF0Y2hlZCBieSBLTydzIGJldHdlZW4gdGhlIEtPX3JlZiBmaWxlIGFuZCBLZWdnQW52aW8KS2VnZ0FudmlvJEtPX0Z1bmN0aW9uID0gS09fcmVmW21hdGNoKEtlZ2dBbnZpbyRBY2Nlc3Npb24sIEtPX3JlZiRLT19BY2Nlc3Npb24pLCAiS09fRnVuY3Rpb24iXQoKIyBBZGQgIlRpZXJfSUkiIGNhdGVnb3J5IHRvIHRoZSBkYXRhc2V0LCBtYXRjaGVkIGJ5IEtPJ3MgYmV0d2VlbiB0aGUgS09fcmVmIGZpbGUgYW5kIEtlZ2dBbnZpbwpLZWdnQW52aW8kVGllcl9JSSA9IEtPX3JlZlttYXRjaChLZWdnQW52aW8kQWNjZXNzaW9uLCBLT19yZWYkS09fQWNjZXNzaW9uKSwgIlRpZXJfSUkiXQoKIyBBZGQgIlRpZXJfSUlJIiBjYXRlZ29yeSB0byB0aGUgZGF0YXNldCwgbWF0Y2hlZCBieSBLTydzIGJldHdlZW4gdGhlIEtPX3JlZiBmaWxlIGFuZCBLZWdnQW52aW8KS2VnZ0FudmlvJFRpZXJfSUlJID0gS09fcmVmW21hdGNoKEtlZ2dBbnZpbyRBY2Nlc3Npb24sIEtPX3JlZiRLT19BY2Nlc3Npb24pLCAiVGllcl9JSUkiXQoKIyBBZGQgIlRpZXJfSVYiIGNhdGVnb3J5IHRvIHRoZSBkYXRhc2V0LCBtYXRjaGVkIGJ5IEtPJ3MgYmV0d2VlbiB0aGUgS09fcmVmIGZpbGUgYW5kIEtlZ2dBbnZpbwpLZWdnQW52aW8kVGllcl9JViA9IEtPX3JlZlttYXRjaChLZWdnQW52aW8kQWNjZXNzaW9uLCBLT19yZWYkS09fQWNjZXNzaW9uKSwgIlRpZXJfSVYiXQoKIyBLZWVwIHRoZSBGdW5jdGlvbiBjYXRlZ29yeSBmcm9tIHRoZSBLTyBSZWZlcmVuY2UgZmlsZSB0byBwb3RlbnRpYWxseSBmaWxsIGluIGdhcHMgaW4gS2VnZ0FudmlvIGFubm90YXRpb25zIChtYW55IEtPJ3MgbGFiZWxlZCBhcyAiTm9uZSIsIGJ1dCB0aGUgS08gc2hvdWxkIG1hdGNoIGEga25vd24gZnVuY3Rpb24gZnJvbSB0aGUgcmVmZXJlbmNlIGZpbGUpLgpLZWdnRnVuY3Rpb248LWRhdGEuZnJhbWUoS2VnZ0FudmlvJElELEtlZ2dBbnZpbyRBY2Nlc3Npb24sS2VnZ0FudmlvJFN5bWJvbCxLZWdnQW52aW8kS09fRnVuY3Rpb24sS2VnZ0FudmlvJFRpZXJfSUksS2VnZ0FudmlvJFRpZXJfSUlJLEtlZ2dBbnZpbyRUaWVyX0lWKQpuYW1lcyhLZWdnRnVuY3Rpb24pPC1jKCJJRCIsIktPIiwiU3ltYm9sIiwiRnVuY3Rpb24iLCJUaWVyX0lJIiwiVGllcl9JSUkiLCJUaWVyX0lWIikKICAKIyBNZXJnZSB0aGUgS08sIFN5bWJvbCwgRnVuY3Rpb24sIGFuZCBhbGwgVGllciBjb2x1bW5zIGludG8gc2luZ2xlICJDb21iaW5lZCIgY29sdW1uIGZvciBzb21lIGRvd25zdHJlYW0gYW5hbHlzZXMKS2VnZ0Z1bmN0aW9uJENvbWJpbmVkPC1wYXN0ZShLZWdnRnVuY3Rpb24kS08sICI6IiwgS2VnZ0Z1bmN0aW9uJFN5bWJvbCwgIjoiLCBLZWdnRnVuY3Rpb24kRnVuY3Rpb24sICI6IiwgS2VnZ0Z1bmN0aW9uJFRpZXJfSUksICI6IiwgS2VnZ0Z1bmN0aW9uJFRpZXJfSUlJLCAiOiIsIEtlZ2dGdW5jdGlvbiRUaWVyX0lWKQoKIyBLZWVwIGp1c3QgIklEIiBhbmQgIkNvbWJpbmVkIiBjb2x1bW5zIGZvciB1c2Ugd2l0aCBzb21lIGRvd25zdHJlYW0gYW5hbHlzZXMKS2VnZ0RhdGE8LWRhdGEuZnJhbWUoS2VnZ0Z1bmN0aW9uJElELCBLZWdnRnVuY3Rpb24kQ29tYmluZWQpCm5hbWVzKEtlZ2dEYXRhKTwtYygiSUQiLCJLRUdHIikKYGBgCgojIyMjIDMuMi4zLiBLRUdHIFRheG9ub215CgpUaGVyZSBhcmUgMyw5MTcsNjE2IHRvdGFsIHVuaXF1ZSBETkEtYmFzZWQgZ2VuZWNhbGxzIGluIHRoZSBtZXRhZ2Vub21pYyBkYXRhc2V0LiBUaGUgR2hvc3RLb2FsYSBLRUdHIHRheG9ub215IGZpbGUgKCIqKktlZ2dUYXhvbm9teS50eHQqKiIpIGNvbnRhaW5zIGFubm90YXRpb25zIGZvciAzLDkxMiwyNTMgdW5pcXVlIEROQS1iYXNlZCBnZW5lY2FsbHMuICBUaGlzIGluZGljYXRlcyB0aGF0ICoqOTkuOSUqKiBvZiB0aGUgdG90YWwgdW5pcXVlIEROQS1iYXNlZCBnZW5lY2FsbHMgY2FuIGJlIHRheG9ub21pY2FsbHkgYW5ub3RhdGVkLiBIZXJlLCB0aGUgdW5pcXVlIGdlbmVjYWxsIHRheG9ub21pYyBhbm5vdGF0aW9ucyB3aWxsIGJlIG1hdGNoZWQgdG8gdGhlIHNhbWUgdW5pcXVlIGdlbmVjYWxscyBpbiB0aGUgRE5BLWJhc2VkIG1ldGFnZW5vbWljIGRhdGFzZXQuCgpgYGB7cn0KI0ltcG9ydCBLZWdnVGF4b25vbXkudHh0IGZyb20gR2hvc3RLb2FsYQpLZWdnVGF4YTwtcmVhZC50YWJsZSgiQW5ub3RhdGlvbnMuRGF0YS9LZWdnVGF4b25vbXkudHh0IiwgaGVhZGVyID0gVFJVRSwgZmlsbCA9IFRSVUUpCm5hbWVzKEtlZ2dUYXhhKTwtYygiSUQiLCJEb21haW4iLCJQaHlsdW0iLCJDbGFzcyIsIk9yZGVyIiwiRmFtaWx5IiwiR2VudXMiLCJTcGVjaWVzIikKCiMgTWVyZ2UgdGhlIHRheG9ub21pYyBjbGFzc2VzIGludG8gYSBzaW5nbGUgY29sdW1uCktlZ2dUYXhhJFRheG9ub215IDwtIHBhc3RlKEtlZ2dUYXhhJERvbWFpbiwgIjoiLCBLZWdnVGF4YSRQaHlsdW0sICI6IiwgS2VnZ1RheGEkQ2xhc3MsICI6IiwgS2VnZ1RheGEkT3JkZXIsICI6IiwgS2VnZ1RheGEkRmFtaWx5LCAiOiIsIEtlZ2dUYXhhJEdlbnVzLCAiOiIsIEtlZ2dUYXhhJFNwZWNpZXMpCgojIE5vdyBrZWVwIGp1c3QgIklEIiBhbmQgIlRheG9ub215IgpLZWdnVGF4YSA8LSBkYXRhLmZyYW1lKEtlZ2dUYXhhJElELCBLZWdnVGF4YSRUYXhvbm9teSkKbmFtZXMoS2VnZ1RheGEpPC1jKCJJRCIsIlRheG9ub215IikKCiMgQWRkICJnZW5lY2FsbF8iIHRvIHRoZSBiZWdpbm5pbmcgb2YgZWFjaCBnZW5lIElEIHZhbHVlIHRvIG1hdGNoIHdpdGggZG93bnN0cmVhbSBhbmFseXNlcwpLZWdnVGF4YSRJRDwtcGFzdGUoImdlbmVjYWxsIiwgS2VnZ1RheGEkSUQsIHNlcD0iXyIpCmBgYAoKIyMgNC4gR2VuZSBGaWx0ZXJpbmcKClRoZSAqKkZVTEwqKiBETkEgQ1RTIGRhdGFzZXQgd2FzIGFzc2VtYmxlZCBhcyBhIHNpbmdsZSBkYXRhZnJhbWUgKGNvbHVtbnM6IFsxXSBnZW5lY2FsbCwgWzJdIGxlbmd0aCwgWzMtMTRdIG1ldGFnZW5vbWUgU2FtcGxlczsgcm93czogMyw5MTcsNjE2IHVuaXF1ZSAiZ2VuZWNhbGxzIikuICBOb3csIHJldGFpbiBvbmx5IHRob3NlIGdlbmVjYWxscyB3aXRoIGEgdmFsdWUgZ3JlYXRlciB0aGFuIHplcm8gaW4gYW55IHNpbmdsZSBzYW1wbGUuICBUaGlzIGluZGljYXRlcyB0aGF0IHRoZXNlIGdlbmVzIHdlcmUgcHJlc2VudCB1bmRlciBhdCBsZWFzdCBPTkUgdHJlYXRtZW50IGluIHRoZSBleHBlcmltZW50IChpLmUuLCBwb3RlbnRpYWwgZXhwcmVzc2lvbikuCgojIyMgNC4xLiBQb3RlbnRpYWwgR2VuZXMKClN1YnNhbXBsZSB0aGUgdW5pcXVlIGdlbmVjYWxscyB0aGF0IGhhdmUgZ3JlYXRlciB0aGFuIHplcm8gcmF3IHJlYWQgY291bnRzICgiUG90ZW50aWFsIEdlbmVzIikgYWNyb3NzIGFsbCBzYW1wbGVzLgoKYGBge3J9CiNjdHNfZG5hX3BvdGVudGlhbApjdHNfZG5hX3BvdGVudGlhbCA8LSBzdWJzZXQoY3RzX2RuYV9hbGwsIFMxMDcxMDQgPiAwIHwgUzEwNzEwNSA+IDAgfCBTMTA3MTA2ID4gMCB8IFMxMDcxMTAgPiAwIHwgUzEwNzExMSA+IDAgfCBTMTA3MTEyID4gMCB8IFMxMDcxMTMgPiAwIHwgUzEwNzExNCA+IDAgfCBTMTA3MTE1ID4gMCB8IFMxMDcxMDcgPiAwIHwgUzEwNzEwOCA+IDAgfCBTMTA3MTE2ID4gMCB8IFMxMDcxMTcgPiAwIHwgUzEwNzExOSA+IDAgfCBTMTA3MTIxID4gMCwgc2VsZWN0PWMoSUQsTGVuZ3RoLFMxMDcxMDQsUzEwNzEwNSxTMTA3MTA2LFMxMDcxMTAsUzEwNzExMSxTMTA3MTEyLFMxMDcxMTMsUzEwNzExNCxTMTA3MTE1LFMxMDcxMDcsUzEwNzEwOCxTMTA3MTE2LFMxMDcxMTcsUzEwNzExOSxTMTA3MTIxKSkKYGBgCgpBZGQgZnVuY3Rpb25hbCBhbmQgdGF4b25vbWljIGFubm90YXRpb25zIHRvIGVhY2ggdW5pcXVlIGdlbmVjYWxsIHdpdGhpbiB0aGUgIlBvdGVudGlhbCIgc3ViZGF0YS4KCmBgYHtyfQojIFBvdGVudGlhbCBHZW5lcyBGdW5jdGlvbmFsIGFuZCBUYXhvbm9taWMgQW5ub3RhdGlvbnMKY3RzX2RuYV9wb3RlbnRpYWwkS0VHRyA9IEtlZ2dEYXRhW21hdGNoKGN0c19kbmFfcG90ZW50aWFsJElELCBLZWdnRGF0YSRJRCksICJLRUdHIl0KY3RzX2RuYV9wb3RlbnRpYWwkVGF4b25vbXkgPSBLZWdnVGF4YVttYXRjaChjdHNfZG5hX3BvdGVudGlhbCRJRCwgS2VnZ1RheGEkSUQpLCAiVGF4b25vbXkiXQoKIyBQb3RlbnRpYWwgQW5ub3RhdGVkIEdlbmVzCmN0c19kbmFfcG90X2FubjwtbmEub21pdChjdHNfZG5hX3BvdGVudGlhbCwgY29scz0iS0VHRyIpCmBgYAoKIyMjIDQuMi4gUG90ZW50aWFsIEFubm90YXRlZCBHZW5lcwoKKioqRnJvbSB0aGlzIHBvaW50KioqLCB3ZSAgcmV0YWluIG9ubHkgdGhvc2UgZ2VuZWNhbGxzIHRoYXQgd2VyZSBwb3RlbnRpYWxseSBleHByZXNzZWQgKioqYW5kKioqIGhhdmUgYSBLRUdHIGZ1bmN0aW9uYWwgYW5ub3RhdGlvbi4gU3RhcnQgYnkgc2VwYXJhdGluZyB0aGUgS0VHRyBjYXRlZ29yaWVzIGludG8gdW5pcXVlIGNvbHVtbnMuIFJlbW92ZSBhbnkgZ2VuZWNhbGwgd2hvc2Ugc3ltYm9sIGFubm90YXRpb24gaXMgIk5vbmUiLiBGdXJ0aGVyIHJlbW92ZSBhbnkgZ2VuZWNhbGwgYW5ub3RhdGVkIGFzIFRpZXIgSUkgIk9yZ2FuaXNtYWwgU3lzdGVtcyIgb3IgIkh1bWFuIERpc2Vhc2VzIi4KCmBgYHtyfQojIFNlcGFyYXRlICJLRUdHIiBjb2x1bW4gaW50byAiS08iLCAiU3ltYm9sIiwgIkZ1bmN0aW9uIiwgIlRpZXJfSUkiLCAiVGllcl9JSUkiLCBhbmQgIlRpZXJfSVYiIGNvbHVtbnMKY3RzX2RuYV9wb3RfYW5uPC1jdHNfZG5hX3BvdF9hbm4gJT4lIHNlcGFyYXRlKEtFR0csIGMoIktPIiwiU3ltYm9sIiwiRnVuY3Rpb24iLCJUaWVyX0lJIiwiVGllcl9JSUkiLCJUaWVyX0lWIiksICI6ICIsIGV4dHJhPSJtZXJnZSIpCgojIFJlbW92ZSBLTydzIHdpdGggIk5vbmUiIGFzIHRoZSAiU3ltYm9sIiBhbm5vdGF0aW9uCmN0c19kbmFfcG90X2FubjwtY3RzX2RuYV9wb3RfYW5uWyFncmVwbCgiTm9uZSIsIGN0c19kbmFfcG90X2FubiRTeW1ib2wpLF0KCiMgUmVtb3ZlIEtPJ3Mgd2l0aCBUaWVyIElJIGNhdGVnb3J5ICJPcmdhbmlzbWFsIFN5c3RlbXMiCmN0c19kbmFfcG90X2FubjwtY3RzX2RuYV9wb3RfYW5uWyFncmVwbCgiT3JnYW5pc21hbCBTeXN0ZW1zICIsIGN0c19kbmFfcG90X2FubiRUaWVyX0lJKSxdCgojIFJlbW92ZSBLTydzIHdpdGggVGllciBJSSBjYXRlZ29yeSAiSHVtYW4gRGlzZWFzZXMiCmN0c19kbmFfcG90X2FubjwtY3RzX2RuYV9wb3RfYW5uWyFncmVwbCgiSHVtYW4gRGlzZWFzZXMgIiwgY3RzX2RuYV9wb3RfYW5uJFRpZXJfSUkpLF0KYGBgCgpTZXBhcmF0ZSB0aGUgVGF4b25vbXkgY2F0ZWdvcmllcyBpbnRvIHVuaXF1ZSBjb2x1bW5zLiBSZW1vdmUgYW55IGdlbmVjYWxsIHdob3NlIHRheG9ub215IGlzIG91dHNpZGUgb2YgIkFyY2hhZWEiLCAiQmFjdGVyaWEiLCBvciAiRnVuZ2kiLgoKYGBge3J9CiMgU2VwYXJhdGUgIlRheG9ub215IiBjb2x1bW4gaW50byAiS2luZ2RvbSIsICJQaHlsdW0iLCAiQ2xhc3MiLCAiT3JkZXIiLCAiRmFtaWx5IiwgIkdlbnVzIiwgYW5kICJTcGVjaWVzIiBjb2x1bW5zCmN0c19kbmFfcG90X2FubjwtY3RzX2RuYV9wb3RfYW5uICU+JSBzZXBhcmF0ZShUYXhvbm9teSwgYygiS2luZ2RvbSIsIlBoeWx1bSIsIkNsYXNzIiwiT3JkZXIiLCJGYW1pbHkiLCJHZW51cyIsIlNwZWNpZXMiKSwgIjogIiwgZXh0cmE9Im1lcmdlIikKCiMgUmVtb3ZlIEtPJ3Mgd2l0aCAiYWciIGFzIHRoZSAiS2luZ2RvbSIgYW5ub3RhdGlvbgpjdHNfZG5hX3BvdF9hbm48LWN0c19kbmFfcG90X2FublshZ3JlcGwoImFnIiwgY3RzX2RuYV9wb3RfYW5uJEtpbmdkb20pLF0KCiMgUmVtb3ZlIEtPJ3Mgd2l0aCAiQW5pbWFscyIgYXMgdGhlICJLaW5nZG9tIiBhbm5vdGF0aW9uCmN0c19kbmFfcG90X2FubjwtY3RzX2RuYV9wb3RfYW5uWyFncmVwbCgiQW5pbWFscyIsIGN0c19kbmFfcG90X2FubiRLaW5nZG9tKSxdCgojIFJlbW92ZSBLTydzIHdpdGggIlBsYW50cyIgYXMgdGhlICJLaW5nZG9tIiBhbm5vdGF0aW9uCmN0c19kbmFfcG90X2FubjwtY3RzX2RuYV9wb3RfYW5uWyFncmVwbCgiUGxhbnRzIiwgY3RzX2RuYV9wb3RfYW5uJEtpbmdkb20pLF0KCiMgUmVtb3ZlIEtPJ3Mgd2l0aCAiUHJvdGlzdHMiIGFzIHRoZSAiS2luZ2RvbSIgYW5ub3RhdGlvbgpjdHNfZG5hX3BvdF9hbm48LWN0c19kbmFfcG90X2FublshZ3JlcGwoIlByb3Rpc3RzIiwgY3RzX2RuYV9wb3RfYW5uJEtpbmdkb20pLF0KCiNSZS1tZXJnZSB0aGUgVGF4b25vbXkgY29sdW1ucyBmb3IgZG93bnN0cmVhbSBhbmFseXNpcwpjdHNfZG5hX3BvdF9hbm4kVGF4b25vbXkgPC0gcGFzdGUoY3RzX2RuYV9wb3RfYW5uJEtpbmdkb20sICI6IiwgY3RzX2RuYV9wb3RfYW5uJFBoeWx1bSwgIjoiLCBjdHNfZG5hX3BvdF9hbm4kQ2xhc3MsICI6IiwgY3RzX2RuYV9wb3RfYW5uJE9yZGVyLCAiOiIsIGN0c19kbmFfcG90X2FubiRGYW1pbHksICI6IiwgY3RzX2RuYV9wb3RfYW5uJEdlbnVzLCAiOiIsIGN0c19kbmFfcG90X2FubiRTcGVjaWVzKQpgYGAKCiMjIDUuIEdlbmUgTm9ybWFsaXphdGlvbgoKKipHUE0gTm9ybWFsaXphdGlvbjoqKiBDb252ZXJ0cyByYXcgRE5BIGdlbmUgY291bnRzIHRvICoqKkdlbmVzIHBlciBNaWxsaW9uKioqLiAgR1BNIGZvbGxvd3MgdGhlIHNhbWUgbWV0aGRzIGFzICoqVFBNKiogKFRyYW5zY3JpcHRzIHBlciBNaWxsaW9uKSBkZXNjcmliZWQgYnkgW1dhZ25lciBldCBhbC4gMjAxMl0oaHR0cHM6Ly9saW5rLnNwcmluZ2VyLmNvbS9hcnRpY2xlLzEwLjEwMDcvczEyMDY0LTAxMi0wMTYyLTMpIGFuZCB1c2VkIHRvIG5vcm1hbGl6ZSBSTkEgZ2VuZSBjb3VudHMgaW4gdGhlIG1ldGF0cmFuc2NyaXB0b21lcyBzZWN0aW9uIGJlbG93LgoKMS4gKipDYWxjdWxhdGUgVGcqKjogVGcgPSBSZWFkIENvdW50IHggQXZlcmFnZSBSZWFkIExlbmd0aCAgLyBHZW5lIExlbmd0aAogICAgKyAqKipSZWFkIENvdW50KioqOiAqbnVtYmVyIG9mIHJlYWRzIG1hcHBlZCB0byBlYWNoIHVuaXF1ZSBnZW5lY2FsbCoKICAgICsgKioqQXZlcmFnZSBSZWFkIExlbmd0aCoqKjogKkF2ZXJhZ2UgcmVhZCBsZW5ndGggKGJldHdlZW4gMTM5LTE0MSBicCkgd2l0aGluIGVhY2ggc2FtcGxlIGZyb20gc2VxdWVuY2VzIHRoYXQgcGFzc2VkIFFDKgogICAgKyAqKipHZW5lIExlbmd0aCoqKjogKkxlbmd0aCBvZiBlYWNoIHVuaXF1ZSBnZW5lY2FsbCoKMi4gKipDb252ZXJ0IFRnIGludG8gR1BNIGJ5IHNhbXBsZSoqOiBHUE0gPSBUZyB4IDFlKzA2IC8gc3VtKFRnKQogICAgKyAqKipUaGUgc3VtIG9mIEdQTSB2YWx1ZXMgaW4gZWFjaCBzYW1wbGUgd2lsbCBlcXVhbCAxLDAwMCwwMDAqKioKCiMjIyA1LjEuIENhbGN1bGF0ZSBUZyBWYWx1ZXMKCkNhbGN1bGF0ZSBUZyB2YWx1ZXMgYnkgbXVsdGlwbHlpbmcgdGhlIHJlYWQgY291bnQgb2YgZWFjaCBnZW5lY2FsbCBieSB0aGUgYXZlcmFnZSByZWFkIGxlbmd0aCB3aXRoaW4gZWFjaCBzYW1wbGUsIHRoZW4gZGl2aWRlIGJ5IHRoZSBnZW5lIGxlbmd0aCBvZiBlYWNoIGdlbmVjYWxsLgoKYGBge3J9CmN0c19kbmFfcG90X2FubiRTMTA3MTA0X1RnPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDQgKiAxMzkpIC8gY3RzX2RuYV9wb3RfYW5uJExlbmd0aApjdHNfZG5hX3BvdF9hbm4kUzEwNzEwNV9UZzwtKGN0c19kbmFfcG90X2FubiRTMTA3MTA1ICogMTQwKSAvIGN0c19kbmFfcG90X2FubiRMZW5ndGgKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDZfVGc8LShjdHNfZG5hX3BvdF9hbm4kUzEwNzEwNiAqIDE0MSkgLyBjdHNfZG5hX3BvdF9hbm4kTGVuZ3RoCmN0c19kbmFfcG90X2FubiRTMTA3MTEwX1RnPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTAgKiAxNDApIC8gY3RzX2RuYV9wb3RfYW5uJExlbmd0aApjdHNfZG5hX3BvdF9hbm4kUzEwNzExMV9UZzwtKGN0c19kbmFfcG90X2FubiRTMTA3MTExICogMTQxKSAvIGN0c19kbmFfcG90X2FubiRMZW5ndGgKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTJfVGc8LShjdHNfZG5hX3BvdF9hbm4kUzEwNzExMiAqIDE0MSkgLyBjdHNfZG5hX3BvdF9hbm4kTGVuZ3RoCmN0c19kbmFfcG90X2FubiRTMTA3MTEzX1RnPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTMgKiAxNDEpIC8gY3RzX2RuYV9wb3RfYW5uJExlbmd0aApjdHNfZG5hX3BvdF9hbm4kUzEwNzExNF9UZzwtKGN0c19kbmFfcG90X2FubiRTMTA3MTE0ICogMTQwKSAvIGN0c19kbmFfcG90X2FubiRMZW5ndGgKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTVfVGc8LShjdHNfZG5hX3BvdF9hbm4kUzEwNzExNSAqIDE0MSkgLyBjdHNfZG5hX3BvdF9hbm4kTGVuZ3RoCmN0c19kbmFfcG90X2FubiRTMTA3MTA3X1RnPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDcgKiAxNDEpIC8gY3RzX2RuYV9wb3RfYW5uJExlbmd0aApjdHNfZG5hX3BvdF9hbm4kUzEwNzEwOF9UZzwtKGN0c19kbmFfcG90X2FubiRTMTA3MTA4ICogMTQxKSAvIGN0c19kbmFfcG90X2FubiRMZW5ndGgKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTZfVGc8LShjdHNfZG5hX3BvdF9hbm4kUzEwNzExNiAqIDE0MSkgLyBjdHNfZG5hX3BvdF9hbm4kTGVuZ3RoCmN0c19kbmFfcG90X2FubiRTMTA3MTE3X1RnPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTcgKiAxNDEpIC8gY3RzX2RuYV9wb3RfYW5uJExlbmd0aApjdHNfZG5hX3BvdF9hbm4kUzEwNzExOV9UZzwtKGN0c19kbmFfcG90X2FubiRTMTA3MTE5ICogMTQxKSAvIGN0c19kbmFfcG90X2FubiRMZW5ndGgKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMjFfVGc8LShjdHNfZG5hX3BvdF9hbm4kUzEwNzEyMSAqIDE0MSkgLyBjdHNfZG5hX3BvdF9hbm4kTGVuZ3RoCmBgYAoKIyMjIDUuMi4gQ2FsY3VsYXRlIEdQTSBWYWx1ZXMKCk5vdyBtdWx0aXBsZSBlYWNoIFRnIHZhbHVlIHdpdGhpbiBhIHNhbXBsZSBieSAxZSswNiBhbmQgZGl2aWRlIGJ5IHRoZSBzdW0gb2YgVGcgdmFsdWVzIGZvciB0aGF0IHNhbXBsZSB0byBkZXRlcm1pbmUgR1BNLgoKYGBge3J9CmN0c19kbmFfcG90X2FubiRTMTA3MTA0X0dQTTwtKGN0c19kbmFfcG90X2FubiRTMTA3MTA0X1RnICogMTAwMDAwMCkgLyBzdW0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDRfVGcsbmEucm09VFJVRSkKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDVfR1BNPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDVfVGcgKiAxMDAwMDAwKSAvIHN1bShjdHNfZG5hX3BvdF9hbm4kUzEwNzEwNV9UZyxuYS5ybT1UUlVFKQpjdHNfZG5hX3BvdF9hbm4kUzEwNzEwNl9HUE08LShjdHNfZG5hX3BvdF9hbm4kUzEwNzEwNl9UZyAqIDEwMDAwMDApIC8gc3VtKGN0c19kbmFfcG90X2FubiRTMTA3MTA2X1RnLG5hLnJtPVRSVUUpCmN0c19kbmFfcG90X2FubiRTMTA3MTEwX0dQTTwtKGN0c19kbmFfcG90X2FubiRTMTA3MTEwX1RnICogMTAwMDAwMCkgLyBzdW0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTBfVGcsbmEucm09VFJVRSkKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTFfR1BNPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTFfVGcgKiAxMDAwMDAwKSAvIHN1bShjdHNfZG5hX3BvdF9hbm4kUzEwNzExMV9UZyxuYS5ybT1UUlVFKQpjdHNfZG5hX3BvdF9hbm4kUzEwNzExMl9HUE08LShjdHNfZG5hX3BvdF9hbm4kUzEwNzExMl9UZyAqIDEwMDAwMDApIC8gc3VtKGN0c19kbmFfcG90X2FubiRTMTA3MTEyX1RnLG5hLnJtPVRSVUUpCmN0c19kbmFfcG90X2FubiRTMTA3MTEzX0dQTTwtKGN0c19kbmFfcG90X2FubiRTMTA3MTEzX1RnICogMTAwMDAwMCkgLyBzdW0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTNfVGcsbmEucm09VFJVRSkKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTRfR1BNPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTRfVGcgKiAxMDAwMDAwKSAvIHN1bShjdHNfZG5hX3BvdF9hbm4kUzEwNzExNF9UZyxuYS5ybT1UUlVFKQpjdHNfZG5hX3BvdF9hbm4kUzEwNzExNV9HUE08LShjdHNfZG5hX3BvdF9hbm4kUzEwNzExNV9UZyAqIDEwMDAwMDApIC8gc3VtKGN0c19kbmFfcG90X2FubiRTMTA3MTE1X1RnLG5hLnJtPVRSVUUpCmN0c19kbmFfcG90X2FubiRTMTA3MTA3X0dQTTwtKGN0c19kbmFfcG90X2FubiRTMTA3MTA3X1RnICogMTAwMDAwMCkgLyBzdW0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDdfVGcsbmEucm09VFJVRSkKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDhfR1BNPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDhfVGcgKiAxMDAwMDAwKSAvIHN1bShjdHNfZG5hX3BvdF9hbm4kUzEwNzEwOF9UZyxuYS5ybT1UUlVFKQpjdHNfZG5hX3BvdF9hbm4kUzEwNzExNl9HUE08LShjdHNfZG5hX3BvdF9hbm4kUzEwNzExNl9UZyAqIDEwMDAwMDApIC8gc3VtKGN0c19kbmFfcG90X2FubiRTMTA3MTE2X1RnLG5hLnJtPVRSVUUpCmN0c19kbmFfcG90X2FubiRTMTA3MTE3X0dQTTwtKGN0c19kbmFfcG90X2FubiRTMTA3MTE3X1RnICogMTAwMDAwMCkgLyBzdW0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTdfVGcsbmEucm09VFJVRSkKY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTlfR1BNPC0oY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTlfVGcgKiAxMDAwMDAwKSAvIHN1bShjdHNfZG5hX3BvdF9hbm4kUzEwNzExOV9UZyxuYS5ybT1UUlVFKQpjdHNfZG5hX3BvdF9hbm4kUzEwNzEyMV9HUE08LShjdHNfZG5hX3BvdF9hbm4kUzEwNzEyMV9UZyAqIDEwMDAwMDApIC8gc3VtKGN0c19kbmFfcG90X2FubiRTMTA3MTIxX1RnLG5hLnJtPVRSVUUpCmBgYAoKIyMjIDUuMy4gQ3JlYXRlIEdQTSBEYXRhZnJhbWUKCkNyZWF0ZSB0aGUgR1BNIGRhdGFmcmFtZSBieSBzdWJzZXR0aW5nIGNvbHVtbnMgb2YgaW50ZXJlc3QgZnJvbSB0aGUgY3RzX2RuYV9wb3RfYW5uIGRhdGFmcmFtZS4KCmBgYHtyfQpncG1fYWxsPC1kYXRhLmZyYW1lKGN0c19kbmFfcG90X2FubiRJRCxjdHNfZG5hX3BvdF9hbm4kUzEwNzEwNF9HUE0sY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDVfR1BNLGN0c19kbmFfcG90X2FubiRTMTA3MTA2X0dQTSxjdHNfZG5hX3BvdF9hbm4kUzEwNzExMF9HUE0sY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTFfR1BNLGN0c19kbmFfcG90X2FubiRTMTA3MTEyX0dQTSxjdHNfZG5hX3BvdF9hbm4kUzEwNzExM19HUE0sY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTRfR1BNLGN0c19kbmFfcG90X2FubiRTMTA3MTE1X0dQTSxjdHNfZG5hX3BvdF9hbm4kUzEwNzEwN19HUE0sY3RzX2RuYV9wb3RfYW5uJFMxMDcxMDhfR1BNLGN0c19kbmFfcG90X2FubiRTMTA3MTE2X0dQTSxjdHNfZG5hX3BvdF9hbm4kUzEwNzExN19HUE0sY3RzX2RuYV9wb3RfYW5uJFMxMDcxMTlfR1BNLGN0c19kbmFfcG90X2FubiRTMTA3MTIxX0dQTSxjdHNfZG5hX3BvdF9hbm4kS08sY3RzX2RuYV9wb3RfYW5uJFN5bWJvbCxjdHNfZG5hX3BvdF9hbm4kRnVuY3Rpb24sY3RzX2RuYV9wb3RfYW5uJFRpZXJfSUksY3RzX2RuYV9wb3RfYW5uJFRpZXJfSUlJLGN0c19kbmFfcG90X2FubiRUaWVyX0lWLGN0c19kbmFfcG90X2FubiRUYXhvbm9teSkKCm5hbWVzKGdwbV9hbGwpPC1jKCJJRCIsIlMxMDcxMDRfR1BNIiwiUzEwNzEwNV9HUE0iLCJTMTA3MTA2X0dQTSIsIlMxMDcxMTBfR1BNIiwiUzEwNzExMV9HUE0iLCJTMTA3MTEyX0dQTSIsIlMxMDcxMTNfR1BNIiwiUzEwNzExNF9HUE0iLCJTMTA3MTE1X0dQTSIsIlMxMDcxMDdfR1BNIiwiUzEwNzEwOF9HUE0iLCJTMTA3MTE2X0dQTSIsIlMxMDcxMTdfR1BNIiwiUzEwNzExOV9HUE0iLCJTMTA3MTIxX0dQTSIsIktPIiwiU3ltYm9sIiwiRnVuY3Rpb24iLCJUaWVyX0lJIiwiVGllcl9JSUkiLCJUaWVyX0lWIiwiVGF4b25vbXkiKQpgYGAKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CndyaXRlLmNzdihncG1fYWxsLCAnTm9ybS5SZXN1bHRzL2dwbS5hbGwuZGF0YS5jc3YnKQpgYGAKCiMjIDYuIEdlbmUgRGF0YXNldHMKCk5vdywgd2UgZnVydGhlciBzZXBhcmF0ZSB0aGUgbm9ybWFsaXplZCBwb3RlbnRpYWwgYW5ub3RhdGVkIEROQSBzdWJkYXRhIGludG8gdGhlaXIgZXhwZXJpbWVudGFsIHRyZWF0bWVudHMgaW4gb3JkZXIgdG8gYW5hbHl6ZSBzdGF0aXN0aWNhbCBkaWZmZXJlbmNlcyBpbiBwb3RlbnRpYWwgZ2VuZSBleHByZXNzaW9uIHBhdHRlcm5zIGJldHdlZW4gZXhwZXJpbWVudGFsIHRyZWF0bWVudHMuIFBhaXJ3aXNlIHNpbWlsYXJpdGllcyBhbW9uZyBtZXRhZ2Vub21jZXMgd2lsbCBiZSBjYWxjdWxhdGVkIHVzaW5nIEJyYXktQ3VydGlzIHNpbWlsYXJpdHkgdmFsdWVzLCB3aXRoIGRpZmZlcmVuY2VzIGJldHdlZW4gdHJlYXRtZW50cyBhc3Nlc3NlZCB2aWEgUEVSTUFOT1ZBLgoKIyMjIDYuMS4gVHVzc29jayBHZW5lIERhdGEKClNlcGFyYXRlIHRoZSAqKlR1c3NvY2sqKiBzYW1wbGVzIGludG8gdGhlaXIgb3duIGRhdGFzZXQuICAqKipLZWVwIG9ubHkgdGhvc2UgdW5pcXVlIGdlbmVjYWxscyB0aGF0IGhhdmUgcG90ZW50aWFsIGV4cHJlc3Npb24gaW4gYXQgbGVhc3QgMSBUdXNzIHNhbXBsZS4qKioKCmBgYHtyfQojIFN1YnNldCB0aGUgVFVTUyBHUE0gTm9ybWFsaXplZCBQb3RlbnRpYWwgQW5ub3RhdGVkIHN1YmRhdGEKZ3BtX3R1c3MgPC0gc3Vic2V0KGdwbV9hbGwsIHNlbGVjdD1jKElELFMxMDcxMDdfR1BNLFMxMDcxMDhfR1BNLFMxMDcxMTZfR1BNLFMxMDcxMTdfR1BNLFMxMDcxMTlfR1BNLFMxMDcxMjFfR1BNLEtPLFN5bWJvbCxGdW5jdGlvbixUaWVyX0lJLFRpZXJfSUlJLFRpZXJfSVYsIFRheG9ub215KSkKCm5hbWVzKGdwbV90dXNzKTwtYygiSUQiLCJUdXNzMV9UMCIsIlR1c3MyX1QwIiwiVHVzczFfVDQiLCJUdXNzMl9UNCIsIlR1c3MxX1QyNCIsIlR1c3MzX1QyNCIsIktPIiwiU3ltYm9sIiwiRnVuY3Rpb24iLCJUaWVyX0lJIiwiVGllcl9JSUkiLCJUaWVyX0lWIiwiVGF4b25vbXkiKQoKIyBSZW1vdmUgYW55IG5vbi1leHByZXNzZWQgZ2VuZXMgZnJvbSB0aGUgVHVzc29jayBzYW1wbGVzCmdwbV90dXNzX3BvdGVudGlhbCA8LSBzdWJzZXQoZ3BtX3R1c3MsIFR1c3MxX1QwID4gMCB8IFR1c3MyX1QwID4gMCB8IFR1c3MxX1Q0ID4gMCB8IFR1c3MyX1Q0ID4gMCB8IFR1c3MxX1QyNCA+IDAgfCBUdXNzM19UMjQgPiAwLCBzZWxlY3Q9YyhJRCxUdXNzMV9UMCxUdXNzMl9UMCxUdXNzMV9UNCxUdXNzMl9UNCxUdXNzMV9UMjQsVHVzczNfVDI0LEtPLFN5bWJvbCxGdW5jdGlvbixUaWVyX0lJLFRpZXJfSUlJLFRpZXJfSVYsVGF4b25vbXkpKQpgYGAKCiMjIyA2LjIuIFdldCBTZWRnZSBHZW5lIERhdGEKClNlcGFyYXRlIHRoZSAqKldldCBTZWRnZSoqIHNhbXBsZXMgaW50byB0aGVpciBvd24gZGF0YXNldC4gICoqKktlZXAgb25seSB0aG9zZSB1bmlxdWUgZ2VuZWNhbGxzIHRoYXQgaGF2ZSBwb3RlbnRpYWwgZXhwcmVzc2lvbiBpbiBhdCBsZWFzdCAxIFdTIHNhbXBsZS4qKioKCmBgYHtyfQojIFN1YnNldCB0aGUgV1MgR1BNIE5vcm1hbGl6ZWQgUG90ZW50aWFsIEFubm90YXRlZCBzdWJkYXRhCmdwbV93cyA8LSBzdWJzZXQoZ3BtX2FsbCwgc2VsZWN0PWMoSUQsUzEwNzEwNF9HUE0sUzEwNzEwNV9HUE0sUzEwNzEwNl9HUE0sUzEwNzExMF9HUE0sUzEwNzExMV9HUE0sUzEwNzExMl9HUE0sUzEwNzExM19HUE0sUzEwNzExNF9HUE0sUzEwNzExNV9HUE0sS08sU3ltYm9sLEZ1bmN0aW9uLFRpZXJfSUksVGllcl9JSUksVGllcl9JVixUYXhvbm9teSkpCm5hbWVzKGdwbV93cyk8LWMoIklEIiwiV1MxX1QwIiwiV1MyX1QwIiwiV1MzX1QwIiwiV1MxX1Q0IiwiV1MyX1Q0IiwiV1MzX1Q0IiwiV1MxX1QyNCIsIldTMl9UMjQiLCJXUzNfVDI0IiwiS08iLCJTeW1ib2wiLCJGdW5jdGlvbiIsIlRpZXJfSUkiLCJUaWVyX0lJSSIsIlRpZXJfSVYiLCJUYXhvbm9teSIpCgojIFJlbW92ZSBhbnkgbm9uLWV4cHJlc3NlZCBnZW5lcyBmcm9tIHRoZSBXZXQgU2VkZ2Ugc2FtcGxlcwpncG1fd3NfcG90ZW50aWFsIDwtIHN1YnNldChncG1fd3MsIFdTMV9UMCA+IDAgfCBXUzJfVDAgPiAwIHwgV1MzX1QwID4gMCB8IFdTMV9UNCA+IDAgfCBXUzJfVDQgPiAwIHwgV1MzX1Q0ID4gMCB8IFdTMV9UMjQgPiAwIHwgV1MyX1QyNCA+IDAgfCBXUzNfVDI0ID4gMCwgc2VsZWN0PWMoSUQsV1MxX1QwLFdTMl9UMCxXUzNfVDAsV1MxX1Q0LFdTMl9UNCxXUzNfVDQsV1MxX1QyNCxXUzJfVDI0LFdTM19UMjQsS08sU3ltYm9sLEZ1bmN0aW9uLFRpZXJfSUksVGllcl9JSUksVGllcl9JVixUYXhvbm9teSkpCmBgYAoKIyMjIDYuMy4gQWxsIEdlbmUgRGF0YQoKV2UgYWxzbyBuZWVkIHRoZSBmdWxsIFRVU1MgYW5kIFdTIFBvdGVudGlhbCBBbm5vdGF0ZWQgZGF0YSB0b2dldGhlciB0byBtYWtlIGNvbXBhcmlzb25zIGJldHdlZW4gZWNvc3lzdGVtcyB3aXRoaW4gZWFjaCBzYW1wbGluZyB0aW1lcG9pbnQuICBSZWZvcm1hdCB0aGUgYGdwbV9hbGxgIHRhYmxlIGFuZCBzZXBhcmF0ZSB0aGUgIktFR0ciIGNvbHVtbiBpbnRvIGFsbCBvZiBpdHMgZnVuY3Rpb25hbCBjYXRlZ29yaWVzIGZvciBkb3duc3RyZWFtIHVzZS4KCmBgYHtyfQojIE1ha2UgYSBuZXcgb2JqZWN0IGZvciB0aGUgcnBtX2FsbCB0YWJsZSBzbyB0aGF0IHlvdSBkb24ndCBvdmVyd3JpdGUgdGhlIG9yaWdpbmFsCmdwbV9hbGxfcG90X2FubjwtZ3BtX2FsbAoKbmFtZXMoZ3BtX2FsbF9wb3RfYW5uKTwtYygiSUQiLCJTMTA3MTA0IiwiUzEwNzEwNSIsIlMxMDcxMDYiLCJTMTA3MTEwIiwiUzEwNzExMSIsIlMxMDcxMTIiLCJTMTA3MTEzIiwiUzEwNzExNCIsIlMxMDcxMTUiLCJTMTA3MTA3IiwiUzEwNzEwOCIsIlMxMDcxMTYiLCJTMTA3MTE3IiwiUzEwNzExOSIsIlMxMDcxMjEiLCJLTyIsIlN5bWJvbCIsIkZ1bmN0aW9uIiwiVGllcl9JSSIsIlRpZXJfSUlJIiwiVGllcl9JViIsIlRheG9ub215IikKYGBgCgojIyA3LiBHZW5lIEFuYWx5c2lzCgojIyMgNy4xLiBUYXhvbm9teQpIZXJlLCB3ZSBkZXRlcm1pbmUgdGhlIHRheG9ub21pYyBjb21wb3NpdGlvbiBvZiB0aGUgbWljcm9iaWFsIGNvbW11bml0eSBieSBhbmFseXppbmcgdGhlIHJlbGF0aXZlIGFidW5kYW5jZSBvZiBwb3RlbnRpYWwgZ2VuZXMgZm9yIEtFR0cgdGllciBJViAiUmlib3NvbWVzIiAoMDMwMTAgUmlib3NvbWUgUEFUSDoga28wMzAxMCkuICBXaXRoaW4gdGhlICJSaWJvc29tZSIgY2F0ZWdvcnksIHRoZXJlIGFyZSBhbm5vdGF0aW9ucyBmb3IgInNtYWxsIHN1YnVuaXQgcmlib3NvbWFsIHByb3RlaW4iIChzc3UpIGFuZCAibGFyZ2Ugc3VidW5pdCByaWJvc29tYWwgcHJvdGVpbiIgKGxzdSkuIEZvciBCYWN0ZXJpYSBhbmQgQXJjaGFlYSwgd2UgdXNlIHRoZSBzc3UgYW5ub3RhdGlvbnMgKHNpbWlsYXIgdG8gMTZTIHNzdSByUk5BIHRhcmdldGVkIGFuYWx5c2lzKS4gRm9yIEZ1bmdpLCB3ZSB1c2UgYm90aCB0aGUgc3N1ICgxOFMgc3N1IHJSTkEpIGFuZCBsc3UgKDI4UyBsc3UgclJOQSkgYW5ub3RhdGlvbnMuCgojIyMjIDcuMS4xLiBCYWN0ZXJpYS9BcmNoYWVhIFNTVQpUaGUgZmlyc3QgYW5hbHlzaXMgcHVsbHMgb3V0IGFsbCBnZW5lIGV4cHJlc3Npb24gZm9yICJSaWJvc29tZXMiIGFuZCByZW1vdmVzIGxzdSBhbm5vdGF0aW9ucyBzdWNoIHRoYXQgb25seSBzc3UgYW5ub3RhdGlvbnMgYXJlIHVzZWQgZm9yIGRldGVybWluaW5nIHJlbGF0aXZlIGV4cHJlc3Npb24gb2YgQmFjdGVyaWEgYW5kIEFyY2hhZWEgYXQgZWFjaCBzYW1wbGluZyB0aW1lIHBvaW50IGluIGJvdGggdHVzc29jayBhbmQgd2V0IHNlZGdlIHR1bmRyYS4KCmBgYHtyfQojIFN1YnNldCBhbGwgdW5pcXVlIGdlbmVjYWxscyB3aG9zZSBhbm5vdGF0aW9uIG1hdGNoZXMgIlJpYm9zb21lcyIKdGF4YV9yaWJvX2RuYV9hbGw8LSBncG1fYWxsX3BvdF9hbm5bIHdoaWNoKGdwbV9hbGxfcG90X2FubiRUaWVyX0lWPT0nMDMwMTAgUmlib3NvbWUgW1BBVEg6a28wMzAxMF0nKSxdCmBgYAoKYGBge3Igd2FybmluZz1GQUxTRX0KIyBNYWtlIGNvcHkgb2YgUmlib3NvbWUgZGF0YXNldCB0byBtYW5pcHVsYXRlCnRheGFfcmlib19kbmFfc3N1PC10YXhhX3JpYm9fZG5hX2FsbAoKIyBSZW1vdmUgImxhcmdlIHN1YnVuaXQgcmlib3NvbWFsIHByb3RlaW4iIGZyb20gZGF0YXNldAp0YXhhX3JpYm9fZG5hX3NzdTwtdGF4YV9yaWJvX2RuYV9zc3VbIWdyZXBsKCJsYXJnZSBzdWJ1bml0IHJpYm9zb21hbCBwcm90ZWluIiwgdGF4YV9yaWJvX2RuYV9zc3UkRnVuY3Rpb24pLF0KCiMgV3JpdGUgZGF0YSB0byBmaWxlIGZvciBBbHBoYSBEaXZlcnNpdHkgc3RhdGlzdGljcwp3cml0ZS5jc3YodGF4YV9yaWJvX2RuYV9zc3UsICdSaWJvLlJlc3VsdHMvQUxQSEEudGF4YS5kbmEuc3N1LmNzdicpCgojIFJlbW92ZSAiRnVuZ2kiIGZyb20gZGF0YXNldAp0YXhhX3JpYm9fZG5hX3NzdTwtdGF4YV9yaWJvX2RuYV9zc3VbIWdyZXBsKCJGdW5naSIsIHRheGFfcmlib19kbmFfc3N1JFRheG9ub215KSxdCgojIFNlcGFyYXRlICJUYXhvbm9teSIgY29sdW1uIGludG8gYWxsIHN1YmRpdmlzaW9ucwp0YXhhX3JpYm9fZG5hX3NzdTwtdGF4YV9yaWJvX2RuYV9zc3UgJT4lIHNlcGFyYXRlKFRheG9ub215LCBjKCJLaW5nZG9tIiwiUGh5bHVtIiwiQ2xhc3MiLCJPcmRlciIsIkZhbWlseSIsIkdlbnVzIiwiU3BlY2llcyIpLCAiOiAiLCBleHRyYT0ibWVyZ2UiKQoKIyBLZWVwICJLaW5nZG9tIiBhbmQgIlBoeWx1bSIKdGF4YV9yaWJvX2RuYV9zc3UgPC0gZGF0YS5mcmFtZSh0YXhhX3JpYm9fZG5hX3NzdSRLaW5nZG9tLHRheGFfcmlib19kbmFfc3N1JFBoeWx1bSwgdGF4YV9yaWJvX2RuYV9zc3UkUzEwNzEwNCx0YXhhX3JpYm9fZG5hX3NzdSRTMTA3MTA1LHRheGFfcmlib19kbmFfc3N1JFMxMDcxMDYsdGF4YV9yaWJvX2RuYV9zc3UkUzEwNzExMCx0YXhhX3JpYm9fZG5hX3NzdSRTMTA3MTExLHRheGFfcmlib19kbmFfc3N1JFMxMDcxMTIsdGF4YV9yaWJvX2RuYV9zc3UkUzEwNzExMyx0YXhhX3JpYm9fZG5hX3NzdSRTMTA3MTE0LHRheGFfcmlib19kbmFfc3N1JFMxMDcxMTUsdGF4YV9yaWJvX2RuYV9zc3UkUzEwNzEwNyx0YXhhX3JpYm9fZG5hX3NzdSRTMTA3MTA4LHRheGFfcmlib19kbmFfc3N1JFMxMDcxMTYsdGF4YV9yaWJvX2RuYV9zc3UkUzEwNzExNyx0YXhhX3JpYm9fZG5hX3NzdSRTMTA3MTE5LHRheGFfcmlib19kbmFfc3N1JFMxMDcxMjEpCm5hbWVzKHRheGFfcmlib19kbmFfc3N1KTwtYygiS2luZ2RvbSIsIlBoeWx1bSIsIndzMS1UMCIsIndzMi1UMCIsIndzMy1UMCIsIndzMS1UNCIsIndzMi1UNCIsIndzMy1UNCIsIndzMS1UMjQiLCJ3czItVDI0Iiwid3MzLVQyNCIsInR1c3MxLVQwIiwidHVzczItVDAiLCJ0dXNzMS1UNCIsInR1c3MyLVQ0IiwidHVzczEtVDI0IiwidHVzczMtVDI0IikKCiMgUmVtb3ZlICJVbmNsYXNzaWZpZWQiIHRheGEgb3RoZXJ3aXNlIGl0IHdpbGwgY2x1bXAgdW5jbGFzc2lmaWVkIEFyY2hhZWEgd2l0aCB1bmNsYXNzaWZpZWQgQmFjdGVyaWEgKG5vdCB3aGF0IHdlIHdhbnQpCnRheGFfcmlib19kbmFfc3N1PC10YXhhX3JpYm9fZG5hX3NzdVshZ3JlcGwoIlVuY2xhc3NpZmllZCIsIHRheGFfcmlib19kbmFfc3N1JFBoeWx1bSksXQoKIyBSZW1vdmUgIk90aGVyIiB0YXhhIG90aGVyd2lzZSBpdCB3aWxsIGNsdW1wICJvdGhlciIgQXJjaGFlYSB3aXRoICJvdGhlciIgQmFjdGVyaWEgKG5vdCB3aGF0IHdlIHdhbnQpCnRheGFfcmlib19kbmFfc3N1PC10YXhhX3JpYm9fZG5hX3NzdVshZ3JlcGwoIk90aGVyIiwgdGF4YV9yaWJvX2RuYV9zc3UkUGh5bHVtKSxdCgojIFNvcnQgZGF0YSBieSBLaW5nZG9tIGFscGhhYmV0aWNhbGx5CnRheGFfcmlib19kbmFfc3N1PC10YXhhX3JpYm9fZG5hX3NzdVtvcmRlcih0YXhhX3JpYm9fZG5hX3NzdSRLaW5nZG9tLHRheGFfcmlib19kbmFfc3N1JFBoeWx1bSksXQoKIyBTdW0gZWFjaCBjb2x1bW4gYnkgdW5pcXVlIFBoeWx1bQp0YXhhX3JpYm9fZG5hX3NzdV9zdW08LXRheGFfcmlib19kbmFfc3N1ICU+JSBncm91cF9ieShQaHlsdW0pICU+JSBzdW1tYXJpc2VfYXQodmFycygid3MxLVQwIiwid3MyLVQwIiwid3MzLVQwIiwid3MxLVQ0Iiwid3MyLVQ0Iiwid3MzLVQ0Iiwid3MxLVQyNCIsIndzMi1UMjQiLCJ3czMtVDI0IiwidHVzczEtVDAiLCJ0dXNzMi1UMCIsInR1c3MxLVQ0IiwidHVzczItVDQiLCJ0dXNzMS1UMjQiLCJ0dXNzMy1UMjQiKSwgc3VtKQp0YXhhX3JpYm9fZG5hX3NzdV9zdW08LXRheGFfcmlib19kbmFfc3N1X3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMoJ3dzMS1UMCcsJ3dzMi1UMCcsJ3dzMy1UMCcsJ3dzMS1UNCcsJ3dzMi1UNCcsJ3dzMy1UNCcsJ3dzMS1UMjQnLCd3czItVDI0Jywnd3MzLVQyNCcsJ3R1c3MxLVQwJywndHVzczItVDAnLCd0dXNzMS1UNCcsJ3R1c3MyLVQ0JywndHVzczEtVDI0JywndHVzczMtVDI0JyksIGZ1bnMocm91bmQoLiwgMCkpKQp0YXhhX3JpYm9fZG5hX3NzdV9zdW08LWFzLmRhdGEuZnJhbWUodGF4YV9yaWJvX2RuYV9zc3Vfc3VtKQoKdGF4YV9yaWJvX2RuYV9zc3Vfc3VtCmBgYAoKYGBge3IgZWNobz1GQUxTRX0KIyBTYXZlIHRheGFfcmlib19kbmFfc3N1X3N1bSBhcyAuY3N2IGZpbGUKd3JpdGUuY3N2KHRheGFfcmlib19kbmFfc3N1X3N1bSwgJ1JpYm8uUmVzdWx0cy90YXhhLnJpYm8uZG5hLnNzdS5zdW0uY3N2JykKYGBgCgpSZXBlYXQgdGhlIHNhbWUgIlJpYm9zb21lIiBhbmFseXNpcyBhcyBhYm92ZSAoYXQgUGh5bHVtIGxldmVsKSwgYnV0IHRoaXMgdGltZSBrZWVwIGFsbCB0aGUgdGF4b25vbXkgaW5mb3JtYXRpb24uCmBgYHtyfQojIE1ha2UgY29weSBvZiB0YXhhX3JpYm9fYWxsIHRvIG1hbmlwdWxhdGUKdGF4YV9yaWJvX2RuYV9zc3UyPC10YXhhX3JpYm9fZG5hX2FsbAoKIyBLZWVwICJUYXhvbm9teSIgY29sdW1uCnRheGFfcmlib19kbmFfc3N1MiA8LSBkYXRhLmZyYW1lKHRheGFfcmlib19kbmFfc3N1MiRGdW5jdGlvbix0YXhhX3JpYm9fZG5hX3NzdTIkVGF4b25vbXksdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMDQsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMDUsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMDYsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTAsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTEsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTIsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTMsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTQsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTUsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMDcsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMDgsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTYsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTcsdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMTksdGF4YV9yaWJvX2RuYV9zc3UyJFMxMDcxMjEpCm5hbWVzKHRheGFfcmlib19kbmFfc3N1Mik8LWMoIkZ1bmN0aW9uIiwiVGF4b25vbXkiLCJ3czEtVDAiLCJ3czItVDAiLCJ3czMtVDAiLCJ3czEtVDQiLCJ3czItVDQiLCJ3czMtVDQiLCJ3czEtVDI0Iiwid3MyLVQyNCIsIndzMy1UMjQiLCJ0dXNzMS1UMCIsInR1c3MyLVQwIiwidHVzczEtVDQiLCJ0dXNzMi1UNCIsInR1c3MxLVQyNCIsInR1c3MzLVQyNCIpCgojIFJlbW92ZSAibGFyZ2Ugc3VidW5pdCByaWJvc29tYWwgcHJvdGVpbiIgZnJvbSBkYXRhc2V0CnRheGFfcmlib19kbmFfc3N1MjwtdGF4YV9yaWJvX2RuYV9zc3UyWyFncmVwbCgibGFyZ2Ugc3VidW5pdCByaWJvc29tYWwgcHJvdGVpbiIsIHRheGFfcmlib19kbmFfc3N1MiRGdW5jdGlvbiksXQoKIyBSZW1vdmUgIkZ1bmdpIiBmcm9tIGRhdGFzZXQKdGF4YV9yaWJvX2RuYV9zc3UyPC10YXhhX3JpYm9fZG5hX3NzdTJbIWdyZXBsKCJGdW5naSIsIHRheGFfcmlib19kbmFfc3N1MiRUYXhvbm9teSksXQpgYGAKCmBgYHtyfQojIFNvcnQgZGF0YSBieSBLaW5nZG9tIGFscGhhYmV0aWNhbGx5CnRheGFfcmlib19kbmFfc3N1MjwtdGF4YV9yaWJvX2RuYV9zc3UyW29yZGVyKHRheGFfcmlib19kbmFfc3N1MiRGdW5jdGlvbix0YXhhX3JpYm9fZG5hX3NzdTIkVGF4b25vbXkpLF0KCiMgU3VtIGVhY2ggY29sdW1uIGJ5IHVuaXF1ZSBUYXhvbm9teQp0YXhhX3JpYm9fZG5hX3NzdTJfc3VtPC10YXhhX3JpYm9fZG5hX3NzdTIgJT4lIGdyb3VwX2J5KFRheG9ub215KSAlPiUgc3VtbWFyaXNlX2F0KHZhcnMoIndzMS1UMCIsIndzMi1UMCIsIndzMy1UMCIsIndzMS1UNCIsIndzMi1UNCIsIndzMy1UNCIsIndzMS1UMjQiLCJ3czItVDI0Iiwid3MzLVQyNCIsInR1c3MxLVQwIiwidHVzczItVDAiLCJ0dXNzMS1UNCIsInR1c3MyLVQ0IiwidHVzczEtVDI0IiwidHVzczMtVDI0IiksIHN1bSkKdGF4YV9yaWJvX2RuYV9zc3UyX3N1bTwtdGF4YV9yaWJvX2RuYV9zc3UyX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMoJ3dzMS1UMCcsJ3dzMi1UMCcsJ3dzMy1UMCcsJ3dzMS1UNCcsJ3dzMi1UNCcsJ3dzMy1UNCcsJ3dzMS1UMjQnLCd3czItVDI0Jywnd3MzLVQyNCcsJ3R1c3MxLVQwJywndHVzczItVDAnLCd0dXNzMS1UNCcsJ3R1c3MyLVQ0JywndHVzczEtVDI0JywndHVzczMtVDI0JyksIGZ1bnMocm91bmQoLiwgMCkpKQp0YXhhX3JpYm9fZG5hX3NzdTJfc3VtPC1hcy5kYXRhLmZyYW1lKHRheGFfcmlib19kbmFfc3N1Ml9zdW0pCgp0YXhhX3JpYm9fZG5hX3NzdTJfc3VtCmBgYAoKYGBge3IgZWNobz1GQUxTRX0KIyBTYXZlIHRheGFfcmlib19kbmFfYWxsX3N1bSBhcyAuY3N2IGZpbGUKd3JpdGUuY3N2KHRheGFfcmlib19kbmFfc3N1Ml9zdW0sICdSaWJvLlJlc3VsdHMvdGF4YV9yaWJvX2RuYV9zc3UyX3N1bS5jc3YnKQpgYGAKCiMjIyMgNy4xLjIuIEZ1bmdpIFNTVS9MU1UKVGhlIHNlY29uZCBhbmFseXNpcyBwdWxscyBvdXQgYWxsIGdlbmUgZXhwcmVzc2lvbiBmb3IgIlJpYm9zb21lcyIgYW5kIHJlbW92ZXMgQmFjdGVyaWEgYW5kIEFyY2hhZWEgYW5ub3RhdGlvbnMgd2hpbGUgcmV0YWluaW5nIGp1c3QgRnVuZ2kgd2l0aCBib3RoIHNzdSBhbmQgbHN1IGFubm90YXRpb25zIHRvIGRldGVybWluZSByZWxhdGl2ZSBleHByZXNzaW9uIG9mIEZ1bmdpIGF0IGVhY2ggc2FtcGxpbmcgdGltZSBwb2ludCBpbiBib3RoIHR1c3NvY2sgYW5kIHdldCBzZWRnZSB0dW5kcmEuCgpgYGB7cn0KIyBNYWtlIGNvcHkgb2YgUmlib3NvbWUgZGF0YXNldCB0byBtYW5pcHVsYXRlCnRheGFfcmlib19kbmFfZnVuZ2k8LXRheGFfcmlib19kbmFfYWxsCgojIFJlbW92ZSAiQmFjdGVyaWEiIGZyb20gZGF0YXNldAp0YXhhX3JpYm9fZG5hX2Z1bmdpPC10YXhhX3JpYm9fZG5hX2Z1bmdpWyFncmVwbCgiQmFjdGVyaWEiLCB0YXhhX3JpYm9fZG5hX2Z1bmdpJFRheG9ub215KSxdCgojIFJlbW92ZSAiQXJjaGFlYSIgZnJvbSBkYXRhc2V0CnRheGFfcmlib19kbmFfZnVuZ2k8LXRheGFfcmlib19kbmFfZnVuZ2lbIWdyZXBsKCJBcmNoYWVhIiwgdGF4YV9yaWJvX2RuYV9mdW5naSRUYXhvbm9teSksXQoKIyBTZXBhcmF0ZSAiVGF4b25vbXkiIGNvbHVtbiBpbnRvIGFsbCBzdWJkaXZpc2lvbnMKdGF4YV9yaWJvX2RuYV9mdW5naTwtdGF4YV9yaWJvX2RuYV9mdW5naSAlPiUgc2VwYXJhdGUoVGF4b25vbXksIGMoIktpbmdkb20iLCJQaHlsdW0iLCJDbGFzcyIsIk9yZGVyIiwiRmFtaWx5IiwiR2VudXMiLCJTcGVjaWVzIiksICI6ICIsIGV4dHJhPSJtZXJnZSIpCgojIEtlZXAgIktpbmdkb20iIGFuZCAiUGh5bHVtIgp0YXhhX3JpYm9fZG5hX2Z1bmdpIDwtIGRhdGEuZnJhbWUodGF4YV9yaWJvX2RuYV9mdW5naSRLaW5nZG9tLHRheGFfcmlib19kbmFfZnVuZ2kkUGh5bHVtLCB0YXhhX3JpYm9fZG5hX2Z1bmdpJFMxMDcxMDQsdGF4YV9yaWJvX2RuYV9mdW5naSRTMTA3MTA1LHRheGFfcmlib19kbmFfZnVuZ2kkUzEwNzEwNix0YXhhX3JpYm9fZG5hX2Z1bmdpJFMxMDcxMTAsdGF4YV9yaWJvX2RuYV9mdW5naSRTMTA3MTExLHRheGFfcmlib19kbmFfZnVuZ2kkUzEwNzExMix0YXhhX3JpYm9fZG5hX2Z1bmdpJFMxMDcxMTMsdGF4YV9yaWJvX2RuYV9mdW5naSRTMTA3MTE0LHRheGFfcmlib19kbmFfZnVuZ2kkUzEwNzExNSx0YXhhX3JpYm9fZG5hX2Z1bmdpJFMxMDcxMDcsdGF4YV9yaWJvX2RuYV9mdW5naSRTMTA3MTA4LHRheGFfcmlib19kbmFfZnVuZ2kkUzEwNzExNix0YXhhX3JpYm9fZG5hX2Z1bmdpJFMxMDcxMTcsdGF4YV9yaWJvX2RuYV9mdW5naSRTMTA3MTE5LHRheGFfcmlib19kbmFfZnVuZ2kkUzEwNzEyMSkKbmFtZXModGF4YV9yaWJvX2RuYV9mdW5naSk8LWMoIktpbmdkb20iLCJQaHlsdW0iLCJ3czEtVDAiLCJ3czItVDAiLCJ3czMtVDAiLCJ3czEtVDQiLCJ3czItVDQiLCJ3czMtVDQiLCJ3czEtVDI0Iiwid3MyLVQyNCIsIndzMy1UMjQiLCJ0dXNzMS1UMCIsInR1c3MyLVQwIiwidHVzczEtVDQiLCJ0dXNzMi1UNCIsInR1c3MxLVQyNCIsInR1c3MzLVQyNCIpCgojIFJlbW92ZSAiVW5jbGFzc2lmaWVkIiB0YXhhCnRheGFfcmlib19kbmFfZnVuZ2k8LXRheGFfcmlib19kbmFfZnVuZ2lbIWdyZXBsKCJVbmNsYXNzaWZpZWQiLCB0YXhhX3JpYm9fZG5hX2Z1bmdpJFBoeWx1bSksXQoKIyBSZW1vdmUgIk90aGVyIiB0YXhhCnRheGFfcmlib19kbmFfZnVuZ2k8LXRheGFfcmlib19kbmFfZnVuZ2lbIWdyZXBsKCJPdGhlciIsIHRheGFfcmlib19kbmFfZnVuZ2kkUGh5bHVtKSxdCgojIFNvcnQgZGF0YSBieSBLaW5nZG9tIGFscGhhYmV0aWNhbGx5CnRheGFfcmlib19kbmFfZnVuZ2k8LXRheGFfcmlib19kbmFfZnVuZ2lbb3JkZXIodGF4YV9yaWJvX2RuYV9mdW5naSRLaW5nZG9tLHRheGFfcmlib19kbmFfZnVuZ2kkUGh5bHVtKSxdCgojIFN1bSBlYWNoIGNvbHVtbiBieSB1bmlxdWUgUGh5bHVtCnRheGFfcmlib19kbmFfZnVuZ2lfc3VtPC10YXhhX3JpYm9fZG5hX2Z1bmdpICU+JSBncm91cF9ieShQaHlsdW0pICU+JSBzdW1tYXJpc2VfYXQodmFycygid3MxLVQwIiwid3MyLVQwIiwid3MzLVQwIiwid3MxLVQ0Iiwid3MyLVQ0Iiwid3MzLVQ0Iiwid3MxLVQyNCIsIndzMi1UMjQiLCJ3czMtVDI0IiwidHVzczEtVDAiLCJ0dXNzMi1UMCIsInR1c3MxLVQ0IiwidHVzczItVDQiLCJ0dXNzMS1UMjQiLCJ0dXNzMy1UMjQiKSwgc3VtKQp0YXhhX3JpYm9fZG5hX2Z1bmdpX3N1bTwtdGF4YV9yaWJvX2RuYV9mdW5naV9zdW0gJT4lIG11dGF0ZV9hdCh2YXJzKCd3czEtVDAnLCd3czItVDAnLCd3czMtVDAnLCd3czEtVDQnLCd3czItVDQnLCd3czMtVDQnLCd3czEtVDI0Jywnd3MyLVQyNCcsJ3dzMy1UMjQnLCd0dXNzMS1UMCcsJ3R1c3MyLVQwJywndHVzczEtVDQnLCd0dXNzMi1UNCcsJ3R1c3MxLVQyNCcsJ3R1c3MzLVQyNCcpLCBmdW5zKHJvdW5kKC4sIDApKSkKdGF4YV9yaWJvX2RuYV9mdW5naV9zdW08LWFzLmRhdGEuZnJhbWUodGF4YV9yaWJvX2RuYV9mdW5naV9zdW0pCgp0YXhhX3JpYm9fZG5hX2Z1bmdpX3N1bQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CiMgU2F2ZSB0YXhhX3JpYm9fZG5hX2Z1bmdpX3N1bSBhcyAuY3N2IGZpbGUKd3JpdGUuY3N2KHRheGFfcmlib19kbmFfZnVuZ2lfc3VtLCAnUmliby5SZXN1bHRzL3RheGEucmliby5kbmEuZnVuZ2kuc3VtLmNzdicpCmBgYAoKUmVwZWF0IHRoZSBzYW1lICJSaWJvc29tZSIgYW5hbHlzaXMgYXMgYWJvdmUgKGF0IFBoeWx1bSBsZXZlbCksIGJ1dCB0aGlzIHRpbWUga2VlcCBhbGwgdGhlIHRheG9ub215IGluZm9ybWF0aW9uLgpgYGB7cn0KIyBNYWtlIGNvcHkgb2YgdGF4YV9yaWJvX2FsbCB0byBtYW5pcHVsYXRlCnRheGFfcmlib19kbmFfZnVuZ2kyPC10YXhhX3JpYm9fZG5hX2FsbAoKIyBLZWVwICJUYXhvbm9teSIgY29sdW1uCnRheGFfcmlib19kbmFfZnVuZ2kyIDwtIGRhdGEuZnJhbWUodGF4YV9yaWJvX2RuYV9mdW5naTIkRnVuY3Rpb24sdGF4YV9yaWJvX2RuYV9mdW5naTIkVGF4b25vbXksdGF4YV9yaWJvX2RuYV9mdW5naTIkUzEwNzEwNCx0YXhhX3JpYm9fZG5hX2Z1bmdpMiRTMTA3MTA1LHRheGFfcmlib19kbmFfZnVuZ2kyJFMxMDcxMDYsdGF4YV9yaWJvX2RuYV9mdW5naTIkUzEwNzExMCx0YXhhX3JpYm9fZG5hX2Z1bmdpMiRTMTA3MTExLHRheGFfcmlib19kbmFfZnVuZ2kyJFMxMDcxMTIsdGF4YV9yaWJvX2RuYV9mdW5naTIkUzEwNzExMyx0YXhhX3JpYm9fZG5hX2Z1bmdpMiRTMTA3MTE0LHRheGFfcmlib19kbmFfZnVuZ2kyJFMxMDcxMTUsdGF4YV9yaWJvX2RuYV9mdW5naTIkUzEwNzEwNyx0YXhhX3JpYm9fZG5hX2Z1bmdpMiRTMTA3MTA4LHRheGFfcmlib19kbmFfZnVuZ2kyJFMxMDcxMTYsdGF4YV9yaWJvX2RuYV9mdW5naTIkUzEwNzExNyx0YXhhX3JpYm9fZG5hX2Z1bmdpMiRTMTA3MTE5LHRheGFfcmlib19kbmFfZnVuZ2kyJFMxMDcxMjEpCm5hbWVzKHRheGFfcmlib19kbmFfZnVuZ2kyKTwtYygiRnVuY3Rpb24iLCJUYXhvbm9teSIsIndzMS1UMCIsIndzMi1UMCIsIndzMy1UMCIsIndzMS1UNCIsIndzMi1UNCIsIndzMy1UNCIsIndzMS1UMjQiLCJ3czItVDI0Iiwid3MzLVQyNCIsInR1c3MxLVQwIiwidHVzczItVDAiLCJ0dXNzMS1UNCIsInR1c3MyLVQ0IiwidHVzczEtVDI0IiwidHVzczMtVDI0IikKCiMgUmVtb3ZlICJCYWN0ZXJpYSIgZnJvbSBkYXRhc2V0CnRheGFfcmlib19kbmFfZnVuZ2kyPC10YXhhX3JpYm9fZG5hX2Z1bmdpMlshZ3JlcGwoIkJhY3RlcmlhIiwgdGF4YV9yaWJvX2RuYV9mdW5naTIkVGF4b25vbXkpLF0KCiMgUmVtb3ZlICJBcmNoYWVhIiBmcm9tIGRhdGFzZXQKdGF4YV9yaWJvX2RuYV9mdW5naTI8LXRheGFfcmlib19kbmFfZnVuZ2kyWyFncmVwbCgiQXJjaGFlYSIsIHRheGFfcmlib19kbmFfZnVuZ2kyJFRheG9ub215KSxdCmBgYAoKYGBge3J9CiMgU29ydCBkYXRhIGJ5IEtpbmdkb20gYWxwaGFiZXRpY2FsbHkKdGF4YV9yaWJvX2RuYV9mdW5naTI8LXRheGFfcmlib19kbmFfZnVuZ2kyW29yZGVyKHRheGFfcmlib19kbmFfZnVuZ2kyJEZ1bmN0aW9uLHRheGFfcmlib19kbmFfZnVuZ2kyJFRheG9ub215KSxdCgojIFN1bSBlYWNoIGNvbHVtbiBieSB1bmlxdWUgVGF4b25vbXkKdGF4YV9yaWJvX2RuYV9mdW5naTJfc3VtPC10YXhhX3JpYm9fZG5hX2Z1bmdpMiAlPiUgZ3JvdXBfYnkoVGF4b25vbXkpICU+JSBzdW1tYXJpc2VfYXQodmFycygid3MxLVQwIiwid3MyLVQwIiwid3MzLVQwIiwid3MxLVQ0Iiwid3MyLVQ0Iiwid3MzLVQ0Iiwid3MxLVQyNCIsIndzMi1UMjQiLCJ3czMtVDI0IiwidHVzczEtVDAiLCJ0dXNzMi1UMCIsInR1c3MxLVQ0IiwidHVzczItVDQiLCJ0dXNzMS1UMjQiLCJ0dXNzMy1UMjQiKSwgc3VtKQp0YXhhX3JpYm9fZG5hX2Z1bmdpMl9zdW08LXRheGFfcmlib19kbmFfZnVuZ2kyX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMoJ3dzMS1UMCcsJ3dzMi1UMCcsJ3dzMy1UMCcsJ3dzMS1UNCcsJ3dzMi1UNCcsJ3dzMy1UNCcsJ3dzMS1UMjQnLCd3czItVDI0Jywnd3MzLVQyNCcsJ3R1c3MxLVQwJywndHVzczItVDAnLCd0dXNzMS1UNCcsJ3R1c3MyLVQ0JywndHVzczEtVDI0JywndHVzczMtVDI0JyksIGZ1bnMocm91bmQoLiwgMCkpKQp0YXhhX3JpYm9fZG5hX2Z1bmdpMl9zdW08LWFzLmRhdGEuZnJhbWUodGF4YV9yaWJvX2RuYV9mdW5naTJfc3VtKQoKdGF4YV9yaWJvX2RuYV9mdW5naTJfc3VtCmBgYAoKYGBge3IgZWNobz1GQUxTRX0KIyBTYXZlIHRheGFfcmlib19kbmFfZnVuZ2kyX3N1bSBhcyAuY3N2IGZpbGUKd3JpdGUuY3N2KHRheGFfcmlib19kbmFfZnVuZ2kyX3N1bSwgJ1JpYm8uUmVzdWx0cy90YXhhLnJpYm8uZG5hLmZ1bmdpMi5zdW0uY3N2JykKYGBgCgojIyMjIDcuMS4zLiBQbG90dGluZyBUYXhvbm9teQoKUGxvdCB0aGUgcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIHRheGEgYnkgYWxsIHJlcGxpY2F0ZXMgd2l0aGluIHR1c3NvY2sgYW5kIHdldCBzZWRnZSB0dW5kcmEgYXMgYSBzdGFja3Bsb3QuCmBgYHtyIGVjaG89RkFMU0V9CnRheGEuTUcuYWxsLmNoYXJ0PC1yZWFkLmNzdigiUGxvdC5EYXRhL3RheGEuTUcuYWxsLnN0YWNrcGxvdC5jc3YiKQpgYGAKCmBgYHtyfQojIFBsYWNlIHRheGEgaW4gb3JkZXIgZm9yIHBsb3R0aW5nCnRheGEuTUcuYWxsLmNoYXJ0JFNwZWNpZXM8LWZhY3Rvcih0YXhhLk1HLmFsbC5jaGFydCRTcGVjaWVzLGxldmVscyA9IGMoIkFjaWRvYmFjdGVyaWEiLCJBY3Rpbm9iYWN0ZXJpYSIsIkFscGhhcHJvdGVvYmFjdGVyaWEiLCJCZXRhcHJvdGVvYmFjdGVyaWEiLCJEZWx0YXByb3Rlb2JhY3RlcmlhIiwiR2FtbWFwcm90ZW9iYWN0ZXJpYSIsIlByb3Rlb2JhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3Rlcm9pZGV0ZXMiLCJDaGxvcm9mbGV4aSIsIkZpcm1pY3V0ZXMiLCJQbGFuY3RvbXljZXRlcyIsIlZlcnJ1Y29taWNyb2JpYSIsIkJhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3RlcmlhIE90aGVyIiwiQXJjaGFlYSIsIkZ1bmdpIikpCgp0YXhhLk1HLmFsbC5jaGFydCRTcGVjaWVzPC1mY3RfcmV2KHRheGEuTUcuYWxsLmNoYXJ0JFNwZWNpZXMpCgp0YXhhLk1HLmFsbC5jaGFydCRTYW1wbGU8LWZhY3Rvcih0YXhhLk1HLmFsbC5jaGFydCRTYW1wbGUsbGV2ZWxzID0gYygiVHVzczEtTUctVDAiLCJUdXNzMi1NRy1UMCIsIlR1c3MxLU1HLVQ0IiwiVHVzczItTUctVDQiLCJUdXNzMS1NRy1UMjQiLCJUdXNzMy1NRy1UMjQiLCJXUzEtTUctVDAiLCJXUzItTUctVDAiLCJXUzMtTUctVDAiLCJXUzEtTUctVDQiLCJXUzItTUctVDQiLCJXUzMtTUctVDQiLCJXUzEtTUctVDI0IiwiV1MyLU1HLVQyNCIsIldTMy1NRy1UMjQiKSkKYGBgCgpgYGB7cn0KY29sb3VyQ291bnQgPSBsZW5ndGgodW5pcXVlKHRheGEuTUcuYWxsLmNoYXJ0JFNwZWNpZXMpKQpnZXRQYWxldHRlID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDEyLCAiUGFpcmVkIikpCgp0YXhhLk1HLmFsbC5wbG90PC1nZ3Bsb3QodGF4YS5NRy5hbGwuY2hhcnQsIGFlcyhmaWxsPVNwZWNpZXMsIHk9VmFsdWUsIHg9U2FtcGxlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IiwgY29sb3I9ImJsYWNrIikgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiUmVsYXRpdmUgVGF4b24iLCBwYXN0ZSgiRXhwcmVzc2lvbiAoJSkiKSkpKSArIHRoZW1lX21pbmltYWwoKSArIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjc1LCJsaW5lIiksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oU2FtcGxlKSBzdHJfd3JhcChTYW1wbGUsIHdpZHRoID0gOCkpICsgc2NhbGVfc2l6ZShndWlkZT1GQUxTRSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXYoZ2V0UGFsZXR0ZShjb2xvdXJDb3VudCkpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oU2FtcGxlKSBzdHJfd3JhcChTYW1wbGUsIHdpZHRoID0gMTUpKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdD0wKSkgCmBgYAoKYGBge3J9CnRheGEuTUcuYWxsLnBsb3QKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KIyBTYXZlIHRoZSBSaWJvc29tZSBUYXhvbm9teSBwbG90IGFzIGFuIGluZGl2aWR1YWwgZmlndXJlCnNldEVQUygpCnBvc3RzY3JpcHQoIkZpZy5TMi5SaWJvLlN0YWNrcGxvdC5lcHMiLCB3aWR0aD03LCBoZWlnaHQgPSA1LjApCmdnYXJyYW5nZSh0YXhhLnJpYm8ucGxvdCwgaGVpZ2h0cz1jKDMsMyksCiAgICAgICAgICBuY29sID0gMSwgbnJvdyA9IDEpCmRldi5vZmYoKQpgYGAKCiMjIyMgNC4yLjIgTWVhbiBUaW1lIFBvaW50CgpQbG90IHRoZSBtZWFuIHJlbGF0aXZlIGFidW5kYW5jZSBvZiB0YXhhIGJ5IHNhbXBsaW5nIHRpbWUgcG9pbnQgd2l0aGluIHR1c3NvY2sgYW5kIHdldCBzZWRnZSB0dW5kcmEgYXMgYSBzdGFja3Bsb3QuCmBgYHtyIGVjaG89RkFMU0V9CnRheGEuTUcudGltZS5tZWFuLmNoYXJ0PC1yZWFkLmNzdigiUGxvdC5EYXRhL3RheGEuTUcudGltZS5tZWFuLnN0YWNrcGxvdC5jc3YiKQpgYGAKCmBgYHtyfQojIFBsYWNlIHRheGEgaW4gb3JkZXIgZm9yIHBsb3R0aW5nCnRheGEuTUcudGltZS5tZWFuLmNoYXJ0JFNwZWNpZXM8LWZhY3Rvcih0YXhhLk1HLnRpbWUubWVhbi5jaGFydCRTcGVjaWVzLGxldmVscyA9IGMoIkFjaWRvYmFjdGVyaWEiLCJBY3Rpbm9iYWN0ZXJpYSIsIkFscGhhcHJvdGVvYmFjdGVyaWEiLCJCZXRhcHJvdGVvYmFjdGVyaWEiLCJEZWx0YXByb3Rlb2JhY3RlcmlhIiwiR2FtbWFwcm90ZW9iYWN0ZXJpYSIsIlByb3Rlb2JhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3Rlcm9pZGV0ZXMiLCJDaGxvcm9mbGV4aSIsIkZpcm1pY3V0ZXMiLCJQbGFuY3RvbXljZXRlcyIsIlZlcnJ1Y29taWNyb2JpYSIsIkJhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3RlcmlhIE90aGVyIiwiQXJjaGFlYSIsIkZ1bmdpIikpCgp0YXhhLk1HLnRpbWUubWVhbi5jaGFydCRTcGVjaWVzPC1mY3RfcmV2KHRheGEuTUcudGltZS5tZWFuLmNoYXJ0JFNwZWNpZXMpCgp0YXhhLk1HLnRpbWUubWVhbi5jaGFydCRTYW1wbGU8LWZhY3Rvcih0YXhhLk1HLnRpbWUubWVhbi5jaGFydCRTYW1wbGUsbGV2ZWxzID0gYygiVHVzcy1NRy1UMCIsIlR1c3MtTUctVDQiLCJUdXNzLU1HLVQyNCIsIldTLU1HLVQwIiwiV1MtTUctVDQiLCJXUy1NRy1UMjQiKSkKYGBgCgpgYGB7cn0KY29sb3VyQ291bnQgPSBsZW5ndGgodW5pcXVlKHRheGEuTUcudGltZS5tZWFuLmNoYXJ0JFNwZWNpZXMpKQpnZXRQYWxldHRlID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDEyLCAiUGFpcmVkIikpCgp0YXhhLk1HLnRpbWUubWVhbi5wbG90PC1nZ3Bsb3QodGF4YS5NRy50aW1lLm1lYW4uY2hhcnQsIGFlcyhmaWxsPVNwZWNpZXMsIHk9VmFsdWUsIHg9U2FtcGxlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IiwgY29sb3I9ImJsYWNrIikgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiUmVsYXRpdmUgVGF4b24iLCBwYXN0ZSgiRXhwcmVzc2lvbiAoJSkiKSkpKSArIHRoZW1lX21pbmltYWwoKSArIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjc1LCJsaW5lIiksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oU2FtcGxlKSBzdHJfd3JhcChTYW1wbGUsIHdpZHRoID0gOCkpICsgc2NhbGVfc2l6ZShndWlkZT1GQUxTRSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXYoZ2V0UGFsZXR0ZShjb2xvdXJDb3VudCkpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oU2FtcGxlKSBzdHJfd3JhcChTYW1wbGUsIHdpZHRoID0gMTUpKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdD0wKSkgCmBgYAoKYGBge3J9CnRheGEuTUcudGltZS5tZWFuLnBsb3QKYGBgCgojIyMjIDQuMi4zIE1lYW4gVHVuZHJhCgpQbG90IHRoZSBtZWFuIHJlbGF0aXZlIGFidW5kYW5jZSBvZiB0YXhhIGJ5IHdpdGhpbiB0dXNzb2NrIGFuZCB3ZXQgc2VkZ2UgdHVuZHJhIGFzIGEgc3RhY2twbG90LgpgYGB7ciBlY2hvPUZBTFNFfQp0YXhhLk1HLnR1bmRyYS5tZWFuLmNoYXJ0PC1yZWFkLmNzdigiUGxvdC5EYXRhL3RheGEuTUcudHVuZHJhLm1lYW4uc3RhY2twbG90LmNzdiIpCmBgYAoKYGBge3J9CiMgUGxhY2UgdGF4YSBpbiBvcmRlciBmb3IgcGxvdHRpbmcKdGF4YS5NRy50dW5kcmEubWVhbi5jaGFydCRTcGVjaWVzPC1mYWN0b3IodGF4YS5NRy50dW5kcmEubWVhbi5jaGFydCRTcGVjaWVzLGxldmVscyA9IGMoIkFjaWRvYmFjdGVyaWEiLCJBY3Rpbm9iYWN0ZXJpYSIsIkFscGhhcHJvdGVvYmFjdGVyaWEiLCJCZXRhcHJvdGVvYmFjdGVyaWEiLCJEZWx0YXByb3Rlb2JhY3RlcmlhIiwiR2FtbWFwcm90ZW9iYWN0ZXJpYSIsIlByb3Rlb2JhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3Rlcm9pZGV0ZXMiLCJDaGxvcm9mbGV4aSIsIkZpcm1pY3V0ZXMiLCJQbGFuY3RvbXljZXRlcyIsIlZlcnJ1Y29taWNyb2JpYSIsIkJhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3RlcmlhIE90aGVyIiwiQXJjaGFlYSIsIkZ1bmdpIikpCgp0YXhhLk1HLnR1bmRyYS5tZWFuLmNoYXJ0JFNwZWNpZXM8LWZjdF9yZXYodGF4YS5NRy50dW5kcmEubWVhbi5jaGFydCRTcGVjaWVzKQoKdGF4YS5NRy50dW5kcmEubWVhbi5jaGFydCRTYW1wbGU8LWZhY3Rvcih0YXhhLk1HLnR1bmRyYS5tZWFuLmNoYXJ0JFNhbXBsZSxsZXZlbHMgPSBjKCJUdXNzLU1HIiwiV1MtTUciKSkKYGBgCgpgYGB7cn0KY29sb3VyQ291bnQgPSBsZW5ndGgodW5pcXVlKHRheGEuTUcudHVuZHJhLm1lYW4uY2hhcnQkU3BlY2llcykpCmdldFBhbGV0dGUgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTIsICJQYWlyZWQiKSkKCnRheGEuTUcudHVuZHJhLm1lYW4ucGxvdDwtZ2dwbG90KHRheGEuTUcudHVuZHJhLm1lYW4uY2hhcnQsIGFlcyhmaWxsPVNwZWNpZXMsIHk9VmFsdWUsIHg9U2FtcGxlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IiwgY29sb3I9ImJsYWNrIikgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiUmVsYXRpdmUgVGF4b24iLCBwYXN0ZSgiRXhwcmVzc2lvbiAoJSkiKSkpKSArIHRoZW1lX21pbmltYWwoKSArIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjc1LCJsaW5lIiksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oU2FtcGxlKSBzdHJfd3JhcChTYW1wbGUsIHdpZHRoID0gOCkpICsgc2NhbGVfc2l6ZShndWlkZT1GQUxTRSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXYoZ2V0UGFsZXR0ZShjb2xvdXJDb3VudCkpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oU2FtcGxlKSBzdHJfd3JhcChTYW1wbGUsIHdpZHRoID0gMTUpKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdD0wKSkgCmBgYAoKYGBge3J9CnRheGEuTUcudHVuZHJhLm1lYW4ucGxvdApgYGAKClBsb3QgdGhlIHJlbGF0aXZlIGV4cHJlc3Npb24gb2Ygcmlib3NvbWVzIGFzIGEgc3RhY2twbG90IHdpdGggdGhlIE1FQU4gb2Ygc2FtcGxlcyBieSB0aW1lIHBvaW50CmBgYHtyIGVjaG89RkFMU0V9CnRheGEudHVzcy5kbmEubWVhbi5yaWJvLmNoYXJ0PC1yZWFkLmNzdigiUGxvdC5EYXRhL3RheGEudHVzcy5kbmEubWVhbi5yaWJvLnN0YWNrcGxvdC5jc3YiKQpgYGAKCmBgYHtyfQojIFBsYWNlIHRheGEgaW4gb3JkZXIgZm9yIHBsb3R0aW5nCnRheGEudHVzcy5kbmEubWVhbi5yaWJvLmNoYXJ0JFNwZWNpZXM8LWZhY3Rvcih0YXhhLnR1c3MuZG5hLm1lYW4ucmliby5jaGFydCRTcGVjaWVzLGxldmVscyA9IGMoIkFjaWRvYmFjdGVyaWEiLCJBY3Rpbm9iYWN0ZXJpYSIsIkFscGhhcHJvdGVvYmFjdGVyaWEiLCJCZXRhcHJvdGVvYmFjdGVyaWEiLCJEZWx0YXByb3Rlb2JhY3RlcmlhIiwiR2FtbWFwcm90ZW9iYWN0ZXJpYSIsIlByb3Rlb2JhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3Rlcm9pZGV0ZXMiLCJDaGxvcm9mbGV4aSIsIkZpcm1pY3V0ZXMiLCJQbGFuY3RvbXljZXRlcyIsIlZlcnJ1Y29taWNyb2JpYSIsIkJhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3RlcmlhIE90aGVyIiwiQXJjaGFlYSIsIkZ1bmdpIikpCgp0YXhhLnR1c3MuZG5hLm1lYW4ucmliby5jaGFydCRTcGVjaWVzPC1mY3RfcmV2KHRheGEudHVzcy5kbmEubWVhbi5yaWJvLmNoYXJ0JFNwZWNpZXMpCgp0YXhhLnR1c3MuZG5hLm1lYW4ucmliby5jaGFydCRTYW1wbGU8LWZhY3Rvcih0YXhhLnR1c3MuZG5hLm1lYW4ucmliby5jaGFydCRTYW1wbGUsbGV2ZWxzID0gYygiVHVzcy1NRy1UMCIsIlR1c3MtTUctVDQiLCJUdXNzLU1HLVQyNCIpKQpgYGAKCmBgYHtyfQpjb2xvdXJDb3VudCA9IGxlbmd0aCh1bmlxdWUodGF4YS50dXNzLmRuYS5tZWFuLnJpYm8uY2hhcnQkU3BlY2llcykpCmdldFBhbGV0dGUgPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTIsICJQYWlyZWQiKSkKCnRheGEudHVzcy5kbmEubWVhbi5yaWJvLnBsb3Q8LWdncGxvdCh0YXhhLnR1c3MuZG5hLm1lYW4ucmliby5jaGFydCwgYWVzKGZpbGw9U3BlY2llcywgeT1WYWx1ZSwgeD1TYW1wbGUpKSArIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiLCBjb2xvcj0iYmxhY2siKSArIHlsYWIoZXhwcmVzc2lvbihhdG9wKCJDb21tdW5pdHkgQ29tcG9zaXRpb24iLCBwYXN0ZSgiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpKSkpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcmV2KGdldFBhbGV0dGUoY29sb3VyQ291bnQpKSwgZ3VpZGU9Z3VpZGVfbGVnZW5kKHJldmVyc2U9RkFMU0UpKSArIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIGhqdXN0PTApLCBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEyKSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSkgKyBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSwgbGltaXRzID0gYygwLCAxMDEpKQpgYGAKCmBgYHtyfQp0YXhhLnR1c3MuZG5hLm1lYW4ucmliby5wbG90CmBgYAoKUGxvdCB0aGUgcmVsYXRpdmUgZXhwcmVzc2lvbiBvZiByaWJvc29tZXMgYXMgYSBzdGFja3Bsb3Qgd2l0aCB0aGUgTUVBTiBvZiBzYW1wbGVzIGJ5IHRpbWUgcG9pbnQKYGBge3IgZWNobz1GQUxTRX0KdGF4YS53cy5kbmEubWVhbi5yaWJvLmNoYXJ0PC1yZWFkLmNzdigiUGxvdC5EYXRhL3RheGEud3MuZG5hLm1lYW4ucmliby5zdGFja3Bsb3QuY3N2IikKYGBgCgpgYGB7cn0KIyBQbGFjZSB0YXhhIGluIG9yZGVyIGZvciBwbG90dGluZwp0YXhhLndzLmRuYS5tZWFuLnJpYm8uY2hhcnQkU3BlY2llczwtZmFjdG9yKHRheGEud3MuZG5hLm1lYW4ucmliby5jaGFydCRTcGVjaWVzLGxldmVscyA9IGMoIkFjaWRvYmFjdGVyaWEiLCJBY3Rpbm9iYWN0ZXJpYSIsIkFscGhhcHJvdGVvYmFjdGVyaWEiLCJCZXRhcHJvdGVvYmFjdGVyaWEiLCJEZWx0YXByb3Rlb2JhY3RlcmlhIiwiR2FtbWFwcm90ZW9iYWN0ZXJpYSIsIlByb3Rlb2JhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3Rlcm9pZGV0ZXMiLCJDaGxvcm9mbGV4aSIsIkZpcm1pY3V0ZXMiLCJQbGFuY3RvbXljZXRlcyIsIlZlcnJ1Y29taWNyb2JpYSIsIkJhY3RlcmlhIFVuY2xhc3NpZmllZCIsIkJhY3RlcmlhIE90aGVyIiwiQXJjaGFlYSIsIkZ1bmdpIikpCgp0YXhhLndzLmRuYS5tZWFuLnJpYm8uY2hhcnQkU3BlY2llczwtZmN0X3Jldih0YXhhLndzLmRuYS5tZWFuLnJpYm8uY2hhcnQkU3BlY2llcykKCnRheGEud3MuZG5hLm1lYW4ucmliby5jaGFydCRTYW1wbGU8LWZhY3Rvcih0YXhhLndzLmRuYS5tZWFuLnJpYm8uY2hhcnQkU2FtcGxlLGxldmVscyA9IGMoIldTLU1HLVQwIiwiV1MtTUctVDQiLCJXUy1NRy1UMjQiKSkKYGBgCgpgYGB7cn0KY29sb3VyQ291bnQgPSBsZW5ndGgodW5pcXVlKHRheGEud3MuZG5hLm1lYW4ucmliby5jaGFydCRTcGVjaWVzKSkKZ2V0UGFsZXR0ZSA9IGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCgxMiwgIlBhaXJlZCIpKQoKdGF4YS53cy5kbmEubWVhbi5yaWJvLnBsb3Q8LWdncGxvdCh0YXhhLndzLmRuYS5tZWFuLnJpYm8uY2hhcnQsIGFlcyhmaWxsPVNwZWNpZXMsIHk9VmFsdWUsIHg9U2FtcGxlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IiwgY29sb3I9ImJsYWNrIikgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiQ29tbXVuaXR5IENvbXBvc2l0aW9uIiwgcGFzdGUoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSkpKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHJldihnZXRQYWxldHRlKGNvbG91ckNvdW50KSksIGd1aWRlPWd1aWRlX2xlZ2VuZChyZXZlcnNlPUZBTFNFKSkgKyB0aGVtZV9jbGFzc2ljKCkgKyB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdD0wKSwgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNzUsImxpbmUiKSkgKyBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSwgbGltaXRzID0gYygwLCAxMDEpKQpgYGAKCmBgYHtyfQp0YXhhLndzLmRuYS5tZWFuLnJpYm8ucGxvdApgYGAKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CiMgU2F2ZSB0aGUgUmlib3NvbWUgVGF4b25vbXkgcGxvdCBhcyBhbiBpbmRpdmlkdWFsIGZpZ3VyZQpzZXRFUFMoKQpwb3N0c2NyaXB0KCJGaWcuMS4xLlRheGEuTUcuTVQuZXBzIiwgd2lkdGg9MTAuMCwgaGVpZ2h0ID0gNS4wKQpkaXYucGxvdDwtcGxvdF9ncmlkKHRheGEudHVzcy5kbmEubWVhbi5yaWJvLnBsb3QsIHRheGEud3MuZG5hLm1lYW4ucmliby5wbG90LCByZWxfd2lkdGhzID0gYygyLDMpLCBsYWJlbHM9YygiQSIsIkIiKSkKcGxvdF9ncmlkKGRpdi5wbG90LCBuY29sID0gMSkKZGV2Lm9mZigpCmBgYAoKYGBge3IgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KIyBTYXZlIHRoZSBSaWJvc29tZSBUYXhvbm9teSBwbG90IGFzIGFuIGluZGl2aWR1YWwgZmlndXJlCnNldEVQUygpCnBvc3RzY3JpcHQoIkZpZy4xLjEuMS5NRy5UYXhhLmVwcyIsIHdpZHRoPTUuMCwgaGVpZ2h0ID0gNS4wKQpnZ2FycmFuZ2UodGF4YS50dXNzLmRuYS5tZWFuLnJpYm8ucGxvdCwgbmNvbCA9IDEsIG5yb3cgPSAxLCBhbGlnbj0idiIpCmRldi5vZmYoKQpgYGAKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CiMgU2F2ZSB0aGUgUmlib3NvbWUgVGF4b25vbXkgcGxvdCBhcyBhbiBpbmRpdmlkdWFsIGZpZ3VyZQpzZXRFUFMoKQpwb3N0c2NyaXB0KCJGaWcuMS4xLjIuTUcuVGF4YS5lcHMiLCB3aWR0aD03LjAsIGhlaWdodCA9IDUuMCkKZ2dhcnJhbmdlKHRheGEud3MuZG5hLm1lYW4ucmliby5wbG90LCBuY29sID0gMSwgbnJvdyA9IDEsIGFsaWduPSJ2IikKZGV2Lm9mZigpCmBgYAoKIyMjIyA3LjEuNC4gVGF4b25vbXkgU3RhdGlzdGljcwoKVG8gZGV0ZXJtaW5lIGlmIHRoZXJlIGFyZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiBtZWFuIHJlbGF0aXZlIGFidW5kYW5jZSBvZiBkb21pbmFudCB0YXhhIGJldHdlZW4gdHVuZHJhIGVjb3N5c3RlbXMsIHdlIGNhbGN1bGF0ZSB0aGUgbWVhbiAoU0QpIG9mIGVhY2ggcGh5bHVtIChkb21pbmFudCBwaHlsdW07ID4xJSkgd2l0aGluIHR1c3NvY2sgdHVuZHJhIGFuZCB3aXRoaW4gd2V0IHNlZGdlIHR1bmRyYSB0aHJvdWdob3V0IHRoZSBleHBlcmltZW50IGFuZCBjb21wYXJlIHRvIGVhY2ggb3RoZXIuCgpgYGB7ciBlY2hvPUZBTFNFfQp0YXhhLmRuYS50YWJsZTwtcmVhZC5jc3YoIlRhYmxlLkRhdGEvdGF4YS5kbmEudGFibGUuY3N2IikKYGBgCgpgYGB7cn0KIyBSZW5hbWUgY29sdW1uIGhlYWRpbmdzCmNvbG5hbWVzKHRheGEuZG5hLnRhYmxlKTwtYygiVGF4b25vbXkiLCJUdXNzIFJlbGF0aXZlIEFidW5kYW5jZSAoJSkiLCJXUyBSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIiwiTWVhbiBEaWZmZXJlbmNlIiwgIlBhaXJlZCB0LXRlc3QgKHAtdmFsdWUpIikKCmthYmxlKHRheGEuZG5hLnRhYmxlLCBjYXB0aW9uID0gIlJlbGF0aXZlIGFidW5kYW5jZSAobWVhbiAoU0QpKSBvZiBtaWNyb2JpYWwgdGF4YSB3aXRoaW4gdHVzc29jayB0dW5kcmEgYW5kIHdldCBzZWRnZSB0dW5kcmEgd2l0aCBtZWFuIGRpZmZlcmVuY2UgKCUpIGFuZCBzaWduaWZpY2FuY2UgKHAtdmFsdWUpLiIsIGZvcm1hdC5hcmdzID0gbGlzdChiaWcubWFyayA9ICIsIiksIGFsaWduID0gImwiKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpCmBgYAoKVGVzdCBmb3IgZGlmZmVyZW5jZXMgaW4gbWVhbiByZWxhdGl2ZSBhYnVuZGFuY2Ugb2YgZG9taW5hbnQgcGh5bGEgYmV0d2VlbiB0dW5kcmEgZWNvc3lzdGVtcy4KCmBgYHtyIGVjaG89RkFMU0V9CnRheGEuZG5hLnBoeWx1bS50LnRlc3Q8LXJlYWQuY3N2KCJTdGF0cy5EYXRhL3RheGEuZG5hLnBoeWx1bS50LnRlc3QuY3N2IikKYGBgCgpgYGB7cn0KIyBQYWlyd2lzZSBjb21wYXJpc29ucyBiZXR3ZWVuIHR1bmRyYSBlY29zeXN0ZW1zIGZvciBlYWNoIG1pY3JvYmlhbCB0YXhvbm9taWMgY2xhc3MKdGF4YS5kbmEucGh5bHVtLnQudGVzdC5zdGF0cyA8LSB0YXhhLmRuYS5waHlsdW0udC50ZXN0ICU+JQogIGdyb3VwX2J5KFBoeWx1bSkgJT4lCiAgcGFpcndpc2VfdF90ZXN0KAogICAgQWJ1bmRhbmNlIH4gVHVuZHJhLCBwYWlyZWQgPSBUUlVFLCAKICAgIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIgogICAgKSAlPiUKICBzZWxlY3QoLS55LiwgLW4xLCAtbjIsIC1kZiwgLXN0YXRpc3RpYywgLXApICMgUmVtb3ZlIGRldGFpbHMKdGF4YS5kbmEucGh5bHVtLnQudGVzdC5zdGF0cwpgYGAKCioqQWxwaGEgRGl2ZXJzaXR5OioqICBXZSBhbHNvIHRlc3QgZm9yIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIHRoZSBkaXZlcnNpdHkgb2YgbWljcm9iaWFsIHRheGEgYmV0d2VlbiB0dW5kcmEgZWNvc3lzdGVtcy4KYGBge3IgZWNobz1GQUxTRX0KYWxwaGEuZG5hLnRheGE8LXJlYWQuY3N2KCJTdGF0cy5EYXRhL0FMUEhBLnRheGEuZG5hLnNzdS5jc3YiKQoKcm93bmFtZXMoYWxwaGEuZG5hLnRheGEpIDwtIGFscGhhLmRuYS50YXhhJElECmFscGhhLmRuYS50YXhhWzFdIDwtIE5VTEwKYGBgCgpgYGB7cn0KIyBSaWNobmVzczogU3VtIHVwIHRoZSBudW1iZXIgb2Ygbm9uLXplcm8gZW50cmllcyBwZXIgcm93CmFscGhhLmRuYS50YXhhLnJpY2ggPC0gYXBwbHkoYWxwaGEuZG5hLnRheGE+MCwxLHN1bSkKd3JpdGUuY3N2KGFscGhhLmRuYS50YXhhLnJpY2gsICdSaWJvLlJlc3VsdHMvYWxwaGEuZG5hLnRheGEucmljaC5jc3YnKQphbHBoYS5kbmEudGF4YS5yaWNoCgojIEFidW5kYW5jZTogc3VtIHVwIHRoZSBudW1iZXIgb2Ygbm9uLXplcm8gZW50cmllcyBwZXIgcm93ICgxKQphbHBoYS5kbmEudGF4YS5hYnVuZCA8LSBhcHBseShhbHBoYS5kbmEudGF4YSwxLHN1bSkKd3JpdGUuY3N2KGFscGhhLmRuYS50YXhhLmFidW5kLCAnUmliby5SZXN1bHRzL2FscGhhLmRuYS50YXhhLmFidW5kLmNzdicpCmFscGhhLmRuYS50YXhhLmFidW5kCgojIERpdmVyc2l0eTogU2hhbm5vbi1XaWVuZXIgSW5kZXggKEgnKQphbHBoYS5kbmEudGF4YS5kaXYgPC0gZGl2ZXJzaXR5KGFscGhhLmRuYS50YXhhLCBpbmRleD0ic2hhbm5vbiIpCndyaXRlLmNzdihhbHBoYS5kbmEudGF4YS5kaXYsICdSaWJvLlJlc3VsdHMvYWxwaGEuZG5hLnRheGEuZGl2LmNzdicpCmFscGhhLmRuYS50YXhhLmRpdgpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmFscGhhLmRuYS50YXhhLnQudGVzdDwtcmVhZC5jc3YoIlN0YXRzLkRhdGEvYWxwaGEuZG5hLnRheGEudC50ZXN0LmNzdiIpCmBgYAoKUnVuIHBhaXJlZCB0LXRlc3QgdG8gZGV0ZXJtaW5lIHNpZ25pZmljYW5jZSBmb3IgU2hhbm5vbiBEaXZlcnNpdHkuCmBgYHtyfQp0LnRlc3QoYWxwaGEuZG5hLnRheGEudC50ZXN0JFR1c3MsYWxwaGEuZG5hLnRheGEudC50ZXN0JFdTLHBhaXJlZD1UUlVFKQpgYGAKCkJldGEgRGl2ZXJzaXR5CgpDYWxjdWxhdGUgdGhlIEJyYXktQ3VydGlzIGRpc3NpbWlsYXJpdHkgbWF0cml4IHRvIHVzZSB3aXRoIGBhZG9uaXNgCgpgYGB7ciBlY2hvPUZBTFNFfQpiZXRhLmRuYS50YXhhPC1yZWFkLmNzdigiU3RhdHMuRGF0YS9BTFBIQS50YXhhLmRuYS5zc3UuY3N2IikKCnJvd25hbWVzKGJldGEuZG5hLnRheGEpIDwtIGJldGEuZG5hLnRheGEkSUQKYmV0YS5kbmEudGF4YVsxXSA8LSBOVUxMCmBgYAoKYGBge3J9CiMgTWFrZSBkbmFfdGF4YV9ncG1fYWxsX2dyb3VwcyBvYmplY3QKYmV0YS5kbmEudGF4YV9zYW1wbGU8LWMoIndzMS1UMCIsIndzMi1UMCIsIndzMy1UMCIsIndzMS1UNCIsIndzMi1UNCIsIndzMy1UNCIsIndzMS1UMjQiLCJ3czItVDI0Iiwid3MzLVQyNCIsInR1c3MxLVQwIiwidHVzczItVDAiLCJ0dXNzMS1UNCIsInR1c3MyLVQ0IiwidHVzczEtVDI0IiwidHVzczItVDI0IikKYmV0YS5kbmEudGF4YV92ZWc8LWMoIldTIiwiV1MiLCJXUyIsIldTIiwiV1MiLCJXUyIsIldTIiwiV1MiLCJXUyIsIlRVU1MiLCJUVVNTIiwiVFVTUyIsIlRVU1MiLCJUVVNTIiwiVFVTUyIpCmJldGEuZG5hLnRheGFfdGltZTwtYygiVDAiLCJUMCIsIlQwIiwiVDQiLCJUNCIsIlQ0IiwiVDI0IiwiVDI0IiwiVDI0IiwiVDAiLCJUMCIsIlQ0IiwiVDQiLCJUMjQiLCJUMjQiKQpiZXRhLmRuYS50YXhhX2dyb3VwczwtZGF0YS5mcmFtZShiZXRhLmRuYS50YXhhX3NhbXBsZSxiZXRhLmRuYS50YXhhX3ZlZyxiZXRhLmRuYS50YXhhX3RpbWUpCgojIENvbnZlcnQgdGhlIHZhbHVlcyBpbiBDb2x1bW4gMSAoImJldGEuZG5hLnRheGFfc2FtcGxlIikgaW50byByb3cgbmFtZXMKcm93bmFtZXMoYmV0YS5kbmEudGF4YV9ncm91cHMpPC1iZXRhLmRuYS50YXhhX2dyb3Vwc1ssMV0KYmV0YS5kbmEudGF4YV9ncm91cHM8LWJldGEuZG5hLnRheGFfZ3JvdXBzWywtMV0KYGBgCgpgYGB7cn0KIyBCcmF5LUN1cnRpcyBEaXNzaW1pbGFyaXR5IE1hdHJpeCBmb3IgdHBtX2FsbF90YXhhX2JldGEKZG5hLnRwbS50YXhhLmJjLmRpc3Q8LXZlZ2Rpc3QoYmV0YS5kbmEudGF4YSwgbWV0aG9kID0gImJyYXkiKQpgYGAKClJ1biBQRVJNQU5PVkEgdXNpbmcgYGFkb25pc2AgZnVuY3Rpb24gb2YgdGhlICoqVmVnYW4qKiBwYWNrYWdlCgpQRVJNQU5PVkEgLSBNRy1HUE0tVGF4YSAtIEJyYXktQ3VydGlzCmBgYHtyfQphZG9uaXMoZG5hLnRwbS50YXhhLmJjLmRpc3R+YmV0YS5kbmEudGF4YV92ZWcqYmV0YS5kbmEudGF4YV90aW1lLCBkYXRhPWJldGEuZG5hLnRheGFfZ3JvdXBzKQpgYGAKCiMjIyA3LjIuIEdlbmUgRGl2ZXJzaXR5CgpBbHBoYSBkaXZlcnNpdHkgb2YgZWFjaCBwb3RlbnRpYWwsIGFubm90YXRlZCBtZXRhZ2Vub21lIHdhcyBhc3Nlc3NlZCBieSB0aGUgU2hhbm5vbiBpbmRleC4gRm9yIGJldGEgZGl2ZXJzaXR5LCBwYWlyd2lzZSBzaW1pbGFyaXRpZXMgYW1vbmcgbWV0YWdlbm9tZXMgd2VyZSBjYWxjdWxhdGVkIHVzaW5nIEJyYXktQ3VydGlzIHNpbWlsYXJpdHkgdmFsdWVzIGFuZCB2aXN1YWxpemVkIHdpdGggcHJpbmNpcGxlIGNvb3JkaW5hdGVzIGFuYWx5c2lzLiBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRyZWF0bWVudHMgd2FzIGFzc2Vzc2VkIHdpdGggUEVSTUFOT1ZBLgoKIyMjIyA3LjIuMS4gQWxwaGEgRGl2ZXJzaXR5CgpXZSBjYWxjdWxhdGVkIGFscGhhIGRpdmVyc2l0eSBiYXNlZCBvbiByYXcgZ2VuZSBjb3VudHMuICBNZWFzdXJlbWVudHMgaW5jbHVkZSAqKlJpY2huZXNzKiosICoqQWJ1bmRhbmNlKiosIGFuZCAqKlNoYW5ub24tV2llbmVyIERpdmVyc2l0eSBJbmRleCAoSCcpKiouCgpgYGB7cn0KIyBTdWJzZXQgdGhlIHJwbV9hbGxfZXhwX2FubiBmaWxlIHRvIHByZXBhcmUgZm9yIGFscGhhIGRpdmVyc2l0eSBhbmFseXNpcwpjdHNfZG5hX2FsbF9hbHBoYTwtc3Vic2V0KGN0c19kbmFfcG90X2Fubiwgc2VsZWN0PWMoUzEwNzEwNCxTMTA3MTA1LFMxMDcxMDYsUzEwNzExMCxTMTA3MTExLFMxMDcxMTIsUzEwNzExMyxTMTA3MTE0LFMxMDcxMTUsUzEwNzEwNyxTMTA3MTA4LFMxMDcxMTYsUzEwNzExNyxTMTA3MTE5LFMxMDcxMjEpKQpuYW1lcyhjdHNfZG5hX2FsbF9hbHBoYSk8LWMoIldTMS1UMCIsIldTMi1UMCIsIldTMy1UMCIsIldTMS1UNCIsIldTMi1UNCIsIldTMy1UNCIsIldTMS1UMjQiLCJXUzItVDI0IiwiV1MzLVQyNCIsIlR1c3MxLVQwIiwiVHVzczItVDAiLCJUdXNzMS1UNCIsIlR1c3MyLVQ0IiwiVHVzczEtVDI0IiwiVHVzczMtVDI0IikKCiMgVHJhbnNwb3NlIGFsbCBidXQgdGhlIGZpcnN0IGNvbHVtbiAoIklEIikKY3RzX2RuYV9hbGxfYWxwaGE8LWFzLmRhdGEuZnJhbWUodChjdHNfZG5hX2FsbF9hbHBoYSkpCmBgYAoKKipSaWNobmVzczoqKiBEZXRlcm1pbmUgdGhlIG51bWJlciBvZiB1bmlxdWUgZ2VuZWNhbGxzIHRoYXQgaGF2ZSBtb3JlIHRoYW4gb25lIGNvdW50IHJlY29yZGVkIHdpdGhpbiBlYWNoIHNhbXBsZS4KCmBgYHtyfQojIFN1bSB1cCB0aGUgbnVtYmVyIG9mIG5vbi16ZXJvIGVudHJpZXMgcGVyIHJvdwphcHBseShjdHNfZG5hX2FsbF9hbHBoYT4wLDEsc3VtKQpgYGAKCioqQWJ1bmRhbmNlOioqIERldGVybWluZSB0aGUgdG90YWwgYWJ1bmRhbmNlIG9mIGluZGl2aWR1YWwgZ2VuZWNhbGxzCgpgYGB7cn0KIyBzdW0gdXAgdGhlIG51bWJlciBvZiBub24temVybyBlbnRyaWVzIHBlciByb3cgKDEpCmFwcGx5KGN0c19kbmFfYWxsX2FscGhhLDEsc3VtKQpgYGAKCioqU2hhbm5vbi1XaWVuZXIgRGl2ZXJzaXR5IEluZGV4IChIJyk6KiogQW4gaW5mb3JtYXRpb24gaW5kZXggdGhhdCBxdWFudGlmaWVzIHRoZSB1bmNlcnRhaW50eSBhc3NvY2lhdGVkIHdpdGggcHJlZGljdGluZyB0aGUgaWRlbnRpdHkgb2YgYSBuZXcgZ2VuZWNhbGwgZ2l2ZW4gdGhlIHRvdGFsIG51bWJlciBvZiBnZW5lY2FsbHMgYW5kIHRoZSBldmVubmVzcyBpbiBjb3VudCBhYnVuZGFuY2VzIHdpdGhpbiBlYWNoIGdlbmVjYWxsLgoKYGBge3J9CmRpdmVyc2l0eShjdHNfZG5hX2FsbF9hbHBoYSwgaW5kZXg9InNoYW5ub24iKQpgYGAKClRoZSBmb2xsb3dpbmcgdGFibGUgaXMgYSBzdW1tYXJ5IG9mIHRoZSAqKkFscGhhIERpdmVyc2l0eSoqIG9uIHRoZSByYXcgZ2VuZSBjb3VudHMgZm9yIHRoZSAqKlBvdGVudGlhbCBBbm5vdGF0ZWQgR2VuZXMqKiAoKnBvdGVudGlhbCBhbm5vdGF0ZWQgZ2VuZXMgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMqKSBieSBzYW1wbGUuCgpgYGB7ciBlY2hvPUZBTFNFfQpkbmEuZXhwZXJpbWVudDwtcmVhZC50YWJsZSgiVGFibGUuRGF0YS9kbmEuYWxwaGEuc3VtbWFyeS50YWJsZS50eHQiLHNlcD0nXHQnLCBxdW90ZT0iIiwgZmlsbD1UUlVFLGhlYWRlciA9IFRSVUUpCm5hbWVzKGRuYS5leHBlcmltZW50KTwtYygiSUQiLCAiVHVuZHJhIiwgIlRpbWUiLCAiUmVwbGljYXRlIiwgIkdlbmUgUmljaG5lc3MiLCJHZW5lIEFidW5kYW5jZSIsIkdlbmUgRGl2ZXJzaXR5IChIJykiKQprYWJsZShkbmEuZXhwZXJpbWVudCwgY2FwdGlvbiA9ICJBbHBoYSBEaXZlcnNpdHkgZm9yIFBvdGVudGlhbCBBbm5vdGF0ZWQgR2VuZWNhbGxzIGluIHRoZSBETkEtYmFzZWQgbWV0YWdlbm9taWMgc2VxdWVuY2luZyBkYXRhc2V0IiwgZm9ybWF0LmFyZ3MgPSBsaXN0KGJpZy5tYXJrID0gIiwiKSwgYWxpZ24gPSAiYyIpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQphbHBoYS5kbmEudC50ZXN0PC1yZWFkLmNzdigiU3RhdHMuRGF0YS9hbHBoYS5kbmEudC50ZXN0LmNzdiIpCmBgYAoKUnVuIHBhaXJlZCB0LXRlc3QgdG8gZGV0ZXJtaW5lIHNpZ25pZmljYW5jZS4KYGBge3J9CnQudGVzdChhbHBoYS5kbmEudC50ZXN0JFR1c3MsYWxwaGEuZG5hLnQudGVzdCRXUyxwYWlyZWQ9VFJVRSkKYGBgCgpQbG90IHRoZSBBbHBoYSBEaXZlcnNpdHkgc3VtbWFyeS4KCmBgYHtyIGVjaG89RkFMU0V9CmFscGhhLmRuYTwtcmVhZC5jc3YoIlBsb3QuRGF0YS9hbHBoYS5kbmEuYm94cGxvdC5jc3YiKQpgYGAKCmBgYHtyfQojIFJlLWFycmFuZ2Ugc2FtcGxlcyBmb3IgcGxvdHRpbmcgUENvQQphbHBoYS5kbmEkVHVuZHJhIDwtIGZhY3RvcihhbHBoYS5kbmEkVHVuZHJhLCBsZXZlbHM9YygiVHVzcy1NRy1UMCIsIlR1c3MtTUctVDQiLCJUdXNzLU1HLVQyNCIsIldTLU1HLVQwIiwiV1MtTUctVDQiLCJXUy1NRy1UMjQiKSkKCmFscGhhLmRuYS5ib3hwbG90PC1nZ3Bsb3QoYWxwaGEuZG5hLCBhZXMoeD1UdW5kcmEsIHk9SCwgZmlsbD1UdW5kcmEpKSArIAogICAgZ2VvbV9ib3hwbG90KCkgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiU2hhbm5vbi1XaWVuZXIiLCBwYXN0ZSgiRGl2ZXJzaXR5IEluZGV4IChIJykiKSkpKSArIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdD0wLCB2anVzdD0wLjUpLCBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEyKSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpICsgeWxpbSgxMS41LDEzKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTMuNSwgeT0xMywgbGFiZWw9IlBhaXJlZCB0LXRlc3QiKSArIGFubm90YXRlKCJ0ZXh0IiwgeD0zLjUsIHk9MTIuOSwgc2l6ZT0zLCBsYWJlbCA9ICJUdW5kcmF+KGl0YWxpYyhwKSA8IDAuMDAxKSIsIHBhcnNlID0gVFJVRSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiZ3JheTgzIiwgImdyYXk4MyIsICJncmF5ODMiLCAiYmxhY2siLCAiYmxhY2siLCAiYmxhY2siKSwgYnJlYWtzPWMoIlR1c3MtTUctVDAiLCAiV1MtTUctVDAiLCAiVHVzcy1NRy1UNCIsICJXUy1NRy1UNCIsICJUdXNzLU1HLVQyNCIsICJXUy1NRy1UMjQiKSwgbGFiZWxzPWMoIlR1c3MtTUctVDAiLCAiV1MtTUctVDAiLCAiVHVzcy1NRy1UNCIsICJXUy1NRy1UNCIsICJUdXNzLU1HLVQyNCIsICJXUy1NRy1UMjQiKSkKYGBgCgpgYGB7cn0KYWxwaGEuZG5hLmJveHBsb3QKYGBgCgojIyMjIDcuMi4yLiBCZXRhIERpdmVyc2l0eQoKV2UgY2FsY3VsYXRlZCBiZXRhIGRpdmVyc2l0eSBhcyB0aGUgdmFyaWF0aW9uIGluIGdlbmUgcG90ZW50aWFsIGJldHdlZW4gb3VyIHR3byB0dW5kcmEgZWNvc3lzdGVtcyB1c2luZyBCcmF5LUN1cnRpcyBzaW1pbGFyaXR5IHZhbHVlcy4KCiMjIyMjIDcuMi4yLjEuIFN1YnNldCBEYXRhCgpGaXJzdCwgc3Vic2V0IHRoZSBjb2x1bW5zIG9mIGludGVyZXN0IGZyb20gdGhlICoqZ3BtX2FsbF9wb3RfYW5uKiogb2JqZWN0IChJRCBhbmQgYWxsIHNhbXBsZXMpIHRvIGFuYWx5emUgdGhlIGJldGEgZGl2ZXJzaXR5IG9mIGJvdGggZWNvc3lzdGVtcyB0b2dldGhlci4gQ3JlYXRlIGEgKipncG1fZ3JvdXBzKiogb2JqZWN0IHdpdGggY29sdW1ucyBmb3Igc2FtcGxlIElELCB2ZWdldGF0aW9uIHR5cGUsIGFuZCB0aW1lcG9pbnQgdG8gYmUgdXNlZCBmb3IgY2FsY3VsYXRpbmcgcGFpcndpc2Ugc2ltaWxpYXJpdGllcyBhbW9uZyBzYW1wbGVzIHZpYSBQRVJNQU5PVkEgKCpgYWRvbmlzYCBmcm9tICoqVmVnYW4qKiBwYWNrYWdlKikKCmBgYHtyfQojIFN1YnNldCB0aGUgZ3BtX2FsbF9wb3RfYW5uIGZpbGUgdG8gcHJlcGFyZSBmb3IgYmV0YSBkaXZlcnNpdHkgYW5hbHlzaXMKZ3BtX2FsbF9iZXRhPC1zdWJzZXQoZ3BtX2FsbF9wb3RfYW5uLCBzZWxlY3Q9YyhJRCxTMTA3MTA0LFMxMDcxMDUsUzEwNzEwNixTMTA3MTEwLFMxMDcxMTEsUzEwNzExMixTMTA3MTEzLFMxMDcxMTQsUzEwNzExNSxTMTA3MTA3LFMxMDcxMDgsUzEwNzExNixTMTA3MTE3LFMxMDcxMTksUzEwNzEyMSkpCm5hbWVzKGdwbV9hbGxfYmV0YSk8LWMoIklEIiwiV1MxLVQwIiwiV1MyLVQwIiwiV1MzLVQwIiwiV1MxLVQ0IiwiV1MyLVQ0IiwiV1MzLVQ0IiwiV1MxLVQyNCIsIldTMi1UMjQiLCJXUzMtVDI0IiwiVHVzczEtVDAiLCJUdXNzMi1UMCIsIlR1c3MxLVQ0IiwiVHVzczItVDQiLCJUdXNzMS1UMjQiLCJUdXNzMy1UMjQiKQoKIyBSZW1lbWJlciAiSUQiIGNvbHVtbiBhcyBub24tbnVtZXJpYyB2YWx1ZXMKZ3BtX2FsbF9iZXRhX0lEPC1ncG1fYWxsX2JldGEkSUQKCiMgVHJhbnNwb3NlIGFsbCBidXQgdGhlIGZpcnN0IGNvbHVtbiAoIklEIikKZ3BtX2FsbF9iZXRhPC1hcy5kYXRhLmZyYW1lKHQoZ3BtX2FsbF9iZXRhWywtMV0pKQpjb2xuYW1lcyhncG1fYWxsX2JldGEpPC1ncG1fYWxsX2JldGFfSUQKCiMgTWFrZSBncG1fYWxsX2dyb3VwcyBvYmplY3QKZ3BtX2FsbF9zYW1wbGU8LWMoIldTMS1UMCIsIldTMi1UMCIsIldTMy1UMCIsIldTMS1UNCIsIldTMi1UNCIsIldTMy1UNCIsIldTMS1UMjQiLCJXUzItVDI0IiwiV1MzLVQyNCIsIlR1c3MxLVQwIiwiVHVzczItVDAiLCJUdXNzMS1UNCIsIlR1c3MyLVQ0IiwiVHVzczEtVDI0IiwiVHVzczMtVDI0IikKZ3BtX2FsbF92ZWc8LWMoIldTIiwiV1MiLCJXUyIsIldTIiwiV1MiLCJXUyIsIldTIiwiV1MiLCJXUyIsIlRVU1MiLCJUVVNTIiwiVFVTUyIsIlRVU1MiLCJUVVNTIiwiVFVTUyIpCmdwbV9hbGxfdGltZTwtYygiVDAiLCJUMCIsIlQwIiwiVDQiLCJUNCIsIlQ0IiwiVDI0IiwiVDI0IiwiVDI0IiwiVDAiLCJUMCIsIlQ0IiwiVDQiLCJUMjQiLCJUMjQiKQpncG1fYWxsX2dyb3VwczwtZGF0YS5mcmFtZShncG1fYWxsX3NhbXBsZSxncG1fYWxsX3ZlZyxncG1fYWxsX3RpbWUpCgojIENvbnZlcnQgdGhlIHZhbHVlcyBpbiBDb2x1bW4gMSAoImdwbV9zYW1wbGUiKSBpbnRvIHJvdyBuYW1lcwpyb3duYW1lcyhncG1fYWxsX2dyb3Vwcyk8LWdwbV9hbGxfZ3JvdXBzWywxXQpncG1fYWxsX2dyb3VwczwtZ3BtX2FsbF9ncm91cHNbLC0xXQpgYGAKClNlY29uZCwgc3Vic2V0IHRoZSBjb2x1bW5zIG9mIGludGVyZXN0IGZyb20gdGhlICoqZ3BtX2FsbF9wb3RfYW5uKiogb2JqZWN0IChJRCBhbmQgYWxsIHNhbXBsZXMpIHRvIGFuYWx5emUgdGhlIGJldGEgZGl2ZXJzaXR5IG9mIHRoZSBXZXQgU2VkZ2UgZWNvc3lzdGVtCgpgYGB7cn0KIyBTdWJzZXQgdGhlIGdwbV93c19leHBfYW5uIGZpbGUgdG8gcHJlcGFyZSBmb3IgYmV0YSBkaXZlcnNpdHkgYW5hbHlzaXMKZ3BtX3dzX2JldGE8LXN1YnNldChncG1fYWxsX3BvdF9hbm4sIHNlbGVjdD1jKElELFMxMDcxMDQsUzEwNzEwNSxTMTA3MTA2LFMxMDcxMTAsUzEwNzExMSxTMTA3MTEyLFMxMDcxMTMsUzEwNzExNCxTMTA3MTE1KSkKbmFtZXMoZ3BtX3dzX2JldGEpPC1jKCJJRCIsIldTMS1UMCIsIldTMi1UMCIsIldTMy1UMCIsIldTMS1UNCIsIldTMi1UNCIsIldTMy1UNCIsIldTMS1UMjQiLCJXUzItVDI0IiwiV1MzLVQyNCIpCgojIFJlbWVtYmVyICJJRCIgY29sdW1uIGFzIG5vbi1udW1lcmljIHZhbHVlcwpncG1fd3NfYmV0YV9JRDwtZ3BtX3dzX2JldGEkSUQKCiMgVHJhbnNwb3NlIGFsbCBidXQgdGhlIGZpcnN0IGNvbHVtbiAoIklEIikKZ3BtX3dzX2JldGE8LWFzLmRhdGEuZnJhbWUodChncG1fd3NfYmV0YVssLTFdKSkKY29sbmFtZXMoZ3BtX3dzX2JldGEpPC1ncG1fd3NfYmV0YV9JRAoKIyBNYWtlIGdwbV93c19ncm91cHMgb2JqZWN0CmdwbV93c19zYW1wbGU8LWMoIldTMS1UMCIsIldTMi1UMCIsIldTMy1UMCIsIldTMS1UNCIsIldTMi1UNCIsIldTMy1UNCIsIldTMS1UMjQiLCJXUzItVDI0IiwiV1MzLVQyNCIpCmdwbV93c192ZWc8LWMoIldTIiwiV1MiLCJXUyIsIldTIiwiV1MiLCJXUyIsIldTIiwiV1MiLCJXUyIpCmdwbV93c190aW1lPC1jKCJUMCIsIlQwIiwiVDAiLCJUNCIsIlQ0IiwiVDQiLCJUMjQiLCJUMjQiLCJUMjQiKQpncG1fd3NfZ3JvdXBzPC1kYXRhLmZyYW1lKGdwbV93c19zYW1wbGUsZ3BtX3dzX3ZlZyxncG1fd3NfdGltZSkKCiMgQ29udmVydCB0aGUgdmFsdWVzIGluIENvbHVtbiAxICgiZ3BtX3NhbXBsZSIpIGludG8gcm93IG5hbWVzCnJvd25hbWVzKGdwbV93c19ncm91cHMpPC1ncG1fd3NfZ3JvdXBzWywxXQpncG1fd3NfZ3JvdXBzPC1ncG1fd3NfZ3JvdXBzWywtMV0KYGBgCgpUaGlyZCwgc3Vic2V0IHRoZSBjb2x1bW5zIG9mIGludGVyZXN0IGZyb20gdGhlICoqZ3BtX2FsbF9wb3RfYW5uKiogb2JqZWN0IChJRCBhbmQgYWxsIHNhbXBsZXMpIHRvIGFuYWx5emUgdGhlIGJldGEgZGl2ZXJzaXR5IG9mIHRoZSBUdXNzb2NrIGVjb3N5c3RlbQoKYGBge3J9CiMgU3Vic2V0IHRoZSBncG1fdHVzc19leHBfYW5uIGZpbGUgdG8gcHJlcGFyZSBmb3IgYmV0YSBkaXZlcnNpdHkgYW5hbHlzaXMKZ3BtX3R1c3NfYmV0YTwtc3Vic2V0KGdwbV9hbGxfcG90X2Fubiwgc2VsZWN0PWMoSUQsUzEwNzEwNyxTMTA3MTA4LFMxMDcxMTYsUzEwNzExNyxTMTA3MTE5LFMxMDcxMjEpKQpuYW1lcyhncG1fdHVzc19iZXRhKTwtYygiSUQiLCJUdXNzMS1UMCIsIlR1c3MyLVQwIiwiVHVzczEtVDQiLCJUdXNzMi1UNCIsIlR1c3MxLVQyNCIsIlR1c3MzLVQyNCIpCgojIFJlbWVtYmVyICJJRCIgY29sdW1uIGFzIG5vbi1udW1lcmljIHZhbHVlcwpncG1fdHVzc19iZXRhX0lEPC1ncG1fdHVzc19iZXRhJElECgojIFRyYW5zcG9zZSBhbGwgYnV0IHRoZSBmaXJzdCBjb2x1bW4gKCJJRCIpCmdwbV90dXNzX2JldGE8LWFzLmRhdGEuZnJhbWUodChncG1fdHVzc19iZXRhWywtMV0pKQpjb2xuYW1lcyhncG1fdHVzc19iZXRhKTwtZ3BtX3R1c3NfYmV0YV9JRAoKIyBNYWtlIGdwbV90dXNzX2dyb3VwcyBvYmplY3QKZ3BtX3R1c3Nfc2FtcGxlPC1jKCJUdXNzMS1UMCIsIlR1c3MyLVQwIiwiVHVzczEtVDQiLCJUdXNzMi1UNCIsIlR1c3MxLVQyNCIsIlR1c3MzLVQyNCIpCmdwbV90dXNzX3ZlZzwtYygiVFVTUyIsIlRVU1MiLCJUVVNTIiwiVFVTUyIsIlRVU1MiLCJUVVNTIikKZ3BtX3R1c3NfdGltZTwtYygiVDAiLCJUMCIsIlQ0IiwiVDQiLCJUMjQiLCJUMjQiKQpncG1fdHVzc19ncm91cHM8LWRhdGEuZnJhbWUoZ3BtX3R1c3Nfc2FtcGxlLGdwbV90dXNzX3ZlZyxncG1fdHVzc190aW1lKQoKIyBDb252ZXJ0IHRoZSB2YWx1ZXMgaW4gQ29sdW1uIDEgKCJncG1fc2FtcGxlIikgaW50byByb3cgbmFtZXMKcm93bmFtZXMoZ3BtX3R1c3NfZ3JvdXBzKTwtZ3BtX3R1c3NfZ3JvdXBzWywxXQpncG1fdHVzc19ncm91cHM8LWdwbV90dXNzX2dyb3Vwc1ssLTFdCmBgYAoKIyMjIyMgNy4yLjIuMi4gQnJheS1DdXJ0aXMKCkNhbGN1bGF0ZSB0aGUgQnJheS1DdXJ0aXMgZGlzc2ltaWxhcml0eSBtYXRyaXggdG8gdXNlIHdpdGggYGFkb25pc2AKCmBgYHtyfQojIEJyYXktQ3VydGlzIERpc3NpbWlsYXJpdHkgTWF0cml4IGZvciBncG1fYWxsX2JldGEKZ3BtLmFsbC5iYy5kaXN0PC12ZWdkaXN0KGdwbV9hbGxfYmV0YSwgbWV0aG9kID0gImJyYXkiKQoKIyBCcmF5LUN1cnRpcyBEaXNzaW1pbGFyaXR5IE1hdHJpeCBmb3IgZ3BtX3dzX2JldGEKZ3BtLndzLmJjLmRpc3Q8LXZlZ2Rpc3QoZ3BtX3dzX2JldGEsIG1ldGhvZCA9ICJicmF5IikKCiMgQnJheS1DdXJ0aXMgRGlzc2ltaWxhcml0eSBNYXRyaXggZm9yIGdwbV90dXNzX2JldGEKZ3BtLnR1c3MuYmMuZGlzdDwtdmVnZGlzdChncG1fdHVzc19iZXRhLCBtZXRob2QgPSAiYnJheSIpCmBgYAoKIyMjIyMgNy4yLjIuMy4gUENvQSBQbG90cwoKUHJpbmNpcGFsIGNvb3JkaW5hdGVzIGFuYWx5c2lzIChQQ29BLCBhbHNvIGtub3duIGFzIG1ldHJpYyBtdWx0aWRpbWVuc2lvbmFsIHNjYWxpbmcpIGF0dGVtcHRzIHRvIHJlcHJlc2VudCB0aGUgZGlzdGFuY2VzIGJldHdlZW4gc2FtcGxlcyBpbiBhIGxvdy1kaW1lbnNpb25hbCwgRXVjbGlkZWFuIHNwYWNlLiBJbiBwYXJ0aWN1bGFyLCBpdCBtYXhpbWl6ZXMgdGhlIGxpbmVhciBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBkaXN0YW5jZXMgaW4gdGhlIGRpc3RhbmNlIG1hdHJpeCwgYW5kIHRoZSBkaXN0YW5jZXMgaW4gYSBzcGFjZSBvZiBsb3cgZGltZW5zaW9uICh0eXBpY2FsbHksIDIgb3IgMyBheGVzIGFyZSBzZWxlY3RlZCkuCgpUaGUgZmlyc3Qgc3RlcCBvZiBhIFBDb0EgaXMgdGhlIGNvbnN0cnVjdGlvbiBvZiBhIChkaXMpc2ltaWxhcml0eSBtYXRyaXguIFdoaWxlIFBDQSAocHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcykgaXMgYmFzZWQgb24gRXVjbGlkZWFuIGRpc3RhbmNlcywgUENvQSBjYW4gaGFuZGxlIChkaXMpc2ltaWxhcml0eSBtYXRyaWNlcyBjYWxjdWxhdGVkIGZyb20gcXVhbnRpdGF0aXZlLCBzZW1pLXF1YW50aXRhdGl2ZSwgcXVhbGl0YXRpdmUsIGFuZCBtaXhlZCB2YXJpYWJsZXMuIEFzIGFsd2F5cywgdGhlIGNob2ljZSBvZiAoZGlzKXNpbWlsYXJpdHkgbWVhc3VyZSBpcyBjcml0aWNhbCBhbmQgbXVzdCBiZSBzdWl0YWJsZSB0byB0aGUgZGF0YSBpbiBxdWVzdGlvbi4gRm9yIGNvdW50IGRhdGEsIEJyYXktQ3VydGlzIGRpc3RhbmNlIGlzIHJlY29tbWVuZGVkLiBZb3UgY2FuIHVzZSBKYWNjYXJkIGluZGV4IGZvciBwcmVzZW5jZS9hYnNlbmNlIGRhdGEuIFdoZW4gdGhlIGRpc3RhbmNlIG1ldHJpYyBpcyBFdWNsaWRlYW4sIFBDb0EgaXMgZXF1aXZhbGVudCB0byBQQ0EuCgoqKlRoZSBmaXJzdCBQQ29BIGNvbXBhcmVzIHNpbWlsYXJpdHkgYmV0d2VlbiB0dW5kcmEgZWNvc3lzdGVtcyBieSBpbmNvcnBvcmF0aW5nIHRoZSBjb21iaW5lZCBkYXRhc2V0LioqCgpgYGB7cn0KIyBSdW4gUENvQSBhbmFseXNpcyBvbiB0aGUgQnJheS1DdXJ0aXMgZGlzc2ltaWxhcml0eSBtYXRyaXgKZ3BtLmFsbC5iYy5wY29hPC1wY29hKGdwbS5hbGwuYmMuZGlzdCkKYGBgCgpFeHRyYWN0IHRoZSBlaWdlbnZhbHVlcyBhbmQgY2FsY3VsYXRlIHRoZSB2YXJpYXRpb24gZXhwbGFpbmVkIGJ5IGVhY2ggYXhpcy4KCmBgYHtyfQpwY29hLmRuYS5hbGw8LWNtZHNjYWxlKGdwbS5hbGwuYmMuZGlzdCwgZWlnPVRSVUUsIGs9MikKcGNvYS5kbmEuYWxsCgojIENhbGN1bGF0ZSB0aGUgcGVyY2VudCB2YXJpYXRpb24gZXhwbGFpbmVkIGJ5IEF4aXMgMQpwY29hLmRuYS5hbGwuZXhwLnZhcjE8LXJvdW5kKHBjb2EuZG5hLmFsbCRlaWdbMV0gLyBzdW0ocGNvYS5kbmEuYWxsJGVpZyksIDIpICogMTAwCnBjb2EuZG5hLmFsbC5leHAudmFyMQoKIyBDYWxjdWxhdGUgdGhlIHBlcmNlbnQgdmFyaWF0aW9uIGV4cGxhaW5lZCBieSBBeGlzIDIKcGNvYS5kbmEuYWxsLmV4cC52YXIyPC1yb3VuZChwY29hLmRuYS5hbGwkZWlnWzJdIC8gc3VtKHBjb2EuZG5hLmFsbCRlaWcpLCAyKSAqIDEwMApwY29hLmRuYS5hbGwuZXhwLnZhcjIKCiMgU3VtIHRoZSBwZXJjZW50IHZhcmlhdGlvbiBleHBsYWluZWQgYnkgYm90aCBheGVzCnBjb2EuZG5hLmFsbC5zdW0uZWlnPC1zdW0ocGNvYS5kbmEuYWxsLmV4cC52YXIxLCBwY29hLmRuYS5hbGwuZXhwLnZhcjIpCnBjb2EuZG5hLmFsbC5zdW0uZWlnCmBgYAoKUGxvdCB0aGUgUENvQS4KCmBgYHtyfQojIEV4dHJhY3QgdGhlIHBsb3Qgc2NvcmVzIGZyb20gZmlyc3QgdHdvIFBDb0EgYXhlcwpncG0uYWxsLmJjLnBjb2EuYXhlcyA8LSBncG0uYWxsLmJjLnBjb2EkdmVjdG9yc1ssYygxLDIpXQoKIyBDcmVhdGUgbmV3IG9iamVjdCB3aXRoIFBDb0EgYXhlcwphbGwuZG5hLmJjLnBjb2E8LWRhdGEuZnJhbWUoZ3BtLmFsbC5iYy5wY29hLmF4ZXMpCgojIEFkZCBUaW1lcG9pbnQgdmFyaWFibGUgdG8gdGhlIGRhdGFmcmFtZQphbGwuZG5hLnRpbWVwb2ludDwtYygnV1MtTUctVDAnLCdXUy1NRy1UMCcsJ1dTLU1HLVQwJywnV1MtTUctVDQnLCdXUy1NRy1UNCcsJ1dTLU1HLVQ0JywnV1MtTUctVDI0JywnV1MtTUctVDI0JywnV1MtTUctVDI0JywnVHVzcy1NRy1UMCcsJ1R1c3MtTUctVDAnLCdUdXNzLU1HLVQ0JywnVHVzcy1NRy1UNCcsJ1R1c3MtTUctVDI0JywnVHVzcy1NRy1UMjQnKQphbGwuZG5hLnBjb2EuMTwtYWxsLmRuYS5iYy5wY29hJEF4aXMuMQphbGwuZG5hLnBjb2EuMjwtYWxsLmRuYS5iYy5wY29hJEF4aXMuMgphbGwuZG5hLmJjLnBjb2E8LWRhdGEuZnJhbWUoYWxsLmRuYS50aW1lcG9pbnQsYWxsLmRuYS5wY29hLjEsYWxsLmRuYS5wY29hLjIpCgojIFJlbmFtZSBjb2x1bW4gaGVhZGluZ3MKY29sbmFtZXMoYWxsLmRuYS5iYy5wY29hKTwtYygiVGltZXBvaW50IiwiUENvQV8xIiwiUENvQV8yIikKCiMgUmUtYXJyYW5nZSBzYW1wbGVzIGZvciBwbG90dGluZyBQQ29BCmFsbC5kbmEuYmMucGNvYSRUaW1lcG9pbnQgPC0gZmFjdG9yKGFsbC5kbmEuYmMucGNvYSRUaW1lcG9pbnQsIGxldmVscz1jKCJUdXNzLU1HLVQwIiwiV1MtTUctVDAiLCJUdXNzLU1HLVQ0IiwiV1MtTUctVDQiLCJUdXNzLU1HLVQyNCIsIldTLU1HLVQyNCIpKQoKIyBQbG90IHRoZSBQQ29BCmFsbC5kbmEucGNvYTwtZ2dwbG90KGRhdGE9YWxsLmRuYS5iYy5wY29hLCBhZXMoeD1QQ29BXzEsIHk9UENvQV8yLCBncm91cD1UaW1lcG9pbnQsIGNvbG9yPVRpbWVwb2ludCkpICsgZ2VvbV9wb2ludChhZXMoc2hhcGU9VGltZXBvaW50LCBzaXplPTAuNzUsIGZpbGw9VGltZXBvaW50KSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiZ3JheTgzIiwgImJsYWNrIiwgImdyYXk4MyIsICJibGFjayIsICJncmF5ODMiLCAiYmxhY2siKSkgKyBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjEsMjEsMjIsMjIsMjQsMjQpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAiYmxhY2siLCAiYmxhY2siLCAiYmxhY2siLCAiYmxhY2siLCAiYmxhY2siKSkgKyB4bGFiKCJQQ29BIDEgKDYzJSkiKSArIHlsYWIoIlBDb0EgMiAoMTElKSIpICsgdGhlbWVfY2xhc3NpYygpICsgdGhlbWUoYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpICsgZ3VpZGVzKHNoYXBlID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDMpKSkgKyBzY2FsZV9zaXplKGd1aWRlPSJub25lIikgKyBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMCksIGNvbG9yPSJncmF5IiwgbGluZXR5cGU9ImRhc2hlZCIpICsgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD0wKSwgY29sb3I9ImdyYXkiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyB5bGltKC0wLjYsMC42KSArIHhsaW0oLTAuNiwwLjYpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MC4wLCB5PTAuNTksIGxhYmVsPSJQRVJNQU5PVkEiKSAgICsgYW5ub3RhdGUoInRleHQiLCB4ID0gMCwgeSA9IDAuNTIsIHNpemU9MywgbGFiZWwgPSAiVHVuZHJhfihpdGFsaWMocCkgPT0gMC4wMDEpIiwgcGFyc2UgPSBUUlVFKSArIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAsIHkgPSAwLjQ1LCBzaXplPTMsIGxhYmVsID0gIlRpbWV+UG9pbnR+KGl0YWxpYyhwKSA9PSAwLjc1NSkiLCBwYXJzZSA9IFRSVUUpICsgYW5ub3RhdGUoInRleHQiLCB4ID0gMCwgeSA9IDAuMzgsIHNpemU9MywgbGFiZWwgPSAiVHVuZHJhOlRpbWV+UG9pbnR+KGl0YWxpYyhwKSA9PSAwLjYyMikiLCBwYXJzZSA9IFRSVUUpCmBgYAoKYGBge3J9CmFsbC5kbmEucGNvYQpgYGAKCioqVGhlIHNlY29uZCBQQ29BIGNvbXBhcmVzIHNpbWlsYXJpdHkgYmV0d2VlbiBzYW1wbGluZyB0aW1lIHBvaW50cyB3aXRoaW4gdGhlIFR1c3NvY2sgdHVuZHJhIGVjb3N5c3RlbS4qKgoKYGBge3J9CiMgUnVuIFBDb0EgYW5hbHlzaXMgb24gdGhlIEJyYXktQ3VydGlzIGRpc3NpbWlsYXJpdHkgbWF0cml4CmdwbS50dXNzLmJjLnBjb2E8LXBjb2EoZ3BtLnR1c3MuYmMuZGlzdCkKYGBgCgpFeHRyYWN0IHRoZSBlaWdlbnZhbHVlcyBhbmQgY2FsY3VsYXRlIHRoZSB2YXJpYXRpb24gZXhwbGFpbmVkIGJ5IGVhY2ggYXhpcy4KCmBgYHtyfQpwY29hLmRuYS50dXNzPC1jbWRzY2FsZShncG0udHVzcy5iYy5kaXN0LCBlaWc9VFJVRSwgaz0yKQpwY29hLmRuYS50dXNzCgojIENhbGN1bGF0ZSB0aGUgcGVyY2VudCB2YXJpYXRpb24gZXhwbGFpbmVkIGJ5IEF4aXMgMQpwY29hLmRuYS50dXNzLmV4cC52YXIxPC1yb3VuZChwY29hLmRuYS50dXNzJGVpZ1sxXSAvIHN1bShwY29hLmRuYS50dXNzJGVpZyksIDIpICogMTAwCnBjb2EuZG5hLnR1c3MuZXhwLnZhcjEKCiMgQ2FsY3VsYXRlIHRoZSBwZXJjZW50IHZhcmlhdGlvbiBleHBsYWluZWQgYnkgQXhpcyAyCnBjb2EuZG5hLnR1c3MuZXhwLnZhcjI8LXJvdW5kKHBjb2EuZG5hLnR1c3MkZWlnWzJdIC8gc3VtKHBjb2EuZG5hLnR1c3MkZWlnKSwgMikgKiAxMDAKcGNvYS5kbmEudHVzcy5leHAudmFyMgoKIyBTdW0gdGhlIHBlcmNlbnQgdmFyaWF0aW9uIGV4cGxhaW5lZCBieSBib3RoIGF4ZXMKcGNvYS5kbmEudHVzcy5zdW0uZWlnPC1zdW0ocGNvYS5kbmEudHVzcy5leHAudmFyMSwgcGNvYS5kbmEudHVzcy5leHAudmFyMikKcGNvYS5kbmEudHVzcy5zdW0uZWlnCmBgYAoKUGxvdCB0aGUgUENvQS4KCmBgYHtyfQojIEV4dHJhY3QgdGhlIHBsb3Qgc2NvcmVzIGZyb20gZmlyc3QgdHdvIFBDb0EgYXhlcwpncG0udHVzcy5iYy5wY29hLmF4ZXMgPC0gZ3BtLnR1c3MuYmMucGNvYSR2ZWN0b3JzWyxjKDEsMildCgojIENyZWF0ZSBuZXcgb2JqZWN0IHdpdGggUENvQSBheGVzCnR1c3MuZG5hLmJjLnBjb2E8LWRhdGEuZnJhbWUoZ3BtLnR1c3MuYmMucGNvYS5heGVzKQoKIyBBZGQgVGltZXBvaW50IHZhcmlhYmxlIHRvIHRoZSBkYXRhZnJhbWUKdHVzcy5kbmEudGltZXBvaW50PC1jKCdUdXNzLVQwJywnVHVzcy1UMCcsJ1R1c3MtVDQnLCdUdXNzLVQ0JywnVHVzcy1UMjQnLCdUdXNzLVQyNCcpCnR1c3MuZG5hLnBjb2EuMTwtdHVzcy5kbmEuYmMucGNvYSRBeGlzLjEKdHVzcy5kbmEucGNvYS4yPC10dXNzLmRuYS5iYy5wY29hJEF4aXMuMgp0dXNzLmRuYS5iYy5wY29hPC1kYXRhLmZyYW1lKHR1c3MuZG5hLnRpbWVwb2ludCx0dXNzLmRuYS5wY29hLjEsdHVzcy5kbmEucGNvYS4yKQoKIyBSZW5hbWUgY29sdW1uIGhlYWRpbmdzCmNvbG5hbWVzKHR1c3MuZG5hLmJjLnBjb2EpPC1jKCJUaW1lcG9pbnQiLCJQQ29BXzEiLCJQQ29BXzIiKQojdHVzcy5kbmEuYmMucGNvYQoKIyBSZS1hcnJhbmdlIHNhbXBsZXMgZm9yIHBsb3R0aW5nIFBDb0EKdHVzcy5kbmEuYmMucGNvYSRUaW1lcG9pbnQ8LWZhY3Rvcih0dXNzLmRuYS5iYy5wY29hJFRpbWVwb2ludCwgbGV2ZWxzPWMoIlR1c3MtVDAiLCJUdXNzLVQ0IiwiVHVzcy1UMjQiKSkKCiMgUGxvdCB0aGUgUENvQQp0dXNzLmRuYS5wY29hPC1nZ3Bsb3QoZGF0YT10dXNzLmRuYS5iYy5wY29hLCBhZXMoeD1QQ29BXzEsIHk9UENvQV8yLCBncm91cD1UaW1lcG9pbnQsIGNvbG9yPVRpbWVwb2ludCkpICsgZ2VvbV9wb2ludChhZXMoc2hhcGU9VGltZXBvaW50LCBzaXplPTAuNzUsIGZpbGw9VGltZXBvaW50KSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygicGFsZWdyZWVuIiwiZ3JlZW4zIiwiZGFya2dyZWVuIikpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxLDI0LDIyKSkgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwiYmxhY2siLCJibGFjayIpKSArIHhsYWIoIlBDb0EgMSAoNDAlKSIpICsgeWxhYigiUENvQSAyICgyNyUpIikgKyB0aGVtZV9taW5pbWFsKCkgKyB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTQpKSsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheSIpLCBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiLCBmaWxsPU5BLCBzaXplPTEpKSArIHNjYWxlX3NpemUoZ3VpZGU9RkFMU0UpICsgZ3VpZGVzKHNoYXBlID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDMpKSkgKyBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMCksIGNvbG9yPSJncmF5IiwgbGluZXR5cGU9ImRhc2hlZCIpICsgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD0wKSwgY29sb3I9ImdyYXkiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyB5bGltKC0wLjUsMC41KSArIHhsaW0oLTAuNSwwLjUpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MC4wLCB5PTAuNDksIGxhYmVsPSJQRVJNQU5PVkEiKSArIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAsIHkgPSAwLjQyLCBzaXplPTMsIGxhYmVsID0gIlRpbWV+UG9pbnR+KGl0YWxpYyhwKSA9PSAwLjQwMCkiLCBwYXJzZSA9IFRSVUUpCmBgYAoKYGBge3J9CnR1c3MuZG5hLnBjb2EKYGBgCgoqKlRoZSB0aGlyZCBQQ29BIGNvbXBhcmVzIHNpbWlsYXJpdHkgYmV0d2VlbiBzYW1wbGluZyB0aW1lIHBvaW50cyB3aXRoaW4gdGhlIFdldCBTZWRnZSB0dW5kcmEgZWNvc3lzdGVtLioqCgpgYGB7cn0KIyBSdW4gUENvQSBhbmFseXNpcyBvbiB0aGUgQnJheS1DdXJ0aXMgZGlzc2ltaWxhcml0eSBtYXRyaXgKZ3BtLndzLmJjLnBjb2E8LXBjb2EoZ3BtLndzLmJjLmRpc3QpCmBgYAoKRXh0cmFjdCB0aGUgZWlnZW52YWx1ZXMgYW5kIGNhbGN1bGF0ZSB0aGUgdmFyaWF0aW9uIGV4cGxhaW5lZCBieSBlYWNoIGF4aXMuCgpgYGB7cn0KcGNvYS5kbmEud3M8LWNtZHNjYWxlKGdwbS53cy5iYy5kaXN0LCBlaWc9VFJVRSwgaz0yKQpwY29hLmRuYS53cwoKIyBDYWxjdWxhdGUgdGhlIHBlcmNlbnQgdmFyaWF0aW9uIGV4cGxhaW5lZCBieSBBeGlzIDEKcGNvYS5kbmEud3MuZXhwLnZhcjE8LXJvdW5kKHBjb2EuZG5hLndzJGVpZ1sxXSAvIHN1bShwY29hLmRuYS53cyRlaWcpLCAyKSAqIDEwMApwY29hLmRuYS53cy5leHAudmFyMQoKIyBDYWxjdWxhdGUgdGhlIHBlcmNlbnQgdmFyaWF0aW9uIGV4cGxhaW5lZCBieSBBeGlzIDIKcGNvYS5kbmEud3MuZXhwLnZhcjI8LXJvdW5kKHBjb2EuZG5hLndzJGVpZ1syXSAvIHN1bShwY29hLmRuYS53cyRlaWcpLCAyKSAqIDEwMApwY29hLmRuYS53cy5leHAudmFyMgoKIyBTdW0gdGhlIHBlcmNlbnQgdmFyaWF0aW9uIGV4cGxhaW5lZCBieSBib3RoIGF4ZXMKcGNvYS5kbmEud3Muc3VtLmVpZzwtc3VtKHBjb2EuZG5hLndzLmV4cC52YXIxLCBwY29hLmRuYS53cy5leHAudmFyMikKcGNvYS5kbmEud3Muc3VtLmVpZwpgYGAKClBsb3QgdGhlIFBDb0EuCgpgYGB7cn0KIyBFeHRyYWN0IHRoZSBwbG90IHNjb3JlcyBmcm9tIGZpcnN0IHR3byBQQ29BIGF4ZXMKZ3BtLndzLmJjLnBjb2EuYXhlcyA8LSBncG0ud3MuYmMucGNvYSR2ZWN0b3JzWyxjKDEsMildCgojIENyZWF0ZSBuZXcgb2JqZWN0IHdpdGggUENvQSBheGVzCndzLmRuYS5iYy5wY29hPC1kYXRhLmZyYW1lKGdwbS53cy5iYy5wY29hLmF4ZXMpCgojIEFkZCBUaW1lcG9pbnQgdmFyaWFibGUgdG8gdGhlIGRhdGFmcmFtZQp3cy5kbmEudGltZXBvaW50PC1jKCdXUy1UMCcsJ1dTLVQwJywnV1MtVDAnLCdXUy1UNCcsJ1dTLVQ0JywnV1MtVDQnLCdXUy1UMjQnLCdXUy1UMjQnLCdXUy1UMjQnKQp3cy5kbmEucGNvYS4xPC13cy5kbmEuYmMucGNvYSRBeGlzLjEKd3MuZG5hLnBjb2EuMjwtd3MuZG5hLmJjLnBjb2EkQXhpcy4yCndzLmRuYS5iYy5wY29hPC1kYXRhLmZyYW1lKHdzLmRuYS50aW1lcG9pbnQsd3MuZG5hLnBjb2EuMSx3cy5kbmEucGNvYS4yKQoKIyBSZW5hbWUgY29sdW1uIGhlYWRpbmdzCmNvbG5hbWVzKHdzLmRuYS5iYy5wY29hKTwtYygiVGltZXBvaW50IiwiUENvQV8xIiwiUENvQV8yIikKI3dzLmRuYS5iYy5wY29hCgojIFJlLWFycmFuZ2Ugc2FtcGxlcyBmb3IgcGxvdHRpbmcgUENvQQp3cy5kbmEuYmMucGNvYSRUaW1lcG9pbnQ8LWZhY3Rvcih3cy5kbmEuYmMucGNvYSRUaW1lcG9pbnQsIGxldmVscz1jKCJXUy1UMCIsIldTLVQ0IiwiV1MtVDI0IikpCgojIFBsb3QgdGhlIFBDb0EKd3MuZG5hLnBjb2E8LWdncGxvdChkYXRhPXdzLmRuYS5iYy5wY29hLCBhZXMoeD1QQ29BXzEsIHk9UENvQV8yLCBncm91cD1UaW1lcG9pbnQsIGNvbG9yPVRpbWVwb2ludCkpICsgZ2VvbV9wb2ludChhZXMoc2hhcGU9VGltZXBvaW50LCBzaXplPTAuNzUsIGZpbGw9VGltZXBvaW50KSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCJibGFjayIsImJsYWNrIikpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxLDI0LDIyKSkgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImdyYXk4MyIsImdyYXk4MyIsImdyYXk4MyIpKSArIHhsYWIoIlBDb0EgMSAoNDclKSIpICsgeWxhYigiUENvQSAyICgxOCUpIikgKyB0aGVtZV9taW5pbWFsKCkgKyB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTQpKSsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheSIpLCBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiLCBmaWxsPU5BLCBzaXplPTEpKSArIHNjYWxlX3NpemUoZ3VpZGU9RkFMU0UpICsgZ3VpZGVzKHNoYXBlID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDMpKSkgKyBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gMCksIGNvbG9yPSJncmF5IiwgbGluZXR5cGU9ImRhc2hlZCIpICsgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD0wKSwgY29sb3I9ImdyYXkiLCBsaW5ldHlwZT0iZGFzaGVkIikgKyB5bGltKC0wLjUsMC41KSArIHhsaW0oLTAuNSwwLjUpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MC4wLCB5PTAuNDksIGxhYmVsPSJQRVJNQU5PVkEiKSArIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAsIHkgPSAwLjQyLCBzaXplPTMsIGxhYmVsID0gIlRpbWV+UG9pbnR+KGl0YWxpYyhwKSA9PSAwLjkxNikiLCBwYXJzZSA9IFRSVUUpCmBgYAoKYGBge3J9CndzLmRuYS5wY29hCmBgYAoKIyMjIyMgNy4yLjIuNC4gUEVSTUFOT1ZBCgotIFJ1biBQRVJNQU5PVkEgdXNpbmcgYGFkb25pc2AgZnVuY3Rpb24gb2YgdGhlICoqVmVnYW4qKiBwYWNrYWdlCgpQRVJNQU5PVkEgLSBHUE0tQWxsIC0gQnJheS1DdXJ0aXMKYGBge3J9CmFkb25pcyhncG0uYWxsLmJjLmRpc3R+Z3BtX2FsbF92ZWcqZ3BtX2FsbF90aW1lLCBkYXRhPWdwbV9hbGxfZ3JvdXBzKQpgYGAKClBFUk1BTk9WQSAtIEdQTS1UdXNzIC0gQnJheS1DdXJ0aXMKYGBge3J9CmFkb25pcyhncG0udHVzcy5iYy5kaXN0fmdwbV90dXNzX3RpbWUsIGRhdGE9Z3BtX3R1c3NfZ3JvdXBzKQpgYGAKClBFUk1BTk9WQSAtIEdQTS1XUyAtIEJyYXktQ3VydGlzCmBgYHtyfQphZG9uaXMoZ3BtLndzLmJjLmRpc3R+Z3BtX3dzX3RpbWUsIGRhdGE9Z3BtX3dzX2dyb3VwcykKYGBgCgojIyMgNy4zLiBLRUdHIFRpZXIgUGF0dGVybnMKCkxvb2sgZm9yIGRpZmZlcmVuY2VzIGluIGdlbmUgZXhwcmVzc2lvbiBhdCBtdWx0aXBsZSBLRUdHIHRpZXIgbGV2ZWxzIChJSS1JVikgdXNpbmcgR1BNLW5vcm1hbGl6ZWQgdmFsdWVzLgoKIyMjIyA3LjMuMS4gVHVzc29jayBUdW5kcmEKCkxvb2sgYXQgZGlmZmVyZW5jZXMgaW4gZ2VuZSBleHByZXNzaW9uIHBhdHRlcm5zIGZvciBtdWx0aXBsZSBUaWVyIGxldmVscyB3aXRoaW4gdGhlIFR1c3NvY2sgdHVuZHJhIGJldHdlZW4gc2FtcGxpbmcgdGltZSBwb2ludHMuCgojIyMjIyA3LjMuMS4xLiBUaWVyIElJIEV4cHJlc3Npb24KYGBge3J9CiMgQ2FsY3VsYXRlIEdQTS1ub3JtYWxpemVkIGdlbmUgY291bnQgc3VtcyBmb3IgZWFjaCBUdXNzIHNhbXBsZSBpbiBlYWNoIFRpZXIgSUkgY2F0ZWdvcnkKdHVzc19kbmFfdElJX3N1bTwtZ3BtX2FsbF9wb3RfYW5uICU+JSBncm91cF9ieShUaWVyX0lJKSAlPiUgc3VtbWFyaXNlX2F0KHZhcnMoIlMxMDcxMDciLCJTMTA3MTA4IiwiUzEwNzExNiIsIlMxMDcxMTciLCJTMTA3MTE5IiwiUzEwNzEyMSIpLCBzdW0pCgp0dXNzX2RuYV90SUlfc3VtPC10dXNzX2RuYV90SUlfc3VtICU+JSBtdXRhdGVfYXQodmFycyhTMTA3MTA3LFMxMDcxMDgsUzEwNzExNixTMTA3MTE3LFMxMDcxMTksUzEwNzEyMSksIGZ1bnMocm91bmQoLiwgMCkpKQoKdHVzc19kbmFfdElJX3N1bTwtYXMuZGF0YS5mcmFtZSh0dXNzX2RuYV90SUlfc3VtKQoKdHVzc19kbmFfdElJX3N1bTwtdHVzc19kbmFfdElJX3N1bVtvcmRlcigtdHVzc19kbmFfdElJX3N1bSRTMTA3MTA3KSxdCmBgYAoKSGVhdG1hcCBmb3IgVGllciBJSSBjYXRlZ29yaWVzIGJ5IHNhbXBsaW5nIHRpbWVwb2ludHMKYGBge3J9CiMgQ3JlYXRlIGNvcHkgb2YgIndzX3RJSV9zdW0iIG9iamVjdCB0byBwcmVwIGZvciBoZWF0bWFwCnR1c3NfZG5hX3RJSV9oZWF0bWFwPC10dXNzX2RuYV90SUlfc3VtCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoVGllciBjYXRlZ29yaWVzKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKHR1c3NfZG5hX3RJSV9oZWF0bWFwKSA8LSB0dXNzX2RuYV90SUlfaGVhdG1hcCRUaWVyX0lJCnR1c3NfZG5hX3RJSV9oZWF0bWFwPC1hcy5kYXRhLmZyYW1lKHR1c3NfZG5hX3RJSV9oZWF0bWFwWy0xXSkKCiMgUmVuYW1lIGNvbHVtbnMgdG8gc2FtcGxlIElEcwpjb2xuYW1lcyh0dXNzX2RuYV90SUlfaGVhdG1hcCk8LWMoIlR1c3MxLVQwIiwiVHVzczItVDAiLCJUdXNzMS1UNCIsIlR1c3MyLVQ0IiwiVHVzczEtVDI0IiwiVHVzczMtVDI0IikKCiMgUmVtb3ZlIHJvd3MgZm9yICJPcmdhbmlzbWFsIFN5c3RlbXMiIGFuZCAiSHVtYW4gRGlzZWFzZXMiCiN0dXNzX2RuYV90SUlfaGVhdG1hcCA8LSB0dXNzX2RuYV90SUlfaGVhdG1hcFstYyg1LDYpLF0KCiMgQ29udmVydCBkYXRhZnJhbWUgaW50byBhIG1hdHJpeCBmb3IgaGVhdG1hcAp0dXNzX2RuYV90SUlfaGVhdG1hcDwtYXMubWF0cml4KHR1c3NfZG5hX3RJSV9oZWF0bWFwKQoKIyBTY2FsZSBtYXRyaXggdmFsdWVzIHRvIGdlbmVyYXRlIFotc2NvcmVzCnR1c3NfZG5hX3RJSV9oZWF0bWFwPC1zY2FsZSh0KHR1c3NfZG5hX3RJSV9oZWF0bWFwKSkKCnR1c3NfZG5hX3RJSV9oZWF0bWFwPC10KHR1c3NfZG5hX3RJSV9oZWF0bWFwKQoKIyBTcGVjaWZ5IFJDb2xvckJyZXdlciBjdXN0b20gY29sb3IgcGFsZXR0ZQpjb2wgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDEwLCAiUmRZbEJ1IikpKDI1NikKCiMgUGhlYXRtYXAKcGhlYXRtYXAodHVzc19kbmFfdElJX2hlYXRtYXAsIHRyZWVoZWlnaHRfcm93ID0gMCwgdHJlZWhlaWdodF9jb2wgPSAwLGNsdXN0ZXJfcm93cyA9IEZBTFNFLCBjbHVzdGVyX2NvbHMgPSBGQUxTRSkKYGBgCgpTdW1tZWQgdmFsdWVzIGJ5IHJlcGxpY2F0ZSBmb3IgZWFjaCBLRUdHIHRpZXIgSUkgY2F0ZWdvcnkuCmBgYHtyIGVjaG89RkFMU0V9CmthYmxlKHR1c3NfZG5hX3RJSV9zdW0sIGNhcHRpb24gPSAiVHVzc29jayBUaWVyIElJIEtFR0cgY2F0ZWdvcnkgc3VtbWFyeSBieSBzYW1wbGUuIiwgZm9ybWF0LmFyZ3MgPSBsaXN0KGJpZy5tYXJrPSIsIikpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsImhvdmVyIiwiY29uZGVuc2VkIikpCmBgYAoKQ2FsY3VsYXRlIG1lYW4gdmFsdWVzIGZyb20gdGhlIHJlcGxpY2F0ZSBzdW1zCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp0dXNzX2RuYV90SUlfc3VtJG1lYW50dXNzX1QwPC1hcHBseSh0dXNzX2RuYV90SUlfc3VtWywyOjNdLCAxLCBtZWFuKQp0dXNzX2RuYV90SUlfc3VtJG1lYW50dXNzX1Q0PC1hcHBseSh0dXNzX2RuYV90SUlfc3VtWyw0OjVdLCAxLCBtZWFuKQp0dXNzX2RuYV90SUlfc3VtJG1lYW50dXNzX1QyNDwtYXBwbHkodHVzc19kbmFfdElJX3N1bVssNjo3XSwgMSwgbWVhbikKdHVzc19kbmFfdElJX3N1bTwtdHVzc19kbmFfdElJX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMobWVhbnR1c3NfVDAsbWVhbnR1c3NfVDQsbWVhbnR1c3NfVDI0KSwgZnVucyhyb3VuZCguLCAwKSkpCgojIENhbGN1bGF0ZSBzZCB2YWx1ZXMgZnJvbSB0aGUgcmVwbGljYXRlIHN1bXMKdHVzc19kbmFfdElJX3N1bSRzZHR1c3NfVDA8LWFwcGx5KHR1c3NfZG5hX3RJSV9zdW1bLDI6M10sIDEsIHNkKQp0dXNzX2RuYV90SUlfc3VtJHNkdHVzc19UNDwtYXBwbHkodHVzc19kbmFfdElJX3N1bVssNDo1XSwgMSwgc2QpCnR1c3NfZG5hX3RJSV9zdW0kc2R0dXNzX1QyNDwtYXBwbHkodHVzc19kbmFfdElJX3N1bVssNjo3XSwgMSwgc2QpCnR1c3NfZG5hX3RJSV9zdW08LXR1c3NfZG5hX3RJSV9zdW0gJT4lIG11dGF0ZV9hdCh2YXJzKHNkdHVzc19UMCxzZHR1c3NfVDQsc2R0dXNzX1QyNCksIGZ1bnMocm91bmQoLiwgMCkpKQoKIyBTdWJzZXQgTWVhbiB2YWx1ZXMKdHVzc19kbmFfdElJX21lYW48LXN1YnNldCh0dXNzX2RuYV90SUlfc3VtLCBzZWxlY3Q9YyhUaWVyX0lJLG1lYW50dXNzX1QwLG1lYW50dXNzX1Q0LG1lYW50dXNzX1QyNCkpCm5hbWVzKHR1c3NfZG5hX3RJSV9tZWFuKTwtYygiVGllciBJSSIsICJUdXNzLVQwIiwgIlR1c3MtVDQiLCAiVHVzcy1UMjQiKQoKIyBTdWJzZXQgU0QgdmFsdWVzCnR1c3NfZG5hX3RJSV9zZDwtc3Vic2V0KHR1c3NfZG5hX3RJSV9zdW0sIHNlbGVjdD1jKFRpZXJfSUksc2R0dXNzX1QwLHNkdHVzc19UNCxzZHR1c3NfVDI0KSkKbmFtZXModHVzc19kbmFfdElJX3NkKTwtYygiVGllciBJSSIsICJUdXNzLVQwIiwgIlR1c3MtVDQiLCAiVHVzcy1UMjQiKQoKIyBSZW1lbWJlciAiVGllciBJSSIgYXMgbm9uLW51bWVyaWMgdmFsdWVzCnR1c3NfZG5hX3RJSV9tZWFuX1RpZXJJSTwtdHVzc19kbmFfdElJX21lYW4kYFRpZXIgSUlgCnR1c3NfZG5hX3RJSV9zZF9UaWVySUk8LXR1c3NfZG5hX3RJSV9zZCRgVGllciBJSWAKCiMgVHJhbnNwb3NlIGFsbCBidXQgZmlyc3QgY29sdW1uIChUaWVyIElJKQp0dXNzX2RuYV90SUlfbWVhbjwtYXMuZGF0YS5mcmFtZSh0KHR1c3NfZG5hX3RJSV9tZWFuWywtMV0pKQpjb2xuYW1lcyh0dXNzX2RuYV90SUlfbWVhbik8LXR1c3NfZG5hX3RJSV9tZWFuX1RpZXJJSQp0dXNzX2RuYV90SUlfc2Q8LWFzLmRhdGEuZnJhbWUodCh0dXNzX2RuYV90SUlfc2RbLC0xXSkpCmNvbG5hbWVzKHR1c3NfZG5hX3RJSV9zZCk8LXR1c3NfZG5hX3RJSV9zZF9UaWVySUkKCiMgQ29tYmluZSBtZWFuIGFuZCBzZCBpbnRvIHNpbmdsZSBjb2x1bW4gd2l0aCDCsSBkaXZpZGVyCnR1c3NfZG5hX3RJSV90YWJsZTwtYXMuZGF0YS5mcmFtZShkby5jYWxsKGNiaW5kLCBsYXBwbHkoMTpuY29sKHR1c3NfZG5hX3RJSV9tZWFuKSwgZnVuY3Rpb24oaSkgcGFzdGUwKHR1c3NfZG5hX3RJSV9tZWFuWyAsIGldLCAiIMKxICIsIHR1c3NfZG5hX3RJSV9zZFsgLCBpXSkpKSkKCiMgVHJhbnNwb3NlIHRoZSB0YWJsZSBiYWNrCnR1c3NfZG5hX3RJSV90YWJsZTwtdCh0dXNzX2RuYV90SUlfdGFibGUpCgojIFJlbmFtZSBjb2x1bW5zIHRvIFNpdGVzCmNvbG5hbWVzKHR1c3NfZG5hX3RJSV90YWJsZSk8LWMoIlR1c3NvY2sgKFQwKSIsICJUdXNzb2NrIChUNCkiLCAiVHVzc29jayAoVDI0KSIpCgpyb3duYW1lcyh0dXNzX2RuYV90SUlfdGFibGUpPC10dXNzX2RuYV90SUlfbWVhbl9UaWVySUkKCmthYmxlKHR1c3NfZG5hX3RJSV90YWJsZSwgY2FwdGlvbiA9ICJUdXNzb2NrIFRpZXIgSUkgS0VHRyBjYXRlZ29yeSBhdmVyYWdlcyAowrEgc3RhbmRhcmQgZGV2aWF0aW9uKSBieSBzYW1wbGUgZm9yIE1ldGFnZW5vbWVzLiIsIGZvcm1hdC5hcmdzID0gbGlzdChiaWcubWFyaz0iLCIpLCBhbGlnbiA9ICJsIikgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwiaG92ZXIiLCJjb25kZW5zZWQiKSkKYGBgCgpSdW4gc3RhdGlzdGljYWwgdGVzdHMgdG8gZGV0ZXJtaW5lIGlmIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGV4aXN0IGJldHdlZW4gc2FtcGxpbmcgdGltZXBvaW50cyBmb3IgZWFjaCBUaWVyIEtFR0cgY2F0ZWdvcnkgaW4gdGhlIG1ldGFnZW5vbWUuIENsaWNrIG9uIHRoZSAqKlNob3cvSGlkZSoqIGJ1dHRvbiB0byBzZWUgdGhlIHN0YXRpc3RpY3MuCgo8YnV0dG9uIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtdG9nZ2xlPSJjb2xsYXBzZSIgZGF0YS10YXJnZXQ9IiNCbG9ja05hbWU1NiI+IFNob3cvSGlkZSA8L2J1dHRvbj4gIAo8ZGl2IGlkPSJCbG9ja05hbWU1NiIgY2xhc3M9ImNvbGxhcHNlIj4KYGBge3J9CiMgU3Vic2V0IHRoZSAic3VtIiB2YWx1ZXMgZm9yIGVhY2ggc2FtcGxlCnR1c3NfZG5hX3RJSV9zdGF0czwtc3Vic2V0KHR1c3NfZG5hX3RJSV9zdW0sIHNlbGVjdD1jKFRpZXJfSUksUzEwNzEwNyxTMTA3MTA4LFMxMDcxMTYsUzEwNzExNyxTMTA3MTE5LFMxMDcxMjEpKQoKcm93bmFtZXModHVzc19kbmFfdElJX3N0YXRzKSA8LSB0dXNzX2RuYV90SUlfc3RhdHMkVGllcl9JSQp0dXNzX2RuYV90SUlfc3RhdHM8LWFzLmRhdGEuZnJhbWUodCh0dXNzX2RuYV90SUlfc3RhdHNbLTFdKSkKCiMgQ3JlYXRlIGEgY29sdW1uIHdpdGggdGltZXBvaW50IHZhcmlhYmxlIG5hbWVzClRpbWVwb2ludDwtYygiVDAiLCJUMCIsIlQ0IiwiVDQiLCJUMjQiLCJUMjQiKQpUaW1lcG9pbnQ8LWRhdGEuZnJhbWUoVGltZXBvaW50KQoKIyBBZGQgdGhlIHRpbWVwb2ludCBjb2x1bW4gdG8gdGhlIHN1bSB0YWJsZQp0dXNzX2RuYV90SUlfc3RhdHM8LWRhdGEuZnJhbWUoVGltZXBvaW50LHR1c3NfZG5hX3RJSV9zdGF0cykKCiMgU3Vic2V0IHJlc3BvbnNlIHZhcmlhYmxlcyBmb3IgTUFOT1ZBCnR1c3NfZG5hX3RJSV9zdGF0cyRyZXNwb25zZSA8LSBhcy5tYXRyaXgodHVzc19kbmFfdElJX3N0YXRzWywgMjo1XSkKCiMgTUFOT1ZBIHRlc3QKdHVzc19kbmFfdElJX21hbm92YSA8LSBtYW5vdmEocmVzcG9uc2UgfiBUaW1lcG9pbnQsIGRhdGE9dHVzc19kbmFfdElJX3N0YXRzKQpzdW1tYXJ5LmFvdih0dXNzX2RuYV90SUlfbWFub3ZhKQpgYGAKClJ1biBBTk9WQSBmb3IgZWFjaCBjYXRlZ29yeSBvZiBpbnRlcmVzdCAoc2lnbmlmaWNhbnQgaW4gTUFOT1ZBKQpgYGB7cn0KIyBNZXRhYm9saXNtCnR1c3NfZG5hX3RJSV9hb3YxPC1hb3YoTWV0YWJvbGlzbS5+VGltZXBvaW50LGRhdGE9dHVzc19kbmFfdElJX3N0YXRzKQpzdW1tYXJ5LmFvdih0dXNzX2RuYV90SUlfYW92MSkKVHVrZXlIU0QodHVzc19kbmFfdElJX2FvdjEpCgojIEdlbmV0aWMgSW5mb3JtYXRpb24gUHJvY2Vzc2luZwp0dXNzX2RuYV90SUlfYW92MjwtYW92KEdlbmV0aWMuSW5mb3JtYXRpb24uUHJvY2Vzc2luZy5+VGltZXBvaW50LGRhdGE9dHVzc19kbmFfdElJX3N0YXRzKQpzdW1tYXJ5LmFvdih0dXNzX2RuYV90SUlfYW92MikKVHVrZXlIU0QodHVzc19kbmFfdElJX2FvdjIpCgojIEVudmlyb25tZW50YWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZwp0dXNzX2RuYV90SUlfYW92MzwtYW92KEVudmlyb25tZW50YWwuSW5mb3JtYXRpb24uUHJvY2Vzc2luZy5+VGltZXBvaW50LGRhdGE9dHVzc19kbmFfdElJX3N0YXRzKQpzdW1tYXJ5LmFvdih0dXNzX2RuYV90SUlfYW92MykKVHVrZXlIU0QodHVzc19kbmFfdElJX2FvdjMpCgojIENlbGx1bGFyIFByb2Nlc3NpbmcKdHVzc19kbmFfdElJX2FvdjQ8LWFvdihDZWxsdWxhci5Qcm9jZXNzZXMuflRpbWVwb2ludCxkYXRhPXR1c3NfZG5hX3RJSV9zdGF0cykKc3VtbWFyeS5hb3YodHVzc19kbmFfdElJX2FvdjQpClR1a2V5SFNEKHR1c3NfZG5hX3RJSV9hb3Y0KQpgYGAKPC9kaXY+CgpQbG90IHRoZSBLRUdHIHRpZXIgSUkgY2F0ZWdvcmllcyBhcyBhIGJhcmNoYXJ0LgpgYGB7ciwgZWNobz1GQUxTRX0KdHVzc19kbmFfdElJX2JhcmRhdGE8LXJlYWQuY3N2KCJQbG90LkRhdGEvdHVzc19kbmFfdElJX2JhcnBsb3QuY3N2IikKYGBgCgpgYGB7cn0KIyBQbGFjZSB0aGUgS0VHRyB0aWVyIElJIGNhdGVnb3JpZXMgaW4gdGhlIHByZWZlcnJlZCBvcmRlciBmb3IgcGxvdHRpbmcKdHVzc19kbmFfdElJX2JhcmRhdGEkVGllci5JSSA8LSBmYWN0b3IodHVzc19kbmFfdElJX2JhcmRhdGEkVGllci5JSSxsZXZlbHMgPSBjKCJNZXRhYm9saXNtIiwgIkdlbmV0aWMgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyIsICJFbnZpcm9ubWVudGFsIEluZm9ybWF0aW9uIFByb2Nlc3NpbmciLCAiQ2VsbHVsYXIgUHJvY2Vzc2VzIikpCgp0dXNzX2RuYV90SUlfYmFyZGF0YSRTYW1wbGUgPC0gZmFjdG9yKHR1c3NfZG5hX3RJSV9iYXJkYXRhJFNhbXBsZSxsZXZlbHM9YygiVHVzcy1UMCIsIlR1c3MtVDQiLCJUdXNzLVQyNCIpKQoKdHVzc19kbmFfdElJX2JhcnBsb3Q8LWdncGxvdCh0dXNzX2RuYV90SUlfYmFyZGF0YSwgYWVzKHggPSBUaWVyLklJLCB5ID0gTWVhbiwgZmlsbCA9IFNhbXBsZSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3I9ImJsYWNrIikgKyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gTWVhbiAtIFNELCB5bWF4ID0gTWVhbiArIFNEKSwgd2lkdGggPSAwLjIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiS0VHRyBUaWVyIElJIENhdGVnb3JpZXMiLCBwYXN0ZSgiR2VuZSBDb3VudHMgKEdQTSkiKSkpKSArIHRoZW1lX21pbmltYWwoKSArIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTIpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheSIpLCBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkiLCBmaWxsPU5BLCBzaXplPTEpKSArIHNjYWxlX3NpemUoZ3VpZGU9RkFMU0UpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoInBhbGVncmVlbiIsICJncmVlbjMiLCAiZGFya2dyZWVuIikpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBmdW5jdGlvbihUaWVyLklJKSBzdHJfd3JhcChUaWVyLklJLCB3aWR0aCA9IDEwKSkgKyB5bGltKDAsODAwMDAwKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTEuMCwgeT03Nzc1MDAsIGxhYmVsPSJpdGFsaWMoTi5TLikiLCBwYXJzZT1UUlVFKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTIuMCwgeT0yNTAwMDAsIGxhYmVsPSJpdGFsaWMoTi5TLikiLCBwYXJzZT1UUlVFKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTMuMCwgeT0yMDAwMDAsIGxhYmVsPSJpdGFsaWMoTi5TLikiLCBwYXJzZT1UUlVFKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTQuMCwgeT0xNTAwMDAsIGxhYmVsPSJpdGFsaWMoTi5TLikiLCBwYXJzZT1UUlVFKQpgYGAKCmBgYHtyfQp0dXNzX2RuYV90SUlfYmFycGxvdApgYGAKCiMjIyMjIDcuMy4xLjIuIFRpZXIgSUlJIEV4cHJlc3Npb24KCkNhbGN1bGF0ZSBHUE0tbm9ybWFsaXplZCBnZW5lIGNvdW50IHN1bXMgZm9yIGVhY2ggVHVzcyBzYW1wbGUgaW4gZWFjaCBUaWVyIElJSSBjYXRlZ29yeS4KYGBge3J9CiMgQ2FsY3VsYXRlIEdQTS1ub3JtYWxpemVkIGdlbmUgY291bnQgc3VtcyBmb3IgZWFjaCBUdXNzIHNhbXBsZSBpbiBlYWNoIFRpZXIgSUlJIGNhdGVnb3J5CnR1c3NfZG5hX3RJSUlfc3VtPC1ncG1fYWxsX3BvdF9hbm4gJT4lIGdyb3VwX2J5KFRpZXJfSUlJKSAlPiUgc3VtbWFyaXNlX2F0KHZhcnMoIlMxMDcxMDciLCJTMTA3MTA4IiwiUzEwNzExNiIsIlMxMDcxMTciLCJTMTA3MTE5IiwiUzEwNzEyMSIpLCBzdW0pCnR1c3NfZG5hX3RJSUlfc3VtPC10dXNzX2RuYV90SUlJX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMoUzEwNzEwNyxTMTA3MTA4LFMxMDcxMTYsUzEwNzExNyxTMTA3MTE5LFMxMDcxMjEpLCBmdW5zKHJvdW5kKC4sIDApKSkKdHVzc19kbmFfdElJSV9zdW08LWFzLmRhdGEuZnJhbWUodHVzc19kbmFfdElJSV9zdW0pCnR1c3NfZG5hX3RJSUlfc3VtPC10dXNzX2RuYV90SUlJX3N1bVtvcmRlcigtdHVzc19kbmFfdElJSV9zdW0kUzEwNzEwNyksXQpgYGAKCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp0dXNzX2RuYV90SUlJX3N1bSRtZWFudHVzc19UMDwtYXBwbHkodHVzc19kbmFfdElJSV9zdW1bLDI6M10sIDEsIG1lYW4pCnR1c3NfZG5hX3RJSUlfc3VtJG1lYW50dXNzX1Q0PC1hcHBseSh0dXNzX2RuYV90SUlJX3N1bVssNDo1XSwgMSwgbWVhbikKdHVzc19kbmFfdElJSV9zdW0kbWVhbnR1c3NfVDI0PC1hcHBseSh0dXNzX2RuYV90SUlJX3N1bVssNjo3XSwgMSwgbWVhbikKdHVzc19kbmFfdElJSV9zdW08LXR1c3NfZG5hX3RJSUlfc3VtICU+JSBtdXRhdGVfYXQodmFycyhtZWFudHVzc19UMCxtZWFudHVzc19UNCxtZWFudHVzc19UMjQpLCBmdW5zKHJvdW5kKC4sIDApKSkKCiMgQ2FsY3VsYXRlIHNkIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp0dXNzX2RuYV90SUlJX3N1bSRzZHR1c3NfVDA8LWFwcGx5KHR1c3NfZG5hX3RJSUlfc3VtWywyOjNdLCAxLCBzZCkKdHVzc19kbmFfdElJSV9zdW0kc2R0dXNzX1Q0PC1hcHBseSh0dXNzX2RuYV90SUlJX3N1bVssNDo1XSwgMSwgc2QpCnR1c3NfZG5hX3RJSUlfc3VtJHNkdHVzc19UMjQ8LWFwcGx5KHR1c3NfZG5hX3RJSUlfc3VtWyw2OjddLCAxLCBzZCkKdHVzc19kbmFfdElJSV9zdW08LXR1c3NfZG5hX3RJSUlfc3VtICU+JSBtdXRhdGVfYXQodmFycyhzZHR1c3NfVDAsc2R0dXNzX1Q0LHNkdHVzc19UMjQpLCBmdW5zKHJvdW5kKC4sIDApKSkKCiMgV3JpdGUgZGF0YSB0byAuY3N2IGZpbGUKd3JpdGUuY3N2KHR1c3NfZG5hX3RJSUlfc3VtLCAnTm9ybS5SZXN1bHRzL3R1c3MuZG5hLnRJSUkubWVhbi5zZC5jc3YnKQoKIyBTdWJzZXQgTWVhbiB2YWx1ZXMKdHVzc19kbmFfdElJSV9tZWFuPC1zdWJzZXQodHVzc19kbmFfdElJSV9zdW0sIHNlbGVjdD1jKFRpZXJfSUlJLG1lYW50dXNzX1QwLG1lYW50dXNzX1Q0LG1lYW50dXNzX1QyNCkpCm5hbWVzKHR1c3NfZG5hX3RJSUlfbWVhbik8LWMoIlRpZXIgSUlJIiwgIlR1c3MtVDAiLCAiVHVzcy1UNCIsICJUdXNzLVQyNCIpCgojIFN1YnNldCBTRCB2YWx1ZXMKdHVzc19kbmFfdElJSV9zZDwtc3Vic2V0KHR1c3NfZG5hX3RJSUlfc3VtLCBzZWxlY3Q9YyhUaWVyX0lJSSxzZHR1c3NfVDAsc2R0dXNzX1Q0LHNkdHVzc19UMjQpKQpuYW1lcyh0dXNzX2RuYV90SUlJX3NkKTwtYygiVGllciBJSUkiLCAiVHVzcy1UMCIsICJUdXNzLVQ0IiwgIlR1c3MtVDI0IikKCiMgUmVtZW1iZXIgIlRpZXIgSUlJIiBhcyBub24tbnVtZXJpYyB2YWx1ZXMKdHVzc19kbmFfdElJSV9tZWFuX1RpZXJJSUk8LXR1c3NfZG5hX3RJSUlfbWVhbiRgVGllciBJSUlgCnR1c3NfZG5hX3RJSUlfc2RfVGllcklJSTwtdHVzc19kbmFfdElJSV9zZCRgVGllciBJSUlgCgojIFRyYW5zcG9zZSBhbGwgYnV0IGZpcnN0IGNvbHVtbiAoVGllciBJSSkKdHVzc19kbmFfdElJSV9tZWFuPC1hcy5kYXRhLmZyYW1lKHQodHVzc19kbmFfdElJSV9tZWFuWywtMV0pKQpjb2xuYW1lcyh0dXNzX2RuYV90SUlJX21lYW4pPC10dXNzX2RuYV90SUlJX21lYW5fVGllcklJSQp0dXNzX2RuYV90SUlJX3NkPC1hcy5kYXRhLmZyYW1lKHQodHVzc19kbmFfdElJSV9zZFssLTFdKSkKY29sbmFtZXModHVzc19kbmFfdElJSV9zZCk8LXR1c3NfZG5hX3RJSUlfc2RfVGllcklJSQoKIyBDb21iaW5lIG1lYW4gYW5kIHNkIGludG8gc2luZ2xlIGNvbHVtbiB3aXRoIMKxIGRpdmlkZXIKdHVzc19kbmFfdElJSV90YWJsZTwtYXMuZGF0YS5mcmFtZShkby5jYWxsKGNiaW5kLCBsYXBwbHkoMTpuY29sKHR1c3NfZG5hX3RJSUlfbWVhbiksIGZ1bmN0aW9uKGkpIHBhc3RlMCh0dXNzX2RuYV90SUlJX21lYW5bICwgaV0sICIgwrEgIiwgdHVzc19kbmFfdElJSV9zZFsgLCBpXSkpKSkKCiMgVHJhbnNwb3NlIHRoZSB0YWJsZSBiYWNrCnR1c3NfZG5hX3RJSUlfdGFibGU8LXQodHVzc19kbmFfdElJSV90YWJsZSkKCiMgUmVuYW1lIGNvbHVtbnMgdG8gU2l0ZXMKY29sbmFtZXModHVzc19kbmFfdElJSV90YWJsZSk8LWMoIlR1c3NvY2sgKFQwKSIsICJUdXNzb2NrIChUNCkiLCAiVHVzc29jayAoVDI0KSIpCgpyb3duYW1lcyh0dXNzX2RuYV90SUlJX3RhYmxlKTwtdHVzc19kbmFfdElJSV9tZWFuX1RpZXJJSUkKCiN0dXNzX2RuYV90SUlJX3RhYmxlCmBgYAoKUnVuIHN0YXRpc3RpY2FsIHRlc3RzIHRvIGRldGVybWluZSBpZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBleGlzdCBiZXR3ZWVuIHNhbXBsaW5nIHRpbWVwb2ludHMgZm9yIGVhY2ggVGllciBLRUdHIGNhdGVnb3J5LiBDbGljayBvbiB0aGUgKipTaG93L0hpZGUqKiBidXR0b24gdG8gc2VlIHRoZSBzdGF0aXN0aWNzLgoKPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLXRvZ2dsZT0iY29sbGFwc2UiIGRhdGEtdGFyZ2V0PSIjQmxvY2tOYW1lNTciPiBTaG93L0hpZGUgPC9idXR0b24+ICAKPGRpdiBpZD0iQmxvY2tOYW1lNTciIGNsYXNzPSJjb2xsYXBzZSI+CmBgYHtyfQojIFN1YnNldCB0aGUgInN1bSIgdmFsdWVzIGZvciBlYWNoIHNhbXBsZQp0dXNzX2RuYV90SUlJX3N0YXRzPC1zdWJzZXQodHVzc19kbmFfdElJSV9zdW0sIHNlbGVjdD1jKFRpZXJfSUlJLFMxMDcxMDcsUzEwNzEwOCxTMTA3MTE2LFMxMDcxMTcsUzEwNzExOSxTMTA3MTIxKSkKCnJvd25hbWVzKHR1c3NfZG5hX3RJSUlfc3RhdHMpIDwtIHR1c3NfZG5hX3RJSUlfc3RhdHMkVGllcl9JSUkKdHVzc19kbmFfdElJSV9zdGF0czwtYXMuZGF0YS5mcmFtZSh0KHR1c3NfZG5hX3RJSUlfc3RhdHNbLTFdKSkKCiMgQWRkIHRoZSB0aW1lcG9pbnQgY29sdW1uIHRvIHRoZSBzdW0gdGFibGUKdHVzc19kbmFfdElJSV9zdGF0czwtZGF0YS5mcmFtZShUaW1lcG9pbnQsdHVzc19kbmFfdElJSV9zdGF0cykKCiMgU3Vic2V0IHJlc3BvbnNlIHZhcmlhYmxlcyBmb3IgTUFOT1ZBCnR1c3NfZG5hX3RJSUlfc3RhdHMkcmVzcG9uc2UgPC0gYXMubWF0cml4KHR1c3NfZG5hX3RJSUlfc3RhdHNbLCAyOjI2XSkKCiMgTUFOT1ZBIHRlc3QKdHVzc19kbmFfdElJSV9tYW5vdmEgPC0gbWFub3ZhKHJlc3BvbnNlIH4gVGltZXBvaW50LCBkYXRhPXR1c3NfZG5hX3RJSUlfc3RhdHMpCnN1bW1hcnkuYW92KHR1c3NfZG5hX3RJSUlfbWFub3ZhKQpgYGAKPC9kaXY+CgojIyMjIyA3LjMuMS4zLiBUaWVyIElWIEV4cHJlc3Npb24KCkNhbGN1bGF0ZSBHUE0tbm9ybWFsaXplZCBnZW5lIGNvdW50IHN1bXMgZm9yIGVhY2ggVHVzcyBzYW1wbGUgaW4gZWFjaCBUaWVyIElWIGNhdGVnb3J5LgpgYGB7cn0KIyBDYWxjdWxhdGUgR1BNLW5vcm1hbGl6ZWQgZ2VuZSBjb3VudCBzdW1zIGZvciBlYWNoIFR1c3Mgc2FtcGxlIGluIGVhY2ggVGllciBJSUkgY2F0ZWdvcnkKdHVzc19kbmFfdElWX3N1bTwtZ3BtX2FsbF9wb3RfYW5uICU+JSBncm91cF9ieShUaWVyX0lWKSAlPiUgc3VtbWFyaXNlX2F0KHZhcnMoIlMxMDcxMDciLCJTMTA3MTA4IiwiUzEwNzExNiIsIlMxMDcxMTciLCJTMTA3MTE5IiwiUzEwNzEyMSIpLCBzdW0pCnR1c3NfZG5hX3RJVl9zdW08LXR1c3NfZG5hX3RJVl9zdW0gJT4lIG11dGF0ZV9hdCh2YXJzKFMxMDcxMDcsUzEwNzEwOCxTMTA3MTE2LFMxMDcxMTcsUzEwNzExOSxTMTA3MTIxKSwgZnVucyhyb3VuZCguLCAwKSkpCnR1c3NfZG5hX3RJVl9zdW08LWFzLmRhdGEuZnJhbWUodHVzc19kbmFfdElWX3N1bSkKdHVzc19kbmFfdElWX3N1bTwtdHVzc19kbmFfdElWX3N1bVtvcmRlcigtdHVzc19kbmFfdElWX3N1bSRTMTA3MTA3KSxdCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIG1lYW4gdmFsdWVzIGZyb20gdGhlIHJlcGxpY2F0ZSBzdW1zCnR1c3NfZG5hX3RJVl9zdW0kbWVhbnR1c3NfVDA8LWFwcGx5KHR1c3NfZG5hX3RJVl9zdW1bLDI6M10sIDEsIG1lYW4pCnR1c3NfZG5hX3RJVl9zdW0kbWVhbnR1c3NfVDQ8LWFwcGx5KHR1c3NfZG5hX3RJVl9zdW1bLDQ6NV0sIDEsIG1lYW4pCnR1c3NfZG5hX3RJVl9zdW0kbWVhbnR1c3NfVDI0PC1hcHBseSh0dXNzX2RuYV90SVZfc3VtWyw2OjddLCAxLCBtZWFuKQp0dXNzX2RuYV90SVZfc3VtPC10dXNzX2RuYV90SVZfc3VtICU+JSBtdXRhdGVfYXQodmFycyhtZWFudHVzc19UMCxtZWFudHVzc19UNCxtZWFudHVzc19UMjQpLCBmdW5zKHJvdW5kKC4sIDApKSkKCiMgQ2FsY3VsYXRlIHNkIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp0dXNzX2RuYV90SVZfc3VtJHNkdHVzc19UMDwtYXBwbHkodHVzc19kbmFfdElWX3N1bVssMjozXSwgMSwgc2QpCnR1c3NfZG5hX3RJVl9zdW0kc2R0dXNzX1Q0PC1hcHBseSh0dXNzX2RuYV90SVZfc3VtWyw0OjVdLCAxLCBzZCkKdHVzc19kbmFfdElWX3N1bSRzZHR1c3NfVDI0PC1hcHBseSh0dXNzX2RuYV90SVZfc3VtWyw2OjddLCAxLCBzZCkKdHVzc19kbmFfdElWX3N1bTwtdHVzc19kbmFfdElWX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMoc2R0dXNzX1QwLHNkdHVzc19UNCxzZHR1c3NfVDI0KSwgZnVucyhyb3VuZCguLCAwKSkpCgojIFdyaXRlIGRhdGEgdG8gLmNzdiBmaWxlCndyaXRlLmNzdih0dXNzX2RuYV90SVZfc3VtLCAnTm9ybS5SZXN1bHRzL3R1c3MuZG5hLnRJVi5tZWFuLnNkLmNzdicpCgojIFN1YnNldCBNZWFuIHZhbHVlcwp0dXNzX2RuYV90SVZfbWVhbjwtc3Vic2V0KHR1c3NfZG5hX3RJVl9zdW0sIHNlbGVjdD1jKFRpZXJfSVYsbWVhbnR1c3NfVDAsbWVhbnR1c3NfVDQsbWVhbnR1c3NfVDI0KSkKbmFtZXModHVzc19kbmFfdElWX21lYW4pPC1jKCJUaWVyIElWIiwgIlR1c3MtVDAiLCAiVHVzcy1UNCIsICJUdXNzLVQyNCIpCgojIFN1YnNldCBTRCB2YWx1ZXMKdHVzc19kbmFfdElWX3NkPC1zdWJzZXQodHVzc19kbmFfdElWX3N1bSwgc2VsZWN0PWMoVGllcl9JVixzZHR1c3NfVDAsc2R0dXNzX1Q0LHNkdHVzc19UMjQpKQpuYW1lcyh0dXNzX2RuYV90SVZfc2QpPC1jKCJUaWVyIElWIiwgIlR1c3MtVDAiLCAiVHVzcy1UNCIsICJUdXNzLVQyNCIpCgojIFJlbWVtYmVyICJUaWVyIElWIiBhcyBub24tbnVtZXJpYyB2YWx1ZXMKdHVzc19kbmFfdElWX21lYW5fVGllcklWPC10dXNzX2RuYV90SVZfbWVhbiRgVGllciBJVmAKdHVzc19kbmFfdElWX3NkX1RpZXJJVjwtdHVzc19kbmFfdElWX3NkJGBUaWVyIElWYAoKIyBUcmFuc3Bvc2UgYWxsIGJ1dCBmaXJzdCBjb2x1bW4gKFRpZXIgSVYpCnR1c3NfZG5hX3RJVl9tZWFuPC1hcy5kYXRhLmZyYW1lKHQodHVzc19kbmFfdElWX21lYW5bLC0xXSkpCmNvbG5hbWVzKHR1c3NfZG5hX3RJVl9tZWFuKTwtdHVzc19kbmFfdElWX21lYW5fVGllcklWCnR1c3NfZG5hX3RJVl9zZDwtYXMuZGF0YS5mcmFtZSh0KHR1c3NfZG5hX3RJVl9zZFssLTFdKSkKY29sbmFtZXModHVzc19kbmFfdElWX3NkKTwtdHVzc19kbmFfdElWX3NkX1RpZXJJVgoKIyBDb21iaW5lIG1lYW4gYW5kIHNkIGludG8gc2luZ2xlIGNvbHVtbiB3aXRoIMKxIGRpdmlkZXIKdHVzc19kbmFfdElWX3RhYmxlPC1hcy5kYXRhLmZyYW1lKGRvLmNhbGwoY2JpbmQsIGxhcHBseSgxOm5jb2wodHVzc19kbmFfdElWX21lYW4pLCBmdW5jdGlvbihpKSBwYXN0ZTAodHVzc19kbmFfdElWX21lYW5bICwgaV0sICIgwrEgIiwgdHVzc19kbmFfdElWX3NkWyAsIGldKSkpKQoKIyBUcmFuc3Bvc2UgdGhlIHRhYmxlIGJhY2sKdHVzc19kbmFfdElWX3RhYmxlPC10KHR1c3NfZG5hX3RJVl90YWJsZSkKCiMgUmVuYW1lIGNvbHVtbnMgdG8gU2l0ZXMKY29sbmFtZXModHVzc19kbmFfdElWX3RhYmxlKTwtYygiVHVzc29jayAoVDApIiwgIlR1c3NvY2sgKFQ0KSIsICJUdXNzb2NrIChUMjQpIikKCnJvd25hbWVzKHR1c3NfZG5hX3RJVl90YWJsZSk8LXR1c3NfZG5hX3RJVl9tZWFuX1RpZXJJVgoKI3R1c3NfZG5hX3RJVl90YWJsZQpgYGAKCiMjIyMgNy4zLjIuIFdldCBTZWRnZSBUdW5kcmEKCkxvb2sgYXQgZGlmZmVyZW5jZXMgaW4gZ2VuZSBleHByZXNzaW9uIHBhdHRlcm5zIGZvciBtdWx0aXBsZSBUaWVyIGxldmVscyB3aXRoaW4gdGhlIFdldCBTZWRnZSB0dW5kcmEgYmV0d2VlbiBzYW1wbGluZyB0aW1lIHBvaW50cy4KCiMjIyMjIDcuMy4yLjEuIFRpZXIgSUkgRXhwcmVzc2lvbgoKQ2FsY3VsYXRlIEdQTS1ub3JtYWxpemVkIGdlbmUgY291bnQgc3VtcyBmb3IgZWFjaCBXUyBzYW1wbGUgaW4gZWFjaCBUaWVyIElJIGNhdGVnb3J5LgpgYGB7cn0KIyBDYWxjdWxhdGUgR1BNLW5vcm1hbGl6ZWQgZ2VuZSBjb3VudCBzdW1zIGZvciBlYWNoIFdTIHNhbXBsZSBpbiBlYWNoIFRpZXIgSUkgY2F0ZWdvcnkKd3NfZG5hX3RJSV9zdW08LWdwbV9hbGxfcG90X2FubiAlPiUgZ3JvdXBfYnkoVGllcl9JSSkgJT4lIHN1bW1hcmlzZV9hdCh2YXJzKCJTMTA3MTA0IiwiUzEwNzEwNSIsIlMxMDcxMDYiLCJTMTA3MTEwIiwiUzEwNzExMSIsIlMxMDcxMTIiLCJTMTA3MTEzIiwiUzEwNzExNCIsIlMxMDcxMTUiKSwgc3VtKQoKd3NfZG5hX3RJSV9zdW08LXdzX2RuYV90SUlfc3VtICU+JSBtdXRhdGVfYXQodmFycyhTMTA3MTA0LFMxMDcxMDUsUzEwNzEwNixTMTA3MTEwLFMxMDcxMTEsUzEwNzExMixTMTA3MTEzLFMxMDcxMTQsUzEwNzExNSksIGZ1bnMocm91bmQoLiwgMCkpKQoKd3NfZG5hX3RJSV9zdW08LWFzLmRhdGEuZnJhbWUod3NfZG5hX3RJSV9zdW0pCgp3c19kbmFfdElJX3N1bTwtd3NfZG5hX3RJSV9zdW1bb3JkZXIoLXdzX2RuYV90SUlfc3VtJFMxMDcxMDQpLF0KYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQprYWJsZSh3c19kbmFfdElJX3N1bSwgY2FwdGlvbiA9ICJXZXQgU2VkZ2UgVGllciBJSSBLRUdHIGNhdGVnb3J5IHN1bW1hcnkgYnkgc2FtcGxlIGluIE1ldGFnZW5vbWUuIiwgZm9ybWF0LmFyZ3MgPSBsaXN0KGJpZy5tYXJrPSIsIikpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsImhvdmVyIiwiY29uZGVuc2VkIikpCmBgYAoKSGVhdG1hcCBmb3IgVGllciBJSSBjYXRlZ29yaWVzIGJ5IHNhbXBsaW5nIHRpbWVwb2ludHMKYGBge3J9CiMgQ3JlYXRlIGNvcHkgb2YgIndzX2RuYV90SUlfc3VtIiBvYmplY3QgdG8gcHJlcCBmb3IgaGVhdG1hcAp3c19kbmFfdElJX2hlYXRtYXA8LXdzX2RuYV90SUlfc3VtCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoVGllciBjYXRlZ29yaWVzKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKHdzX2RuYV90SUlfaGVhdG1hcCkgPC0gd3NfZG5hX3RJSV9oZWF0bWFwJFRpZXJfSUkKd3NfZG5hX3RJSV9oZWF0bWFwPC1hcy5kYXRhLmZyYW1lKHdzX2RuYV90SUlfaGVhdG1hcFstMV0pCgojIFJlbmFtZSBjb2x1bW5zIHRvIHNhbXBsZSBJRHMKY29sbmFtZXMod3NfZG5hX3RJSV9oZWF0bWFwKTwtYygiV1MxLVQwIiwiV1MyLVQwIiwiV1MzLVQwIiwiV1MxLVQ0IiwiV1MyLVQ0IiwiV1MzLVQ0IiwiV1MxLVQyNCIsIldTMi1UMjQiLCJXUzMtVDI0IikKCiMgUmVtb3ZlIHJvd3MgZm9yICJPcmdhbmlzbWFsIFN5c3RlbXMiIGFuZCAiSHVtYW4gRGlzZWFzZXMiCiN3c19kbmFfdElJX2hlYXRtYXAgPC0gd3NfZG5hX3RJSV9oZWF0bWFwWy1jKDUsNiksXQoKIyBDb252ZXJ0IGRhdGFmcmFtZSBpbnRvIGEgbWF0cml4IGZvciBoZWF0bWFwCndzX2RuYV90SUlfaGVhdG1hcDwtYXMubWF0cml4KHdzX2RuYV90SUlfaGVhdG1hcCkKCiMgU2NhbGUgbWF0cml4IHZhbHVlcyB0byBnZW5lcmF0ZSBaLXNjb3Jlcwp3c19kbmFfdElJX2hlYXRtYXA8LXNjYWxlKHQod3NfZG5hX3RJSV9oZWF0bWFwKSkKCndzX2RuYV90SUlfaGVhdG1hcDwtdCh3c19kbmFfdElJX2hlYXRtYXApCgojIFNwZWNpZnkgUkNvbG9yQnJld2VyIGN1c3RvbSBjb2xvciBwYWxldHRlCmNvbCA8LSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTAsICJSZFlsQnUiKSkoMjU2KQoKIyBQaGVhdG1hcApwaGVhdG1hcCh3c19kbmFfdElJX2hlYXRtYXAsIHRyZWVoZWlnaHRfcm93ID0gMCwgdHJlZWhlaWdodF9jb2wgPSAwLGNsdXN0ZXJfcm93cyA9IEZBTFNFLCBjbHVzdGVyX2NvbHMgPSBGQUxTRSkKYGBgCgpDYWxjdWxhdGUgbWVhbiB2YWx1ZXMgZnJvbSB0aGUgcmVwbGljYXRlIHN1bXMuCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp3c19kbmFfdElJX3N1bSRtZWFuV1NfVDA8LWFwcGx5KHdzX2RuYV90SUlfc3VtWywyOjRdLCAxLCBtZWFuKQp3c19kbmFfdElJX3N1bSRtZWFuV1NfVDQ8LWFwcGx5KHdzX2RuYV90SUlfc3VtWyw1OjddLCAxLCBtZWFuKQp3c19kbmFfdElJX3N1bSRtZWFuV1NfVDI0PC1hcHBseSh3c19kbmFfdElJX3N1bVssODoxMF0sIDEsIG1lYW4pCndzX2RuYV90SUlfc3VtPC13c19kbmFfdElJX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMobWVhbldTX1QwLG1lYW5XU19UNCxtZWFuV1NfVDI0KSwgZnVucyhyb3VuZCguLCAwKSkpCgojIENhbGN1bGF0ZSBzZCB2YWx1ZXMgZnJvbSB0aGUgcmVwbGljYXRlIHN1bXMKd3NfZG5hX3RJSV9zdW0kc2RXU19UMDwtYXBwbHkod3NfZG5hX3RJSV9zdW1bLDI6NF0sIDEsIHNkKQp3c19kbmFfdElJX3N1bSRzZFdTX1Q0PC1hcHBseSh3c19kbmFfdElJX3N1bVssNTo3XSwgMSwgc2QpCndzX2RuYV90SUlfc3VtJHNkV1NfVDI0PC1hcHBseSh3c19kbmFfdElJX3N1bVssODoxMF0sIDEsIHNkKQp3c19kbmFfdElJX3N1bTwtd3NfZG5hX3RJSV9zdW0gJT4lIG11dGF0ZV9hdCh2YXJzKHNkV1NfVDAsc2RXU19UNCxzZFdTX1QyNCksIGZ1bnMocm91bmQoLiwgMCkpKQoKIyBTdWJzZXQgTWVhbiB2YWx1ZXMKd3NfZG5hX3RJSV9tZWFuPC1zdWJzZXQod3NfZG5hX3RJSV9zdW0sIHNlbGVjdD1jKFRpZXJfSUksbWVhbldTX1QwLG1lYW5XU19UNCxtZWFuV1NfVDI0KSkKbmFtZXMod3NfZG5hX3RJSV9tZWFuKTwtYygiVGllciBJSSIsICJXUyAtIFQwIiwgIldTIC0gVDQiLCAiV1MgLSBUMjQiKQoKIyBTdWJzZXQgU0QgdmFsdWVzCndzX2RuYV90SUlfc2Q8LXN1YnNldCh3c19kbmFfdElJX3N1bSwgc2VsZWN0PWMoVGllcl9JSSxzZFdTX1QwLHNkV1NfVDQsc2RXU19UMjQpKQpuYW1lcyh3c19kbmFfdElJX3NkKTwtYygiVGllciBJSSIsICJXUyAtIFQwIiwgIldTIC0gVDQiLCAiV1MgLSBUMjQiKQoKIyBSZW1lbWJlciAiVGllciBJSSIgYXMgbm9uLW51bWVyaWMgdmFsdWVzCndzX2RuYV90SUlfbWVhbl9UaWVySUk8LXdzX2RuYV90SUlfbWVhbiRgVGllciBJSWAKd3NfZG5hX3RJSV9zZF9UaWVySUk8LXdzX2RuYV90SUlfc2QkYFRpZXIgSUlgCgojIFRyYW5zcG9zZSBhbGwgYnV0IGZpcnN0IGNvbHVtbiAoVGllciBJSSkKd3NfZG5hX3RJSV9tZWFuPC1hcy5kYXRhLmZyYW1lKHQod3NfZG5hX3RJSV9tZWFuWywtMV0pKQpjb2xuYW1lcyh3c19kbmFfdElJX21lYW4pPC13c19kbmFfdElJX21lYW5fVGllcklJCndzX2RuYV90SUlfc2Q8LWFzLmRhdGEuZnJhbWUodCh3c19kbmFfdElJX3NkWywtMV0pKQpjb2xuYW1lcyh3c19kbmFfdElJX3NkKTwtd3NfZG5hX3RJSV9zZF9UaWVySUkKCiMgQ29tYmluZSBtZWFuIGFuZCBzZCBpbnRvIHNpbmdsZSBjb2x1bW4gd2l0aCDCsSBkaXZpZGVyCndzX2RuYV90SUlfdGFibGU8LWFzLmRhdGEuZnJhbWUoZG8uY2FsbChjYmluZCwgbGFwcGx5KDE6bmNvbCh3c19kbmFfdElJX21lYW4pLCBmdW5jdGlvbihpKSBwYXN0ZTAod3NfZG5hX3RJSV9tZWFuWyAsIGldLCAiIMKxICIsIHdzX2RuYV90SUlfc2RbICwgaV0pKSkpCgojIFRyYW5zcG9zZSB0aGUgdGFibGUgYmFjawp3c19kbmFfdElJX3RhYmxlPC10KHdzX2RuYV90SUlfdGFibGUpCgojIFJlbmFtZSBjb2x1bW5zIHRvIFNpdGVzCmNvbG5hbWVzKHdzX2RuYV90SUlfdGFibGUpPC1jKCJXZXQgU2VkZ2UgKFQwKSIsICJXZXQgU2VkZ2UgKFQ0KSIsICJXZXQgU2VkZ2UgKFQyNCkiKQoKcm93bmFtZXMod3NfZG5hX3RJSV90YWJsZSk8LXdzX2RuYV90SUlfbWVhbl9UaWVySUkKCmthYmxlKHdzX2RuYV90SUlfdGFibGUsIGNhcHRpb24gPSAiV2V0IFNlZGdlIFRpZXIgSUkgS0VHRyBjYXRlZ29yeSBhdmVyYWdlcyAowrEgc3RhbmRhcmQgZGV2aWF0aW9uKSBieSBzYW1wbGUuIiwgZm9ybWF0LmFyZ3MgPSBsaXN0KGJpZy5tYXJrPSIsIiksIGFsaWduID0gImwiKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJob3ZlciIsImNvbmRlbnNlZCIpKQpgYGAKClJ1biBzdGF0aXN0aWNhbCB0ZXN0cyB0byBkZXRlcm1pbmUgaWYgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgZXhpc3QgYmV0d2VlbiBzYW1wbGluZyB0aW1lcG9pbnRzIGZvciBlYWNoIFRpZXIgS0VHRyBjYXRlZ29yeS4gQ2xpY2sgb24gdGhlICoqU2hvdy9IaWRlKiogYnV0dG9uIHRvIHNlZSB0aGUgc3RhdGlzdGljcy4KCjxidXR0b24gY2xhc3M9ImJ0biBidG4tcHJpbWFyeSIgZGF0YS10b2dnbGU9ImNvbGxhcHNlIiBkYXRhLXRhcmdldD0iI0Jsb2NrTmFtZTU5Ij4gU2hvdy9IaWRlIDwvYnV0dG9uPiAgCjxkaXYgaWQ9IkJsb2NrTmFtZTU5IiBjbGFzcz0iY29sbGFwc2UiPgpgYGB7cn0KIyBTdWJzZXQgdGhlICJzdW0iIHZhbHVlcyBmb3IgZWFjaCBzYW1wbGUKd3NfZG5hX3RJSV9zdGF0czwtc3Vic2V0KHdzX2RuYV90SUlfc3VtLCBzZWxlY3Q9YyhUaWVyX0lJLFMxMDcxMDQsUzEwNzEwNSxTMTA3MTA2LFMxMDcxMTAsUzEwNzExMSxTMTA3MTEyLFMxMDcxMTMsUzEwNzExNCxTMTA3MTE1KSkKCnJvd25hbWVzKHdzX2RuYV90SUlfc3RhdHMpIDwtIHdzX2RuYV90SUlfc3RhdHMkVGllcl9JSQp3c19kbmFfdElJX3N0YXRzPC1hcy5kYXRhLmZyYW1lKHQod3NfZG5hX3RJSV9zdGF0c1stMV0pKQoKIyBDcmVhdGUgVGltZXBvaW50IG9iamVjdCBmb3IgV1NfRE5BICg5IHNhbXBsZXMpClRpbWVwb2ludDI8LWMoIlQwIiwiVDAiLCJUMCIsIlQ0IiwiVDQiLCJUNCIsIlQyNCIsIlQyNCIsIlQyNCIpClRpbWVwb2ludDI8LWRhdGEuZnJhbWUoVGltZXBvaW50MikKCiMgQWRkIHRoZSB0aW1lcG9pbnQgY29sdW1uIHRvIHRoZSBzdW0gdGFibGUKd3NfZG5hX3RJSV9zdGF0czwtZGF0YS5mcmFtZShUaW1lcG9pbnQyLHdzX2RuYV90SUlfc3RhdHMpCgojIFN1YnNldCByZXNwb25zZSB2YXJpYWJsZXMgZm9yIE1BTk9WQQp3c19kbmFfdElJX3N0YXRzJHJlc3BvbnNlIDwtIGFzLm1hdHJpeCh3c19kbmFfdElJX3N0YXRzWywgMjo1XSkKCiMgTUFOT1ZBIHRlc3QKd3NfZG5hX3RJSV9tYW5vdmEgPC0gbWFub3ZhKHJlc3BvbnNlIH4gVGltZXBvaW50MiwgZGF0YT13c19kbmFfdElJX3N0YXRzKQpzdW1tYXJ5LmFvdih3c19kbmFfdElJX21hbm92YSkKYGBgCjwvZGl2PgoKUGxvdCBhIGJhcmNoYXJ0IGZvciBUaWVyIElJIGNhdGVnb3JpZXMgYnkgc2FtcGxpbmcgdGltZXBvaW50cy4KYGBge3IgZWNobz1GQUxTRX0Kd3NfZG5hX3RJSV9iYXJkYXRhPC1yZWFkLmNzdigiUGxvdC5EYXRhL3dzX2RuYV90SUlfYmFycGxvdC5jc3YiKQpgYGAKCmBgYHtyfQojIFBsYWNlIFRpZXIgSUkgY2F0ZWdvcmllcyBpbiB0aGUgcHJlZmVycmVkIG9yZGVyIGZvciBwbG90dGluZwp3c19kbmFfdElJX2JhcmRhdGEkVGllci5JSSA8LSBmYWN0b3Iod3NfZG5hX3RJSV9iYXJkYXRhJFRpZXIuSUksbGV2ZWxzID0gYygiTWV0YWJvbGlzbSIsICJHZW5ldGljIEluZm9ybWF0aW9uIFByb2Nlc3NpbmciLCAiRW52aXJvbm1lbnRhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nIiwgIkNlbGx1bGFyIFByb2Nlc3NlcyIpKQoKd3NfZG5hX3RJSV9iYXJkYXRhJFNhbXBsZSA8LSBmYWN0b3Iod3NfZG5hX3RJSV9iYXJkYXRhJFNhbXBsZSxsZXZlbHM9YygiV1MtVDAiLCJXUy1UNCIsIldTLVQyNCIpKQoKd3NfZG5hX3RJSV9iYXJwbG90PC1nZ3Bsb3Qod3NfZG5hX3RJSV9iYXJkYXRhLCBhZXMoeCA9IFRpZXIuSUksIHkgPSBNZWFuLCBmaWxsID0gU2FtcGxlKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCBjb2xvcj0iYmxhY2siKSArIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBNZWFuIC0gU0QsIHltYXggPSBNZWFuICsgU0QpLCB3aWR0aCA9IDAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArIHlsYWIoZXhwcmVzc2lvbihhdG9wKCJLRUdHIFRpZXIgSUkgQ2F0ZWdvcmllcyIsIHBhc3RlKCJHZW5lIENvdW50cyAoR1BNKSIpKSkpICsgdGhlbWVfbWluaW1hbCgpICsgdGhlbWUoYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5IiksIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JheSIsIGZpbGw9TkEsIHNpemU9MSkpICsgc2NhbGVfc2l6ZShndWlkZT1GQUxTRSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygibGlnaHRza3libHVlMSIsImRvZGdlcmJsdWUxIiwibWlkbmlnaHRibHVlIikpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKFRpZXIuSUkpIHN0cl93cmFwKFRpZXIuSUksIHdpZHRoID0gMTApKSArIHlsaW0oMCw4MDAwMDApICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MS4wLCB5PTc1MDAwMCwgbGFiZWw9Iml0YWxpYyhOLlMuKSIsIHBhcnNlPVRSVUUpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9Mi4wLCB5PTI1MDAwMCwgbGFiZWw9Iml0YWxpYyhOLlMuKSIsIHBhcnNlPVRSVUUpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9My4wLCB5PTIwMDAwMCwgbGFiZWw9Iml0YWxpYyhOLlMuKSIsIHBhcnNlPVRSVUUpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9NC4wLCB5PTE1MDAwMCwgbGFiZWw9Iml0YWxpYyhOLlMuKSIsIHBhcnNlPVRSVUUpCmBgYAoKYGBge3J9CndzX2RuYV90SUlfYmFycGxvdApgYGAKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CiMgU2F2ZSB0aGUgVFVORFJBIEJFVEEgRElWRVJTSVRZIHBsb3RzIGFuZCBUVU5EUkEgVElFUiBJSSBwbG90cyB0b2dldGhlcgpzZXRFUFMoKQpwb3N0c2NyaXB0KCJGaWcuRGl2LktFR0cuZXBzIiwgd2lkdGg9MTAuMCwgaGVpZ2h0ID0gOC4wKQpnZ2FycmFuZ2UodHVzcy5wY29hLCB3cy5wY29hLCB0dXNzX3RJSV9iYXJwbG90LCB3c190SUlfYmFycGxvdCwgaGVpZ2h0cz1jKDMsMyksCiAgICAgICAgICBsYWJlbHMgPSBjKCJBIiwiQiIsIkMiLCJEIiksCiAgICAgICAgICBuY29sID0gMiwgbnJvdyA9IDIsIGFsaWduPSJ2IikKZGV2Lm9mZigpCmBgYAoKIyMjIyMgNy4zLjIuMi4gVGllciBJSUkgRXhwcmVzc2lvbgoKQ2FsY3VsYXRlIEdQTS1ub3JtYWxpemVkIGdlbmUgY291bnQgc3VtcyBmb3IgZWFjaCBXUyBzYW1wbGUgaW4gZWFjaCBUaWVyIElJSSBjYXRlZ29yeS4KYGBge3J9CiMgQ2FsY3VsYXRlIEdQTS1ub3JtYWxpemVkIGdlbmUgY291bnQgc3VtcyBmb3IgZWFjaCBXUyBzYW1wbGUgaW4gZWFjaCBUaWVyIElJSSBjYXRlZ29yeQp3c19kbmFfdElJSV9zdW08LWdwbV9hbGxfcG90X2FubiAlPiUgZ3JvdXBfYnkoVGllcl9JSUkpICU+JSBzdW1tYXJpc2VfYXQodmFycygiUzEwNzEwNCIsIlMxMDcxMDUiLCJTMTA3MTA2IiwiUzEwNzExMCIsIlMxMDcxMTEiLCJTMTA3MTEyIiwiUzEwNzExMyIsIlMxMDcxMTQiLCJTMTA3MTE1IiksIHN1bSkKd3NfZG5hX3RJSUlfc3VtPC13c19kbmFfdElJSV9zdW0gJT4lIG11dGF0ZV9hdCh2YXJzKFMxMDcxMDQsUzEwNzEwNSxTMTA3MTA2LFMxMDcxMTAsUzEwNzExMSxTMTA3MTEyLFMxMDcxMTMsUzEwNzExNCxTMTA3MTE1KSwgZnVucyhyb3VuZCguLCAwKSkpCndzX2RuYV90SUlJX3N1bTwtYXMuZGF0YS5mcmFtZSh3c19kbmFfdElJSV9zdW0pCndzX2RuYV90SUlJX3N1bTwtd3NfZG5hX3RJSUlfc3VtW29yZGVyKC13c19kbmFfdElJSV9zdW0kUzEwNzEwNCksXQpgYGAKCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp3c19kbmFfdElJSV9zdW0kbWVhbldTX1QwPC1hcHBseSh3c19kbmFfdElJSV9zdW1bLDI6NF0sIDEsIG1lYW4pCndzX2RuYV90SUlJX3N1bSRtZWFuV1NfVDQ8LWFwcGx5KHdzX2RuYV90SUlJX3N1bVssNTo3XSwgMSwgbWVhbikKd3NfZG5hX3RJSUlfc3VtJG1lYW5XU19UMjQ8LWFwcGx5KHdzX2RuYV90SUlJX3N1bVssODoxMF0sIDEsIG1lYW4pCndzX2RuYV90SUlJX3N1bTwtd3NfZG5hX3RJSUlfc3VtICU+JSBtdXRhdGVfYXQodmFycyhtZWFuV1NfVDAsbWVhbldTX1Q0LG1lYW5XU19UMjQpLCBmdW5zKHJvdW5kKC4sIDApKSkKCiMgQ2FsY3VsYXRlIHNkIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp3c19kbmFfdElJSV9zdW0kc2RXU19UMDwtYXBwbHkod3NfZG5hX3RJSUlfc3VtWywyOjRdLCAxLCBzZCkKd3NfZG5hX3RJSUlfc3VtJHNkV1NfVDQ8LWFwcGx5KHdzX2RuYV90SUlJX3N1bVssNTo3XSwgMSwgc2QpCndzX2RuYV90SUlJX3N1bSRzZFdTX1QyNDwtYXBwbHkod3NfZG5hX3RJSUlfc3VtWyw4OjEwXSwgMSwgc2QpCndzX2RuYV90SUlJX3N1bTwtd3NfZG5hX3RJSUlfc3VtICU+JSBtdXRhdGVfYXQodmFycyhzZFdTX1QwLHNkV1NfVDQsc2RXU19UMjQpLCBmdW5zKHJvdW5kKC4sIDApKSkKCiMgV3JpdGUgZGF0YSB0byAuY3N2IGZpbGUKd3JpdGUuY3N2KHdzX2RuYV90SUlJX3N1bSwgJ05vcm0uUmVzdWx0cy93cy5kbmEudElJSS5tZWFuLnNkLmNzdicpCgojIFN1YnNldCBNZWFuIHZhbHVlcwp3c19kbmFfdElJSV9tZWFuPC1zdWJzZXQod3NfZG5hX3RJSUlfc3VtLCBzZWxlY3Q9YyhUaWVyX0lJSSxtZWFuV1NfVDAsbWVhbldTX1Q0LG1lYW5XU19UMjQpKQpuYW1lcyh3c19kbmFfdElJSV9tZWFuKTwtYygiVGllciBJSUkiLCAiV1MgLSBUMCIsICJXUyAtIFQ0IiwgIldTIC0gVDI0IikKCiMgU3Vic2V0IFNEIHZhbHVlcwp3c19kbmFfdElJSV9zZDwtc3Vic2V0KHdzX2RuYV90SUlJX3N1bSwgc2VsZWN0PWMoVGllcl9JSUksc2RXU19UMCxzZFdTX1Q0LHNkV1NfVDI0KSkKbmFtZXMod3NfZG5hX3RJSUlfc2QpPC1jKCJUaWVyIElJSSIsICJXUyAtIFQwIiwgIldTIC0gVDQiLCAiV1MgLSBUMjQiKQoKIyBSZW1lbWJlciAiVGllciBJSUkiIGFzIG5vbi1udW1lcmljIHZhbHVlcwp3c19kbmFfdElJSV9tZWFuX1RpZXJJSUk8LXdzX2RuYV90SUlJX21lYW4kYFRpZXIgSUlJYAp3c19kbmFfdElJSV9zZF9UaWVySUlJPC13c19kbmFfdElJSV9zZCRgVGllciBJSUlgCgojIFRyYW5zcG9zZSBhbGwgYnV0IGZpcnN0IGNvbHVtbiAoVGllciBJSSkKd3NfZG5hX3RJSUlfbWVhbjwtYXMuZGF0YS5mcmFtZSh0KHdzX2RuYV90SUlJX21lYW5bLC0xXSkpCmNvbG5hbWVzKHdzX2RuYV90SUlJX21lYW4pPC13c19kbmFfdElJSV9tZWFuX1RpZXJJSUkKd3NfZG5hX3RJSUlfc2Q8LWFzLmRhdGEuZnJhbWUodCh3c19kbmFfdElJSV9zZFssLTFdKSkKY29sbmFtZXMod3NfZG5hX3RJSUlfc2QpPC13c19kbmFfdElJSV9zZF9UaWVySUlJCgojIENvbWJpbmUgbWVhbiBhbmQgc2QgaW50byBzaW5nbGUgY29sdW1uIHdpdGggwrEgZGl2aWRlcgp3c19kbmFfdElJSV90YWJsZTwtYXMuZGF0YS5mcmFtZShkby5jYWxsKGNiaW5kLCBsYXBwbHkoMTpuY29sKHdzX2RuYV90SUlJX21lYW4pLCBmdW5jdGlvbihpKSBwYXN0ZTAod3NfZG5hX3RJSUlfbWVhblsgLCBpXSwgIiDCsSAiLCB3c19kbmFfdElJSV9zZFsgLCBpXSkpKSkKCiMgVHJhbnNwb3NlIHRoZSB0YWJsZSBiYWNrCndzX2RuYV90SUlJX3RhYmxlPC10KHdzX2RuYV90SUlJX3RhYmxlKQoKIyBSZW5hbWUgY29sdW1ucyB0byBTaXRlcwpjb2xuYW1lcyh3c19kbmFfdElJSV90YWJsZSk8LWMoIldldCBTZWRnZSAoVDApIiwgIldldCBTZWRnZSAoVDQpIiwgIldldCBTZWRnZSAoVDI0KSIpCgpyb3duYW1lcyh3c19kbmFfdElJSV90YWJsZSk8LXdzX2RuYV90SUlJX21lYW5fVGllcklJSQoKI3dzX2RuYV90SUlJX3RhYmxlCmBgYAoKUnVuIHN0YXRpc3RpY2FsIHRlc3RzIHRvIGRldGVybWluZSBpZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBleGlzdCBiZXR3ZWVuIHNhbXBsaW5nIHRpbWVwb2ludHMgZm9yIGVhY2ggVGllciBLRUdHIGNhdGVnb3J5LiBDbGljayBvbiB0aGUgKipTaG93L0hpZGUqKiBidXR0b24gdG8gc2VlIHRoZSBzdGF0aXN0aWNzLgoKPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLXRvZ2dsZT0iY29sbGFwc2UiIGRhdGEtdGFyZ2V0PSIjQmxvY2tOYW1lNjAiPiBTaG93L0hpZGUgPC9idXR0b24+ICAKPGRpdiBpZD0iQmxvY2tOYW1lNjAiIGNsYXNzPSJjb2xsYXBzZSI+CmBgYHtyfQojIFN1YnNldCB0aGUgInN1bSIgdmFsdWVzIGZvciBlYWNoIHNhbXBsZQp3c19kbmFfdElJSV9zdGF0czwtc3Vic2V0KHdzX2RuYV90SUlJX3N1bSwgc2VsZWN0PWMoVGllcl9JSUksUzEwNzEwNCxTMTA3MTA1LFMxMDcxMDYsUzEwNzExMCxTMTA3MTExLFMxMDcxMTIsUzEwNzExMyxTMTA3MTE0LFMxMDcxMTUpKQoKcm93bmFtZXMod3NfZG5hX3RJSUlfc3RhdHMpIDwtIHdzX2RuYV90SUlJX3N0YXRzJFRpZXJfSUlJCndzX2RuYV90SUlJX3N0YXRzPC1hcy5kYXRhLmZyYW1lKHQod3NfZG5hX3RJSUlfc3RhdHNbLTFdKSkKCiMgQWRkIHRoZSB0aW1lcG9pbnQgY29sdW1uIHRvIHRoZSBzdW0gdGFibGUKd3NfZG5hX3RJSUlfc3RhdHM8LWRhdGEuZnJhbWUoVGltZXBvaW50Mix3c19kbmFfdElJSV9zdGF0cykKCiMgU3Vic2V0IHJlc3BvbnNlIHZhcmlhYmxlcyBmb3IgTUFOT1ZBCndzX2RuYV90SUlJX3N0YXRzJHJlc3BvbnNlIDwtIGFzLm1hdHJpeCh3c19kbmFfdElJSV9zdGF0c1ssIDI6MjZdKQoKIyBNQU5PVkEgdGVzdAp3c19kbmFfdElJSV9tYW5vdmEgPC0gbWFub3ZhKHJlc3BvbnNlIH4gVGltZXBvaW50MiwgZGF0YT13c19kbmFfdElJSV9zdGF0cykKc3VtbWFyeS5hb3Yod3NfZG5hX3RJSUlfbWFub3ZhKQpgYGAKPC9kaXY+CgojIyMjIyA3LjMuMi4zLiBUaWVyIElWIEV4cHJlc3Npb24KCkNhbGN1bGF0ZSBHUE0tbm9ybWFsaXplZCBnZW5lIGNvdW50IHN1bXMgZm9yIGVhY2ggV1Mgc2FtcGxlIGluIGVhY2ggVGllciBJViBjYXRlZ29yeS4KYGBge3J9CiMgQ2FsY3VsYXRlIEdQTS1ub3JtYWxpemVkIGdlbmUgY291bnQgc3VtcyBmb3IgZWFjaCBXUyBzYW1wbGUgaW4gZWFjaCBUaWVyIElWIGNhdGVnb3J5CndzX2RuYV90SVZfc3VtPC1ncG1fYWxsX3BvdF9hbm4gJT4lIGdyb3VwX2J5KFRpZXJfSVYpICU+JSBzdW1tYXJpc2VfYXQodmFycygiUzEwNzEwNCIsIlMxMDcxMDUiLCJTMTA3MTA2IiwiUzEwNzExMCIsIlMxMDcxMTEiLCJTMTA3MTEyIiwiUzEwNzExMyIsIlMxMDcxMTQiLCJTMTA3MTE1IiksIHN1bSkKd3NfZG5hX3RJVl9zdW08LXdzX2RuYV90SVZfc3VtICU+JSBtdXRhdGVfYXQodmFycyhTMTA3MTA0LFMxMDcxMDUsUzEwNzEwNixTMTA3MTEwLFMxMDcxMTEsUzEwNzExMixTMTA3MTEzLFMxMDcxMTQsUzEwNzExNSksIGZ1bnMocm91bmQoLiwgMCkpKQp3c19kbmFfdElWX3N1bTwtYXMuZGF0YS5mcmFtZSh3c19kbmFfdElWX3N1bSkKd3NfZG5hX3RJVl9zdW08LXdzX2RuYV90SVZfc3VtW29yZGVyKC13c19kbmFfdElWX3N1bSRTMTA3MTA0KSxdCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIG1lYW4gdmFsdWVzIGZyb20gdGhlIHJlcGxpY2F0ZSBzdW1zCndzX2RuYV90SVZfc3VtJG1lYW5XU19UMDwtYXBwbHkod3NfZG5hX3RJVl9zdW1bLDI6NF0sIDEsIG1lYW4pCndzX2RuYV90SVZfc3VtJG1lYW5XU19UNDwtYXBwbHkod3NfZG5hX3RJVl9zdW1bLDU6N10sIDEsIG1lYW4pCndzX2RuYV90SVZfc3VtJG1lYW5XU19UMjQ8LWFwcGx5KHdzX2RuYV90SVZfc3VtWyw4OjEwXSwgMSwgbWVhbikKd3NfZG5hX3RJVl9zdW08LXdzX2RuYV90SVZfc3VtICU+JSBtdXRhdGVfYXQodmFycyhtZWFuV1NfVDAsbWVhbldTX1Q0LG1lYW5XU19UMjQpLCBmdW5zKHJvdW5kKC4sIDApKSkKCiMgQ2FsY3VsYXRlIHNkIHZhbHVlcyBmcm9tIHRoZSByZXBsaWNhdGUgc3Vtcwp3c19kbmFfdElWX3N1bSRzZFdTX1QwPC1hcHBseSh3c19kbmFfdElWX3N1bVssMjo0XSwgMSwgc2QpCndzX2RuYV90SVZfc3VtJHNkV1NfVDQ8LWFwcGx5KHdzX2RuYV90SVZfc3VtWyw1OjddLCAxLCBzZCkKd3NfZG5hX3RJVl9zdW0kc2RXU19UMjQ8LWFwcGx5KHdzX2RuYV90SVZfc3VtWyw4OjEwXSwgMSwgc2QpCndzX2RuYV90SVZfc3VtPC13c19kbmFfdElWX3N1bSAlPiUgbXV0YXRlX2F0KHZhcnMoc2RXU19UMCxzZFdTX1Q0LHNkV1NfVDI0KSwgZnVucyhyb3VuZCguLCAwKSkpCgojIFdyaXRlIGRhdGEgdG8gLmNzdiBmaWxlCndyaXRlLmNzdih3c19kbmFfdElWX3N1bSwgJ05vcm0uUmVzdWx0cy93cy5kbmEudElWLm1lYW4uc2QuY3N2JykKCiMgU3Vic2V0IE1lYW4gdmFsdWVzCndzX2RuYV90SVZfbWVhbjwtc3Vic2V0KHdzX2RuYV90SVZfc3VtLCBzZWxlY3Q9YyhUaWVyX0lWLG1lYW5XU19UMCxtZWFuV1NfVDQsbWVhbldTX1QyNCkpCm5hbWVzKHdzX2RuYV90SVZfbWVhbik8LWMoIlRpZXIgSVYiLCAiV1MgLSBUMCIsICJXUyAtIFQ0IiwgIldTIC0gVDI0IikKCiMgU3Vic2V0IFNEIHZhbHVlcwp3c19kbmFfdElWX3NkPC1zdWJzZXQod3NfZG5hX3RJVl9zdW0sIHNlbGVjdD1jKFRpZXJfSVYsc2RXU19UMCxzZFdTX1Q0LHNkV1NfVDI0KSkKbmFtZXMod3NfZG5hX3RJVl9zZCk8LWMoIlRpZXIgSVYiLCAiV1MgLSBUMCIsICJXUyAtIFQ0IiwgIldTIC0gVDI0IikKCiMgUmVtZW1iZXIgIlRpZXIgSVYiIGFzIG5vbi1udW1lcmljIHZhbHVlcwp3c19kbmFfdElWX21lYW5fVGllcklWPC13c19kbmFfdElWX21lYW4kYFRpZXIgSVZgCndzX2RuYV90SVZfc2RfVGllcklWPC13c19kbmFfdElWX3NkJGBUaWVyIElWYAoKIyBUcmFuc3Bvc2UgYWxsIGJ1dCBmaXJzdCBjb2x1bW4gKFRpZXIgSVYpCndzX2RuYV90SVZfbWVhbjwtYXMuZGF0YS5mcmFtZSh0KHdzX2RuYV90SVZfbWVhblssLTFdKSkKY29sbmFtZXMod3NfZG5hX3RJVl9tZWFuKTwtd3NfZG5hX3RJVl9tZWFuX1RpZXJJVgp3c19kbmFfdElWX3NkPC1hcy5kYXRhLmZyYW1lKHQod3NfZG5hX3RJVl9zZFssLTFdKSkKY29sbmFtZXMod3NfZG5hX3RJVl9zZCk8LXdzX2RuYV90SVZfc2RfVGllcklWCgojIENvbWJpbmUgbWVhbiBhbmQgc2QgaW50byBzaW5nbGUgY29sdW1uIHdpdGggwrEgZGl2aWRlcgp3c19kbmFfdElWX3RhYmxlPC1hcy5kYXRhLmZyYW1lKGRvLmNhbGwoY2JpbmQsIGxhcHBseSgxOm5jb2wod3NfZG5hX3RJVl9tZWFuKSwgZnVuY3Rpb24oaSkgcGFzdGUwKHdzX2RuYV90SVZfbWVhblsgLCBpXSwgIiDCsSAiLCB3c19kbmFfdElWX3NkWyAsIGldKSkpKQoKIyBUcmFuc3Bvc2UgdGhlIHRhYmxlIGJhY2sKd3NfZG5hX3RJVl90YWJsZTwtdCh3c19kbmFfdElWX3RhYmxlKQoKIyBSZW5hbWUgY29sdW1ucyB0byBTaXRlcwpjb2xuYW1lcyh3c19kbmFfdElWX3RhYmxlKTwtYygiV2V0IFNlZGdlIChUMCkiLCAiV2V0IFNlZGdlIChUNCkiLCAiV2V0IFNlZGdlIChUMjQpIikKCnJvd25hbWVzKHdzX2RuYV90SVZfdGFibGUpPC13c19kbmFfdElWX21lYW5fVGllcklWCgojd3NfZG5hX3RJVl90YWJsZQpgYGAKCiMjIyA3LjQuIFR1bmRyYSBNRyBEaWZmZXJlbmNlcwoKRXZhbHVhdGUgZGlmZmVyZW5jZXMgaW4gbWV0YWdlbm9tZSBhYnVuZGFuY2UgYmV0d2VlbiB0dXNzb2NrIGFuZCB3ZXQgc2VkZ2UgdHVuZHJhIGVjb3N5c3RlbXMuCgojIyMjIDcuNC4xIFR1bmRyYSBNRyBCYXJwbG90cwoKUGxvdCB0aGUgY29tYmluZWQgVHVzcy1NRyBhbmQgV1MtTUcgS0VHRyB0aWVyIElJIGNhdGVnb3JpZXMgYXMgYSBiYXJjaGFydC4KYGBge3IsIGVjaG89RkFMU0V9CnR1c3Nfd3NfZG5hX3RJSV9iYXJkYXRhPC1yZWFkLmNzdigiUGxvdC5EYXRhL3R1c3Mud3MuZG5hLnRJSS5iYXJwbG90LmNzdiIpCmBgYAoKYGBge3J9CiMgUGxhY2UgdGhlIEtFR0cgdGllciBJSSBjYXRlZ29yaWVzIGluIHRoZSBwcmVmZXJyZWQgb3JkZXIgZm9yIHBsb3R0aW5nCnR1c3Nfd3NfZG5hX3RJSV9iYXJkYXRhJFRpZXIuSUkgPC0gZmFjdG9yKHR1c3Nfd3NfZG5hX3RJSV9iYXJkYXRhJFRpZXIuSUksbGV2ZWxzID0gYygiTWV0YWJvbGlzbSIsICJHZW5ldGljIEluZm9ybWF0aW9uIFByb2Nlc3NpbmciLCAiRW52aXJvbm1lbnRhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nIiwgIkNlbGx1bGFyIFByb2Nlc3NlcyIpKQoKdHVzc193c19kbmFfdElJX2JhcmRhdGEkU2FtcGxlIDwtIGZhY3Rvcih0dXNzX3dzX2RuYV90SUlfYmFyZGF0YSRTYW1wbGUsbGV2ZWxzPWMoIlR1c3MtTUciLCJXUy1NRyIpKQoKdHVzc193c19kbmFfdElJX2JhcnBsb3Q8LWdncGxvdCh0dXNzX3dzX2RuYV90SUlfYmFyZGF0YSwgYWVzKHggPSBUaWVyLklJLCB5ID0gTWVhbiwgZmlsbCA9IFNhbXBsZSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3I9ImJsYWNrIikgKyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gTWVhbiAtIFNELCB5bWF4ID0gTWVhbiArIFNEKSwgd2lkdGggPSAwLjIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKyB5bGFiKGV4cHJlc3Npb24oYXRvcCgiS0VHRyBUaWVyIElJIENhdGVnb3JpZXMiLCBwYXN0ZSgiR2VuZSBDb3VudHMiKSkpKSArIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTIpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpICsgc2NhbGVfc2l6ZShndWlkZT1GQUxTRSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiZ3JheTgzIiwiYmxhY2siKSkgKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKFRpZXIuSUkpIHN0cl93cmFwKFRpZXIuSUksIHdpZHRoID0gMTApKSArIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApLCBsaW1pdHMgPSBjKDAsIDgwMDAwMCkpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9MSwgeT03NTAwMDAsIHNpemU9MywgbGFiZWw9Iml0YWxpYyhwKT09MC4wMDciLCBwYXJzZT1UUlVFKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTIsIHk9MjI1MDAwLCBzaXplPTMsIGxhYmVsPSJpdGFsaWMoTi5TLikiLCBwYXJzZT1UUlVFKSArIGFubm90YXRlKGdlb209InRleHQiLCB4PTMsIHk9MjAwMDAwLCBzaXplPTMsIGxhYmVsPSJpdGFsaWMocCk9PTAuMDAxIiwgcGFyc2U9VFJVRSkgKyBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeD00LCB5PTExMDAwMCwgc2l6ZT0zLCBsYWJlbD0iaXRhbGljKHApPT0wLjAwMSIsIHBhcnNlPVRSVUUpICsgYW5ub3RhdGUoZ2VvbT0idGV4dCIsIHg9Mi41LCB5PTc4MDAwMCwgbGFiZWw9IlBhaXJlZCB0LXRlc3QiKQpgYGAKCmBgYHtyfQp0dXNzX3dzX2RuYV90SUlfYmFycGxvdApgYGAKCmBgYHtyIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9CiMgU2F2ZSB0aGUgTUcgQWxwaGEsIEJldGEsIGFuZCB0SUkgcGxvdHMgdG9nZXRoZXIKc2V0RVBTKCkKcG9zdHNjcmlwdCgiRmlnLlMxLk1HLkRpdi5lcHMiLCB3aWR0aD02LjAsIGhlaWdodCA9IDEyLjApCmdnYXJyYW5nZShhbHBoYS5kbmEuYm94cGxvdCwgYWxsLmRuYS5wY29hLCB0dXNzX3dzX2RuYV90SUlfYmFycGxvdCwgaGVpZ2h0cz1jKDMsMywzKSwKICAgICAgICAgIGxhYmVscyA9IGMoIkEiLCJCIiwiQyIpLAogICAgICAgICAgbmNvbCA9IDEsIG5yb3cgPSAzLCBhbGlnbj0idiIpCmRldi5vZmYoKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CnR1c3Mud3MuZG5hLnRJSS50LnRlc3Q8LXJlYWQuY3N2KCJTdGF0cy5EYXRhL3R1c3Mud3MuZG5hLnRJSS50LnRlc3QuY3N2IikKYGBgCgpSdW4gcGFpcmVkIHQtdGVzdHMgdG8gZGV0ZXJtaW5lIHNpZ25pZmljYW5jZS4KYGBge3J9CiMgTWV0YWJvbGlzbQp0LnRlc3QodHVzcy53cy5kbmEudElJLnQudGVzdCRUdXNzLk1ldGEsdHVzcy53cy5kbmEudElJLnQudGVzdCRXUy5NZXRhLHBhaXJlZD1UUlVFKQoKIyBHZW5ldGljIEluZm9ybWF0aW9uIFByb2Nlc3NpbmcKdC50ZXN0KHR1c3Mud3MuZG5hLnRJSS50LnRlc3QkVHVzcy5HZW5lLHR1c3Mud3MuZG5hLnRJSS50LnRlc3QkV1MuR2VuZSxwYWlyZWQ9VFJVRSkKCiMgRW52aXJvbm1lbnRhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nCnQudGVzdCh0dXNzLndzLmRuYS50SUkudC50ZXN0JFR1c3MuRW52LHR1c3Mud3MuZG5hLnRJSS50LnRlc3QkV1MuRW52LHBhaXJlZD1UUlVFKQoKIyBDZWxsdWxhciBQcm9jZXNzZXMKdC50ZXN0KHR1c3Mud3MuZG5hLnRJSS50LnRlc3QkVHVzcy5DZWxsLHR1c3Mud3MuZG5hLnRJSS50LnRlc3QkV1MuQ2VsbCxwYWlyZWQ9VFJVRSkKYGBgCgpQbG90IHRoZSBjb21iaW5lZCBUdXNzLU1HIGFuZCBXUy1NRyBLRUdHIHRpZXIgSUlJIGNhdGVnb3JpZXMgYXMgYSBzaW5nbGUgYmFyY2hhcnQuCmBgYHtyLCBlY2hvPUZBTFNFfQp0dXNzX3dzX2RuYV90SUlJX2FsbF9iYXJkYXRhPC1yZWFkLmNzdigiUGxvdC5EYXRhL3R1c3Mud3MuZG5hLnRJSUkuYWxsLmJhcnBsb3QuY3N2IikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KdHVzc193c19kbmFfdElJSV9hbGxfYmFyZGF0YSRTYW1wbGUgPC0gZmFjdG9yKHR1c3Nfd3NfZG5hX3RJSUlfYWxsX2JhcmRhdGEkU2FtcGxlLCBsZXZlbHM9YygiV1MtTUciLCAiVHVzcy1NRyIpKQoKdHVzc193c19kbmFfdElJSV9hbGxfYmFyZGF0YSRUaWVyLklJSSA8LSBmYWN0b3IodHVzc193c19kbmFfdElJSV9hbGxfYmFyZGF0YSRUaWVyLklJSSwgbGV2ZWxzPWMoIlRyYW5zcG9ydCBhbmQgY2F0YWJvbGlzbSAiLCJDZWxsIG1vdGlsaXR5ICIsIkNlbGwgZ3Jvd3RoIGFuZCBkZWF0aCAiLCJDZWxsdWxhciBjb21tdW5pdHkgLSBwcm9rYXJ5b3RlcyAiLCJTaWduYWxpbmcgbW9sZWN1bGVzIGFuZCBpbnRlcmFjdGlvbiAiLCJTaWduYWwgdHJhbnNkdWN0aW9uICIsIk1lbWJyYW5lIHRyYW5zcG9ydCAiLCJUcmFuc2xhdGlvbiAiLCJUcmFuc2NyaXB0aW9uICIsIlJlcGxpY2F0aW9uIGFuZCByZXBhaXIgIiwiRm9sZGluZywgc29ydGluZyBhbmQgZGVncmFkYXRpb24gIiwiWGVub2Jpb3RpY3MgYmlvZGVncmFkYXRpb24gYW5kIG1ldGFib2xpc20gIiwiQmlvc3ludGhlc2lzIG9mIG90aGVyIHNlY29uZGFyeSBtZXRhYm9saXRlcyAiLCJOdWNsZW90aWRlIG1ldGFib2xpc20gIiwiTWV0YWJvbGlzbSBvZiB0ZXJwZW5vaWRzIGFuZCBwb2x5a2V0aWRlcyAiLCJNZXRhYm9saXNtIG9mIGNvZmFjdG9ycyBhbmQgdml0YW1pbnMgIiwiTGlwaWQgbWV0YWJvbGlzbSAiLCJHbHljYW4gYmlvc3ludGhlc2lzIGFuZCBtZXRhYm9saXNtICIsIkVuZXJneSBtZXRhYm9saXNtICIsIkNhcmJvaHlkcmF0ZSBtZXRhYm9saXNtICIsIk1ldGFib2xpc20gb2Ygb3RoZXIgYW1pbm8gYWNpZHMgIiwiQW1pbm8gYWNpZCBtZXRhYm9saXNtICIpKQoKdHVzc193c19kbmFfdElJSV9hbGxfYmFycGxvdDwtZ2dwbG90KHR1c3Nfd3NfZG5hX3RJSUlfYWxsX2JhcmRhdGEsIGFlcyh4ID0gVGllci5JSUksIHkgPSBNZWFuLCBmaWxsID0gU2FtcGxlKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCBjb2xvcj0iYmxhY2siKSArIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBNZWFuIC0gU0QsIHltYXggPSBNZWFuICsgU0QpLCB3aWR0aCA9IDAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArIGNvb3JkX2ZsaXAoKSArIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApLCBsaW1pdHMgPSBjKDAsIDEyNTAwMCksIHBvc2l0aW9uPSJib3R0b20iKSAgKyB5bGFiKCJHZW5lIENvdW50cyIpICsgdGhlbWVfY2xhc3NpYygpICsgdGhlbWUoYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMTAsIDIwLCAxMCwgMTApLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OCkpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwiZ3JheTgzIiksIGd1aWRlPWd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKQoKIyMjIFNhdmluZyBhcyAuZXBzIGZpbGUgd2l0aCBSIFZpZXdlcgojIFJlLXNpemUgdGhlIHZpZXdlciB0byB0aGUgZm9sbG93aW5nIGRpbWVuc2lvbnMgYmVmb3JlIHNhdmluZyBhcyAuZXBzIGZpbGUKIyBJbiBDb25zb2xlLCB0eXBlICJ0dXNzX3dzX2RuYV90SUlJX3BoZWF0bWFwIgojIEluIFBsb3QgVmlld2VyLCBjbGljayAiRXhwb3J0IiAtLT4gIlNhdmUgYXMgSW1hZ2UiCiMgV2lkdGg6IDUwMCAgSGVpZ2h0OiA3MDAKIyBDbGljayAiVXBkYXRlIFByZXZpZXciIC0tPiBzYXZlIGFzICJFUFMiIGZpbGUgdHlwZSAtLT4gcmVuYW1lIGFzIEZpZy4yLkJhcgpgYGAKCmBgYHtyfQp0dXNzX3dzX2RuYV90SUlJX2FsbF9iYXJwbG90CmBgYAoKYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0KdHVzcy53cy5kbmEudElJSS50LnRlc3Q8LXJlYWQuY3N2KCJTdGF0cy5EYXRhL3R1c3Mud3MuZG5hLnRJSUkudC50ZXN0LmNzdiIpCmBgYAoKUnVuIHN0YXRpc3RpY2FsIHRlc3RzIHRvIGRldGVybWluZSBpZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBleGlzdCBiZXR3ZWVuIHR1bmRyYSBjb21tdW5pdGllcyBmb3IgZWFjaCBLRUdHIFRpZXIgSUlJIGNhdGVnb3J5LiBDbGljayBvbiB0aGUgKipTaG93L0hpZGUqKiBidXR0b24gdG8gc2VlIHRoZSBzdGF0aXN0aWNzLgoKPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLXRvZ2dsZT0iY29sbGFwc2UiIGRhdGEtdGFyZ2V0PSIjQmxvY2tOYW1lNjkiPiBTaG93L0hpZGUgPC9idXR0b24+ICAKPGRpdiBpZD0iQmxvY2tOYW1lNjkiIGNsYXNzPSJjb2xsYXBzZSI+CgpSdW4gcGFpcmVkIHQtdGVzdHMgdG8gZGV0ZXJtaW5lIHNpZ25pZmljYW5jZS4KYGBge3J9CiMgQW1pbm8gYWNpZCBtZXRhYm9saXNtCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLkFBLHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFdTLkFBLHBhaXJlZD1UUlVFKQoKIyBPdGhlciBhbWlubyBhY2lkIG1ldGFib2xpc20KdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuT0FBLHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFdTLk9BQSxwYWlyZWQ9VFJVRSkKCiMgQ2FyYm9oeWRyYXRlIG1ldGFib2xpc20KdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuQ2FyYix0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5DYXJiLHBhaXJlZD1UUlVFKQoKIyBFbmVyZ3kgbWV0YWJvbGlzbQp0LnRlc3QodHVzcy53cy5kbmEudElJSS50LnRlc3QkVHVzcy5FbmVyLHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFdTLkVuZXIscGFpcmVkPVRSVUUpCgojIEdseWNhbiBtZXRhYm9saXNtCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLkdseSx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5HbHkscGFpcmVkPVRSVUUpCgojIExpcGlkIG1ldGFib2xpc20KdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuTGlwLHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFdTLkxpcCxwYWlyZWQ9VFJVRSkKCiMgQ29mYWN0b3IgbWV0YWJvbGlzbQp0LnRlc3QodHVzcy53cy5kbmEudElJSS50LnRlc3QkVHVzcy5Db2ZhYyx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5Db2ZhYyxwYWlyZWQ9VFJVRSkKCiMgVGVycGVub2lkcyBtZXRhYm9saXNtCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLlRlcnAsdHVzcy53cy5kbmEudElJSS50LnRlc3QkV1MuVGVycCxwYWlyZWQ9VFJVRSkKCiMgTnVjbGVvdGlkZSBtZXRhYm9saXNtCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLk51Y2xlbyx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5OdWNsZW8scGFpcmVkPVRSVUUpCgojIFNlY29uZGFyeSBtZXRhYm9saXRlcyBtZXRhYm9saXNtCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLlNlY01ldCx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5TZWNNZXQscGFpcmVkPVRSVUUpCgojIFhlbm9iaW90aWNzIG1ldGFib2xpc20KdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuWGVubyx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5YZW5vLHBhaXJlZD1UUlVFKQoKIyBGb2xkaW5nLCBzb3J0aW5nLCBhbmQgZGVncmFkYXRpb24KdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuRm9sZCx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5Gb2xkLHBhaXJlZD1UUlVFKQoKIyBSZXBsaWNhdGlvbgp0LnRlc3QodHVzcy53cy5kbmEudElJSS50LnRlc3QkVHVzcy5SZXBsaWMsdHVzcy53cy5kbmEudElJSS50LnRlc3QkV1MuUmVwbGljLHBhaXJlZD1UUlVFKQoKIyBUcmFuc2NyaXB0aW9uCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLlRyYW5zYyx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5UcmFuc2MscGFpcmVkPVRSVUUpCgojIFRyYW5zbGF0aW9uCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLlRyYW5zbCx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5UcmFuc2wscGFpcmVkPVRSVUUpCgojIE1lbWJyYW5lIFRyYW5zcG9ydAp0LnRlc3QodHVzcy53cy5kbmEudElJSS50LnRlc3QkVHVzcy5NZW1iVHJhbnMsdHVzcy53cy5kbmEudElJSS50LnRlc3QkV1MuTWVtYlRyYW5zLHBhaXJlZD1UUlVFKQoKIyBTaWduYWwgVHJhbnNkdWN0aW9uCnQudGVzdCh0dXNzLndzLmRuYS50SUlJLnQudGVzdCRUdXNzLlNpZ25UcmFucyx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5TaWduVHJhbnMscGFpcmVkPVRSVUUpCgojIFNpZ25hbGluZyBNb2xlY3VsZXMKdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuU2lnbk1vbCx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5TaWduTW9sLHBhaXJlZD1UUlVFKQoKIyBDZWxsdWxhciBDb21tdW5pdHkKdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuQ2VsbENvbW0sdHVzcy53cy5kbmEudElJSS50LnRlc3QkV1MuQ2VsbENvbW0scGFpcmVkPVRSVUUpCgojIENlbGx1bGFyIEdyb3d0aAp0LnRlc3QodHVzcy53cy5kbmEudElJSS50LnRlc3QkVHVzcy5DZWxsR3Jvdyx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5DZWxsR3JvdyxwYWlyZWQ9VFJVRSkKCiMgQ2VsbHVsYXIgTW90aWxpdHkKdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuQ2VsbE1vdCx0dXNzLndzLmRuYS50SUlJLnQudGVzdCRXUy5DZWxsTW90LHBhaXJlZD1UUlVFKQoKIyBUcmFuc3BvcnQgYW5kIENhdGFib2xpc20KdC50ZXN0KHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFR1c3MuVHJhbnNwLHR1c3Mud3MuZG5hLnRJSUkudC50ZXN0JFdTLlRyYW5zcCxwYWlyZWQ9VFJVRSkKYGBgCjwvZGl2PgoKIyMjIyA3LjQuMiBUdW5kcmEgTUcgSGVhdG1hcAoKSGVhdG1hcCBmb3IgTUcgVGllciBJSUkgY2F0ZWdvcmllcyBieSBzYW1wbGluZyB0aW1lcG9pbnRzCmBgYHtyIGVjaG89RkFMU0V9CnR1c3Nfd3NfZG5hX3RJSUlfaGVhdG1hcDwtcmVhZC5jc3YoIlBsb3QuRGF0YS90dXNzLndzLmRuYS50SUlJLmhlYXRtYXAuY3N2IikKYGBgCgpgYGB7cn0KIyBDcmVhdGUgYSB2ZWN0b3Igd2l0aCBjYXRlZ29yaWVzIGluIHRoZSBkZXNpcmVkIG9yZGVyCnR1c3Nfd3NfZG5hX3RJSUlfeCA8LSBjKCJBbWlubyBhY2lkIG1ldGFib2xpc20gIiwKICAgICAgICAgICAgICAgICAgICAgICAgIk1ldGFib2xpc20gb2Ygb3RoZXIgYW1pbm8gYWNpZHMgIiwKICAgICAgICAgICAgICAgICAgICAgICAgIkNhcmJvaHlkcmF0ZSBtZXRhYm9saXNtICIsCiAgICAgICAgICAgICAgICAgICAgICAgICJFbmVyZ3kgbWV0YWJvbGlzbSAiLAogICAgICAgICAgICAgICAgICAgICAgICAiR2x5Y2FuIGJpb3N5bnRoZXNpcyBhbmQgbWV0YWJvbGlzbSAiLAogICAgICAgICAgICAgICAgICAgICAgICAiTGlwaWQgbWV0YWJvbGlzbSAiLAogICAgICAgICAgICAgICAgICAgICAgICAiTWV0YWJvbGlzbSBvZiBjb2ZhY3RvcnMgYW5kIHZpdGFtaW5zICIsCiAgICAgICAgICAgICAgICAgICAgICAgICJNZXRhYm9saXNtIG9mIHRlcnBlbm9pZHMgYW5kIHBvbHlrZXRpZGVzICIsCiAgICAgICAgICAgICAgICAgICAgICAgICJOdWNsZW90aWRlIG1ldGFib2xpc20gIiwKICAgICAgICAgICAgICAgICAgICAgICAgIkJpb3N5bnRoZXNpcyBvZiBvdGhlciBzZWNvbmRhcnkgbWV0YWJvbGl0ZXMgIiwKICAgICAgICAgICAgICAgICAgICAgICAgIlhlbm9iaW90aWNzIGJpb2RlZ3JhZGF0aW9uIGFuZCBtZXRhYm9saXNtICIsCiAgICAgICAgICAgICAgICAgICAgICAgICJGb2xkaW5nLCBzb3J0aW5nIGFuZCBkZWdyYWRhdGlvbiAiLAogICAgICAgICAgICAgICAgICAgICAgICAiUmVwbGljYXRpb24gYW5kIHJlcGFpciAiLAogICAgICAgICAgICAgICAgICAgICAgICAiVHJhbnNjcmlwdGlvbiAiLAogICAgICAgICAgICAgICAgICAgICAgICAiVHJhbnNsYXRpb24gIiwKICAgICAgICAgICAgICAgICAgICAgICAgIk1lbWJyYW5lIHRyYW5zcG9ydCAiLAogICAgICAgICAgICAgICAgICAgICAgICAiU2lnbmFsIHRyYW5zZHVjdGlvbiAiLAogICAgICAgICAgICAgICAgICAgICAgICAiU2lnbmFsaW5nIG1vbGVjdWxlcyBhbmQgaW50ZXJhY3Rpb24gIiwKICAgICAgICAgICAgICAgICAgICAgICAgIkNlbGx1bGFyIGNvbW11bml0eSAtIHByb2thcnlvdGVzICIsCiAgICAgICAgICAgICAgICAgICAgICAgICJDZWxsIGdyb3d0aCBhbmQgZGVhdGggIiwKICAgICAgICAgICAgICAgICAgICAgICAgIkNlbGwgbW90aWxpdHkgIiwKICAgICAgICAgICAgICAgICAgICAgICAgIlRyYW5zcG9ydCBhbmQgY2F0YWJvbGlzbSAiKQoKIyBSZS1zb3J0IHRoZSBkYXRhIGluIHRoZSBkZXNpcmVkIG9yZGVyCnR1c3Nfd3NfZG5hX3RJSUlfaGVhdG1hcDwtdHVzc193c19kbmFfdElJSV9oZWF0bWFwICU+JQogIHNsaWNlKG1hdGNoKHR1c3Nfd3NfZG5hX3RJSUlfeCwgVGllcl9JSUkpKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFRpZXIgY2F0ZWdvcmllcykgaW50byByb3duYW1lcwpyb3duYW1lcyh0dXNzX3dzX2RuYV90SUlJX2hlYXRtYXApIDwtIHR1c3Nfd3NfZG5hX3RJSUlfaGVhdG1hcCRUaWVyX0lJSQp0dXNzX3dzX2RuYV90SUlJX2hlYXRtYXA8LWFzLmRhdGEuZnJhbWUodHVzc193c19kbmFfdElJSV9oZWF0bWFwWy0xXSkKCiMgUmVuYW1lIGNvbHVtbnMgdG8gc2FtcGxlIElEcyAoVGhpcyBpbmNsdWRlcyBUMjQgcmVwbGljYXRlcykKY29sbmFtZXModHVzc193c19kbmFfdElJSV9oZWF0bWFwKTwtYygiVHVzcy1NRy1UMCIsIlR1c3MtTUctVDQiLCJUdXNzLU1HLVQyNCIsIldTLU1HLVQwIiwiV1MtTUctVDQiLCJXUy1NRy1UMjQiKQoKIyBDb252ZXJ0IGRhdGFmcmFtZSBpbnRvIGEgbWF0cml4IGZvciBoZWF0bWFwCnR1c3Nfd3NfZG5hX3RJSUlfaGVhdG1hcC1hcy5tYXRyaXgodHVzc193c19kbmFfdElJSV9oZWF0bWFwKQoKIyBTY2FsZSBtYXRyaXggdmFsdWVzIHRvIGdlbmVyYXRlIFotc2NvcmVzCnR1c3Nfd3NfZG5hX3RJSUlfaGVhdG1hcDwtc2NhbGUodCh0dXNzX3dzX2RuYV90SUlJX2hlYXRtYXApKQoKdHVzc193c19kbmFfdElJSV9oZWF0bWFwPC10KHR1c3Nfd3NfZG5hX3RJSUlfaGVhdG1hcCkKCiMgU3BlY2lmeSBSQ29sb3JCcmV3ZXIgY3VzdG9tIGNvbG9yIHBhbGV0dGUKY29sIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCgxMCwgIlJkWWxCdSIpKSgyNTYpCgojIyMgU2F2aW5nIGFzIC5lcHMgZmlsZSB3aXRoIFIgVmlld2VyCiMgUmUtc2l6ZSB0aGUgdmlld2VyIHRvIHRoZSBmb2xsb3dpbmcgZGltZW5zaW9ucyBiZWZvcmUgc2F2aW5nIGFzIC5lcHMgZmlsZQojIEluIENvbnNvbGUsIHR5cGUgInR1c3Nfd3NfZG5hX3RJSUlfcGhlYXRtYXAiCiMgSW4gUGxvdCBWaWV3ZXIsIGNsaWNrICJFeHBvcnQiIC0tPiAiU2F2ZSBhcyBJbWFnZSIKIyBXaWR0aDogNTUwICBIZWlnaHQ6IDY1MAojIENsaWNrICJVcGRhdGUgUHJldmlldyIgLS0+IHNhdmUgYXMgIkVQUyIgZmlsZSB0eXBlIC0tPiByZW5hbWUgYXMgRmlnLjIuSGVhdAoKIyBQaGVhdG1hcAp0dXNzX3dzX2RuYV90SUlJX3BoZWF0bWFwPC1waGVhdG1hcCh0dXNzX3dzX2RuYV90SUlJX2hlYXRtYXAsIHRyZWVoZWlnaHRfcm93ID0gMCwgdHJlZWhlaWdodF9jb2wgPSAwLCBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgY2x1c3Rlcl9jb2xzID0gRkFMU0UpCmBgYAoKIyMjIDcuNS4gRmUgR2VuZSBFeHByZXNzaW9uCgpQb3RlbnRpYWwgZ2VuZSBleHByZXNzaW9uIHJlbGF0ZWQgdG8gaXJvbiBhY3F1aXNpdGlvbiwgaXJvbiByZWRveCBjeWNsaW5nLCBhbmQgaXJvbiBzdG9yYWdlIGluIHRoZSBtZXRhZ2Vub21lcyB3ZXJlIGRldGVybWluZWQgdXNpbmcgRmVHZW5pZSBbKEdhcmJlciBldCBhbC4gMjAyMCldKGh0dHBzOi8vd3d3LmZyb250aWVyc2luLm9yZy9hcnRpY2xlcy8xMC4zMzg5L2ZtaWNiLjIwMjAuMDAwMzcvZnVsbCkuICBGZUdlbmllIHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSBkYXRhYmFzZSBvZiBoaWRkZW4gTWFya292IG1vZGVscyAoSE1NcykgYmFzZWQgb24gZ2VuZXMgcmVsYXRlZCB0byBpcm9uIGFjcXVpc2l0aW9uLCBzdG9yYWdlLCBhbmQgb3hpZGF0aW9uL3JlZHVjdGlvbiBpbiBCYWN0ZXJpYSBhbmQgQXJjaGFlYSwgd2hpY2ggYXJlIGdlbmVyYWxseSBub3QgYW5ub3RhdGVkIGFzIHN1Y2ggYnkgZXN0YWJsaXNoZWQgZ2VuZSBhbm5vdGF0aW9uIHBpcGVsaW5lcywgc3VjaCBhcyBHaG9zdEtPQUxBLCB3aGljaCB3YXMgdXNlZCB0byBhbm5vdGF0ZSB0aGUgbWV0YWdlbm9tZXMgKGFuZCBtZXRhdHJhbnNjcmlwdG9tZXMpIHByZXNlbnRlZCBpbiB0aGlzIHN0dWR5LgoKSGVyZSwgdGhlIHF1YWxpdHktY29udHJvbGxlZCBzZXF1ZW5jaW5nIHJlYWRzIGZvciBlYWNoIG1ldGFnZW5vbWUgc2FtcGxlIHdlcmUgYXNzZW1ibGVkIGJ5IHR1bmRyYSBlY29zeXN0ZW0gdXNpbmcgTUVHQUhJVCB0byBnZW5lcmF0ZSBhIHR1bmRyYS1zcGVjaWZpYyBjb250aWdzIGZpbGUuICBUaGUgbWV0YWdlbm9tZSBjb250aWdzIGZpbGVzIHdlcmUgdXNlZCBhcyBpbnB1dCBmb3IgRmVHZW5pZSwgd2hpY2ggZmlyc3QgcHJlZGljdGVkIG9wZW4tcmVhZGluZyBmcmFtZXMgKE9SRnMpIHVzaW5nIFByb2RpZ2FsIGFuZCB0aGVuIHF1ZXJpZWQgdGhlbSBhZ2FpbnN0IGEgY3VzdG9tIGxpYnJhcnkgb2YgSE1NcyB1c2luZyBobW1zZWFyY2gsIHdpdGggY3VzdG9tIGJpdCBzY29yZSBjdXRvZmZzIGZvciBlYWNoIEhNTS4gIFJlc3VsdHMgZnJvbSBGZUdlbmllIGluY2x1ZGVkIGFsbCBpZGVudGlmaWVkIHB1dGF0aXZlIGlyb24tcmVsYXRlZCBnZW5lcywgdGhlaXIgZnVuY3Rpb25hbCBjYXRlZ29yeSwgYml0IHNjb3JlLCBudW1iZXIgb2YgY2Fub25pY2FsIGhlbWUtYmluZGluZyBtb3RpZnMsIGFtaW5vIGFjaWQgc2VxdWVuY2UsIGFuZCBjbG9zZXN0IGhvbW9sb2cuICBDb3VudHMgd2l0aGluIGVhY2ggaXJvbiBnZW5lIGNhdGVnb3J5IHdlcmUgc3VtbWFyaXplZCBhcyB0aGVpciByZWxhdGl2ZSBhYnVuZGFuY2UgYWdhaW5zdCBhbGwgaWRlbnRpZmllZCBpcm9uIGdlbmVzLgoKQXNzZW1ibGUgIFFDJ2QgbWV0YWdlbm9tZSBzYW1wbGVzIGJ5IHR1bmRyYSBlY29zeXN0ZW0gZm9yIHVzZSBpbiBGZUdlbmllCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9Cm1vZHVsZSBsb2FkIEJpb2luZm9ybWF0aWNzIG1lZ2FoaXQvMS4yLjgKY2F0ICpfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSA+IFR1c3NfRE5BX2RhdGFfZndkLnFjLmZhc3RxCmNhdCAqX2FkdHJpbV9jbGVhbl9xdHJpbV9yZXYuZGVyZXAuZmFzdHEgPiBUdXNzX0ROQV9kYXRhX3Jldi5xYy5mYXN0cQptZWdhaGl0IC0tay1taW4gMjEgLS1rLW1heCAxNDEgLS1rLXN0ZXAgMTIgLTEgVHVzc19ETkFfZGF0YV9md2QucWMuZmFzdHEgLTIgVHVzc19ETkFfZGF0YV9yZXYucWMuZmFzdHEgLW8gLi9tZWdhaGl0X3R1c3NfZG5hX291dApjZCAvZ3Bmcy9hY2NvdW50cy9nd2tfcm9vdC9nd2sxL2tqcm9tYW5vL0ROQV9hc3NlbWJseS9XU19ETkEKY2F0ICpfYWR0cmltX2NsZWFuX3F0cmltX2Z3ZC5kZXJlcC5mYXN0cSA+IFdTX0ROQV9kYXRhX2Z3ZC5xYy5mYXN0cQpjYXQgKl9hZHRyaW1fY2xlYW5fcXRyaW1fcmV2LmRlcmVwLmZhc3RxID4gV1NfRE5BX2RhdGFfcmV2LnFjLmZhc3RxCm1lZ2FoaXQgLS1rLW1pbiAyMSAtLWstbWF4IDE0MSAtLWstc3RlcCAxMiAtMSBXU19ETkFfZGF0YV9md2QucWMuZmFzdHEgLTIgV1NfRE5BX2RhdGFfcmV2LnFjLmZhc3RxIC1vIC4vbWVnYWhpdF93c19kbmFfb3V0CmBgYGAKCiMjIyMgNy41LjEuIEZlR2VuaWUgU3VtbWFyeQoKRmVHZW5pZSBpcyBhIHB5dGhvbiBzY3JpcHQgd2l0aCBkZXBlbmRlbmNpZXMgdGhhdCBjYW4gYmUgZG93bmxvYWRlZCBmcm9tICBbQXJrYWRpeS1HYXJiZXIgR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vQXJrYWRpeS1HYXJiZXIvRmVHZW5pZSkuCgpTdGFydCBieSBsb2FkaW5nIHByZXJlcXVpc2l0ZSBtb2R1bGVzCmBgYGBtYXJrZG93bgpgciAnJ2B7VGVybWluYWx9Cm1vZHVsZSBsb2FkIHB5dGhvbjMuNi1hbmFjb25kYSBCaW9pbmZvcm1hdGljcyBobW1lciBwcm9kaWdhbCBuY2JpLWJsYXN0IFIKYGBgYAoKUnVuIHRoZSBGZUdlbmllIHB5dGhvbiBzY3JpcHQKYGBgYG1hcmtkb3duCmByICcnYHtUZXJtaW5hbH0KdHVzc19kbmFfcnVuLnNoCgojIFRoaXMgaXMgd2hhdCdzIGluc2lkZSB0aGUgInR1c3NfZG5hX3J1bi5zaCIgc2NyaXB0CkZlR2VuaWUucHkgLWJpbl9kaXIgL2dwZnMvYWNjb3VudHMvZ3drX3Jvb3QvZ3drMS9ranJvbWFuby9ETkFfYXNzZW1ibHkvVHVzc19ETkEvbWVnYWhpdF90dXNzX2RuYV9vdXQvIC1iaW5fZXh0IGZhIC1vdXQgdHVzc19kbmFfb3V0Cgp3c19kbmFfcnVuLnNoCgojIFRoaXMgaXMgd2hhdCdzIGluc2lkZSB0aGUgIndzX2RuYV9ydW4uc2giIHNjcmlwdApGZUdlbmllLnB5IC1iaW5fZGlyIC9ETkFfYXNzZW1ibHkvV1NfRE5BL21lZ2FoaXRfd3NfZG5hX291dC8gLWJpbl9leHQgZmEgLW91dCBXU19kbmFfb3V0CmBgYGAKClN1bW1hcnkgdGFibGUgb2YgdGhlIHJlbGF0aXZlIGFidW5kYW5jZSBvZiBpcm9uIGdlbmUgY2F0ZWdvcmllcyBmcm9tIHRoZSBNRVRBR0VOT01FUyBvZiBUdXNzIGFuZCBXUyB0dW5kcmEgZWNvc3lzdGVtcy4KYGBge3IgZWNobz1GQUxTRX0KRmVHZW5pZS5ETkE8LXJlYWQuY3N2KCJUYWJsZS5EYXRhL0ZlR2VuaWUuRE5BLmNzdiIpCkZlR2VuaWUuRE5BCmBgYAoKIyBSZXByb2R1Y2liaWxpdHkKClRoZSBzZXNzaW9uIGluZm9ybWF0aW9uIGlzIHByb3ZpZGVkIGZvciBmdWxsIHJlcHJvZHVjaWJpbGl0eS4KYGBge3J9CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGA=