1 Introduction

Physicochemical and biological data from anaerobic processes, which underwent 16S rRNA gene sequencing in public SRA repositories of the NCBI, were analyzed to propose potential microbial indicators. The statistical analyses involved categorizing CH₄ yield based on histogram bins, which were then used for further analyses, including diversity analysis, significance test, differential analysis, Venn diagram construction, and correlation analysis. These methods allowed for the identification of significant changes in physicochemical parameters and microbial data, ultimately leading to the inference of potential microbial indicators. This RPub presents the code framework that guided the decision-making process for proposing microbial indicators in anaerobic digesters fed with FW/OFMSW.

For further details, refer to the article “Identifying reliable microbial indicators in anaerobic digestion of organic solid waste: Insights from a meta-analysis”

The statistical framework was divided into two parts: -Part 1: Determination of methane yield performance categories to evaluate OFMSW/FW digesters in terms of physicochemical response and taxonomic diversity. -Part 2: Identification of microbial indicators to assess the performance of OFMSW/FW digesters.

2 Categorization of samples according to CH4 yield

CH4 yield (measured in mL CH4/gVSadded) is commonly used as a process indicator; thus, it was selected as both a categorical and quantitative variable for classifying AD performance. This classification, known as the methane yield category, was derived from the classes of a beta distribution histogram following the Freedman-Diaconis rule.

Freedman-Diaconis rule equation \[ \text{Class width} = 2 \quad \frac{\text{IQR}}{\sqrt[3]{n}} \] where IQR is the interquartile range of the data, and n is the number of observations.

# Load packages
library(readr)
library(here)
library(DT)
library(grDevices)
library(skimr)
library(janitor)
library(fitdistrplus)
library(fdth)
library(ggplot2)
# Load Physicochemical data from meta-analysis
df <- read_csv(here("data", "meta-analysis-physicochemical-data.csv"), 
               locale = locale(encoding = "latin1"), show_col_types = FALSE) %>%
      as.data.frame()
# Data cleaning
# Replace "ND" with NA in all character-type columns
df[] <- lapply(df, function(x) {
        if (is.character(x)) {
        x[x == "ND"] <- NA
        }
        return(x)
        })

# Automatically convert columns class (character, numeric) according to the values of their cells and clean names
df <-  df %>%
       mutate_all(~ type.convert(as.character(.), as.is = TRUE)) %>% 
       clean_names()

# Create a "pr_ac" and "tan_acetic" ratio variable
df <-  df %>%
       mutate(pr_ac = acetic_acid_mg_l / propionic_acid_mg_l,
              pr_ac = ifelse(is.finite(pr_ac), pr_ac, NA),
              tan_acetic = acetic_acid_mg_l / total_ammonia_nitrogen_mg_l,
              tan_acetic = ifelse(is.finite(tan_acetic), tan_acetic, NA))

# Save object df as RDS object for upstreams analysis (part 2)
saveRDS(df, file = here("rds","df_physicochemical_data_metanalysis.rds"))
# Table with physicochemical parameters
# The following table displays the information collected from multiple FW/OFMSW anaerobic processes.
datatable(df)
# Summary of Descriptive Statistics
skim(df)
Data summary
Name df
Number of rows 178
Number of columns 39
_______________________
Column type frequency:
character 16
numeric 23
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
sample_id 0 1.00 4 6 0 178 0
label_study 0 1.00 3 66 0 138 0
run_accesion 0 1.00 10 11 0 178 0
feedstock 0 1.00 10 74 0 8 0
reactor_type 45 0.75 3 9 0 6 0
scale_up 0 1.00 9 11 0 3 0
feeding_regime 0 1.00 5 15 0 3 0
digestion_process 0 1.00 17 20 0 2 0
inoculum_source 0 1.00 18 47 0 7 0
process_status 127 0.29 6 12 0 6 0
freedman_class 80 0.55 2 2 0 6 0
group 0 1.00 7 16 0 2 0
primers 0 1.00 65 81 0 54 0
region_of_16s_r_rna 0 1.00 2 5 0 3 0
reference 0 1.00 14 26 0 12 0
doi 0 1.00 41 47 0 12 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
temperature_c 0 1.00 39.61 6.68 35.0 37.00 37.0 37.00 55.00 ▇▁▁▁▂
organic_loading_rate_g_vs_l_d 106 0.40 4.00 3.98 0.4 3.00 3.0 3.00 18.90 ▇▁▁▁▁
hrt_d 125 0.30 11.23 13.18 3.0 10.00 10.0 10.00 100.00 ▇▁▁▁▁
total_ammonia_nitrogen_mg_l 51 0.71 3434.70 1839.11 532.8 1970.00 3000.0 4320.00 7500.00 ▅▇▅▃▂
free_ammonia_nitrogen_mg_l 150 0.16 100.91 50.76 24.9 80.00 100.0 137.00 186.00 ▆▅▇▂▇
volatile_fatty_acid_mg_l 146 0.18 3119.16 3033.15 487.0 806.00 1652.0 4388.25 9910.00 ▇▂▂▁▂
acetic_acid_mg_l 65 0.63 827.80 928.63 0.0 91.00 451.0 1333.00 3266.00 ▇▂▂▁▁
propionic_acid_mg_l 65 0.63 767.70 1417.16 0.0 40.00 195.0 439.00 5768.00 ▇▁▁▁▁
butyric_acid_mg_l 98 0.45 137.06 191.14 0.0 8.75 64.0 221.00 1035.00 ▇▂▁▁▁
valeric_acid_mg_l 123 0.31 578.21 683.26 1.0 90.40 255.0 813.50 2000.00 ▇▂▁▂▂
caproic_acid_mg_l 171 0.04 296.14 332.23 1.0 1.00 250.0 499.50 821.00 ▇▂▂▂▂
isobutyric_acid_mg_l 129 0.28 204.84 189.05 0.0 91.00 96.0 416.00 639.00 ▇▂▁▂▁
isovaleric_acid_mg_l 139 0.22 217.21 241.20 0.0 1.00 101.0 418.00 666.00 ▇▂▁▂▂
formic_acid_mg_l 172 0.03 10.00 0.00 10.0 10.00 10.0 10.00 10.00 ▁▁▇▁▁
myristic_acid_mg_l 148 0.17 471.30 276.63 105.0 220.00 375.0 729.00 916.00 ▆▇▁▅▅
palmitic_acid_mg_l 148 0.17 4977.00 3667.00 355.0 1568.75 3357.0 8618.00 10847.00 ▇▇▁▅▅
stearic_acid_mg_l 148 0.17 2889.33 1786.59 65.0 1034.00 2703.5 4803.00 5252.00 ▆▂▃▁▇
oleic_acid_mg_l 148 0.17 2664.57 1474.35 39.0 1232.00 2257.5 4019.00 4756.00 ▁▅▆▁▇
linoleic_acid_mg_l 148 0.17 655.70 218.75 131.0 552.00 711.5 778.00 923.00 ▁▂▂▆▇
sulfate_mg_l 176 0.01 118.50 6.36 114.0 116.25 118.5 120.75 123.00 ▇▁▁▁▇
ch4_yield_m_lch4_g_v_sadded 80 0.55 370.21 187.67 0.0 237.00 428.0 533.25 684.00 ▃▅▃▇▅
pr_ac 81 0.54 8.40 31.45 0.0 0.81 2.2 4.00 182.50 ▇▁▁▁▁
tan_acetic 96 0.46 0.32 0.30 0.0 0.06 0.2 0.44 0.97 ▇▇▂▁▃
# Select the CH4 yield column considering it as the variable of interest that will define the performance categories
# CH4 yield data frame
CH4_yield_df <- df %>%
                dplyr::filter(!is.na(ch4_yield_m_lch4_g_v_sadded) & ch4_yield_m_lch4_g_v_sadded != "") %>%
                rename(YCH4_mLgVS = ch4_yield_m_lch4_g_v_sadded)

# Save object CH4_yield_df as RDS object for upstreams analysis (part 2)
saveRDS(CH4_yield_df, file = here("rds","CH4_yield_df.rds"))
# Normality test - Shapiro-Wilk test If p > 0.05, the data follow a normal distribution
shapiro.test(CH4_yield_df$YCH4_mLgVS) # p < 0.05
## 
##  Shapiro-Wilk normality test
## 
## data:  CH4_yield_df$YCH4_mLgVS
## W = 0.91781, p-value = 1.301e-05
# Since p < 0.05 the data do not follow a normal distribution. The results indicate a beta distribution.
descdist(CH4_yield_df$YCH4_mLgVS, discrete = FALSE, boot = 1000) 

## summary statistics
## ------
## min:  0   max:  684 
## median:  428 
## mean:  370.2112 
## estimated sd:  187.6712 
## estimated skewness:  -0.5623359 
## estimated kurtosis:  2.233972
# See adjustments. Compare normal distribution and beta distribution
fit.norm <- fitdist(CH4_yield_df$YCH4_mLgVS, "norm")
# Plot the data distribution
plot(fit.norm)

# Data exploration
quantile(CH4_yield_df$YCH4_mLgVS)
##     0%    25%    50%    75%   100% 
##   0.00 237.00 428.00 533.25 684.00
# Define intervals using the Freedman–Diaconis rule
interval_FD <- nclass.FD(CH4_yield_df$YCH4_mLgVS)

# Store the CH4 yield data in a vector
data_YCH4_mLgVS <- CH4_yield_df$YCH4_mLgVS

# Create a table with the CH4 yield intervals obtained
table.FD <- transform(table(cut(data_YCH4_mLgVS, breaks = interval_FD))) %>%
            rename(YCH4_mLgVS_intervals = Var1) # Rename column

datatable(table.FD)
# Extract intervals and values from "table.FD"
# Get the intervals from the "YCH4_mLgVS_intervals" column in "table.FD"
intervals <- table.FD$YCH4_mLgVS_intervals
# Extract the limits for each interval for the cut() function
breaks <- c(-Inf, 114, 228, 342, 456, 570, 685)  # The cutoff values for each class

# Use cut() to categorize the values in "data_YCH4_mLgVS" according to the intervals
categories <- cut(data_YCH4_mLgVS, breaks = breaks, labels = c("C1", "C2", "C3", "C4", "C5", "C6"), include.lowest = TRUE)

# Create the dataframe with the yields and categories
CH4_yield_df_2 <- data.frame(
                  YCH4_mLgVS = data_YCH4_mLgVS,
                  Freedman = as.factor(categories))
# Histogram with Freedman-Diaconis classes
my_bar_FD <- barplot(table.FD$Freq, 
                    border = FALSE,
                    las = 2,
                    ylim = c(0,40),
                    ylab = "Frequency",
                    xlab = "Classes of CH4 yield in Food-waste/OFMSW anaerobic digesters",
                    names.arg = c("C1", "C2", "C3", "C4", "C5", "C6"),
                    cex.axis = 0.75,
                    cex.lab = 0.75,
                    cex.names = 0.75,
                    col = "darkred")

# Add separation line (Interval size = 1.2)
abline(v = c(1.3, 2.5, 3.7, 4.9, 6.1, 7.3, 8.5), col = "grey") # FD
text(my_bar_FD, table.FD$Freq + 1.4, paste("n: ", table.FD$Freq, sep = ""), cex = 0.5)

Histogram showing the frequency distribution of CH4 yields grouped by class.

# Assign different colors to each class
colors <- c("#cc3300ff", "#ff9966ff", "#004cffff", "#ffcc00ff", "#99cc33ff", "#339900ff") 

# Create the boxplot with different colors for each class
myplot_FD <- boxplot(YCH4_mLgVS ~ Freedman, data= CH4_yield_df_2, ylab="", xlab = "",
                     border = colors,  # Assign colors to the boxes
                     col = colors,     # Colors for the inside of the boxes
                     xaxt="n",         # Remove ticks from the x-axis
                     yaxt = "n")        # Remove ticks from the y-axis

# Y-axis
axis(2, ylim=c(0,1000), col="black", las=1, cex.axis = 0.75) 
mtext("CH4 yield (mLCH4 gVS)", side=2, line=2.2, cex = 0.75)

# X-axis
my_names <- sapply(strsplit(myplot_FD$names, '\\.') , function(x) x[[1]])
my_names <- my_names[seq(1, length(my_names), 1)]
axis(1, at = seq(1, 6, 1), labels = my_names, tick=FALSE, cex.axis = 0.75)
mtext("Freedman-Diaconis Classes", side=1, line=2, cex = 0.75)

# Add grey vertical lines
for(i in seq(0.5 , 20 , 1)){ 
  abline(v=i, lty=1, col="grey")
}

Boxplot illustrating CH4 yield values grouped for each class.

3 Physicochemical parameters

The physicochemical parameters and methane yield categories were assessed using the Kruskal-Wallis test and Wilcoxon rank sum test with Benjamini-Hochberg correction for tests among and within methane yield categories respectively.

# Load packages
library(here)
library(dplyr)      
library(reshape2)   
library(ggplot2)    
library(knitr)      
library(kableExtra) 
library(DT)
library(ggtext)
# Select relevant physicochemical parameters
op_cond_wide <- CH4_yield_df %>%
                dplyr::select("sample_id", "total_ammonia_nitrogen_mg_l", "free_ammonia_nitrogen_mg_l", "volatile_fatty_acid_mg_l",
                       "acetic_acid_mg_l", "propionic_acid_mg_l", "butyric_acid_mg_l", "valeric_acid_mg_l", "caproic_acid_mg_l",
                       "isobutyric_acid_mg_l", "isovaleric_acid_mg_l", "formic_acid_mg_l", "myristic_acid_mg_l",
                       "palmitic_acid_mg_l", "stearic_acid_mg_l", "oleic_acid_mg_l", "linoleic_acid_mg_l", "sulfate_mg_l",
                       "YCH4_mLgVS", "pr_ac", "tan_acetic", "freedman_class")

# Change dataframe format from wide format to long format
op_cond <- melt(op_cond_wide)

# Convert CH4 yield categories en factor class
freedman_levels <- c("C1","C2","C3","C4","C5","C6")
op_cond$freedman_class <- factor(op_cond$freedman_class, levels = freedman_levels)
# See physicochemical parameters dataframe
datatable(op_cond)
# Select physicochemical parameters
variables_interest <- c("volatile_fatty_acid_mg_l","acetic_acid_mg_l","butyric_acid_mg_l",
                       "propionic_acid_mg_l","isobutyric_acid_mg_l","isovaleric_acid_mg_l",
                       "valeric_acid_mg_l","total_ammonia_nitrogen_mg_l","free_ammonia_nitrogen_mg_l",
                       "linoleic_acid_mg_l","myristic_acid_mg_l", "oleic_acid_mg_l",
                       "palmitic_acid_mg_l","stearic_acid_mg_l","pr_ac", "tan_acetic")
# Create an empty list to store the results of significance tests and figures.
results <- list()

# Iteration over each variable
for (var in variables_interest) {
  
  phys_data <- op_cond %>%
    dplyr::filter(variable == var) %>%
    dplyr::select(variable, freedman_class, value) %>%
    stats::na.omit()
  
  # Kruskal-Wallis Test
  kruskal <- kruskal.test(value ~ freedman_class, data = phys_data)
  
  # Wilcoxon test with BH correction
  wilcoxon <- pairwise.wilcox.test(phys_data$value, phys_data$freedman_class, p.adjust.method = "BH")
  
  # Box-and-whisker plot
  # Assign fixed colors to each CH4 yield categories
  fixed_colors <- c("#cc3300", "#ff9966", "#004cff", "#ffcc00", "#99cc33", "#339900")
  p <- ggplot(phys_data, aes(x = freedman_class, y = value, color = freedman_class)) +
    geom_boxplot(outlier.shape = NA, outlier.size = 0.5, notch = FALSE) +
    geom_jitter(width = 0.2) +
    scale_color_manual(values = setNames(fixed_colors, freedman_levels), drop = FALSE) +
    theme_bw() +
    labs(title = var) +
    theme(plot.title = element_markdown(size = 10, face = "bold"))
  
  # Save results in a list
  results[[var]] <- list(
    kruskal = kruskal,
    wilcoxon = wilcoxon,
    figure = p
  )
}

📈 Statistical analysis for volatile_fatty_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 16.752, df = 3, p-value = 0.0007946

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2    C3    C4   
C3 0.072 -     -    
C4 0.090 0.038 -    
C5 0.064 0.010 0.064

P value adjustment method: BH 

📈 Statistical analysis for acetic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 28.131, df = 5, p-value = 3.432e-05

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1     C2     C3     C4     C5    
C2 0.2152 -      -      -      -     
C3 0.2381 0.7912 -      -      -     
C4 0.7912 0.1329 0.0648 -      -     
C5 0.7912 0.0096 0.0077 0.7757 -     
C6 0.1329 0.0077 0.0020 0.0094 0.0020

P value adjustment method: BH 

📈 Statistical analysis for butyric_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 11.759, df = 5, p-value = 0.03824

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.90 -    -    -    -   
C3 1.00 0.32 -    -    -   
C4 0.45 0.32 0.27 -    -   
C5 0.32 0.32 0.27 0.32 -   
C6 0.77 0.45 0.32 0.32 0.32

P value adjustment method: BH 

📈 Statistical analysis for propionic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 3.748, df = 5, p-value = 0.5862

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 1.00 -    -    -    -   
C3 1.00 1.00 -    -    -   
C4 1.00 1.00 0.46 -    -   
C5 1.00 1.00 0.46 1.00 -   
C6 1.00 1.00 0.46 1.00 1.00

P value adjustment method: BH 

📈 Statistical analysis for isobutyric_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 22.894, df = 3, p-value = 4.25e-05

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2     C3     C4    
C3 0.0484 -      -     
C4 0.0104 0.0270 -     
C5 0.0051 0.0035 0.0270

P value adjustment method: BH 

📈 Statistical analysis for isovaleric_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 6.2312, df = 3, p-value = 0.1009

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2    C3    C4   
C3 0.047 -     -    
C4 0.245 0.425 -    
C5 0.245 0.245 0.245

P value adjustment method: BH 

