# load packages
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(tidyr)
library(ggplot2)

What DEGs are also expected to interact with miRNA?

tp1.v.tp2 <- read.csv("../output/03.00-D-Apul-RNAseq-gene-expression-DESeq2/tp1.v.tp2.results.table.csv")
tp1.v.tp2 <- rename(tp1.v.tp2, "geneID" = "X")

tp1.v.tp3 <- read.csv("../output/03.00-D-Apul-RNAseq-gene-expression-DESeq2/tp1.v.tp3.results.table.csv")
tp1.v.tp3 <- rename(tp1.v.tp3, "geneID" = "X")

tp1.v.tp4 <- read.csv("../output/03.00-D-Apul-RNAseq-gene-expression-DESeq2/tp1.v.tp4.results.table.csv")
tp1.v.tp4 <- rename(tp1.v.tp4, "geneID" = "X")

tp2.v.tp3 <- read.csv("../output/03.00-D-Apul-RNAseq-gene-expression-DESeq2/tp2.v.tp3.results.table.csv")
tp2.v.tp3 <- rename(tp2.v.tp3, "geneID" = "X")

tp2.v.tp4 <- read.csv("../output/03.00-D-Apul-RNAseq-gene-expression-DESeq2/tp2.v.tp4.results.table.csv")
tp2.v.tp4 <- rename(tp2.v.tp4, "geneID" = "X")

tp3.v.tp4 <- read.csv("../output/03.00-D-Apul-RNAseq-gene-expression-DESeq2/tp3.v.tp4.results.table.csv")
tp3.v.tp4 <- rename(tp3.v.tp4, "geneID" = "X")

Timepoints 2 vs 4 has the most DEGs

paste("Of ", nrow(tp1.v.tp2), " genes")
## [1] "Of  44371  genes"
paste("")
## [1] ""
paste("tp1 vs tp2: ", nrow(filter(tp1.v.tp2, padj < 0.05)))
## [1] "tp1 vs tp2:  623"
paste("tp1 vs tp3: ", nrow(filter(tp1.v.tp3, padj < 0.05)))
## [1] "tp1 vs tp3:  293"
paste("tp1 vs tp4: ", nrow(filter(tp1.v.tp4, padj < 0.05)))
## [1] "tp1 vs tp4:  341"
paste("tp2 vs tp3: ", nrow(filter(tp2.v.tp3, padj < 0.05)))
## [1] "tp2 vs tp3:  349"
paste("tp2 vs tp4: ", nrow(filter(tp2.v.tp4, padj < 0.05)))
## [1] "tp2 vs tp4:  684"
paste("tp3 vs tp4: ", nrow(filter(tp3.v.tp4, padj < 0.05)))
## [1] "tp3 vs tp4:  461"

These DEG counts make sense with our PCA, which shows timepoints 1 and 4 clustering more closely together, and timepoints 2 and 3 clustering more closely together.

Read in miRanda results (miRNAs binding to 3UTRs)

miRanda <- read.table("../output/07-Apul-miRNA-mRNA-miRanda/Apul-miRanda-3UTR-strict-parsed-geneIDs.txt", header = FALSE, sep = "\t")

Annotate pairwise comparison results with putative miRNA interactions

# Some UTRs are associated with 2 gene IDs (due to the genes sitting very close to each other)
# Expand those geneIDs into multiple rows
miRanda_expand <- miRanda %>%
  separate_rows(V10, sep = ",")  # Split the FUN column by commas into multiple rows

tp1.v.tp2.miRanda <- left_join(tp1.v.tp2, miRanda, by = c("geneID" = "V10"))
tp1.v.tp2.miRanda$V1 <- gsub(">", "", tp1.v.tp2.miRanda$V1)
tp1.v.tp2.miRanda$V1 <- gsub("\\..*", "", tp1.v.tp2.miRanda$V1)

tp1.v.tp3.miRanda <- left_join(tp1.v.tp3, miRanda, by = c("geneID" = "V10"))
tp1.v.tp3.miRanda$V1 <- gsub(">", "", tp1.v.tp3.miRanda$V1)
tp1.v.tp3.miRanda$V1 <- gsub("\\..*", "", tp1.v.tp3.miRanda$V1)

tp1.v.tp4.miRanda <- left_join(tp1.v.tp4, miRanda, by = c("geneID" = "V10"))
tp1.v.tp4.miRanda$V1 <- gsub(">", "", tp1.v.tp4.miRanda$V1)
tp1.v.tp4.miRanda$V1 <- gsub("\\..*", "", tp1.v.tp4.miRanda$V1)

tp2.v.tp3.miRanda <- left_join(tp2.v.tp3, miRanda, by = c("geneID" = "V10"))
tp2.v.tp3.miRanda$V1 <- gsub(">", "", tp2.v.tp3.miRanda$V1)
tp2.v.tp3.miRanda$V1 <- gsub("\\..*", "", tp2.v.tp3.miRanda$V1)

tp2.v.tp4.miRanda <- left_join(tp2.v.tp4, miRanda, by = c("geneID" = "V10"))
tp2.v.tp4.miRanda$V1 <- gsub(">", "", tp2.v.tp4.miRanda$V1)
tp2.v.tp4.miRanda$V1 <- gsub("\\..*", "", tp2.v.tp4.miRanda$V1)

tp3.v.tp4.miRanda <- left_join(tp3.v.tp4, miRanda, by = c("geneID" = "V10"))
tp3.v.tp4.miRanda$V1 <- gsub(">", "", tp3.v.tp4.miRanda$V1)
tp3.v.tp4.miRanda$V1 <- gsub("\\..*", "", tp3.v.tp4.miRanda$V1)

Keep in mind that, since an miRNA may be predicted to bind at multiple places in a single 3UTR, or multiple miRNAs may be predicted to bind to the same 3UTR, this table no longer contains a single row for each gene ID.

This table essentially shows every miRNA-3UTR predicted interaction and the DESeq2 pairwise expression comparison for the gene associated with that gene.

Let’s take a look. We’ll filter to significant DEGs (padj < 0.05). In cnidarians, miRNA-mRNA binding is believed to require near-complete complementarity of the full mature miRNA, similarly to plants, so we may want to look at how many putative interactions are predicted for a binding length of at least 20 nucleotides (the length of our smallest mature miRNA is 21) and 80% alignment rate (allows for 4 mismatches in a 20bp alignment). Finally, we should remove the duplicates caused by an miRNA putatively binding to multiple places in the 3UTR – multiple putative binding sites still indicate one miRNA-mRNA binding pair.

paste("Column descriptions:")
## [1] "Column descriptions:"
paste("Number of putative miRNA-DEG interactions")
## [1] "Number of putative miRNA-DEG interactions"
paste("Number of putative miRNA-DEG interactions (at least 20bp binding)")
## [1] "Number of putative miRNA-DEG interactions (at least 20bp binding)"
paste("Number of putative miRNA-DEG interactions(at least 20bp binding, max 4 mismatches)")
## [1] "Number of putative miRNA-DEG interactions(at least 20bp binding, max 4 mismatches)"
z <- data.frame(
  pairwise = c("tp1_tp2", "tp1_tp3", "tp1_tp4", "tp2_tp3", "tp2_tp4", "tp3_tp4"), 
  miRNA_DEG = c(tp1.v.tp2.miRanda %>% filter(padj < 0.05) %>% distinct(geneID, V1) %>% nrow(), 
                tp1.v.tp3.miRanda %>% filter(padj < 0.05) %>% distinct(geneID, V1) %>% nrow(), 
                tp1.v.tp4.miRanda %>% filter(padj < 0.05) %>% distinct(geneID, V1) %>% nrow(), 
                tp2.v.tp3.miRanda %>% filter(padj < 0.05) %>% distinct(geneID, V1) %>% nrow(), 
                tp2.v.tp4.miRanda %>% filter(padj < 0.05) %>% distinct(geneID, V1) %>% nrow(), 
                tp3.v.tp4.miRanda %>% filter(padj < 0.05) %>% distinct(geneID, V1) %>% nrow()), 
  miRNA_DEG_20bp = c(tp1.v.tp2.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% distinct(geneID, V1) %>% nrow(), 
                tp1.v.tp3.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% distinct(geneID, V1) %>% nrow(), 
                tp1.v.tp4.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% distinct(geneID, V1) %>% nrow(), 
                tp2.v.tp3.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% distinct(geneID, V1) %>% nrow(), 
                tp2.v.tp4.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% distinct(geneID, V1) %>% nrow(), 
                tp3.v.tp4.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% distinct(geneID, V1) %>% nrow()),
  miRNA_DEG_20bp_4mis = c(tp1.v.tp2.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% filter(V8 > 80) %>% distinct(geneID, V1) %>% nrow(), 
                tp1.v.tp3.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% filter(V8 > 80) %>% distinct(geneID, V1) %>% nrow(), 
                tp1.v.tp4.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% filter(V8 > 80) %>% distinct(geneID, V1) %>% nrow(), 
                tp2.v.tp3.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% filter(V8 > 80) %>% distinct(geneID, V1) %>% nrow(), 
                tp2.v.tp4.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% filter(V8 > 80) %>% distinct(geneID, V1) %>% nrow(), 
                tp3.v.tp4.miRanda %>% filter(padj < 0.05) %>% filter(V7 > 19) %>% filter(V8 > 80) %>% distinct(geneID, V1) %>% nrow())
)
z
##   pairwise miRNA_DEG miRNA_DEG_20bp miRNA_DEG_20bp_4mis
## 1  tp1_tp2      1950            498                  17
## 2  tp1_tp3       917            246                  13
## 3  tp1_tp4      1013            255                  13
## 4  tp2_tp3      1056            275                   7
## 5  tp2_tp4      2156            570                  29
## 6  tp3_tp4      1424            347                  17

1 Binding + Coexpression (miRanda + Pearson’s correlation)

Jill was able to run the miRNA-gene expression Pearson’s correlation code (14-Apul-miRNA-mRNA-coexpression) for me, so let’s look at those results.

# Load in results
pcc_miRanda_all <- read.csv("../output/14-Apul-miRNA-mRNA-coexpression/pcc_miranda_interactions.csv") %>% select(-X)
pcc_miRanda_sig <- read.csv("../output/14-Apul-miRNA-mRNA-coexpression/pcc_pairs_of_interest.csv") %>% select(-X)

pcc_miRanda_all %>% filter(p_value < 0.05) %>% nrow()
## [1] 10712
pcc_miRanda_all %>% filter(p_value < 0.01) %>% nrow()
## [1] 4312
pcc_miRanda_all %>% filter(p_value < 0.001) %>% nrow()
## [1] 1347
pcc_miRanda_sig %>% nrow()
## [1] 1357
pcc_miRanda_sig %>% filter(p_value < 0.001) %>% nrow()
## [1] 1347

So 10,712 putative miRNA-mRNA interactions predicted by miRanda are also significantly correlated in expression with a significance level of 0.05. For p < 0.01, expression of 4,312 putative interactions are significantly correlated. For p < 0.001, 1,347 are significant.

Note that the “pcc_pairs_of_interest” are interactions that are coexpressed with a correlation magnitude of at least 0.5 and a p < 0.05, but this ends up being essentially the same as a p < 0.001 significance level.

