1 Introduction

Use ShortStack (Axtell2013-xu?; Johnson et al. 2016; Shahid2014-lx?) to perform alignment of sRNAseq data and annotation of sRNA-producing genes.


Inputs:

Outputs:

Software requirements:

  • Utilizes a ShortStack Conda/Mamba environment, per the installation instructions.

Replace with name of your ShortStack environment and the path to the corresponding conda installation (find this after you’ve activated the environment).

E.g.

# Activate environment
conda activate ShortStack-4.0.3_env

# Find conda path
which conda

2 Set R variables

shortstack_conda_env_name <- c("ShortStack-4.0.3_env")
shortstack_cond_path <- c("/home/sam/programs/mambaforge/condabin/conda")

3 Create a Bash variables file

This allows usage of Bash variables across R Markdown chunks.

{
echo "#### Assign Variables ####"
echo ""

echo "# Trimmed FastQ naming pattern"
echo "export trimmed_fastqs_pattern='*fastp-adapters-polyG-31bp-merged.fq.gz'"

echo "# Data directories"
echo 'export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive'
echo 'export deep_dive_data_dir="${deep_dive_dir}/data"'
echo 'export output_dir_top=${deep_dive_dir}/E-Peve/output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged'
echo 'export trimmed_fastqs_dir="${deep_dive_dir}/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/trimmed-reads"'
echo ""

echo "# Input/Output files"
echo 'export genome_fasta_dir=${deep_dive_dir}/E-Peve/data'
echo 'export genome_fasta_name="Porites_evermanni_v1.fa"'
echo 'export shortstack_genome_fasta_name="Porites_evermanni_v1.fa"'
echo 'export mirbase_mature_fasta_version=cnidarian-mirbase-mature-v22.1.fasta'
echo 'export genome_fasta="${genome_fasta_dir}/${shortstack_genome_fasta_name}"'
echo ""


echo "# Set number of CPUs to use"
echo 'export threads=40'
echo ""

echo "# Initialize arrays"
echo 'export trimmed_fastqs_array=()'


} > .bashvars

cat .bashvars
#### Assign Variables ####

# Trimmed FastQ naming pattern
export trimmed_fastqs_pattern='*fastp-adapters-polyG-31bp-merged.fq.gz'
# Data directories
export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive
export deep_dive_data_dir="${deep_dive_dir}/data"
export output_dir_top=${deep_dive_dir}/E-Peve/output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged
export trimmed_fastqs_dir="${deep_dive_dir}/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/trimmed-reads"

# Input/Output files
export genome_fasta_dir=${deep_dive_dir}/E-Peve/data
export genome_fasta_name="Porites_evermanni_v1.fa"
export shortstack_genome_fasta_name="Porites_evermanni_v1.fa"
export mirbase_mature_fasta_version=cnidarian-mirbase-mature-v22.1.fasta
export genome_fasta="${genome_fasta_dir}/${shortstack_genome_fasta_name}"

# Set number of CPUs to use
export threads=40

# Initialize arrays
export trimmed_fastqs_array=()

4 Load ShortStack conda environment

If this is successful, the first line of output should show that the Python being used is the one in your [ShortStack](https://github.com/MikeAxtell/ShortStack conda environment path.

E.g.

python: /home/sam/programs/mambaforge/envs/mirmachine_env/bin/python

use_condaenv(condaenv = shortstack_conda_env_name, conda = shortstack_cond_path)

# Check successful env loading
py_config()
python:         /home/sam/programs/mambaforge/envs/ShortStack-4.0.3_env/bin/python
libpython:      /home/sam/programs/mambaforge/envs/ShortStack-4.0.3_env/lib/libpython3.10.so
pythonhome:     /home/sam/programs/mambaforge/envs/ShortStack-4.0.3_env:/home/sam/programs/mambaforge/envs/ShortStack-4.0.3_env
version:        3.10.13 | packaged by conda-forge | (main, Dec 23 2023, 15:36:39) [GCC 12.3.0]
numpy:          /home/sam/programs/mambaforge/envs/ShortStack-4.0.3_env/lib/python3.10/site-packages/numpy
numpy_version:  1.26.4

NOTE: Python version was forced by use_python() function

5 Run ShortStack

5.1 Excecute ShortStack command

5.1.1 THIS KEEPS CRASHING AFTER Screening of possible de novo microRNAs

Uses the --dn_mirna option to identify miRNAs in the genome, without relying on the --known_miRNAs.

This part of the code redirects the output of time to the end of shortstack.log file.

  • ; } \ 2>> ${output_dir_top}/shortstack.log
# Load bash variables into memory
source .bashvars

# Make output directory, if it doesn't exist
mkdir --parents "${output_dir_top}"

# Create array of trimmed FastQs
trimmed_fastqs_array=(${trimmed_fastqs_dir}/${trimmed_fastqs_pattern})


# Pass array contents to new variable as space-delimited list
trimmed_fastqs_list=$(echo "${trimmed_fastqs_array[*]}")


###### Run ShortStack ######
{ time \
ShortStack \
--genomefile "${genome_fasta}" \
--readfile ${trimmed_fastqs_list} \
--known_miRNAs ${deep_dive_data_dir}/${mirbase_mature_fasta_version} \
--dn_mirna \
--threads ${threads} \
--outdir ${output_dir_top}/ShortStack_out \
&> ${output_dir_top}/shortstack.log ; } \
2>> ${output_dir_top}/shortstack.log

5.2 Check runtime

# Load bash variables into memory
source .bashvars

tail -n 3 ${output_dir_top}/shortstack.log \
| grep "real" \
| awk '{print "ShortStack runtime:" "\t" $2}'
ShortStack runtime: 32m32.272s

6 Results

6.1 ShortStack synopsis

# Load bash variables into memory
source .bashvars

tail -n 25 ${output_dir_top}/shortstack.log
Writing final files

Found a total of 46 MIRNA loci


Non-MIRNA loci by DicerCall:
N 16529
22 59
23 47
21 31
24 24

Creating visualizations of microRNA loci with strucVis
<<< WARNING >>>
Do not rely on these results alone to annotate new MIRNA loci!
The false positive rate for de novo MIRNA identification is low, but NOT ZERO
Insepct each mirna locus, especially the strucVis output, and see
https://doi.org/10.1105/tpc.17.00851 , https://doi.org/10.1093/nar/gky1141

