##################
# LOAD LIBRARIES #
##################
suppressWarnings({suppressMessages({suppressPackageStartupMessages({
library(tidyverse)
library(edgeR)
library(openxlsx)
library(readxl)
library(rstatix)
#remotes::install_github("czarnewski/niceRplots",force=T)
library(niceRplots)
}) }) })
#########
# PATHS #
#########
result_dir <- "./Suppl.Tbl/"
if( isFALSE(dir.exists(result_dir)) ) { dir.create(result_dir,recursive = TRUE) }
prot_url <- "https://doi.org/10.1371/journal.ppat.1010494.s017"
#cyt_url <- ""
#meta_url <- ""
############
# DOWNLOAD #
############
if(isFALSE(file.exists("../../data/Protein_norm_MFI.xlsx"))){download.file(prot_url, paste0("../../data/", "Protein_norm_MFI.xlsx"), method="auto")}
#if(isFALSE(file.exists("../../data/Cytokine_data.xlsx"))){download.file(cyt_url, paste0("../../data/", "Cytokine_data.xlsx"), method="auto")}
#if(isFALSE(file.exists("../../data/metadata.xlsx"))){download.file(meta_url, paste0("../../data/", "metadata.xlsx"), method="auto")}
#############
# LODA DATA #
#############
# datasets_all_samples <- readRDS("../../results/03_normalize_data_output/datasets_all_samples.RDS")
Protein_V3 <- read_xlsx("../../data/Protein_norm_MFI.xlsx", skip = 2) %>% rename(ID="Patient/Sample ID")
# cytokine_data <- read.csv("../../data/210125_Cytokines_visit3CVL.csv")
metadata <- read.csv("../../data/metadata.csv",row.names = 1, stringsAsFactors = F)
cytokine_data <- read_xlsx(paste0("/Users/vilkal/work/Brolidens_work/Projects/broliden_5325/data/", "Cytokine_data.xlsx"), na = "NA", sheet = "Cytokine_data")
#################
# COLOR PALETTS #
#################
pal <- c( "#0072B2", "#009E73","#D55E00", "#CC79A7", "#E69F00", "#999999")
taxa_pal <- c(RColorBrewer::brewer.pal(8,"Pastel2"),RColorBrewer::brewer.pal(8,"Pastel1"),"grey90")
cytokine_data <- cytokine_data %>%
column_to_rownames(var = "ID") %>%
as.matrix()
cytokine_data <- t(cytokine_data)
cytokine_data[is.na(cytokine_data)] <- 0.01
cytokine_data <- log2(cytokine_data+1)
cytokine_data_log <- cytokine_data
cyto2 <- as.data.frame(t(cytokine_data))
cyto2$ID<-row.names(cyto2)
#select data and re-format to long format
cytogr.long <- metadata %>%
select(ID, Luminal_gr, Tissue_gr) %>%
left_join(.,cyto2, by="ID") %>%
pivot_longer(c(-Luminal_gr, -Tissue_gr, -ID), names_to = "Cytokines", values_to = "value")
test.krusk_dunn.fun <- function(df, var, group) {
var <- enquo(var)
stat.test.krusk <- df %>%
group_by(!!(var)) %>%
kruskal_test(., as.formula(paste("value", "~", group))) %>%
adjust_pvalue(method = "BH") %>%
select(-.y., -n, -df) %>%
arrange(p) %>%
rename(p.value = "p") %>%
add_significance()
# select the significant proteins from kruskal
sig <- stat.test.krusk %>% filter(p.adj<0.05) %>% pull(!!var)
### Post hoc test
stat.test.dunn <- df %>%
filter(!!var %in% sig) %>%
group_by(!!var) %>%
dunn_test(., as.formula(paste("value", "~", group))) %>%
#dunn_test(value ~ !!group) %>%
select(-.y.) %>%
arrange(p) %>%
rename(p.value = "p") %>%
filter(p.adj<0.05)
sig2 <- stat.test.dunn[stat.test.dunn$p.adj<0.05,]
l <- list(stat.test.krusk, stat.test.dunn)
n <- c("Kruskal", "Dunn's") %>% paste0(., "_", group, sep = "")
l <- set_names(l, n)
return(l)
}
n <- c("Luminal_gr", "Tissue_gr") %>% set_names(c("Luminal", "Tissue"))
stat <- imap(n, ~test.krusk_dunn.fun(cytogr.long, Cytokines, .x))
s <- flatten(stat)
names <- c("15 Luminal", "16 Tissue") %>% set_names()
# save TopTables pairwise
l_top_p <- list(pairwise_dpe_L$top, pairwise_dge_T$top) %>% set_names(names)
# save TopTables across + cytokines
l_top_a <- list( list(Across = dpe_L$top), list(Across = dpe_T$top)) %>% set_names(names)
l <- list(l_top_a, stat, l_top_p)
p_list <- imap(names, ~flatten(map_depth(l, 1, .x)))
imap(p_list, ~write.xlsx(.x,file=paste0(result_dir,"Suppl.Tbl.",.y,"_Proteins.xlsx"))) # Excel
write.xlsx(list("L2T2 vs L2T3"=dpe_LT$top),file=paste0(result_dir,"Suppl.Tbl.17"," L2T2_L2T3_Proteins.xlsx"))
# dev.new(height=10, width=6.6929133858, noRStudioGD = TRUE)
figlabels <- letters
####################################
# TOP DIFF. EXPRESSED PROT HEATMAP #
####################################
### A
# Luminal groups
t <- top_dpe.fun(dpe_L$top)
plot_heatmap.fun(t, "Luminal_gr", scale = T, layout = "multi")
### C
# Tissue groups
t <- top_dpe.fun(dpe_T$top)
par(mfg = c(2,1)) # adds the remaning plots to the previous layout
plot_heatmap.fun(t, "Tissue_gr", scale = T)
##############################
# SIG. CYTOKINES VIOLIN PLOT #
##############################
### B
# Luminal groups
g <- c("MIG", "IL1b", "IL12_p70", "MCP1", "IL1a", "IP10")
#g <- c("MIG", "IL12_p70","IL1a", "IP10", "IL1b", "MCP1" )
lab <- c("MIG", "IL-1\u03b2", "IL-12-p70", "MCP-1", "IL-1\u03b1", "IP-10" )
#lab <- c("IP-10", "IL-1\u03b2", "IL-12-p70", "MCP-1","IL-1\u03b1", "MIG")
Luminal <- sig_stars.fun(s$Kruskal_Luminal_gr, s$`Dunn's_Luminal_gr`, "Luminal_gr", order = g[1:4])
rownames(Luminal$sig_df) <- lab
stars <- Luminal$stars_df
par( mar=c(1.4,5,1.5,2)) #b,l,t,r
violist(data=Luminal$sig_df,
srt=45, y_padding = 2, smooth = .2,
genes= lab[1:4],
#cex.axis = 1.1,
#add_ylims = T, #gives starting value of y-axis and max value of all data points
col = pal, transparency = 50,
clustering=c(Luminal$groupings))
segments(x0 = stars$line_x0, x1 = stars$line_x1, y0 = stars$y_, y1 = stars$y_)
text( stars$x , stars$y_+.05,
labels = stars$p.adj.signif, srt = 0, xpd = TRUE, cex=1)
title(main = "Luminal gr. Cytokines", line = 0.7, cex.main = 1.1)
add_letter("b")
Luminal <- sig_stars.fun(s$Kruskal_Luminal_gr, s$`Dunn's_Luminal_gr`, "Luminal_gr", order = g[5:6])
rownames(Luminal$sig_df) <- lab
stars <- Luminal$stars_df
par(mar=c(1.4,5,1.5,2) ) #b,l,t,r
violist(data=Luminal$sig_df,
srt=45, y_padding = 2, smooth = .2,
genes= lab[5:6],
#add_ylims = T, #gives starting value of y-axis and max value of all data points
col = pal, transparency = 50,
clustering=c(Luminal$groupings))
segments(x0 = stars$line_x0, x1 = stars$line_x1, y0 = stars$y_, y1 = stars$y_)
text( stars$x , stars$y_+.05,
labels = stars$p.adj.signif, srt = 0, xpd = TRUE, cex=1)
title(main = "Luminal gr. Cytokines", line = 0.7, cex.main = 1.1)
### D
# Tissue groups
lab <- c("IL-1\u03b1", "IP-10")
Tissue <- sig_stars.fun(s$Kruskal_Tissue_gr, s$`Dunn's_Tissue_gr`, "Tissue_gr")
rownames(Tissue$sig_df) <- lab
stars <- Tissue$stars_df
#par(mar=c(20.4,6,1.5,3)) #b,l,t,r # ps = 20, point size
par(mar=c(1,5,1.5,5)) #b,l,t,r
violist(data=Tissue$sig_df,
srt=45, y_padding = 2, smooth = .2,
genes= rownames(Tissue$sig_df),
col = pal, transparency = 50,
# add_ylims = T,
clustering=Tissue$groupings )
segments(x0 = stars$line_x0, x1 = stars$line_x1, y0 = stars$y_, y1 = stars$y_)
text( stars$x , stars$y_+.05,
labels = stars$p.adj.signif, srt = 0, xpd = TRUE, cex=1)
title(main = "Tissue gr. Cytokines", line = 0.7, cex.main = 1.1)
add_letter("d")