It’s believed that cnidarian miRNAs act more like than plant miRNAs than other animals, requiring more complete complementarity of the full mature miRNA to bind (in comparison, most animal miRNAs require only complementarity of the ~8bp “seed” region). For our putative miRNA-mRNA interactions, what is the distribution of shared bp?

pcc_miRanda_sig %>%
  ggplot(aes(x = total_bp_shared)) +
  geom_bar(fill = "#408EC6", color = "black") +
  labs(title = "Alignment lengths of coexpressed miRNA-mRNA binding pairs", x = "Total bp shared", y = "Frequency") +
  theme_classic() +
  # Add text labels on top of the bars
  geom_text(stat = 'count', aes(label = after_stat(count)), vjust = -0.5, color = "black")  # vjust to adjust the position

Interesting! I see two “spikes”. The 7-8bp spike could indicate seed binding, and the 16-22bp hump could represent the full mature miRNA complementarity expected for cnidarians. Not sure about the middle stuff though (9-15bp). I’, also not sure why there are counts above 24bp, since that’s the length of our longest miRNA…

How many of these highly significant interactions are unique (a gene interacts with only one miRNA) vs shared (a gene interacts with multiple miRNA)?

library(dplyr)
library(ggplot2)

# Add a column with the number of appearances of each mRNA
pcc_miRanda_sig <- pcc_miRanda_sig %>%
  mutate(mRNA_num_interaction = ave(mRNA, mRNA, FUN = length))

# Filter to unique mRNAs and plot histogram of their number of appearances
pcc_miRanda_sig %>%
  distinct(mRNA, mRNA_num_interaction) %>%  # Keep only unique mRNA rows
  ggplot(aes(x = mRNA_num_interaction)) +
  geom_bar(fill = "#408EC6", color = "black") +
  labs(
    title = "Number of distinct putative interactions per gene",
    x = "Interacting miRNAs",
    y = "Frequency"
  ) +
  theme_classic() +
  # Add text labels on top of the bars
  geom_text(stat = 'count', aes(label = after_stat(count)), vjust = -0.5, color = "black")

So miRNA-mRNA interaction is largely discrete, with expression of a given gene influenced by just one or two miRNA

How many genes does each miRNA interact with?

# Count the number of distinct mRNAs associated with each miRNA
miRNA_mRNA_count <- pcc_miRanda_sig %>%
  group_by(miRNA) %>%
  summarise(mRNA_count = n_distinct(mRNA)) %>%
  ungroup()

# Order miRNAs from largest to smallest by mRNA count
miRNA_mRNA_count$miRNA <- reorder(miRNA_mRNA_count$miRNA, -miRNA_mRNA_count$mRNA_count)

# Plot bar plot with all bars the same color
ggplot(miRNA_mRNA_count, aes(x = miRNA, y = mRNA_count)) +
  geom_bar(stat = "identity", fill = "#408EC6", color = "black") +  # Set all bars to the same color
  labs(title = "Number of genes putatively interacting with each miRNA",
       x = "miRNA",
       y = "Number of mRNAs") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for readability

2 Functional Annotation of binding/coexpressed genes

To get an idea of miRNA function, let’s functionally annotate all of the significantly coexpressed genes.

Generation of Uniprot/Swissprot GO annotation table for the A.pulchra genome can be found in deep-dive-expression/D-Apul/code/02-Apul-reference-annotation. Also associated all A.pulchra mRNAs with their respective gene IDs here

# Load FA table
Apul_FA_table <- read.delim("https://github.com/urol-e5/deep-dive-expression/raw/refs/heads/main/D-Apul/output/02-Apul-reference-annotation/Apulcra-genome-mRNA-IDmapping-2024_12_12.tab") %>% select(-X)

# Not sure why but some of these rows are duplicates
# Remove duplicate rows (must have same genomic location *and* functional annotation)
Apul_FA_table <- Apul_FA_table %>%
  distinct(V1, V3, .keep_all = TRUE)

# Load table associating each mRNA with a gene ID
Apul_geneIDs_table <- read.delim("https://github.com/urol-e5/deep-dive-expression/raw/refs/heads/main/D-Apul/output/15-Apul-annotate-UTRs/Apul-mRNA-FUNids.txt", header = FALSE)

head(Apul_FA_table)
##                     V1     V3      V13 Protein.names
## 1   ntLink_4:1155-1537 P35061 4.96e-86   Histone H2A
## 2   ntLink_4:2660-3441 P84239 5.03e-93    Histone H3
## 3   ntLink_4:4515-6830 P35061 6.65e-78   Histone H2A
## 4   ntLink_4:7096-7859 P84239 4.03e-93    Histone H3
## 5   ntLink_4:8474-9669 P35061 7.49e-82   Histone H2A
## 6 ntLink_4:11162-11925 P84239 4.03e-93    Histone H3
##                                     Organism Gene.Ontology..biological.process.
## 1          Acropora formosa (Staghorn coral)                                   
## 2 Urechis caupo (Innkeeper worm) (Spoonworm)                                   
## 3          Acropora formosa (Staghorn coral)                                   
## 4 Urechis caupo (Innkeeper worm) (Spoonworm)                                   
## 5          Acropora formosa (Staghorn coral)                                   
## 6 Urechis caupo (Innkeeper worm) (Spoonworm)                                   
##                                            Gene.Ontology.IDs
## 1 GO:0000786; GO:0003677; GO:0005634; GO:0030527; GO:0046982
## 2 GO:0000786; GO:0003677; GO:0005634; GO:0030527; GO:0046982
## 3 GO:0000786; GO:0003677; GO:0005634; GO:0030527; GO:0046982
## 4 GO:0000786; GO:0003677; GO:0005634; GO:0030527; GO:0046982
## 5 GO:0000786; GO:0003677; GO:0005634; GO:0030527; GO:0046982
## 6 GO:0000786; GO:0003677; GO:0005634; GO:0030527; GO:0046982
head(Apul_geneIDs_table)
##                     V1   V2               V3                V4
## 1   ntLink_0:1104-7056 mRNA ID=FUN_000001-T1 Parent=FUN_000001
## 2 ntLink_0:10214-15286 mRNA ID=FUN_000002-T1 Parent=FUN_000002
## 3 ntLink_0:32056-33275 mRNA ID=FUN_000003-T1 Parent=FUN_000003
## 4 ntLink_0:34823-42794 mRNA ID=FUN_000004-T1 Parent=FUN_000004
## 5 ntLink_0:45952-51024 mRNA ID=FUN_000005-T1 Parent=FUN_000005
## 6 ntLink_0:61628-78213 mRNA ID=FUN_000006-T1 Parent=FUN_000006
##                     V5
## 1 product=hypothetical
## 2 product=hypothetical
## 3 product=hypothetical
## 4 product=hypothetical
## 5 product=hypothetical
## 6 product=hypothetical

Annotate FA table with gene IDs

Apul_FA_table <- left_join(Apul_FA_table, select(Apul_geneIDs_table, V1, V4), by = c("V1" = "V1"))

# Ensure we're not missing gene IDs for any mRNAs
any(is.na(Apul_FA_table$V4))
## [1] FALSE
# Remove the "Parent=" before every gene ID
Apul_FA_table$V4 <- gsub("Parent=", "", Apul_FA_table$V4)

Ok, now that we can associate every gene ID with it’s GO terms and biological processes, let’s see what terms show up in our miRNA-mRNA significant interactions!

pcc_miRanda_sig_FA <- left_join(pcc_miRanda_sig, Apul_FA_table, by = c("mRNA" = "V4"))

To determine whether certain biological processes are signifcantly associated with an miRNA, we can run functional enrichment. This entails taking all of the functional annotations associated with a given miRNA and comparing them to the “background” (functional annotations for every gene present in our samples) to determine whether any functions appear more than expected.

For each miRNA, extract the functional annotation for every gene it significantly interacts with. Specifically we want the Uniprot Accession number.

# Create the output directory (if it doesn't already exist)
output_dir <- "../output/13-Apul-miRNA-mRNA-analysis-comparisons"
if (!dir.exists(output_dir)) {
  dir.create(output_dir)
}

# Loop through each unique miRNA
unique_miRNAs <- unique(pcc_miRanda_sig_FA$miRNA)

for (miRNA in unique_miRNAs) {
  # Filter rows for the current miRNA
  miRNA_data <- pcc_miRanda_sig_FA %>%
    filter(miRNA == !!miRNA) %>%
    filter(!is.na(V3)) %>% # Remove rows with NA values
    select(V3)
  
  # Save the Accession Numbers to a CSV file
  write.table(
    miRNA_data,
    file = file.path(output_dir, paste0(miRNA, "_UniprotAccessions.txt")),
    row.names = FALSE,
    col.names = FALSE,
    quote = FALSE
  )
}

# Confirmation message
cat("Files saved in", output_dir)
## Files saved in ../output/13-Apul-miRNA-mRNA-analysis-comparisons

We also want to get a list of Uniprot Accession numbers for our “background”. This is a reference of all expressed genes we would expect to find in our samples. We could just use IDs from our full reference, but this may include genes we may not actually expect to find in our samples (e.g. genes related to larval development). We should filter to keep only genes present in at least one of our samples.

# Load in Apul RNA raw counts matrix
Apul_raw_RNA_counts <- read.csv("../output/02.20-D-Apul-RNAseq-alignment-HiSat2/apul-gene_count_matrix.csv", row.names = "gene_id")

# Filter to keep only genes present in at least 1 sample
Apul_raw_RNA_counts_present <- Apul_raw_RNA_counts[rowSums(Apul_raw_RNA_counts) != 0, ]

Apul_raw_RNA_counts_present$gene_id <- rownames(Apul_raw_RNA_counts_present)

# Join with FA table to get Accession numbers of expressed genes
Apul_background <- left_join(Apul_raw_RNA_counts_present, Apul_FA_table, by = c("gene_id" = "V4")) 

# Select the column of Uniprot Accession Numbers and remove NA values
Apul_background <- Apul_background %>% select(V3) %>% na.omit

head(Apul_background)
##        V3
## 25 Q95SX7
## 36 Q96AY4
## 38 Q96AY4
## 39 Q96AY4
## 41 Q96AY4
## 43 Q80XJ3
# Looks good! Save
write.table(
    Apul_background,
    file = file.path(output_dir, "Apul_background_UniprotAccessions.txt"),
    row.names = FALSE,
    col.names = FALSE,
    quote = FALSE
  )

Now we can download these formatted lists of accession numbers and run them through DAVID to obtain lists of associated Uniprot keywords. Unfortunately I don’t think this can be done from command line, so I’ll be using the online tool: https://david.ncifcrf.gov/tools.jsp

I upload my miRNA lists as “Gene Lists” and upload the background list as the “Background”, selecting “UNIPROT_ACCESSION” as the identifier for each. I analyzed each miRNA list using the “Functional Annotation” tool, and downloaded the Functional Annotation Table and Functional Annotation Chart for each (below)

Many of the miRNAs only have a couple of intereacting genes with available annotations, so I’ll focus on the larger modules for now

miRNA_mRNA_count <- pcc_miRanda_sig_FA  %>%
  group_by(miRNA) %>%
  summarise(mRNA_count = n_distinct(mRNA)) %>%
  arrange(desc(mRNA_count))