Thu 09 May 2024 10:44:28 -0700 PDT
Run Completed!

real    32m32.272s
user    441m7.302s
sys 194m17.834s

ShortStack found 46 miRNAs.

6.2 Inspect Results.txt

# Load bash variables into memory
source .bashvars

head ${output_dir_top}/ShortStack_out/Results.txt

echo ""
echo "----------------------------------------------------------"
echo ""

echo "Nummber of potential loci:"
awk '(NR>1)' ${output_dir_top}/ShortStack_out/Results.txt | wc -l
Locus   Name    Chrom   Start   End Length  Reads   DistinctSequences   FracTop Strand  MajorRNA    MajorRNAReads   Short   Long    21  22  23  24  DicerCall   MIRNA   known_miRNAs
Porites_evermani_scaffold_1:45711-46131 Cluster_1   Porites_evermani_scaffold_1 45711   46131   421 88  38  1.0 +   CAGUAGAGGUGGCCAAGAAUCAGU    8   24  27  9   8   9   11  N   N   NA
Porites_evermani_scaffold_1:201507-201931   Cluster_2   Porites_evermani_scaffold_1 201507  201931  425 58  14  0.034482758620689655    -   UGUACUUCUGAUUAAACGAACCAGACAUCGC 12  0   50  0   0   0   8   N   N   NA
Porites_evermani_scaffold_1:313446-313846   Cluster_3   Porites_evermani_scaffold_1 313446  313846  401 50  27  0.0 -   CUGACGUUUUAAGCUCAAUAGU  13  10  15  1   17  3   4   N   N   NA
Porites_evermani_scaffold_1:406146-406734   Cluster_4   Porites_evermani_scaffold_1 406146  406734  589 175 61  0.06285714285714286 -   UGAGUGUAUUCUUGAACUGUUUUCCAAC    39  1   159 2   0   5   8   N   N   NA
Porites_evermani_scaffold_1:409839-410269   Cluster_5   Porites_evermani_scaffold_1 409839  410269  431 169 43  0.005917159763313609    -   UGGAACUCCGAUUUAGAACUUGCAAACUUU  61  0   161 1   3   0   4   N   N   NA
Porites_evermani_scaffold_1:465244-465668   Cluster_6   Porites_evermani_scaffold_1 465244  465668  425 169 49  0.0 -   AAGUUGCUCUGAAGAUUAUGU   39  34  52  48  8   20  7   N   N   NA
Porites_evermani_scaffold_1:468473-468950   Cluster_7   Porites_evermani_scaffold_1 468473  468950  478 91900   807 0.0 -   AGCACUGAUGACUGUUCAGUUUUUCUGAAUU 68534   2227    88188   115 138 153 1079    N   N   NA
Porites_evermani_scaffold_1:476827-477250   Cluster_8   Porites_evermani_scaffold_1 476827  477250  424 116 37  0.0 -   CGUGUCUUCGUAAUCGUCUCGUAC    14  33  38  0   12  15  18  N   N   NA
Porites_evermani_scaffold_1:486441-486868   Cluster_9   Porites_evermani_scaffold_1 486441  486868  428 57  11  0.07017543859649122 -   AUAUUGACGAAUCCUGGCCUAGUGAACC    26  0   53  0   0   4   0   N   N   NA

----------------------------------------------------------

Nummber of potential loci:
16736

Column 20 of the Results.txt file identifies if a cluster is a miRNA or not (Y or N).

# Load bash variables into memory
source .bashvars

echo "Number of loci characterized as miRNA:"
awk '$20=="Y" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
echo ""

echo "----------------------------------------------------------"

echo ""
echo "Number of loci _not_ characterized as miRNA:"
awk '$20=="N" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
Number of loci characterized as miRNA:
46

----------------------------------------------------------

Number of loci _not_ characterized as miRNA:
16690

Column 21 of the Results.txt file identifies if a cluster aligned to a known miRNA (miRBase) or not (Y or NA).

# Load bash variables into memory
source .bashvars

echo "Number of loci matching miRBase miRNAs:"
awk '$21!="NA" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
echo ""

echo "----------------------------------------------------------"

echo ""
echo "Number of loci _not_ matching miRBase miRNAs:"
awk '$21=="NA" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
Number of loci matching miRBase miRNAs:
37

----------------------------------------------------------

Number of loci _not_ matching miRBase miRNAs:
16700

Although there are 46 loci with matches to miRBase miRNAs, ShortStack did not annotate 9 of these clusters as miRNAs likely because they do not also match secondary structure criteria.

This explains the difference between the 46 and 37 miRNAs.

6.2.1 Directory tree of all ShortStack outputs

Many of these are large (by GitHub standards) BAM files, so will not be added to the repo.

Additionally, it’s unlikely we’ll utilize most of the other files (bigwig) generated by ShortStack.

# Load bash variables into memory
source .bashvars