📈 Statistical analysis for valeric_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 12.421, df = 5, p-value = 0.02945

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.598 -     -     -     -    
C3 0.598 0.757 -     -     -    
C4 0.979 0.598 0.220 -     -    
C5 0.979 0.504 0.055 0.220 -    
C6 1.000 0.745 0.504 0.598 0.598

P value adjustment method: BH 

📈 Statistical analysis for total_ammonia_nitrogen_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 23.358, df = 5, p-value = 0.0002884

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.434 -     -     -     -    
C3 0.031 0.013 -     -     -    
C4 0.031 0.040 0.753 -     -    
C5 0.021 0.013 0.544 0.620 -    
C6 0.013 0.013 0.013 0.017 0.101

P value adjustment method: BH 

📈 Statistical analysis for free_ammonia_nitrogen_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 3.9648, df = 4, p-value = 0.4108

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1   C2   C3   C4  
C2 0.80 -    -    -   
C3 0.80 0.65 -    -   
C4 0.65 1.00 1.00 -   
C5 0.65 1.00 0.87 0.80

P value adjustment method: BH 

📈 Statistical analysis for linoleic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 9.4066, df = 4, p-value = 0.0517

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2    C3    C4    C5   
C3 0.089 -     -     -    
C4 0.077 0.918 -     -    
C5 0.077 1.000 0.918 -    
C6 0.077 0.834 0.366 0.366

P value adjustment method: BH 

📈 Statistical analysis for myristic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 5.1354, df = 4, p-value = 0.2737

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2   C3   C4   C5  
C3 0.18 -    -    -   
C4 0.47 1.00 -    -   
C5 0.67 1.00 0.67 -   
C6 0.18 1.00 0.67 0.67

P value adjustment method: BH 

📈 Statistical analysis for oleic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 6.939, df = 4, p-value = 0.1391

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2   C3   C4   C5  
C3 0.18 -    -    -   
C4 0.35 0.51 -    -   
C5 0.51 0.51 0.51 -   
C6 0.18 0.21 0.51 0.51

P value adjustment method: BH 

📈 Statistical analysis for palmitic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 5.1354, df = 4, p-value = 0.2737

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2   C3   C4   C5  
C3 0.18 -    -    -   
C4 0.47 1.00 -    -   
C5 0.67 1.00 0.67 -   
C6 0.18 1.00 0.67 0.67

P value adjustment method: BH 

📈 Statistical analysis for stearic_acid_mg_l

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 10.386, df = 4, p-value = 0.03441

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2    C3    C4    C5   
C3 0.089 -     -     -    
C4 0.077 0.511 -     -    
C5 0.077 0.511 0.511 -    
C6 0.077 0.125 0.511 0.511

P value adjustment method: BH 

📈 Statistical analysis for pr_ac

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 13.181, df = 5, p-value = 0.02174

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.809 -     -     -     -    
C3 0.809 0.809 -     -     -    
C4 0.809 0.907 0.809 -     -    
C5 0.907 0.809 0.911 0.809 -    
C6 0.233 0.029 0.020 0.020 0.014

P value adjustment method: BH 

📈 Statistical analysis for tan_acetic

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 27.325, df = 4, p-value = 1.709e-05

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  phys_data$value and phys_data$freedman_class 

   C2     C3     C4     C5    
C3 0.5287 -      -      -     
C4 0.0257 0.0124 -      -     
C5 0.0080 0.0059 0.5287 -     
C6 0.0059 0.0037 0.0080 0.0037

P value adjustment method: BH 

4 Rarefaction curves

Random subsampling without replacement was conducted using the first quartile frequency to rarefy sequencing depth across all samples. This approach guaranteed that richness estimates remained unaffected by variations in sequencing depth.

# Load packages
library(phyloseq)
library(vegan)
library(tibble)
library(readxl)
# Load database
# non-rarefied sOTUs count data from meta-analysis
df_sotus <- read_xlsx(here("data", "meta-analysis-microbial-data.xlsx"), sheet = "otus_abs_count") %>%
                       column_to_rownames("otu") # Data with bacteria-archaea characterization

df_genera <- read_xlsx(here("data", "meta-analysis-microbial-data.xlsx"), sheet = "genera_abs_count") %>%
                       column_to_rownames("genera") %>%  
                       dplyr::select(-"F25_7", -"F17_5", -"F17_3", -"F17_6") # Samples without observed archaea
# Rarefaction curves of the all samples
# OTU
rarecurve(t(df_sotus), step=50, cex=0.5, 
          xlab = "Sample Size", ylab = "sOTUs", col = "blue")

# Genera
rarecurve(t(df_sotus), step=50, cex=0.5, 
          xlab = "Sample Size", ylab = "sOTUs", col = "blue")
# Obtain the total sum of observed sOTUs/genera for each sample
sample_sums_sotus <- rowSums(t(df_sotus))
sample_sums_genera <- rowSums(t(df_genera))

# Quantiles
q_results <- list(
  sOTUs = quantile(sample_sums_sotus),
  Genera = quantile(sample_sums_genera)
)

print(q_results)
## $sOTUs
##    0%   25%   50%   75%  100% 
##  4957 11542 16980 23871 97920 
## 
## $Genera
##       0%      25%      50%      75%     100% 
##  4957.00 11559.25 17021.00 23606.75 97920.00
# Create phyloseq object with data count
ps_otus <- phyloseq(otu_table(df_sotus, taxa_are_rows = TRUE))
ps_genera <- phyloseq(otu_table(df_genera, taxa_are_rows = TRUE))

# Rarefaction using the sampling method without replacement. The first quartile of the sOTUs and genera count found in the samples, which were 11542 and 11559 seqs respectively.
data_raref_otus <- rarefy_even_depth(ps_otus, rngseed = 12345, sample.size=11542, replace = F)
data_raref_genera <- rarefy_even_depth(ps_genera, rngseed = 12345, sample.size=11559, replace = F)

# Convert the sOTUs and genera matrix into a data frame. These data were used to alpha diveristy.
df_raref_otus <- as.data.frame(data_raref_otus)
df_raref_genera <- as.data.frame(data_raref_genera)
# Rarefaction Curve Plots - sOTUs
rarecurve(t(df_raref_otus), step=50, cex=0.5, 
          xlab = "Sample Size", ylab = "sOTUs count", col = "blue")

# Rarefaction Curve Plots - Genera
rarecurve(t(df_raref_genera), step=50, cex=0.5, 
          xlab = "Sample Size", ylab = "Genera count", col = "blue")         

# Save object CH4_yield_df as RDS object for upstreams analysis
saveRDS(df_raref_otus, file = here("rds","sOTUs_rarefied_counts.rds"))
saveRDS(df_raref_genera, file = here("rds","genera_rarefied_counts.rds"))

5 Alpha diversity

Diversity analyses were performed and compared using a rarefied count table at sOTU level and genus level. Alpha diversity was grouped from methane yield categories and assessed using multiple indices, including Chao1, Pielou’s evenness, Shannon, and Hill numbers (q0, q1, and q2). The interaction among these categories and alpha diversity was evaluated using Kruskal-Wallis and Wilcoxon rank sum tests with Benjamini-Hochberg correction

# Load packages
library(phyloseq)
library(vegan)
library(hilldiv)
library(reshape2)
library(ggplot2)
library(dplyr)
library(tidyr)
library(here)
library(tibble)
library(ggpubr)
library(forcats)
# Create phyloseq object with rarefied data count
ps_rare_sotus <- phyloseq(otu_table(df_raref_otus, taxa_are_rows = TRUE))
ps_rare_genera <- phyloseq(otu_table(df_raref_genera, taxa_are_rows = TRUE))
# Load database
CH4_yield_df <- readRDS(file = here("rds","CH4_yield_df.rds"))

5.1 sOTUs

# sOTUs count
obs <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "Observed")
# Chao1
chao1 <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "Chao1") %>% dplyr::select("Chao1")
# Ace
ace <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "ACE")  %>% dplyr::select("ACE")
# Shannon
shannon <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "Shannon") 
# Simpson
Simpson <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "Simpson") 
# InvSimpson
InvSimpson <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "InvSimpson") 
# Fisher
Fisher <- estimate_richness(ps_rare_sotus, split = TRUE, measure = "Fisher") 
# Pielou
pielou <- shannon/log(obs)
colnames(pielou) <- c("pielou")
# q0 - Species richness
q0 <- hill_div(df_raref_otus, qvalue = 0) %>% as.data.frame()
colnames(q0) <- "q0"
#q1 - Shannon diversity
q1 <- hill_div(df_raref_otus, qvalue = 1) %>% as.data.frame()
colnames(q1) <- "q1"
# q2 - Simpson diversity
q2 <- hill_div(df_raref_otus, qvalue = 2) %>% as.data.frame()
colnames(q2) <- "q2"
# Create a data frame with alpha diversity indices
df_alpha_div <- cbind(
  obs,chao1,ace,shannon,Simpson,InvSimpson,
  Fisher,pielou,q0,q1,q2)

# Save the file in .rds format for use in upstream applications in RMarkdown Part 2
saveRDS(df_alpha_div, file = here("rds","df_alpha_div_sotus.rds"))

# # Convert row names of the alpha diversity dataframe to a column named 'sample_id', 
# reshape the dataframe to long format, merge with methane yield classification data 
# based on 'sample_id', and convert 'variable' to character and 'freedman_class' to factor.
df_alpha_div <- df_alpha_div %>%
                rownames_to_column(., var = "sample_id") %>%
                melt() %>%
                left_join(CH4_yield_df %>% dplyr::select(sample_id, freedman_class), by = "sample_id") %>%
                mutate(variable = as.character(variable),
                freedman_class = as.factor(freedman_class))
# Convert CH4 yield categories into a factor class
freedman_levels <- c("C1","C2","C3","C4","C5","C6")
# Convert freedman_class into a factor with defined levels
df_alpha_div$freedman_class <- factor(df_alpha_div$freedman_class, levels = freedman_levels)
# Obtain unique names of diversity indices
sotus_div_names <- unique(df_alpha_div$variable)

# Create an empty list to store the results.
alpha_div_sotus <- list()

# Iterate over each diversity index
for (var in sotus_div_names) {
  # Filter relevant data
  sotus_data <- df_alpha_div %>%
    dplyr::filter(variable == var) %>% 
    dplyr::select(variable, freedman_class, value) %>%
    na.omit()
  

  # Kruskal-Wallis hypothesis test
  kruskal <- kruskal.test(value ~ freedman_class, data = sotus_data)
  
  # Pairwise Wilcoxon hypothesis test
  wilcoxon <- pairwise.wilcox.test(sotus_data$value, sotus_data$freedman_class, 
                                   p.adjust.method = "BH")

  # Define fixed colors for each CH4 yield category.
  fixed_colors <- c("#339900", "#004cff","#99cc33","#ff9966", "#ffcc00","#cc3300")

  # Boxplot plot
  p <- ggplot(sotus_data, aes(x = freedman_class, y = value, color = freedman_class)) +
    geom_boxplot(outlier.shape = NA, notch = FALSE) +
    geom_jitter(width = 0.2, size = 1) +
    scale_color_manual(values = setNames(fixed_colors, unique(sotus_data$freedman_class)), drop = FALSE) +
    theme_bw() +
    labs(title = var) +
    theme(plot.title = element_text(size = 10, face = "bold"))

  # Save results in the list
  alpha_div_sotus[[var]] <- list(
    kruskal = kruskal,
    wilcoxon = wilcoxon,
    figure = p
  )
}

📈 Statistical analysis for Observed

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 9.5063, df = 5, p-value = 0.0905

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.604 -     -     -     -    
C3 0.678 1.000 -     -     -    
C4 0.604 0.678 0.749 -     -    
C5 0.604 0.678 0.678 1.000 -    
C6 0.027 0.028 0.118 0.313 0.209

P value adjustment method: BH 

📈 Statistical analysis for Chao1

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 10.273, df = 5, p-value = 0.06785

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.573 -     -     -     -    
C3 0.674 0.972 -     -     -    
C4 0.573 0.681 0.674 -     -    
C5 0.237 0.704 0.674 0.972 -    
C6 0.018 0.105 0.118 0.377 0.204

P value adjustment method: BH 

📈 Statistical analysis for ACE

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 10.417, df = 5, p-value = 0.06425

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.593 -     -     -     -    
C3 0.674 0.981 -     -     -    
C4 0.593 0.692 0.674 -     -    
C5 0.220 0.692 0.674 1.000 -    
C6 0.018 0.070 0.148 0.377 0.181

P value adjustment method: BH 

📈 Statistical analysis for Shannon

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.7739, df = 5, p-value = 0.1691

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.910 -     -     -     -    
C3 0.803 0.834 -     -     -    
C4 0.634 0.834 0.834 -     -    
C5 0.803 0.834 0.803 0.834 -    
C6 0.027 0.077 0.077 0.077 0.803

P value adjustment method: BH 

📈 Statistical analysis for Simpson

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.8512, df = 5, p-value = 0.1646

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1     C2     C3     C4     C5    
C2 0.8977 -      -      -      -     
C3 0.8977 0.8762 -      -      -     
C4 0.5688 0.8977 1.0000 -      -     
C5 0.8762 0.9771 0.8762 0.8977 -     
C6 0.0024 0.2704 0.1021 0.1021 0.6653

P value adjustment method: BH 

📈 Statistical analysis for InvSimpson

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.8512, df = 5, p-value = 0.1646

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1     C2     C3     C4     C5    
C2 0.8977 -      -      -      -     
C3 0.8977 0.8762 -      -      -     
C4 0.5688 0.8977 1.0000 -      -     
C5 0.8762 0.9771 0.8762 0.8977 -     
C6 0.0024 0.2704 0.1021 0.1021 0.6653

P value adjustment method: BH 

📈 Statistical analysis for Fisher

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 9.5063, df = 5, p-value = 0.0905

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.604 -     -     -     -    
C3 0.678 1.000 -     -     -    
C4 0.604 0.678 0.749 -     -    
C5 0.604 0.678 0.678 1.000 -    
C6 0.027 0.028 0.118 0.313 0.209

P value adjustment method: BH 

📈 Statistical analysis for pielou

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 3.6183, df = 5, p-value = 0.6056

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.90 -    -    -    -   
C3 0.90 0.90 -    -    -   
C4 0.90 0.90 0.90 -    -   
C5 0.90 0.98 0.90 0.90 -   
C6 0.15 0.90 0.90 0.42 0.90

P value adjustment method: BH 

📈 Statistical analysis for q0

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 9.5063, df = 5, p-value = 0.0905

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.604 -     -     -     -    
C3 0.678 1.000 -     -     -    
C4 0.604 0.678 0.749 -     -    
C5 0.604 0.678 0.678 1.000 -    
C6 0.027 0.028 0.118 0.313 0.209

P value adjustment method: BH 

📈 Statistical analysis for q1

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.7739, df = 5, p-value = 0.1691

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.910 -     -     -     -    
C3 0.803 0.834 -     -     -    
C4 0.634 0.834 0.834 -     -    
C5 0.803 0.834 0.803 0.834 -    
C6 0.027 0.077 0.077 0.077 0.803

P value adjustment method: BH 

📈 Statistical analysis for q2

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.8512, df = 5, p-value = 0.1646

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  sotus_data$value and sotus_data$freedman_class 

   C1     C2     C3     C4     C5    
C2 0.8977 -      -      -      -     
C3 0.8977 0.8762 -      -      -     
C4 0.5688 0.8977 1.0000 -      -     
C5 0.8762 0.9771 0.8762 0.8977 -     
C6 0.0024 0.2704 0.1021 0.1021 0.6653

P value adjustment method: BH 

Significant test and distribution of alpha diversity indices grouped by methane yield categories identified by different colors (C1-C6) at sOTU level.

5.2 Genera

# sOTUs count
obs <- estimate_richness(ps_rare_genera, split = TRUE, measure = "Observed")
# Chao1
chao1 <- estimate_richness(ps_rare_genera, split = TRUE, measure = "Chao1") %>% dplyr::select("Chao1")
# Ace
ace <- estimate_richness(ps_rare_genera, split = TRUE, measure = "ACE")  %>% dplyr::select("ACE")
# Shannon
shannon <- estimate_richness(ps_rare_genera, split = TRUE, measure = "Shannon") 
# Simpson
Simpson <- estimate_richness(ps_rare_genera, split = TRUE, measure = "Simpson") 
# InvSimpson
InvSimpson <- estimate_richness(ps_rare_genera, split = TRUE, measure = "InvSimpson") 
# Fisher
Fisher <- estimate_richness(ps_rare_genera, split = TRUE, measure = "Fisher") 
# Pielou
pielou <- shannon/log(obs)
colnames(pielou) <- c("pielou")
# q0 - Species richness
q0 <- hill_div(df_raref_genera, qvalue = 0) %>% as.data.frame()
colnames(q0) <- "q0"
#q1 - Shannon diversity
q1 <- hill_div(df_raref_genera, qvalue = 1) %>% as.data.frame()
colnames(q1) <- "q1"
# q2 - Simpson diversity
q2 <- hill_div(df_raref_genera, qvalue = 2) %>% as.data.frame()
colnames(q2) <- "q2"
# Create a data frame with alpha diversity indices
df_alpha_div <- cbind(
  obs,chao1,ace,shannon,Simpson,InvSimpson,
  Fisher,pielou,q0,q1,q2)

# Save the file in .rds format for use in upstream applications in RMarkdown Part 2
saveRDS(df_alpha_div, file = here("rds","df_alpha_div_genera.rds"))

# # Convert row names of the alpha diversity dataframe to a column named 'sample_id', 
# reshape the dataframe to long format, merge with methane yield classification data 
# based on 'sample_id', and convert 'variable' to character and 'freedman_class' to factor.
df_alpha_div <- df_alpha_div %>%
                rownames_to_column(., var = "sample_id") %>%
                melt() %>%
                left_join(CH4_yield_df %>% dplyr::select(sample_id, freedman_class), by = "sample_id") %>%
                mutate(variable = as.character(variable),
                freedman_class = as.factor(freedman_class))