# View the result
print(miRNA_mRNA_count)
## # A tibble: 44 × 2
##    miRNA         mRNA_count
##    <chr>              <int>
##  1 Cluster_14532        252
##  2 Cluster_4752         129
##  3 Cluster_1865         125
##  4 Cluster_2500          76
##  5 Cluster_2372          71
##  6 Cluster_17245         60
##  7 Cluster_5516          60
##  8 Cluster_3109          47
##  9 Cluster_17623         42
## 10 Cluster_3301          42
## # ℹ 34 more rows
curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736116104887.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_16354_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736116257803.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_16354_FAchart.tab

curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736117285790.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_14532_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736118642554.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_14532_FAchart.tab

curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736117399781.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_4752_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736118277223.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_4752_FAchart.tab

curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736117748893.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_1865_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736118140717.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_1865_FAchart.tab

curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736117835799.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_2500_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736118085470.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_2500_FAchart.tab

curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736118036913.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_2372_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736118001598.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_2372_FAchart.tab

curl https://davidbioinformatics.nih.gov/data/download/tr_273760CB86B81736116422412.txt  > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_17623_FAtable.tab
curl https://davidbioinformatics.nih.gov/data/download/chart_273760CB86B81736116608141.txt > ../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_17623_FAchart.tab

I looked through each of the FA Charts as I generated them, but saw few enriched processes. This is likely due (at least in part) to the small number of genes in each miRNA module. Only 3 miRNAs have more than 100 highly significant interactions, and less than half of those genes of interest are annotated. For example, Cluster 4752 has 129 genes of interest, but only 40 are annotated. Cluster 1865 has 125 genes of interest, with 45 annotated.

Cluster_14532 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_14532_FAchart.tab")
Cluster_4752 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_4752_FAchart.tab")
Cluster_1865 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_1865_FAchart.tab")
Cluster_2500 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_2500_FAchart.tab")
Cluster_2372 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_2372_FAchart.tab")
Cluster_17623 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_17623_FAchart.tab")
Cluster_16354 <- read.delim("../output/13-Apul-miRNA-mRNA-analysis-comparisons/DAVID/Cluster_16354_FAchart.tab")

# Look at enriched processes (I'm going to ignore the protein/structural databases for now)
Cluster_14532 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
##                   Category                                            Term
## 1 UP_KW_MOLECULAR_FUNCTION             KW-0695~RNA-directed DNA polymerase
## 2         GOTERM_MF_DIRECT GO:0003964~RNA-directed DNA polymerase activity
## 3 UP_KW_MOLECULAR_FUNCTION                       KW-0064~Aspartyl protease
## 4         GOTERM_BP_DIRECT                      GO:0015074~DNA integration
## 5 UP_KW_MOLECULAR_FUNCTION                  KW-0548~Nucleotidyltransferase
## 6         GOTERM_MF_DIRECT GO:0004190~aspartic-type endopeptidase activity
## 7 UP_KW_BIOLOGICAL_PROCESS                         KW-0229~DNA integration
## 8 UP_KW_MOLECULAR_FUNCTION             KW-0239~DNA-directed DNA polymerase
## 9 UP_KW_MOLECULAR_FUNCTION                            KW-0255~Endonuclease
Cluster_4752 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
## [1] Category Term    
## <0 rows> (or 0-length row.names)
Cluster_1865 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
##                   Category
## 1             UP_KW_DOMAIN
## 2         GOTERM_BP_DIRECT
## 3             UP_KW_DOMAIN
## 4 UP_KW_CELLULAR_COMPONENT
##                                                              Term
## 1                                     KW-0433~Leucine-rich repeat
## 2 GO:0032731~positive regulation of interleukin-1 beta production
## 3                                                  KW-0677~Repeat
## 4                                               KW-0963~Cytoplasm
Cluster_2500 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
## [1] Category Term    
## <0 rows> (or 0-length row.names)
Cluster_2372 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
##       Category                        Term
## 1 UP_KW_DOMAIN     KW-0245~EGF-like domain
## 2 UP_KW_DOMAIN KW-0433~Leucine-rich repeat
## 3 UP_KW_DOMAIN              KW-0677~Repeat
Cluster_17623 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
## [1] Category Term    
## <0 rows> (or 0-length row.names)
Cluster_16354 %>% filter(Benjamini < 0.05) %>% filter(Category != "INTERPRO") %>% filter(Category != "UP_SEQ_FEATURE") %>% filter(Category != "SMART") %>% select(Category, Term) %>% print()
##                   Category                      Term
## 1 UP_KW_BIOLOGICAL_PROCESS KW-0341~Growth regulation

Cluster 14532 putatively interacts with genes that are enriched for DNA/RNA synthesis, integration, and proteolytic activity, suggesting the miRNA may be primarily involved in maintenance/housekeeping. This is supported by the sheer number of genes it putatively interacts with, since housekeeping genes are plentiful and would be expected to be strongly coexpressed.

Cluster 1865 interacts with genes that are enriched for immune regulation terms, specifically the interleukin-1 beta (IL-1β), a pro-inflammatory cytokine. This suggests Cluster 1865 may play a role in immune response

Cluster 16354 is of particular interest because it’s the only miRNA I identified as differentially expressed over time (note, this may change as i learn how to adjust expression methods for the small number of miRNAs). The set of genes that Cluster 16354 interacts with is enriched for one biological process, Growth Regulation. This suggests Cluster 16354 may be involved in regulating growth in response to environmental signals.