tree -h ${output_dir_top}/
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/
├── [ 17K]  shortstack.log
└── [240K]  ShortStack_out
    ├── [ 16K]  alignment_details.tsv
    ├── [1.1M]  Counts.txt
    ├── [212K]  known_miRNAs.gff3
    ├── [1.8M]  known_miRNAs_unaligned.fasta
    ├── [6.2M]  merged_alignments_21_m.bw
    ├── [6.3M]  merged_alignments_21_p.bw
    ├── [5.6M]  merged_alignments_22_m.bw
    ├── [5.7M]  merged_alignments_22_p.bw
    ├── [9.5M]  merged_alignments_23-24_m.bw
    ├── [9.5M]  merged_alignments_23-24_p.bw
    ├── [644M]  merged_alignments.bam
    ├── [336K]  merged_alignments.bam.csi
    ├── [ 41M]  merged_alignments_other_m.bw
    ├── [ 42M]  merged_alignments_other_p.bw
    ├── [ 32M]  merged_alignments_POR-73-S1-TP2-fastp-adapters-polyG-31bp-merged.bw
    ├── [ 44M]  merged_alignments_POR-79-S1-TP2-fastp-adapters-polyG-31bp-merged.bw
    ├── [ 50M]  merged_alignments_POR-82-S1-TP2-fastp-adapters-polyG-31bp-merged.bw
    ├── [ 15K]  mir.fasta
    ├── [185M]  POR-73-S1-TP2-fastp-adapters-polyG-31bp-merged.bam
    ├── [301K]  POR-73-S1-TP2-fastp-adapters-polyG-31bp-merged.bam.csi
    ├── [199M]  POR-79-S1-TP2-fastp-adapters-polyG-31bp-merged.bam
    ├── [307K]  POR-79-S1-TP2-fastp-adapters-polyG-31bp-merged.bam.csi
    ├── [227M]  POR-82-S1-TP2-fastp-adapters-polyG-31bp-merged.bam
    ├── [312K]  POR-82-S1-TP2-fastp-adapters-polyG-31bp-merged.bam.csi
    ├── [1.9M]  Results.gff3
    ├── [2.9M]  Results.txt
    └── [4.0K]  strucVis
        ├── [ 12K]  Cluster_10850.ps
        ├── [8.1K]  Cluster_10850.txt
        ├── [ 12K]  Cluster_10882.ps
        ├── [ 22K]  Cluster_10882.txt
        ├── [ 12K]  Cluster_11045.ps
        ├── [ 25K]  Cluster_11045.txt
        ├── [ 12K]  Cluster_11046.ps
        ├── [ 43K]  Cluster_11046.txt
        ├── [ 12K]  Cluster_1125.ps
        ├── [ 15K]  Cluster_1125.txt
        ├── [ 12K]  Cluster_1153.ps
        ├── [ 51K]  Cluster_1153.txt
        ├── [ 12K]  Cluster_11890.ps
        ├── [ 13K]  Cluster_11890.txt
        ├── [ 11K]  Cluster_14130.ps
        ├── [2.3K]  Cluster_14130.txt
        ├── [ 11K]  Cluster_14362.ps
        ├── [4.0K]  Cluster_14362.txt
        ├── [ 12K]  Cluster_14865.ps
        ├── [4.1K]  Cluster_14865.txt
        ├── [ 12K]  Cluster_15601.ps
        ├── [8.1K]  Cluster_15601.txt
        ├── [ 12K]  Cluster_15760.ps
        ├── [ 13K]  Cluster_15760.txt
        ├── [ 12K]  Cluster_16267.ps
        ├── [3.0K]  Cluster_16267.txt
        ├── [ 11K]  Cluster_16348.ps
        ├── [ 14K]  Cluster_16348.txt
        ├── [ 12K]  Cluster_2770.ps
        ├── [ 14K]  Cluster_2770.txt
        ├── [ 11K]  Cluster_2837.ps
        ├── [4.9K]  Cluster_2837.txt
        ├── [ 11K]  Cluster_2871.ps
        ├── [ 17K]  Cluster_2871.txt
        ├── [ 11K]  Cluster_29.ps
        ├── [ 32K]  Cluster_29.txt
        ├── [ 12K]  Cluster_4063.ps
        ├── [ 66K]  Cluster_4063.txt
        ├── [ 12K]  Cluster_4064.ps
        ├── [ 56K]  Cluster_4064.txt
        ├── [ 12K]  Cluster_4097.ps
        ├── [ 55K]  Cluster_4097.txt
        ├── [ 12K]  Cluster_4617.ps
        ├── [7.5K]  Cluster_4617.txt
        ├── [ 11K]  Cluster_4722.ps
        ├── [ 12K]  Cluster_4722.txt
        ├── [ 12K]  Cluster_5540.ps
        ├── [ 15K]  Cluster_5540.txt
        ├── [ 12K]  Cluster_5636.ps
        ├── [4.0K]  Cluster_5636.txt
        ├── [ 12K]  Cluster_578.ps
        ├── [ 20K]  Cluster_578.txt
        ├── [ 12K]  Cluster_5849.ps
        ├── [9.2K]  Cluster_5849.txt
        ├── [ 12K]  Cluster_6211.ps
        ├── [4.1K]  Cluster_6211.txt
        ├── [ 12K]  Cluster_6865.ps
        ├── [ 12K]  Cluster_6865.txt
        ├── [ 12K]  Cluster_6866.ps
        ├── [9.9K]  Cluster_6866.txt
        ├── [ 12K]  Cluster_6867.ps
        ├── [ 14K]  Cluster_6867.txt
        ├── [ 11K]  Cluster_6875.ps
        ├── [ 39K]  Cluster_6875.txt
        ├── [ 12K]  Cluster_7013.ps
        ├── [9.7K]  Cluster_7013.txt
        ├── [ 12K]  Cluster_7604.ps
        ├── [ 19K]  Cluster_7604.txt
        ├── [ 12K]  Cluster_7605.ps
        ├── [ 13K]  Cluster_7605.txt
        ├── [ 11K]  Cluster_7804.ps
        ├── [5.7K]  Cluster_7804.txt
        ├── [ 12K]  Cluster_786.ps
        ├── [ 58K]  Cluster_786.txt
        ├── [ 12K]  Cluster_8571.ps
        ├── [5.5K]  Cluster_8571.txt
        ├── [ 12K]  Cluster_8824.ps
        ├── [ 30K]  Cluster_8824.txt
        ├── [ 12K]  Cluster_8827.ps
        ├── [ 15K]  Cluster_8827.txt
        ├── [ 12K]  Cluster_8828.ps
        ├── [ 20K]  Cluster_8828.txt
        ├── [ 11K]  Cluster_8920.ps
        ├── [ 52K]  Cluster_8920.txt
        ├── [ 12K]  Cluster_9077.ps
        ├── [3.3K]  Cluster_9077.txt
        ├── [ 12K]  Cluster_9915.ps
        ├── [ 10K]  Cluster_9915.txt
        ├── [ 12K]  Cluster_9991.ps
        ├── [ 25K]  Cluster_9991.txt
        ├── [ 12K]  Cluster_9992.ps
        └── [ 27K]  Cluster_9992.txt

2 directories, 119 files

6.3 Visualize

We noticed that a) not all of the identified miRNAs have database matches, and b) some reads have a match in the database but are not classified as miRNAs. Let’s look at this in more depth.