# Convert CH4 yield categories en factor class
freedman_levels <- c("C1","C2","C3","C4","C5","C6")
# Convert freedman_class a factor with 6 levels
df_alpha_div$freedman_class <- factor(df_alpha_div$freedman_class, levels = freedman_levels)
# Obtain unique names of diversity indices
genera_div_names <- unique(df_alpha_div$variable)

# Create an empty list to store the results.
alpha_div_genera <- list()

# Iterate over each variable.
for (var in genera_div_names) {
  # Filter relevant data
  genera_data <- df_alpha_div %>%
    dplyr::filter(variable == var) %>% 
    dplyr::select(variable, freedman_class, value) %>%
    na.omit()
  

  # Kruskal-Wallis test
  kruskal <- kruskal.test(value ~ freedman_class, data = genera_data)
  
  # Pairwise Wilcoxon test
  wilcoxon <- pairwise.wilcox.test(genera_data$value, genera_data$freedman_class, 
                                   p.adjust.method = "BH")

  # Define fixed colors for each CH4 yield category.
  fixed_colors <- c("#339900", "#004cff","#99cc33","#ff9966", "#ffcc00","#cc3300")

  # Boxplot
  p <- ggplot(genera_data, aes(x = freedman_class, y = value, color = freedman_class)) +
    geom_boxplot(outlier.shape = NA, notch = FALSE) +
    geom_jitter(width = 0.2, size = 1) +
    scale_color_manual(values = setNames(fixed_colors, unique(genera_data$freedman_class)), drop = FALSE) +
    theme_bw() +
    labs(title = var) +
    theme(plot.title = element_text(size = 10, face = "bold"))

  # Save results in the list
  alpha_div_genera[[var]] <- list(
    kruskal = kruskal,
    wilcoxon = wilcoxon,
    figure = p
  )
}

📈 Statistical analysis for Observed

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 5.4171, df = 5, p-value = 0.3671

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.63 -    -    -    -   
C3 0.59 0.59 -    -    -   
C4 0.59 0.59 0.87 -    -   
C5 0.59 0.65 0.59 0.59 -   
C6 0.59 0.75 0.80 0.59 0.87

P value adjustment method: BH 

📈 Statistical analysis for Chao1

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 6.0451, df = 5, p-value = 0.3019

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.87 -    -    -    -   
C3 0.54 0.54 -    -    -   
C4 0.54 0.54 0.87 -    -   
C5 0.66 0.66 0.54 0.54 -   
C6 0.66 0.66 0.66 0.62 0.69

P value adjustment method: BH 

📈 Statistical analysis for ACE

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 5.1781, df = 5, p-value = 0.3945

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.88 -    -    -    -   
C3 0.55 0.55 -    -    -   
C4 0.55 0.55 0.89 -    -   
C5 0.73 0.73 0.55 0.55 -   
C6 0.82 0.73 0.73 0.73 0.82

P value adjustment method: BH 

📈 Statistical analysis for Shannon

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 12.675, df = 5, p-value = 0.02662

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  genera_data$value and genera_data$freedman_class 

   C1     C2     C3     C4     C5    
C2 0.1721 -      -      -      -     
C3 0.1063 0.7657 -      -      -     
C4 0.0622 0.7657 0.7657 -      -     
C5 0.0096 0.7657 0.5254 0.7657 -     
C6 0.1063 0.7657 0.9385 0.9385 0.9385

P value adjustment method: BH 

📈 Statistical analysis for Simpson

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.6303, df = 5, p-value = 0.1778

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.45 -    -    -    -   
C3 0.45 0.68 -    -    -   
C4 0.45 0.64 0.64 -    -   
C5 0.26 0.75 0.45 0.64 -   
C6 0.45 0.78 0.59 0.75 0.74

P value adjustment method: BH 

📈 Statistical analysis for InvSimpson

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.6303, df = 5, p-value = 0.1778

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.45 -    -    -    -   
C3 0.45 0.68 -    -    -   
C4 0.45 0.64 0.64 -    -   
C5 0.26 0.75 0.45 0.64 -   
C6 0.45 0.78 0.59 0.75 0.74

P value adjustment method: BH 

📈 Statistical analysis for Fisher

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 5.4171, df = 5, p-value = 0.3671

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.63 -    -    -    -   
C3 0.59 0.59 -    -    -   
C4 0.59 0.59 0.87 -    -   
C5 0.59 0.65 0.59 0.59 -   
C6 0.59 0.75 0.80 0.59 0.87

P value adjustment method: BH 

📈 Statistical analysis for pielou

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 13.643, df = 5, p-value = 0.01804

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  genera_data$value and genera_data$freedman_class 

   C1    C2    C3    C4    C5   
C2 0.126 -     -     -     -    
C3 0.519 0.303 -     -     -    
C4 0.034 0.519 0.587 -     -    
C5 0.013 0.587 0.303 0.587 -    
C6 0.134 0.801 0.519 0.828 1.000

P value adjustment method: BH 

📈 Statistical analysis for q0

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 5.4171, df = 5, p-value = 0.3671

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.63 -    -    -    -   
C3 0.59 0.59 -    -    -   
C4 0.59 0.59 0.87 -    -   
C5 0.59 0.65 0.59 0.59 -   
C6 0.59 0.75 0.80 0.59 0.87

P value adjustment method: BH 

📈 Statistical analysis for q1

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 12.675, df = 5, p-value = 0.02662

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  genera_data$value and genera_data$freedman_class 

   C1     C2     C3     C4     C5    
C2 0.1721 -      -      -      -     
C3 0.1063 0.7657 -      -      -     
C4 0.0622 0.7657 0.7657 -      -     
C5 0.0096 0.7657 0.5254 0.7657 -     
C6 0.1063 0.7657 0.9385 0.9385 0.9385

P value adjustment method: BH 

📈 Statistical analysis for q2

⚭ Significant tests

🔹 Kruskal-Wallis test


    Kruskal-Wallis rank sum test

data:  value by freedman_class
Kruskal-Wallis chi-squared = 7.6303, df = 5, p-value = 0.1778

🔹 Wilcoxon test


    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  genera_data$value and genera_data$freedman_class 

   C1   C2   C3   C4   C5  
C2 0.45 -    -    -    -   
C3 0.45 0.68 -    -    -   
C4 0.45 0.64 0.64 -    -   
C5 0.26 0.75 0.45 0.64 -   
C6 0.45 0.78 0.59 0.75 0.74

P value adjustment method: BH 

Significant test and distribution of alpha diversity indices grouped by methane yield categories identified by different colors (C1-C6) at genus level.

6 Beta diversity

Beta diversity analysis were performed and compared using a rarefied count table at sOTU level and genus level. The relationships between methane yield categories and beta diversity distances were assessed using ANOSIM with 999 permutations (p < 0.05).

# Load packages
library(phyloseq)
library(vegan)
library(tibble)
library(DT)
# Load database with rarefied sOTUs data
df_raref_otus <- readRDS(file = here("rds","sOTUs_rarefied_counts.rds")) %>%
                 t() # Rotate
df_raref_genera <- readRDS(file = here("rds","genera_rarefied_counts.rds")) %>%
                 t() # Rotate
# Load database with methane yield categories
CH4_yield_df <- readRDS(file = here("rds","CH4_yield_df.rds")) %>%
                column_to_rownames("sample_id")

6.1 sOTUs

# Compute Bray-Curtis distance matrix from rarefied OTU table 
tax_bc_distmat <- vegdist(df_raref_otus, method = "bray")

# Perform PCoA on Bray-Curtis distance matrix with 6 axes
pcoa_taxa <- cmdscale(tax_bc_distmat, k = 6)
#  Create dataframe with first two PCoA axes from taxa
pcoa_df <- data.frame(PC1 = pcoa_taxa[, 1], PC2 = pcoa_taxa[, 2])

# Assign freedman class to pcoa_df based on row names
pcoa_df$freedman_class <- CH4_yield_df[rownames(pcoa_df), "freedman_class"]

# Convert CH4 yield categories en factor class
freedman_levels <- c("C1","C2","C3","C4","C5","C6")

# Convert freedman_class a factor with 6 levels
pcoa_df$freedman_class <- factor(pcoa_df$freedman_class, levels = freedman_levels)

# Remove rows with NA values in freedman_class column
pcoa_df <- pcoa_df[!is.na(pcoa_df$freedman_class),]
# Convert the taxonomic Bray-Curtis distance matrix to a matrix
tax_bc_distmat_mat <- as.matrix(tax_bc_distmat)

# Subset the distance matrix based on matching row names with pcoa_df
tax_bc_distmat_filt <- tax_bc_distmat_mat[row.names(tax_bc_distmat_mat) %in% row.names(pcoa_df),]

# Perform ANOSIM test with 999 permutations on filtered distance matrix
anosim_result <- anosim(tax_bc_distmat_filt, pcoa_df$freedman_class, perm = 999)
# Create a data frame with formatted statistics for PCoA and ANOSIM
results_df <- data.frame(
  Var_PCoA1 = formatC(var(pcoa_df$PC1), digits = 2, format = "E", flag = "#"),
  Var_PCoA2 = formatC(var(pcoa_df$PC2), digits = 2, format = "E", flag = "#"),
  ANOSIM_R  = formatC(anosim_result$statistic, digits = 2, format = "E", flag = "#"),
  ANOSIM_p  = formatC(anosim_result$signif, digits = 2, format = "E", flag = "#"),
  stringsAsFactors = FALSE
)

#  Display the dataframe in an interactive table format
datatable(results_df)
# Plot PCoA
plot(pcoa_df$PC1, pcoa_df$PC2, type = "n", main = "PCoA - Bray-Curtis - sOTUs", 
     xlab = expression(bold("Axis 1 (7.93%)")), ylab = expression(bold("Axis 2 (4.03%)")))
points(pcoa_df$PC1, pcoa_df$PC2, pch = 19, cex = 0.6, 
       col = c("#cc3300", "#ff9966", "blue", "#ffcc00", "#99cc33", "#339900")[pcoa_df$freedman_class])

Principal coordinate analysis (PCoA) depicts microbial community dynamics through methane yield categories (C1-C6) at sOTUs level.

6.2 Genera

# Compute Bray-Curtis distance matrix from rarefied genera table 
tax_bc_distmat <- vegdist(df_raref_genera, method = "bray")

# Perform PCoA on Bray-Curtis distance matrix with 6 axes
pcoa_taxa <- cmdscale(tax_bc_distmat, k = 6)
#  Create dataframe with first two PCoA axes from taxa
pcoa_df <- data.frame(PC1 = pcoa_taxa[, 1], PC2 = pcoa_taxa[, 2])

# Assign freedman class to pcoa_df based on row names
pcoa_df$freedman_class <- CH4_yield_df[rownames(pcoa_df), "freedman_class"]

# Convert CH4 yield categories en factor class
freedman_levels <- c("C1","C2","C3","C4","C5","C6")

# Convert freedman_class a factor with 6 levels
pcoa_df$freedman_class <- factor(pcoa_df$freedman_class, levels = freedman_levels)

# Remove rows with NA values in freedman_class column
pcoa_df <- pcoa_df[!is.na(pcoa_df$freedman_class),]
# Convert the taxonomic Bray-Curtis distance matrix to a matrix
tax_bc_distmat_mat <- as.matrix(tax_bc_distmat)

# Subset the distance matrix based on matching row names with pcoa_df
tax_bc_distmat_filt <- tax_bc_distmat_mat[row.names(tax_bc_distmat_mat) %in% row.names(pcoa_df),]

# Perform ANOSIM test with 999 permutations on filtered distance matrix
anosim_result <- anosim(tax_bc_distmat_filt, pcoa_df$freedman_class, perm = 999)
# Create a data frame with formatted statistics for PCoA and ANOSIM
results_df <- data.frame(
  Var_PCoA1 = formatC(var(pcoa_df$PC1), digits = 2, format = "E", flag = "#"),
  Var_PCoA2 = formatC(var(pcoa_df$PC2), digits = 2, format = "E", flag = "#"),
  ANOSIM_R  = formatC(anosim_result$statistic, digits = 2, format = "E", flag = "#"),
  ANOSIM_p  = formatC(anosim_result$signif, digits = 2, format = "E", flag = "#"),
  stringsAsFactors = FALSE
)

#  Display the dataframe in an interactive table format
datatable(results_df)
# Plot PCoA
plot(pcoa_df$PC1, pcoa_df$PC2, type = "n", main = "PCoA - Bray-Curtis - Genera", 
     xlab = expression(bold("Axis 1 (3.57%)")), ylab = expression(bold("Axis 2 (3.13%)")))
points(pcoa_df$PC1, pcoa_df$PC2, pch = 19, cex = 0.6, 
       col = c("#cc3300", "#ff9966", "blue", "#ffcc00", "#99cc33", "#339900")[pcoa_df$freedman_class])

Principal coordinate analysis (PCoA) depicts microbial community dynamics through methane yield categories (C1-C6) at genus level.

                                      2MMS
                                      (..)
                                  _O__( u )__0_