LS0tCnRpdGxlOiAiMTMtQXB1bC1taVJOQS1tUk5BLWFuYWx5c2lzLWNvbXBhcmlzb25zIgphdXRob3I6ICJLYXRobGVlbiBEdXJraW4iCmRhdGU6ICIyMDI0LTEyLTE5IgphbHdheXNfYWxsb3dfaHRtbDogdHJ1ZQpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgZ2l0aHViX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgaHRtbF9wcmV2aWV3OiB0cnVlIAotLS0KCmBgYHtyfQojIGxvYWQgcGFja2FnZXMKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQoKYGBgCgpXaGF0IERFR3MgYXJlIGFsc28gZXhwZWN0ZWQgdG8gaW50ZXJhY3Qgd2l0aCBtaVJOQT8KCgpgYGB7cn0KdHAxLnYudHAyIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvMDMuMDAtRC1BcHVsLVJOQXNlcS1nZW5lLWV4cHJlc3Npb24tREVTZXEyL3RwMS52LnRwMi5yZXN1bHRzLnRhYmxlLmNzdiIpCnRwMS52LnRwMiA8LSByZW5hbWUodHAxLnYudHAyLCAiZ2VuZUlEIiA9ICJYIikKCnRwMS52LnRwMyA8LSByZWFkLmNzdigiLi4vb3V0cHV0LzAzLjAwLUQtQXB1bC1STkFzZXEtZ2VuZS1leHByZXNzaW9uLURFU2VxMi90cDEudi50cDMucmVzdWx0cy50YWJsZS5jc3YiKQp0cDEudi50cDMgPC0gcmVuYW1lKHRwMS52LnRwMywgImdlbmVJRCIgPSAiWCIpCgp0cDEudi50cDQgPC0gcmVhZC5jc3YoIi4uL291dHB1dC8wMy4wMC1ELUFwdWwtUk5Bc2VxLWdlbmUtZXhwcmVzc2lvbi1ERVNlcTIvdHAxLnYudHA0LnJlc3VsdHMudGFibGUuY3N2IikKdHAxLnYudHA0IDwtIHJlbmFtZSh0cDEudi50cDQsICJnZW5lSUQiID0gIlgiKQoKdHAyLnYudHAzIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvMDMuMDAtRC1BcHVsLVJOQXNlcS1nZW5lLWV4cHJlc3Npb24tREVTZXEyL3RwMi52LnRwMy5yZXN1bHRzLnRhYmxlLmNzdiIpCnRwMi52LnRwMyA8LSByZW5hbWUodHAyLnYudHAzLCAiZ2VuZUlEIiA9ICJYIikKCnRwMi52LnRwNCA8LSByZWFkLmNzdigiLi4vb3V0cHV0LzAzLjAwLUQtQXB1bC1STkFzZXEtZ2VuZS1leHByZXNzaW9uLURFU2VxMi90cDIudi50cDQucmVzdWx0cy50YWJsZS5jc3YiKQp0cDIudi50cDQgPC0gcmVuYW1lKHRwMi52LnRwNCwgImdlbmVJRCIgPSAiWCIpCgp0cDMudi50cDQgPC0gcmVhZC5jc3YoIi4uL291dHB1dC8wMy4wMC1ELUFwdWwtUk5Bc2VxLWdlbmUtZXhwcmVzc2lvbi1ERVNlcTIvdHAzLnYudHA0LnJlc3VsdHMudGFibGUuY3N2IikKdHAzLnYudHA0IDwtIHJlbmFtZSh0cDMudi50cDQsICJnZW5lSUQiID0gIlgiKQpgYGAKClRpbWVwb2ludHMgMiB2cyA0IGhhcyB0aGUgbW9zdCBERUdzCgpgYGB7cn0KcGFzdGUoIk9mICIsIG5yb3codHAxLnYudHAyKSwgIiBnZW5lcyIpCnBhc3RlKCIiKQpwYXN0ZSgidHAxIHZzIHRwMjogIiwgbnJvdyhmaWx0ZXIodHAxLnYudHAyLCBwYWRqIDwgMC4wNSkpKQpwYXN0ZSgidHAxIHZzIHRwMzogIiwgbnJvdyhmaWx0ZXIodHAxLnYudHAzLCBwYWRqIDwgMC4wNSkpKQpwYXN0ZSgidHAxIHZzIHRwNDogIiwgbnJvdyhmaWx0ZXIodHAxLnYudHA0LCBwYWRqIDwgMC4wNSkpKQpwYXN0ZSgidHAyIHZzIHRwMzogIiwgbnJvdyhmaWx0ZXIodHAyLnYudHAzLCBwYWRqIDwgMC4wNSkpKQpwYXN0ZSgidHAyIHZzIHRwNDogIiwgbnJvdyhmaWx0ZXIodHAyLnYudHA0LCBwYWRqIDwgMC4wNSkpKQpwYXN0ZSgidHAzIHZzIHRwNDogIiwgbnJvdyhmaWx0ZXIodHAzLnYudHA0LCBwYWRqIDwgMC4wNSkpKQpgYGAKClRoZXNlIERFRyBjb3VudHMgbWFrZSBzZW5zZSB3aXRoIG91ciBQQ0EsIHdoaWNoIHNob3dzIHRpbWVwb2ludHMgMSBhbmQgNCBjbHVzdGVyaW5nIG1vcmUgY2xvc2VseSB0b2dldGhlciwgYW5kIHRpbWVwb2ludHMgMiBhbmQgMyBjbHVzdGVyaW5nIG1vcmUgY2xvc2VseSB0b2dldGhlci4KCgpSZWFkIGluIG1pUmFuZGEgcmVzdWx0cyAobWlSTkFzIGJpbmRpbmcgdG8gM1VUUnMpCgpgYGB7cn0KbWlSYW5kYSA8LSByZWFkLnRhYmxlKCIuLi9vdXRwdXQvMDctQXB1bC1taVJOQS1tUk5BLW1pUmFuZGEvQXB1bC1taVJhbmRhLTNVVFItc3RyaWN0LXBhcnNlZC1nZW5lSURzLnR4dCIsIGhlYWRlciA9IEZBTFNFLCBzZXAgPSAiXHQiKQpgYGAKCkFubm90YXRlIHBhaXJ3aXNlIGNvbXBhcmlzb24gcmVzdWx0cyB3aXRoIHB1dGF0aXZlIG1pUk5BIGludGVyYWN0aW9ucwoKYGBge3J9CiMgU29tZSBVVFJzIGFyZSBhc3NvY2lhdGVkIHdpdGggMiBnZW5lIElEcyAoZHVlIHRvIHRoZSBnZW5lcyBzaXR0aW5nIHZlcnkgY2xvc2UgdG8gZWFjaCBvdGhlcikKIyBFeHBhbmQgdGhvc2UgZ2VuZUlEcyBpbnRvIG11bHRpcGxlIHJvd3MKbWlSYW5kYV9leHBhbmQgPC0gbWlSYW5kYSAlPiUKICBzZXBhcmF0ZV9yb3dzKFYxMCwgc2VwID0gIiwiKSAgIyBTcGxpdCB0aGUgRlVOIGNvbHVtbiBieSBjb21tYXMgaW50byBtdWx0aXBsZSByb3dzCgp0cDEudi50cDIubWlSYW5kYSA8LSBsZWZ0X2pvaW4odHAxLnYudHAyLCBtaVJhbmRhLCBieSA9IGMoImdlbmVJRCIgPSAiVjEwIikpCnRwMS52LnRwMi5taVJhbmRhJFYxIDwtIGdzdWIoIj4iLCAiIiwgdHAxLnYudHAyLm1pUmFuZGEkVjEpCnRwMS52LnRwMi5taVJhbmRhJFYxIDwtIGdzdWIoIlxcLi4qIiwgIiIsIHRwMS52LnRwMi5taVJhbmRhJFYxKQoKdHAxLnYudHAzLm1pUmFuZGEgPC0gbGVmdF9qb2luKHRwMS52LnRwMywgbWlSYW5kYSwgYnkgPSBjKCJnZW5lSUQiID0gIlYxMCIpKQp0cDEudi50cDMubWlSYW5kYSRWMSA8LSBnc3ViKCI+IiwgIiIsIHRwMS52LnRwMy5taVJhbmRhJFYxKQp0cDEudi50cDMubWlSYW5kYSRWMSA8LSBnc3ViKCJcXC4uKiIsICIiLCB0cDEudi50cDMubWlSYW5kYSRWMSkKCnRwMS52LnRwNC5taVJhbmRhIDwtIGxlZnRfam9pbih0cDEudi50cDQsIG1pUmFuZGEsIGJ5ID0gYygiZ2VuZUlEIiA9ICJWMTAiKSkKdHAxLnYudHA0Lm1pUmFuZGEkVjEgPC0gZ3N1YigiPiIsICIiLCB0cDEudi50cDQubWlSYW5kYSRWMSkKdHAxLnYudHA0Lm1pUmFuZGEkVjEgPC0gZ3N1YigiXFwuLioiLCAiIiwgdHAxLnYudHA0Lm1pUmFuZGEkVjEpCgp0cDIudi50cDMubWlSYW5kYSA8LSBsZWZ0X2pvaW4odHAyLnYudHAzLCBtaVJhbmRhLCBieSA9IGMoImdlbmVJRCIgPSAiVjEwIikpCnRwMi52LnRwMy5taVJhbmRhJFYxIDwtIGdzdWIoIj4iLCAiIiwgdHAyLnYudHAzLm1pUmFuZGEkVjEpCnRwMi52LnRwMy5taVJhbmRhJFYxIDwtIGdzdWIoIlxcLi4qIiwgIiIsIHRwMi52LnRwMy5taVJhbmRhJFYxKQoKdHAyLnYudHA0Lm1pUmFuZGEgPC0gbGVmdF9qb2luKHRwMi52LnRwNCwgbWlSYW5kYSwgYnkgPSBjKCJnZW5lSUQiID0gIlYxMCIpKQp0cDIudi50cDQubWlSYW5kYSRWMSA8LSBnc3ViKCI+IiwgIiIsIHRwMi52LnRwNC5taVJhbmRhJFYxKQp0cDIudi50cDQubWlSYW5kYSRWMSA8LSBnc3ViKCJcXC4uKiIsICIiLCB0cDIudi50cDQubWlSYW5kYSRWMSkKCnRwMy52LnRwNC5taVJhbmRhIDwtIGxlZnRfam9pbih0cDMudi50cDQsIG1pUmFuZGEsIGJ5ID0gYygiZ2VuZUlEIiA9ICJWMTAiKSkKdHAzLnYudHA0Lm1pUmFuZGEkVjEgPC0gZ3N1YigiPiIsICIiLCB0cDMudi50cDQubWlSYW5kYSRWMSkKdHAzLnYudHA0Lm1pUmFuZGEkVjEgPC0gZ3N1YigiXFwuLioiLCAiIiwgdHAzLnYudHA0Lm1pUmFuZGEkVjEpCgpgYGAKCktlZXAgaW4gbWluZCB0aGF0LCBzaW5jZSBhbiBtaVJOQSBtYXkgYmUgcHJlZGljdGVkIHRvIGJpbmQgYXQgbXVsdGlwbGUgcGxhY2VzIGluIGEgc2luZ2xlIDNVVFIsIG9yIG11bHRpcGxlIG1pUk5BcyBtYXkgYmUgcHJlZGljdGVkIHRvIGJpbmQgdG8gdGhlIHNhbWUgM1VUUiwgdGhpcyB0YWJsZSBubyBsb25nZXIgY29udGFpbnMgYSBzaW5nbGUgcm93IGZvciBlYWNoIGdlbmUgSUQuIAoKVGhpcyB0YWJsZSBlc3NlbnRpYWxseSBzaG93cyBldmVyeSBtaVJOQS0zVVRSIHByZWRpY3RlZCBpbnRlcmFjdGlvbiBhbmQgdGhlIERFU2VxMiBwYWlyd2lzZSBleHByZXNzaW9uIGNvbXBhcmlzb24gZm9yIHRoZSBnZW5lIGFzc29jaWF0ZWQgd2l0aCB0aGF0IGdlbmUuCgpMZXQncyB0YWtlIGEgbG9vay4gV2UnbGwgZmlsdGVyIHRvIHNpZ25pZmljYW50IERFR3MgKHBhZGogPCAwLjA1KS4gSW4gY25pZGFyaWFucywgbWlSTkEtbVJOQSBiaW5kaW5nIGlzIGJlbGlldmVkIHRvIHJlcXVpcmUgbmVhci1jb21wbGV0ZSBjb21wbGVtZW50YXJpdHkgb2YgdGhlIGZ1bGwgbWF0dXJlIG1pUk5BLCBzaW1pbGFybHkgdG8gcGxhbnRzLCBzbyB3ZSBtYXkgd2FudCB0byBsb29rIGF0IGhvdyBtYW55IHB1dGF0aXZlIGludGVyYWN0aW9ucyBhcmUgcHJlZGljdGVkIGZvciBhIGJpbmRpbmcgbGVuZ3RoIG9mIGF0IGxlYXN0IDIwIG51Y2xlb3RpZGVzICh0aGUgbGVuZ3RoIG9mIG91ciBzbWFsbGVzdCBtYXR1cmUgbWlSTkEgaXMgMjEpIGFuZCA4MCUgYWxpZ25tZW50IHJhdGUgKGFsbG93cyBmb3IgNCBtaXNtYXRjaGVzIGluIGEgMjBicCBhbGlnbm1lbnQpLiBGaW5hbGx5LCB3ZSBzaG91bGQgcmVtb3ZlIHRoZSBkdXBsaWNhdGVzIGNhdXNlZCBieSBhbiBtaVJOQSBwdXRhdGl2ZWx5IGJpbmRpbmcgdG8gbXVsdGlwbGUgcGxhY2VzIGluIHRoZSAzVVRSIC0tIG11bHRpcGxlIHB1dGF0aXZlIGJpbmRpbmcgc2l0ZXMgc3RpbGwgaW5kaWNhdGUgb25lIG1pUk5BLW1STkEgYmluZGluZyBwYWlyLgoKYGBge3J9CnBhc3RlKCJDb2x1bW4gZGVzY3JpcHRpb25zOiIpCnBhc3RlKCJOdW1iZXIgb2YgcHV0YXRpdmUgbWlSTkEtREVHIGludGVyYWN0aW9ucyIpCnBhc3RlKCJOdW1iZXIgb2YgcHV0YXRpdmUgbWlSTkEtREVHIGludGVyYWN0aW9ucyAoYXQgbGVhc3QgMjBicCBiaW5kaW5nKSIpCnBhc3RlKCJOdW1iZXIgb2YgcHV0YXRpdmUgbWlSTkEtREVHIGludGVyYWN0aW9ucyhhdCBsZWFzdCAyMGJwIGJpbmRpbmcsIG1heCA0IG1pc21hdGNoZXMpIikKCnogPC0gZGF0YS5mcmFtZSgKICBwYWlyd2lzZSA9IGMoInRwMV90cDIiLCAidHAxX3RwMyIsICJ0cDFfdHA0IiwgInRwMl90cDMiLCAidHAyX3RwNCIsICJ0cDNfdHA0IiksIAogIG1pUk5BX0RFRyA9IGModHAxLnYudHAyLm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAxLnYudHAzLm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAxLnYudHA0Lm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAyLnYudHAzLm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAyLnYudHA0Lm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAzLnYudHA0Lm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCkpLCAKICBtaVJOQV9ERUdfMjBicCA9IGModHAxLnYudHAyLm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGZpbHRlcihWNyA+IDE5KSAlPiUgZGlzdGluY3QoZ2VuZUlELCBWMSkgJT4lIG5yb3coKSwgCiAgICAgICAgICAgICAgICB0cDEudi50cDMubWlSYW5kYSAlPiUgZmlsdGVyKHBhZGogPCAwLjA1KSAlPiUgZmlsdGVyKFY3ID4gMTkpICU+JSBkaXN0aW5jdChnZW5lSUQsIFYxKSAlPiUgbnJvdygpLCAKICAgICAgICAgICAgICAgIHRwMS52LnRwNC5taVJhbmRhICU+JSBmaWx0ZXIocGFkaiA8IDAuMDUpICU+JSBmaWx0ZXIoVjcgPiAxOSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAyLnYudHAzLm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGZpbHRlcihWNyA+IDE5KSAlPiUgZGlzdGluY3QoZ2VuZUlELCBWMSkgJT4lIG5yb3coKSwgCiAgICAgICAgICAgICAgICB0cDIudi50cDQubWlSYW5kYSAlPiUgZmlsdGVyKHBhZGogPCAwLjA1KSAlPiUgZmlsdGVyKFY3ID4gMTkpICU+JSBkaXN0aW5jdChnZW5lSUQsIFYxKSAlPiUgbnJvdygpLCAKICAgICAgICAgICAgICAgIHRwMy52LnRwNC5taVJhbmRhICU+JSBmaWx0ZXIocGFkaiA8IDAuMDUpICU+JSBmaWx0ZXIoVjcgPiAxOSkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCkpLAogIG1pUk5BX0RFR18yMGJwXzRtaXMgPSBjKHRwMS52LnRwMi5taVJhbmRhICU+JSBmaWx0ZXIocGFkaiA8IDAuMDUpICU+JSBmaWx0ZXIoVjcgPiAxOSkgJT4lIGZpbHRlcihWOCA+IDgwKSAlPiUgZGlzdGluY3QoZ2VuZUlELCBWMSkgJT4lIG5yb3coKSwgCiAgICAgICAgICAgICAgICB0cDEudi50cDMubWlSYW5kYSAlPiUgZmlsdGVyKHBhZGogPCAwLjA1KSAlPiUgZmlsdGVyKFY3ID4gMTkpICU+JSBmaWx0ZXIoVjggPiA4MCkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAxLnYudHA0Lm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGZpbHRlcihWNyA+IDE5KSAlPiUgZmlsdGVyKFY4ID4gODApICU+JSBkaXN0aW5jdChnZW5lSUQsIFYxKSAlPiUgbnJvdygpLCAKICAgICAgICAgICAgICAgIHRwMi52LnRwMy5taVJhbmRhICU+JSBmaWx0ZXIocGFkaiA8IDAuMDUpICU+JSBmaWx0ZXIoVjcgPiAxOSkgJT4lIGZpbHRlcihWOCA+IDgwKSAlPiUgZGlzdGluY3QoZ2VuZUlELCBWMSkgJT4lIG5yb3coKSwgCiAgICAgICAgICAgICAgICB0cDIudi50cDQubWlSYW5kYSAlPiUgZmlsdGVyKHBhZGogPCAwLjA1KSAlPiUgZmlsdGVyKFY3ID4gMTkpICU+JSBmaWx0ZXIoVjggPiA4MCkgJT4lIGRpc3RpbmN0KGdlbmVJRCwgVjEpICU+JSBucm93KCksIAogICAgICAgICAgICAgICAgdHAzLnYudHA0Lm1pUmFuZGEgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lIGZpbHRlcihWNyA+IDE5KSAlPiUgZmlsdGVyKFY4ID4gODApICU+JSBkaXN0aW5jdChnZW5lSUQsIFYxKSAlPiUgbnJvdygpKQopCnoKYGBgCgoKIyBCaW5kaW5nICsgQ29leHByZXNzaW9uIChtaVJhbmRhICsgUGVhcnNvbidzIGNvcnJlbGF0aW9uKQoKSmlsbCB3YXMgYWJsZSB0byBydW4gdGhlIG1pUk5BLWdlbmUgZXhwcmVzc2lvbiBQZWFyc29uJ3MgY29ycmVsYXRpb24gY29kZSAoYDE0LUFwdWwtbWlSTkEtbVJOQS1jb2V4cHJlc3Npb25gKSBmb3IgbWUsIHNvIGxldCdzIGxvb2sgYXQgdGhvc2UgcmVzdWx0cy4KCmBgYHtyfQojIExvYWQgaW4gcmVzdWx0cwpwY2NfbWlSYW5kYV9hbGwgPC0gcmVhZC5jc3YoIi4uL291dHB1dC8xNC1BcHVsLW1pUk5BLW1STkEtY29leHByZXNzaW9uL3BjY19taXJhbmRhX2ludGVyYWN0aW9ucy5jc3YiKSAlPiUgc2VsZWN0KC1YKQpwY2NfbWlSYW5kYV9zaWcgPC0gcmVhZC5jc3YoIi4uL291dHB1dC8xNC1BcHVsLW1pUk5BLW1STkEtY29leHByZXNzaW9uL3BjY19wYWlyc19vZl9pbnRlcmVzdC5jc3YiKSAlPiUgc2VsZWN0KC1YKQoKcGNjX21pUmFuZGFfYWxsICU+JSBmaWx0ZXIocF92YWx1ZSA8IDAuMDUpICU+JSBucm93KCkKcGNjX21pUmFuZGFfYWxsICU+JSBmaWx0ZXIocF92YWx1ZSA8IDAuMDEpICU+JSBucm93KCkKcGNjX21pUmFuZGFfYWxsICU+JSBmaWx0ZXIocF92YWx1ZSA8IDAuMDAxKSAlPiUgbnJvdygpCgpwY2NfbWlSYW5kYV9zaWcgJT4lIG5yb3coKQpwY2NfbWlSYW5kYV9zaWcgJT4lIGZpbHRlcihwX3ZhbHVlIDwgMC4wMDEpICU+JSBucm93KCkKYGBgCgpTbyAxMCw3MTIgcHV0YXRpdmUgbWlSTkEtbVJOQSBpbnRlcmFjdGlvbnMgcHJlZGljdGVkIGJ5IG1pUmFuZGEgYXJlIGFsc28gc2lnbmlmaWNhbnRseSBjb3JyZWxhdGVkIGluIGV4cHJlc3Npb24gd2l0aCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1LiBGb3IgcCA8IDAuMDEsIGV4cHJlc3Npb24gb2YgNCwzMTIgcHV0YXRpdmUgaW50ZXJhY3Rpb25zIGFyZSBzaWduaWZpY2FudGx5IGNvcnJlbGF0ZWQuIEZvciBwIDwgMC4wMDEsIDEsMzQ3IGFyZSBzaWduaWZpY2FudC4gCgpOb3RlIHRoYXQgdGhlICJwY2NfcGFpcnNfb2ZfaW50ZXJlc3QiIGFyZSBpbnRlcmFjdGlvbnMgdGhhdCBhcmUgY29leHByZXNzZWQgd2l0aCBhIGNvcnJlbGF0aW9uIG1hZ25pdHVkZSBvZiBhdCBsZWFzdCAwLjUgYW5kIGEgcCA8IDAuMDUsIGJ1dCB0aGlzIGVuZHMgdXAgYmVpbmcgZXNzZW50aWFsbHkgdGhlIHNhbWUgYXMgYSBwIDwgMC4wMDEgc2lnbmlmaWNhbmNlIGxldmVsLgoKCkl0J3MgYmVsaWV2ZWQgdGhhdCBjbmlkYXJpYW4gbWlSTkFzIGFjdCBtb3JlIGxpa2UgdGhhbiBwbGFudCBtaVJOQXMgdGhhbiBvdGhlciBhbmltYWxzLCByZXF1aXJpbmcgbW9yZSBjb21wbGV0ZSBjb21wbGVtZW50YXJpdHkgb2YgdGhlIGZ1bGwgbWF0dXJlIG1pUk5BIHRvIGJpbmQgKGluIGNvbXBhcmlzb24sIG1vc3QgYW5pbWFsIG1pUk5BcyByZXF1aXJlIG9ubHkgY29tcGxlbWVudGFyaXR5IG9mIHRoZSB+OGJwICJzZWVkIiByZWdpb24pLiBGb3Igb3VyIHB1dGF0aXZlIG1pUk5BLW1STkEgaW50ZXJhY3Rpb25zLCB3aGF0IGlzIHRoZSBkaXN0cmlidXRpb24gb2Ygc2hhcmVkIGJwPwoKYGBge3J9CnBjY19taVJhbmRhX3NpZyAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0b3RhbF9icF9zaGFyZWQpKSArCiAgZ2VvbV9iYXIoZmlsbCA9ICIjNDA4RUM2IiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJBbGlnbm1lbnQgbGVuZ3RocyBvZiBjb2V4cHJlc3NlZCBtaVJOQS1tUk5BIGJpbmRpbmcgcGFpcnMiLCB4ID0gIlRvdGFsIGJwIHNoYXJlZCIsIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgIyBBZGQgdGV4dCBsYWJlbHMgb24gdG9wIG9mIHRoZSBiYXJzCiAgZ2VvbV90ZXh0KHN0YXQgPSAnY291bnQnLCBhZXMobGFiZWwgPSBhZnRlcl9zdGF0KGNvdW50KSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiYmxhY2siKSAgIyB2anVzdCB0byBhZGp1c3QgdGhlIHBvc2l0aW9uCmBgYAoKSW50ZXJlc3RpbmchIEkgc2VlIHR3byAic3Bpa2VzIi4gVGhlIDctOGJwIHNwaWtlIGNvdWxkIGluZGljYXRlIHNlZWQgYmluZGluZywgYW5kIHRoZSAxNi0yMmJwIGh1bXAgY291bGQgcmVwcmVzZW50IHRoZSBmdWxsIG1hdHVyZSBtaVJOQSBjb21wbGVtZW50YXJpdHkgZXhwZWN0ZWQgZm9yIGNuaWRhcmlhbnMuIE5vdCBzdXJlIGFib3V0IHRoZSBtaWRkbGUgc3R1ZmYgdGhvdWdoICg5LTE1YnApLiBJJywgYWxzbyBub3Qgc3VyZSB3aHkgdGhlcmUgYXJlIGNvdW50cyBhYm92ZSAyNGJwLCBzaW5jZSB0aGF0J3MgdGhlIGxlbmd0aCBvZiBvdXIgbG9uZ2VzdCBtaVJOQS4uLgoKCkhvdyBtYW55IG9mIHRoZXNlIGhpZ2hseSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbnMgYXJlIHVuaXF1ZSAoYSBnZW5lIGludGVyYWN0cyB3aXRoIG9ubHkgb25lIG1pUk5BKSB2cyBzaGFyZWQgKGEgZ2VuZSBpbnRlcmFjdHMgd2l0aCBtdWx0aXBsZSBtaVJOQSk/CgoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQWRkIGEgY29sdW1uIHdpdGggdGhlIG51bWJlciBvZiBhcHBlYXJhbmNlcyBvZiBlYWNoIG1STkEKcGNjX21pUmFuZGFfc2lnIDwtIHBjY19taVJhbmRhX3NpZyAlPiUKICBtdXRhdGUobVJOQV9udW1faW50ZXJhY3Rpb24gPSBhdmUobVJOQSwgbVJOQSwgRlVOID0gbGVuZ3RoKSkKCiMgRmlsdGVyIHRvIHVuaXF1ZSBtUk5BcyBhbmQgcGxvdCBoaXN0b2dyYW0gb2YgdGhlaXIgbnVtYmVyIG9mIGFwcGVhcmFuY2VzCnBjY19taVJhbmRhX3NpZyAlPiUKICBkaXN0aW5jdChtUk5BLCBtUk5BX251bV9pbnRlcmFjdGlvbikgJT4lICAjIEtlZXAgb25seSB1bmlxdWUgbVJOQSByb3dzCiAgZ2dwbG90KGFlcyh4ID0gbVJOQV9udW1faW50ZXJhY3Rpb24pKSArCiAgZ2VvbV9iYXIoZmlsbCA9ICIjNDA4RUM2IiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicygKICAgIHRpdGxlID0gIk51bWJlciBvZiBkaXN0aW5jdCBwdXRhdGl2ZSBpbnRlcmFjdGlvbnMgcGVyIGdlbmUiLAogICAgeCA9ICJJbnRlcmFjdGluZyBtaVJOQXMiLAogICAgeSA9ICJGcmVxdWVuY3kiCiAgKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICAjIEFkZCB0ZXh0IGxhYmVscyBvbiB0b3Agb2YgdGhlIGJhcnMKICBnZW9tX3RleHQoc3RhdCA9ICdjb3VudCcsIGFlcyhsYWJlbCA9IGFmdGVyX3N0YXQoY291bnQpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJibGFjayIpCgoKYGBgCgpTbyBtaVJOQS1tUk5BIGludGVyYWN0aW9uIGlzIGxhcmdlbHkgZGlzY3JldGUsIHdpdGggZXhwcmVzc2lvbiBvZiBhIGdpdmVuIGdlbmUgaW5mbHVlbmNlZCBieSBqdXN0IG9uZSBvciB0d28gbWlSTkEKCgpIb3cgbWFueSBnZW5lcyBkb2VzIGVhY2ggbWlSTkEgaW50ZXJhY3Qgd2l0aD8KCmBgYHtyfQojIENvdW50IHRoZSBudW1iZXIgb2YgZGlzdGluY3QgbVJOQXMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggbWlSTkEKbWlSTkFfbVJOQV9jb3VudCA8LSBwY2NfbWlSYW5kYV9zaWcgJT4lCiAgZ3JvdXBfYnkobWlSTkEpICU+JQogIHN1bW1hcmlzZShtUk5BX2NvdW50ID0gbl9kaXN0aW5jdChtUk5BKSkgJT4lCiAgdW5ncm91cCgpCgojIE9yZGVyIG1pUk5BcyBmcm9tIGxhcmdlc3QgdG8gc21hbGxlc3QgYnkgbVJOQSBjb3VudAptaVJOQV9tUk5BX2NvdW50JG1pUk5BIDwtIHJlb3JkZXIobWlSTkFfbVJOQV9jb3VudCRtaVJOQSwgLW1pUk5BX21STkFfY291bnQkbVJOQV9jb3VudCkKCiMgUGxvdCBiYXIgcGxvdCB3aXRoIGFsbCBiYXJzIHRoZSBzYW1lIGNvbG9yCmdncGxvdChtaVJOQV9tUk5BX2NvdW50LCBhZXMoeCA9IG1pUk5BLCB5ID0gbVJOQV9jb3VudCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjNDA4RUM2IiwgY29sb3IgPSAiYmxhY2siKSArICAjIFNldCBhbGwgYmFycyB0byB0aGUgc2FtZSBjb2xvcgogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIGdlbmVzIHB1dGF0aXZlbHkgaW50ZXJhY3Rpbmcgd2l0aCBlYWNoIG1pUk5BIiwKICAgICAgIHggPSAibWlSTkEiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgbVJOQXMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgcmVhZGFiaWxpdHkKCgpgYGAKCgojIEZ1bmN0aW9uYWwgQW5ub3RhdGlvbiBvZiBiaW5kaW5nL2NvZXhwcmVzc2VkIGdlbmVzCgpUbyBnZXQgYW4gaWRlYSBvZiBtaVJOQSBmdW5jdGlvbiwgbGV0J3MgZnVuY3Rpb25hbGx5IGFubm90YXRlIGFsbCBvZiB0aGUgc2lnbmlmaWNhbnRseSBjb2V4cHJlc3NlZCBnZW5lcy4KCkdlbmVyYXRpb24gb2YgVW5pcHJvdC9Td2lzc3Byb3QgR08gYW5ub3RhdGlvbiB0YWJsZSBmb3IgdGhlIEEucHVsY2hyYSBnZW5vbWUgY2FuIGJlIGZvdW5kIGluIFtgZGVlcC1kaXZlLWV4cHJlc3Npb24vRC1BcHVsL2NvZGUvMDItQXB1bC1yZWZlcmVuY2UtYW5ub3RhdGlvbmBdKGh0dHBzOi8vZ2l0aHViLmNvbS91cm9sLWU1L2RlZXAtZGl2ZS1leHByZXNzaW9uL3RyZWUvbWFpbi9ELUFwdWwvY29kZS8wMi1BcHVsLXJlZmVyZW5jZS1hbm5vdGF0aW9uLlJtZCkuIEFsc28gYXNzb2NpYXRlZCBhbGwgQS5wdWxjaHJhIG1STkFzIHdpdGggdGhlaXIgcmVzcGVjdGl2ZSBnZW5lIElEcyBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlLWV4cHJlc3Npb24vYmxvYi9tYWluL0QtQXB1bC9jb2RlLzE1LUFwdWwtYW5ub3RhdGUtVVRScy5SbWQpCgpgYGB7cn0KIyBMb2FkIEZBIHRhYmxlCkFwdWxfRkFfdGFibGUgPC0gcmVhZC5kZWxpbSgiaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlLWV4cHJlc3Npb24vcmF3L3JlZnMvaGVhZHMvbWFpbi9ELUFwdWwvb3V0cHV0LzAyLUFwdWwtcmVmZXJlbmNlLWFubm90YXRpb24vQXB1bGNyYS1nZW5vbWUtbVJOQS1JRG1hcHBpbmctMjAyNF8xMl8xMi50YWIiKSAlPiUgc2VsZWN0KC1YKQoKIyBOb3Qgc3VyZSB3aHkgYnV0IHNvbWUgb2YgdGhlc2Ugcm93cyBhcmUgZHVwbGljYXRlcwojIFJlbW92ZSBkdXBsaWNhdGUgcm93cyAobXVzdCBoYXZlIHNhbWUgZ2Vub21pYyBsb2NhdGlvbiAqYW5kKiBmdW5jdGlvbmFsIGFubm90YXRpb24pCkFwdWxfRkFfdGFibGUgPC0gQXB1bF9GQV90YWJsZSAlPiUKICBkaXN0aW5jdChWMSwgVjMsIC5rZWVwX2FsbCA9IFRSVUUpCgojIExvYWQgdGFibGUgYXNzb2NpYXRpbmcgZWFjaCBtUk5BIHdpdGggYSBnZW5lIElECkFwdWxfZ2VuZUlEc190YWJsZSA8LSByZWFkLmRlbGltKCJodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUtZXhwcmVzc2lvbi9yYXcvcmVmcy9oZWFkcy9tYWluL0QtQXB1bC9vdXRwdXQvMTUtQXB1bC1hbm5vdGF0ZS1VVFJzL0FwdWwtbVJOQS1GVU5pZHMudHh0IiwgaGVhZGVyID0gRkFMU0UpCgpoZWFkKEFwdWxfRkFfdGFibGUpCmhlYWQoQXB1bF9nZW5lSURzX3RhYmxlKQpgYGAKCkFubm90YXRlIEZBIHRhYmxlIHdpdGggZ2VuZSBJRHMKYGBge3J9CkFwdWxfRkFfdGFibGUgPC0gbGVmdF9qb2luKEFwdWxfRkFfdGFibGUsIHNlbGVjdChBcHVsX2dlbmVJRHNfdGFibGUsIFYxLCBWNCksIGJ5ID0gYygiVjEiID0gIlYxIikpCgojIEVuc3VyZSB3ZSdyZSBub3QgbWlzc2luZyBnZW5lIElEcyBmb3IgYW55IG1STkFzCmFueShpcy5uYShBcHVsX0ZBX3RhYmxlJFY0KSkKCiMgUmVtb3ZlIHRoZSAiUGFyZW50PSIgYmVmb3JlIGV2ZXJ5IGdlbmUgSUQKQXB1bF9GQV90YWJsZSRWNCA8LSBnc3ViKCJQYXJlbnQ9IiwgIiIsIEFwdWxfRkFfdGFibGUkVjQpCmBgYAoKT2ssIG5vdyB0aGF0IHdlIGNhbiBhc3NvY2lhdGUgZXZlcnkgZ2VuZSBJRCB3aXRoIGl0J3MgR08gdGVybXMgYW5kIGJpb2xvZ2ljYWwgcHJvY2Vzc2VzLCBsZXQncyBzZWUgd2hhdCB0ZXJtcyBzaG93IHVwIGluIG91ciBtaVJOQS1tUk5BIHNpZ25pZmljYW50IGludGVyYWN0aW9ucyEKCmBgYHtyfQpwY2NfbWlSYW5kYV9zaWdfRkEgPC0gbGVmdF9qb2luKHBjY19taVJhbmRhX3NpZywgQXB1bF9GQV90YWJsZSwgYnkgPSBjKCJtUk5BIiA9ICJWNCIpKQpgYGAKCgoKVG8gZGV0ZXJtaW5lIHdoZXRoZXIgY2VydGFpbiBiaW9sb2dpY2FsIHByb2Nlc3NlcyBhcmUgc2lnbmlmY2FudGx5IGFzc29jaWF0ZWQgd2l0aCBhbiBtaVJOQSwgd2UgY2FuIHJ1biBmdW5jdGlvbmFsICplbnJpY2htZW50Ki4gVGhpcyBlbnRhaWxzIHRha2luZyBhbGwgb2YgdGhlIGZ1bmN0aW9uYWwgYW5ub3RhdGlvbnMgYXNzb2NpYXRlZCB3aXRoIGEgZ2l2ZW4gbWlSTkEgYW5kIGNvbXBhcmluZyB0aGVtIHRvIHRoZSAiYmFja2dyb3VuZCIgKGZ1bmN0aW9uYWwgYW5ub3RhdGlvbnMgZm9yIGV2ZXJ5IGdlbmUgcHJlc2VudCBpbiBvdXIgc2FtcGxlcykgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYW55IGZ1bmN0aW9ucyBhcHBlYXIgbW9yZSB0aGFuIGV4cGVjdGVkLiAKCkZvciBlYWNoIG1pUk5BLCBleHRyYWN0IHRoZSBmdW5jdGlvbmFsIGFubm90YXRpb24gZm9yIGV2ZXJ5IGdlbmUgaXQgc2lnbmlmaWNhbnRseSBpbnRlcmFjdHMgd2l0aC4gU3BlY2lmaWNhbGx5IHdlIHdhbnQgdGhlIFVuaXByb3QgQWNjZXNzaW9uIG51bWJlci4KCmBgYHtyfQoKIyBDcmVhdGUgdGhlIG91dHB1dCBkaXJlY3RvcnkgKGlmIGl0IGRvZXNuJ3QgYWxyZWFkeSBleGlzdCkKb3V0cHV0X2RpciA8LSAiLi4vb3V0cHV0LzEzLUFwdWwtbWlSTkEtbVJOQS1hbmFseXNpcy1jb21wYXJpc29ucyIKaWYgKCFkaXIuZXhpc3RzKG91dHB1dF9kaXIpKSB7CiAgZGlyLmNyZWF0ZShvdXRwdXRfZGlyKQp9CgojIExvb3AgdGhyb3VnaCBlYWNoIHVuaXF1ZSBtaVJOQQp1bmlxdWVfbWlSTkFzIDwtIHVuaXF1ZShwY2NfbWlSYW5kYV9zaWdfRkEkbWlSTkEpCgpmb3IgKG1pUk5BIGluIHVuaXF1ZV9taVJOQXMpIHsKICAjIEZpbHRlciByb3dzIGZvciB0aGUgY3VycmVudCBtaVJOQQogIG1pUk5BX2RhdGEgPC0gcGNjX21pUmFuZGFfc2lnX0ZBICU+JQogICAgZmlsdGVyKG1pUk5BID09ICEhbWlSTkEpICU+JQogICAgZmlsdGVyKCFpcy5uYShWMykpICU+JSAjIFJlbW92ZSByb3dzIHdpdGggTkEgdmFsdWVzCiAgICBzZWxlY3QoVjMpCiAgCiAgIyBTYXZlIHRoZSBBY2Nlc3Npb24gTnVtYmVycyB0byBhIENTViBmaWxlCiAgd3JpdGUudGFibGUoCiAgICBtaVJOQV9kYXRhLAogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCBwYXN0ZTAobWlSTkEsICJfVW5pcHJvdEFjY2Vzc2lvbnMudHh0IikpLAogICAgcm93Lm5hbWVzID0gRkFMU0UsCiAgICBjb2wubmFtZXMgPSBGQUxTRSwKICAgIHF1b3RlID0gRkFMU0UKICApCn0KCiMgQ29uZmlybWF0aW9uIG1lc3NhZ2UKY2F0KCJGaWxlcyBzYXZlZCBpbiIsIG91dHB1dF9kaXIpCgpgYGAKCldlIGFsc28gd2FudCB0byBnZXQgYSBsaXN0IG9mIFVuaXByb3QgQWNjZXNzaW9uIG51bWJlcnMgZm9yIG91ciDigJxiYWNrZ3JvdW5k4oCdLiBUaGlzIGlzIGEgcmVmZXJlbmNlIG9mIGFsbCBleHByZXNzZWQgZ2VuZXMgd2Ugd291bGQgZXhwZWN0IHRvIGZpbmQgaW4gb3VyIHNhbXBsZXMuIFdlIGNvdWxkIGp1c3QgdXNlIElEcyBmcm9tIG91ciBmdWxsIHJlZmVyZW5jZSwgYnV0IHRoaXMgbWF5IGluY2x1ZGUgZ2VuZXMgd2UgbWF5IG5vdCBhY3R1YWxseSBleHBlY3QgdG8gZmluZCBpbiBvdXIgc2FtcGxlcyAoZS5nLiBnZW5lcyByZWxhdGVkIHRvIGxhcnZhbCBkZXZlbG9wbWVudCkuIFdlIHNob3VsZCBmaWx0ZXIgdG8ga2VlcCBvbmx5IGdlbmVzIHByZXNlbnQgaW4gYXQgbGVhc3Qgb25lIG9mIG91ciBzYW1wbGVzLgoKYGBge3J9CiMgTG9hZCBpbiBBcHVsIFJOQSByYXcgY291bnRzIG1hdHJpeApBcHVsX3Jhd19STkFfY291bnRzIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvMDIuMjAtRC1BcHVsLVJOQXNlcS1hbGlnbm1lbnQtSGlTYXQyL2FwdWwtZ2VuZV9jb3VudF9tYXRyaXguY3N2Iiwgcm93Lm5hbWVzID0gImdlbmVfaWQiKQoKIyBGaWx0ZXIgdG8ga2VlcCBvbmx5IGdlbmVzIHByZXNlbnQgaW4gYXQgbGVhc3QgMSBzYW1wbGUKQXB1bF9yYXdfUk5BX2NvdW50c19wcmVzZW50IDwtIEFwdWxfcmF3X1JOQV9jb3VudHNbcm93U3VtcyhBcHVsX3Jhd19STkFfY291bnRzKSAhPSAwLCBdCgpBcHVsX3Jhd19STkFfY291bnRzX3ByZXNlbnQkZ2VuZV9pZCA8LSByb3duYW1lcyhBcHVsX3Jhd19STkFfY291bnRzX3ByZXNlbnQpCgojIEpvaW4gd2l0aCBGQSB0YWJsZSB0byBnZXQgQWNjZXNzaW9uIG51bWJlcnMgb2YgZXhwcmVzc2VkIGdlbmVzCkFwdWxfYmFja2dyb3VuZCA8LSBsZWZ0X2pvaW4oQXB1bF9yYXdfUk5BX2NvdW50c19wcmVzZW50LCBBcHVsX0ZBX3RhYmxlLCBieSA9IGMoImdlbmVfaWQiID0gIlY0IikpIAoKIyBTZWxlY3QgdGhlIGNvbHVtbiBvZiBVbmlwcm90IEFjY2Vzc2lvbiBOdW1iZXJzIGFuZCByZW1vdmUgTkEgdmFsdWVzCkFwdWxfYmFja2dyb3VuZCA8LSBBcHVsX2JhY2tncm91bmQgJT4lIHNlbGVjdChWMykgJT4lIG5hLm9taXQKCmhlYWQoQXB1bF9iYWNrZ3JvdW5kKQoKIyBMb29rcyBnb29kISBTYXZlCndyaXRlLnRhYmxlKAogICAgQXB1bF9iYWNrZ3JvdW5kLAogICAgZmlsZSA9IGZpbGUucGF0aChvdXRwdXRfZGlyLCAiQXB1bF9iYWNrZ3JvdW5kX1VuaXByb3RBY2Nlc3Npb25zLnR4dCIpLAogICAgcm93Lm5hbWVzID0gRkFMU0UsCiAgICBjb2wubmFtZXMgPSBGQUxTRSwKICAgIHF1b3RlID0gRkFMU0UKICApCmBgYAoKTm93IHdlIGNhbiBkb3dubG9hZCB0aGVzZSBmb3JtYXR0ZWQgbGlzdHMgb2YgYWNjZXNzaW9uIG51bWJlcnMgYW5kIHJ1biB0aGVtIHRocm91Z2ggREFWSUQgdG8gb2J0YWluIGxpc3RzIG9mIGFzc29jaWF0ZWQgVW5pcHJvdCBrZXl3b3Jkcy4gVW5mb3J0dW5hdGVseSBJIGRvbuKAmXQgdGhpbmsgdGhpcyBjYW4gYmUgZG9uZSBmcm9tIGNvbW1hbmQgbGluZSwgc28gSeKAmWxsIGJlIHVzaW5nIHRoZSBvbmxpbmUgdG9vbDogaHR0cHM6Ly9kYXZpZC5uY2lmY3JmLmdvdi90b29scy5qc3AKCkkgdXBsb2FkIG15IG1pUk5BIGxpc3RzIGFzIOKAnEdlbmUgTGlzdHPigJ0gYW5kIHVwbG9hZCB0aGUgYmFja2dyb3VuZCBsaXN0IGFzIHRoZSDigJxCYWNrZ3JvdW5k4oCdLCBzZWxlY3Rpbmcg4oCcVU5JUFJPVF9BQ0NFU1NJT07igJ0gYXMgdGhlIGlkZW50aWZpZXIgZm9yIGVhY2guIEkgYW5hbHl6ZWQgZWFjaCBtaVJOQSBsaXN0IHVzaW5nIHRoZSDigJxGdW5jdGlvbmFsIEFubm90YXRpb27igJ0gdG9vbCwgYW5kIGRvd25sb2FkZWQgdGhlIEZ1bmN0aW9uYWwgQW5ub3RhdGlvbiBUYWJsZSBhbmQgRnVuY3Rpb25hbCBBbm5vdGF0aW9uIENoYXJ0IGZvciBlYWNoIChiZWxvdykKCk1hbnkgb2YgdGhlIG1pUk5BcyBvbmx5IGhhdmUgYSBjb3VwbGUgb2YgaW50ZXJlYWN0aW5nIGdlbmVzIHdpdGggYXZhaWxhYmxlIGFubm90YXRpb25zLCBzbyBJJ2xsIGZvY3VzIG9uIHRoZSBsYXJnZXIgbW9kdWxlcyBmb3Igbm93CgpgYGB7cn0KbWlSTkFfbVJOQV9jb3VudCA8LSBwY2NfbWlSYW5kYV9zaWdfRkEgICU+JQogIGdyb3VwX2J5KG1pUk5BKSAlPiUKICBzdW1tYXJpc2UobVJOQV9jb3VudCA9IG5fZGlzdGluY3QobVJOQSkpICU+JQogIGFycmFuZ2UoZGVzYyhtUk5BX2NvdW50KSkKCiMgVmlldyB0aGUgcmVzdWx0CnByaW50KG1pUk5BX21STkFfY291bnQpCmBgYAoKCmBgYHtyLCBlbmdpbmU9J2Jhc2gnLCBldmFsID0gRkFMU0V9CmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC90cl8yNzM3NjBDQjg2QjgxNzM2MTE2MTA0ODg3LnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8xNjM1NF9GQXRhYmxlLnRhYgpjdXJsIGh0dHBzOi8vZGF2aWRiaW9pbmZvcm1hdGljcy5uaWguZ292L2RhdGEvZG93bmxvYWQvY2hhcnRfMjczNzYwQ0I4NkI4MTczNjExNjI1NzgwMy50eHQgPiAuLi9vdXRwdXQvMTMtQXB1bC1taVJOQS1tUk5BLWFuYWx5c2lzLWNvbXBhcmlzb25zL0RBVklEL0NsdXN0ZXJfMTYzNTRfRkFjaGFydC50YWIKCmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC90cl8yNzM3NjBDQjg2QjgxNzM2MTE3Mjg1NzkwLnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8xNDUzMl9GQXRhYmxlLnRhYgpjdXJsIGh0dHBzOi8vZGF2aWRiaW9pbmZvcm1hdGljcy5uaWguZ292L2RhdGEvZG93bmxvYWQvY2hhcnRfMjczNzYwQ0I4NkI4MTczNjExODY0MjU1NC50eHQgPiAuLi9vdXRwdXQvMTMtQXB1bC1taVJOQS1tUk5BLWFuYWx5c2lzLWNvbXBhcmlzb25zL0RBVklEL0NsdXN0ZXJfMTQ1MzJfRkFjaGFydC50YWIKCmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC90cl8yNzM3NjBDQjg2QjgxNzM2MTE3Mzk5NzgxLnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl80NzUyX0ZBdGFibGUudGFiCmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC9jaGFydF8yNzM3NjBDQjg2QjgxNzM2MTE4Mjc3MjIzLnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl80NzUyX0ZBY2hhcnQudGFiCgpjdXJsIGh0dHBzOi8vZGF2aWRiaW9pbmZvcm1hdGljcy5uaWguZ292L2RhdGEvZG93bmxvYWQvdHJfMjczNzYwQ0I4NkI4MTczNjExNzc0ODg5My50eHQgPiAuLi9vdXRwdXQvMTMtQXB1bC1taVJOQS1tUk5BLWFuYWx5c2lzLWNvbXBhcmlzb25zL0RBVklEL0NsdXN0ZXJfMTg2NV9GQXRhYmxlLnRhYgpjdXJsIGh0dHBzOi8vZGF2aWRiaW9pbmZvcm1hdGljcy5uaWguZ292L2RhdGEvZG93bmxvYWQvY2hhcnRfMjczNzYwQ0I4NkI4MTczNjExODE0MDcxNy50eHQgPiAuLi9vdXRwdXQvMTMtQXB1bC1taVJOQS1tUk5BLWFuYWx5c2lzLWNvbXBhcmlzb25zL0RBVklEL0NsdXN0ZXJfMTg2NV9GQWNoYXJ0LnRhYgoKY3VybCBodHRwczovL2RhdmlkYmlvaW5mb3JtYXRpY3MubmloLmdvdi9kYXRhL2Rvd25sb2FkL3RyXzI3Mzc2MENCODZCODE3MzYxMTc4MzU3OTkudHh0ID4gLi4vb3V0cHV0LzEzLUFwdWwtbWlSTkEtbVJOQS1hbmFseXNpcy1jb21wYXJpc29ucy9EQVZJRC9DbHVzdGVyXzI1MDBfRkF0YWJsZS50YWIKY3VybCBodHRwczovL2RhdmlkYmlvaW5mb3JtYXRpY3MubmloLmdvdi9kYXRhL2Rvd25sb2FkL2NoYXJ0XzI3Mzc2MENCODZCODE3MzYxMTgwODU0NzAudHh0ID4gLi4vb3V0cHV0LzEzLUFwdWwtbWlSTkEtbVJOQS1hbmFseXNpcy1jb21wYXJpc29ucy9EQVZJRC9DbHVzdGVyXzI1MDBfRkFjaGFydC50YWIKCmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC90cl8yNzM3NjBDQjg2QjgxNzM2MTE4MDM2OTEzLnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8yMzcyX0ZBdGFibGUudGFiCmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC9jaGFydF8yNzM3NjBDQjg2QjgxNzM2MTE4MDAxNTk4LnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8yMzcyX0ZBY2hhcnQudGFiCgpjdXJsIGh0dHBzOi8vZGF2aWRiaW9pbmZvcm1hdGljcy5uaWguZ292L2RhdGEvZG93bmxvYWQvdHJfMjczNzYwQ0I4NkI4MTczNjExNjQyMjQxMi50eHQgID4gLi4vb3V0cHV0LzEzLUFwdWwtbWlSTkEtbVJOQS1hbmFseXNpcy1jb21wYXJpc29ucy9EQVZJRC9DbHVzdGVyXzE3NjIzX0ZBdGFibGUudGFiCmN1cmwgaHR0cHM6Ly9kYXZpZGJpb2luZm9ybWF0aWNzLm5paC5nb3YvZGF0YS9kb3dubG9hZC9jaGFydF8yNzM3NjBDQjg2QjgxNzM2MTE2NjA4MTQxLnR4dCA+IC4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8xNzYyM19GQWNoYXJ0LnRhYgoKYGBgCgpJIGxvb2tlZCB0aHJvdWdoIGVhY2ggb2YgdGhlIEZBIENoYXJ0cyBhcyBJIGdlbmVyYXRlZCB0aGVtLCBidXQgc2F3IGZldyBlbnJpY2hlZCBwcm9jZXNzZXMuIFRoaXMgaXMgbGlrZWx5IGR1ZSAoYXQgbGVhc3QgaW4gcGFydCkgdG8gdGhlIHNtYWxsIG51bWJlciBvZiBnZW5lcyBpbiBlYWNoIG1pUk5BIG1vZHVsZS4gT25seSAzIG1pUk5BcyBoYXZlIG1vcmUgdGhhbiAxMDAgaGlnaGx5IHNpZ25pZmljYW50IGludGVyYWN0aW9ucywgYW5kIGxlc3MgdGhhbiBoYWxmIG9mIHRob3NlIGdlbmVzIG9mIGludGVyZXN0IGFyZSBhbm5vdGF0ZWQuIEZvciBleGFtcGxlLCBDbHVzdGVyIDQ3NTIgaGFzIDEyOSBnZW5lcyBvZiBpbnRlcmVzdCwgYnV0IG9ubHkgNDAgYXJlIGFubm90YXRlZC4gQ2x1c3RlciAxODY1IGhhcyAxMjUgZ2VuZXMgb2YgaW50ZXJlc3QsIHdpdGggNDUgYW5ub3RhdGVkLgoKYGBge3J9CkNsdXN0ZXJfMTQ1MzIgPC0gcmVhZC5kZWxpbSgiLi4vb3V0cHV0LzEzLUFwdWwtbWlSTkEtbVJOQS1hbmFseXNpcy1jb21wYXJpc29ucy9EQVZJRC9DbHVzdGVyXzE0NTMyX0ZBY2hhcnQudGFiIikKQ2x1c3Rlcl80NzUyIDwtIHJlYWQuZGVsaW0oIi4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl80NzUyX0ZBY2hhcnQudGFiIikKQ2x1c3Rlcl8xODY1IDwtIHJlYWQuZGVsaW0oIi4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8xODY1X0ZBY2hhcnQudGFiIikKQ2x1c3Rlcl8yNTAwIDwtIHJlYWQuZGVsaW0oIi4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8yNTAwX0ZBY2hhcnQudGFiIikKQ2x1c3Rlcl8yMzcyIDwtIHJlYWQuZGVsaW0oIi4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8yMzcyX0ZBY2hhcnQudGFiIikKQ2x1c3Rlcl8xNzYyMyA8LSByZWFkLmRlbGltKCIuLi9vdXRwdXQvMTMtQXB1bC1taVJOQS1tUk5BLWFuYWx5c2lzLWNvbXBhcmlzb25zL0RBVklEL0NsdXN0ZXJfMTc2MjNfRkFjaGFydC50YWIiKQpDbHVzdGVyXzE2MzU0IDwtIHJlYWQuZGVsaW0oIi4uL291dHB1dC8xMy1BcHVsLW1pUk5BLW1STkEtYW5hbHlzaXMtY29tcGFyaXNvbnMvREFWSUQvQ2x1c3Rlcl8xNjM1NF9GQWNoYXJ0LnRhYiIpCgojIExvb2sgYXQgZW5yaWNoZWQgcHJvY2Vzc2VzIChJJ20gZ29pbmcgdG8gaWdub3JlIHRoZSBwcm90ZWluL3N0cnVjdHVyYWwgZGF0YWJhc2VzIGZvciBub3cpCkNsdXN0ZXJfMTQ1MzIgJT4lIGZpbHRlcihCZW5qYW1pbmkgPCAwLjA1KSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJJTlRFUlBSTyIpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIlVQX1NFUV9GRUFUVVJFIikgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiU01BUlQiKSAlPiUgc2VsZWN0KENhdGVnb3J5LCBUZXJtKSAlPiUgcHJpbnQoKQpDbHVzdGVyXzQ3NTIgJT4lIGZpbHRlcihCZW5qYW1pbmkgPCAwLjA1KSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJJTlRFUlBSTyIpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIlVQX1NFUV9GRUFUVVJFIikgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiU01BUlQiKSAlPiUgc2VsZWN0KENhdGVnb3J5LCBUZXJtKSAlPiUgcHJpbnQoKQpDbHVzdGVyXzE4NjUgJT4lIGZpbHRlcihCZW5qYW1pbmkgPCAwLjA1KSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJJTlRFUlBSTyIpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIlVQX1NFUV9GRUFUVVJFIikgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiU01BUlQiKSAlPiUgc2VsZWN0KENhdGVnb3J5LCBUZXJtKSAlPiUgcHJpbnQoKQpDbHVzdGVyXzI1MDAgJT4lIGZpbHRlcihCZW5qYW1pbmkgPCAwLjA1KSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJJTlRFUlBSTyIpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIlVQX1NFUV9GRUFUVVJFIikgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiU01BUlQiKSAlPiUgc2VsZWN0KENhdGVnb3J5LCBUZXJtKSAlPiUgcHJpbnQoKQpDbHVzdGVyXzIzNzIgJT4lIGZpbHRlcihCZW5qYW1pbmkgPCAwLjA1KSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJJTlRFUlBSTyIpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIlVQX1NFUV9GRUFUVVJFIikgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiU01BUlQiKSAlPiUgc2VsZWN0KENhdGVnb3J5LCBUZXJtKSAlPiUgcHJpbnQoKQpDbHVzdGVyXzE3NjIzICU+JSBmaWx0ZXIoQmVuamFtaW5pIDwgMC4wNSkgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiSU5URVJQUk8iKSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJVUF9TRVFfRkVBVFVSRSIpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIlNNQVJUIikgJT4lIHNlbGVjdChDYXRlZ29yeSwgVGVybSkgJT4lIHByaW50KCkKQ2x1c3Rlcl8xNjM1NCAlPiUgZmlsdGVyKEJlbmphbWluaSA8IDAuMDUpICU+JSBmaWx0ZXIoQ2F0ZWdvcnkgIT0gIklOVEVSUFJPIikgJT4lIGZpbHRlcihDYXRlZ29yeSAhPSAiVVBfU0VRX0ZFQVRVUkUiKSAlPiUgZmlsdGVyKENhdGVnb3J5ICE9ICJTTUFSVCIpICU+JSBzZWxlY3QoQ2F0ZWdvcnksIFRlcm0pICU+JSBwcmludCgpCmBgYAoKQ2x1c3RlciAxNDUzMiBwdXRhdGl2ZWx5IGludGVyYWN0cyB3aXRoIGdlbmVzIHRoYXQgYXJlIGVucmljaGVkIGZvciBETkEvUk5BIHN5bnRoZXNpcywgaW50ZWdyYXRpb24sIGFuZCBwcm90ZW9seXRpYyBhY3Rpdml0eSwgc3VnZ2VzdGluZyB0aGUgbWlSTkEgbWF5IGJlIHByaW1hcmlseSBpbnZvbHZlZCBpbiBtYWludGVuYW5jZS9ob3VzZWtlZXBpbmcuIFRoaXMgaXMgc3VwcG9ydGVkIGJ5IHRoZSBzaGVlciBudW1iZXIgb2YgZ2VuZXMgaXQgcHV0YXRpdmVseSBpbnRlcmFjdHMgd2l0aCwgc2luY2UgaG91c2VrZWVwaW5nIGdlbmVzIGFyZSBwbGVudGlmdWwgYW5kIHdvdWxkIGJlIGV4cGVjdGVkIHRvIGJlIHN0cm9uZ2x5IGNvZXhwcmVzc2VkLgoKQ2x1c3RlciAxODY1IGludGVyYWN0cyB3aXRoIGdlbmVzIHRoYXQgYXJlIGVucmljaGVkIGZvciBpbW11bmUgcmVndWxhdGlvbiB0ZXJtcywgc3BlY2lmaWNhbGx5IHRoZSBpbnRlcmxldWtpbi0xIGJldGEgKElMLTHOsiksIGEgcHJvLWluZmxhbW1hdG9yeSBjeXRva2luZS4gVGhpcyBzdWdnZXN0cyBDbHVzdGVyIDE4NjUgbWF5IHBsYXkgYSByb2xlIGluIGltbXVuZSByZXNwb25zZQoKQ2x1c3RlciAxNjM1NCBpcyBvZiBwYXJ0aWN1bGFyIGludGVyZXN0IGJlY2F1c2UgaXQncyB0aGUgb25seSBtaVJOQSBJIGlkZW50aWZpZWQgYXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIG92ZXIgdGltZSAobm90ZSwgdGhpcyBtYXkgY2hhbmdlIGFzIGkgbGVhcm4gaG93IHRvIGFkanVzdCBleHByZXNzaW9uIG1ldGhvZHMgZm9yIHRoZSBzbWFsbCBudW1iZXIgb2YgbWlSTkFzKS4gVGhlIHNldCBvZiBnZW5lcyB0aGF0IENsdXN0ZXIgMTYzNTQgaW50ZXJhY3RzIHdpdGggaXMgZW5yaWNoZWQgZm9yIG9uZSBiaW9sb2dpY2FsIHByb2Nlc3MsIEdyb3d0aCBSZWd1bGF0aW9uLiBUaGlzIHN1Z2dlc3RzIENsdXN0ZXIgMTYzNTQgbWF5IGJlIGludm9sdmVkIGluIHJlZ3VsYXRpbmcgZ3Jvd3RoIGluIHJlc3BvbnNlIHRvIGVudmlyb25tZW50YWwgc2lnbmFscy4K