R Notebook: Provides reproducible analysis for Hierarchical Clustering data in the following manuscript:

Citation: Romanowicz KJ and Kling GW. (In Press) Summer thaw duration is a strong predictor of the soil microbiome and its response to permafrost thaw in arctic tundra. Environmental Microbiology. https://doi.org/10.1111/1462-2920.16218

GitHub Repository: https://github.com/kromanowicz/2022-Annual-Thaw-Microbes

NCBI BioProject: https://www.ncbi.nlm.nih.gov/bioproject/?term=PRJNA794857

Accepted for Publication: 22 September 2022 Environmental Microbiology

Experiment

This R Notebook provides complete reproducibility of the data analysis presented in “Summer thaw duration is a strong predictor of the soil microbiome and its response to permafrost thaw in arctic tundra” by Romanowicz and Kling.

This pipeline uses amplicon sequence variants (ASVs) generated from 16S rRNA gene sequences in hierarchical clustering analysis to determine statistically significant clusters based on soil depth and shared taxonomy.

# Make a vector of required packages
required.packages <- c("corrr","data.table","devtools","dplyr","forcats","ggalluvial","ggdendro","ggplot2","ggpubr","grid","gridExtra","knitr","magrittr","microeco","patchwork","pheatmap","pvclust","qiime2R","RColorBrewer","tidyr","UpSetR","vegan")

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

Hierarchical Clustering

This analysis includes heatmaps of z-scored relative abundance taxonomic data and hierarchical clustering by soil depth and taxa using pvclust and 10,000 bootstrap iterations.

Toolik MAT

Import mean abundance of taxa by depth for TTT heatmap

asv.taxa.ttt.mean <- read.csv("QIIME/SILVA/R_Data/taxa.mean.ttt.csv")

colnames(asv.taxa.ttt.mean)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.ttt.mean) <- asv.taxa.ttt.mean$Phylum
asv.taxa.ttt.mean<-as.data.frame(asv.taxa.ttt.mean[-1])

# Convert dataframe into a matrix for heatmap
asv.taxa.ttt.mean<-as.matrix(asv.taxa.ttt.mean)

# Scale matrix values to generate Z-scores
asv.taxa.ttt.mean<-scale(t(asv.taxa.ttt.mean))

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Pheatmap
asv.taxa.ttt.mean.pheatmap <- pheatmap(asv.taxa.ttt.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = TRUE, cutree_cols = 3, cutree_rows = 3, angle_col=45, fontsize_col=8, legend = FALSE)


asv.taxa.ttt.mean.pheatmap.v2 <- pheatmap(asv.taxa.ttt.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = FALSE, cutree_cols = 3, gaps_row = c(2, 4), angle_col=45, fontsize_col=10, legend = FALSE, cellheight=16, cellwidth=18)


#Export as .eps (width:650, height:600; "ttt.heat.silva.eps")

Soil Depth pvclust

TTT Soil Depth pvclust Analysis

asv.taxa.ttt.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.ttt.csv")

colnames(asv.taxa.ttt.mean.pvclust)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.ttt.mean.pvclust) <- asv.taxa.ttt.mean.pvclust$Phylum
asv.taxa.ttt.mean.pvclust<-as.data.frame(asv.taxa.ttt.mean.pvclust[-1])

# Scale data
asv.taxa.ttt.mean.pvclust<-scale(asv.taxa.ttt.mean.pvclust)
result.10k.ttt <- pvclust(asv.taxa.ttt.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.ttt)
pvrect(result.10k.ttt, alpha=0.95)

Taxonomy pvclust

TTT Soil Taxa pvclust Analysis

asv.depth.ttt.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.ttt.cols.csv")

# Convert the first column (Phylum) into rownames
rownames(asv.depth.ttt.mean.pvclust) <- asv.depth.ttt.mean.pvclust$Phylum
asv.depth.ttt.mean.pvclust<-as.data.frame(asv.depth.ttt.mean.pvclust[-1])

# Scale data
asv.depth.ttt.mean.pvclust<-scale(asv.depth.ttt.mean.pvclust)
result.10k.ttt.taxa <- pvclust(asv.depth.ttt.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.ttt.taxa)
pvrect(result.10k.ttt.taxa, alpha=0.95)

Toolik WS

Import mean abundance of taxa by depth for TWS heatmap

asv.taxa.tws.mean <- read.csv("QIIME/SILVA/R_Data/taxa.mean.tws.csv")

colnames(asv.taxa.tws.mean)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.tws.mean) <- asv.taxa.tws.mean$Phylum
asv.taxa.tws.mean<-as.data.frame(asv.taxa.tws.mean[-1])

# Convert dataframe into a matrix for heatmap
asv.taxa.tws.mean<-as.matrix(asv.taxa.tws.mean)

# Scale matrix values to generate Z-scores
asv.taxa.tws.mean<-scale(t(asv.taxa.tws.mean))

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Pheatmap
asv.taxa.tws.mean.pheatmap <- pheatmap(asv.taxa.tws.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = TRUE, cutree_cols = 3, cutree_rows = 3, angle_col=45, fontsize_col=8, legend = FALSE)


asv.taxa.tws.mean.pheatmap.v2 <- pheatmap(asv.taxa.tws.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = FALSE, cutree_cols = 3, gaps_row = c(1, 5), angle_col=45, fontsize_col=10, legend = FALSE, cellheight=16, cellwidth=18)


#Export as .eps (width:650, height:600; "tws.heat.silva.eps")

Soil Depth pvclust

TWS pvclust analysis

asv.taxa.tws.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.tws.csv")

colnames(asv.taxa.tws.mean.pvclust)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.tws.mean.pvclust) <- asv.taxa.tws.mean.pvclust$Phylum
asv.taxa.tws.mean.pvclust<-as.data.frame(asv.taxa.tws.mean.pvclust[-1])

# Scale data
asv.taxa.tws.mean.pvclust<-scale(asv.taxa.tws.mean.pvclust)
result.10k.tws <- pvclust(asv.taxa.tws.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.tws)
pvrect(result.10k.tws, alpha=0.95)

Taxonomy pvclust

TWS Soil Taxa pvclust Analysis

asv.depth.tws.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.tws.cols.csv")

# Convert the first column (Phylum) into rownames
rownames(asv.depth.tws.mean.pvclust) <- asv.depth.tws.mean.pvclust$Phylum
asv.depth.tws.mean.pvclust<-as.data.frame(asv.depth.tws.mean.pvclust[-1])

# Scale data
asv.depth.tws.mean.pvclust<-scale(asv.depth.tws.mean.pvclust)
result.10k.tws.taxa <- pvclust(asv.depth.tws.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.tws.taxa)
pvrect(result.10k.tws.taxa, alpha=0.95)

Imnavait MAT

Import mean abundance of taxa by depth for ITT heatmap

asv.taxa.itt.mean <- read.csv("QIIME/SILVA/R_Data/taxa.mean.itt.csv")

colnames(asv.taxa.itt.mean)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.itt.mean) <- asv.taxa.itt.mean$Phylum
asv.taxa.itt.mean<-as.data.frame(asv.taxa.itt.mean[-1])

# Convert dataframe into a matrix for heatmap
asv.taxa.itt.mean<-as.matrix(asv.taxa.itt.mean)

# Scale matrix values to generate Z-scores
asv.taxa.itt.mean<-scale(t(asv.taxa.itt.mean))

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Pheatmap
asv.taxa.itt.mean.pheatmap <- pheatmap(asv.taxa.itt.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = TRUE, cutree_cols = 3, cutree_rows = 3, angle_col=45, fontsize_col=8, legend = FALSE)


asv.taxa.itt.mean.pheatmap.v2 <- pheatmap(asv.taxa.itt.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = FALSE, cutree_cols = 3, gaps_row = c(2, 4), angle_col=45, fontsize_col=10, legend = FALSE, cellheight=16, cellwidth=17)


#Export as .eps (width:650, height:600; "itt.heat.silva.eps")

Soil Depth pvclust

ITT pvclust analysis

asv.taxa.itt.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.itt.csv")

colnames(asv.taxa.itt.mean.pvclust)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.itt.mean.pvclust) <- asv.taxa.itt.mean.pvclust$Phylum
asv.taxa.itt.mean.pvclust<-as.data.frame(asv.taxa.itt.mean.pvclust[-1])

# Scale data
asv.taxa.itt.mean.pvclust<-scale(asv.taxa.itt.mean.pvclust)
result.10k.itt <- pvclust(asv.taxa.itt.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.itt)
pvrect(result.10k.itt, alpha=0.95)

Taxonomy pvclust

ITT Soil Taxa pvclust Analysis

asv.depth.itt.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.itt.cols.csv")

# Convert the first column (Phylum) into rownames
rownames(asv.depth.itt.mean.pvclust) <- asv.depth.itt.mean.pvclust$Phylum
asv.depth.itt.mean.pvclust<-as.data.frame(asv.depth.itt.mean.pvclust[-1])

# Scale data
asv.depth.itt.mean.pvclust<-scale(asv.depth.itt.mean.pvclust)
result.10k.itt.taxa <- pvclust(asv.depth.itt.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.itt.taxa)
pvrect(result.10k.itt.taxa, alpha=0.95)

Imnavait WS

Import mean abundance of taxa by depth for IWS heatmap

asv.taxa.iws.mean <- read.csv("QIIME/SILVA/R_Data/taxa.mean.iws.csv")

colnames(asv.taxa.iws.mean)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90","90-100")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.iws.mean) <- asv.taxa.iws.mean$Phylum
asv.taxa.iws.mean<-as.data.frame(asv.taxa.iws.mean[-1])

# Convert dataframe into a matrix for heatmap
asv.taxa.iws.mean<-as.matrix(asv.taxa.iws.mean)

# Scale matrix values to generate Z-scores
asv.taxa.iws.mean<-scale(t(asv.taxa.iws.mean))

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Pheatmap
asv.taxa.iws.mean.pheatmap <- pheatmap(asv.taxa.iws.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = TRUE, cutree_cols = 2, cutree_rows = 4, angle_col=45, fontsize_col=8, legend = FALSE)


asv.taxa.iws.mean.pheatmap.v2 <- pheatmap(asv.taxa.iws.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = FALSE, cutree_cols = 3, gaps_row = c(1, 4, 6), angle_col=45, fontsize_col=10, legend = FALSE, cellheight=14, cellwidth=17)


#Export as .eps (width:650, height:600; "iws.heat.silva.eps")

Soil Depth pvclust

IWS pvclust analysis

asv.taxa.iws.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.iws.csv")