Figure 6. Characterization of the host protein profile as
stratified by the luminal and tissue-adherent microbiome study
groups. All study samples were assessed for significant
differences in protein levels across the study groups.
a,b The five luminal study groups and
c,d the five corresponding tissue
groups. a, c Proteins with a p-value > 0.05 were omitted from the
heatmap. Proteins with significantly different levels across the groups
were clustered by hierarchical agglomerative clustering using inverse
Pearson’s correlation as distance measure and Ward’s method (“ward. D2”)
for linkage. Color-coded rows below the heatmaps show clinical diagnosis
of bacterial vaginosis (BV, binned Nugent’s scores) and HIV diagnosis,
respectively. Color coding for BV: Gray: negative, orange: intermediate,
red: positive; and for HIV: Gray: HIV seronegative, red: HIV
seropositive. b, d Violin plots of log2 transformed cytokine levels
across the luminal and tissue study groups (as indicated on the x-axis),
respectively. The asterisk and lines indicate statistically significant
results of Dunn’s test with Benjamini Hochberg’s correction analysis.
Adjusted p-values: * < 0.05, ** < 0.01, *** < 0.001, **** <
0.0001
LS0tCnRpdGxlOiAiRmlndXJlIDYuIERpZmZlcmVudGlhbCBQcm90ZWluIGV4cHJlc3Npb24iCmdlb21ldHJ5OiAibGVmdD0yY20scmlnaHQ9MmNtLHRvcD0yY20sYm90dG9tPTJjbSIKaGVhZGVyLWluY2x1ZGVzOiAKLSBcdXNlcGFja2FnZXtmbG9hdH0KZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCmtuaXQ6IChmdW5jdGlvbihpbnB1dEZpbGUsIG91dF9kaXIsIC4uLikgewogICAgc291cmNlKCIuLi8uLi9jb2RlL2tuaXRfZnVuY3Rpb24uUiIpOwogICAgY3VzdG9tX2tuaXQoaW5wdXRGaWxlLCAiLi4vLi4vbGFiX2Jvb2svRmlndXJlNi8iLCAuLi4pCiAgICB9KQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgcmVzdWx0cyAgICA9ICJob2xkIiwKICBtZXNzYWdlICAgID0gRkFMU0UsCiAgd2FybmluZyAgICA9IEZBTFNFLAogIGZpZy53aWR0aCAgPSA2LjY5MjkxMzM4NTgsCiAgZmlnLmFsaWduICA9ICJjZW50ZXIiLAogIGZpZy5wYXRoICAgPSAiLi9GaWd1cmVzLyIsCiAgZmlnLnByb2Nlc3MgPSBmdW5jdGlvbihmaWxlbmFtZSl7CiAgICBuZXdfZmlsZW5hbWUgPC0gc3RyaW5ncjo6c3RyX3JlbW92ZShzdHJpbmcgPSBmaWxlbmFtZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIi0xIikKICAgIGZzOjpmaWxlX21vdmUocGF0aCA9IGZpbGVuYW1lLCBuZXdfcGF0aCA9IG5ld19maWxlbmFtZSkKICAgIGlmZWxzZShmczo6ZmlsZV9leGlzdHMobmV3X2ZpbGVuYW1lKSwgbmV3X2ZpbGVuYW1lLCBmaWxlbmFtZSkKfSkKIyBzZXR3ZCgiL1VzZXJzL3ZpbGthbC93b3JrL0Jyb2xpZGVuc193b3JrL1Byb2plY3RzL2Jyb2xpZGVuXzUzMjUvcmVwb3J0cy9tYW51c2NyaXB0IikKYGBgCgpgYGB7ciBMb2FkLWRhdGEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIyMjIyMjIyMjIyMjIyMjIwojIExPQUQgTElCUkFSSUVTICMKIyMjIyMjIyMjIyMjIyMjIyMjCnN1cHByZXNzV2FybmluZ3Moe3N1cHByZXNzTWVzc2FnZXMoe3N1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyh7CiAgbGlicmFyeSh0aWR5dmVyc2UpCiAgbGlicmFyeShlZGdlUikKICBsaWJyYXJ5KG9wZW54bHN4KQogIGxpYnJhcnkocmVhZHhsKQogIGxpYnJhcnkocnN0YXRpeCkKICAjcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoImN6YXJuZXdza2kvbmljZVJwbG90cyIsZm9yY2U9VCkKICBsaWJyYXJ5KG5pY2VScGxvdHMpCn0pICB9KSAgfSkKCiMjIyMjIyMjIwojIFBBVEhTICMKIyMjIyMjIyMjCnJlc3VsdF9kaXIgPC0gIi4vU3VwcGwuVGJsLyIKaWYoIGlzRkFMU0UoZGlyLmV4aXN0cyhyZXN1bHRfZGlyKSkgKSB7IGRpci5jcmVhdGUocmVzdWx0X2RpcixyZWN1cnNpdmUgPSBUUlVFKSB9Cgpwcm90X3VybCA8LSAiaHR0cHM6Ly9kb2kub3JnLzEwLjEzNzEvam91cm5hbC5wcGF0LjEwMTA0OTQuczAxNyIKI2N5dF91cmwgPC0gIiIKI21ldGFfdXJsIDwtICIiCgojIyMjIyMjIyMjIyMKIyBET1dOTE9BRCAjCiMjIyMjIyMjIyMjIwppZihpc0ZBTFNFKGZpbGUuZXhpc3RzKCIuLi8uLi9kYXRhL1Byb3RlaW5fbm9ybV9NRkkueGxzeCIpKSl7ZG93bmxvYWQuZmlsZShwcm90X3VybCwgcGFzdGUwKCIuLi8uLi9kYXRhLyIsICJQcm90ZWluX25vcm1fTUZJLnhsc3giKSwgbWV0aG9kPSJhdXRvIil9CiNpZihpc0ZBTFNFKGZpbGUuZXhpc3RzKCIuLi8uLi9kYXRhL0N5dG9raW5lX2RhdGEueGxzeCIpKSl7ZG93bmxvYWQuZmlsZShjeXRfdXJsLCBwYXN0ZTAoIi4uLy4uL2RhdGEvIiwgIkN5dG9raW5lX2RhdGEueGxzeCIpLCBtZXRob2Q9ImF1dG8iKX0KI2lmKGlzRkFMU0UoZmlsZS5leGlzdHMoIi4uLy4uL2RhdGEvbWV0YWRhdGEueGxzeCIpKSl7ZG93bmxvYWQuZmlsZShtZXRhX3VybCwgcGFzdGUwKCIuLi8uLi9kYXRhLyIsICJtZXRhZGF0YS54bHN4IiksIG1ldGhvZD0iYXV0byIpfQoKIyMjIyMjIyMjIyMjIwojIExPREEgREFUQSAjCiMjIyMjIyMjIyMjIyMKIyBkYXRhc2V0c19hbGxfc2FtcGxlcyA8LSByZWFkUkRTKCIuLi8uLi9yZXN1bHRzLzAzX25vcm1hbGl6ZV9kYXRhX291dHB1dC9kYXRhc2V0c19hbGxfc2FtcGxlcy5SRFMiKQpQcm90ZWluX1YzIDwtIHJlYWRfeGxzeCgiLi4vLi4vZGF0YS9Qcm90ZWluX25vcm1fTUZJLnhsc3giLCBza2lwID0gMikgJT4lIHJlbmFtZShJRD0iUGF0aWVudC9TYW1wbGUgSUQiKQojIGN5dG9raW5lX2RhdGEgPC0gcmVhZC5jc3YoIi4uLy4uL2RhdGEvMjEwMTI1X0N5dG9raW5lc192aXNpdDNDVkwuY3N2IikKbWV0YWRhdGEgPC0gcmVhZC5jc3YoIi4uLy4uL2RhdGEvbWV0YWRhdGEuY3N2Iixyb3cubmFtZXMgPSAxLCBzdHJpbmdzQXNGYWN0b3JzID0gRikKCmN5dG9raW5lX2RhdGEgPC0gcmVhZF94bHN4KHBhc3RlMCgiL1VzZXJzL3ZpbGthbC93b3JrL0Jyb2xpZGVuc193b3JrL1Byb2plY3RzL2Jyb2xpZGVuXzUzMjUvZGF0YS8iLCAiQ3l0b2tpbmVfZGF0YS54bHN4IiksIG5hID0gIk5BIiwgc2hlZXQgPSAiQ3l0b2tpbmVfZGF0YSIpIAojIyMjIyMjIyMjIyMjIyMjIwojIENPTE9SIFBBTEVUVFMgIwojIyMjIyMjIyMjIyMjIyMjIwpwYWwgPC0gYyggIiMwMDcyQjIiLCAiIzAwOUU3MyIsIiNENTVFMDAiLCAiI0NDNzlBNyIsICIjRTY5RjAwIiwgIiM5OTk5OTkiKQp0YXhhX3BhbCA8LSBjKFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbCg4LCJQYXN0ZWwyIiksUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDgsIlBhc3RlbDEiKSwiZ3JleTkwIikKYGBgCgpgYGB7ciBEUEUtRnVuY3Rpb25zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIERFRydzIEZVTkNUSU9OIEFDUk9TUyBHUk9VUFMgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojZ3JvdXAgPC0gIlRpc3N1ZV9nciIKI2dyb3VwIDwtICJMdW1pbmFsX2dyIgojZ3JvdXAgPC0gIkxfVF9ncm91cHMiCmxpbW1hX2RwZS5mdW4gPC0gZnVuY3Rpb24oZ3JvdXAsIGNvbmZvdW5kKSB7CiAgZ3JvdXBzIDwtIG1ldGFkYXRhW3NhbXBsZV91c2UsIGdyb3VwXQogIG5fZ3IgPC0gbGVuZ3RoKG5hLm9taXQodW5pcXVlKGdyb3VwcykpKQogIAogIGlmKGFueShpcy5uYShncm91cHMpKSkgewogICAgZ3JvdXBzIDwtIHJlcGxhY2VfbmEoZ3JvdXBzLCAiWCIpCiAgfQogIAogIGlmKGNvbmZvdW5kPT1GQUxTRSkgewogICAgYyA8LSAiX25vX2NvbmYiCiAgICBkZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gIGdyb3VwcywgZGF0YT1tZXRhZGF0YVtzYW1wbGVfdXNlLF0pIH0gIyB3aXRob3V0IGNvbmZvdW5kZXJzCiAgZWxzZXsKICAgIGMgPC0gIl9jb25mIgogICAgIyBkZXNpZ24gPC0gbW9kZWwubWF0cml4KH5ncm91cHMrSElWc3RhdHVzK0NvbnRyYWNlcHRpb24rYWdlK3NleHdvcmtfbW9udGhzLAogICAgIyAgICAgICAgICAgICAgICAgICAgICBkYXRhPW1ldGFkYXRhW3NhbXBsZV91c2UsXSkKICAgIGRlc2lnbiA8LSBtb2RlbC5tYXRyaXgofiBncm91cHMrQ29udHJhY2VwdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9bWV0YWRhdGFbc2FtcGxlX3VzZSxdKQogIH0KICAjZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+MCArIGdyb3VwcytDb250cmFjZXB0aW9uK0hJVnN0YXR1cythZ2Urc2V4d29ya19tb250aHMsIAogICAgICAgICAgICAgICAgICAgICAgICAgI2RhdGE9bWV0YWRhdGFbc2FtcGxlX3VzZSxdKSAjIHdpdGhvdXQgaW50ZXJjZXB0CiAgCiAgY29sbmFtZXMoZGVzaWduKSA8LSBzdWIoImdyb3VwcyIsIiIsY29sbmFtZXMoZGVzaWduKSkKICBjb2xuYW1lcyhkZXNpZ24pIDwtIHN1YigiXFwoSW50ZXJjZXB0XFwpIiwiSW50ZXJjZXB0Iixjb2xuYW1lcyhkZXNpZ24pKQogIGNvbG5hbWVzKGRlc2lnbikgPC0gc3ViKCIgIiwiXyIsY29sbmFtZXMoZGVzaWduKSkKICAKICB5IDwtIFByb3RlaW5bLHNhbXBsZV91c2VdCiAgZml0IDwtIGxtRml0KHksIGRlc2lnbikKICBmaXQyIDwtIGNvbnRyYXN0cy5maXQoZml0LCBjb2VmZmljaWVudHM9MjpuX2dyKQogIGVmaXQgPC0gZUJheWVzKGZpdDIpCiAgCiAgIyBEUEUgYWNyb3NzIGFsbCBncm91cHMKICB0b3AgPC0gdG9wVGFibGUoZWZpdCwgYWRqdXN0Lm1ldGhvZCA9ICJCSCIsbnVtYmVyID0gImFsbCIpICMgQU5PVkEKICB0b3AgPC0gY2JpbmQoTG9nRkMuaW50ZXJjZXB0PTAsdG9wKSAjIHdpdGggaW50ZXJjZXB0CiAgdG9wIDwtICByb3duYW1lc190b19jb2x1bW4odG9wLCB2YXIgPSAiQW50aWJvZHkiKQogIApyZXR1cm4obGlzdChkZXNpZ249ZGVzaWduLCB5PXksIGZpdD1maXQsIGVmaXQ9ZWZpdCwgdG9wPXRvcCwgYz1jKSkKfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgREVHJ3MgRlVOQ1RJT04gUEFJUldJU0UgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKcGFpcndpc2VfZHBlLmZ1biA8LSBmdW5jdGlvbihncm91cCwgZml0LCBkZXNpZ24pIHsKICBncm91cHMgPC0gbWV0YWRhdGFbc2FtcGxlX3VzZSwgZ3JvdXBdCiAgbGV2ZWxzIDwtIGFzLmNoYXJhY3Rlcihzb3J0KHVuaXF1ZShncm91cHMpKSkKICAKICAjIHdpdGhvdXQgaW50ZXJjZXB0OgogIG4gPC0gY29tYm4obGV2ZWxzLDIpIAogIGcgPC0gbWFwX2NocihzZXFfYWxvbmcoMTpuY29sKG4pKSwgfnBhc3RlKG5bMSwueF0sIG5bMiwueF0sIHNlcCA9ICItIikpCiAgcyA8LSBzZXFfYWxvbmcoMTpuY29sKG4pKSAlPiUgc2V0X25hbWVzKGcpCiAgI25hbWUgPC0gbWFwX2NocihzZXFfYWxvbmcoMTpuY29sKG4pKSwgfnBhc3RlKHN0cl9leHRyYWN0KG5bMSwueF0sICJeZy4iKSwgc3RyX2V4dHJhY3QoblsyLC54XSwgIl5nLiIpLCBzZXAgPSAiXyIpKQogIAogICMgd2l0aCBpbnRlcmNlcHQ6CiAgZyA8LSBzdWIocGFzdGUwKCJeKCIsbGV2ZWxzWzFdLCAiKS0oLiopIiksICctXFwyJywgZykKICAKICBDT05UUkFTVFMgPC0gbWFrZUNvbnRyYXN0cyggY29udHJhc3RzPWcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGRlc2lnbiApCiAgCiAgCiAgIyBEUEUgcGFpcndpc2UgY29tcGFyaXNvbgogIGZpdDIgPC0gY29udHJhc3RzLmZpdChmaXQsIENPTlRSQVNUUykKICBlZml0IDwtIGVCYXllcyhmaXQyKQogIHRvcCA8LSBtYXAocywgfiB0b3BUYWJsZShlZml0LCBjb2VmPS54LCBhZGp1c3QubWV0aG9kID0gIkJIIixudW1iZXIgPSAiYWxsIixzb3J0LmJ5ID0gIlAiKSkgJT4lCiAgICBtYXAoLiwgfnJvd25hbWVzX3RvX2NvbHVtbigueCwgdmFyID0gIkFudGlib2R5IikpCiAgCiAgcmVzdWx0cyA8LSBkZWNpZGVUZXN0cyhmaXQyLCBtZXRob2Q9InNlcGFyYXRlIiwgcC52YWx1ZSA9IDAuMDUpCiAgc3VtbWFyeSA8LSByb3duYW1lc190b19jb2x1bW4oYXMuZGF0YS5mcmFtZS5hcnJheShzdW1tYXJ5KHJlc3VsdHMpKSwgdmFyPSJGRFI8MC4wNSIpCiAgdG9wIDwtIGMoc3VtbWFyeSA9IGxpc3Qoc3VtbWFyeSksIHRvcCkKICAKICAjc2F2ZVJEUyh0b3AsIGZpbGUgPSAiLi9Ub3BUYWJsZV9hbGxfZ3JvdXBzXzA2LjA0LjIwMjEuUkRTIikKICAjc2F2ZVJEUyh0b3AsIGZpbGUgPSAiLi9Ub3BUYWJsZV9Nb2RpZmllZE00X3BhaXJ3aXNlXzE3LjA1LjIwMjEuUkRTIikKcmV0dXJuKGxpc3QoZWZpdD1lZml0LCB0b3A9dG9wLCBDT05UUkFTVFM9Q09OVFJBU1RTKSkKfQoKCgpgYGAKCmBgYHtyIGZvcm1hdC1kYXRhLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp0b19yZW1vdmUgPC0gYygiQ1NUQl9IUEEwMTczODAiLCJTUElOSzVfSFBBMDA5MDY3IiwiU1BSUjNfSFBBMDI0MzMwIiwiRkdBX0hQQTA2NDc1NSIsIlMxMDBBMTJfSFBBMDAyODgxIiwiS1JUMV9IUEEwMTk3OTciLCJLUlQxX0hQQTA2MjkwOCIsIkxHTU5fSFBBMDAxNDI2IiwiVEFDU1REMl9IUEEwNDMxMDQiLCJGTE5BX0hQQTAwMTExNSIsIkdQWDNfSFBBMDcxNTIwIiwiQ1NUQV9IUEEwMDEwMzEiLCJTRVJQSU5CNV9IUEEwMTkxMzIiLCJJVElIMl9IUEEwNTkxNTAiLCJOQ0YyX0hQQTAwMjMyNyIsIkFOWEEzX0hQQTAxMzQzMSIpCgpQcm90ZWluIDwtIFByb3RlaW5fVjMgJT4lCiAgc2VsZWN0KElELCBjb250YWlucygiSFBBIikpICU+JQogIGZpbHRlcihJRCAlaW4lIG1ldGFkYXRhJElEKSAlPiUKICBwaXZvdF9sb25nZXIoLiwgLUlELCBuYW1lc190byA9ICJBbnRpYm9keSIpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAiSUQiLCB2YWx1ZXNfZnJvbSA9ICJ2YWx1ZSIgKSAlPiUKICBmaWx0ZXIoIShBbnRpYm9keSAlaW4lIHRvX3JlbW92ZSkpICU+JQogIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAiQW50aWJvZHkiKSAKCmBgYAoKYGBge3IgQWNyb3NzLWFuZC1QYWlyd2lzZS10YWJsZXMsIGluY2x1ZGU9RkFMU0V9CiMgU2FtcGxlcyB0byB1c2UKIyBUUlggPC0gZGF0YXNldHNfYWxsX3NhbXBsZXNbWyJUaXNzdWVfUk5Bc2VxX1YzX25vcm1hbGl6ZWQiXV0KIyBzYW1wbGVfdXNlIDwtIGludGVyc2VjdChtZXRhZGF0YSRJRCwgY29sbmFtZXMoVFJYKVtjb2xTdW1zKFRSWCkhPTBdKQpzYW1wbGVfdXNlIDwtIG1ldGFkYXRhJElECnNhbXBsZV91c2UgPC0gaW50ZXJzZWN0KGNvbG5hbWVzKFByb3RlaW4pLCBzYW1wbGVfdXNlKQoKIyBBY3Jvc3MgZ3JvdXBzIERQRQpkcGVfTCA8LSBsaW1tYV9kcGUuZnVuKCJMdW1pbmFsX2dyIiwgY29uZm91bmQ9VCkKZHBlX1QgPC0gbGltbWFfZHBlLmZ1bigiVGlzc3VlX2dyIiwgY29uZm91bmQ9VCkKCiMgTDIgdG8gVDIvVDMKbWV0YWRhdGEgPC0gbWV0YWRhdGEgJT4lIAogIG11dGF0ZShMX1RfZ3JvdXBzID0gcGFzdGUwKC4kTHVtaW5hbF9nciwgLiRUaXNzdWVfZ3IpKSAlPiUKICBtdXRhdGUoTF9UX2dyb3VwcyA9IGlmZWxzZShncmVwbCgiTDJUMnxMMlQzIiwgLiRMX1RfZ3JvdXBzKSwgLiRMX1RfZ3JvdXBzLCBOQSkpCgpkcGVfTFQgPC0gbGltbWFfZHBlLmZ1bigiTF9UX2dyb3VwcyIsIGNvbmZvdW5kPVQpCgoKIyBQYWlyd2lzZSBEUEUncwpwYWlyd2lzZV9kcGVfTCA8LSBwYWlyd2lzZV9kcGUuZnVuKCJMdW1pbmFsX2dyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpdD1kcGVfTCRmaXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ249ZHBlX0wkZGVzaWduICkKcGFpcndpc2VfZGdlX1QgPC0gcGFpcndpc2VfZHBlLmZ1bigiVGlzc3VlX2dyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXQ9ZHBlX1QkZml0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbj1kcGVfVCRkZXNpZ24pCgpgYGAKCmBgYHtyIGhlYXRtYXAtZnVuY3Rpb25zLCBlY2hvPUZBTFNFfQp0b3BfZHBlLmZ1biA8LSBmdW5jdGlvbih0b3ApewogIHBfdmFsIDwtIHB1bGwodG9wLCAiUC5WYWx1ZSIpCiAgdG9wX2RwZSA8LSAocF92YWwgPCAwLjA1KSAjJiAocm93U3VtcyggYWJzKHRvcFssZ3JlcCgibG9nRkMiLGNvbG5hbWVzKHRvcCkpXSkgPj0gbG9nMigxLjUpICkgPj0gMSkKICB0b3BfZHBlIDwtIHRvcCRBbnRpYm9keVsgdG9wX2RwZSBdCiAgCiAgdG9wX1BST1RfbWZpIDwtIFByb3RlaW5bdG9wX2RwZSwgc2FtcGxlX3VzZV0KICAKICByZXR1cm4odG9wX1BST1RfbWZpKQp9CgojIHRvcF9QUk9UX21maSA8LSB0CiMgc2FjYWxlID0gVAojIGdyIDwtICJMdW1pbmFsX2dyIgojIHBsb3RfaGVhdG1hcC5mdW4odCwgIkx1bWluYWxfZ3IiLCBzY2FsZSA9IFQpCnBsb3RfaGVhdG1hcC5mdW4gPC0gZnVuY3Rpb24odG9wX1BST1RfbWZpLCBnciwgc2NhbGUgPSBGQUxTRSwgbGF5b3V0ID0gIm5vbmUiKXsKICBkZiA8LSBuYS5vbWl0KG1ldGFkYXRhW3NhbXBsZV91c2UsIGMoZ3IsICJJRCIpXSkKICBkZiA8LSBhcnJhbmdlKGRmLCBkZlsxXSkKICBzYW1wbGVzIDwtIGRmWywgIklEIl0KICBuYW1lcyhzYW1wbGVzKSA8LSBkZlssIGdyXQogIAogIGlmKHNjYWxlID09IFRSVUUpIHsKICAgIG4gPC0gY29sbmFtZXModG9wX1BST1RfbWZpKQogICAgdG9wX1BST1RfbWZpIDwtIHQoYXBwbHkodG9wX1BST1RfbWZpLDEsZnVuY3Rpb24oeCl7c2NhbGUoeCxULFQpfSkpCiAgICBjb2xuYW1lcyh0b3BfUFJPVF9tZmkpIDwtIG4KICAgIGJyZWFrcyA9IHNlcSgtNSw1LGxlbmd0aC5vdXQgPSAxMDApCiAgfWVsc2V7YnJlYWtzID0gc2VxKDAsNSxsZW5ndGgub3V0ID0gMTAwKX0KICAKICBoIDwtIGhjbHVzdCggYXMuZGlzdCggKDEtIGNvcih0KHRvcF9QUk9UX21maSkpKS8yICksIG1ldGhvZCA9ICJ3YXJkLkQyIikKCiAgaWYobGF5b3V0ID09ICJtdWx0aSIpIHsKICAgIGxheW91dChtYXRyaXgoYygxLDIsNSw2LAogICAgICAgICAgICAgICAgICAgIDcsNyw4LDgsCiAgICAgICAgICAgICAgICAgICAgNyw3LDksOSwKICAgICAgICAgICAgICAgICAgICAzLDMsNCw0KSwKICAgICAgICAgICBucm93ID0gNCwgbmNvbCA9IDQsYnlyb3cgPSBUKSwKICAgICAgICAgICB3aWR0aHMgPSBjKDEsMiwuOCwyKSwgaGVpZ2h0cyA9IGMoMSwuMzUsLjM1LC4wMSkgKQogICAgIyBsYXlvdXQuc2hvdyg5KQogICAgfQogIGlmKGxheW91dCA9PSAic2luZ2xlIikgewogICAgbGF5b3V0KG1hdHJpeChjKDEsMiksCiAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDEsIG5jb2wgPSAyLGJ5cm93ID0gVCksd2lkdGhzID0gYygxLDIpICkgfQogIAogICAgIyMgRGVuZG9ncmFtCiAgICBwYXIobWdwPWMoMCwwLjIsMCksIG1hcj1jKDQsLjYsMi41LC4yKSkgIyhib3R0b20sIGxlZnQsIHRvcCwgcmlnaHQpIAogICAgcGxvdCggcmV2KGFzLmRlbmRyb2dyYW0oaCkpICwgeGxpbT1jKG1heChoJGhlaWdodCksLS4wMSksCiAgICAgICAgICBob3JpeiA9IFQsIGxlYWZsYWIgPSAibm9uZSIseGF4cz0iaSIseWF4cz0iaSIsYXhlcz1ULCBjZXguYXhpcyA9IC44ICkKICAgICN0aXRsZSh4bGFiPSJoZWlnaHQiLCBsaW5lPTMpCiAgICBtdGV4dCggYygiSGVpZ2h0IiksIHNpZGU9MSwgbGFzID0gMSwgY2V4ID0gLjcsIGxpbmUgPTEseHBkPVQpCiAgICAKICAgIGlmKGdyID09ICJUaXNzdWVfZ3IiKSB7CiAgICAgIGhlaWdodCA8LTEuNSAKICAgICAgYWRkX2xldHRlcigiYyIpCiAgICB9ZWxzZXsKICAgICAgIyBhZGRfc2NhbGVfbGVnZW5kKHggPSBwYXIoInVzciIpWzFdLTAuMSwgaGVpZ2h0ID0gMS41LCNkaWZmKHBhcigidXNyIilbMzo0XSktMjAsCiAgICAgICMgICAgICAgICAgICAgICAgcGFsID0gY29sb3JSYW1wUGFsZXR0ZShjKCJuYXZ5IiwiZ3JleTk1IiwiZmlyZWJyaWNrIikpKDkxKSwKICAgICAgIyAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCItNSIsIjAiLCI1IikpCiAgICAgICMgaGVpZ2h0IDwtIHJvdW5kKG1heChoJGhlaWdodCkpCiAgICAgICMgYWRkX2xldHRlcigiYSIpCiAgICAgIH0KICAgICNsaW5lcyh4PWMoMCxoZWlnaHQpLCB5PWMoMC40NSwwLjQ1KSwgY29sPSJibGFjayIsIGx0eT0xLCBsd2QgPSAyLjUpICMgb25seSBmb3IgZ3JvYgogICAgCiAgICAjIyBIZWF0bWFwCiAgICBwYXIobWFyPWMoNCwuMiwyLjUsMy4yKSkgIyhib3R0b20sIGxlZnQsIHRvcCwgcmlnaHQpIAogICAgaW1hZ2UoIHQodG9wX1BST1RfbWZpW2gkb3JkZXIscHVsbChkZiwgIklEIildW25yb3codG9wX1BST1RfbWZpKToxLF0pLAogICAgICAgICAgIGNvbCA9IGNvbG9yUmFtcFBhbGV0dGUoYygibmF2eSIsIm5hdnkiLCJncmV5OTUiLCJmaXJlYnJpY2s0IiwiZmlyZWJyaWNrNCIpICkoOTkpLAogICAgICAgICAgIGJyZWFrcyA9IGJyZWFrcywKICAgICAgICAgICBheGVzPUYpCiAgICBtdGV4dCggIkRpZmZlcmVudGlhbHkgRXhwcmVzc2VkIFByb3RlaW5zIiwgc2lkZT0zLCBsYXMgPSAxLCBjZXggPSAuNywgZm9udCA9IDIsIGxpbmUgPTEuNSx4cGQ9VCkKICAgIG10ZXh0KCBjKCJTdHVkeSBHcm91cHMiKSwgc2lkZT0xLCBsYXMgPSAxLCBjZXggPSAuNywgbGluZSA9IDEseHBkPVQpCiAgICAKICAgICMgU3R1ZHkgZ3JvdXAgYW5ub3RhdGlvbgogICAgZW5kIDwtIHRhYmxlKHBhbFtmYWN0b3IobmFtZXMoc2FtcGxlcykpWyBvcmRlcihkZlsxXSldXSkKICAgIGVuZCA8LSBlbmRbb3JkZXIoZmFjdG9yKG5hbWVzKGVuZCksIGxldmVscyA9IHBhbCkpXQogICAgZW5kIDwtIG1hcF9kYmwoY3Vtc3VtKGVuZCksIH4gKC54ICogKHBhcigidXNyIilbMl0pL2xlbmd0aChzYW1wbGVzKS0uMDE3KSApCiAgICBzdGFydCA8LSBjKDAsIG1hcF9kYmwoZW5kWzE6NF0sIH4ueCswLjAxNSkpCiAgICBlbmQgPC0gYyhlbmRbMTpsZW5ndGgoZW5kKS0xXSwgcGFyKCJ1c3IiKVsyXS0uMDA1KQogICAgCiAgICBheGlzKDEsIGF0ID0gYyhzdGFydCwgZW5kKSwgbGFiZWwgPSBGLCBwb3MgPTEuMDMyICwgeHBkPVQsIGNvbD0id2hpdGUiLGNvbC50aWNrcz0iYmxhY2siKQogICAgbWFwMihzdGFydCwgZW5kLCB+bGluZXMoeD1jKC55LCAueCksIHk9IGMoMS4wMzIsIDEuMDMyKSwgeHBkPVQsIGNleD0uOCkpCiAgICAjIHRleHQgbGFiZWxzCiAgICB0IDwtIG1hcDIoc3RhcnQsIGVuZCwgfigueCsueSkvMikKICAgIG1hcDIodCxsZXZlbHMoZmFjdG9yKG5hbWVzKHNhbXBsZXMpKSksIH50ZXh0KHg9LngsIHk9MS4wNDMsIC55LHhwZD1ULCBjZXg9LjgpKQogICAgCiAgICAjIEJveGVzIAogICAgaWYoZ3IgPT0gIkx1bWluYWxfZ3IiKSB7CiAgICAgIGxpbmVzKHg9YygwLC42MDMsLjYwMywtLjAwMiwtLjAwMiksCiAgICAgICAgICAgIHk9YyguNDg4LC40ODgsMS4wMDgsIDEuMDA4LC40ODgpLCBjb2w9InJlZCIsIGx0eT0xLCBsd2QgPSAxLjUpCiAgICAgIGxpbmVzKHg9YyguMzksLjk0LC45NCwuMzksLjM5KSwKICAgICAgICAgICAgeT1jKC40ODgsLjQ4OCwtMC4wMDgsIC0wLjAwOCwuNDg4KSwgY29sPSJyZWQiLCBsdHk9MSwgbHdkID0gMS41KX0KICAgIGlmKGdyID09ICJUaXNzdWVfZ3IiKSB7CiAgICAgIGxpbmVzKHg9YyguNjUzLC45NSwuOTUsLjY1MywuNjUzKSwKICAgICAgICAgICAgeT1jKC43MzUsLjczNSwxLjAxMSwgMS4wMTEsLjczNSksIGNvbD0icmVkIiwgbHR5PTEsIGx3ZCA9IDEuNSkKICAgICAgbGluZXMoeD1jKC42NTMsLjk1LC45NSwuNjUzLC42NTMpLAogICAgICAgICAgICB5PWMoLjczNSwuNzM1LC0wLjAxMiwgLTAuMDEyLC43MzUpLCBjb2w9InJlZCIsIGx0eT0xLCBsd2QgPSAxLjUpCiAgICB9CiAgICAKICAgICMjIE1ldGEgaW5mbyBiYXJzCiAgICBpZihnciA9PSAiTHVtaW5hbF9nciIpe3NpemUgPSAuNX1lbHNle3NpemU9LjZ9CiAgICBwb2ludHMoIHNlcSgwLDEsbGVuZ3RoLm91dCA9IGxlbmd0aChzYW1wbGVzKSkscmVwKHBhcigidXNyIilbNF0sbGVuZ3RoKHNhbXBsZXMpKSsuMDA1LAogICAgICAgICAgICBjb2w9cGFsW2ZhY3RvcihuYW1lcyhzYW1wbGVzKSlbIG9yZGVyKGRmWzFdKV1dLAogICAgICAgICAgICBwY2g9MTUseHBkPVQsY2V4PS43KQogICAgCiAgICBwb2ludHMoIHNlcSgwLDEsbGVuZ3RoLm91dCA9IG5jb2wodG9wX1BST1RfbWZpKSkscmVwKHBhcigidXNyIilbM10sbmNvbCh0b3BfUFJPVF9tZmkpKS0uMDA4LAogICAgICAgICAgICBjb2w9YygidG9tYXRvIiwib3JhbmdlIiwiI2Q3ZDdkNyIpWyBmYWN0b3IobWV0YWRhdGFbc2FtcGxlcywiQlZfRGlhZ25vc2lzX3YzIl1bb3JkZXIoZGZbMV0pXSkgXSwKICAgICAgICAgICAgcGNoPTE1LHhwZD1ULGNleD1zaXplKSAKICAgIHBvaW50cyggc2VxKDAsMSxsZW5ndGgub3V0ID0gbmNvbCh0b3BfUFJPVF9tZmkpKSxyZXAocGFyKCJ1c3IiKVszXSxuY29sKHRvcF9QUk9UX21maSkpLS4wMjAsCiAgICAgICAgICAgIGNvbD0gYygiI2Q3ZDdkNyIsInRvbWF0byIpWyBmYWN0b3IobWV0YWRhdGFbc2FtcGxlcywiSElWc3RhdHVzIl1bb3JkZXIoZGZbMV0pXSkgXSwKICAgICAgICAgICAgcGNoPTE1LHhwZD1ULGNleD1zaXplKQogICAgCiAgICBtdGV4dCggcGFzdGUwKCIgIiwgZ3N1YigiXy4rIiwiIixyb3duYW1lcyh0b3BfUFJPVF9tZmkpW3JldihoJG9yZGVyKV0pKSwgc2lkZT00LCBsYXMgPSAxLCBjZXggPSAuNTMsCiAgICAgICAgICAgYXQ9c2VxKDAsMSxsZW5ndGgub3V0ID0gbGVuZ3RoKHJvd25hbWVzKHRvcF9QUk9UX21maSkpKSwgeHBkPVQpCiAgICAKICAgIG10ZXh0KCBjKCIgQlYiLCIgSElWIiksIHNpZGU9NCwgbGFzID0gMSwgY2V4ID0gLjQ1LAogICAgICAgICAgIGF0PWMocGFyKCJ1c3IiKVszXS0uMDA4LHBhcigidXNyIilbM10tLjAyMiksIHhwZD1UKQp9CgpgYGAKCmBgYHtyIHNpZy1jeXRva2luZXMtZnVuY3Rpb24sIGluY2x1ZGU9RkFMU0V9CnNpZ19zdGFycy5mdW4gPC0gZnVuY3Rpb24oZGZfa3J1c2ssIGRmX2R1bm4sIGdyb3VwLCBuID0gNiwgb3JkZXIgPSBOVUxMKXsKICBzYW1wbGVzX3VzZSA8LSBtZXRhZGF0YVssYyhncm91cCwgIklEIildICU+JSBuYS5vbWl0KCkgJT4lIGZpbHRlcihJRCAlaW4lIGNvbG5hbWVzKGN5dG9raW5lX2RhdGEpKQogIAogICMgc2VsZWN0IG9ubHkgc2lnLiBjeXRva2luZXMgCiAgc2lnIDwtIGRmX2tydXNrICU+JSAKICAgIGZpbHRlcihwLmFkajwwLjA1KSAlPiUKICAgIHB1bGwoQ3l0b2tpbmVzKQogIHNpZ19kZiA8LSBjeXRva2luZV9kYXRhX2xvZ1tzaWcsc2FtcGxlc191c2UkSURdCiAgCiAgZ3JvdXBpbmdzIDwtIHNhbXBsZXNfdXNlW1tncm91cF1dIFsgbWF0Y2goIGNvbG5hbWVzKHNpZ19kZlssMTpuY29sKHNpZ19kZiktMV0pICwgYXMuY2hhcmFjdGVyKHNhbXBsZXNfdXNlJElEKSAgKSBdCiAgZ3JvdXBpbmdzIDwtIGMoZ3JvdXBpbmdzKQogIAogICBpZihpcy5udWxsKG9yZGVyKSl7CiAgICBnIDwtIHJvd25hbWVzKHNpZ19kZikKICB9ZWxzZXtnIDwtIG9yZGVyfQogIAogIHN0YXJzX2RmIDwtIGRmX2R1bm4gJT4lCiAgICBtdXRhdGUoeCA9IChhcy5pbnRlZ2VyKHN0cl9leHRyYWN0KC4kZ3JvdXAxLCAiXFxkIikpICsgCiAgICAgICAgICAgICAgICAgIGFzLmludGVnZXIoc3RyX2V4dHJhY3QoLiRncm91cDIsICJcXGQiKSkpLzIpICU+JQogICAgbXV0YXRlKGxpbmVfeDAgPSBhcy5pbnRlZ2VyKHN0cl9leHRyYWN0KC4kZ3JvdXAxLCAiXFxkIikpKSAlPiUKICAgIG11dGF0ZShsaW5lX3gxID0gYXMuaW50ZWdlcihzdHJfZXh0cmFjdCguJGdyb3VwMiwgIlxcZCIpKSkgJT4lCiAgICBtdXRhdGUoeSA9IChhcy5udW1lcmljKGZhY3RvcihDeXRva2luZXMsIGxldmVscyA9IHJldihnKSkpKS0uMykgJT4lCiAgICBhcnJhbmdlKGdyb3VwMSwgZ3JvdXAyKSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShDeXRva2luZXMpICU+JQogICAgbmVzdCgpICU+JQogICAgbXV0YXRlKHlfID0gbWFwKGRhdGEsIH5hY2N1bXVsYXRlKC4keSwgfi54ICsgLjEpKSkgJT4lCiAgICB1bm5lc3QoYyhkYXRhLCB5XykpIAogIAogIHJldHVybihsaXN0KHNpZ19kZj1zaWdfZGYsIHN0YXJzX2RmPXN0YXJzX2RmLCBncm91cGluZ3M9Z3JvdXBpbmdzLCBzYW1wbGVzX3VzZT1zYW1wbGVzX3VzZSkpCn0KYGBgCgpgYGB7ciBDeXRva2luZS1zdGF0cy10ZXN0cywgaW5jbHVkZT1UUlVFfQpjeXRva2luZV9kYXRhIDwtIGN5dG9raW5lX2RhdGEgJT4lIAogIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAiSUQiKSAlPiUgCiAgYXMubWF0cml4KCkKCmN5dG9raW5lX2RhdGEgPC0gdChjeXRva2luZV9kYXRhKQpjeXRva2luZV9kYXRhW2lzLm5hKGN5dG9raW5lX2RhdGEpXSA8LSAwLjAxCmN5dG9raW5lX2RhdGEgPC0gbG9nMihjeXRva2luZV9kYXRhKzEpCmN5dG9raW5lX2RhdGFfbG9nIDwtIGN5dG9raW5lX2RhdGEKCmN5dG8yIDwtIGFzLmRhdGEuZnJhbWUodChjeXRva2luZV9kYXRhKSkKY3l0bzIkSUQ8LXJvdy5uYW1lcyhjeXRvMikKCiNzZWxlY3QgZGF0YSBhbmQgcmUtZm9ybWF0IHRvIGxvbmcgZm9ybWF0CmN5dG9nci5sb25nIDwtIG1ldGFkYXRhICU+JQogIHNlbGVjdChJRCwgTHVtaW5hbF9nciwgVGlzc3VlX2dyKSAlPiUKICBsZWZ0X2pvaW4oLixjeXRvMiwgYnk9IklEIikgJT4lCiAgcGl2b3RfbG9uZ2VyKGMoLUx1bWluYWxfZ3IsIC1UaXNzdWVfZ3IsIC1JRCksIG5hbWVzX3RvID0gIkN5dG9raW5lcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpIAoKdGVzdC5rcnVza19kdW5uLmZ1biA8LSBmdW5jdGlvbihkZiwgdmFyLCBncm91cCkgewogIHZhciA8LSBlbnF1byh2YXIpCiAgCiAgc3RhdC50ZXN0LmtydXNrIDwtIGRmICU+JQogIGdyb3VwX2J5KCEhKHZhcikpICU+JQogIGtydXNrYWxfdGVzdCguLCBhcy5mb3JtdWxhKHBhc3RlKCJ2YWx1ZSIsICJ+IiwgZ3JvdXApKSkgJT4lCiAgYWRqdXN0X3B2YWx1ZShtZXRob2QgPSAiQkgiKSAlPiUKICBzZWxlY3QoLS55LiwgLW4sIC1kZikgJT4lCiAgYXJyYW5nZShwKSAlPiUKICByZW5hbWUocC52YWx1ZSA9ICJwIikgJT4lCiAgYWRkX3NpZ25pZmljYW5jZSgpCgojIHNlbGVjdCB0aGUgc2lnbmlmaWNhbnQgcHJvdGVpbnMgZnJvbSBrcnVza2FsCnNpZyA8LSBzdGF0LnRlc3Qua3J1c2sgJT4lIGZpbHRlcihwLmFkajwwLjA1KSAlPiUgcHVsbCghIXZhcikKCiMjIyBQb3N0IGhvYyB0ZXN0CnN0YXQudGVzdC5kdW5uIDwtIGRmICU+JQogIGZpbHRlcighIXZhciAlaW4lIHNpZykgJT4lCiAgZ3JvdXBfYnkoISF2YXIpICU+JQogIGR1bm5fdGVzdCguLCBhcy5mb3JtdWxhKHBhc3RlKCJ2YWx1ZSIsICJ+IiwgZ3JvdXApKSkgJT4lCiAgI2R1bm5fdGVzdCh2YWx1ZSB+ICEhZ3JvdXApICU+JQogIHNlbGVjdCgtLnkuKSAlPiUKICBhcnJhbmdlKHApICU+JQogIHJlbmFtZShwLnZhbHVlID0gInAiKSAlPiUKICBmaWx0ZXIocC5hZGo8MC4wNSkKCiAgc2lnMiA8LSBzdGF0LnRlc3QuZHVubltzdGF0LnRlc3QuZHVubiRwLmFkajwwLjA1LF0KICAKIGwgPC0gbGlzdChzdGF0LnRlc3Qua3J1c2ssIHN0YXQudGVzdC5kdW5uKQogbiA8LSAgYygiS3J1c2thbCIsICJEdW5uJ3MiKSAlPiUgcGFzdGUwKC4sICJfIiwgZ3JvdXAsIHNlcCA9ICIiKQogbCA8LSBzZXRfbmFtZXMobCwgbikKCnJldHVybihsKQp9CgpuIDwtIGMoIkx1bWluYWxfZ3IiLCAiVGlzc3VlX2dyIikgJT4lIHNldF9uYW1lcyhjKCJMdW1pbmFsIiwgIlRpc3N1ZSIpKQpzdGF0IDwtIGltYXAobiwgfnRlc3Qua3J1c2tfZHVubi5mdW4oY3l0b2dyLmxvbmcsIEN5dG9raW5lcywgLngpKQpzIDwtIGZsYXR0ZW4oc3RhdCkKYGBgCgpgYGB7ciBTdXBwbC4gVGJsLiAxNSAxNiAmIDE3LCBpbmNsdWRlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9Cm5hbWVzIDwtIGMoIjE1IEx1bWluYWwiLCAiMTYgVGlzc3VlIikgJT4lIHNldF9uYW1lcygpCgojIHNhdmUgVG9wVGFibGVzIHBhaXJ3aXNlCmxfdG9wX3AgPC0gbGlzdChwYWlyd2lzZV9kcGVfTCR0b3AsIHBhaXJ3aXNlX2RnZV9UJHRvcCkgICU+JSBzZXRfbmFtZXMobmFtZXMpCgojIHNhdmUgVG9wVGFibGVzIGFjcm9zcyArIGN5dG9raW5lcwpsX3RvcF9hIDwtIGxpc3QoIGxpc3QoQWNyb3NzID0gZHBlX0wkdG9wKSwgbGlzdChBY3Jvc3MgPSBkcGVfVCR0b3ApKSAgJT4lIHNldF9uYW1lcyhuYW1lcykKbCA8LSBsaXN0KGxfdG9wX2EsIHN0YXQsIGxfdG9wX3ApCnBfbGlzdCA8LSBpbWFwKG5hbWVzLCB+ZmxhdHRlbihtYXBfZGVwdGgobCwgMSwgLngpKSkgCgppbWFwKHBfbGlzdCwgfndyaXRlLnhsc3goLngsZmlsZT1wYXN0ZTAocmVzdWx0X2RpciwiU3VwcGwuVGJsLiIsLnksIl9Qcm90ZWlucy54bHN4IikpKSAjIEV4Y2VsCndyaXRlLnhsc3gobGlzdCgiTDJUMiB2cyBMMlQzIj1kcGVfTFQkdG9wKSxmaWxlPXBhc3RlMChyZXN1bHRfZGlyLCJTdXBwbC5UYmwuMTciLCIgTDJUMl9MMlQzX1Byb3RlaW5zLnhsc3giKSkKYGBgCgpgYGB7ciBGaWd1cmUgNiwgZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9N30KIyBkZXYubmV3KGhlaWdodD0xMCwgd2lkdGg9Ni42OTI5MTMzODU4LCBub1JTdHVkaW9HRCA9IFRSVUUpCmZpZ2xhYmVscyA8LSBsZXR0ZXJzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFRPUCBESUZGLiBFWFBSRVNTRUQgUFJPVCBIRUFUTUFQICMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyBBCiMgTHVtaW5hbCBncm91cHMKdCA8LSB0b3BfZHBlLmZ1bihkcGVfTCR0b3ApCnBsb3RfaGVhdG1hcC5mdW4odCwgIkx1bWluYWxfZ3IiLCBzY2FsZSA9IFQsIGxheW91dCA9ICJtdWx0aSIpCgojIyMgQwojIFRpc3N1ZSBncm91cHMKdCA8LSB0b3BfZHBlLmZ1bihkcGVfVCR0b3ApCnBhcihtZmcgPSBjKDIsMSkpICMgYWRkcyB0aGUgcmVtYW5pbmcgcGxvdHMgdG8gdGhlIHByZXZpb3VzIGxheW91dApwbG90X2hlYXRtYXAuZnVuKHQsICJUaXNzdWVfZ3IiLCBzY2FsZSA9IFQpCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgU0lHLiBDWVRPS0lORVMgVklPTElOIFBMT1QgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIEIKIyBMdW1pbmFsIGdyb3VwcwpnIDwtIGMoIk1JRyIsICJJTDFiIiwgIklMMTJfcDcwIiwgIk1DUDEiLCAiSUwxYSIsICJJUDEwIikgCiNnIDwtIGMoIk1JRyIsICJJTDEyX3A3MCIsIklMMWEiLCAiSVAxMCIsICJJTDFiIiwgIk1DUDEiICkKbGFiIDwtIGMoIk1JRyIsICJJTC0xXHUwM2IyIiwgIklMLTEyLXA3MCIsICJNQ1AtMSIsICJJTC0xXHUwM2IxIiwgIklQLTEwIiApCiNsYWIgPC0gYygiSVAtMTAiLCAiSUwtMVx1MDNiMiIsICJJTC0xMi1wNzAiLCAiTUNQLTEiLCJJTC0xXHUwM2IxIiwgIk1JRyIpCkx1bWluYWwgPC0gc2lnX3N0YXJzLmZ1bihzJEtydXNrYWxfTHVtaW5hbF9nciwgcyRgRHVubidzX0x1bWluYWxfZ3JgLCAiTHVtaW5hbF9nciIsIG9yZGVyID0gZ1sxOjRdKQpyb3duYW1lcyhMdW1pbmFsJHNpZ19kZikgPC0gbGFiCnN0YXJzIDwtIEx1bWluYWwkc3RhcnNfZGYgCgpwYXIoIG1hcj1jKDEuNCw1LDEuNSwyKSkgI2IsbCx0LHIgCnZpb2xpc3QoZGF0YT1MdW1pbmFsJHNpZ19kZiwKICAgICAgICAgIHNydD00NSwgeV9wYWRkaW5nID0gMiwgc21vb3RoID0gLjIsCiAgICAgICAgICBnZW5lcz0gbGFiWzE6NF0sCiAgICAgICAgICAjY2V4LmF4aXMgPSAxLjEsCiAgICAgICAgICAjYWRkX3lsaW1zID0gVCwgI2dpdmVzIHN0YXJ0aW5nIHZhbHVlIG9mIHktYXhpcyBhbmQgbWF4IHZhbHVlIG9mIGFsbCBkYXRhIHBvaW50cwogICAgICAgICAgY29sID0gcGFsLCB0cmFuc3BhcmVuY3kgPSA1MCwKICAgICAgICAgIGNsdXN0ZXJpbmc9YyhMdW1pbmFsJGdyb3VwaW5ncykpCnNlZ21lbnRzKHgwID0gc3RhcnMkbGluZV94MCwgeDEgPSBzdGFycyRsaW5lX3gxLCB5MCA9IHN0YXJzJHlfLCB5MSA9IHN0YXJzJHlfKSAKdGV4dCggc3RhcnMkeCAsIHN0YXJzJHlfKy4wNSwKICAgICAgICBsYWJlbHMgPSBzdGFycyRwLmFkai5zaWduaWYsIHNydCA9IDAsIHhwZCA9IFRSVUUsIGNleD0xKQp0aXRsZShtYWluID0gIkx1bWluYWwgZ3IuIEN5dG9raW5lcyIsIGxpbmUgPSAwLjcsIGNleC5tYWluID0gMS4xKQoKYWRkX2xldHRlcigiYiIpCgpMdW1pbmFsIDwtIHNpZ19zdGFycy5mdW4ocyRLcnVza2FsX0x1bWluYWxfZ3IsIHMkYER1bm4nc19MdW1pbmFsX2dyYCwgIkx1bWluYWxfZ3IiLCBvcmRlciA9IGdbNTo2XSkKcm93bmFtZXMoTHVtaW5hbCRzaWdfZGYpIDwtIGxhYgpzdGFycyA8LSBMdW1pbmFsJHN0YXJzX2RmIApwYXIobWFyPWMoMS40LDUsMS41LDIpICkgI2IsbCx0LHIKdmlvbGlzdChkYXRhPUx1bWluYWwkc2lnX2RmLAogICAgICAgICAgc3J0PTQ1LCB5X3BhZGRpbmcgPSAyLCBzbW9vdGggPSAuMiwKICAgICAgICAgIGdlbmVzPSBsYWJbNTo2XSwKICAgICAgICAgICNhZGRfeWxpbXMgPSBULCAjZ2l2ZXMgc3RhcnRpbmcgdmFsdWUgb2YgeS1heGlzIGFuZCBtYXggdmFsdWUgb2YgYWxsIGRhdGEgcG9pbnRzCiAgICAgICAgICBjb2wgPSBwYWwsIHRyYW5zcGFyZW5jeSA9IDUwLAogICAgICAgICAgY2x1c3RlcmluZz1jKEx1bWluYWwkZ3JvdXBpbmdzKSkKc2VnbWVudHMoeDAgPSBzdGFycyRsaW5lX3gwLCB4MSA9IHN0YXJzJGxpbmVfeDEsIHkwID0gc3RhcnMkeV8sIHkxID0gc3RhcnMkeV8pCnRleHQoIHN0YXJzJHggLCBzdGFycyR5XysuMDUsCiAgICAgICAgbGFiZWxzID0gc3RhcnMkcC5hZGouc2lnbmlmLCBzcnQgPSAwLCB4cGQgPSBUUlVFLCBjZXg9MSkKdGl0bGUobWFpbiA9ICJMdW1pbmFsIGdyLiBDeXRva2luZXMiLCBsaW5lID0gMC43LCBjZXgubWFpbiA9IDEuMSkKCiMjIyBECiMgVGlzc3VlIGdyb3VwcwpsYWIgPC0gYygiSUwtMVx1MDNiMSIsICJJUC0xMCIpClRpc3N1ZSA8LSBzaWdfc3RhcnMuZnVuKHMkS3J1c2thbF9UaXNzdWVfZ3IsIHMkYER1bm4nc19UaXNzdWVfZ3JgLCAiVGlzc3VlX2dyIikKcm93bmFtZXMoVGlzc3VlJHNpZ19kZikgPC0gbGFiCnN0YXJzIDwtIFRpc3N1ZSRzdGFyc19kZgoKI3BhcihtYXI9YygyMC40LDYsMS41LDMpKSAjYixsLHQsciAjIHBzID0gMjAsIHBvaW50IHNpemUKcGFyKG1hcj1jKDEsNSwxLjUsNSkpICNiLGwsdCxyCnZpb2xpc3QoZGF0YT1UaXNzdWUkc2lnX2RmLAogICAgICAgICAgc3J0PTQ1LCB5X3BhZGRpbmcgPSAyLCBzbW9vdGggPSAuMiwKICAgICAgICAgIGdlbmVzPSByb3duYW1lcyhUaXNzdWUkc2lnX2RmKSwKICAgICAgICAgIGNvbCA9IHBhbCwgdHJhbnNwYXJlbmN5ID0gNTAsCiAgICAgICAgICAjIGFkZF95bGltcyA9IFQsCiAgICAgICAgICBjbHVzdGVyaW5nPVRpc3N1ZSRncm91cGluZ3MgKQpzZWdtZW50cyh4MCA9IHN0YXJzJGxpbmVfeDAsIHgxID0gc3RhcnMkbGluZV94MSwgeTAgPSBzdGFycyR5XywgeTEgPSBzdGFycyR5XykKdGV4dCggc3RhcnMkeCAsIHN0YXJzJHlfKy4wNSwKICAgICAgICBsYWJlbHMgPSBzdGFycyRwLmFkai5zaWduaWYsIHNydCA9IDAsIHhwZCA9IFRSVUUsIGNleD0xKQp0aXRsZShtYWluID0gIlRpc3N1ZSBnci4gQ3l0b2tpbmVzIiwgbGluZSA9IDAuNywgY2V4Lm1haW4gPSAxLjEpCgphZGRfbGV0dGVyKCJkIikKCmBgYAoKKipGaWd1cmUgNi4gQ2hhcmFjdGVyaXphdGlvbiBvZiB0aGUgaG9zdCBwcm90ZWluIHByb2ZpbGUgYXMgc3RyYXRpZmllZCBieSB0aGUgbHVtaW5hbCBhbmQgdGlzc3VlLWFkaGVyZW50IG1pY3JvYmlvbWUgc3R1ZHkgZ3JvdXBzLioqIEFsbCBzdHVkeSBzYW1wbGVzIHdlcmUgYXNzZXNzZWQgZm9yIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIHByb3RlaW4gbGV2ZWxzIGFjcm9zcyB0aGUgc3R1ZHkgZ3JvdXBzLiAqKmEqKiwqKmIqKiBUaGUgZml2ZSBsdW1pbmFsIHN0dWR5IGdyb3VwcyBhbmQgKipjKiosKipkKiogdGhlIGZpdmUgY29ycmVzcG9uZGluZyB0aXNzdWUgZ3JvdXBzLiBhLCBjIFByb3RlaW5zIHdpdGggYSBwLXZhbHVlID4gMC4wNSB3ZXJlIG9taXR0ZWQgZnJvbSB0aGUgaGVhdG1hcC4gUHJvdGVpbnMgd2l0aCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBsZXZlbHMgYWNyb3NzIHRoZSBncm91cHMgd2VyZSBjbHVzdGVyZWQgYnkgaGllcmFyY2hpY2FsIGFnZ2xvbWVyYXRpdmUgY2x1c3RlcmluZyB1c2luZyBpbnZlcnNlIFBlYXJzb27igJlzIGNvcnJlbGF0aW9uIGFzIGRpc3RhbmNlIG1lYXN1cmUgYW5kIFdhcmTigJlzIG1ldGhvZCAo4oCcd2FyZC4gRDLigJ0pIGZvciBsaW5rYWdlLiBDb2xvci1jb2RlZCByb3dzIGJlbG93IHRoZSBoZWF0bWFwcyBzaG93IGNsaW5pY2FsIGRpYWdub3NpcyBvZiBiYWN0ZXJpYWwgdmFnaW5vc2lzIChCViwgYmlubmVkIE51Z2VudOKAmXMgc2NvcmVzKSBhbmQgSElWIGRpYWdub3NpcywgcmVzcGVjdGl2ZWx5LiBDb2xvciBjb2RpbmcgZm9yIEJWOiBHcmF5OiBuZWdhdGl2ZSwgb3JhbmdlOiBpbnRlcm1lZGlhdGUsIHJlZDogcG9zaXRpdmU7IGFuZCBmb3IgSElWOiBHcmF5OiBISVYgc2Vyb25lZ2F0aXZlLCByZWQ6IEhJViBzZXJvcG9zaXRpdmUuIGIsIGQgVmlvbGluIHBsb3RzIG9mIGxvZzIgdHJhbnNmb3JtZWQgY3l0b2tpbmUgbGV2ZWxzIGFjcm9zcyB0aGUgbHVtaW5hbCBhbmQgdGlzc3VlIHN0dWR5IGdyb3VwcyAoYXMgaW5kaWNhdGVkIG9uIHRoZSB4LWF4aXMpLCByZXNwZWN0aXZlbHkuIFRoZSBhc3RlcmlzayBhbmQgbGluZXMgaW5kaWNhdGUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCByZXN1bHRzIG9mIER1bm7igJlzIHRlc3Qgd2l0aCBCZW5qYW1pbmkgSG9jaGJlcmfigJlzIGNvcnJlY3Rpb24gYW5hbHlzaXMuIEFkanVzdGVkIHAtdmFsdWVzOiAqIDwgMC4wNSwgKiogPCAwLjAxLCAqKiogPCAwLjAwMSwgKioqKiA8IDAuMDAwMQoKYGBge3Igb2xkLUZpZ3VyZSA2LCBlY2hvID0gRkFMU0UsIGV2YWwgPSBGQUxTRSwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTd9CiMgb2xkIGxheW91dAogICAgIyBsYXlvdXQobWF0cml4KGMoMSwyLDUsNiwKICAgICMgICAgICAgICAgICAgICAgIDcsNyw4LDgsCiAgICAjICAgICAgICAgICAgICAgICAzLDMsNCw0KSwKICAgICMgICAgICAgIG5yb3cgPSAzLCBuY29sID0gNCxieXJvdyA9IFQpLAogICAgIyAgICAgICAgd2lkdGhzID0gYygxLDIsLjgsMiksIGhlaWdodHMgPSBjKDEsMSwuMDEpICkKZmlnbGFiZWxzIDwtIGxldHRlcnMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgVE9QIERJRkYuIEVYUFJFU1NFRCBQUk9UIEhFQVRNQVAgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIEEKIyBMdW1pbmFsIGdyb3Vwcwp0IDwtIHRvcF9kcGUuZnVuKGRwZV9MJHRvcCkKcGxvdF9oZWF0bWFwLmZ1bih0LCAiTHVtaW5hbF9nciIsIHNjYWxlID0gVCwgbGF5b3V0ID0gIm11bHRpIikKCiMjIyBDCiMgVGlzc3VlIGdyb3Vwcwp0IDwtIHRvcF9kcGUuZnVuKGRwZV9UJHRvcCkKcGFyKG1mZyA9IGMoMiwxKSkgIyBhZGRzIHRoZSByZW1hbmluZyBwbG90cyB0byB0aGUgcHJldmlvdXMgbGF5b3V0CnBsb3RfaGVhdG1hcC5mdW4odCwgIlRpc3N1ZV9nciIsIHNjYWxlID0gVCkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTSUcuIENZVE9LSU5FUyBWSU9MSU4gUExPVCAjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMgQgojIEx1bWluYWwgZ3JvdXBzCmcgPC0gYygiSUwxYSIsICJNSUciLCAiSVAxMCIsICJJTDFiIiwgIklMMTJfcDcwIiwgIk1DUDEiKQpsYWIgPC0gYygiSUwtMVx1MDNiMSIsICJNSUciLCAiSVAtMTAiLCAiSUwtMVx1MDNiMiIsICJJTC0xMi1wNzAiLCAiTUNQLTEiKQpMdW1pbmFsIDwtIHNpZ19zdGFycy5mdW4ocyRLcnVza2FsX0x1bWluYWxfZ3IsIHMkYER1bm4nc19MdW1pbmFsX2dyYCwgIkx1bWluYWxfZ3IiLCBvcmRlciA9IGcpCnJvd25hbWVzKEx1bWluYWwkc2lnX2RmKSA8LSBsYWIKc3RhcnMgPC0gTHVtaW5hbCRzdGFyc19kZgoKcGFyKCBtYXI9YygxLjQsNSwxLjUsMikpICNiLGwsdCxyIAp2aW9saXN0KGRhdGE9THVtaW5hbCRzaWdfZGYsCiAgICAgICAgICBzcnQ9NDUsIHlfcGFkZGluZyA9IDIsIHNtb290aCA9IC4yLAogICAgICAgICAgZ2VuZXM9IGxhYiwKICAgICAgICAgICNhZGRfeWxpbXMgPSBULCAjZ2l2ZXMgc3RhcnRpbmcgdmFsdWUgb2YgeS1heGlzIGFuZCBtYXggdmFsdWUgb2YgYWxsIGRhdGEgcG9pbnRzCiAgICAgICAgICBjb2wgPSBwYWwsIHRyYW5zcGFyZW5jeSA9IDUwLAogICAgICAgICAgY2x1c3RlcmluZz1jKEx1bWluYWwkZ3JvdXBpbmdzKSkKc2VnbWVudHMoeDAgPSBzdGFycyRsaW5lX3gwLCB4MSA9IHN0YXJzJGxpbmVfeDEsIHkwID0gc3RhcnMkeV8sIHkxID0gc3RhcnMkeV8pIAp0ZXh0KCBzdGFycyR4ICwgc3RhcnMkeV8rLjA1LAogICAgICAgIGxhYmVscyA9IHN0YXJzJHAuYWRqLnNpZ25pZiwgc3J0ID0gMCwgeHBkID0gVFJVRSwgY2V4PTEpCnRpdGxlKG1haW4gPSAiTHVtaW5hbCBnci4gQ3l0b2tpbmVzIiwgbGluZSA9IDAuNywgY2V4Lm1haW4gPSAuOSkKCmFkZF9sZXR0ZXIoImIiKQoKIyMjIEQKIyBUaXNzdWUgZ3JvdXBzCmxhYiA8LSBjKCJJTC0xXHUwM2IxIiwgIklQLTEwIikKVGlzc3VlIDwtIHNpZ19zdGFycy5mdW4ocyRLcnVza2FsX1Rpc3N1ZV9nciwgcyRgRHVubidzX1Rpc3N1ZV9ncmAsICJUaXNzdWVfZ3IiKQpyb3duYW1lcyhUaXNzdWUkc2lnX2RmKSA8LSBsYWIKc3RhcnMgPC0gVGlzc3VlJHN0YXJzX2RmCgpwYXIobWFyPWMoMjAuNCw2LDEuNSwzKSkgI2IsbCx0LHIgIyBwcyA9IDIwLCBwb2ludCBzaXplCnZpb2xpc3QoZGF0YT1UaXNzdWUkc2lnX2RmLAogICAgICAgICAgc3J0PTQ1LCB5X3BhZGRpbmcgPSAyLCBzbW9vdGggPSAuMiwKICAgICAgICAgIGdlbmVzPSByb3duYW1lcyhUaXNzdWUkc2lnX2RmKSwgCiAgICAgICAgICBjb2wgPSBwYWwsIHRyYW5zcGFyZW5jeSA9IDUwLCAKICAgICAgICAgICMgYWRkX3lsaW1zID0gVCwKICAgICAgICAgIGNsdXN0ZXJpbmc9VGlzc3VlJGdyb3VwaW5ncyApCnNlZ21lbnRzKHgwID0gc3RhcnMkbGluZV94MCwgeDEgPSBzdGFycyRsaW5lX3gxLCB5MCA9IHN0YXJzJHlfLCB5MSA9IHN0YXJzJHlfKSAKdGV4dCggc3RhcnMkeCAsIHN0YXJzJHlfKy4wNSwKICAgICAgICBsYWJlbHMgPSBzdGFycyRwLmFkai5zaWduaWYsIHNydCA9IDAsIHhwZCA9IFRSVUUsIGNleD0xKQp0aXRsZShtYWluID0gIlRpc3N1ZSBnci4gQ3l0b2tpbmVzIiwgbGluZSA9IDAuNywgY2V4Lm1haW4gPSAuOSkKCmFkZF9sZXR0ZXIoImQiKQoKYGBgCgpgYGB7ciBBbGwtZHBlLXBsb3QsIGV2YWw9RkFMU0UsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoY293cGxvdCkKCnBsb3RfaGVhdG1hcC5mdW4oUHJvdGVpblssc2FtcGxlX3VzZV0sICJMdW1pbmFsX2dyIikKcC5wbG90IDwtIHJlY29yZFBsb3QoKQoKcGxvdF9oZWF0bWFwLmZ1bihQcm90ZWluWyxzYW1wbGVfdXNlXSwgIlRpc3N1ZV9nciIpCnAucGxvdF9UIDwtIHJlY29yZFBsb3QoKQoKIyBzaWRlIGJ5IHNpZGUgdW5zY2FsZWQKcGxvdF9ncmlkKGdnZHJhdyhwLnBsb3QpLGdnZHJhdyhwLnBsb3RfVCksIAogICAgICAgICAgbGFiZWxzID0gYygnYScsICdiJykscmVsX3dpZHRocz1jKDEsMSksIGdyZWVkeSA9IEYpCgpgYGAK