Peve_shortstack_results <- read.csv("../output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/ShortStack_out/Results.txt", sep="\t")
# Reads identified as miRNAs (but not necessarily known)
Peve_shortstack_results %>% 
  filter(MIRNA == "Y") %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = known_miRNAs)) +
  geom_bar(stat = "identity") +
   geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads identified by ShortStack as miRNAs",
       fill = "Annotation") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/figures/Peve_ShortStack_miRNA_histogram.png", width = 12, height = 7, units = "in")


# Reads matched in the reference db (but not necessarily identified as miRNA)
Peve_shortstack_results %>% 
  filter(!is.na(known_miRNAs)) %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = MIRNA)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads with miRBase+cnidarian database matches",
       fill = "Identified as miRNA?") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/figures/Peve_ShortStack_dbmatch_histogram.png", width = 12, height = 7, units = "in")

There’s one miRNA with a very high read count, and it’s making visualization of the rest difficult. Let’s remove it and retry visualizing the rest.

# Reads identified as miRNAs (but not necessarily known)
Peve_shortstack_results %>% 
  filter(MIRNA == "Y") %>%
  filter(Reads < 200000) %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = known_miRNAs)) +
  geom_bar(stat = "identity") +
   geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads identified by ShortStack as miRNAs",
       fill = "Annotation") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/figures/Peve_ShortStack_miRNA_histogram_reduced.png", width = 12, height = 7, units = "in")


# Reads matched in the reference db (but not necessarily identified as miRNA)
Peve_shortstack_results %>% 
  filter(!is.na(known_miRNAs)) %>%
  filter(Reads < 200000) %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = MIRNA)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads with miRBase+cnidarian database matches",
       fill = "Identified as miRNA?") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/figures/Peve_ShortStack_dbmatch_histogram_reduced.png", width = 12, height = 7, units = "in")
# Make list
mirnas <- Peve_shortstack_results %>% filter(MIRNA == "Y") %>% pull(Locus)
matches <- Peve_shortstack_results %>% filter(!is.na(known_miRNAs)) %>% pull(Locus)

Peve_shortstack_vennlist <- list(
  "Identified as miRNA" = mirnas,
  "Database match" = matches
)

# Make venn diagrams
ggvenn(Peve_shortstack_vennlist)