colnames(asv.taxa.iws.mean.pvclust)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90","90-100")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.iws.mean.pvclust) <- asv.taxa.iws.mean.pvclust$Phylum
asv.taxa.iws.mean.pvclust<-as.data.frame(asv.taxa.iws.mean.pvclust[-1])

# Scale data
asv.taxa.iws.mean.pvclust<-scale(asv.taxa.iws.mean.pvclust)
result.10k.iws <- pvclust(asv.taxa.iws.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.iws)
pvrect(result.10k.iws, alpha=0.9)

Taxonomy pvclust

IWS Soil Taxa pvclust Analysis

asv.depth.iws.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.iws.cols.csv")

# Convert the first column (Phylum) into rownames
rownames(asv.depth.iws.mean.pvclust) <- asv.depth.iws.mean.pvclust$Phylum
asv.depth.iws.mean.pvclust<-as.data.frame(asv.depth.iws.mean.pvclust[-1])

# Scale data
asv.depth.iws.mean.pvclust<-scale(asv.depth.iws.mean.pvclust)
result.10k.iws.taxa <- pvclust(asv.depth.iws.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.iws.taxa)
pvrect(result.10k.iws.taxa, alpha=0.95)

Sagwon MAT

Import mean abundance of taxa by depth for STT heatmap

asv.taxa.stt.mean <- read.csv("QIIME/SILVA/R_Data/taxa.mean.stt.csv")

colnames(asv.taxa.stt.mean)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.stt.mean) <- asv.taxa.stt.mean$Phylum
asv.taxa.stt.mean<-as.data.frame(asv.taxa.stt.mean[-1])

# Convert dataframe into a matrix for heatmap
asv.taxa.stt.mean<-as.matrix(asv.taxa.stt.mean)

# Scale matrix values to generate Z-scores
asv.taxa.stt.mean<-scale(t(asv.taxa.stt.mean))

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Pheatmap
asv.taxa.stt.mean.pheatmap <- pheatmap(asv.taxa.stt.mean, clustering_method = "complete", cluster_cols = TRUE, cluster_rows = TRUE, cutree_cols = 2, cutree_rows = 2, angle_col=45, fontsize_col=8, legend = FALSE)


asv.taxa.stt.mean.pheatmap.v2 <- pheatmap(asv.taxa.stt.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = FALSE, cutree_cols = 3, gaps_row = c(3,5), angle_col=45, fontsize_col=10, legend = FALSE, cellheight=16, cellwidth=18)


#Export as .eps (width:650, height:600; "stt.heat.silva.eps")

Soil Depth pvclust

STT pvclust analysis

asv.taxa.stt.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.stt.csv")

colnames(asv.taxa.stt.mean.pvclust)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70","70-80","80-90")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.stt.mean.pvclust) <- asv.taxa.stt.mean.pvclust$Phylum
asv.taxa.stt.mean.pvclust<-as.data.frame(asv.taxa.stt.mean.pvclust[-1])

# Scale data
asv.taxa.stt.mean.pvclust<-scale(asv.taxa.stt.mean.pvclust)
result.10k.stt <- pvclust(asv.taxa.stt.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.stt)
pvrect(result.10k.stt, alpha=0.95)

Taxonomy pvclust

STT Soil Taxa pvclust Analysis

asv.depth.stt.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.stt.cols.csv")

# Convert the first column (Phylum) into rownames
rownames(asv.depth.stt.mean.pvclust) <- asv.depth.stt.mean.pvclust$Phylum
asv.depth.stt.mean.pvclust<-as.data.frame(asv.depth.stt.mean.pvclust[-1])

# Scale data
asv.depth.stt.mean.pvclust<-scale(asv.depth.stt.mean.pvclust)
result.10k.stt.taxa <- pvclust(asv.depth.stt.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.stt.taxa)
pvrect(result.10k.stt.taxa, alpha=0.95)

Sagwon WS

Import mean abundance of taxa by depth for SWS heatmap

asv.taxa.sws.mean <- read.csv("QIIME/SILVA/R_Data/taxa.mean.sws.csv")

colnames(asv.taxa.sws.mean)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.sws.mean) <- asv.taxa.sws.mean$Phylum
asv.taxa.sws.mean<-as.data.frame(asv.taxa.sws.mean[-1])

# Convert dataframe into a matrix for heatmap
asv.taxa.sws.mean<-as.matrix(asv.taxa.sws.mean)

# Scale matrix values to generate Z-scores
asv.taxa.sws.mean<-scale(t(asv.taxa.sws.mean))

# Specify RColorBrewer custom color palette
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Pheatmap
asv.taxa.sws.mean.pheatmap <- pheatmap(asv.taxa.sws.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = TRUE, cutree_cols = 2, cutree_rows = 2, angle_col=45, fontsize_col=8, legend = FALSE)


asv.taxa.sws.mean.pheatmap.v2 <- pheatmap(asv.taxa.sws.mean, clustering_method = "average", cluster_cols = TRUE, cluster_rows = FALSE, cutree_cols = 2, gaps_row = 4, angle_col=45, fontsize_col=10, legend = FALSE, cellheight=16, cellwidth=16)


#Export as .eps (width:650, height:600; "sws.heat.silva.eps")

Soil Depth pvclust

SWS pvclust analysis

asv.taxa.sws.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.sws.csv")

colnames(asv.taxa.sws.mean.pvclust)<-c("Phylum","0-10","10-20","20-30","30-40","40-50","50-60","60-70")

# Convert the first column (Phylum) into rownames
rownames(asv.taxa.sws.mean.pvclust) <- asv.taxa.sws.mean.pvclust$Phylum
asv.taxa.sws.mean.pvclust<-as.data.frame(asv.taxa.sws.mean.pvclust[-1])

# Scale data
asv.taxa.sws.mean.pvclust<-scale(asv.taxa.sws.mean.pvclust)
result.10k.sws <- pvclust(asv.taxa.sws.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.sws)
pvrect(result.10k.sws, alpha=0.95)

Taxonomy pvclust

SWS Soil Taxa pvclust Analysis

asv.depth.sws.mean.pvclust <- read.csv("QIIME/SILVA/R_Data/taxa.mean.sws.cols.csv")

# Convert the first column (Phylum) into rownames
rownames(asv.depth.sws.mean.pvclust) <- asv.depth.sws.mean.pvclust$Phylum
asv.depth.sws.mean.pvclust<-as.data.frame(asv.depth.sws.mean.pvclust[-1])

# Scale data
asv.depth.sws.mean.pvclust<-scale(asv.depth.sws.mean.pvclust)
result.10k.sws.taxa <- pvclust(asv.depth.sws.mean.pvclust, method.dist="cor", method.hclust="average", nboot=10000, parallel=TRUE)
Creating a temporary cluster...done:
socket cluster with 3 nodes on host ‘localhost’
Multiscale bootstrap... Done.
plot(result.10k.sws.taxa)
pvrect(result.10k.sws.taxa, alpha=0.95)

Reproducibility

The session information is provided for full reproducibility.

devtools::session_info()
─ Session info ────────────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.2.1 (2022-06-23)
 os       macOS Monterey 12.6
 system   x86_64, darwin17.0
 ui       RStudio
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       America/Los_Angeles
 date     2022-09-22
 rstudio  2022.07.1+554 Spotted Wakerobin (desktop)
 pandoc   2.18 @ /Applications/RStudio.app/Contents/MacOS/quarto/bin/tools/ (via rmarkdown)