LS0tDQp0aXRsZTogIkEgU3RhdGlzdGljYWwgRnJhbWV3b3JrIERldmVsb3BlZCBpbiBSIGZvciBJZGVudGlmeWluZyBQb3RlbnRpYWwgTWljcm9iaWFsIEluZGljYXRvcnMgaW4gT0ZNU1cvRlcgRGlnZXN0ZXJzIC0gUGFydCAxOiBTYW1wbGUgQ2F0ZWdvcml6YXRpb24gYW5kIERpdmVyc2l0eSBJbmRpY2VzLiINCmF1dGhvcjogQ29ydGV6LUNlcnZhbnRlcyBKLg0KZGF0ZTogMjAyNS0wNC0xMA0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRoZW1lOiB5ZXRpIA0KICAgIGhpZ2hsaWdodDogZXNwcmVzc28NCiAgICBjc3M6ICJzdHlsZXMuY3NzIg0KICAgIG1hdGhqYXg6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAxLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNClBoeXNpY29jaGVtaWNhbCBhbmQgYmlvbG9naWNhbCBkYXRhIGZyb20gYW5hZXJvYmljIHByb2Nlc3Nlcywgd2hpY2ggdW5kZXJ3ZW50IDE2UyByUk5BIGdlbmUgc2VxdWVuY2luZyBpbiBwdWJsaWMgU1JBIHJlcG9zaXRvcmllcyBvZiB0aGUgTkNCSSwgd2VyZSBhbmFseXplZCB0byBwcm9wb3NlIHBvdGVudGlhbCBtaWNyb2JpYWwgaW5kaWNhdG9ycy4gVGhlIHN0YXRpc3RpY2FsIGFuYWx5c2VzIGludm9sdmVkIGNhdGVnb3JpemluZyBDSOKChCB5aWVsZCBiYXNlZCBvbiBoaXN0b2dyYW0gYmlucywgd2hpY2ggd2VyZSB0aGVuIHVzZWQgZm9yIGZ1cnRoZXIgYW5hbHlzZXMsIGluY2x1ZGluZyBkaXZlcnNpdHkgYW5hbHlzaXMsIHNpZ25pZmljYW5jZSB0ZXN0LCBkaWZmZXJlbnRpYWwgYW5hbHlzaXMsIFZlbm4gZGlhZ3JhbSBjb25zdHJ1Y3Rpb24sIGFuZCBjb3JyZWxhdGlvbiBhbmFseXNpcy4gVGhlc2UgbWV0aG9kcyBhbGxvd2VkIGZvciB0aGUgaWRlbnRpZmljYXRpb24gb2Ygc2lnbmlmaWNhbnQgY2hhbmdlcyBpbiBwaHlzaWNvY2hlbWljYWwgcGFyYW1ldGVycyBhbmQgbWljcm9iaWFsIGRhdGEsIHVsdGltYXRlbHkgbGVhZGluZyB0byB0aGUgaW5mZXJlbmNlIG9mIHBvdGVudGlhbCBtaWNyb2JpYWwgaW5kaWNhdG9ycy4gVGhpcyBSUHViIHByZXNlbnRzIHRoZSBjb2RlIGZyYW1ld29yayB0aGF0IGd1aWRlZCB0aGUgZGVjaXNpb24tbWFraW5nIHByb2Nlc3MgZm9yIHByb3Bvc2luZyBtaWNyb2JpYWwgaW5kaWNhdG9ycyBpbiBhbmFlcm9iaWMgZGlnZXN0ZXJzIGZlZCB3aXRoIEZXL09GTVNXLg0KDQpGb3IgZnVydGhlciBkZXRhaWxzLCByZWZlciB0byB0aGUgYXJ0aWNsZSAqIklkZW50aWZ5aW5nIHJlbGlhYmxlIG1pY3JvYmlhbCBpbmRpY2F0b3JzIGluIGFuYWVyb2JpYyBkaWdlc3Rpb24gb2Ygb3JnYW5pYyBzb2xpZCB3YXN0ZTogSW5zaWdodHMgZnJvbSBhIG1ldGEtYW5hbHlzaXMiKg0KDQpUaGUgc3RhdGlzdGljYWwgZnJhbWV3b3JrIHdhcyBkaXZpZGVkIGludG8gdHdvIHBhcnRzOg0KLVBhcnQgMTogRGV0ZXJtaW5hdGlvbiBvZiBtZXRoYW5lIHlpZWxkIHBlcmZvcm1hbmNlIGNhdGVnb3JpZXMgdG8gZXZhbHVhdGUgT0ZNU1cvRlcgZGlnZXN0ZXJzIGluIHRlcm1zIG9mIHBoeXNpY29jaGVtaWNhbCByZXNwb25zZSBhbmQgdGF4b25vbWljIGRpdmVyc2l0eS4NCi1QYXJ0IDI6IElkZW50aWZpY2F0aW9uIG9mIG1pY3JvYmlhbCBpbmRpY2F0b3JzIHRvIGFzc2VzcyB0aGUgcGVyZm9ybWFuY2Ugb2YgT0ZNU1cvRlcgZGlnZXN0ZXJzLg0KDQojIENhdGVnb3JpemF0aW9uIG9mIHNhbXBsZXMgYWNjb3JkaW5nIHRvIENIfjR+IHlpZWxkDQpDSDQgeWllbGQgKG1lYXN1cmVkIGluIG1MIENINC9nVlNhZGRlZCkgaXMgY29tbW9ubHkgdXNlZCBhcyBhIHByb2Nlc3MgaW5kaWNhdG9yOyB0aHVzLCBpdCB3YXMgc2VsZWN0ZWQgYXMgYm90aCBhIGNhdGVnb3JpY2FsIGFuZCBxdWFudGl0YXRpdmUgdmFyaWFibGUgZm9yIGNsYXNzaWZ5aW5nIEFEIHBlcmZvcm1hbmNlLiBUaGlzIGNsYXNzaWZpY2F0aW9uLCBrbm93biBhcyB0aGUgbWV0aGFuZSB5aWVsZCBjYXRlZ29yeSwgd2FzIGRlcml2ZWQgZnJvbSB0aGUgY2xhc3NlcyBvZiBhIGJldGEgZGlzdHJpYnV0aW9uIGhpc3RvZ3JhbSBmb2xsb3dpbmcgdGhlIEZyZWVkbWFuLURpYWNvbmlzIHJ1bGUuDQoNCipGcmVlZG1hbi1EaWFjb25pcyBydWxlIGVxdWF0aW9uKiAkJA0KXHRleHR7Q2xhc3Mgd2lkdGh9ID0gMiBccXVhZCBcZnJhY3tcdGV4dHtJUVJ9fXtcc3FydFszXXtufX0NCiQkIHdoZXJlIElRUiBpcyB0aGUgaW50ZXJxdWFydGlsZSByYW5nZSBvZiB0aGUgZGF0YSwgYW5kIG4gaXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgTG9hZCBwYWNrYWdlcw0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGdyRGV2aWNlcykNCmxpYnJhcnkoc2tpbXIpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KGZpdGRpc3RycGx1cykNCmxpYnJhcnkoZmR0aCkNCmxpYnJhcnkoZ2dwbG90MikNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIExvYWQgUGh5c2ljb2NoZW1pY2FsIGRhdGEgZnJvbSBtZXRhLWFuYWx5c2lzDQpkZiA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwgIm1ldGEtYW5hbHlzaXMtcGh5c2ljb2NoZW1pY2FsLWRhdGEuY3N2IiksIA0KICAgICAgICAgICAgICAgbG9jYWxlID0gbG9jYWxlKGVuY29kaW5nID0gImxhdGluMSIpLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUNCiAgICAgIGFzLmRhdGEuZnJhbWUoKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgRGF0YSBjbGVhbmluZw0KIyBSZXBsYWNlICJORCIgd2l0aCBOQSBpbiBhbGwgY2hhcmFjdGVyLXR5cGUgY29sdW1ucw0KZGZbXSA8LSBsYXBwbHkoZGYsIGZ1bmN0aW9uKHgpIHsNCiAgICAgICAgaWYgKGlzLmNoYXJhY3Rlcih4KSkgew0KICAgICAgICB4W3ggPT0gIk5EIl0gPC0gTkENCiAgICAgICAgfQ0KICAgICAgICByZXR1cm4oeCkNCiAgICAgICAgfSkNCg0KIyBBdXRvbWF0aWNhbGx5IGNvbnZlcnQgY29sdW1ucyBjbGFzcyAoY2hhcmFjdGVyLCBudW1lcmljKSBhY2NvcmRpbmcgdG8gdGhlIHZhbHVlcyBvZiB0aGVpciBjZWxscyBhbmQgY2xlYW4gbmFtZXMNCmRmIDwtICBkZiAlPiUNCiAgICAgICBtdXRhdGVfYWxsKH4gdHlwZS5jb252ZXJ0KGFzLmNoYXJhY3RlciguKSwgYXMuaXMgPSBUUlVFKSkgJT4lIA0KICAgICAgIGNsZWFuX25hbWVzKCkNCg0KIyBDcmVhdGUgYSAicHJfYWMiIGFuZCAidGFuX2FjZXRpYyIgcmF0aW8gdmFyaWFibGUNCmRmIDwtICBkZiAlPiUNCiAgICAgICBtdXRhdGUocHJfYWMgPSBhY2V0aWNfYWNpZF9tZ19sIC8gcHJvcGlvbmljX2FjaWRfbWdfbCwNCiAgICAgICAgICAgICAgcHJfYWMgPSBpZmVsc2UoaXMuZmluaXRlKHByX2FjKSwgcHJfYWMsIE5BKSwNCiAgICAgICAgICAgICAgdGFuX2FjZXRpYyA9IGFjZXRpY19hY2lkX21nX2wgLyB0b3RhbF9hbW1vbmlhX25pdHJvZ2VuX21nX2wsDQogICAgICAgICAgICAgIHRhbl9hY2V0aWMgPSBpZmVsc2UoaXMuZmluaXRlKHRhbl9hY2V0aWMpLCB0YW5fYWNldGljLCBOQSkpDQoNCiMgU2F2ZSBvYmplY3QgZGYgYXMgUkRTIG9iamVjdCBmb3IgdXBzdHJlYW1zIGFuYWx5c2lzIChwYXJ0IDIpDQpzYXZlUkRTKGRmLCBmaWxlID0gaGVyZSgicmRzIiwiZGZfcGh5c2ljb2NoZW1pY2FsX2RhdGFfbWV0YW5hbHlzaXMucmRzIikpDQoNCmBgYA0KDQpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1UUlVFfQ0KIyBUYWJsZSB3aXRoIHBoeXNpY29jaGVtaWNhbCBwYXJhbWV0ZXJzDQojIFRoZSBmb2xsb3dpbmcgdGFibGUgZGlzcGxheXMgdGhlIGluZm9ybWF0aW9uIGNvbGxlY3RlZCBmcm9tIG11bHRpcGxlIEZXL09GTVNXIGFuYWVyb2JpYyBwcm9jZXNzZXMuDQpkYXRhdGFibGUoZGYpDQpgYGANCg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG89VFJVRX0NCiMgU3VtbWFyeSBvZiBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzDQpza2ltKGRmKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvPVRSVUV9DQojIFNlbGVjdCB0aGUgQ0g0IHlpZWxkIGNvbHVtbiBjb25zaWRlcmluZyBpdCBhcyB0aGUgdmFyaWFibGUgb2YgaW50ZXJlc3QgdGhhdCB3aWxsIGRlZmluZSB0aGUgcGVyZm9ybWFuY2UgY2F0ZWdvcmllcw0KIyBDSDQgeWllbGQgZGF0YSBmcmFtZQ0KQ0g0X3lpZWxkX2RmIDwtIGRmICU+JQ0KICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGNoNF95aWVsZF9tX2xjaDRfZ192X3NhZGRlZCkgJiBjaDRfeWllbGRfbV9sY2g0X2dfdl9zYWRkZWQgIT0gIiIpICU+JQ0KICAgICAgICAgICAgICAgIHJlbmFtZShZQ0g0X21MZ1ZTID0gY2g0X3lpZWxkX21fbGNoNF9nX3Zfc2FkZGVkKQ0KDQojIFNhdmUgb2JqZWN0IENINF95aWVsZF9kZiBhcyBSRFMgb2JqZWN0IGZvciB1cHN0cmVhbXMgYW5hbHlzaXMgKHBhcnQgMikNCnNhdmVSRFMoQ0g0X3lpZWxkX2RmLCBmaWxlID0gaGVyZSgicmRzIiwiQ0g0X3lpZWxkX2RmLnJkcyIpKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvPVRSVUV9DQojIE5vcm1hbGl0eSB0ZXN0IC0gU2hhcGlyby1XaWxrIHRlc3QgSWYgcCA+IDAuMDUsIHRoZSBkYXRhIGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24NCnNoYXBpcm8udGVzdChDSDRfeWllbGRfZGYkWUNINF9tTGdWUykgIyBwIDwgMC4wNQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvPVRSVUUsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KIyBTaW5jZSBwIDwgMC4wNSB0aGUgZGF0YSBkbyBub3QgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVGhlIHJlc3VsdHMgaW5kaWNhdGUgYSBiZXRhIGRpc3RyaWJ1dGlvbi4NCmRlc2NkaXN0KENINF95aWVsZF9kZiRZQ0g0X21MZ1ZTLCBkaXNjcmV0ZSA9IEZBTFNFLCBib290ID0gMTAwMCkgDQpgYGANCg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG89VFJVRSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQojIFNlZSBhZGp1c3RtZW50cy4gQ29tcGFyZSBub3JtYWwgZGlzdHJpYnV0aW9uIGFuZCBiZXRhIGRpc3RyaWJ1dGlvbg0KZml0Lm5vcm0gPC0gZml0ZGlzdChDSDRfeWllbGRfZGYkWUNINF9tTGdWUywgIm5vcm0iKQ0KIyBQbG90IHRoZSBkYXRhIGRpc3RyaWJ1dGlvbg0KcGxvdChmaXQubm9ybSkNCmBgYA0KDQpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1UUlVFfQ0KIyBEYXRhIGV4cGxvcmF0aW9uDQpxdWFudGlsZShDSDRfeWllbGRfZGYkWUNINF9tTGdWUykNCmBgYA0KDQpgYGB7ciBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1UUlVFfQ0KIyBEZWZpbmUgaW50ZXJ2YWxzIHVzaW5nIHRoZSBGcmVlZG1hbuKAk0RpYWNvbmlzIHJ1bGUNCmludGVydmFsX0ZEIDwtIG5jbGFzcy5GRChDSDRfeWllbGRfZGYkWUNINF9tTGdWUykNCg0KIyBTdG9yZSB0aGUgQ0g0IHlpZWxkIGRhdGEgaW4gYSB2ZWN0b3INCmRhdGFfWUNINF9tTGdWUyA8LSBDSDRfeWllbGRfZGYkWUNINF9tTGdWUw0KDQojIENyZWF0ZSBhIHRhYmxlIHdpdGggdGhlIENINCB5aWVsZCBpbnRlcnZhbHMgb2J0YWluZWQNCnRhYmxlLkZEIDwtIHRyYW5zZm9ybSh0YWJsZShjdXQoZGF0YV9ZQ0g0X21MZ1ZTLCBicmVha3MgPSBpbnRlcnZhbF9GRCkpKSAlPiUNCiAgICAgICAgICAgIHJlbmFtZShZQ0g0X21MZ1ZTX2ludGVydmFscyA9IFZhcjEpICMgUmVuYW1lIGNvbHVtbg0KDQpkYXRhdGFibGUodGFibGUuRkQpDQpgYGANCg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG89VFJVRX0NCiMgRXh0cmFjdCBpbnRlcnZhbHMgYW5kIHZhbHVlcyBmcm9tICJ0YWJsZS5GRCINCiMgR2V0IHRoZSBpbnRlcnZhbHMgZnJvbSB0aGUgIllDSDRfbUxnVlNfaW50ZXJ2YWxzIiBjb2x1bW4gaW4gInRhYmxlLkZEIg0KaW50ZXJ2YWxzIDwtIHRhYmxlLkZEJFlDSDRfbUxnVlNfaW50ZXJ2YWxzDQojIEV4dHJhY3QgdGhlIGxpbWl0cyBmb3IgZWFjaCBpbnRlcnZhbCBmb3IgdGhlIGN1dCgpIGZ1bmN0aW9uDQpicmVha3MgPC0gYygtSW5mLCAxMTQsIDIyOCwgMzQyLCA0NTYsIDU3MCwgNjg1KSAgIyBUaGUgY3V0b2ZmIHZhbHVlcyBmb3IgZWFjaCBjbGFzcw0KDQojIFVzZSBjdXQoKSB0byBjYXRlZ29yaXplIHRoZSB2YWx1ZXMgaW4gImRhdGFfWUNINF9tTGdWUyIgYWNjb3JkaW5nIHRvIHRoZSBpbnRlcnZhbHMNCmNhdGVnb3JpZXMgPC0gY3V0KGRhdGFfWUNINF9tTGdWUywgYnJlYWtzID0gYnJlYWtzLCBsYWJlbHMgPSBjKCJDMSIsICJDMiIsICJDMyIsICJDNCIsICJDNSIsICJDNiIpLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpDQoNCiMgQ3JlYXRlIHRoZSBkYXRhZnJhbWUgd2l0aCB0aGUgeWllbGRzIGFuZCBjYXRlZ29yaWVzDQpDSDRfeWllbGRfZGZfMiA8LSBkYXRhLmZyYW1lKA0KICAgICAgICAgICAgICAgICAgWUNINF9tTGdWUyA9IGRhdGFfWUNINF9tTGdWUywNCiAgICAgICAgICAgICAgICAgIEZyZWVkbWFuID0gYXMuZmFjdG9yKGNhdGVnb3JpZXMpKQ0KYGBgDQoNCmBgYHtyICBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1UUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCiMgSGlzdG9ncmFtIHdpdGggRnJlZWRtYW4tRGlhY29uaXMgY2xhc3Nlcw0KbXlfYmFyX0ZEIDwtIGJhcnBsb3QodGFibGUuRkQkRnJlcSwgDQogICAgICAgICAgICAgICAgICAgIGJvcmRlciA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICBsYXMgPSAyLA0KICAgICAgICAgICAgICAgICAgICB5bGltID0gYygwLDQwKSwNCiAgICAgICAgICAgICAgICAgICAgeWxhYiA9ICJGcmVxdWVuY3kiLA0KICAgICAgICAgICAgICAgICAgICB4bGFiID0gIkNsYXNzZXMgb2YgQ0g0IHlpZWxkIGluIEZvb2Qtd2FzdGUvT0ZNU1cgYW5hZXJvYmljIGRpZ2VzdGVycyIsDQogICAgICAgICAgICAgICAgICAgIG5hbWVzLmFyZyA9IGMoIkMxIiwgIkMyIiwgIkMzIiwgIkM0IiwgIkM1IiwgIkM2IiksDQogICAgICAgICAgICAgICAgICAgIGNleC5heGlzID0gMC43NSwNCiAgICAgICAgICAgICAgICAgICAgY2V4LmxhYiA9IDAuNzUsDQogICAgICAgICAgICAgICAgICAgIGNleC5uYW1lcyA9IDAuNzUsDQogICAgICAgICAgICAgICAgICAgIGNvbCA9ICJkYXJrcmVkIikNCg0KIyBBZGQgc2VwYXJhdGlvbiBsaW5lIChJbnRlcnZhbCBzaXplID0gMS4yKQ0KYWJsaW5lKHYgPSBjKDEuMywgMi41LCAzLjcsIDQuOSwgNi4xLCA3LjMsIDguNSksIGNvbCA9ICJncmV5IikgIyBGRA0KdGV4dChteV9iYXJfRkQsIHRhYmxlLkZEJEZyZXEgKyAxLjQsIHBhc3RlKCJuOiAiLCB0YWJsZS5GRCRGcmVxLCBzZXAgPSAiIiksIGNleCA9IDAuNSkNCmBgYA0KDQo6OjogY2VudGVyLXRleHQNCkhpc3RvZ3JhbSBzaG93aW5nIHRoZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIG9mIENIfjR+IHlpZWxkcyBncm91cGVkIGJ5IGNsYXNzLg0KOjo6DQoNCmBgYHtyICBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1UUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCiMgQXNzaWduIGRpZmZlcmVudCBjb2xvcnMgdG8gZWFjaCBjbGFzcw0KY29sb3JzIDwtIGMoIiNjYzMzMDBmZiIsICIjZmY5OTY2ZmYiLCAiIzAwNGNmZmZmIiwgIiNmZmNjMDBmZiIsICIjOTljYzMzZmYiLCAiIzMzOTkwMGZmIikgDQoNCiMgQ3JlYXRlIHRoZSBib3hwbG90IHdpdGggZGlmZmVyZW50IGNvbG9ycyBmb3IgZWFjaCBjbGFzcw0KbXlwbG90X0ZEIDwtIGJveHBsb3QoWUNINF9tTGdWUyB+IEZyZWVkbWFuLCBkYXRhPSBDSDRfeWllbGRfZGZfMiwgeWxhYj0iIiwgeGxhYiA9ICIiLA0KICAgICAgICAgICAgICAgICAgICAgYm9yZGVyID0gY29sb3JzLCAgIyBBc3NpZ24gY29sb3JzIHRvIHRoZSBib3hlcw0KICAgICAgICAgICAgICAgICAgICAgY29sID0gY29sb3JzLCAgICAgIyBDb2xvcnMgZm9yIHRoZSBpbnNpZGUgb2YgdGhlIGJveGVzDQogICAgICAgICAgICAgICAgICAgICB4YXh0PSJuIiwgICAgICAgICAjIFJlbW92ZSB0aWNrcyBmcm9tIHRoZSB4LWF4aXMNCiAgICAgICAgICAgICAgICAgICAgIHlheHQgPSAibiIpICAgICAgICAjIFJlbW92ZSB0aWNrcyBmcm9tIHRoZSB5LWF4aXMNCg0KIyBZLWF4aXMNCmF4aXMoMiwgeWxpbT1jKDAsMTAwMCksIGNvbD0iYmxhY2siLCBsYXM9MSwgY2V4LmF4aXMgPSAwLjc1KSANCm10ZXh0KCJDSDQgeWllbGQgKG1MQ0g0IGdWUykiLCBzaWRlPTIsIGxpbmU9Mi4yLCBjZXggPSAwLjc1KQ0KDQojIFgtYXhpcw0KbXlfbmFtZXMgPC0gc2FwcGx5KHN0cnNwbGl0KG15cGxvdF9GRCRuYW1lcywgJ1xcLicpICwgZnVuY3Rpb24oeCkgeFtbMV1dKQ0KbXlfbmFtZXMgPC0gbXlfbmFtZXNbc2VxKDEsIGxlbmd0aChteV9uYW1lcyksIDEpXQ0KYXhpcygxLCBhdCA9IHNlcSgxLCA2LCAxKSwgbGFiZWxzID0gbXlfbmFtZXMsIHRpY2s9RkFMU0UsIGNleC5heGlzID0gMC43NSkNCm10ZXh0KCJGcmVlZG1hbi1EaWFjb25pcyBDbGFzc2VzIiwgc2lkZT0xLCBsaW5lPTIsIGNleCA9IDAuNzUpDQoNCiMgQWRkIGdyZXkgdmVydGljYWwgbGluZXMNCmZvcihpIGluIHNlcSgwLjUgLCAyMCAsIDEpKXsgDQogIGFibGluZSh2PWksIGx0eT0xLCBjb2w9ImdyZXkiKQ0KfQ0KYGBgDQoNCjo6OiBjZW50ZXItdGV4dA0KQm94cGxvdCBpbGx1c3RyYXRpbmcgQ0h+NH4geWllbGQgdmFsdWVzIGdyb3VwZWQgZm9yIGVhY2ggY2xhc3MuDQo6OjoNCg0KIyBQaHlzaWNvY2hlbWljYWwgcGFyYW1ldGVycw0KVGhlIHBoeXNpY29jaGVtaWNhbCBwYXJhbWV0ZXJzIGFuZCBtZXRoYW5lIHlpZWxkIGNhdGVnb3JpZXMgd2VyZSBhc3Nlc3NlZCB1c2luZyB0aGUgS3J1c2thbC1XYWxsaXMgdGVzdCBhbmQgV2lsY294b24gcmFuayBzdW0gdGVzdCB3aXRoIEJlbmphbWluaS1Ib2NoYmVyZyBjb3JyZWN0aW9uIGZvciB0ZXN0cyBhbW9uZyBhbmQgd2l0aGluIG1ldGhhbmUgeWllbGQgY2F0ZWdvcmllcyByZXNwZWN0aXZlbHkuDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIExvYWQgcGFja2FnZXMNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZHBseXIpICAgICAgDQpsaWJyYXJ5KHJlc2hhcGUyKSAgIA0KbGlicmFyeShnZ3Bsb3QyKSAgICANCmxpYnJhcnkoa25pdHIpICAgICAgDQpsaWJyYXJ5KGthYmxlRXh0cmEpIA0KbGlicmFyeShEVCkNCmxpYnJhcnkoZ2d0ZXh0KQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgU2VsZWN0IHJlbGV2YW50IHBoeXNpY29jaGVtaWNhbCBwYXJhbWV0ZXJzDQpvcF9jb25kX3dpZGUgPC0gQ0g0X3lpZWxkX2RmICU+JQ0KICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoInNhbXBsZV9pZCIsICJ0b3RhbF9hbW1vbmlhX25pdHJvZ2VuX21nX2wiLCAiZnJlZV9hbW1vbmlhX25pdHJvZ2VuX21nX2wiLCAidm9sYXRpbGVfZmF0dHlfYWNpZF9tZ19sIiwNCiAgICAgICAgICAgICAgICAgICAgICAgImFjZXRpY19hY2lkX21nX2wiLCAicHJvcGlvbmljX2FjaWRfbWdfbCIsICJidXR5cmljX2FjaWRfbWdfbCIsICJ2YWxlcmljX2FjaWRfbWdfbCIsICJjYXByb2ljX2FjaWRfbWdfbCIsDQogICAgICAgICAgICAgICAgICAgICAgICJpc29idXR5cmljX2FjaWRfbWdfbCIsICJpc292YWxlcmljX2FjaWRfbWdfbCIsICJmb3JtaWNfYWNpZF9tZ19sIiwgIm15cmlzdGljX2FjaWRfbWdfbCIsDQogICAgICAgICAgICAgICAgICAgICAgICJwYWxtaXRpY19hY2lkX21nX2wiLCAic3RlYXJpY19hY2lkX21nX2wiLCAib2xlaWNfYWNpZF9tZ19sIiwgImxpbm9sZWljX2FjaWRfbWdfbCIsICJzdWxmYXRlX21nX2wiLA0KICAgICAgICAgICAgICAgICAgICAgICAiWUNINF9tTGdWUyIsICJwcl9hYyIsICJ0YW5fYWNldGljIiwgImZyZWVkbWFuX2NsYXNzIikNCg0KIyBDaGFuZ2UgZGF0YWZyYW1lIGZvcm1hdCBmcm9tIHdpZGUgZm9ybWF0IHRvIGxvbmcgZm9ybWF0DQpvcF9jb25kIDwtIG1lbHQob3BfY29uZF93aWRlKQ0KDQojIENvbnZlcnQgQ0g0IHlpZWxkIGNhdGVnb3JpZXMgZW4gZmFjdG9yIGNsYXNzDQpmcmVlZG1hbl9sZXZlbHMgPC0gYygiQzEiLCJDMiIsIkMzIiwiQzQiLCJDNSIsIkM2IikNCm9wX2NvbmQkZnJlZWRtYW5fY2xhc3MgPC0gZmFjdG9yKG9wX2NvbmQkZnJlZWRtYW5fY2xhc3MsIGxldmVscyA9IGZyZWVkbWFuX2xldmVscykNCg0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgU2VlIHBoeXNpY29jaGVtaWNhbCBwYXJhbWV0ZXJzIGRhdGFmcmFtZQ0KZGF0YXRhYmxlKG9wX2NvbmQpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBTZWxlY3QgcGh5c2ljb2NoZW1pY2FsIHBhcmFtZXRlcnMNCnZhcmlhYmxlc19pbnRlcmVzdCA8LSBjKCJ2b2xhdGlsZV9mYXR0eV9hY2lkX21nX2wiLCJhY2V0aWNfYWNpZF9tZ19sIiwiYnV0eXJpY19hY2lkX21nX2wiLA0KICAgICAgICAgICAgICAgICAgICAgICAicHJvcGlvbmljX2FjaWRfbWdfbCIsImlzb2J1dHlyaWNfYWNpZF9tZ19sIiwiaXNvdmFsZXJpY19hY2lkX21nX2wiLA0KICAgICAgICAgICAgICAgICAgICAgICAidmFsZXJpY19hY2lkX21nX2wiLCJ0b3RhbF9hbW1vbmlhX25pdHJvZ2VuX21nX2wiLCJmcmVlX2FtbW9uaWFfbml0cm9nZW5fbWdfbCIsDQogICAgICAgICAgICAgICAgICAgICAgICJsaW5vbGVpY19hY2lkX21nX2wiLCJteXJpc3RpY19hY2lkX21nX2wiLCAib2xlaWNfYWNpZF9tZ19sIiwNCiAgICAgICAgICAgICAgICAgICAgICAgInBhbG1pdGljX2FjaWRfbWdfbCIsInN0ZWFyaWNfYWNpZF9tZ19sIiwicHJfYWMiLCAidGFuX2FjZXRpYyIpDQpgYGANCg0KYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9MiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCiMgQ3JlYXRlIGFuIGVtcHR5IGxpc3QgdG8gc3RvcmUgdGhlIHJlc3VsdHMgb2Ygc2lnbmlmaWNhbmNlIHRlc3RzIGFuZCBmaWd1cmVzLg0KcmVzdWx0cyA8LSBsaXN0KCkNCg0KIyBJdGVyYXRpb24gb3ZlciBlYWNoIHZhcmlhYmxlDQpmb3IgKHZhciBpbiB2YXJpYWJsZXNfaW50ZXJlc3QpIHsNCiAgDQogIHBoeXNfZGF0YSA8LSBvcF9jb25kICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIodmFyaWFibGUgPT0gdmFyKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHZhcmlhYmxlLCBmcmVlZG1hbl9jbGFzcywgdmFsdWUpICU+JQ0KICAgIHN0YXRzOjpuYS5vbWl0KCkNCiAgDQogICMgS3J1c2thbC1XYWxsaXMgVGVzdA0KICBrcnVza2FsIDwtIGtydXNrYWwudGVzdCh2YWx1ZSB+IGZyZWVkbWFuX2NsYXNzLCBkYXRhID0gcGh5c19kYXRhKQ0KICANCiAgIyBXaWxjb3hvbiB0ZXN0IHdpdGggQkggY29ycmVjdGlvbg0KICB3aWxjb3hvbiA8LSBwYWlyd2lzZS53aWxjb3gudGVzdChwaHlzX2RhdGEkdmFsdWUsIHBoeXNfZGF0YSRmcmVlZG1hbl9jbGFzcywgcC5hZGp1c3QubWV0aG9kID0gIkJIIikNCiAgDQogICMgQm94LWFuZC13aGlza2VyIHBsb3QNCiAgIyBBc3NpZ24gZml4ZWQgY29sb3JzIHRvIGVhY2ggQ0g0IHlpZWxkIGNhdGVnb3JpZXMNCiAgZml4ZWRfY29sb3JzIDwtIGMoIiNjYzMzMDAiLCAiI2ZmOTk2NiIsICIjMDA0Y2ZmIiwgIiNmZmNjMDAiLCAiIzk5Y2MzMyIsICIjMzM5OTAwIikNCiAgcCA8LSBnZ3Bsb3QocGh5c19kYXRhLCBhZXMoeCA9IGZyZWVkbWFuX2NsYXNzLCB5ID0gdmFsdWUsIGNvbG9yID0gZnJlZWRtYW5fY2xhc3MpKSArDQogICAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgb3V0bGllci5zaXplID0gMC41LCBub3RjaCA9IEZBTFNFKSArDQogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIpICsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc2V0TmFtZXMoZml4ZWRfY29sb3JzLCBmcmVlZG1hbl9sZXZlbHMpLCBkcm9wID0gRkFMU0UpICsNCiAgICB0aGVtZV9idygpICsNCiAgICBsYWJzKHRpdGxlID0gdmFyKSArDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oc2l6ZSA9IDEwLCBmYWNlID0gImJvbGQiKSkNCiAgDQogICMgU2F2ZSByZXN1bHRzIGluIGEgbGlzdA0KICByZXN1bHRzW1t2YXJdXSA8LSBsaXN0KA0KICAgIGtydXNrYWwgPSBrcnVza2FsLA0KICAgIHdpbGNveG9uID0gd2lsY294b24sDQogICAgZmlndXJlID0gcA0KICApDQp9DQpgYGANCg0KYGBge3IgIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KY2F0KCc8ZGl2IHN0eWxlPSJ3aWR0aDogMTAwJTsgaGVpZ2h0OiA4MDBweDsgb3ZlcmZsb3cteTogYXV0bzsgYm9yZGVyOiAxcHggc29saWQgYmxhY2s7IHBhZGRpbmc6IDIwcHg7IGJhY2tncm91bmQtY29sb3I6ICNmOGY5ZmE7Ij4nKQ0KDQojIEl0ZXJhdGUgb3ZlciBlYWNoIHZhcmlhYmxlLg0KZm9yICh2YXIgaW4gdmFyaWFibGVzX2ludGVyZXN0KSB7DQogIA0KICAjIFRpdGxlIHdpdGhvdXQgaGVhZGluZyBsZXZlbA0KICBjYXQocGFzdGUwKCI8cCBzdHlsZT0nY29sb3I6IzAwMDAwMDsgZm9udC1mYW1pbHk6IEFyaWFsOyBmb250LXdlaWdodDogYm9sZDsgZm9udC1zaXplOiAxMnB0Oyc+IPCfk4ggU3RhdGlzdGljYWwgYW5hbHlzaXMgZm9yICIsIHZhciwgIjwvcD5cbiIpKQ0KDQogICMgQ29sbGFwc2libGUgc2VjdGlvbg0KICBjYXQoIjxkZXRhaWxzPjxzdW1tYXJ5IHN0eWxlPSdjdXJzb3I6cG9pbnRlcjsgZm9udC13ZWlnaHQ6Ym9sZDsgY29sb3I6IzAwNTZiMzsnPiDimq0gU2lnbmlmaWNhbnQgdGVzdHM8L3N1bW1hcnk+XG5cbiIpDQoNCiAgIyBLcnVza2FsLVdhbGxpcyB0ZXN0DQogIGNhdCgiPHAgc3R5bGU9J2NvbG9yOiMzMzMzNjY7IGZvbnQtd2VpZ2h0OiBib2xkOyc+8J+UuSBLcnVza2FsLVdhbGxpcyB0ZXN0PC9wPlxuIikNCiAgY2F0KCI8cHJlIHN0eWxlPSdiYWNrZ3JvdW5kOiNlOWVjZWY7IHBhZGRpbmc6MTBweDsgYm9yZGVyLXJhZGl1czo1cHg7Jz48Y29kZT4iKQ0KICBjYXQocGFzdGUoY2FwdHVyZS5vdXRwdXQocmVzdWx0c1tbdmFyXV0ka3J1c2thbCksIGNvbGxhcHNlID0gIlxuIikpDQogIGNhdCgiPC9jb2RlPjwvcHJlPlxuXG4iKQ0KDQogICMgV2lsY294b24gdGVzdA0KICBjYXQoIjxwIHN0eWxlPSdjb2xvcjojMzMzMzY2OyBmb250LXdlaWdodDogYm9sZDsnPvCflLkgV2lsY294b24gdGVzdDwvcD5cbiIpDQogIGNhdCgiPHByZSBzdHlsZT0nYmFja2dyb3VuZDojZTllY2VmOyBwYWRkaW5nOjEwcHg7IGJvcmRlci1yYWRpdXM6NXB4Oyc+PGNvZGU+IikNCiAgY2F0KHBhc3RlKGNhcHR1cmUub3V0cHV0KHJlc3VsdHNbW3Zhcl1dJHdpbGNveG9uKSwgY29sbGFwc2UgPSAiXG4iKSkNCiAgY2F0KCI8L2NvZGU+PC9wcmU+XG5cbiIpDQoNCiAgY2F0KCI8L2RldGFpbHM+XG5cbiIpDQoNCiAgIyBCb3gtcGxvdHMNCiAgcHJpbnQocmVzdWx0c1tbdmFyXV0kZmlndXJlKQ0KfQ0KDQpjYXQoJzwvZGl2PicpDQpgYGANCg0KIyBSYXJlZmFjdGlvbiBjdXJ2ZXMNClJhbmRvbSBzdWJzYW1wbGluZyB3aXRob3V0IHJlcGxhY2VtZW50IHdhcyBjb25kdWN0ZWQgdXNpbmcgdGhlIGZpcnN0IHF1YXJ0aWxlIGZyZXF1ZW5jeSB0byByYXJlZnkgc2VxdWVuY2luZyBkZXB0aCBhY3Jvc3MgYWxsIHNhbXBsZXMuIFRoaXMgYXBwcm9hY2ggZ3VhcmFudGVlZCB0aGF0IHJpY2huZXNzIGVzdGltYXRlcyByZW1haW5lZCB1bmFmZmVjdGVkIGJ5IHZhcmlhdGlvbnMgaW4gc2VxdWVuY2luZyBkZXB0aC4NCg0KYGBge3Igc2V0dXAyLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgTG9hZCBwYWNrYWdlcw0KbGlicmFyeShwaHlsb3NlcSkNCmxpYnJhcnkodmVnYW4pDQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkocmVhZHhsKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgTG9hZCBkYXRhYmFzZQ0KIyBub24tcmFyZWZpZWQgc09UVXMgY291bnQgZGF0YSBmcm9tIG1ldGEtYW5hbHlzaXMNCmRmX3NvdHVzIDwtIHJlYWRfeGxzeChoZXJlKCJkYXRhIiwgIm1ldGEtYW5hbHlzaXMtbWljcm9iaWFsLWRhdGEueGxzeCIpLCBzaGVldCA9ICJvdHVzX2Fic19jb3VudCIpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5fdG9fcm93bmFtZXMoIm90dSIpICMgRGF0YSB3aXRoIGJhY3RlcmlhLWFyY2hhZWEgY2hhcmFjdGVyaXphdGlvbg0KDQpkZl9nZW5lcmEgPC0gcmVhZF94bHN4KGhlcmUoImRhdGEiLCAibWV0YS1hbmFseXNpcy1taWNyb2JpYWwtZGF0YS54bHN4IiksIHNoZWV0ID0gImdlbmVyYV9hYnNfY291bnQiKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RvX3Jvd25hbWVzKCJnZW5lcmEiKSAlPiUgIA0KICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KC0iRjI1XzciLCAtIkYxN181IiwgLSJGMTdfMyIsIC0iRjE3XzYiKSAjIFNhbXBsZXMgd2l0aG91dCBvYnNlcnZlZCBhcmNoYWVhDQpgYGANCg0KYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCiMgUmFyZWZhY3Rpb24gY3VydmVzIG9mIHRoZSBhbGwgc2FtcGxlcw0KIyBPVFUNCnJhcmVjdXJ2ZSh0KGRmX3NvdHVzKSwgc3RlcD01MCwgY2V4PTAuNSwgDQogICAgICAgICAgeGxhYiA9ICJTYW1wbGUgU2l6ZSIsIHlsYWIgPSAic09UVXMiLCBjb2wgPSAiYmx1ZSIpDQoNCiMgR2VuZXJhDQpyYXJlY3VydmUodChkZl9zb3R1cyksIHN0ZXA9NTAsIGNleD0wLjUsIA0KICAgICAgICAgIHhsYWIgPSAiU2FtcGxlIFNpemUiLCB5bGFiID0gInNPVFVzIiwgY29sID0gImJsdWUiKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgT2J0YWluIHRoZSB0b3RhbCBzdW0gb2Ygb2JzZXJ2ZWQgc09UVXMvZ2VuZXJhIGZvciBlYWNoIHNhbXBsZQ0Kc2FtcGxlX3N1bXNfc290dXMgPC0gcm93U3Vtcyh0KGRmX3NvdHVzKSkNCnNhbXBsZV9zdW1zX2dlbmVyYSA8LSByb3dTdW1zKHQoZGZfZ2VuZXJhKSkNCg0KIyBRdWFudGlsZXMNCnFfcmVzdWx0cyA8LSBsaXN0KA0KICBzT1RVcyA9IHF1YW50aWxlKHNhbXBsZV9zdW1zX3NvdHVzKSwNCiAgR2VuZXJhID0gcXVhbnRpbGUoc2FtcGxlX3N1bXNfZ2VuZXJhKQ0KKQ0KDQpwcmludChxX3Jlc3VsdHMpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBDcmVhdGUgcGh5bG9zZXEgb2JqZWN0IHdpdGggZGF0YSBjb3VudA0KcHNfb3R1cyA8LSBwaHlsb3NlcShvdHVfdGFibGUoZGZfc290dXMsIHRheGFfYXJlX3Jvd3MgPSBUUlVFKSkNCnBzX2dlbmVyYSA8LSBwaHlsb3NlcShvdHVfdGFibGUoZGZfZ2VuZXJhLCB0YXhhX2FyZV9yb3dzID0gVFJVRSkpDQoNCiMgUmFyZWZhY3Rpb24gdXNpbmcgdGhlIHNhbXBsaW5nIG1ldGhvZCB3aXRob3V0IHJlcGxhY2VtZW50LiBUaGUgZmlyc3QgcXVhcnRpbGUgb2YgdGhlIHNPVFVzIGFuZCBnZW5lcmEgY291bnQgZm91bmQgaW4gdGhlIHNhbXBsZXMsIHdoaWNoIHdlcmUgMTE1NDIgYW5kIDExNTU5IHNlcXMgcmVzcGVjdGl2ZWx5Lg0KZGF0YV9yYXJlZl9vdHVzIDwtIHJhcmVmeV9ldmVuX2RlcHRoKHBzX290dXMsIHJuZ3NlZWQgPSAxMjM0NSwgc2FtcGxlLnNpemU9MTE1NDIsIHJlcGxhY2UgPSBGKQ0KZGF0YV9yYXJlZl9nZW5lcmEgPC0gcmFyZWZ5X2V2ZW5fZGVwdGgocHNfZ2VuZXJhLCBybmdzZWVkID0gMTIzNDUsIHNhbXBsZS5zaXplPTExNTU5LCByZXBsYWNlID0gRikNCg0KIyBDb252ZXJ0IHRoZSBzT1RVcyBhbmQgZ2VuZXJhIG1hdHJpeCBpbnRvIGEgZGF0YSBmcmFtZS4gVGhlc2UgZGF0YSB3ZXJlIHVzZWQgdG8gYWxwaGEgZGl2ZXJpc3R5Lg0KZGZfcmFyZWZfb3R1cyA8LSBhcy5kYXRhLmZyYW1lKGRhdGFfcmFyZWZfb3R1cykNCmRmX3JhcmVmX2dlbmVyYSA8LSBhcy5kYXRhLmZyYW1lKGRhdGFfcmFyZWZfZ2VuZXJhKQ0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQojIFJhcmVmYWN0aW9uIEN1cnZlIFBsb3RzIC0gc09UVXMNCnJhcmVjdXJ2ZSh0KGRmX3JhcmVmX290dXMpLCBzdGVwPTUwLCBjZXg9MC41LCANCiAgICAgICAgICB4bGFiID0gIlNhbXBsZSBTaXplIiwgeWxhYiA9ICJzT1RVcyBjb3VudCIsIGNvbCA9ICJibHVlIikNCg0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQojIFJhcmVmYWN0aW9uIEN1cnZlIFBsb3RzIC0gR2VuZXJhDQpyYXJlY3VydmUodChkZl9yYXJlZl9nZW5lcmEpLCBzdGVwPTUwLCBjZXg9MC41LCANCiAgICAgICAgICB4bGFiID0gIlNhbXBsZSBTaXplIiwgeWxhYiA9ICJHZW5lcmEgY291bnQiLCBjb2wgPSAiYmx1ZSIpICAgICAgICAgDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBTYXZlIG9iamVjdCBDSDRfeWllbGRfZGYgYXMgUkRTIG9iamVjdCBmb3IgdXBzdHJlYW1zIGFuYWx5c2lzDQpzYXZlUkRTKGRmX3JhcmVmX290dXMsIGZpbGUgPSBoZXJlKCJyZHMiLCJzT1RVc19yYXJlZmllZF9jb3VudHMucmRzIikpDQpzYXZlUkRTKGRmX3JhcmVmX2dlbmVyYSwgZmlsZSA9IGhlcmUoInJkcyIsImdlbmVyYV9yYXJlZmllZF9jb3VudHMucmRzIikpDQpgYGANCg0KIyBBbHBoYSBkaXZlcnNpdHkNCkRpdmVyc2l0eSBhbmFseXNlcyB3ZXJlIHBlcmZvcm1lZCBhbmQgY29tcGFyZWQgdXNpbmcgYSByYXJlZmllZCBjb3VudCB0YWJsZSBhdCBzT1RVIGxldmVsIGFuZCBnZW51cyBsZXZlbC4gQWxwaGEgZGl2ZXJzaXR5IHdhcyBncm91cGVkIGZyb20gbWV0aGFuZSB5aWVsZCBjYXRlZ29yaWVzIGFuZCBhc3Nlc3NlZCB1c2luZyBtdWx0aXBsZSBpbmRpY2VzLCBpbmNsdWRpbmcgQ2hhbzEsIFBpZWxvdeKAmXMgZXZlbm5lc3MsIFNoYW5ub24sIGFuZCBIaWxsIG51bWJlcnMgKHEwLCBxMSwgYW5kIHEyKS4gVGhlIGludGVyYWN0aW9uIGFtb25nIHRoZXNlIGNhdGVnb3JpZXMgYW5kIGFscGhhIGRpdmVyc2l0eSB3YXMgZXZhbHVhdGVkIHVzaW5nIEtydXNrYWwtV2FsbGlzIGFuZCBXaWxjb3hvbiByYW5rIHN1bSB0ZXN0cyB3aXRoIEJlbmphbWluaS1Ib2NoYmVyZyBjb3JyZWN0aW9uDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIExvYWQgcGFja2FnZXMNCmxpYnJhcnkocGh5bG9zZXEpDQpsaWJyYXJ5KHZlZ2FuKQ0KbGlicmFyeShoaWxsZGl2KQ0KbGlicmFyeShyZXNoYXBlMikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkoZm9yY2F0cykNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIENyZWF0ZSBwaHlsb3NlcSBvYmplY3Qgd2l0aCByYXJlZmllZCBkYXRhIGNvdW50DQpwc19yYXJlX3NvdHVzIDwtIHBoeWxvc2VxKG90dV90YWJsZShkZl9yYXJlZl9vdHVzLCB0YXhhX2FyZV9yb3dzID0gVFJVRSkpDQpwc19yYXJlX2dlbmVyYSA8LSBwaHlsb3NlcShvdHVfdGFibGUoZGZfcmFyZWZfZ2VuZXJhLCB0YXhhX2FyZV9yb3dzID0gVFJVRSkpDQojIExvYWQgZGF0YWJhc2UNCkNINF95aWVsZF9kZiA8LSByZWFkUkRTKGZpbGUgPSBoZXJlKCJyZHMiLCJDSDRfeWllbGRfZGYucmRzIikpDQpgYGANCiMjIHNPVFVzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIHNPVFVzIGNvdW50DQpvYnMgPC0gZXN0aW1hdGVfcmljaG5lc3MocHNfcmFyZV9zb3R1cywgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIk9ic2VydmVkIikNCiMgQ2hhbzENCmNoYW8xIDwtIGVzdGltYXRlX3JpY2huZXNzKHBzX3JhcmVfc290dXMsIHNwbGl0ID0gVFJVRSwgbWVhc3VyZSA9ICJDaGFvMSIpICU+JSBkcGx5cjo6c2VsZWN0KCJDaGFvMSIpDQojIEFjZQ0KYWNlIDwtIGVzdGltYXRlX3JpY2huZXNzKHBzX3JhcmVfc290dXMsIHNwbGl0ID0gVFJVRSwgbWVhc3VyZSA9ICJBQ0UiKSAgJT4lIGRwbHlyOjpzZWxlY3QoIkFDRSIpDQojIFNoYW5ub24NCnNoYW5ub24gPC0gZXN0aW1hdGVfcmljaG5lc3MocHNfcmFyZV9zb3R1cywgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIlNoYW5ub24iKSANCiMgU2ltcHNvbg0KU2ltcHNvbiA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwc19yYXJlX3NvdHVzLCBzcGxpdCA9IFRSVUUsIG1lYXN1cmUgPSAiU2ltcHNvbiIpIA0KIyBJbnZTaW1wc29uDQpJbnZTaW1wc29uIDwtIGVzdGltYXRlX3JpY2huZXNzKHBzX3JhcmVfc290dXMsIHNwbGl0ID0gVFJVRSwgbWVhc3VyZSA9ICJJbnZTaW1wc29uIikgDQojIEZpc2hlcg0KRmlzaGVyIDwtIGVzdGltYXRlX3JpY2huZXNzKHBzX3JhcmVfc290dXMsIHNwbGl0ID0gVFJVRSwgbWVhc3VyZSA9ICJGaXNoZXIiKSANCiMgUGllbG91DQpwaWVsb3UgPC0gc2hhbm5vbi9sb2cob2JzKQ0KY29sbmFtZXMocGllbG91KSA8LSBjKCJwaWVsb3UiKQ0KIyBxMCAtIFNwZWNpZXMgcmljaG5lc3MNCnEwIDwtIGhpbGxfZGl2KGRmX3JhcmVmX290dXMsIHF2YWx1ZSA9IDApICU+JSBhcy5kYXRhLmZyYW1lKCkNCmNvbG5hbWVzKHEwKSA8LSAicTAiDQojcTEgLSBTaGFubm9uIGRpdmVyc2l0eQ0KcTEgPC0gaGlsbF9kaXYoZGZfcmFyZWZfb3R1cywgcXZhbHVlID0gMSkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KY29sbmFtZXMocTEpIDwtICJxMSINCiMgcTIgLSBTaW1wc29uIGRpdmVyc2l0eQ0KcTIgPC0gaGlsbF9kaXYoZGZfcmFyZWZfb3R1cywgcXZhbHVlID0gMikgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KY29sbmFtZXMocTIpIDwtICJxMiINCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgd2l0aCBhbHBoYSBkaXZlcnNpdHkgaW5kaWNlcw0KZGZfYWxwaGFfZGl2IDwtIGNiaW5kKA0KICBvYnMsY2hhbzEsYWNlLHNoYW5ub24sU2ltcHNvbixJbnZTaW1wc29uLA0KICBGaXNoZXIscGllbG91LHEwLHExLHEyKQ0KDQojIFNhdmUgdGhlIGZpbGUgaW4gLnJkcyBmb3JtYXQgZm9yIHVzZSBpbiB1cHN0cmVhbSBhcHBsaWNhdGlvbnMgaW4gUk1hcmtkb3duIFBhcnQgMg0Kc2F2ZVJEUyhkZl9hbHBoYV9kaXYsIGZpbGUgPSBoZXJlKCJyZHMiLCJkZl9hbHBoYV9kaXZfc290dXMucmRzIikpDQoNCiMgIyBDb252ZXJ0IHJvdyBuYW1lcyBvZiB0aGUgYWxwaGEgZGl2ZXJzaXR5IGRhdGFmcmFtZSB0byBhIGNvbHVtbiBuYW1lZCAnc2FtcGxlX2lkJywgDQojIHJlc2hhcGUgdGhlIGRhdGFmcmFtZSB0byBsb25nIGZvcm1hdCwgbWVyZ2Ugd2l0aCBtZXRoYW5lIHlpZWxkIGNsYXNzaWZpY2F0aW9uIGRhdGEgDQojIGJhc2VkIG9uICdzYW1wbGVfaWQnLCBhbmQgY29udmVydCAndmFyaWFibGUnIHRvIGNoYXJhY3RlciBhbmQgJ2ZyZWVkbWFuX2NsYXNzJyB0byBmYWN0b3IuDQpkZl9hbHBoYV9kaXYgPC0gZGZfYWxwaGFfZGl2ICU+JQ0KICAgICAgICAgICAgICAgIHJvd25hbWVzX3RvX2NvbHVtbiguLCB2YXIgPSAic2FtcGxlX2lkIikgJT4lDQogICAgICAgICAgICAgICAgbWVsdCgpICU+JQ0KICAgICAgICAgICAgICAgIGxlZnRfam9pbihDSDRfeWllbGRfZGYgJT4lIGRwbHlyOjpzZWxlY3Qoc2FtcGxlX2lkLCBmcmVlZG1hbl9jbGFzcyksIGJ5ID0gInNhbXBsZV9pZCIpICU+JQ0KICAgICAgICAgICAgICAgIG11dGF0ZSh2YXJpYWJsZSA9IGFzLmNoYXJhY3Rlcih2YXJpYWJsZSksDQogICAgICAgICAgICAgICAgZnJlZWRtYW5fY2xhc3MgPSBhcy5mYWN0b3IoZnJlZWRtYW5fY2xhc3MpKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgQ29udmVydCBDSDQgeWllbGQgY2F0ZWdvcmllcyBpbnRvIGEgZmFjdG9yIGNsYXNzDQpmcmVlZG1hbl9sZXZlbHMgPC0gYygiQzEiLCJDMiIsIkMzIiwiQzQiLCJDNSIsIkM2IikNCiMgQ29udmVydCBmcmVlZG1hbl9jbGFzcyBpbnRvIGEgZmFjdG9yIHdpdGggZGVmaW5lZCBsZXZlbHMNCmRmX2FscGhhX2RpdiRmcmVlZG1hbl9jbGFzcyA8LSBmYWN0b3IoZGZfYWxwaGFfZGl2JGZyZWVkbWFuX2NsYXNzLCBsZXZlbHMgPSBmcmVlZG1hbl9sZXZlbHMpDQpgYGANCg0KYGBge3IgIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQojIE9idGFpbiB1bmlxdWUgbmFtZXMgb2YgZGl2ZXJzaXR5IGluZGljZXMNCnNvdHVzX2Rpdl9uYW1lcyA8LSB1bmlxdWUoZGZfYWxwaGFfZGl2JHZhcmlhYmxlKQ0KDQojIENyZWF0ZSBhbiBlbXB0eSBsaXN0IHRvIHN0b3JlIHRoZSByZXN1bHRzLg0KYWxwaGFfZGl2X3NvdHVzIDwtIGxpc3QoKQ0KDQojIEl0ZXJhdGUgb3ZlciBlYWNoIGRpdmVyc2l0eSBpbmRleA0KZm9yICh2YXIgaW4gc290dXNfZGl2X25hbWVzKSB7DQogICMgRmlsdGVyIHJlbGV2YW50IGRhdGENCiAgc290dXNfZGF0YSA8LSBkZl9hbHBoYV9kaXYgJT4lDQogICAgZHBseXI6OmZpbHRlcih2YXJpYWJsZSA9PSB2YXIpICU+JSANCiAgICBkcGx5cjo6c2VsZWN0KHZhcmlhYmxlLCBmcmVlZG1hbl9jbGFzcywgdmFsdWUpICU+JQ0KICAgIG5hLm9taXQoKQ0KICANCg0KICAjIEtydXNrYWwtV2FsbGlzIGh5cG90aGVzaXMgdGVzdA0KICBrcnVza2FsIDwtIGtydXNrYWwudGVzdCh2YWx1ZSB+IGZyZWVkbWFuX2NsYXNzLCBkYXRhID0gc290dXNfZGF0YSkNCiAgDQogICMgUGFpcndpc2UgV2lsY294b24gaHlwb3RoZXNpcyB0ZXN0DQogIHdpbGNveG9uIDwtIHBhaXJ3aXNlLndpbGNveC50ZXN0KHNvdHVzX2RhdGEkdmFsdWUsIHNvdHVzX2RhdGEkZnJlZWRtYW5fY2xhc3MsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLmFkanVzdC5tZXRob2QgPSAiQkgiKQ0KDQogICMgRGVmaW5lIGZpeGVkIGNvbG9ycyBmb3IgZWFjaCBDSDQgeWllbGQgY2F0ZWdvcnkuDQogIGZpeGVkX2NvbG9ycyA8LSBjKCIjMzM5OTAwIiwgIiMwMDRjZmYiLCIjOTljYzMzIiwiI2ZmOTk2NiIsICIjZmZjYzAwIiwiI2NjMzMwMCIpDQoNCiAgIyBCb3hwbG90IHBsb3QNCiAgcCA8LSBnZ3Bsb3Qoc290dXNfZGF0YSwgYWVzKHggPSBmcmVlZG1hbl9jbGFzcywgeSA9IHZhbHVlLCBjb2xvciA9IGZyZWVkbWFuX2NsYXNzKSkgKw0KICAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIG5vdGNoID0gRkFMU0UpICsNCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgc2l6ZSA9IDEpICsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc2V0TmFtZXMoZml4ZWRfY29sb3JzLCB1bmlxdWUoc290dXNfZGF0YSRmcmVlZG1hbl9jbGFzcykpLCBkcm9wID0gRkFMU0UpICsNCiAgICB0aGVtZV9idygpICsNCiAgICBsYWJzKHRpdGxlID0gdmFyKSArDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2UgPSAiYm9sZCIpKQ0KDQogICMgU2F2ZSByZXN1bHRzIGluIHRoZSBsaXN0DQogIGFscGhhX2Rpdl9zb3R1c1tbdmFyXV0gPC0gbGlzdCgNCiAgICBrcnVza2FsID0ga3J1c2thbCwNCiAgICB3aWxjb3hvbiA9IHdpbGNveG9uLA0KICAgIGZpZ3VyZSA9IHANCiAgKQ0KfQ0KYGBgDQoNCmBgYHtyICBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0yLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30NCmNhdCgnPGRpdiBzdHlsZT0id2lkdGg6IDEwMCU7IGhlaWdodDogODAwcHg7IG92ZXJmbG93LXk6IGF1dG87IGJvcmRlcjogMXB4IHNvbGlkIGJsYWNrOyBwYWRkaW5nOiAyMHB4OyBiYWNrZ3JvdW5kLWNvbG9yOiAjZjhmOWZhOyI+JykNCg0KIyBJdGVyYXRlIG92ZXIgZWFjaCB2YXJpYWJsZS4NCmZvciAodmFyIGluIHNvdHVzX2Rpdl9uYW1lcykgew0KICANCiAgIyBIZWFkZXIgd2l0aCBzZXBhcmF0b3IgbGluZSAoY29udmVydGVkIHRvIHBhcmFncmFwaCkNCiAgY2F0KHBhc3RlMCgiPHAgc3R5bGU9J2NvbG9yOiMwMDAwMDA7IGZvbnQtZmFtaWx5OiBBcmlhbDsgZm9udC13ZWlnaHQ6IGJvbGQ7IGZvbnQtc2l6ZTogMTJwdDsnPiDwn5OIIFN0YXRpc3RpY2FsIGFuYWx5c2lzIGZvciAiLCB2YXIsICI8L3A+XG4iKSkNCiAgDQogICMgQ29sbGFwc2libGUgYnV0dG9uIHRvIGRpc3BsYXkgcmVzdWx0cw0KICBjYXQoIjxkZXRhaWxzPjxzdW1tYXJ5IHN0eWxlPSdjdXJzb3I6cG9pbnRlcjsgZm9udC13ZWlnaHQ6Ym9sZDsgY29sb3I6IzAwNTZiMzsnPiAg4pqtIFNpZ25pZmljYW50IHRlc3RzIDwvc3VtbWFyeT5cblxuIikNCiAgDQogICMgS3J1c2thbC1XYWxsaXMgdGVzdCAoY29udmVydGVkIHRvIHBhcmFncmFwaCB3aXRoIGJvbGQgdGV4dCkNCiAgY2F0KCI8cCBzdHlsZT0nY29sb3I6IzMzMzM2NjsgZm9udC13ZWlnaHQ6IGJvbGQ7Jz7wn5S5IEtydXNrYWwtV2FsbGlzIHRlc3Q8L3A+XG4iKQ0KICBjYXQoIjxwcmUgc3R5bGU9J2JhY2tncm91bmQ6I2U5ZWNlZjsgcGFkZGluZzoxMHB4OyBib3JkZXItcmFkaXVzOjVweDsnPjxjb2RlPiIpDQogIGNhdChwYXN0ZShjYXB0dXJlLm91dHB1dChhbHBoYV9kaXZfc290dXNbW3Zhcl1dJGtydXNrYWwpLCBjb2xsYXBzZSA9ICJcbiIpKQ0KICBjYXQoIjwvY29kZT48L3ByZT5cblxuIikNCiAgDQogICMgV2lsY294b24gdGVzdCAoY29udmVydGVkIHRvIHBhcmFncmFwaCB3aXRoIGJvbGQgdGV4dCkNCiAgY2F0KCI8cCBzdHlsZT0nY29sb3I6IzMzMzM2NjsgZm9udC13ZWlnaHQ6IGJvbGQ7Jz7wn5S5IFdpbGNveG9uIHRlc3Q8L3A+XG4iKQ0KICBjYXQoIjxwcmUgc3R5bGU9J2JhY2tncm91bmQ6I2U5ZWNlZjsgcGFkZGluZzoxMHB4OyBib3JkZXItcmFkaXVzOjVweDsnPjxjb2RlPiIpDQogIGNhdChwYXN0ZShjYXB0dXJlLm91dHB1dChhbHBoYV9kaXZfc290dXNbW3Zhcl1dJHdpbGNveG9uKSwgY29sbGFwc2UgPSAiXG4iKSkNCiAgY2F0KCI8L2NvZGU+PC9wcmU+XG5cbiIpDQogIA0KICBjYXQoIjwvZGV0YWlscz5cblxuIikNCiAgDQogICMgQm94LXBsb3RzDQogIHByaW50KGFscGhhX2Rpdl9zb3R1c1tbdmFyXV0kZmlndXJlKQ0KfQ0KDQpjYXQoJzwvZGl2PicpDQpgYGANCg0KOjo6IGNlbnRlci10ZXh0DQpTaWduaWZpY2FudCB0ZXN0IGFuZCBkaXN0cmlidXRpb24gb2YgYWxwaGEgZGl2ZXJzaXR5IGluZGljZXMgZ3JvdXBlZCBieSBtZXRoYW5lIHlpZWxkIGNhdGVnb3JpZXMgaWRlbnRpZmllZCBieSBkaWZmZXJlbnQgY29sb3JzIChDMS1DNikgYXQgc09UVSBsZXZlbC4NCjo6Og0KDQojIyBHZW5lcmENCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgc09UVXMgY291bnQNCm9icyA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwc19yYXJlX2dlbmVyYSwgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIk9ic2VydmVkIikNCiMgQ2hhbzENCmNoYW8xIDwtIGVzdGltYXRlX3JpY2huZXNzKHBzX3JhcmVfZ2VuZXJhLCBzcGxpdCA9IFRSVUUsIG1lYXN1cmUgPSAiQ2hhbzEiKSAlPiUgZHBseXI6OnNlbGVjdCgiQ2hhbzEiKQ0KIyBBY2UNCmFjZSA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwc19yYXJlX2dlbmVyYSwgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIkFDRSIpICAlPiUgZHBseXI6OnNlbGVjdCgiQUNFIikNCiMgU2hhbm5vbg0Kc2hhbm5vbiA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwc19yYXJlX2dlbmVyYSwgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIlNoYW5ub24iKSANCiMgU2ltcHNvbg0KU2ltcHNvbiA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwc19yYXJlX2dlbmVyYSwgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIlNpbXBzb24iKSANCiMgSW52U2ltcHNvbg0KSW52U2ltcHNvbiA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwc19yYXJlX2dlbmVyYSwgc3BsaXQgPSBUUlVFLCBtZWFzdXJlID0gIkludlNpbXBzb24iKSANCiMgRmlzaGVyDQpGaXNoZXIgPC0gZXN0aW1hdGVfcmljaG5lc3MocHNfcmFyZV9nZW5lcmEsIHNwbGl0ID0gVFJVRSwgbWVhc3VyZSA9ICJGaXNoZXIiKSANCiMgUGllbG91DQpwaWVsb3UgPC0gc2hhbm5vbi9sb2cob2JzKQ0KY29sbmFtZXMocGllbG91KSA8LSBjKCJwaWVsb3UiKQ0KIyBxMCAtIFNwZWNpZXMgcmljaG5lc3MNCnEwIDwtIGhpbGxfZGl2KGRmX3JhcmVmX2dlbmVyYSwgcXZhbHVlID0gMCkgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KY29sbmFtZXMocTApIDwtICJxMCINCiNxMSAtIFNoYW5ub24gZGl2ZXJzaXR5DQpxMSA8LSBoaWxsX2RpdihkZl9yYXJlZl9nZW5lcmEsIHF2YWx1ZSA9IDEpICU+JSBhcy5kYXRhLmZyYW1lKCkNCmNvbG5hbWVzKHExKSA8LSAicTEiDQojIHEyIC0gU2ltcHNvbiBkaXZlcnNpdHkNCnEyIDwtIGhpbGxfZGl2KGRmX3JhcmVmX2dlbmVyYSwgcXZhbHVlID0gMikgJT4lIGFzLmRhdGEuZnJhbWUoKQ0KY29sbmFtZXMocTIpIDwtICJxMiINCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVRSVUV9DQojIENyZWF0ZSBhIGRhdGEgZnJhbWUgd2l0aCBhbHBoYSBkaXZlcnNpdHkgaW5kaWNlcw0KZGZfYWxwaGFfZGl2IDwtIGNiaW5kKA0KICBvYnMsY2hhbzEsYWNlLHNoYW5ub24sU2ltcHNvbixJbnZTaW1wc29uLA0KICBGaXNoZXIscGllbG91LHEwLHExLHEyKQ0KDQojIFNhdmUgdGhlIGZpbGUgaW4gLnJkcyBmb3JtYXQgZm9yIHVzZSBpbiB1cHN0cmVhbSBhcHBsaWNhdGlvbnMgaW4gUk1hcmtkb3duIFBhcnQgMg0Kc2F2ZVJEUyhkZl9hbHBoYV9kaXYsIGZpbGUgPSBoZXJlKCJyZHMiLCJkZl9hbHBoYV9kaXZfZ2VuZXJhLnJkcyIpKQ0KDQojICMgQ29udmVydCByb3cgbmFtZXMgb2YgdGhlIGFscGhhIGRpdmVyc2l0eSBkYXRhZnJhbWUgdG8gYSBjb2x1bW4gbmFtZWQgJ3NhbXBsZV9pZCcsIA0KIyByZXNoYXBlIHRoZSBkYXRhZnJhbWUgdG8gbG9uZyBmb3JtYXQsIG1lcmdlIHdpdGggbWV0aGFuZSB5aWVsZCBjbGFzc2lmaWNhdGlvbiBkYXRhIA0KIyBiYXNlZCBvbiAnc2FtcGxlX2lkJywgYW5kIGNvbnZlcnQgJ3ZhcmlhYmxlJyB0byBjaGFyYWN0ZXIgYW5kICdmcmVlZG1hbl9jbGFzcycgdG8gZmFjdG9yLg0KZGZfYWxwaGFfZGl2IDwtIGRmX2FscGhhX2RpdiAlPiUNCiAgICAgICAgICAgICAgICByb3duYW1lc190b19jb2x1bW4oLiwgdmFyID0gInNhbXBsZV9pZCIpICU+JQ0KICAgICAgICAgICAgICAgIG1lbHQoKSAlPiUNCiAgICAgICAgICAgICAgICBsZWZ0X2pvaW4oQ0g0X3lpZWxkX2RmICU+JSBkcGx5cjo6c2VsZWN0KHNhbXBsZV9pZCwgZnJlZWRtYW5fY2xhc3MpLCBieSA9ICJzYW1wbGVfaWQiKSAlPiUNCiAgICAgICAgICAgICAgICBtdXRhdGUodmFyaWFibGUgPSBhcy5jaGFyYWN0ZXIodmFyaWFibGUpLA0KICAgICAgICAgICAgICAgIGZyZWVkbWFuX2NsYXNzID0gYXMuZmFjdG9yKGZyZWVkbWFuX2NsYXNzKSkNCg0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgQ29udmVydCBDSDQgeWllbGQgY2F0ZWdvcmllcyBlbiBmYWN0b3IgY2xhc3MNCmZyZWVkbWFuX2xldmVscyA8LSBjKCJDMSIsIkMyIiwiQzMiLCJDNCIsIkM1IiwiQzYiKQ0KIyBDb252ZXJ0IGZyZWVkbWFuX2NsYXNzIGEgZmFjdG9yIHdpdGggNiBsZXZlbHMNCmRmX2FscGhhX2RpdiRmcmVlZG1hbl9jbGFzcyA8LSBmYWN0b3IoZGZfYWxwaGFfZGl2JGZyZWVkbWFuX2NsYXNzLCBsZXZlbHMgPSBmcmVlZG1hbl9sZXZlbHMpDQpgYGANCg0KYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9MiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCiMgT2J0YWluIHVuaXF1ZSBuYW1lcyBvZiBkaXZlcnNpdHkgaW5kaWNlcw0KZ2VuZXJhX2Rpdl9uYW1lcyA8LSB1bmlxdWUoZGZfYWxwaGFfZGl2JHZhcmlhYmxlKQ0KDQojIENyZWF0ZSBhbiBlbXB0eSBsaXN0IHRvIHN0b3JlIHRoZSByZXN1bHRzLg0KYWxwaGFfZGl2X2dlbmVyYSA8LSBsaXN0KCkNCg0KIyBJdGVyYXRlIG92ZXIgZWFjaCB2YXJpYWJsZS4NCmZvciAodmFyIGluIGdlbmVyYV9kaXZfbmFtZXMpIHsNCiAgIyBGaWx0ZXIgcmVsZXZhbnQgZGF0YQ0KICBnZW5lcmFfZGF0YSA8LSBkZl9hbHBoYV9kaXYgJT4lDQogICAgZHBseXI6OmZpbHRlcih2YXJpYWJsZSA9PSB2YXIpICU+JSANCiAgICBkcGx5cjo6c2VsZWN0KHZhcmlhYmxlLCBmcmVlZG1hbl9jbGFzcywgdmFsdWUpICU+JQ0KICAgIG5hLm9taXQoKQ0KICANCg0KICAjIEtydXNrYWwtV2FsbGlzIHRlc3QNCiAga3J1c2thbCA8LSBrcnVza2FsLnRlc3QodmFsdWUgfiBmcmVlZG1hbl9jbGFzcywgZGF0YSA9IGdlbmVyYV9kYXRhKQ0KICANCiAgIyBQYWlyd2lzZSBXaWxjb3hvbiB0ZXN0DQogIHdpbGNveG9uIDwtIHBhaXJ3aXNlLndpbGNveC50ZXN0KGdlbmVyYV9kYXRhJHZhbHVlLCBnZW5lcmFfZGF0YSRmcmVlZG1hbl9jbGFzcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAuYWRqdXN0Lm1ldGhvZCA9ICJCSCIpDQoNCiAgIyBEZWZpbmUgZml4ZWQgY29sb3JzIGZvciBlYWNoIENINCB5aWVsZCBjYXRlZ29yeS4NCiAgZml4ZWRfY29sb3JzIDwtIGMoIiMzMzk5MDAiLCAiIzAwNGNmZiIsIiM5OWNjMzMiLCIjZmY5OTY2IiwgIiNmZmNjMDAiLCIjY2MzMzAwIikNCg0KICAjIEJveHBsb3QNCiAgcCA8LSBnZ3Bsb3QoZ2VuZXJhX2RhdGEsIGFlcyh4ID0gZnJlZWRtYW5fY2xhc3MsIHkgPSB2YWx1ZSwgY29sb3IgPSBmcmVlZG1hbl9jbGFzcykpICsNCiAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBub3RjaCA9IEZBTFNFKSArDQogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIHNpemUgPSAxKSArDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHNldE5hbWVzKGZpeGVkX2NvbG9ycywgdW5pcXVlKGdlbmVyYV9kYXRhJGZyZWVkbWFuX2NsYXNzKSksIGRyb3AgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKw0KICAgIGxhYnModGl0bGUgPSB2YXIpICsNCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIikpDQoNCiAgIyBTYXZlIHJlc3VsdHMgaW4gdGhlIGxpc3QNCiAgYWxwaGFfZGl2X2dlbmVyYVtbdmFyXV0gPC0gbGlzdCgNCiAgICBrcnVza2FsID0ga3J1c2thbCwNCiAgICB3aWxjb3hvbiA9IHdpbGNveG9uLA0KICAgIGZpZ3VyZSA9IHANCiAgKQ0KfQ0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KY2F0KCc8ZGl2IHN0eWxlPSJ3aWR0aDogMTAwJTsgaGVpZ2h0OiA4MDBweDsgb3ZlcmZsb3cteTogYXV0bzsgYm9yZGVyOiAxcHggc29saWQgYmxhY2s7IHBhZGRpbmc6IDIwcHg7IGJhY2tncm91bmQtY29sb3I6ICNmOGY5ZmE7Ij4nKQ0KDQojIEl0ZXJhdGUgb3ZlciBlYWNoIHZhcmlhYmxlLg0KZm9yICh2YXIgaW4gZ2VuZXJhX2Rpdl9uYW1lcykgew0KICANCiAgIyBIZWFkZXIgd2l0aCBzZXBhcmF0b3IgbGluZSAoY29udmVydGVkIHRvIHBhcmFncmFwaCkNCiAgY2F0KHBhc3RlMCgiPHAgc3R5bGU9J2NvbG9yOiMwMDAwMDA7IGZvbnQtZmFtaWx5OiBBcmlhbDsgZm9udC13ZWlnaHQ6IGJvbGQ7IGZvbnQtc2l6ZTogMTJwdDsnPiDwn5OIIFN0YXRpc3RpY2FsIGFuYWx5c2lzIGZvciAiLCB2YXIsICI8L3A+XG4iKSkNCiAgDQogICMgQ29sbGFwc2libGUgYnV0dG9uIHRvIGRpc3BsYXkgcmVzdWx0cw0KICBjYXQoIjxkZXRhaWxzPjxzdW1tYXJ5IHN0eWxlPSdjdXJzb3I6cG9pbnRlcjsgZm9udC13ZWlnaHQ6Ym9sZDsgY29sb3I6IzAwNTZiMzsnPiAg4pqtIFNpZ25pZmljYW50IHRlc3RzIDwvc3VtbWFyeT5cblxuIikNCiAgDQogICMgS3J1c2thbC1XYWxsaXMgdGVzdCAoY29udmVydGVkIHRvIHBhcmFncmFwaCB3aXRoIGJvbGQgdGV4dCkNCiAgY2F0KCI8cCBzdHlsZT0nY29sb3I6IzMzMzM2NjsgZm9udC13ZWlnaHQ6IGJvbGQ7Jz7wn5S5IEtydXNrYWwtV2FsbGlzIHRlc3Q8L3A+XG4iKQ0KICBjYXQoIjxwcmUgc3R5bGU9J2JhY2tncm91bmQ6I2U5ZWNlZjsgcGFkZGluZzoxMHB4OyBib3JkZXItcmFkaXVzOjVweDsnPjxjb2RlPiIpDQogIGNhdChwYXN0ZShjYXB0dXJlLm91dHB1dChhbHBoYV9kaXZfZ2VuZXJhW1t2YXJdXSRrcnVza2FsKSwgY29sbGFwc2UgPSAiXG4iKSkNCiAgY2F0KCI8L2NvZGU+PC9wcmU+XG5cbiIpDQogIA0KICAjIFdpbGNveG9uIHRlc3QgKGNvbnZlcnRlZCB0byBwYXJhZ3JhcGggd2l0aCBib2xkIHRleHQpDQogIGNhdCgiPHAgc3R5bGU9J2NvbG9yOiMzMzMzNjY7IGZvbnQtd2VpZ2h0OiBib2xkOyc+8J+UuSBXaWxjb3hvbiB0ZXN0PC9wPlxuIikNCiAgY2F0KCI8cHJlIHN0eWxlPSdiYWNrZ3JvdW5kOiNlOWVjZWY7IHBhZGRpbmc6MTBweDsgYm9yZGVyLXJhZGl1czo1cHg7Jz48Y29kZT4iKQ0KICBjYXQocGFzdGUoY2FwdHVyZS5vdXRwdXQoYWxwaGFfZGl2X2dlbmVyYVtbdmFyXV0kd2lsY294b24pLCBjb2xsYXBzZSA9ICJcbiIpKQ0KICBjYXQoIjwvY29kZT48L3ByZT5cblxuIikNCiAgDQogIGNhdCgiPC9kZXRhaWxzPlxuXG4iKQ0KICANCiAgIyBCb3gtcGxvdHMNCiAgcHJpbnQoYWxwaGFfZGl2X2dlbmVyYVtbdmFyXV0kZmlndXJlKQ0KfQ0KDQpjYXQoJzwvZGl2PicpDQpgYGANCg0KOjo6IGNlbnRlci10ZXh0DQpTaWduaWZpY2FudCB0ZXN0IGFuZCBkaXN0cmlidXRpb24gb2YgYWxwaGEgZGl2ZXJzaXR5IGluZGljZXMgZ3JvdXBlZCBieSBtZXRoYW5lIHlpZWxkIGNhdGVnb3JpZXMgaWRlbnRpZmllZCBieSBkaWZmZXJlbnQgY29sb3JzIChDMS1DNikgYXQgZ2VudXMgbGV2ZWwuDQo6OjoNCg0KIyBCZXRhIGRpdmVyc2l0eQ0KQmV0YSBkaXZlcnNpdHkgYW5hbHlzaXMgd2VyZSBwZXJmb3JtZWQgYW5kIGNvbXBhcmVkIHVzaW5nIGEgcmFyZWZpZWQgY291bnQgdGFibGUgYXQgc09UVSBsZXZlbCBhbmQgZ2VudXMgbGV2ZWwuIFRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gbWV0aGFuZSB5aWVsZCBjYXRlZ29yaWVzIGFuZCBiZXRhIGRpdmVyc2l0eSBkaXN0YW5jZXMgd2VyZSBhc3Nlc3NlZCB1c2luZyBBTk9TSU0gd2l0aCA5OTkgcGVybXV0YXRpb25zIChwIDwgMC4wNSkuDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgTG9hZCBwYWNrYWdlcw0KbGlicmFyeShwaHlsb3NlcSkNCmxpYnJhcnkodmVnYW4pDQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkoRFQpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBMb2FkIGRhdGFiYXNlIHdpdGggcmFyZWZpZWQgc09UVXMgZGF0YQ0KZGZfcmFyZWZfb3R1cyA8LSByZWFkUkRTKGZpbGUgPSBoZXJlKCJyZHMiLCJzT1RVc19yYXJlZmllZF9jb3VudHMucmRzIikpICU+JQ0KICAgICAgICAgICAgICAgICB0KCkgIyBSb3RhdGUNCmRmX3JhcmVmX2dlbmVyYSA8LSByZWFkUkRTKGZpbGUgPSBoZXJlKCJyZHMiLCJnZW5lcmFfcmFyZWZpZWRfY291bnRzLnJkcyIpKSAlPiUNCiAgICAgICAgICAgICAgICAgdCgpICMgUm90YXRlDQojIExvYWQgZGF0YWJhc2Ugd2l0aCBtZXRoYW5lIHlpZWxkIGNhdGVnb3JpZXMNCkNINF95aWVsZF9kZiA8LSByZWFkUkRTKGZpbGUgPSBoZXJlKCJyZHMiLCJDSDRfeWllbGRfZGYucmRzIikpICU+JQ0KICAgICAgICAgICAgICAgIGNvbHVtbl90b19yb3duYW1lcygic2FtcGxlX2lkIikNCmBgYA0KDQojIyBzT1RVcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBDb21wdXRlIEJyYXktQ3VydGlzIGRpc3RhbmNlIG1hdHJpeCBmcm9tIHJhcmVmaWVkIE9UVSB0YWJsZSANCnRheF9iY19kaXN0bWF0IDwtIHZlZ2Rpc3QoZGZfcmFyZWZfb3R1cywgbWV0aG9kID0gImJyYXkiKQ0KDQojIFBlcmZvcm0gUENvQSBvbiBCcmF5LUN1cnRpcyBkaXN0YW5jZSBtYXRyaXggd2l0aCA2IGF4ZXMNCnBjb2FfdGF4YSA8LSBjbWRzY2FsZSh0YXhfYmNfZGlzdG1hdCwgayA9IDYpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyAgQ3JlYXRlIGRhdGFmcmFtZSB3aXRoIGZpcnN0IHR3byBQQ29BIGF4ZXMgZnJvbSB0YXhhDQpwY29hX2RmIDwtIGRhdGEuZnJhbWUoUEMxID0gcGNvYV90YXhhWywgMV0sIFBDMiA9IHBjb2FfdGF4YVssIDJdKQ0KDQojIEFzc2lnbiBmcmVlZG1hbiBjbGFzcyB0byBwY29hX2RmIGJhc2VkIG9uIHJvdyBuYW1lcw0KcGNvYV9kZiRmcmVlZG1hbl9jbGFzcyA8LSBDSDRfeWllbGRfZGZbcm93bmFtZXMocGNvYV9kZiksICJmcmVlZG1hbl9jbGFzcyJdDQoNCiMgQ29udmVydCBDSDQgeWllbGQgY2F0ZWdvcmllcyBlbiBmYWN0b3IgY2xhc3MNCmZyZWVkbWFuX2xldmVscyA8LSBjKCJDMSIsIkMyIiwiQzMiLCJDNCIsIkM1IiwiQzYiKQ0KDQojIENvbnZlcnQgZnJlZWRtYW5fY2xhc3MgYSBmYWN0b3Igd2l0aCA2IGxldmVscw0KcGNvYV9kZiRmcmVlZG1hbl9jbGFzcyA8LSBmYWN0b3IocGNvYV9kZiRmcmVlZG1hbl9jbGFzcywgbGV2ZWxzID0gZnJlZWRtYW5fbGV2ZWxzKQ0KDQojIFJlbW92ZSByb3dzIHdpdGggTkEgdmFsdWVzIGluIGZyZWVkbWFuX2NsYXNzIGNvbHVtbg0KcGNvYV9kZiA8LSBwY29hX2RmWyFpcy5uYShwY29hX2RmJGZyZWVkbWFuX2NsYXNzKSxdDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBDb252ZXJ0IHRoZSB0YXhvbm9taWMgQnJheS1DdXJ0aXMgZGlzdGFuY2UgbWF0cml4IHRvIGEgbWF0cml4DQp0YXhfYmNfZGlzdG1hdF9tYXQgPC0gYXMubWF0cml4KHRheF9iY19kaXN0bWF0KQ0KDQojIFN1YnNldCB0aGUgZGlzdGFuY2UgbWF0cml4IGJhc2VkIG9uIG1hdGNoaW5nIHJvdyBuYW1lcyB3aXRoIHBjb2FfZGYNCnRheF9iY19kaXN0bWF0X2ZpbHQgPC0gdGF4X2JjX2Rpc3RtYXRfbWF0W3Jvdy5uYW1lcyh0YXhfYmNfZGlzdG1hdF9tYXQpICVpbiUgcm93Lm5hbWVzKHBjb2FfZGYpLF0NCg0KIyBQZXJmb3JtIEFOT1NJTSB0ZXN0IHdpdGggOTk5IHBlcm11dGF0aW9ucyBvbiBmaWx0ZXJlZCBkaXN0YW5jZSBtYXRyaXgNCmFub3NpbV9yZXN1bHQgPC0gYW5vc2ltKHRheF9iY19kaXN0bWF0X2ZpbHQsIHBjb2FfZGYkZnJlZWRtYW5fY2xhc3MsIHBlcm0gPSA5OTkpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggZm9ybWF0dGVkIHN0YXRpc3RpY3MgZm9yIFBDb0EgYW5kIEFOT1NJTQ0KcmVzdWx0c19kZiA8LSBkYXRhLmZyYW1lKA0KICBWYXJfUENvQTEgPSBmb3JtYXRDKHZhcihwY29hX2RmJFBDMSksIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJFIiwgZmxhZyA9ICIjIiksDQogIFZhcl9QQ29BMiA9IGZvcm1hdEModmFyKHBjb2FfZGYkUEMyKSwgZGlnaXRzID0gMiwgZm9ybWF0ID0gIkUiLCBmbGFnID0gIiMiKSwNCiAgQU5PU0lNX1IgID0gZm9ybWF0Qyhhbm9zaW1fcmVzdWx0JHN0YXRpc3RpYywgZGlnaXRzID0gMiwgZm9ybWF0ID0gIkUiLCBmbGFnID0gIiMiKSwNCiAgQU5PU0lNX3AgID0gZm9ybWF0Qyhhbm9zaW1fcmVzdWx0JHNpZ25pZiwgZGlnaXRzID0gMiwgZm9ybWF0ID0gIkUiLCBmbGFnID0gIiMiKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgIERpc3BsYXkgdGhlIGRhdGFmcmFtZSBpbiBhbiBpbnRlcmFjdGl2ZSB0YWJsZSBmb3JtYXQNCmRhdGF0YWJsZShyZXN1bHRzX2RmKQ0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQojIFBsb3QgUENvQQ0KcGxvdChwY29hX2RmJFBDMSwgcGNvYV9kZiRQQzIsIHR5cGUgPSAibiIsIG1haW4gPSAiUENvQSAtIEJyYXktQ3VydGlzIC0gc09UVXMiLCANCiAgICAgeGxhYiA9IGV4cHJlc3Npb24oYm9sZCgiQXhpcyAxICg3LjkzJSkiKSksIHlsYWIgPSBleHByZXNzaW9uKGJvbGQoIkF4aXMgMiAoNC4wMyUpIikpKQ0KcG9pbnRzKHBjb2FfZGYkUEMxLCBwY29hX2RmJFBDMiwgcGNoID0gMTksIGNleCA9IDAuNiwgDQogICAgICAgY29sID0gYygiI2NjMzMwMCIsICIjZmY5OTY2IiwgImJsdWUiLCAiI2ZmY2MwMCIsICIjOTljYzMzIiwgIiMzMzk5MDAiKVtwY29hX2RmJGZyZWVkbWFuX2NsYXNzXSkNCmBgYA0KDQo6OjogY2VudGVyLXRleHQNClByaW5jaXBhbCBjb29yZGluYXRlIGFuYWx5c2lzIChQQ29BKSBkZXBpY3RzIG1pY3JvYmlhbCBjb21tdW5pdHkgZHluYW1pY3MgdGhyb3VnaCBtZXRoYW5lIHlpZWxkIGNhdGVnb3JpZXMgKEMxLUM2KSBhdCBzT1RVcyBsZXZlbC4NCjo6Og0KDQojIyBHZW5lcmENCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VFJVRX0NCiMgQ29tcHV0ZSBCcmF5LUN1cnRpcyBkaXN0YW5jZSBtYXRyaXggZnJvbSByYXJlZmllZCBnZW5lcmEgdGFibGUgDQp0YXhfYmNfZGlzdG1hdCA8LSB2ZWdkaXN0KGRmX3JhcmVmX2dlbmVyYSwgbWV0aG9kID0gImJyYXkiKQ0KDQojIFBlcmZvcm0gUENvQSBvbiBCcmF5LUN1cnRpcyBkaXN0YW5jZSBtYXRyaXggd2l0aCA2IGF4ZXMNCnBjb2FfdGF4YSA8LSBjbWRzY2FsZSh0YXhfYmNfZGlzdG1hdCwgayA9IDYpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyAgQ3JlYXRlIGRhdGFmcmFtZSB3aXRoIGZpcnN0IHR3byBQQ29BIGF4ZXMgZnJvbSB0YXhhDQpwY29hX2RmIDwtIGRhdGEuZnJhbWUoUEMxID0gcGNvYV90YXhhWywgMV0sIFBDMiA9IHBjb2FfdGF4YVssIDJdKQ0KDQojIEFzc2lnbiBmcmVlZG1hbiBjbGFzcyB0byBwY29hX2RmIGJhc2VkIG9uIHJvdyBuYW1lcw0KcGNvYV9kZiRmcmVlZG1hbl9jbGFzcyA8LSBDSDRfeWllbGRfZGZbcm93bmFtZXMocGNvYV9kZiksICJmcmVlZG1hbl9jbGFzcyJdDQoNCiMgQ29udmVydCBDSDQgeWllbGQgY2F0ZWdvcmllcyBlbiBmYWN0b3IgY2xhc3MNCmZyZWVkbWFuX2xldmVscyA8LSBjKCJDMSIsIkMyIiwiQzMiLCJDNCIsIkM1IiwiQzYiKQ0KDQojIENvbnZlcnQgZnJlZWRtYW5fY2xhc3MgYSBmYWN0b3Igd2l0aCA2IGxldmVscw0KcGNvYV9kZiRmcmVlZG1hbl9jbGFzcyA8LSBmYWN0b3IocGNvYV9kZiRmcmVlZG1hbl9jbGFzcywgbGV2ZWxzID0gZnJlZWRtYW5fbGV2ZWxzKQ0KDQojIFJlbW92ZSByb3dzIHdpdGggTkEgdmFsdWVzIGluIGZyZWVkbWFuX2NsYXNzIGNvbHVtbg0KcGNvYV9kZiA8LSBwY29hX2RmWyFpcy5uYShwY29hX2RmJGZyZWVkbWFuX2NsYXNzKSxdDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBDb252ZXJ0IHRoZSB0YXhvbm9taWMgQnJheS1DdXJ0aXMgZGlzdGFuY2UgbWF0cml4IHRvIGEgbWF0cml4DQp0YXhfYmNfZGlzdG1hdF9tYXQgPC0gYXMubWF0cml4KHRheF9iY19kaXN0bWF0KQ0KDQojIFN1YnNldCB0aGUgZGlzdGFuY2UgbWF0cml4IGJhc2VkIG9uIG1hdGNoaW5nIHJvdyBuYW1lcyB3aXRoIHBjb2FfZGYNCnRheF9iY19kaXN0bWF0X2ZpbHQgPC0gdGF4X2JjX2Rpc3RtYXRfbWF0W3Jvdy5uYW1lcyh0YXhfYmNfZGlzdG1hdF9tYXQpICVpbiUgcm93Lm5hbWVzKHBjb2FfZGYpLF0NCg0KIyBQZXJmb3JtIEFOT1NJTSB0ZXN0IHdpdGggOTk5IHBlcm11dGF0aW9ucyBvbiBmaWx0ZXJlZCBkaXN0YW5jZSBtYXRyaXgNCmFub3NpbV9yZXN1bHQgPC0gYW5vc2ltKHRheF9iY19kaXN0bWF0X2ZpbHQsIHBjb2FfZGYkZnJlZWRtYW5fY2xhc3MsIHBlcm0gPSA5OTkpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggZm9ybWF0dGVkIHN0YXRpc3RpY3MgZm9yIFBDb0EgYW5kIEFOT1NJTQ0KcmVzdWx0c19kZiA8LSBkYXRhLmZyYW1lKA0KICBWYXJfUENvQTEgPSBmb3JtYXRDKHZhcihwY29hX2RmJFBDMSksIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJFIiwgZmxhZyA9ICIjIiksDQogIFZhcl9QQ29BMiA9IGZvcm1hdEModmFyKHBjb2FfZGYkUEMyKSwgZGlnaXRzID0gMiwgZm9ybWF0ID0gIkUiLCBmbGFnID0gIiMiKSwNCiAgQU5PU0lNX1IgID0gZm9ybWF0Qyhhbm9zaW1fcmVzdWx0JHN0YXRpc3RpYywgZGlnaXRzID0gMiwgZm9ybWF0ID0gIkUiLCBmbGFnID0gIiMiKSwNCiAgQU5PU0lNX3AgID0gZm9ybWF0Qyhhbm9zaW1fcmVzdWx0JHNpZ25pZiwgZGlnaXRzID0gMiwgZm9ybWF0ID0gIkUiLCBmbGFnID0gIiMiKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgIERpc3BsYXkgdGhlIGRhdGFmcmFtZSBpbiBhbiBpbnRlcmFjdGl2ZSB0YWJsZSBmb3JtYXQNCmRhdGF0YWJsZShyZXN1bHRzX2RmKQ0KYGBgDQoNCg0KYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1UUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCiMgUGxvdCBQQ29BDQpwbG90KHBjb2FfZGYkUEMxLCBwY29hX2RmJFBDMiwgdHlwZSA9ICJuIiwgbWFpbiA9ICJQQ29BIC0gQnJheS1DdXJ0aXMgLSBHZW5lcmEiLCANCiAgICAgeGxhYiA9IGV4cHJlc3Npb24oYm9sZCgiQXhpcyAxICgzLjU3JSkiKSksIHlsYWIgPSBleHByZXNzaW9uKGJvbGQoIkF4aXMgMiAoMy4xMyUpIikpKQ0KcG9pbnRzKHBjb2FfZGYkUEMxLCBwY29hX2RmJFBDMiwgcGNoID0gMTksIGNleCA9IDAuNiwgDQogICAgICAgY29sID0gYygiI2NjMzMwMCIsICIjZmY5OTY2IiwgImJsdWUiLCAiI2ZmY2MwMCIsICIjOTljYzMzIiwgIiMzMzk5MDAiKVtwY29hX2RmJGZyZWVkbWFuX2NsYXNzXSkNCmBgYA0KDQo6OjogY2VudGVyLXRleHQNClByaW5jaXBhbCBjb29yZGluYXRlIGFuYWx5c2lzIChQQ29BKSBkZXBpY3RzIG1pY3JvYmlhbCBjb21tdW5pdHkgZHluYW1pY3MgdGhyb3VnaCBtZXRoYW5lIHlpZWxkIGNhdGVnb3JpZXMgKEMxLUM2KSBhdCBnZW51cyBsZXZlbC4NCjo6Og0KDQoNCg0KYGBgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDJNTVMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKC4uKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9PX18oIHUgKV9fMF8NCmBgYA0K