ggsave("../output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/figures/Peve_ShortStack_venn.png", width = 12, height = 7, units = "in")
Johnson, Nathan R, Jonathan M Yeoh, Ceyda Coruh, and Michael J Axtell. 2016. “Improved Placement of Multi-Mapping Small RNAs.” G3 Genes|Genomes|Genetics 6 (7): 2103–11. https://doi.org/10.1534/g3.116.030452.
LS0tCnRpdGxlOiAiMDguMi1QZXZlLXNSTkFzZXEtU2hvcnRTdGFjay0zMWJwLWZhc3RwLW1lcmdlZCIKYXV0aG9yOiAiU2FtIFdoaXRlIgpkYXRlOiAiMjAyNC0wMi0xMiIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWIKbGluay1jaXRhdGlvbnM6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGdndmVubikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBGQUxTRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKCiMgSW50cm9kdWN0aW9uCgpVc2UgW1Nob3J0U3RhY2tdKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2spIFtAQXh0ZWxsMjAxMy14dTsgQGpvaG5zb24yMDE2OyBAU2hhaGlkMjAxNC1seF0gdG8gcGVyZm9ybSBhbGlnbm1lbnQgb2Ygc1JOQXNlcSBkYXRhIGFuZCBhbm5vdGF0aW9uIG9mIHNSTkEtcHJvZHVjaW5nIGdlbmVzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpJbnB1dHM6CgotICAgUmVxdWlyZXMgdHJpbW1lZCBzUk5Bc2VxIGZpbGVzIGdlbmVyYXRlZCBieSBbMDYuMi1QZXZlLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQuUm1kXShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9jb2RlLzA2LjItUGV2ZS1zUk5Bc2VxLXRyaW1taW5nLTMxYnAtZmFzdHAtbWVyZ2VkLlJtZCkKCiAgICAtICAgRmlsZW5hbWVzIGZvcm1hdHRlZDogYCpmYXN0cC1SMS0zMWJwLWF1dG9fYWRhcHRlcnMtcG9seUcuZnEuZ3pgCgotICAgR2Vub21lIEZhc3RBLiBTZWUgWzA3LVBldmUtc1JOQXNlcS1NaXJNYWNoaW5lLm1kXShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9jb2RlLzA3LVBldmUtc1JOQXNlcS1NaXJNYWNoaW5lLm1kKSBmb3IgZG93bmxvYWQgaW5mbyBpZiBuZWVkZWQuCgotIE1vZGlmaWVkIE1pUkJhc2UgdjIyLjEgRmFzdEEuIEluY2x1ZGVzIGNuaWRhcmlhbiBtaVJOQXMgcHJvdmlkZWQgYnkgSmlsbCBBc2hsZXkuCgpPdXRwdXRzOgoKLSAgIFNlZSBbU2hvcnRTdGFjayBvdXRwdXRzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2sjb3V0cHV0cykgZm9yIGZ1bGwgbGlzdCBhbmQgZGV0YWlsZWQgZGVzY3JpcHRpb25zLgoKU29mdHdhcmUgcmVxdWlyZW1lbnRzOgoKLSAgIFV0aWxpemVzIGEgW1Nob3J0U3RhY2tdKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2sjaW5zdGFsbGF0aW9uKSBDb25kYS9NYW1iYSBlbnZpcm9ubWVudCwgcGVyIHRoZSBpbnN0YWxsYXRpb24gaW5zdHJ1Y3Rpb25zLgoKUmVwbGFjZSB3aXRoIG5hbWUgb2YgeW91ciBTaG9ydFN0YWNrIGVudmlyb25tZW50IGFuZCB0aGUgcGF0aCB0byB0aGUgY29ycmVzcG9uZGluZyBjb25kYSBpbnN0YWxsYXRpb24gKGZpbmQgdGhpcyAqYWZ0ZXIqIHlvdSd2ZSBhY3RpdmF0ZWQgdGhlIGVudmlyb25tZW50KS4KCkUuZy4KCmBgYCBiYXNoCiMgQWN0aXZhdGUgZW52aXJvbm1lbnQKY29uZGEgYWN0aXZhdGUgU2hvcnRTdGFjay00LjAuM19lbnYKCiMgRmluZCBjb25kYSBwYXRoCndoaWNoIGNvbmRhCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIFNldCBSIHZhcmlhYmxlcwoKYGBge3IgUi12YXJpYWJsZXMsIGV2YWw9VFJVRX0Kc2hvcnRzdGFja19jb25kYV9lbnZfbmFtZSA8LSBjKCJTaG9ydFN0YWNrLTQuMC4zX2VudiIpCnNob3J0c3RhY2tfY29uZF9wYXRoIDwtIGMoIi9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2NvbmRhYmluL2NvbmRhIikKYGBgCgojIENyZWF0ZSBhIEJhc2ggdmFyaWFibGVzIGZpbGUKClRoaXMgYWxsb3dzIHVzYWdlIG9mIEJhc2ggdmFyaWFibGVzIGFjcm9zcyBSIE1hcmtkb3duIGNodW5rcy4KCmBgYHtyIHNhdmUtYmFzaC12YXJpYWJsZXMtdG8tcnZhcnMtZmlsZSwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQp7CmVjaG8gIiMjIyMgQXNzaWduIFZhcmlhYmxlcyAjIyMjIgplY2hvICIiCgplY2hvICIjIFRyaW1tZWQgRmFzdFEgbmFtaW5nIHBhdHRlcm4iCmVjaG8gImV4cG9ydCB0cmltbWVkX2Zhc3Rxc19wYXR0ZXJuPScqZmFzdHAtYWRhcHRlcnMtcG9seUctMzFicC1tZXJnZWQuZnEuZ3onIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgZGVlcF9kaXZlX2Rpcj0vaG9tZS9zaGFyZWQvOFRCX0hERF8wMS9zYW0vZ2l0cmVwb3MvZGVlcC1kaXZlJwplY2hvICdleHBvcnQgZGVlcF9kaXZlX2RhdGFfZGlyPSIke2RlZXBfZGl2ZV9kaXJ9L2RhdGEiJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9JHtkZWVwX2RpdmVfZGlyfS9FLVBldmUvb3V0cHV0LzA4LjItUGV2ZS1zUk5Bc2VxLVNob3J0U3RhY2stMzFicC1mYXN0cC1tZXJnZWQnCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3Rxc19kaXI9IiR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wNi4yLVBldmUtc1JOQXNlcS10cmltbWluZy0zMWJwLWZhc3RwLW1lcmdlZC90cmltbWVkLXJlYWRzIicKZWNobyAiIgoKZWNobyAiIyBJbnB1dC9PdXRwdXQgZmlsZXMiCmVjaG8gJ2V4cG9ydCBnZW5vbWVfZmFzdGFfZGlyPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL2RhdGEnCmVjaG8gJ2V4cG9ydCBnZW5vbWVfZmFzdGFfbmFtZT0iUG9yaXRlc19ldmVybWFubmlfdjEuZmEiJwplY2hvICdleHBvcnQgc2hvcnRzdGFja19nZW5vbWVfZmFzdGFfbmFtZT0iUG9yaXRlc19ldmVybWFubmlfdjEuZmEiJwplY2hvICdleHBvcnQgbWlyYmFzZV9tYXR1cmVfZmFzdGFfdmVyc2lvbj1jbmlkYXJpYW4tbWlyYmFzZS1tYXR1cmUtdjIyLjEuZmFzdGEnCmVjaG8gJ2V4cG9ydCBnZW5vbWVfZmFzdGE9IiR7Z2Vub21lX2Zhc3RhX2Rpcn0vJHtzaG9ydHN0YWNrX2dlbm9tZV9mYXN0YV9uYW1lfSInCmVjaG8gIiIKCgplY2hvICIjIFNldCBudW1iZXIgb2YgQ1BVcyB0byB1c2UiCmVjaG8gJ2V4cG9ydCB0aHJlYWRzPTQwJwplY2hvICIiCgplY2hvICIjIEluaXRpYWxpemUgYXJyYXlzIgplY2hvICdleHBvcnQgdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCknCgoKfSA+IC5iYXNodmFycwoKY2F0IC5iYXNodmFycwpgYGAKCiMgTG9hZCBbU2hvcnRTdGFja10oaHR0cHM6Ly9naXRodWIuY29tL01pa2VBeHRlbGwvU2hvcnRTdGFjaykgY29uZGEgZW52aXJvbm1lbnQKCklmIHRoaXMgaXMgc3VjY2Vzc2Z1bCwgdGhlIGZpcnN0IGxpbmUgb2Ygb3V0cHV0IHNob3VsZCBzaG93IHRoYXQgdGhlIFB5dGhvbiBiZWluZyB1c2VkIGlzIHRoZSBvbmUgaW4geW91ciBbU2hvcnRTdGFja10oPGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2s+IGNvbmRhIGVudmlyb25tZW50IHBhdGguCgpFLmcuCgpgcHl0aG9uOiAgICAgICAgIC9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2VudnMvbWlybWFjaGluZV9lbnYvYmluL3B5dGhvbmAKCmBgYHtyIGxvYWQtc2hvcnRzdGFjay1jb25kYS1lbnYsIGV2YWw9VFJVRX0KdXNlX2NvbmRhZW52KGNvbmRhZW52ID0gc2hvcnRzdGFja19jb25kYV9lbnZfbmFtZSwgY29uZGEgPSBzaG9ydHN0YWNrX2NvbmRfcGF0aCkKCiMgQ2hlY2sgc3VjY2Vzc2Z1bCBlbnYgbG9hZGluZwpweV9jb25maWcoKQpgYGAKCgoKIyBSdW4gU2hvcnRTdGFjawoKIyMgRXhjZWN1dGUgU2hvcnRTdGFjayBjb21tYW5kCgojIyMgVEhJUyBLRUVQUyBDUkFTSElORyBBRlRFUiBTY3JlZW5pbmcgb2YgcG9zc2libGUgZGUgbm92byBtaWNyb1JOQXMKClVzZXMgdGhlIGAtLWRuX21pcm5hYCBvcHRpb24gdG8gaWRlbnRpZnkgbWlSTkFzIGluIHRoZSBnZW5vbWUsIHdpdGhvdXQgcmVseWluZyBvbiB0aGUgYC0ta25vd25fbWlSTkFzYC4KClRoaXMgcGFydCBvZiB0aGUgY29kZSByZWRpcmVjdHMgdGhlIG91dHB1dCBvZiBgdGltZWAgdG8gdGhlIGVuZCBvZiBgc2hvcnRzdGFjay5sb2dgIGZpbGUuCgotICAgYDsgfSBcIDI+PiAke291dHB1dF9kaXJfdG9wfS9zaG9ydHN0YWNrLmxvZ2AKCmBgYHtyIHNob3J0c3RhY2ssIGVuZ2luZT0nYmFzaCcsIGNhY2hlPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIE1ha2Ugb3V0cHV0IGRpcmVjdG9yeSwgaWYgaXQgZG9lc24ndCBleGlzdApta2RpciAtLXBhcmVudHMgIiR7b3V0cHV0X2Rpcl90b3B9IgoKIyBDcmVhdGUgYXJyYXkgb2YgdHJpbW1lZCBGYXN0UXMKdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCR7dHJpbW1lZF9mYXN0cXNfZGlyfS8ke3RyaW1tZWRfZmFzdHFzX3BhdHRlcm59KQoKCiMgUGFzcyBhcnJheSBjb250ZW50cyB0byBuZXcgdmFyaWFibGUgYXMgc3BhY2UtZGVsaW1pdGVkIGxpc3QKdHJpbW1lZF9mYXN0cXNfbGlzdD0kKGVjaG8gIiR7dHJpbW1lZF9mYXN0cXNfYXJyYXlbKl19IikKCgojIyMjIyMgUnVuIFNob3J0U3RhY2sgIyMjIyMjCnsgdGltZSBcClNob3J0U3RhY2sgXAotLWdlbm9tZWZpbGUgIiR7Z2Vub21lX2Zhc3RhfSIgXAotLXJlYWRmaWxlICR7dHJpbW1lZF9mYXN0cXNfbGlzdH0gXAotLWtub3duX21pUk5BcyAke2RlZXBfZGl2ZV9kYXRhX2Rpcn0vJHttaXJiYXNlX21hdHVyZV9mYXN0YV92ZXJzaW9ufSBcCi0tZG5fbWlybmEgXAotLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0ZGlyICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0IFwKJj4gJHtvdXRwdXRfZGlyX3RvcH0vc2hvcnRzdGFjay5sb2cgOyB9IFwKMj4+ICR7b3V0cHV0X2Rpcl90b3B9L3Nob3J0c3RhY2subG9nCgpgYGAKCiMjIENoZWNrIHJ1bnRpbWUKCmBgYHtyIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCnRhaWwgLW4gMyAke291dHB1dF9kaXJfdG9wfS9zaG9ydHN0YWNrLmxvZyBcCnwgZ3JlcCAicmVhbCIgXAp8IGF3ayAne3ByaW50ICJTaG9ydFN0YWNrIHJ1bnRpbWU6IiAiXHQiICQyfScKCmBgYAoKIyBSZXN1bHRzCgojIyBTaG9ydFN0YWNrIHN5bm9wc2lzCgpgYGB7ciBzaG9ydHN0YWNrLXN5bm9wc2lzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgp0YWlsIC1uIDI1ICR7b3V0cHV0X2Rpcl90b3B9L3Nob3J0c3RhY2subG9nCmBgYAoKU2hvcnRTdGFjayBmb3VuZCA0NiBtaVJOQXMuCgojIyBJbnNwZWN0IGBSZXN1bHRzLnR4dGAKCmBgYHtyIHJlc3VsdHMtdHh0LWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmhlYWQgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQKCmVjaG8gIiIKZWNobyAiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSIKZWNobyAiIgoKZWNobyAiTnVtbWJlciBvZiBwb3RlbnRpYWwgbG9jaToiCmF3ayAnKE5SPjEpJyAke291dHB1dF9kaXJfdG9wfS9TaG9ydFN0YWNrX291dC9SZXN1bHRzLnR4dCB8IHdjIC1sCmBgYAoKQ29sdW1uIDIwIG9mIHRoZSBgUmVzdWx0cy50eHRgIGZpbGUgaWRlbnRpZmllcyBpZiBhIGNsdXN0ZXIgaXMgYSBtaVJOQSBvciBub3QgKGBZYCBvciBgTmApLgoKYGBge3IgcmVzdWx0cy10eHQtbWlSTkFzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgplY2hvICJOdW1iZXIgb2YgbG9jaSBjaGFyYWN0ZXJpemVkIGFzIG1pUk5BOiIKYXdrICckMjA9PSJZIiB7cHJpbnQgJDB9JyAke291dHB1dF9kaXJfdG9wfS9TaG9ydFN0YWNrX291dC9SZXN1bHRzLnR4dCBcCnwgd2MgLWwKZWNobyAiIgoKZWNobyAiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSIKCmVjaG8gIiIKZWNobyAiTnVtYmVyIG9mIGxvY2kgX25vdF8gY2hhcmFjdGVyaXplZCBhcyBtaVJOQToiCmF3ayAnJDIwPT0iTiIge3ByaW50ICQwfScgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQgXAp8IHdjIC1sCgpgYGAKCkNvbHVtbiAyMSBvZiB0aGUgYFJlc3VsdHMudHh0YCBmaWxlIGlkZW50aWZpZXMgaWYgYSBjbHVzdGVyIGFsaWduZWQgdG8gYSBrbm93biBtaVJOQSAobWlSQmFzZSkgb3Igbm90IChgWWAgb3IgYE5BYCkuCgoKYGBge3IgcmVzdWx0cy10eHQtbWlSQmFzZS1taVJOQXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmVjaG8gIk51bWJlciBvZiBsb2NpIG1hdGNoaW5nIG1pUkJhc2UgbWlSTkFzOiIKYXdrICckMjEhPSJOQSIge3ByaW50ICQwfScgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQgXAp8IHdjIC1sCmVjaG8gIiIKCmVjaG8gIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0iCgplY2hvICIiCmVjaG8gIk51bWJlciBvZiBsb2NpIF9ub3RfIG1hdGNoaW5nIG1pUkJhc2UgbWlSTkFzOiIKYXdrICckMjE9PSJOQSIge3ByaW50ICQwfScgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQgXAp8IHdjIC1sCgpgYGAKCkFsdGhvdWdoIHRoZXJlIGFyZSA0NiBsb2NpIHdpdGggbWF0Y2hlcyB0byBtaVJCYXNlIG1pUk5BcywgU2hvcnRTdGFjayBkaWQgKm5vdCogYW5ub3RhdGUgOSBvZiB0aGVzZSBjbHVzdGVycyBhcyBtaVJOQXMgbGlrZWx5IFtiZWNhdXNlIHRoZXkgZG8gbm90ICphbHNvKiBtYXRjaCBzZWNvbmRhcnkgc3RydWN0dXJlIGNyaXRlcmlhXShodHRwczovL2dpdGh1Yi5jb20vTWlrZUF4dGVsbC9TaG9ydFN0YWNrI21pcm5hLWFubm90YXRpb24pLgoKVGhpcyBleHBsYWlucyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSA0NiBhbmQgMzcgbWlSTkFzLgoKIyMjIERpcmVjdG9yeSB0cmVlIG9mIGFsbCBTaG9ydFN0YWNrIG91dHB1dHMKCk1hbnkgb2YgdGhlc2UgYXJlIGxhcmdlIChieSBHaXRIdWIgc3RhbmRhcmRzKSBCQU0gZmlsZXMsIHNvIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSByZXBvLgoKQWRkaXRpb25hbGx5LCBpdCdzIHVubGlrZWx5IHdlJ2xsIHV0aWxpemUgbW9zdCBvZiB0aGUgb3RoZXIgZmlsZXMgKGJpZ3dpZykgZ2VuZXJhdGVkIGJ5IFNob3J0U3RhY2suCgpgYGB7ciBzaG9ydHN0YWNrLWRpcmVjdG9yeS10cmVlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgp0cmVlIC1oICR7b3V0cHV0X2Rpcl90b3B9LwoKYGBgCgojIyBWaXN1YWxpemUKCldlIG5vdGljZWQgdGhhdCBhKSBub3QgYWxsIG9mIHRoZSBpZGVudGlmaWVkIG1pUk5BcyBoYXZlIGRhdGFiYXNlIG1hdGNoZXMsIGFuZCBiKSBzb21lIHJlYWRzIGhhdmUgYSBtYXRjaCBpbiB0aGUgZGF0YWJhc2UgYnV0IGFyZSAqbm90KiBjbGFzc2lmaWVkIGFzIG1pUk5Bcy4gTGV0J3MgbG9vayBhdCB0aGlzIGluIG1vcmUgZGVwdGguCgpgYGB7ciBsb2FkLXJlc3VsdHMsIGV2YWw9VFJVRX0KUGV2ZV9zaG9ydHN0YWNrX3Jlc3VsdHMgPC0gcmVhZC5jc3YoIi4uL291dHB1dC8wOC4yLVBldmUtc1JOQXNlcS1TaG9ydFN0YWNrLTMxYnAtZmFzdHAtbWVyZ2VkL1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0Iiwgc2VwPSJcdCIpCmBgYAoKYGBge3IgZ2VuZXJhdGUtcGxvdHMsIGV2YWw9VFJVRX0KIyBSZWFkcyBpZGVudGlmaWVkIGFzIG1pUk5BcyAoYnV0IG5vdCBuZWNlc3NhcmlseSBrbm93bikKUGV2ZV9zaG9ydHN0YWNrX3Jlc3VsdHMgJT4lIAogIGZpbHRlcihNSVJOQSA9PSAiWSIpICU+JQogIG11dGF0ZShrbm93bl9taVJOQXMgPSBzdHJfc3ViKGtub3duX21pUk5BcywgMSwgNDApKSAlPiUKICBtdXRhdGUoTG9jdXMgPSBzdHJfc3ViKExvY3VzLCAyMCwgNDApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKExvY3VzLCBSZWFkcyksIHkgPSBSZWFkcywgZmlsbCA9IGtub3duX21pUk5BcykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUmVhZHMpLCB2anVzdCA9IDAuNSwgaGp1c3QgPSAwLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjUsIGFuZ2xlID0gOTApICsKICBsYWJzKHggPSAibWlSTkEiLCB5ID0gIlJlYWQgY291bnQiLCAKICAgICAgIHRpdGxlID0gIlJlYWRzIGlkZW50aWZpZWQgYnkgU2hvcnRTdGFjayBhcyBtaVJOQXMiLAogICAgICAgZmlsbCA9ICJBbm5vdGF0aW9uIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSkKICAKZ2dzYXZlKCIuLi9vdXRwdXQvMDguMi1QZXZlLXNSTkFzZXEtU2hvcnRTdGFjay0zMWJwLWZhc3RwLW1lcmdlZC9maWd1cmVzL1BldmVfU2hvcnRTdGFja19taVJOQV9oaXN0b2dyYW0ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgdW5pdHMgPSAiaW4iKQoKCiMgUmVhZHMgbWF0Y2hlZCBpbiB0aGUgcmVmZXJlbmNlIGRiIChidXQgbm90IG5lY2Vzc2FyaWx5IGlkZW50aWZpZWQgYXMgbWlSTkEpClBldmVfc2hvcnRzdGFja19yZXN1bHRzICU+JSAKICBmaWx0ZXIoIWlzLm5hKGtub3duX21pUk5BcykpICU+JQogIG11dGF0ZShrbm93bl9taVJOQXMgPSBzdHJfc3ViKGtub3duX21pUk5BcywgMSwgNDApKSAlPiUKICBtdXRhdGUoTG9jdXMgPSBzdHJfc3ViKExvY3VzLCAyMCwgNDApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKExvY3VzLCBSZWFkcyksIHkgPSBSZWFkcywgZmlsbCA9IE1JUk5BKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFJlYWRzKSwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMCwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMi41LCBhbmdsZSA9IDkwKSArCiAgbGFicyh4ID0gIm1pUk5BIiwgeSA9ICJSZWFkIGNvdW50IiwgCiAgICAgICB0aXRsZSA9ICJSZWFkcyB3aXRoIG1pUkJhc2UrY25pZGFyaWFuIGRhdGFiYXNlIG1hdGNoZXMiLAogICAgICAgZmlsbCA9ICJJZGVudGlmaWVkIGFzIG1pUk5BPyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoIi4uL291dHB1dC8wOC4yLVBldmUtc1JOQXNlcS1TaG9ydFN0YWNrLTMxYnAtZmFzdHAtbWVyZ2VkL2ZpZ3VyZXMvUGV2ZV9TaG9ydFN0YWNrX2RibWF0Y2hfaGlzdG9ncmFtLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIHVuaXRzID0gImluIikKYGBgCgpUaGVyZSdzIG9uZSBtaVJOQSB3aXRoIGEgdmVyeSBoaWdoIHJlYWQgY291bnQsIGFuZCBpdCdzIG1ha2luZyB2aXN1YWxpemF0aW9uIG9mIHRoZSByZXN0IGRpZmZpY3VsdC4gTGV0J3MgcmVtb3ZlIGl0IGFuZCByZXRyeSB2aXN1YWxpemluZyB0aGUgcmVzdC4KCmBgYHtyIGdlbmVyYXRlLXBsb3RzLXJlZHVjZWQsIGV2YWw9VFJVRX0KIyBSZWFkcyBpZGVudGlmaWVkIGFzIG1pUk5BcyAoYnV0IG5vdCBuZWNlc3NhcmlseSBrbm93bikKUGV2ZV9zaG9ydHN0YWNrX3Jlc3VsdHMgJT4lIAogIGZpbHRlcihNSVJOQSA9PSAiWSIpICU+JQogIGZpbHRlcihSZWFkcyA8IDIwMDAwMCkgJT4lCiAgbXV0YXRlKGtub3duX21pUk5BcyA9IHN0cl9zdWIoa25vd25fbWlSTkFzLCAxLCA0MCkpICU+JQogIG11dGF0ZShMb2N1cyA9IHN0cl9zdWIoTG9jdXMsIDIwLCA0MCkpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTG9jdXMsIFJlYWRzKSwgeSA9IFJlYWRzLCBmaWxsID0ga25vd25fbWlSTkFzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBSZWFkcyksIHZqdXN0ID0gMC41LCBoanVzdCA9IDAsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIuNSwgYW5nbGUgPSA5MCkgKwogIGxhYnMoeCA9ICJtaVJOQSIsIHkgPSAiUmVhZCBjb3VudCIsIAogICAgICAgdGl0bGUgPSAiUmVhZHMgaWRlbnRpZmllZCBieSBTaG9ydFN0YWNrIGFzIG1pUk5BcyIsCiAgICAgICBmaWxsID0gIkFubm90YXRpb24iKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpKQogIApnZ3NhdmUoIi4uL291dHB1dC8wOC4yLVBldmUtc1JOQXNlcS1TaG9ydFN0YWNrLTMxYnAtZmFzdHAtbWVyZ2VkL2ZpZ3VyZXMvUGV2ZV9TaG9ydFN0YWNrX21pUk5BX2hpc3RvZ3JhbV9yZWR1Y2VkLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIHVuaXRzID0gImluIikKCgojIFJlYWRzIG1hdGNoZWQgaW4gdGhlIHJlZmVyZW5jZSBkYiAoYnV0IG5vdCBuZWNlc3NhcmlseSBpZGVudGlmaWVkIGFzIG1pUk5BKQpQZXZlX3Nob3J0c3RhY2tfcmVzdWx0cyAlPiUgCiAgZmlsdGVyKCFpcy5uYShrbm93bl9taVJOQXMpKSAlPiUKICBmaWx0ZXIoUmVhZHMgPCAyMDAwMDApICU+JQogIG11dGF0ZShrbm93bl9taVJOQXMgPSBzdHJfc3ViKGtub3duX21pUk5BcywgMSwgNDApKSAlPiUKICBtdXRhdGUoTG9jdXMgPSBzdHJfc3ViKExvY3VzLCAyMCwgNDApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKExvY3VzLCBSZWFkcyksIHkgPSBSZWFkcywgZmlsbCA9IE1JUk5BKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFJlYWRzKSwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMCwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMi41LCBhbmdsZSA9IDkwKSArCiAgbGFicyh4ID0gIm1pUk5BIiwgeSA9ICJSZWFkIGNvdW50IiwgCiAgICAgICB0aXRsZSA9ICJSZWFkcyB3aXRoIG1pUkJhc2UrY25pZGFyaWFuIGRhdGFiYXNlIG1hdGNoZXMiLAogICAgICAgZmlsbCA9ICJJZGVudGlmaWVkIGFzIG1pUk5BPyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoIi4uL291dHB1dC8wOC4yLVBldmUtc1JOQXNlcS1TaG9ydFN0YWNrLTMxYnAtZmFzdHAtbWVyZ2VkL2ZpZ3VyZXMvUGV2ZV9TaG9ydFN0YWNrX2RibWF0Y2hfaGlzdG9ncmFtX3JlZHVjZWQucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgdW5pdHMgPSAiaW4iKQpgYGAKCmBgYHtyIHZlbm4tZGlhZ3JhbSwgZXZhbD1UUlVFfQojIE1ha2UgbGlzdAptaXJuYXMgPC0gUGV2ZV9zaG9ydHN0YWNrX3Jlc3VsdHMgJT4lIGZpbHRlcihNSVJOQSA9PSAiWSIpICU+JSBwdWxsKExvY3VzKQptYXRjaGVzIDwtIFBldmVfc2hvcnRzdGFja19yZXN1bHRzICU+JSBmaWx0ZXIoIWlzLm5hKGtub3duX21pUk5BcykpICU+JSBwdWxsKExvY3VzKQoKUGV2ZV9zaG9ydHN0YWNrX3Zlbm5saXN0IDwtIGxpc3QoCiAgIklkZW50aWZpZWQgYXMgbWlSTkEiID0gbWlybmFzLAogICJEYXRhYmFzZSBtYXRjaCIgPSBtYXRjaGVzCikKCiMgTWFrZSB2ZW5uIGRpYWdyYW1zCmdndmVubihQZXZlX3Nob3J0c3RhY2tfdmVubmxpc3QpCgpnZ3NhdmUoIi4uL291dHB1dC8wOC4yLVBldmUtc1JOQXNlcS1TaG9ydFN0YWNrLTMxYnAtZmFzdHAtbWVyZ2VkL2ZpZ3VyZXMvUGV2ZV9TaG9ydFN0YWNrX3Zlbm4ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgdW5pdHMgPSAiaW4iKQpgYGAKCg==