─ Packages ────────────────────────────────────────────────────────────────────────
 package          * version  date (UTC) lib source
 abind              1.4-5    2016-07-21 [1] CRAN (R 4.2.0)
 ade4               1.7-19   2022-04-19 [1] CRAN (R 4.2.0)
 agricolae        * 1.3-5    2021-06-06 [1] CRAN (R 4.2.0)
 AlgDesign          1.2.1    2022-05-25 [1] CRAN (R 4.2.0)
 ape                5.6-2    2022-03-02 [1] CRAN (R 4.2.0)
 backports          1.4.1    2021-12-13 [1] CRAN (R 4.2.0)
 base64enc          0.1-3    2015-07-28 [1] CRAN (R 4.2.0)
 Biobase            2.56.0   2022-04-26 [1] Bioconductor
 BiocGenerics       0.42.0   2022-04-26 [1] Bioconductor
 biomformat         1.24.0   2022-04-26 [1] Bioconductor
 Biostrings         2.64.1   2022-08-18 [1] Bioconductor
 bitops             1.0-7    2021-04-24 [1] CRAN (R 4.2.0)
 broom              1.0.0    2022-07-01 [1] CRAN (R 4.2.0)
 bslib              0.4.0    2022-07-16 [1] CRAN (R 4.2.0)
 cachem             1.0.6    2021-08-19 [1] CRAN (R 4.2.0)
 callr              3.7.2    2022-08-22 [1] CRAN (R 4.2.0)
 car                3.1-0    2022-06-15 [1] CRAN (R 4.2.0)
 carData            3.0-5    2022-01-06 [1] CRAN (R 4.2.0)
 checkmate          2.1.0    2022-04-21 [1] CRAN (R 4.2.0)
 cli                3.3.0    2022-04-25 [1] CRAN (R 4.2.0)
 cluster            2.1.3    2022-03-28 [1] CRAN (R 4.2.1)
 codetools          0.2-18   2020-11-04 [1] CRAN (R 4.2.1)
 colorspace         2.0-3    2022-02-21 [1] CRAN (R 4.2.0)
 combinat           0.0-8    2012-10-29 [1] CRAN (R 4.2.0)
 corrr            * 0.4.4    2022-08-16 [1] CRAN (R 4.2.0)
 crayon             1.5.1    2022-03-26 [1] CRAN (R 4.2.0)
 data.table       * 1.14.2   2021-09-27 [1] CRAN (R 4.2.0)
 deldir             1.0-6    2021-10-23 [1] CRAN (R 4.2.0)
 devtools         * 2.4.4    2022-07-20 [1] CRAN (R 4.2.0)
 digest             0.6.29   2021-12-01 [1] CRAN (R 4.2.0)
 dplyr            * 1.0.9    2022-04-28 [1] CRAN (R 4.2.0)
 DT                 0.24     2022-08-09 [1] CRAN (R 4.2.0)
 ellipsis           0.3.2    2021-04-29 [1] CRAN (R 4.2.0)
 evaluate           0.16     2022-08-09 [1] CRAN (R 4.2.0)
 fansi              1.0.3    2022-03-24 [1] CRAN (R 4.2.0)
 farver             2.1.1    2022-07-06 [1] CRAN (R 4.2.0)
 fastmap            1.1.0    2021-01-25 [1] CRAN (R 4.2.0)
 forcats          * 0.5.2    2022-08-19 [1] CRAN (R 4.2.0)
 foreach            1.5.2    2022-02-02 [1] CRAN (R 4.2.0)
 foreign            0.8-82   2022-01-16 [1] CRAN (R 4.2.1)
 Formula            1.2-4    2020-10-16 [1] CRAN (R 4.2.0)
 fs                 1.5.2    2021-12-08 [1] CRAN (R 4.2.0)
 generics           0.1.3    2022-07-05 [1] CRAN (R 4.2.0)
 GenomeInfoDb       1.32.3   2022-08-09 [1] Bioconductor
 GenomeInfoDbData   1.2.8    2022-08-29 [1] Bioconductor
 ggalluvial       * 0.12.3   2020-12-05 [1] CRAN (R 4.2.0)
 ggdendro         * 0.1.23   2022-02-16 [1] CRAN (R 4.2.0)
 ggplot2          * 3.3.6    2022-05-03 [1] CRAN (R 4.2.0)
 ggpubr           * 0.4.0    2020-06-27 [1] CRAN (R 4.2.0)
 ggsignif           0.6.3    2021-09-09 [1] CRAN (R 4.2.0)
 glue               1.6.2    2022-02-24 [1] CRAN (R 4.2.0)
 gridExtra        * 2.3      2017-09-09 [1] CRAN (R 4.2.0)
 gtable             0.3.0    2019-03-25 [1] CRAN (R 4.2.0)
 haven              2.5.1    2022-08-22 [1] CRAN (R 4.2.0)
 highr              0.9      2021-04-16 [1] CRAN (R 4.2.0)
 Hmisc              4.7-1    2022-08-15 [1] CRAN (R 4.2.0)
 hms                1.1.2    2022-08-19 [1] CRAN (R 4.2.0)
 htmlTable          2.4.1    2022-07-07 [1] CRAN (R 4.2.0)
 htmltools          0.5.3    2022-07-18 [1] CRAN (R 4.2.0)
 htmlwidgets        1.5.4    2021-09-08 [1] CRAN (R 4.2.0)
 httpuv             1.6.5    2022-01-05 [1] CRAN (R 4.2.0)
 igraph             1.3.4    2022-07-19 [1] CRAN (R 4.2.0)
 interp             1.1-3    2022-07-13 [1] CRAN (R 4.2.0)
 IRanges            2.30.1   2022-08-18 [1] Bioconductor
 iterators          1.0.14   2022-02-05 [1] CRAN (R 4.2.0)
 jpeg               0.1-9    2021-07-24 [1] CRAN (R 4.2.0)
 jquerylib          0.1.4    2021-04-26 [1] CRAN (R 4.2.0)
 jsonlite           1.8.0    2022-02-22 [1] CRAN (R 4.2.0)
 klaR               1.7-1    2022-06-27 [1] CRAN (R 4.2.0)
 knitr            * 1.40     2022-08-24 [1] CRAN (R 4.2.0)
 labeling           0.4.2    2020-10-20 [1] CRAN (R 4.2.0)
 labelled           2.9.1    2022-05-05 [1] CRAN (R 4.2.0)
 later              1.3.0    2021-08-18 [1] CRAN (R 4.2.0)
 lattice          * 0.20-45  2021-09-22 [1] CRAN (R 4.2.1)
 latticeExtra       0.6-30   2022-07-04 [1] CRAN (R 4.2.0)
 lifecycle          1.0.1    2021-09-24 [1] CRAN (R 4.2.0)
 magrittr         * 2.0.3    2022-03-30 [1] CRAN (R 4.2.0)
 MASS               7.3-57   2022-04-22 [1] CRAN (R 4.2.1)
 Matrix             1.4-1    2022-03-23 [1] CRAN (R 4.2.1)
 memoise            2.0.1    2021-11-26 [1] CRAN (R 4.2.0)
 mgcv               1.8-40   2022-03-29 [1] CRAN (R 4.2.1)
 microeco         * 0.11.0   2022-06-22 [1] CRAN (R 4.2.0)
 mime               0.12     2021-09-28 [1] CRAN (R 4.2.0)
 miniUI             0.1.1.1  2018-05-18 [1] CRAN (R 4.2.0)
 multtest           2.52.0   2022-04-26 [1] Bioconductor
 munsell            0.5.0    2018-06-12 [1] CRAN (R 4.2.0)
 NADA               1.6-1.1  2020-03-22 [1] CRAN (R 4.2.0)
 nlme               3.1-157  2022-03-25 [1] CRAN (R 4.2.1)
 nnet               7.3-17   2022-01-16 [1] CRAN (R 4.2.1)
 patchwork        * 1.1.2    2022-08-19 [1] CRAN (R 4.2.0)
 permute          * 0.9-7    2022-01-27 [1] CRAN (R 4.2.0)
 pheatmap         * 1.0.12   2019-01-04 [1] CRAN (R 4.2.0)
 phyloseq           1.40.0   2022-04-26 [1] Bioconductor
 pillar             1.8.1    2022-08-19 [1] CRAN (R 4.2.0)
 pkgbuild           1.3.1    2021-12-20 [1] CRAN (R 4.2.0)
 pkgconfig          2.0.3    2019-09-22 [1] CRAN (R 4.2.0)
 pkgload            1.3.0    2022-06-27 [1] CRAN (R 4.2.0)
 plyr               1.8.7    2022-03-24 [1] CRAN (R 4.2.0)
 png                0.1-7    2013-12-03 [1] CRAN (R 4.2.0)
 prettyunits        1.1.1    2020-01-24 [1] CRAN (R 4.2.0)
 processx           3.7.0    2022-07-07 [1] CRAN (R 4.2.0)
 profvis            0.3.7    2020-11-02 [1] CRAN (R 4.2.0)
 promises           1.2.0.1  2021-02-11 [1] CRAN (R 4.2.0)
 ps                 1.7.1    2022-06-18 [1] CRAN (R 4.2.0)
 purrr              0.3.4    2020-04-17 [1] CRAN (R 4.2.0)
 pvclust          * 2.2-0    2019-11-19 [1] CRAN (R 4.2.0)
 qiime2R          * 0.99.6   2022-08-29 [1] Github (jbisanz/qiime2R@2a3cee1)
 questionr          0.7.7    2022-01-31 [1] CRAN (R 4.2.0)
 R6                 2.5.1    2021-08-19 [1] CRAN (R 4.2.0)
 RColorBrewer     * 1.1-3    2022-04-03 [1] CRAN (R 4.2.0)
 Rcpp               1.0.9    2022-07-08 [1] CRAN (R 4.2.0)
 RCurl              1.98-1.8 2022-07-30 [1] CRAN (R 4.2.0)
 remotes            2.4.2    2021-11-30 [1] CRAN (R 4.2.0)
 reshape2           1.4.4    2020-04-09 [1] CRAN (R 4.2.0)
 rhdf5              2.40.0   2022-04-26 [1] Bioconductor
 rhdf5filters       1.8.0    2022-04-26 [1] Bioconductor
 Rhdf5lib           1.18.2   2022-05-17 [1] Bioconductor
 rlang              1.0.4    2022-07-12 [1] CRAN (R 4.2.0)
 rmarkdown          2.16     2022-08-24 [1] CRAN (R 4.2.0)
 rpart              4.1.16   2022-01-24 [1] CRAN (R 4.2.1)
 rsconnect          0.8.27   2022-07-12 [1] CRAN (R 4.2.1)
 rstatix            0.7.0    2021-02-13 [1] CRAN (R 4.2.0)
 rstudioapi         0.14     2022-08-22 [1] CRAN (R 4.2.0)
 S4Vectors          0.34.0   2022-04-26 [1] Bioconductor
 sass               0.4.2    2022-07-16 [1] CRAN (R 4.2.0)
 scales             1.2.1    2022-08-20 [1] CRAN (R 4.2.0)
 sessioninfo        1.2.2    2021-12-06 [1] CRAN (R 4.2.0)
 shiny              1.7.2    2022-07-19 [1] CRAN (R 4.2.0)
 stringi            1.7.8    2022-07-11 [1] CRAN (R 4.2.0)
 stringr            1.4.1    2022-08-20 [1] CRAN (R 4.2.0)
 survival           3.3-1    2022-03-03 [1] CRAN (R 4.2.1)
 tibble             3.1.8    2022-07-22 [1] CRAN (R 4.2.0)
 tidyr            * 1.2.0    2022-02-01 [1] CRAN (R 4.2.0)
 tidyselect         1.1.2    2022-02-21 [1] CRAN (R 4.2.0)
 truncnorm          1.0-8    2018-02-27 [1] CRAN (R 4.2.0)
 UpSetR           * 1.4.0    2019-05-22 [1] CRAN (R 4.2.0)
 urlchecker         1.0.1    2021-11-30 [1] CRAN (R 4.2.0)
 usethis          * 2.1.6    2022-05-25 [1] CRAN (R 4.2.0)
 utf8               1.2.2    2021-07-24 [1] CRAN (R 4.2.0)
 vctrs              0.4.1    2022-04-13 [1] CRAN (R 4.2.0)
 vegan            * 2.6-2    2022-04-17 [1] CRAN (R 4.2.0)
 withr              2.5.0    2022-03-03 [1] CRAN (R 4.2.0)
 xfun               0.32     2022-08-10 [1] CRAN (R 4.2.0)
 xtable             1.8-4    2019-04-21 [1] CRAN (R 4.2.0)
 XVector            0.36.0   2022-04-26 [1] Bioconductor
 yaml               2.3.5    2022-02-21 [1] CRAN (R 4.2.0)
 zCompositions      1.4.0-1  2022-03-26 [1] CRAN (R 4.2.0)
 zlibbioc           1.42.0   2022-04-26 [1] Bioconductor

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

───────────────────────────────────────────────────────────────────────────────────
LS0tCnRpdGxlOiAiTWljcm9iaWFsIFJlc3BvbnNlIHRvIEludGVybWl0dGVudCBQZXJtYWZyb3N0IFRoYXcgLS0gQ2x1c3RlcmluZyIKYXV0aG9yOiAnQXV0aG9yczogW0thcmwgSi4gUm9tYW5vd2ljel0oaHR0cHM6Ly9rcm9tYW5vd2ljei5naXRodWIuaW8vKSBhbmQgR2VvcmdlIFcuIEtsaW5nJwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBzcGFjZWxhYgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwogICAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzUnCiAgICBkZl9wcmludDogcGFnZWQKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnNScKLS0tCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwoKKipSIE5vdGVib29rOioqIDxmb250IGNvbG9yPSJncmVlbiI+UHJvdmlkZXMgcmVwcm9kdWNpYmxlIGFuYWx5c2lzIGZvciAqKkhpZXJhcmNoaWNhbCBDbHVzdGVyaW5nKiogZGF0YSBpbiB0aGUgZm9sbG93aW5nIG1hbnVzY3JpcHQ6PC9mb250PgoKKipDaXRhdGlvbjoqKiBSb21hbm93aWN6IEtKIGFuZCBLbGluZyBHVy4gKCoqKkluIFByZXNzKioqKSBTdW1tZXIgdGhhdyBkdXJhdGlvbiBpcyBhIHN0cm9uZyBwcmVkaWN0b3Igb2YgdGhlIHNvaWwgbWljcm9iaW9tZSBhbmQgaXRzIHJlc3BvbnNlIHRvIHBlcm1hZnJvc3QgdGhhdyBpbiBhcmN0aWMgdHVuZHJhLiAqKipFbnZpcm9ubWVudGFsIE1pY3JvYmlvbG9neSoqKi4gW2h0dHBzOi8vZG9pLm9yZy8xMC4xMTExLzE0NjItMjkyMC4xNjIxOF0oaHR0cHM6Ly9kb2kub3JnLzEwLjExMTEvMTQ2Mi0yOTIwLjE2MjE4KQoKKipHaXRIdWIgUmVwb3NpdG9yeToqKiBbaHR0cHM6Ly9naXRodWIuY29tL2tyb21hbm93aWN6LzIwMjItQW5udWFsLVRoYXctTWljcm9iZXNdKGh0dHBzOi8vZ2l0aHViLmNvbS9rcm9tYW5vd2ljei8yMDIyLUFubnVhbC1UaGF3LU1pY3JvYmVzKQoKKipOQ0JJIEJpb1Byb2plY3Q6KiogW2h0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvYmlvcHJvamVjdC8/dGVybT1QUkpOQTc5NDg1N10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9iaW9wcm9qZWN0Lz90ZXJtPVBSSk5BNzk0ODU3KQoKKipBY2NlcHRlZCBmb3IgUHVibGljYXRpb246KiogPGZvbnQgY29sb3I9ImdyZWVuIj4yMiBTZXB0ZW1iZXIgMjAyMjwvZm9udD4gKkVudmlyb25tZW50YWwgTWljcm9iaW9sb2d5KgoKIyBFeHBlcmltZW50CgpUaGlzIFIgTm90ZWJvb2sgcHJvdmlkZXMgY29tcGxldGUgcmVwcm9kdWNpYmlsaXR5IG9mIHRoZSBkYXRhIGFuYWx5c2lzIHByZXNlbnRlZCBpbiAqKioiU3VtbWVyIHRoYXcgZHVyYXRpb24gaXMgYSBzdHJvbmcgcHJlZGljdG9yIG9mIHRoZSBzb2lsIG1pY3JvYmlvbWUgYW5kIGl0cyByZXNwb25zZSB0byBwZXJtYWZyb3N0IHRoYXcgaW4gYXJjdGljIHR1bmRyYSIqKiogYnkgUm9tYW5vd2ljeiBhbmQgS2xpbmcuCgo8Zm9udCBjb2xvcj0iZ3JlZW4iPlRoaXMgcGlwZWxpbmUgdXNlcyBhbXBsaWNvbiBzZXF1ZW5jZSB2YXJpYW50cyAoQVNWcykgZ2VuZXJhdGVkIGZyb20gMTZTIHJSTkEgZ2VuZSBzZXF1ZW5jZXMgaW4gaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcgYW5hbHlzaXMgdG8gZGV0ZXJtaW5lIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgY2x1c3RlcnMgYmFzZWQgb24gc29pbCBkZXB0aCBhbmQgc2hhcmVkIHRheG9ub215LjwvZm9udD4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQojIFNldCBnbG9iYWwgb3B0aW9ucyBmb3Igbm90ZWJvb2sKa25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSBub3JtYWxpemVQYXRoKCJ+L0Rlc2t0b3AvVHVuZHJhUHJvMTgiKSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFfQojIE1ha2UgYSB2ZWN0b3Igb2YgcmVxdWlyZWQgcGFja2FnZXMKcmVxdWlyZWQucGFja2FnZXMgPC0gYygiY29ycnIiLCJkYXRhLnRhYmxlIiwiZGV2dG9vbHMiLCJkcGx5ciIsImZvcmNhdHMiLCJnZ2FsbHV2aWFsIiwiZ2dkZW5kcm8iLCJnZ3Bsb3QyIiwiZ2dwdWJyIiwiZ3JpZCIsImdyaWRFeHRyYSIsImtuaXRyIiwibWFncml0dHIiLCJtaWNyb2VjbyIsInBhdGNod29yayIsInBoZWF0bWFwIiwicHZjbHVzdCIsInFpaW1lMlIiLCJSQ29sb3JCcmV3ZXIiLCJ0aWR5ciIsIlVwU2V0UiIsInZlZ2FuIikKCiMgTG9hZCByZXF1aXJlZCBwYWNrYWdlcwpsYXBwbHkocmVxdWlyZWQucGFja2FnZXMsIGxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojIHNldC5zZWVkIGlzIHVzZWQgdG8gZml4IHRoZSByYW5kb20gbnVtYmVyIGdlbmVyYXRpb24gdG8gbWFrZSB0aGUgcmVzdWx0cyByZXBlYXRhYmxlCnNldC5zZWVkKDEyMykKYGBgCgojIEhpZXJhcmNoaWNhbCBDbHVzdGVyaW5nCgpUaGlzIGFuYWx5c2lzIGluY2x1ZGVzIGhlYXRtYXBzIG9mIHotc2NvcmVkIHJlbGF0aXZlIGFidW5kYW5jZSB0YXhvbm9taWMgZGF0YSBhbmQgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcgYnkgc29pbCBkZXB0aCBhbmQgdGF4YSB1c2luZyBwdmNsdXN0IGFuZCAxMCwwMDAgYm9vdHN0cmFwIGl0ZXJhdGlvbnMuCgojIyBUb29saWsgTUFUCgpJbXBvcnQgbWVhbiBhYnVuZGFuY2Ugb2YgdGF4YSBieSBkZXB0aCBmb3IgVFRUIGhlYXRtYXAKYGBge3J9CmFzdi50YXhhLnR0dC5tZWFuIDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLnR0dC5jc3YiKQoKY29sbmFtZXMoYXN2LnRheGEudHR0Lm1lYW4pPC1jKCJQaHlsdW0iLCIwLTEwIiwiMTAtMjAiLCIyMC0zMCIsIjMwLTQwIiwiNDAtNTAiLCI1MC02MCIsIjYwLTcwIiwiNzAtODAiLCI4MC05MCIpCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoUGh5bHVtKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKGFzdi50YXhhLnR0dC5tZWFuKSA8LSBhc3YudGF4YS50dHQubWVhbiRQaHlsdW0KYXN2LnRheGEudHR0Lm1lYW48LWFzLmRhdGEuZnJhbWUoYXN2LnRheGEudHR0Lm1lYW5bLTFdKQoKIyBDb252ZXJ0IGRhdGFmcmFtZSBpbnRvIGEgbWF0cml4IGZvciBoZWF0bWFwCmFzdi50YXhhLnR0dC5tZWFuPC1hcy5tYXRyaXgoYXN2LnRheGEudHR0Lm1lYW4pCgojIFNjYWxlIG1hdHJpeCB2YWx1ZXMgdG8gZ2VuZXJhdGUgWi1zY29yZXMKYXN2LnRheGEudHR0Lm1lYW48LXNjYWxlKHQoYXN2LnRheGEudHR0Lm1lYW4pKQoKIyBTcGVjaWZ5IFJDb2xvckJyZXdlciBjdXN0b20gY29sb3IgcGFsZXR0ZQpjb2wgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDEwLCAiUmRZbEJ1IikpKDI1NikKYGBgCgpgYGB7cn0KIyBQaGVhdG1hcAphc3YudGF4YS50dHQubWVhbi5waGVhdG1hcCA8LSBwaGVhdG1hcChhc3YudGF4YS50dHQubWVhbiwgY2x1c3RlcmluZ19tZXRob2QgPSAiYXZlcmFnZSIsIGNsdXN0ZXJfY29scyA9IFRSVUUsIGNsdXN0ZXJfcm93cyA9IFRSVUUsIGN1dHJlZV9jb2xzID0gMywgY3V0cmVlX3Jvd3MgPSAzLCBhbmdsZV9jb2w9NDUsIGZvbnRzaXplX2NvbD04LCBsZWdlbmQgPSBGQUxTRSkKCmFzdi50YXhhLnR0dC5tZWFuLnBoZWF0bWFwLnYyIDwtIHBoZWF0bWFwKGFzdi50YXhhLnR0dC5tZWFuLCBjbHVzdGVyaW5nX21ldGhvZCA9ICJhdmVyYWdlIiwgY2x1c3Rlcl9jb2xzID0gVFJVRSwgY2x1c3Rlcl9yb3dzID0gRkFMU0UsIGN1dHJlZV9jb2xzID0gMywgZ2Fwc19yb3cgPSBjKDIsIDQpLCBhbmdsZV9jb2w9NDUsIGZvbnRzaXplX2NvbD0xMCwgbGVnZW5kID0gRkFMU0UsIGNlbGxoZWlnaHQ9MTYsIGNlbGx3aWR0aD0xOCkKCiNFeHBvcnQgYXMgLmVwcyAod2lkdGg6NjUwLCBoZWlnaHQ6NjAwOyAidHR0LmhlYXQuc2lsdmEuZXBzIikKYGBgCgojIyMgU29pbCBEZXB0aCBwdmNsdXN0CgpUVFQgU29pbCBEZXB0aCBwdmNsdXN0IEFuYWx5c2lzCmBgYHtyfQphc3YudGF4YS50dHQubWVhbi5wdmNsdXN0IDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLnR0dC5jc3YiKQoKY29sbmFtZXMoYXN2LnRheGEudHR0Lm1lYW4ucHZjbHVzdCk8LWMoIlBoeWx1bSIsIjAtMTAiLCIxMC0yMCIsIjIwLTMwIiwiMzAtNDAiLCI0MC01MCIsIjUwLTYwIiwiNjAtNzAiLCI3MC04MCIsIjgwLTkwIikKCiMgQ29udmVydCB0aGUgZmlyc3QgY29sdW1uIChQaHlsdW0pIGludG8gcm93bmFtZXMKcm93bmFtZXMoYXN2LnRheGEudHR0Lm1lYW4ucHZjbHVzdCkgPC0gYXN2LnRheGEudHR0Lm1lYW4ucHZjbHVzdCRQaHlsdW0KYXN2LnRheGEudHR0Lm1lYW4ucHZjbHVzdDwtYXMuZGF0YS5mcmFtZShhc3YudGF4YS50dHQubWVhbi5wdmNsdXN0Wy0xXSkKCiMgU2NhbGUgZGF0YQphc3YudGF4YS50dHQubWVhbi5wdmNsdXN0PC1zY2FsZShhc3YudGF4YS50dHQubWVhbi5wdmNsdXN0KQpgYGAKCmBgYHtyfQpyZXN1bHQuMTBrLnR0dCA8LSBwdmNsdXN0KGFzdi50YXhhLnR0dC5tZWFuLnB2Y2x1c3QsIG1ldGhvZC5kaXN0PSJjb3IiLCBtZXRob2QuaGNsdXN0PSJhdmVyYWdlIiwgbmJvb3Q9MTAwMDAsIHBhcmFsbGVsPVRSVUUpCgpwbG90KHJlc3VsdC4xMGsudHR0KQpwdnJlY3QocmVzdWx0LjEway50dHQsIGFscGhhPTAuOTUpCmBgYAoKIyMjIFRheG9ub215IHB2Y2x1c3QKClRUVCBTb2lsIFRheGEgcHZjbHVzdCBBbmFseXNpcwpgYGB7cn0KYXN2LmRlcHRoLnR0dC5tZWFuLnB2Y2x1c3QgPC0gcmVhZC5jc3YoIlFJSU1FL1NJTFZBL1JfRGF0YS90YXhhLm1lYW4udHR0LmNvbHMuY3N2IikKCiMgQ29udmVydCB0aGUgZmlyc3QgY29sdW1uIChQaHlsdW0pIGludG8gcm93bmFtZXMKcm93bmFtZXMoYXN2LmRlcHRoLnR0dC5tZWFuLnB2Y2x1c3QpIDwtIGFzdi5kZXB0aC50dHQubWVhbi5wdmNsdXN0JFBoeWx1bQphc3YuZGVwdGgudHR0Lm1lYW4ucHZjbHVzdDwtYXMuZGF0YS5mcmFtZShhc3YuZGVwdGgudHR0Lm1lYW4ucHZjbHVzdFstMV0pCgojIFNjYWxlIGRhdGEKYXN2LmRlcHRoLnR0dC5tZWFuLnB2Y2x1c3Q8LXNjYWxlKGFzdi5kZXB0aC50dHQubWVhbi5wdmNsdXN0KQpgYGAKCmBgYHtyfQpyZXN1bHQuMTBrLnR0dC50YXhhIDwtIHB2Y2x1c3QoYXN2LmRlcHRoLnR0dC5tZWFuLnB2Y2x1c3QsIG1ldGhvZC5kaXN0PSJjb3IiLCBtZXRob2QuaGNsdXN0PSJhdmVyYWdlIiwgbmJvb3Q9MTAwMDAsIHBhcmFsbGVsPVRSVUUpCgpwbG90KHJlc3VsdC4xMGsudHR0LnRheGEpCnB2cmVjdChyZXN1bHQuMTBrLnR0dC50YXhhLCBhbHBoYT0wLjk1KQpgYGAKCiMjIFRvb2xpayBXUwoKSW1wb3J0IG1lYW4gYWJ1bmRhbmNlIG9mIHRheGEgYnkgZGVwdGggZm9yIFRXUyBoZWF0bWFwCmBgYHtyfQphc3YudGF4YS50d3MubWVhbiA8LSByZWFkLmNzdigiUUlJTUUvU0lMVkEvUl9EYXRhL3RheGEubWVhbi50d3MuY3N2IikKCmNvbG5hbWVzKGFzdi50YXhhLnR3cy5tZWFuKTwtYygiUGh5bHVtIiwiMC0xMCIsIjEwLTIwIiwiMjAtMzAiLCIzMC00MCIsIjQwLTUwIiwiNTAtNjAiLCI2MC03MCIsIjcwLTgwIiwiODAtOTAiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YudGF4YS50d3MubWVhbikgPC0gYXN2LnRheGEudHdzLm1lYW4kUGh5bHVtCmFzdi50YXhhLnR3cy5tZWFuPC1hcy5kYXRhLmZyYW1lKGFzdi50YXhhLnR3cy5tZWFuWy0xXSkKCiMgQ29udmVydCBkYXRhZnJhbWUgaW50byBhIG1hdHJpeCBmb3IgaGVhdG1hcAphc3YudGF4YS50d3MubWVhbjwtYXMubWF0cml4KGFzdi50YXhhLnR3cy5tZWFuKQoKIyBTY2FsZSBtYXRyaXggdmFsdWVzIHRvIGdlbmVyYXRlIFotc2NvcmVzCmFzdi50YXhhLnR3cy5tZWFuPC1zY2FsZSh0KGFzdi50YXhhLnR3cy5tZWFuKSkKCiMgU3BlY2lmeSBSQ29sb3JCcmV3ZXIgY3VzdG9tIGNvbG9yIHBhbGV0dGUKY29sIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCgxMCwgIlJkWWxCdSIpKSgyNTYpCmBgYAoKYGBge3J9CiMgUGhlYXRtYXAKYXN2LnRheGEudHdzLm1lYW4ucGhlYXRtYXAgPC0gcGhlYXRtYXAoYXN2LnRheGEudHdzLm1lYW4sIGNsdXN0ZXJpbmdfbWV0aG9kID0gImF2ZXJhZ2UiLCBjbHVzdGVyX2NvbHMgPSBUUlVFLCBjbHVzdGVyX3Jvd3MgPSBUUlVFLCBjdXRyZWVfY29scyA9IDMsIGN1dHJlZV9yb3dzID0gMywgYW5nbGVfY29sPTQ1LCBmb250c2l6ZV9jb2w9OCwgbGVnZW5kID0gRkFMU0UpCgphc3YudGF4YS50d3MubWVhbi5waGVhdG1hcC52MiA8LSBwaGVhdG1hcChhc3YudGF4YS50d3MubWVhbiwgY2x1c3RlcmluZ19tZXRob2QgPSAiYXZlcmFnZSIsIGNsdXN0ZXJfY29scyA9IFRSVUUsIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCBjdXRyZWVfY29scyA9IDMsIGdhcHNfcm93ID0gYygxLCA1KSwgYW5nbGVfY29sPTQ1LCBmb250c2l6ZV9jb2w9MTAsIGxlZ2VuZCA9IEZBTFNFLCBjZWxsaGVpZ2h0PTE2LCBjZWxsd2lkdGg9MTgpCgojRXhwb3J0IGFzIC5lcHMgKHdpZHRoOjY1MCwgaGVpZ2h0OjYwMDsgInR3cy5oZWF0LnNpbHZhLmVwcyIpCmBgYAoKIyMjIFNvaWwgRGVwdGggcHZjbHVzdAoKVFdTIHB2Y2x1c3QgYW5hbHlzaXMKYGBge3J9CmFzdi50YXhhLnR3cy5tZWFuLnB2Y2x1c3QgPC0gcmVhZC5jc3YoIlFJSU1FL1NJTFZBL1JfRGF0YS90YXhhLm1lYW4udHdzLmNzdiIpCgpjb2xuYW1lcyhhc3YudGF4YS50d3MubWVhbi5wdmNsdXN0KTwtYygiUGh5bHVtIiwiMC0xMCIsIjEwLTIwIiwiMjAtMzAiLCIzMC00MCIsIjQwLTUwIiwiNTAtNjAiLCI2MC03MCIsIjcwLTgwIiwiODAtOTAiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YudGF4YS50d3MubWVhbi5wdmNsdXN0KSA8LSBhc3YudGF4YS50d3MubWVhbi5wdmNsdXN0JFBoeWx1bQphc3YudGF4YS50d3MubWVhbi5wdmNsdXN0PC1hcy5kYXRhLmZyYW1lKGFzdi50YXhhLnR3cy5tZWFuLnB2Y2x1c3RbLTFdKQoKIyBTY2FsZSBkYXRhCmFzdi50YXhhLnR3cy5tZWFuLnB2Y2x1c3Q8LXNjYWxlKGFzdi50YXhhLnR3cy5tZWFuLnB2Y2x1c3QpCmBgYAoKYGBge3J9CnJlc3VsdC4xMGsudHdzIDwtIHB2Y2x1c3QoYXN2LnRheGEudHdzLm1lYW4ucHZjbHVzdCwgbWV0aG9kLmRpc3Q9ImNvciIsIG1ldGhvZC5oY2x1c3Q9ImF2ZXJhZ2UiLCBuYm9vdD0xMDAwMCwgcGFyYWxsZWw9VFJVRSkKCnBsb3QocmVzdWx0LjEway50d3MpCnB2cmVjdChyZXN1bHQuMTBrLnR3cywgYWxwaGE9MC45NSkKYGBgCgojIyMgVGF4b25vbXkgcHZjbHVzdAoKVFdTIFNvaWwgVGF4YSBwdmNsdXN0IEFuYWx5c2lzCmBgYHtyfQphc3YuZGVwdGgudHdzLm1lYW4ucHZjbHVzdCA8LSByZWFkLmNzdigiUUlJTUUvU0lMVkEvUl9EYXRhL3RheGEubWVhbi50d3MuY29scy5jc3YiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YuZGVwdGgudHdzLm1lYW4ucHZjbHVzdCkgPC0gYXN2LmRlcHRoLnR3cy5tZWFuLnB2Y2x1c3QkUGh5bHVtCmFzdi5kZXB0aC50d3MubWVhbi5wdmNsdXN0PC1hcy5kYXRhLmZyYW1lKGFzdi5kZXB0aC50d3MubWVhbi5wdmNsdXN0Wy0xXSkKCiMgU2NhbGUgZGF0YQphc3YuZGVwdGgudHdzLm1lYW4ucHZjbHVzdDwtc2NhbGUoYXN2LmRlcHRoLnR3cy5tZWFuLnB2Y2x1c3QpCmBgYAoKYGBge3J9CnJlc3VsdC4xMGsudHdzLnRheGEgPC0gcHZjbHVzdChhc3YuZGVwdGgudHdzLm1lYW4ucHZjbHVzdCwgbWV0aG9kLmRpc3Q9ImNvciIsIG1ldGhvZC5oY2x1c3Q9ImF2ZXJhZ2UiLCBuYm9vdD0xMDAwMCwgcGFyYWxsZWw9VFJVRSkKCnBsb3QocmVzdWx0LjEway50d3MudGF4YSkKcHZyZWN0KHJlc3VsdC4xMGsudHdzLnRheGEsIGFscGhhPTAuOTUpCmBgYAoKIyMgSW1uYXZhaXQgTUFUCgpJbXBvcnQgbWVhbiBhYnVuZGFuY2Ugb2YgdGF4YSBieSBkZXB0aCBmb3IgSVRUIGhlYXRtYXAKYGBge3J9CmFzdi50YXhhLml0dC5tZWFuIDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLml0dC5jc3YiKQoKY29sbmFtZXMoYXN2LnRheGEuaXR0Lm1lYW4pPC1jKCJQaHlsdW0iLCIwLTEwIiwiMTAtMjAiLCIyMC0zMCIsIjMwLTQwIiwiNDAtNTAiLCI1MC02MCIsIjYwLTcwIikKCiMgQ29udmVydCB0aGUgZmlyc3QgY29sdW1uIChQaHlsdW0pIGludG8gcm93bmFtZXMKcm93bmFtZXMoYXN2LnRheGEuaXR0Lm1lYW4pIDwtIGFzdi50YXhhLml0dC5tZWFuJFBoeWx1bQphc3YudGF4YS5pdHQubWVhbjwtYXMuZGF0YS5mcmFtZShhc3YudGF4YS5pdHQubWVhblstMV0pCgojIENvbnZlcnQgZGF0YWZyYW1lIGludG8gYSBtYXRyaXggZm9yIGhlYXRtYXAKYXN2LnRheGEuaXR0Lm1lYW48LWFzLm1hdHJpeChhc3YudGF4YS5pdHQubWVhbikKCiMgU2NhbGUgbWF0cml4IHZhbHVlcyB0byBnZW5lcmF0ZSBaLXNjb3Jlcwphc3YudGF4YS5pdHQubWVhbjwtc2NhbGUodChhc3YudGF4YS5pdHQubWVhbikpCgojIFNwZWNpZnkgUkNvbG9yQnJld2VyIGN1c3RvbSBjb2xvciBwYWxldHRlCmNvbCA8LSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTAsICJSZFlsQnUiKSkoMjU2KQpgYGAKCmBgYHtyfQojIFBoZWF0bWFwCmFzdi50YXhhLml0dC5tZWFuLnBoZWF0bWFwIDwtIHBoZWF0bWFwKGFzdi50YXhhLml0dC5tZWFuLCBjbHVzdGVyaW5nX21ldGhvZCA9ICJhdmVyYWdlIiwgY2x1c3Rlcl9jb2xzID0gVFJVRSwgY2x1c3Rlcl9yb3dzID0gVFJVRSwgY3V0cmVlX2NvbHMgPSAzLCBjdXRyZWVfcm93cyA9IDMsIGFuZ2xlX2NvbD00NSwgZm9udHNpemVfY29sPTgsIGxlZ2VuZCA9IEZBTFNFKQoKYXN2LnRheGEuaXR0Lm1lYW4ucGhlYXRtYXAudjIgPC0gcGhlYXRtYXAoYXN2LnRheGEuaXR0Lm1lYW4sIGNsdXN0ZXJpbmdfbWV0aG9kID0gImF2ZXJhZ2UiLCBjbHVzdGVyX2NvbHMgPSBUUlVFLCBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgY3V0cmVlX2NvbHMgPSAzLCBnYXBzX3JvdyA9IGMoMiwgNCksIGFuZ2xlX2NvbD00NSwgZm9udHNpemVfY29sPTEwLCBsZWdlbmQgPSBGQUxTRSwgY2VsbGhlaWdodD0xNiwgY2VsbHdpZHRoPTE3KQoKI0V4cG9ydCBhcyAuZXBzICh3aWR0aDo2NTAsIGhlaWdodDo2MDA7ICJpdHQuaGVhdC5zaWx2YS5lcHMiKQpgYGAKCiMjIyBTb2lsIERlcHRoIHB2Y2x1c3QKCklUVCBwdmNsdXN0IGFuYWx5c2lzCmBgYHtyfQphc3YudGF4YS5pdHQubWVhbi5wdmNsdXN0IDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLml0dC5jc3YiKQoKY29sbmFtZXMoYXN2LnRheGEuaXR0Lm1lYW4ucHZjbHVzdCk8LWMoIlBoeWx1bSIsIjAtMTAiLCIxMC0yMCIsIjIwLTMwIiwiMzAtNDAiLCI0MC01MCIsIjUwLTYwIiwiNjAtNzAiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YudGF4YS5pdHQubWVhbi5wdmNsdXN0KSA8LSBhc3YudGF4YS5pdHQubWVhbi5wdmNsdXN0JFBoeWx1bQphc3YudGF4YS5pdHQubWVhbi5wdmNsdXN0PC1hcy5kYXRhLmZyYW1lKGFzdi50YXhhLml0dC5tZWFuLnB2Y2x1c3RbLTFdKQoKIyBTY2FsZSBkYXRhCmFzdi50YXhhLml0dC5tZWFuLnB2Y2x1c3Q8LXNjYWxlKGFzdi50YXhhLml0dC5tZWFuLnB2Y2x1c3QpCmBgYAoKYGBge3J9CnJlc3VsdC4xMGsuaXR0IDwtIHB2Y2x1c3QoYXN2LnRheGEuaXR0Lm1lYW4ucHZjbHVzdCwgbWV0aG9kLmRpc3Q9ImNvciIsIG1ldGhvZC5oY2x1c3Q9ImF2ZXJhZ2UiLCBuYm9vdD0xMDAwMCwgcGFyYWxsZWw9VFJVRSkKCnBsb3QocmVzdWx0LjEway5pdHQpCnB2cmVjdChyZXN1bHQuMTBrLml0dCwgYWxwaGE9MC45NSkKYGBgCgojIyMgVGF4b25vbXkgcHZjbHVzdAoKSVRUIFNvaWwgVGF4YSBwdmNsdXN0IEFuYWx5c2lzCmBgYHtyfQphc3YuZGVwdGguaXR0Lm1lYW4ucHZjbHVzdCA8LSByZWFkLmNzdigiUUlJTUUvU0lMVkEvUl9EYXRhL3RheGEubWVhbi5pdHQuY29scy5jc3YiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YuZGVwdGguaXR0Lm1lYW4ucHZjbHVzdCkgPC0gYXN2LmRlcHRoLml0dC5tZWFuLnB2Y2x1c3QkUGh5bHVtCmFzdi5kZXB0aC5pdHQubWVhbi5wdmNsdXN0PC1hcy5kYXRhLmZyYW1lKGFzdi5kZXB0aC5pdHQubWVhbi5wdmNsdXN0Wy0xXSkKCiMgU2NhbGUgZGF0YQphc3YuZGVwdGguaXR0Lm1lYW4ucHZjbHVzdDwtc2NhbGUoYXN2LmRlcHRoLml0dC5tZWFuLnB2Y2x1c3QpCmBgYAoKYGBge3J9CnJlc3VsdC4xMGsuaXR0LnRheGEgPC0gcHZjbHVzdChhc3YuZGVwdGguaXR0Lm1lYW4ucHZjbHVzdCwgbWV0aG9kLmRpc3Q9ImNvciIsIG1ldGhvZC5oY2x1c3Q9ImF2ZXJhZ2UiLCBuYm9vdD0xMDAwMCwgcGFyYWxsZWw9VFJVRSkKCnBsb3QocmVzdWx0LjEway5pdHQudGF4YSkKcHZyZWN0KHJlc3VsdC4xMGsuaXR0LnRheGEsIGFscGhhPTAuOTUpCmBgYAoKIyMgSW1uYXZhaXQgV1MKCkltcG9ydCBtZWFuIGFidW5kYW5jZSBvZiB0YXhhIGJ5IGRlcHRoIGZvciBJV1MgaGVhdG1hcApgYGB7cn0KYXN2LnRheGEuaXdzLm1lYW4gPC0gcmVhZC5jc3YoIlFJSU1FL1NJTFZBL1JfRGF0YS90YXhhLm1lYW4uaXdzLmNzdiIpCgpjb2xuYW1lcyhhc3YudGF4YS5pd3MubWVhbik8LWMoIlBoeWx1bSIsIjAtMTAiLCIxMC0yMCIsIjIwLTMwIiwiMzAtNDAiLCI0MC01MCIsIjUwLTYwIiwiNjAtNzAiLCI3MC04MCIsIjgwLTkwIiwiOTAtMTAwIikKCiMgQ29udmVydCB0aGUgZmlyc3QgY29sdW1uIChQaHlsdW0pIGludG8gcm93bmFtZXMKcm93bmFtZXMoYXN2LnRheGEuaXdzLm1lYW4pIDwtIGFzdi50YXhhLml3cy5tZWFuJFBoeWx1bQphc3YudGF4YS5pd3MubWVhbjwtYXMuZGF0YS5mcmFtZShhc3YudGF4YS5pd3MubWVhblstMV0pCgojIENvbnZlcnQgZGF0YWZyYW1lIGludG8gYSBtYXRyaXggZm9yIGhlYXRtYXAKYXN2LnRheGEuaXdzLm1lYW48LWFzLm1hdHJpeChhc3YudGF4YS5pd3MubWVhbikKCiMgU2NhbGUgbWF0cml4IHZhbHVlcyB0byBnZW5lcmF0ZSBaLXNjb3Jlcwphc3YudGF4YS5pd3MubWVhbjwtc2NhbGUodChhc3YudGF4YS5pd3MubWVhbikpCgojIFNwZWNpZnkgUkNvbG9yQnJld2VyIGN1c3RvbSBjb2xvciBwYWxldHRlCmNvbCA8LSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTAsICJSZFlsQnUiKSkoMjU2KQpgYGAKCmBgYHtyfQojIFBoZWF0bWFwCmFzdi50YXhhLml3cy5tZWFuLnBoZWF0bWFwIDwtIHBoZWF0bWFwKGFzdi50YXhhLml3cy5tZWFuLCBjbHVzdGVyaW5nX21ldGhvZCA9ICJhdmVyYWdlIiwgY2x1c3Rlcl9jb2xzID0gVFJVRSwgY2x1c3Rlcl9yb3dzID0gVFJVRSwgY3V0cmVlX2NvbHMgPSAyLCBjdXRyZWVfcm93cyA9IDQsIGFuZ2xlX2NvbD00NSwgZm9udHNpemVfY29sPTgsIGxlZ2VuZCA9IEZBTFNFKQoKYXN2LnRheGEuaXdzLm1lYW4ucGhlYXRtYXAudjIgPC0gcGhlYXRtYXAoYXN2LnRheGEuaXdzLm1lYW4sIGNsdXN0ZXJpbmdfbWV0aG9kID0gImF2ZXJhZ2UiLCBjbHVzdGVyX2NvbHMgPSBUUlVFLCBjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgY3V0cmVlX2NvbHMgPSAzLCBnYXBzX3JvdyA9IGMoMSwgNCwgNiksIGFuZ2xlX2NvbD00NSwgZm9udHNpemVfY29sPTEwLCBsZWdlbmQgPSBGQUxTRSwgY2VsbGhlaWdodD0xNCwgY2VsbHdpZHRoPTE3KQoKI0V4cG9ydCBhcyAuZXBzICh3aWR0aDo2NTAsIGhlaWdodDo2MDA7ICJpd3MuaGVhdC5zaWx2YS5lcHMiKQpgYGAKCiMjIyBTb2lsIERlcHRoIHB2Y2x1c3QKCklXUyBwdmNsdXN0IGFuYWx5c2lzCmBgYHtyfQphc3YudGF4YS5pd3MubWVhbi5wdmNsdXN0IDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLml3cy5jc3YiKQoKY29sbmFtZXMoYXN2LnRheGEuaXdzLm1lYW4ucHZjbHVzdCk8LWMoIlBoeWx1bSIsIjAtMTAiLCIxMC0yMCIsIjIwLTMwIiwiMzAtNDAiLCI0MC01MCIsIjUwLTYwIiwiNjAtNzAiLCI3MC04MCIsIjgwLTkwIiwiOTAtMTAwIikKCiMgQ29udmVydCB0aGUgZmlyc3QgY29sdW1uIChQaHlsdW0pIGludG8gcm93bmFtZXMKcm93bmFtZXMoYXN2LnRheGEuaXdzLm1lYW4ucHZjbHVzdCkgPC0gYXN2LnRheGEuaXdzLm1lYW4ucHZjbHVzdCRQaHlsdW0KYXN2LnRheGEuaXdzLm1lYW4ucHZjbHVzdDwtYXMuZGF0YS5mcmFtZShhc3YudGF4YS5pd3MubWVhbi5wdmNsdXN0Wy0xXSkKCiMgU2NhbGUgZGF0YQphc3YudGF4YS5pd3MubWVhbi5wdmNsdXN0PC1zY2FsZShhc3YudGF4YS5pd3MubWVhbi5wdmNsdXN0KQpgYGAKCmBgYHtyfQpyZXN1bHQuMTBrLml3cyA8LSBwdmNsdXN0KGFzdi50YXhhLml3cy5tZWFuLnB2Y2x1c3QsIG1ldGhvZC5kaXN0PSJjb3IiLCBtZXRob2QuaGNsdXN0PSJhdmVyYWdlIiwgbmJvb3Q9MTAwMDAsIHBhcmFsbGVsPVRSVUUpCgpwbG90KHJlc3VsdC4xMGsuaXdzKQpwdnJlY3QocmVzdWx0LjEway5pd3MsIGFscGhhPTAuOSkKYGBgCgojIyMgVGF4b25vbXkgcHZjbHVzdAoKSVdTIFNvaWwgVGF4YSBwdmNsdXN0IEFuYWx5c2lzCmBgYHtyfQphc3YuZGVwdGguaXdzLm1lYW4ucHZjbHVzdCA8LSByZWFkLmNzdigiUUlJTUUvU0lMVkEvUl9EYXRhL3RheGEubWVhbi5pd3MuY29scy5jc3YiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YuZGVwdGguaXdzLm1lYW4ucHZjbHVzdCkgPC0gYXN2LmRlcHRoLml3cy5tZWFuLnB2Y2x1c3QkUGh5bHVtCmFzdi5kZXB0aC5pd3MubWVhbi5wdmNsdXN0PC1hcy5kYXRhLmZyYW1lKGFzdi5kZXB0aC5pd3MubWVhbi5wdmNsdXN0Wy0xXSkKCiMgU2NhbGUgZGF0YQphc3YuZGVwdGguaXdzLm1lYW4ucHZjbHVzdDwtc2NhbGUoYXN2LmRlcHRoLml3cy5tZWFuLnB2Y2x1c3QpCmBgYAoKYGBge3J9CnJlc3VsdC4xMGsuaXdzLnRheGEgPC0gcHZjbHVzdChhc3YuZGVwdGguaXdzLm1lYW4ucHZjbHVzdCwgbWV0aG9kLmRpc3Q9ImNvciIsIG1ldGhvZC5oY2x1c3Q9ImF2ZXJhZ2UiLCBuYm9vdD0xMDAwMCwgcGFyYWxsZWw9VFJVRSkKYGBgCgpgYGB7cn0KcGxvdChyZXN1bHQuMTBrLml3cy50YXhhKQpwdnJlY3QocmVzdWx0LjEway5pd3MudGF4YSwgYWxwaGE9MC45NSkKYGBgCgojIyBTYWd3b24gTUFUCgpJbXBvcnQgbWVhbiBhYnVuZGFuY2Ugb2YgdGF4YSBieSBkZXB0aCBmb3IgU1RUIGhlYXRtYXAKYGBge3J9CmFzdi50YXhhLnN0dC5tZWFuIDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLnN0dC5jc3YiKQoKY29sbmFtZXMoYXN2LnRheGEuc3R0Lm1lYW4pPC1jKCJQaHlsdW0iLCIwLTEwIiwiMTAtMjAiLCIyMC0zMCIsIjMwLTQwIiwiNDAtNTAiLCI1MC02MCIsIjYwLTcwIiwiNzAtODAiLCI4MC05MCIpCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoUGh5bHVtKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKGFzdi50YXhhLnN0dC5tZWFuKSA8LSBhc3YudGF4YS5zdHQubWVhbiRQaHlsdW0KYXN2LnRheGEuc3R0Lm1lYW48LWFzLmRhdGEuZnJhbWUoYXN2LnRheGEuc3R0Lm1lYW5bLTFdKQoKIyBDb252ZXJ0IGRhdGFmcmFtZSBpbnRvIGEgbWF0cml4IGZvciBoZWF0bWFwCmFzdi50YXhhLnN0dC5tZWFuPC1hcy5tYXRyaXgoYXN2LnRheGEuc3R0Lm1lYW4pCgojIFNjYWxlIG1hdHJpeCB2YWx1ZXMgdG8gZ2VuZXJhdGUgWi1zY29yZXMKYXN2LnRheGEuc3R0Lm1lYW48LXNjYWxlKHQoYXN2LnRheGEuc3R0Lm1lYW4pKQoKIyBTcGVjaWZ5IFJDb2xvckJyZXdlciBjdXN0b20gY29sb3IgcGFsZXR0ZQpjb2wgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDEwLCAiUmRZbEJ1IikpKDI1NikKYGBgCgpgYGB7cn0KIyBQaGVhdG1hcAphc3YudGF4YS5zdHQubWVhbi5waGVhdG1hcCA8LSBwaGVhdG1hcChhc3YudGF4YS5zdHQubWVhbiwgY2x1c3RlcmluZ19tZXRob2QgPSAiY29tcGxldGUiLCBjbHVzdGVyX2NvbHMgPSBUUlVFLCBjbHVzdGVyX3Jvd3MgPSBUUlVFLCBjdXRyZWVfY29scyA9IDIsIGN1dHJlZV9yb3dzID0gMiwgYW5nbGVfY29sPTQ1LCBmb250c2l6ZV9jb2w9OCwgbGVnZW5kID0gRkFMU0UpCgphc3YudGF4YS5zdHQubWVhbi5waGVhdG1hcC52MiA8LSBwaGVhdG1hcChhc3YudGF4YS5zdHQubWVhbiwgY2x1c3RlcmluZ19tZXRob2QgPSAiYXZlcmFnZSIsIGNsdXN0ZXJfY29scyA9IFRSVUUsIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCBjdXRyZWVfY29scyA9IDMsIGdhcHNfcm93ID0gYygzLDUpLCBhbmdsZV9jb2w9NDUsIGZvbnRzaXplX2NvbD0xMCwgbGVnZW5kID0gRkFMU0UsIGNlbGxoZWlnaHQ9MTYsIGNlbGx3aWR0aD0xOCkKCiNFeHBvcnQgYXMgLmVwcyAod2lkdGg6NjUwLCBoZWlnaHQ6NjAwOyAic3R0LmhlYXQuc2lsdmEuZXBzIikKYGBgCgojIyMgU29pbCBEZXB0aCBwdmNsdXN0CgpTVFQgcHZjbHVzdCBhbmFseXNpcwpgYGB7cn0KYXN2LnRheGEuc3R0Lm1lYW4ucHZjbHVzdCA8LSByZWFkLmNzdigiUUlJTUUvU0lMVkEvUl9EYXRhL3RheGEubWVhbi5zdHQuY3N2IikKCmNvbG5hbWVzKGFzdi50YXhhLnN0dC5tZWFuLnB2Y2x1c3QpPC1jKCJQaHlsdW0iLCIwLTEwIiwiMTAtMjAiLCIyMC0zMCIsIjMwLTQwIiwiNDAtNTAiLCI1MC02MCIsIjYwLTcwIiwiNzAtODAiLCI4MC05MCIpCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoUGh5bHVtKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKGFzdi50YXhhLnN0dC5tZWFuLnB2Y2x1c3QpIDwtIGFzdi50YXhhLnN0dC5tZWFuLnB2Y2x1c3QkUGh5bHVtCmFzdi50YXhhLnN0dC5tZWFuLnB2Y2x1c3Q8LWFzLmRhdGEuZnJhbWUoYXN2LnRheGEuc3R0Lm1lYW4ucHZjbHVzdFstMV0pCgojIFNjYWxlIGRhdGEKYXN2LnRheGEuc3R0Lm1lYW4ucHZjbHVzdDwtc2NhbGUoYXN2LnRheGEuc3R0Lm1lYW4ucHZjbHVzdCkKYGBgCgpgYGB7cn0KcmVzdWx0LjEway5zdHQgPC0gcHZjbHVzdChhc3YudGF4YS5zdHQubWVhbi5wdmNsdXN0LCBtZXRob2QuZGlzdD0iY29yIiwgbWV0aG9kLmhjbHVzdD0iYXZlcmFnZSIsIG5ib290PTEwMDAwLCBwYXJhbGxlbD1UUlVFKQoKcGxvdChyZXN1bHQuMTBrLnN0dCkKcHZyZWN0KHJlc3VsdC4xMGsuc3R0LCBhbHBoYT0wLjk1KQpgYGAKCiMjIyBUYXhvbm9teSBwdmNsdXN0CgpTVFQgU29pbCBUYXhhIHB2Y2x1c3QgQW5hbHlzaXMKYGBge3J9CmFzdi5kZXB0aC5zdHQubWVhbi5wdmNsdXN0IDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLnN0dC5jb2xzLmNzdiIpCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoUGh5bHVtKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKGFzdi5kZXB0aC5zdHQubWVhbi5wdmNsdXN0KSA8LSBhc3YuZGVwdGguc3R0Lm1lYW4ucHZjbHVzdCRQaHlsdW0KYXN2LmRlcHRoLnN0dC5tZWFuLnB2Y2x1c3Q8LWFzLmRhdGEuZnJhbWUoYXN2LmRlcHRoLnN0dC5tZWFuLnB2Y2x1c3RbLTFdKQoKIyBTY2FsZSBkYXRhCmFzdi5kZXB0aC5zdHQubWVhbi5wdmNsdXN0PC1zY2FsZShhc3YuZGVwdGguc3R0Lm1lYW4ucHZjbHVzdCkKYGBgCgpgYGB7cn0KcmVzdWx0LjEway5zdHQudGF4YSA8LSBwdmNsdXN0KGFzdi5kZXB0aC5zdHQubWVhbi5wdmNsdXN0LCBtZXRob2QuZGlzdD0iY29yIiwgbWV0aG9kLmhjbHVzdD0iYXZlcmFnZSIsIG5ib290PTEwMDAwLCBwYXJhbGxlbD1UUlVFKQoKcGxvdChyZXN1bHQuMTBrLnN0dC50YXhhKQpwdnJlY3QocmVzdWx0LjEway5zdHQudGF4YSwgYWxwaGE9MC45NSkKYGBgCgojIyBTYWd3b24gV1MKCkltcG9ydCBtZWFuIGFidW5kYW5jZSBvZiB0YXhhIGJ5IGRlcHRoIGZvciBTV1MgaGVhdG1hcApgYGB7cn0KYXN2LnRheGEuc3dzLm1lYW4gPC0gcmVhZC5jc3YoIlFJSU1FL1NJTFZBL1JfRGF0YS90YXhhLm1lYW4uc3dzLmNzdiIpCgpjb2xuYW1lcyhhc3YudGF4YS5zd3MubWVhbik8LWMoIlBoeWx1bSIsIjAtMTAiLCIxMC0yMCIsIjIwLTMwIiwiMzAtNDAiLCI0MC01MCIsIjUwLTYwIiwiNjAtNzAiKQoKIyBDb252ZXJ0IHRoZSBmaXJzdCBjb2x1bW4gKFBoeWx1bSkgaW50byByb3duYW1lcwpyb3duYW1lcyhhc3YudGF4YS5zd3MubWVhbikgPC0gYXN2LnRheGEuc3dzLm1lYW4kUGh5bHVtCmFzdi50YXhhLnN3cy5tZWFuPC1hcy5kYXRhLmZyYW1lKGFzdi50YXhhLnN3cy5tZWFuWy0xXSkKCiMgQ29udmVydCBkYXRhZnJhbWUgaW50byBhIG1hdHJpeCBmb3IgaGVhdG1hcAphc3YudGF4YS5zd3MubWVhbjwtYXMubWF0cml4KGFzdi50YXhhLnN3cy5tZWFuKQoKIyBTY2FsZSBtYXRyaXggdmFsdWVzIHRvIGdlbmVyYXRlIFotc2NvcmVzCmFzdi50YXhhLnN3cy5tZWFuPC1zY2FsZSh0KGFzdi50YXhhLnN3cy5tZWFuKSkKCiMgU3BlY2lmeSBSQ29sb3JCcmV3ZXIgY3VzdG9tIGNvbG9yIHBhbGV0dGUKY29sIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCgxMCwgIlJkWWxCdSIpKSgyNTYpCmBgYAoKYGBge3J9CiMgUGhlYXRtYXAKYXN2LnRheGEuc3dzLm1lYW4ucGhlYXRtYXAgPC0gcGhlYXRtYXAoYXN2LnRheGEuc3dzLm1lYW4sIGNsdXN0ZXJpbmdfbWV0aG9kID0gImF2ZXJhZ2UiLCBjbHVzdGVyX2NvbHMgPSBUUlVFLCBjbHVzdGVyX3Jvd3MgPSBUUlVFLCBjdXRyZWVfY29scyA9IDIsIGN1dHJlZV9yb3dzID0gMiwgYW5nbGVfY29sPTQ1LCBmb250c2l6ZV9jb2w9OCwgbGVnZW5kID0gRkFMU0UpCgphc3YudGF4YS5zd3MubWVhbi5waGVhdG1hcC52MiA8LSBwaGVhdG1hcChhc3YudGF4YS5zd3MubWVhbiwgY2x1c3RlcmluZ19tZXRob2QgPSAiYXZlcmFnZSIsIGNsdXN0ZXJfY29scyA9IFRSVUUsIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCBjdXRyZWVfY29scyA9IDIsIGdhcHNfcm93ID0gNCwgYW5nbGVfY29sPTQ1LCBmb250c2l6ZV9jb2w9MTAsIGxlZ2VuZCA9IEZBTFNFLCBjZWxsaGVpZ2h0PTE2LCBjZWxsd2lkdGg9MTYpCgojRXhwb3J0IGFzIC5lcHMgKHdpZHRoOjY1MCwgaGVpZ2h0OjYwMDsgInN3cy5oZWF0LnNpbHZhLmVwcyIpCmBgYAoKIyMjIFNvaWwgRGVwdGggcHZjbHVzdAoKU1dTIHB2Y2x1c3QgYW5hbHlzaXMKYGBge3J9CmFzdi50YXhhLnN3cy5tZWFuLnB2Y2x1c3QgPC0gcmVhZC5jc3YoIlFJSU1FL1NJTFZBL1JfRGF0YS90YXhhLm1lYW4uc3dzLmNzdiIpCgpjb2xuYW1lcyhhc3YudGF4YS5zd3MubWVhbi5wdmNsdXN0KTwtYygiUGh5bHVtIiwiMC0xMCIsIjEwLTIwIiwiMjAtMzAiLCIzMC00MCIsIjQwLTUwIiwiNTAtNjAiLCI2MC03MCIpCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoUGh5bHVtKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKGFzdi50YXhhLnN3cy5tZWFuLnB2Y2x1c3QpIDwtIGFzdi50YXhhLnN3cy5tZWFuLnB2Y2x1c3QkUGh5bHVtCmFzdi50YXhhLnN3cy5tZWFuLnB2Y2x1c3Q8LWFzLmRhdGEuZnJhbWUoYXN2LnRheGEuc3dzLm1lYW4ucHZjbHVzdFstMV0pCgojIFNjYWxlIGRhdGEKYXN2LnRheGEuc3dzLm1lYW4ucHZjbHVzdDwtc2NhbGUoYXN2LnRheGEuc3dzLm1lYW4ucHZjbHVzdCkKYGBgCgpgYGB7cn0KcmVzdWx0LjEway5zd3MgPC0gcHZjbHVzdChhc3YudGF4YS5zd3MubWVhbi5wdmNsdXN0LCBtZXRob2QuZGlzdD0iY29yIiwgbWV0aG9kLmhjbHVzdD0iYXZlcmFnZSIsIG5ib290PTEwMDAwLCBwYXJhbGxlbD1UUlVFKQoKcGxvdChyZXN1bHQuMTBrLnN3cykKcHZyZWN0KHJlc3VsdC4xMGsuc3dzLCBhbHBoYT0wLjk1KQpgYGAKCiMjIyBUYXhvbm9teSBwdmNsdXN0CgpTV1MgU29pbCBUYXhhIHB2Y2x1c3QgQW5hbHlzaXMKYGBge3J9CmFzdi5kZXB0aC5zd3MubWVhbi5wdmNsdXN0IDwtIHJlYWQuY3N2KCJRSUlNRS9TSUxWQS9SX0RhdGEvdGF4YS5tZWFuLnN3cy5jb2xzLmNzdiIpCgojIENvbnZlcnQgdGhlIGZpcnN0IGNvbHVtbiAoUGh5bHVtKSBpbnRvIHJvd25hbWVzCnJvd25hbWVzKGFzdi5kZXB0aC5zd3MubWVhbi5wdmNsdXN0KSA8LSBhc3YuZGVwdGguc3dzLm1lYW4ucHZjbHVzdCRQaHlsdW0KYXN2LmRlcHRoLnN3cy5tZWFuLnB2Y2x1c3Q8LWFzLmRhdGEuZnJhbWUoYXN2LmRlcHRoLnN3cy5tZWFuLnB2Y2x1c3RbLTFdKQoKIyBTY2FsZSBkYXRhCmFzdi5kZXB0aC5zd3MubWVhbi5wdmNsdXN0PC1zY2FsZShhc3YuZGVwdGguc3dzLm1lYW4ucHZjbHVzdCkKYGBgCgpgYGB7cn0KcmVzdWx0LjEway5zd3MudGF4YSA8LSBwdmNsdXN0KGFzdi5kZXB0aC5zd3MubWVhbi5wdmNsdXN0LCBtZXRob2QuZGlzdD0iY29yIiwgbWV0aG9kLmhjbHVzdD0iYXZlcmFnZSIsIG5ib290PTEwMDAwLCBwYXJhbGxlbD1UUlVFKQoKcGxvdChyZXN1bHQuMTBrLnN3cy50YXhhKQpwdnJlY3QocmVzdWx0LjEway5zd3MudGF4YSwgYWxwaGE9MC45NSkKYGBgCgpgYGB7ciBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQojIEZvciBjYWxsaW5nIHBsb3RzIGFuZCBzYXZpbmcgYXMgLmVwcyAod2lkdGg6IDUyNTsgaGVpZ2h0OiA2NTApCmFzdi50YXhhLnR0dC5tZWFuLnBoZWF0bWFwLnYyCmFzdi50YXhhLnR3cy5tZWFuLnBoZWF0bWFwLnYyCmFzdi50YXhhLml0dC5tZWFuLnBoZWF0bWFwLnYyCmFzdi50YXhhLml3cy5tZWFuLnBoZWF0bWFwLnYyCmFzdi50YXhhLnN0dC5tZWFuLnBoZWF0bWFwLnYyCmFzdi50YXhhLnN3cy5tZWFuLnBoZWF0bWFwLnYyCmBgYAoKCiMgUmVwcm9kdWNpYmlsaXR5CgpUaGUgc2Vzc2lvbiBpbmZvcm1hdGlvbiBpcyBwcm92aWRlZCBmb3IgZnVsbCByZXByb2R1Y2liaWxpdHkuCmBgYHtyfQpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkKYGBgCg==