I’m looking at differences in DMRs when we change the coverage value cutoffs for the Day 135 samples. I don’t think I’m going to actually run this notebook, as it’s largely cut and paste code from a previous analysis. The only real changes are output file names, to avoid overwriting results and the actual cutoff values.
Cutoff values are located in lines 63 and 64 of the analysis code, that look like and are located in the all(x > 3) section. Changing the numeric value changes the cutoff.
meth.db3 <- meth.db2[apply(meth.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 3)), ]
totcov.db3 <- totcov.db2[apply(totcov.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 3)), ]
The thing you came here for! The different number of DMRs found at each cutoff. I’ll upload the graphs to scaphapoda also
3x |
709 |
5x |
304 |
7x |
136 |
10x |
63 |
Let the cutting and pasting begin! I’ll go 7x, 5x, and 3x in order.
7x Coverage Code
setwd("~/Documents/Day135/Day135Cutoff/")
samples.vec <- c("EPI-151", "EPI-152", "EPI-153", "EPI-154", "EPI-159", "EPI-160", "EPI-161", "EPI-162", "EPI-167", "EPI-168", "EPI-169", "EPI-170")
library(readr)
setwd("~/Documents/Day135/Day135Cutoff/CGoutput")
data <- list.files(path = ".", pattern = "*.output")
print(data)
db <- read_delim("~/Documents/Day135/Day135Cutoff/CGoutput/EPI-151_CG.output", "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
db <- as.data.table(db)
db$EPI103Meth <- rowSums(cbind(db[,4], db[,7]), na.rm = TRUE)
db$EPI103TotCov <- rowSums(cbind(db[,5], db[,8]), na.rm = TRUE)
meth.db <- db[,c(1,2,3,10)]
totcov.db <- db[,c(1,2,3,11)]
for(i in 2:length(data)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/CGoutput/", data[i]), "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
temp <- as.data.table(temp)
temp$Meth <- rowSums(cbind(temp[,4], temp[,7]), na.rm = TRUE)
temp$TotCov <- rowSums(cbind(temp[,5], temp[,8]), na.rm = TRUE)
meth.db <- merge(meth.db, temp[,c(1,2,3,10)], by = names(meth.db[,c(1,2,3)]), all = TRUE)
colnames(meth.db)[ncol(meth.db)] <- paste0(substr(data[i], 1, 7), "Meth")
meth.db <- as.data.table(meth.db)
totcov.db <- merge(totcov.db, temp[,c(1,2,3,11)], by = names(totcov.db[,c(1,2,3)]), all = TRUE)
colnames(totcov.db)[ncol(totcov.db)] <- paste0(substr(data[i], 1, 7), "TotCov")
totcov.db <- as.data.table(totcov.db)
}
setwd("~/Documents/Day135/Day135Cutoff/macau")
meth.db2 <- meth.db[complete.cases(meth.db[,c(4:15)]),]
totcov.db2 <- totcov.db[complete.cases(totcov.db[,c(4:15)]),]
meth.db3 <- meth.db2[apply(meth.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 7)), ]
totcov.db3 <- totcov.db2[apply(totcov.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 7)), ]
meth.db4 <- as.data.table(cbind(paste0(meth.db3$`#CHROM`, "-", meth.db3$POS), meth.db3[,4:ncol(meth.db3)]))
colnames(meth.db4)[1] <- "Site"
totcov.db4 <- as.data.table(cbind(paste0(totcov.db3$`#CHROM`, "-", totcov.db3$POS), totcov.db3[,4:ncol(totcov.db3)]))
colnames(totcov.db4)[1] <- "Site"
totcov.db5 <- totcov.db4[totcov.db4$Site %in% meth.db4$Site,]
nrow(meth.db4)
nrow(totcov.db5)
length(totcov.db5$Site %in% meth.db4$Site)
write.table(meth.db4, file = "sevenx.macau.meth.txt", sep = " ", quote = FALSE, row.names = FALSE)
write.table(totcov.db5, file = "sevenx.macau.totalcov.txt", sep = " ", quote = FALSE, row.names = FALSE)
system("head macau.meth.txt")
system("head macau.totalcov.txt")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
system("/home/shared/macau/macau -g sevenx.macau.meth.csv -t sevenx.macau.totalcov.csv -p Predictor.csv -k day135-relate-finished.csv -o sevenx")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
result_assoc <- read_delim("~/Documents/Day135/Day135Cutoff/macau/output/sevenx.assoc.txt", "\t", escape_double = FALSE, trim_ws = TRUE)
sig.results <- result_assoc[result_assoc$pvalue <= 0.05,]
for(i in 1:nrow(sig.results)) {
temp <- strsplit(sig.results$id[i], "-")
sig.results[i,13] <- temp[[1]][1]
sig.results[i,14] <- temp[[1]][2]
}
colnames(sig.results)[c(13,14)] <- c("Scaffold", "Loc")
bed.test <- as.data.frame(cbind(sig.results[,13], (sig.results[,14]), (sig.results[,14]), sig.results$beta))
colnames(bed.test)[4] <- "beta"
write.table(bed.test, file = "sevenx.DiffMethRegions.bed", sep = "\t", quote = FALSE, col.names = FALSE, row.names = FALSE)
setwd("~/Documents/Day135/Day135Cutoff/")
list.files(path = ".")
library(data.table)
library(readr)
DiffMethRegions <- read_delim("~/Documents/Day135/Day135Cutoff/macau/sevenx.DiffMethRegions.bed",
"\t", escape_double = FALSE, col_names = FALSE,
trim_ws = TRUE)
DiffMethRegions$Loc <- paste0(DiffMethRegions$X1, "-", DiffMethRegions$X2)
head(DiffMethRegions)
sample.files <- list.files(path = "~/Documents/Day135/Day135Cutoff/", pattern = "*.bedgraph")
print(sample.files)
EPI_103_percmeth_bedgraph <- read_delim("~/Documents/Day135/Day135Cutoff/EPI-151-percmeth.bedgraph",
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
EPI_103_percmeth_bedgraph <- as.data.table(EPI_103_percmeth_bedgraph)
head(EPI_103_percmeth_bedgraph)
print(EPI_103_percmeth_bedgraph[7,])
EPI_103_DMRs <- EPI_103_percmeth_bedgraph[EPI_103_percmeth_bedgraph$X1 %in% DiffMethRegions$X1,]
EPI_103_DMRs$Loc <- paste0(EPI_103_DMRs$X1, "-", EPI_103_DMRs$X2)
head(EPI_103_DMRs)
EPI_103_DMRs <- EPI_103_DMRs[EPI_103_DMRs$Loc %in% DiffMethRegions$Loc,]
head(EPI_103_DMRs)
EPI_DMRs <- as.data.table(cbind(EPI_103_DMRs$Loc, EPI_103_DMRs$X4))
colnames(EPI_DMRs)[1] <- "DMRLoc"
colnames(EPI_DMRs)[2] <- "EPI_151"
head(EPI_DMRs)
for(i in 2:length(sample.files)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/", sample.files[i]),
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
temp <- as.data.table(temp)
temp_DMRs <- temp[temp$X1 %in% DiffMethRegions$X1,]
temp_DMRs$Loc <- paste0(temp_DMRs$X1, "-", temp_DMRs$X2)
temp_DMRs <- temp_DMRs[temp_DMRs$Loc %in% DiffMethRegions$Loc,]
EPI_DMRs$temp <- temp_DMRs$X4
colnames(EPI_DMRs)[ncol(EPI_DMRs)] <- substr(sample.files[i], 1, 7)
}
head(EPI_DMRs)
## This is here because for osme reason EPI_103 gets brught in as characters as opposed to doubles. Need to figure out why, but this fixes it for now
EPI_DMRs$EPI_151 <- as.numeric(EPI_DMRs$EPI_151)
treatment.means <- as.data.frame(EPI_DMRs$DMRLoc)
treatment.means$Ambient <- apply(cbind(EPI_DMRs$`EPI-151`, EPI_DMRs$`EPI-152`, EPI_DMRs$`EPI-153`, EPI_DMRs$`EPI-154`) ,MARGIN = 1, FUN = mean)
treatment.means$Low <- apply(cbind(EPI_DMRs$`EPI-159`, EPI_DMRs$`EPI-160`, EPI_DMRs$`EPI-161`, EPI_DMRs$`EPI-162`) ,MARGIN = 1, FUN = mean)
treatment.means$SuperLow <- apply(cbind(EPI_DMRs$`EPI-167`, EPI_DMRs$`EPI-168`, EPI_DMRs$`EPI-169`, EPI_DMRs$`EPI-170`) ,MARGIN = 1, FUN = mean)
head(treatment.means)
for(i in 1:nrow(treatment.means)) {
boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,4], EPI_DMRs[i,5])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
boxplot(t(cbind(EPI_DMRs[i,10], EPI_DMRs[i,11], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
axis(side = 1, at = 2, labels = "Low")
axis(side = 1, at = 3, labels = "Super Low")
title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
}
pdf(file = "sevenx-DMR-Box-Plots.pdf")
for(i in 1:nrow(treatment.means)) {
boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,10], EPI_DMRs[i,11])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
boxplot(t(cbind(EPI_DMRs[i,4], EPI_DMRs[i,5], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
axis(side = 1, at = 2, labels = "Low")
axis(side = 1, at = 3, labels = "Super Low")
title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
}
dev.off()
5x Coverage Code
setwd("~/Documents/Day135/Day135Cutoff/")
samples.vec <- c("EPI-151", "EPI-152", "EPI-153", "EPI-154", "EPI-159", "EPI-160", "EPI-161", "EPI-162", "EPI-167", "EPI-168", "EPI-169", "EPI-170")
library(readr)
setwd("~/Documents/Day135/Day135Cutoff/CGoutput")
data <- list.files(path = ".", pattern = "*.output")
print(data)
db <- read_delim("~/Documents/Day135/Day135Cutoff/CGoutput/EPI-151_CG.output", "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
db <- as.data.table(db)
db$EPI103Meth <- rowSums(cbind(db[,4], db[,7]), na.rm = TRUE)
db$EPI103TotCov <- rowSums(cbind(db[,5], db[,8]), na.rm = TRUE)
meth.db <- db[,c(1,2,3,10)]
totcov.db <- db[,c(1,2,3,11)]
for(i in 2:length(data)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/CGoutput/", data[i]), "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
temp <- as.data.table(temp)
temp$Meth <- rowSums(cbind(temp[,4], temp[,7]), na.rm = TRUE)
temp$TotCov <- rowSums(cbind(temp[,5], temp[,8]), na.rm = TRUE)
meth.db <- merge(meth.db, temp[,c(1,2,3,10)], by = names(meth.db[,c(1,2,3)]), all = TRUE)
colnames(meth.db)[ncol(meth.db)] <- paste0(substr(data[i], 1, 7), "Meth")
meth.db <- as.data.table(meth.db)
totcov.db <- merge(totcov.db, temp[,c(1,2,3,11)], by = names(totcov.db[,c(1,2,3)]), all = TRUE)
colnames(totcov.db)[ncol(totcov.db)] <- paste0(substr(data[i], 1, 7), "TotCov")
totcov.db <- as.data.table(totcov.db)
}
setwd("~/Documents/Day135/Day135Cutoff/macau")
meth.db2 <- meth.db[complete.cases(meth.db[,c(4:15)]),]
totcov.db2 <- totcov.db[complete.cases(totcov.db[,c(4:15)]),]
meth.db3 <- meth.db2[apply(meth.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 5)), ]
totcov.db3 <- totcov.db2[apply(totcov.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 5)), ]
meth.db4 <- as.data.table(cbind(paste0(meth.db3$`#CHROM`, "-", meth.db3$POS), meth.db3[,4:ncol(meth.db3)]))
colnames(meth.db4)[1] <- "Site"
totcov.db4 <- as.data.table(cbind(paste0(totcov.db3$`#CHROM`, "-", totcov.db3$POS), totcov.db3[,4:ncol(totcov.db3)]))
colnames(totcov.db4)[1] <- "Site"
totcov.db5 <- totcov.db4[totcov.db4$Site %in% meth.db4$Site,]
nrow(meth.db4)
nrow(totcov.db5)
length(totcov.db5$Site %in% meth.db4$Site)
write.table(meth.db4, file = "fivex.macau.meth.txt", sep = " ", quote = FALSE, row.names = FALSE)
write.table(totcov.db5, file = "fivex.macau.totalcov.txt", sep = " ", quote = FALSE, row.names = FALSE)
system("head fivex.macau.meth.txt")
system("head fivex.macau.totalcov.txt")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
system("/home/shared/macau/macau -g fivex.macau.meth.txt -t fivex.macau.totalcov.txt -p Predictor.csv -k day135-relate-finished.csv -o threex")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
result_assoc <- read_delim("~/Documents/Day135/Day135Cutoff/macau/output/sevenx.assoc.txt", "\t", escape_double = FALSE, trim_ws = TRUE)
sig.results <- result_assoc[result_assoc$pvalue <= 0.05,]
for(i in 1:nrow(sig.results)) {
temp <- strsplit(sig.results$id[i], "-")
sig.results[i,13] <- temp[[1]][1]
sig.results[i,14] <- temp[[1]][2]
}
colnames(sig.results)[c(13,14)] <- c("Scaffold", "Loc")
bed.test <- as.data.frame(cbind(sig.results[,13], (sig.results[,14]), (sig.results[,14]), sig.results$beta))
colnames(bed.test)[4] <- "beta"
write.table(bed.test, file = "fivex.DiffMethRegions.bed", sep = "\t", quote = FALSE, col.names = FALSE, row.names = FALSE)
setwd("~/Documents/Day135/Day135Cutoff/")
list.files(path = ".")
library(data.table)
library(readr)
DiffMethRegions <- read_delim("~/Documents/Day135/Day135Cutoff/macau/fivex.DiffMethRegions.bed",
"\t", escape_double = FALSE, col_names = FALSE,
trim_ws = TRUE)
DiffMethRegions$Loc <- paste0(DiffMethRegions$X1, "-", DiffMethRegions$X2)
head(DiffMethRegions)
sample.files <- list.files(path = "~/Documents/Day135/Day135Cutoff/", pattern = "*.bedgraph")
print(sample.files)
EPI_103_percmeth_bedgraph <- read_delim("~/Documents/Day135/Day135Cutoff/EPI-151-percmeth.bedgraph",
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
EPI_103_percmeth_bedgraph <- as.data.table(EPI_103_percmeth_bedgraph)
head(EPI_103_percmeth_bedgraph)
print(EPI_103_percmeth_bedgraph[7,])
EPI_103_DMRs <- EPI_103_percmeth_bedgraph[EPI_103_percmeth_bedgraph$X1 %in% DiffMethRegions$X1,]
EPI_103_DMRs$Loc <- paste0(EPI_103_DMRs$X1, "-", EPI_103_DMRs$X2)
head(EPI_103_DMRs)
EPI_103_DMRs <- EPI_103_DMRs[EPI_103_DMRs$Loc %in% DiffMethRegions$Loc,]
head(EPI_103_DMRs)
EPI_DMRs <- as.data.table(cbind(EPI_103_DMRs$Loc, EPI_103_DMRs$X4))
colnames(EPI_DMRs)[1] <- "DMRLoc"
colnames(EPI_DMRs)[2] <- "EPI_151"
head(EPI_DMRs)
for(i in 2:length(sample.files)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/", sample.files[i]),
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
temp <- as.data.table(temp)
temp_DMRs <- temp[temp$X1 %in% DiffMethRegions$X1,]
temp_DMRs$Loc <- paste0(temp_DMRs$X1, "-", temp_DMRs$X2)
temp_DMRs <- temp_DMRs[temp_DMRs$Loc %in% DiffMethRegions$Loc,]
EPI_DMRs$temp <- temp_DMRs$X4
colnames(EPI_DMRs)[ncol(EPI_DMRs)] <- substr(sample.files[i], 1, 7)
}
head(EPI_DMRs)
## This is here because for osme reason EPI_103 gets brught in as characters as opposed to doubles. Need to figure out why, but this fixes it for now
EPI_DMRs$EPI_151 <- as.numeric(EPI_DMRs$EPI_151)
treatment.means <- as.data.frame(EPI_DMRs$DMRLoc)
treatment.means$Ambient <- apply(cbind(EPI_DMRs$`EPI-151`, EPI_DMRs$`EPI-152`, EPI_DMRs$`EPI-153`, EPI_DMRs$`EPI-154`) ,MARGIN = 1, FUN = mean)
treatment.means$Low <- apply(cbind(EPI_DMRs$`EPI-159`, EPI_DMRs$`EPI-160`, EPI_DMRs$`EPI-161`, EPI_DMRs$`EPI-162`) ,MARGIN = 1, FUN = mean)
treatment.means$SuperLow <- apply(cbind(EPI_DMRs$`EPI-167`, EPI_DMRs$`EPI-168`, EPI_DMRs$`EPI-169`, EPI_DMRs$`EPI-170`) ,MARGIN = 1, FUN = mean)
head(treatment.means)
for(i in 1:nrow(treatment.means)) {
boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,4], EPI_DMRs[i,5])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
boxplot(t(cbind(EPI_DMRs[i,10], EPI_DMRs[i,11], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
axis(side = 1, at = 2, labels = "Low")
axis(side = 1, at = 3, labels = "Super Low")
title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
}
pdf(file = "fivex-DMR-Box-Plots.pdf")
for(i in 1:nrow(treatment.means)) {
boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,10], EPI_DMRs[i,11])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
boxplot(t(cbind(EPI_DMRs[i,4], EPI_DMRs[i,5], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
axis(side = 1, at = 2, labels = "Low")
axis(side = 1, at = 3, labels = "Super Low")
title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
}
dev.off()
3x Coverage Code
setwd("~/Documents/Day135/Day135Cutoff/")
samples.vec <- c("EPI-151", "EPI-152", "EPI-153", "EPI-154", "EPI-159", "EPI-160", "EPI-161", "EPI-162", "EPI-167", "EPI-168", "EPI-169", "EPI-170")
library(readr)
setwd("~/Documents/Day135/Day135Cutoff/CGoutput")
data <- list.files(path = ".", pattern = "*.output")
print(data)
db <- read_delim("~/Documents/Day135/Day135Cutoff/CGoutput/EPI-151_CG.output", "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
db <- as.data.table(db)
db$EPI103Meth <- rowSums(cbind(db[,4], db[,7]), na.rm = TRUE)
db$EPI103TotCov <- rowSums(cbind(db[,5], db[,8]), na.rm = TRUE)
meth.db <- db[,c(1,2,3,10)]
totcov.db <- db[,c(1,2,3,11)]
for(i in 2:length(data)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/CGoutput/", data[i]), "\t", escape_double = FALSE, trim_ws = TRUE, na = ".")
temp <- as.data.table(temp)
temp$Meth <- rowSums(cbind(temp[,4], temp[,7]), na.rm = TRUE)
temp$TotCov <- rowSums(cbind(temp[,5], temp[,8]), na.rm = TRUE)
meth.db <- merge(meth.db, temp[,c(1,2,3,10)], by = names(meth.db[,c(1,2,3)]), all = TRUE)
colnames(meth.db)[ncol(meth.db)] <- paste0(substr(data[i], 1, 7), "Meth")
meth.db <- as.data.table(meth.db)
totcov.db <- merge(totcov.db, temp[,c(1,2,3,11)], by = names(totcov.db[,c(1,2,3)]), all = TRUE)
colnames(totcov.db)[ncol(totcov.db)] <- paste0(substr(data[i], 1, 7), "TotCov")
totcov.db <- as.data.table(totcov.db)
}
setwd("~/Documents/Day135/Day135Cutoff/macau")
meth.db2 <- meth.db[complete.cases(meth.db[,c(4:15)]),]
totcov.db2 <- totcov.db[complete.cases(totcov.db[,c(4:15)]),]
meth.db3 <- meth.db2[apply(meth.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 3)), ]
totcov.db3 <- totcov.db2[apply(totcov.db2[, c(4:15)], MARGIN = 1, function(x) all(x > 3)), ]
meth.db4 <- as.data.table(cbind(paste0(meth.db3$`#CHROM`, "-", meth.db3$POS), meth.db3[,4:ncol(meth.db3)]))
colnames(meth.db4)[1] <- "Site"
totcov.db4 <- as.data.table(cbind(paste0(totcov.db3$`#CHROM`, "-", totcov.db3$POS), totcov.db3[,4:ncol(totcov.db3)]))
colnames(totcov.db4)[1] <- "Site"
totcov.db5 <- totcov.db4[totcov.db4$Site %in% meth.db4$Site,]
nrow(meth.db4)
nrow(totcov.db5)
length(totcov.db5$Site %in% meth.db4$Site)
write.table(meth.db4, file = "threex.macau.meth.txt", sep = " ", quote = FALSE, row.names = FALSE)
write.table(totcov.db5, file = "threex.macau.totalcov.txt", sep = " ", quote = FALSE, row.names = FALSE)
system("head threex.macau.meth.txt")
system("head threex.macau.totalcov.txt")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
system("/home/shared/macau/macau -g threex.macau.meth.txt -t threex.macau.totalcov.txt -p Predictor.csv -k day135-relate-finished.csv -o threex")
setwd("~/Documents/Day135/Day135Cutoff/macau/")
threex_assoc <- read_delim("~/Documents/Day135/Day135Cutoff/macau/output/threex.assoc.txt",
"\t", escape_double = FALSE, trim_ws = TRUE)
sig.results <- threex_assoc[threex_assoc$pvalue <= 0.05,]
for(i in 1:nrow(sig.results)) {
temp <- strsplit(sig.results$id[i], "-")
sig.results[i,13] <- temp[[1]][1]
sig.results[i,14] <- temp[[1]][2]
}
colnames(sig.results)[c(13,14)] <- c("Scaffold", "Loc")
bed.test <- as.data.frame(cbind(sig.results[,13], (sig.results[,14]), (sig.results[,14]), sig.results$beta))
colnames(bed.test)[4] <- "beta"
write.table(bed.test, file = "threex.DiffMethRegions.bed", sep = ",", quote = FALSE, col.names = FALSE, row.names = FALSE)
setwd("~/Documents/Day135/Day135Cutoff/")
list.files(path = ".")
library(data.table)
library(readr)
DiffMethRegions <- read_delim("~/Documents/Day135/Day135Cutoff/threex.DiffMethRegions.bed",
",", escape_double = FALSE, col_names = FALSE,
trim_ws = TRUE)
DiffMethRegions$Loc <- paste0(DiffMethRegions$X1, "-", DiffMethRegions$X2)
head(DiffMethRegions)
sample.files <- list.files(path = "~/Documents/Day135/Day135Cutoff/", pattern = "*.bedgraph")
print(sample.files)
EPI_103_percmeth_bedgraph <- read_delim("~/Documents/Day135/Day135Cutoff/EPI-151-percmeth.bedgraph",
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
EPI_103_percmeth_bedgraph <- as.data.table(EPI_103_percmeth_bedgraph)
head(EPI_103_percmeth_bedgraph)
print(EPI_103_percmeth_bedgraph[7,])
EPI_103_DMRs <- EPI_103_percmeth_bedgraph[EPI_103_percmeth_bedgraph$X1 %in% DiffMethRegions$X1,]
EPI_103_DMRs$Loc <- paste0(EPI_103_DMRs$X1, "-", EPI_103_DMRs$X2)
head(EPI_103_DMRs)
EPI_103_DMRs <- EPI_103_DMRs[EPI_103_DMRs$Loc %in% DiffMethRegions$Loc,]
head(EPI_103_DMRs)
EPI_DMRs <- as.data.table(cbind(EPI_103_DMRs$Loc, EPI_103_DMRs$X4))
colnames(EPI_DMRs)[1] <- "DMRLoc"
colnames(EPI_DMRs)[2] <- "EPI_151"
head(EPI_DMRs)
for(i in 2:length(sample.files)) {
temp <- read_delim(paste0("~/Documents/Day135/Day135Cutoff/", sample.files[i]),
"\t", escape_double = FALSE, col_names = FALSE,
col_types = cols(X4 = col_double()),
trim_ws = TRUE)
temp <- as.data.table(temp)
temp_DMRs <- temp[temp$X1 %in% DiffMethRegions$X1,]
temp_DMRs$Loc <- paste0(temp_DMRs$X1, "-", temp_DMRs$X2)
temp_DMRs <- temp_DMRs[temp_DMRs$Loc %in% DiffMethRegions$Loc,]
EPI_DMRs$temp <- temp_DMRs$X4
colnames(EPI_DMRs)[ncol(EPI_DMRs)] <- substr(sample.files[i], 1, 7)
}
head(EPI_DMRs)
## This is here because for osme reason EPI_103 gets brught in as characters as opposed to doubles. Need to figure out why, but this fixes it for now
EPI_DMRs$EPI_151 <- as.numeric(EPI_DMRs$EPI_151)
treatment.means <- as.data.frame(EPI_DMRs$DMRLoc)
treatment.means$Ambient <- apply(cbind(EPI_DMRs$`EPI-151`, EPI_DMRs$`EPI-152`, EPI_DMRs$`EPI-153`, EPI_DMRs$`EPI-154`) ,MARGIN = 1, FUN = mean)
treatment.means$Low <- apply(cbind(EPI_DMRs$`EPI-159`, EPI_DMRs$`EPI-160`, EPI_DMRs$`EPI-161`, EPI_DMRs$`EPI-162`) ,MARGIN = 1, FUN = mean)
treatment.means$SuperLow <- apply(cbind(EPI_DMRs$`EPI-167`, EPI_DMRs$`EPI-168`, EPI_DMRs$`EPI-169`, EPI_DMRs$`EPI-170`) ,MARGIN = 1, FUN = mean)
head(treatment.means)
# for(i in 1:nrow(treatment.means)) {
#
#
# boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,4], EPI_DMRs[i,5])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
#
# boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
#
# boxplot(t(cbind(EPI_DMRs[i,10], EPI_DMRs[i,11], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
#
# axis(side = 1, at = 2, labels = "Low")
# axis(side = 1, at = 3, labels = "Super Low")
#
# title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
#
#
# }
pdf(file = "threex-DMR-Box-Plots.pdf")
for(i in 1:nrow(treatment.means)) {
boxplot(t(cbind(EPI_DMRs[i,6], EPI_DMRs[i,7], EPI_DMRs[i,10], EPI_DMRs[i,11])),xlim = c(0.5, 3.5), ylim = c(min(EPI_DMRs[i,2:13]), max(EPI_DMRs[i,2:13])), boxfill = "blue", names = "Ambient", show.names = TRUE, ylab = "Proportion of reads methylated")
boxplot(t(cbind(EPI_DMRs[i,2], EPI_DMRs[i,3], EPI_DMRs[i,8], EPI_DMRs[i,9])), xaxt = "n", add = TRUE, at = 2, boxfill = "green")
boxplot(t(cbind(EPI_DMRs[i,4], EPI_DMRs[i,5], EPI_DMRs[i,12], EPI_DMRs[i,13])), xaxt = "n", add = TRUE, at = 3, boxfill = "red")
axis(side = 1, at = 2, labels = "Low")
axis(side = 1, at = 3, labels = "Super Low")
title(paste0("Proportion of Methylated reads for DMR \n located at ", EPI_DMRs[i,1]))
}
dev.off()
Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
LS0tCnRpdGxlOiAiRGF5IDEzNSBjdXRvZmYgZGlmZmVyZW5jZXMuIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpJJ20gbG9va2luZyBhdCBkaWZmZXJlbmNlcyBpbiBETVJzIHdoZW4gd2UgY2hhbmdlIHRoZSBjb3ZlcmFnZSB2YWx1ZSBjdXRvZmZzIGZvciB0aGUgRGF5IDEzNSBzYW1wbGVzLiBJIGRvbid0IHRoaW5rIEknbSBnb2luZyB0byBhY3R1YWxseSBydW4gdGhpcyBub3RlYm9vaywgYXMgaXQncyBsYXJnZWx5IGN1dCBhbmQgcGFzdGUgY29kZSBmcm9tIGEgcHJldmlvdXMgYW5hbHlzaXMuIFRoZSBvbmx5IHJlYWwgY2hhbmdlcyBhcmUgb3V0cHV0IGZpbGUgbmFtZXMsIHRvIGF2b2lkIG92ZXJ3cml0aW5nIHJlc3VsdHMgYW5kIHRoZSBhY3R1YWwgY3V0b2ZmIHZhbHVlcy4KCkN1dG9mZiB2YWx1ZXMgYXJlIGxvY2F0ZWQgaW4gbGluZXMgNjMgYW5kIDY0IG9mIHRoZSBhbmFseXNpcyBjb2RlLCB0aGF0IGxvb2sgbGlrZSBhbmQgYXJlIGxvY2F0ZWQgaW4gdGhlIGFsbCh4ID4gMykgc2VjdGlvbi4gQ2hhbmdpbmcgdGhlIG51bWVyaWMgdmFsdWUgY2hhbmdlcyB0aGUgY3V0b2ZmLiAKCgoKYGBge3J9CgptZXRoLmRiMyA8LSBtZXRoLmRiMlthcHBseShtZXRoLmRiMlssIGMoNDoxNSldLCBNQVJHSU4gPSAxLCBmdW5jdGlvbih4KSBhbGwoeCA+IDMpKSwgXQp0b3Rjb3YuZGIzIDwtIHRvdGNvdi5kYjJbYXBwbHkodG90Y292LmRiMlssIGMoNDoxNSldLCBNQVJHSU4gPSAxLCBmdW5jdGlvbih4KSBhbGwoeCA+IDMpKSwgXQoKYGBgCgoKVGhlIHRoaW5nIHlvdSBjYW1lIGhlcmUgZm9yISBUaGUgZGlmZmVyZW50IG51bWJlciBvZiBETVJzIGZvdW5kIGF0IGVhY2ggY3V0b2ZmLiBJJ2xsIHVwbG9hZCB0aGUgZ3JhcGhzIHRvIHNjYXBoYXBvZGEgYWxzbwoKfCBDb3ZlcmFnZSBDdXRvZmYgfCAjIG9mIERNUnMgRm9yIERheSAxMzUgU2FtcGxlcyB8CnwtLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8IDN4ICAgICAgICAgICAgICB8IDcwOSAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCA1eCAgICAgICAgICAgICAgfCAzMDQgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgN3ggICAgICAgICAgICAgIHwgMTM2ICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IDEweCAgICAgICAgICAgICB8IDYzICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKCiAgCiAgCiAgCiAgCgoKTGV0IHRoZSBjdXR0aW5nIGFuZCBwYXN0aW5nIGJlZ2luISBJJ2xsIGdvIDd4LCA1eCwgYW5kIDN4IGluIG9yZGVyLgoKKioqCjd4IENvdmVyYWdlIENvZGUgIAotLS0KICAKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi8iKQoKc2FtcGxlcy52ZWMgPC0gYygiRVBJLTE1MSIsICJFUEktMTUyIiwgIkVQSS0xNTMiLCAiRVBJLTE1NCIsICJFUEktMTU5IiwgIkVQSS0xNjAiLCAiRVBJLTE2MSIsICJFUEktMTYyIiwgIkVQSS0xNjciLCAiRVBJLTE2OCIsICJFUEktMTY5IiwgIkVQSS0xNzAiKQoKYGBgCgoKYGBge3J9CgpsaWJyYXJ5KHJlYWRyKQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9DR291dHB1dCIpCgpkYXRhIDwtIGxpc3QuZmlsZXMocGF0aCA9ICIuIiwgcGF0dGVybiA9ICIqLm91dHB1dCIpCnByaW50KGRhdGEpCgpkYiA8LSByZWFkX2RlbGltKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0NHb3V0cHV0L0VQSS0xNTFfQ0cub3V0cHV0IiwgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCB0cmltX3dzID0gVFJVRSwgbmEgPSAiLiIpCgpkYiA8LSBhcy5kYXRhLnRhYmxlKGRiKQoKZGIkRVBJMTAzTWV0aCA8LSByb3dTdW1zKGNiaW5kKGRiWyw0XSwgZGJbLDddKSwgbmEucm0gPSBUUlVFKQpkYiRFUEkxMDNUb3RDb3YgPC0gcm93U3VtcyhjYmluZChkYlssNV0sIGRiWyw4XSksIG5hLnJtID0gVFJVRSkKbWV0aC5kYiA8LSBkYlssYygxLDIsMywxMCldCnRvdGNvdi5kYiA8LSBkYlssYygxLDIsMywxMSldCgpmb3IoaSBpbiAyOmxlbmd0aChkYXRhKSkgICB7CiAgCiAgdGVtcCA8LSByZWFkX2RlbGltKHBhc3RlMCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9DR291dHB1dC8iLCBkYXRhW2ldKSwgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCB0cmltX3dzID0gVFJVRSwgbmEgPSAiLiIpCiAgdGVtcCA8LSBhcy5kYXRhLnRhYmxlKHRlbXApCiAgdGVtcCRNZXRoIDwtIHJvd1N1bXMoY2JpbmQodGVtcFssNF0sIHRlbXBbLDddKSwgbmEucm0gPSBUUlVFKQogIHRlbXAkVG90Q292IDwtIHJvd1N1bXMoY2JpbmQodGVtcFssNV0sIHRlbXBbLDhdKSwgbmEucm0gPSBUUlVFKQoKICBtZXRoLmRiIDwtIG1lcmdlKG1ldGguZGIsIHRlbXBbLGMoMSwyLDMsMTApXSwgYnkgPSBuYW1lcyhtZXRoLmRiWyxjKDEsMiwzKV0pLCBhbGwgPSBUUlVFKQogIGNvbG5hbWVzKG1ldGguZGIpW25jb2wobWV0aC5kYildIDwtIHBhc3RlMChzdWJzdHIoZGF0YVtpXSwgMSwgNyksICJNZXRoIikKICBtZXRoLmRiIDwtIGFzLmRhdGEudGFibGUobWV0aC5kYikKICAKICB0b3Rjb3YuZGIgPC0gbWVyZ2UodG90Y292LmRiLCB0ZW1wWyxjKDEsMiwzLDExKV0sIGJ5ID0gbmFtZXModG90Y292LmRiWyxjKDEsMiwzKV0pLCBhbGwgPSBUUlVFKQogIGNvbG5hbWVzKHRvdGNvdi5kYilbbmNvbCh0b3Rjb3YuZGIpXSA8LSBwYXN0ZTAoc3Vic3RyKGRhdGFbaV0sIDEsIDcpLCAiVG90Q292IikKICB0b3Rjb3YuZGIgPC0gYXMuZGF0YS50YWJsZSh0b3Rjb3YuZGIpCn0KCgoKYGBgCgpgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUiKQptZXRoLmRiMiA8LSBtZXRoLmRiW2NvbXBsZXRlLmNhc2VzKG1ldGguZGJbLGMoNDoxNSldKSxdCgp0b3Rjb3YuZGIyIDwtIHRvdGNvdi5kYltjb21wbGV0ZS5jYXNlcyh0b3Rjb3YuZGJbLGMoNDoxNSldKSxdCgptZXRoLmRiMyA8LSBtZXRoLmRiMlthcHBseShtZXRoLmRiMlssIGMoNDoxNSldLCBNQVJHSU4gPSAxLCBmdW5jdGlvbih4KSBhbGwoeCA+IDcpKSwgXQp0b3Rjb3YuZGIzIDwtIHRvdGNvdi5kYjJbYXBwbHkodG90Y292LmRiMlssIGMoNDoxNSldLCBNQVJHSU4gPSAxLCBmdW5jdGlvbih4KSBhbGwoeCA+IDcpKSwgXQoKbWV0aC5kYjQgPC0gYXMuZGF0YS50YWJsZShjYmluZChwYXN0ZTAobWV0aC5kYjMkYCNDSFJPTWAsICItIiwgbWV0aC5kYjMkUE9TKSwgbWV0aC5kYjNbLDQ6bmNvbChtZXRoLmRiMyldKSkKY29sbmFtZXMobWV0aC5kYjQpWzFdIDwtICJTaXRlIgp0b3Rjb3YuZGI0IDwtIGFzLmRhdGEudGFibGUoY2JpbmQocGFzdGUwKHRvdGNvdi5kYjMkYCNDSFJPTWAsICItIiwgdG90Y292LmRiMyRQT1MpLCB0b3Rjb3YuZGIzWyw0Om5jb2wodG90Y292LmRiMyldKSkKY29sbmFtZXModG90Y292LmRiNClbMV0gPC0gIlNpdGUiCgp0b3Rjb3YuZGI1IDwtIHRvdGNvdi5kYjRbdG90Y292LmRiNCRTaXRlICVpbiUgbWV0aC5kYjQkU2l0ZSxdCgpucm93KG1ldGguZGI0KQpucm93KHRvdGNvdi5kYjUpCmxlbmd0aCh0b3Rjb3YuZGI1JFNpdGUgJWluJSBtZXRoLmRiNCRTaXRlKQoKd3JpdGUudGFibGUobWV0aC5kYjQsIGZpbGUgPSAic2V2ZW54Lm1hY2F1Lm1ldGgudHh0Iiwgc2VwID0gIiAiLCBxdW90ZSA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUudGFibGUodG90Y292LmRiNSwgZmlsZSA9ICJzZXZlbngubWFjYXUudG90YWxjb3YudHh0Iiwgc2VwID0gIiAiLCBxdW90ZSA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSkKCnN5c3RlbSgiaGVhZCBtYWNhdS5tZXRoLnR4dCIpCnN5c3RlbSgiaGVhZCBtYWNhdS50b3RhbGNvdi50eHQiKQpgYGAKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS8iKQpzeXN0ZW0oIi9ob21lL3NoYXJlZC9tYWNhdS9tYWNhdSAtZyBzZXZlbngubWFjYXUubWV0aC5jc3YgLXQgc2V2ZW54Lm1hY2F1LnRvdGFsY292LmNzdiAtcCBQcmVkaWN0b3IuY3N2IC1rIGRheTEzNS1yZWxhdGUtZmluaXNoZWQuY3N2IC1vIHNldmVueCIpCgpgYGAKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS8iKQpyZXN1bHRfYXNzb2MgPC0gcmVhZF9kZWxpbSgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS9vdXRwdXQvc2V2ZW54LmFzc29jLnR4dCIsICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgdHJpbV93cyA9IFRSVUUpCgpzaWcucmVzdWx0cyA8LSByZXN1bHRfYXNzb2NbcmVzdWx0X2Fzc29jJHB2YWx1ZSA8PSAwLjA1LF0KCiBmb3IoaSBpbiAxOm5yb3coc2lnLnJlc3VsdHMpKSAgIHsKICAgdGVtcCA8LSBzdHJzcGxpdChzaWcucmVzdWx0cyRpZFtpXSwgIi0iKSAKICAgc2lnLnJlc3VsdHNbaSwxM10gPC0gdGVtcFtbMV1dWzFdCiAgIHNpZy5yZXN1bHRzW2ksMTRdIDwtIHRlbXBbWzFdXVsyXQogICAKIH0KIAogY29sbmFtZXMoc2lnLnJlc3VsdHMpW2MoMTMsMTQpXSA8LSBjKCJTY2FmZm9sZCIsICJMb2MiKQogCiBiZWQudGVzdCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKHNpZy5yZXN1bHRzWywxM10sIChzaWcucmVzdWx0c1ssMTRdKSwgKHNpZy5yZXN1bHRzWywxNF0pLCBzaWcucmVzdWx0cyRiZXRhKSkKIGNvbG5hbWVzKGJlZC50ZXN0KVs0XSA8LSAiYmV0YSIKIHdyaXRlLnRhYmxlKGJlZC50ZXN0LCBmaWxlID0gInNldmVueC5EaWZmTWV0aFJlZ2lvbnMuYmVkIiwgc2VwID0gIlx0IiwgcXVvdGUgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQoKYGBgCgpgYGB7cn0KIHNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIpCiAKIGxpc3QuZmlsZXMocGF0aCA9ICIuIikKIAoKYGBgCgpgYGB7cn0KIGxpYnJhcnkoZGF0YS50YWJsZSkKIGxpYnJhcnkocmVhZHIpCiBEaWZmTWV0aFJlZ2lvbnMgPC0gcmVhZF9kZWxpbSgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS9zZXZlbnguRGlmZk1ldGhSZWdpb25zLmJlZCIsIAogICAgICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgY29sX25hbWVzID0gRkFMU0UsIAogICAgIHRyaW1fd3MgPSBUUlVFKQogCiBEaWZmTWV0aFJlZ2lvbnMkTG9jIDwtIHBhc3RlMChEaWZmTWV0aFJlZ2lvbnMkWDEsICItIiwgRGlmZk1ldGhSZWdpb25zJFgyKQogCiBoZWFkKERpZmZNZXRoUmVnaW9ucykKIAogc2FtcGxlLmZpbGVzIDwtIGxpc3QuZmlsZXMocGF0aCA9ICJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIsIHBhdHRlcm4gPSAiKi5iZWRncmFwaCIpCiAKIHByaW50KHNhbXBsZS5maWxlcykKCmBgYAoKYGBge3J9CgogRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaCA8LSByZWFkX2RlbGltKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0VQSS0xNTEtcGVyY21ldGguYmVkZ3JhcGgiLCAKICAgICAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIGNvbF9uYW1lcyA9IEZBTFNFLCAKICAgICBjb2xfdHlwZXMgPSBjb2xzKFg0ID0gY29sX2RvdWJsZSgpKSwgCiAgICAgdHJpbV93cyA9IFRSVUUpCiAKIEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGggPC0gYXMuZGF0YS50YWJsZShFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoKQogCiBoZWFkKEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGgpCiAKIHByaW50KEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGhbNyxdKQoKYGBgCgpgYGB7cn0KCkVQSV8xMDNfRE1ScyA8LSBFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoW0VQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGgkWDEgJWluJSBEaWZmTWV0aFJlZ2lvbnMkWDEsXQoKCkVQSV8xMDNfRE1ScyRMb2MgPC0gcGFzdGUwKEVQSV8xMDNfRE1ScyRYMSwgIi0iLCBFUElfMTAzX0RNUnMkWDIpCgoKaGVhZChFUElfMTAzX0RNUnMpCgpFUElfMTAzX0RNUnMgPC0gRVBJXzEwM19ETVJzW0VQSV8xMDNfRE1ScyRMb2MgJWluJSBEaWZmTWV0aFJlZ2lvbnMkTG9jLF0KCmhlYWQoRVBJXzEwM19ETVJzKQoKRVBJX0RNUnMgPC0gYXMuZGF0YS50YWJsZShjYmluZChFUElfMTAzX0RNUnMkTG9jLCBFUElfMTAzX0RNUnMkWDQpKQoKCgpjb2xuYW1lcyhFUElfRE1ScylbMV0gPC0gIkRNUkxvYyIKY29sbmFtZXMoRVBJX0RNUnMpWzJdIDwtICJFUElfMTUxIgpoZWFkKEVQSV9ETVJzKQoKYGBgCgpgYGB7cn0KCmZvcihpIGluIDI6bGVuZ3RoKHNhbXBsZS5maWxlcykpICAgewoKICB0ZW1wIDwtIHJlYWRfZGVsaW0ocGFzdGUwKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIsIHNhbXBsZS5maWxlc1tpXSksCiAgICAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIGNvbF9uYW1lcyA9IEZBTFNFLAogICAgY29sX3R5cGVzID0gY29scyhYNCA9IGNvbF9kb3VibGUoKSksCiAgICB0cmltX3dzID0gVFJVRSkKCiAgdGVtcCA8LSBhcy5kYXRhLnRhYmxlKHRlbXApCgogIHRlbXBfRE1ScyA8LSB0ZW1wW3RlbXAkWDEgJWluJSBEaWZmTWV0aFJlZ2lvbnMkWDEsXQoKCiAgdGVtcF9ETVJzJExvYyA8LSBwYXN0ZTAodGVtcF9ETVJzJFgxLCAiLSIsIHRlbXBfRE1ScyRYMikKCgogIHRlbXBfRE1ScyA8LSB0ZW1wX0RNUnNbdGVtcF9ETVJzJExvYyAlaW4lIERpZmZNZXRoUmVnaW9ucyRMb2MsXQoKICBFUElfRE1ScyR0ZW1wIDwtIHRlbXBfRE1ScyRYNAoKICBjb2xuYW1lcyhFUElfRE1ScylbbmNvbChFUElfRE1ScyldIDwtIHN1YnN0cihzYW1wbGUuZmlsZXNbaV0sIDEsIDcpCgoKfQoKaGVhZChFUElfRE1ScykKCiMjIFRoaXMgaXMgaGVyZSBiZWNhdXNlIGZvciBvc21lIHJlYXNvbiBFUElfMTAzIGdldHMgYnJ1Z2h0IGluIGFzIGNoYXJhY3RlcnMgYXMgb3Bwb3NlZCB0byBkb3VibGVzLiBOZWVkIHRvIGZpZ3VyZSBvdXQgd2h5LCBidXQgdGhpcyBmaXhlcyBpdCBmb3Igbm93CkVQSV9ETVJzJEVQSV8xNTEgPC0gYXMubnVtZXJpYyhFUElfRE1ScyRFUElfMTUxKQoKYGBgCgpgYGB7cn0KCnRyZWF0bWVudC5tZWFucyA8LSBhcy5kYXRhLmZyYW1lKEVQSV9ETVJzJERNUkxvYykKCnRyZWF0bWVudC5tZWFucyRBbWJpZW50IDwtIGFwcGx5KGNiaW5kKEVQSV9ETVJzJGBFUEktMTUxYCwgRVBJX0RNUnMkYEVQSS0xNTJgLCBFUElfRE1ScyRgRVBJLTE1M2AsIEVQSV9ETVJzJGBFUEktMTU0YCkgLE1BUkdJTiA9IDEsIEZVTiA9IG1lYW4pCgp0cmVhdG1lbnQubWVhbnMkTG93IDwtIGFwcGx5KGNiaW5kKEVQSV9ETVJzJGBFUEktMTU5YCwgRVBJX0RNUnMkYEVQSS0xNjBgLCBFUElfRE1ScyRgRVBJLTE2MWAsIEVQSV9ETVJzJGBFUEktMTYyYCkgLE1BUkdJTiA9IDEsIEZVTiA9IG1lYW4pCgp0cmVhdG1lbnQubWVhbnMkU3VwZXJMb3cgPC0gYXBwbHkoY2JpbmQoRVBJX0RNUnMkYEVQSS0xNjdgLCBFUElfRE1ScyRgRVBJLTE2OGAsIEVQSV9ETVJzJGBFUEktMTY5YCwgRVBJX0RNUnMkYEVQSS0xNzBgKSAsTUFSR0lOID0gMSwgRlVOID0gbWVhbikKCmhlYWQodHJlYXRtZW50Lm1lYW5zKQpgYGAKCmBgYHtyfQoKCgogZm9yKGkgaW4gMTpucm93KHRyZWF0bWVudC5tZWFucykpICAgewogICAKCiAgYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksMl0sIEVQSV9ETVJzW2ksM10sIEVQSV9ETVJzW2ksNF0sIEVQSV9ETVJzW2ksNV0pKSx4bGltID0gYygwLjUsIDMuNSksIHlsaW0gPSBjKG1pbihFUElfRE1Sc1tpLDI6MTNdKSwgbWF4KEVQSV9ETVJzW2ksMjoxM10pKSwgYm94ZmlsbCA9ICJibHVlIiwgbmFtZXMgPSAiQW1iaWVudCIsIHNob3cubmFtZXMgPSBUUlVFLCB5bGFiID0gIlByb3BvcnRpb24gb2YgcmVhZHMgbWV0aHlsYXRlZCIpCgpib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSw2XSwgRVBJX0RNUnNbaSw3XSwgRVBJX0RNUnNbaSw4XSwgRVBJX0RNUnNbaSw5XSkpLCB4YXh0ID0gIm4iLCBhZGQgPSBUUlVFLCBhdCA9IDIsIGJveGZpbGwgPSAiZ3JlZW4iKQoKYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksMTBdLCBFUElfRE1Sc1tpLDExXSwgRVBJX0RNUnNbaSwxMl0sIEVQSV9ETVJzW2ksMTNdKSksIHhheHQgPSAibiIsIGFkZCA9IFRSVUUsIGF0ID0gMywgYm94ZmlsbCA9ICJyZWQiKQoKYXhpcyhzaWRlID0gMSwgYXQgPSAyLCBsYWJlbHMgPSAiTG93IikKYXhpcyhzaWRlID0gMSwgYXQgPSAzLCBsYWJlbHMgPSAiU3VwZXIgTG93IikKCnRpdGxlKHBhc3RlMCgiUHJvcG9ydGlvbiBvZiBNZXRoeWxhdGVkIHJlYWRzIGZvciBETVIgXG4gbG9jYXRlZCBhdCAiLCBFUElfRE1Sc1tpLDFdKSkKCgp9CgoKcGRmKGZpbGUgPSAic2V2ZW54LURNUi1Cb3gtUGxvdHMucGRmIikKCmZvcihpIGluIDE6bnJvdyh0cmVhdG1lbnQubWVhbnMpKSAgIHsKCgogIGJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDZdLCBFUElfRE1Sc1tpLDddLCBFUElfRE1Sc1tpLDEwXSwgRVBJX0RNUnNbaSwxMV0pKSx4bGltID0gYygwLjUsIDMuNSksIHlsaW0gPSBjKG1pbihFUElfRE1Sc1tpLDI6MTNdKSwgbWF4KEVQSV9ETVJzW2ksMjoxM10pKSwgYm94ZmlsbCA9ICJibHVlIiwgbmFtZXMgPSAiQW1iaWVudCIsIHNob3cubmFtZXMgPSBUUlVFLCB5bGFiID0gIlByb3BvcnRpb24gb2YgcmVhZHMgbWV0aHlsYXRlZCIpCgpib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSwyXSwgRVBJX0RNUnNbaSwzXSwgRVBJX0RNUnNbaSw4XSwgRVBJX0RNUnNbaSw5XSkpLCB4YXh0ID0gIm4iLCBhZGQgPSBUUlVFLCBhdCA9IDIsIGJveGZpbGwgPSAiZ3JlZW4iKQoKYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksNF0sIEVQSV9ETVJzW2ksNV0sIEVQSV9ETVJzW2ksMTJdLCBFUElfRE1Sc1tpLDEzXSkpLCB4YXh0ID0gIm4iLCBhZGQgPSBUUlVFLCBhdCA9IDMsIGJveGZpbGwgPSAicmVkIikKCmF4aXMoc2lkZSA9IDEsIGF0ID0gMiwgbGFiZWxzID0gIkxvdyIpCmF4aXMoc2lkZSA9IDEsIGF0ID0gMywgbGFiZWxzID0gIlN1cGVyIExvdyIpCgp0aXRsZShwYXN0ZTAoIlByb3BvcnRpb24gb2YgTWV0aHlsYXRlZCByZWFkcyBmb3IgRE1SIFxuIGxvY2F0ZWQgYXQgIiwgRVBJX0RNUnNbaSwxXSkpCgoKfQoKZGV2Lm9mZigpCgpgYGAKCgoqKioKNXggQ292ZXJhZ2UgQ29kZSAgCi0tLQoKYGBge3J9CnNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIpCgpzYW1wbGVzLnZlYyA8LSBjKCJFUEktMTUxIiwgIkVQSS0xNTIiLCAiRVBJLTE1MyIsICJFUEktMTU0IiwgIkVQSS0xNTkiLCAiRVBJLTE2MCIsICJFUEktMTYxIiwgIkVQSS0xNjIiLCAiRVBJLTE2NyIsICJFUEktMTY4IiwgIkVQSS0xNjkiLCAiRVBJLTE3MCIpCgpgYGAKCgpgYGB7cn0KCmxpYnJhcnkocmVhZHIpCnNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0NHb3V0cHV0IikKCmRhdGEgPC0gbGlzdC5maWxlcyhwYXRoID0gIi4iLCBwYXR0ZXJuID0gIioub3V0cHV0IikKcHJpbnQoZGF0YSkKCmRiIDwtIHJlYWRfZGVsaW0oIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvQ0dvdXRwdXQvRVBJLTE1MV9DRy5vdXRwdXQiLCAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFLCBuYSA9ICIuIikKCmRiIDwtIGFzLmRhdGEudGFibGUoZGIpCgpkYiRFUEkxMDNNZXRoIDwtIHJvd1N1bXMoY2JpbmQoZGJbLDRdLCBkYlssN10pLCBuYS5ybSA9IFRSVUUpCmRiJEVQSTEwM1RvdENvdiA8LSByb3dTdW1zKGNiaW5kKGRiWyw1XSwgZGJbLDhdKSwgbmEucm0gPSBUUlVFKQptZXRoLmRiIDwtIGRiWyxjKDEsMiwzLDEwKV0KdG90Y292LmRiIDwtIGRiWyxjKDEsMiwzLDExKV0KCmZvcihpIGluIDI6bGVuZ3RoKGRhdGEpKSAgIHsKICAKICB0ZW1wIDwtIHJlYWRfZGVsaW0ocGFzdGUwKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0NHb3V0cHV0LyIsIGRhdGFbaV0pLCAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFLCBuYSA9ICIuIikKICB0ZW1wIDwtIGFzLmRhdGEudGFibGUodGVtcCkKICB0ZW1wJE1ldGggPC0gcm93U3VtcyhjYmluZCh0ZW1wWyw0XSwgdGVtcFssN10pLCBuYS5ybSA9IFRSVUUpCiAgdGVtcCRUb3RDb3YgPC0gcm93U3VtcyhjYmluZCh0ZW1wWyw1XSwgdGVtcFssOF0pLCBuYS5ybSA9IFRSVUUpCgogIG1ldGguZGIgPC0gbWVyZ2UobWV0aC5kYiwgdGVtcFssYygxLDIsMywxMCldLCBieSA9IG5hbWVzKG1ldGguZGJbLGMoMSwyLDMpXSksIGFsbCA9IFRSVUUpCiAgY29sbmFtZXMobWV0aC5kYilbbmNvbChtZXRoLmRiKV0gPC0gcGFzdGUwKHN1YnN0cihkYXRhW2ldLCAxLCA3KSwgIk1ldGgiKQogIG1ldGguZGIgPC0gYXMuZGF0YS50YWJsZShtZXRoLmRiKQogIAogIHRvdGNvdi5kYiA8LSBtZXJnZSh0b3Rjb3YuZGIsIHRlbXBbLGMoMSwyLDMsMTEpXSwgYnkgPSBuYW1lcyh0b3Rjb3YuZGJbLGMoMSwyLDMpXSksIGFsbCA9IFRSVUUpCiAgY29sbmFtZXModG90Y292LmRiKVtuY29sKHRvdGNvdi5kYildIDwtIHBhc3RlMChzdWJzdHIoZGF0YVtpXSwgMSwgNyksICJUb3RDb3YiKQogIHRvdGNvdi5kYiA8LSBhcy5kYXRhLnRhYmxlKHRvdGNvdi5kYikKfQoKCgpgYGAKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdSIpCm1ldGguZGIyIDwtIG1ldGguZGJbY29tcGxldGUuY2FzZXMobWV0aC5kYlssYyg0OjE1KV0pLF0KCnRvdGNvdi5kYjIgPC0gdG90Y292LmRiW2NvbXBsZXRlLmNhc2VzKHRvdGNvdi5kYlssYyg0OjE1KV0pLF0KCm1ldGguZGIzIDwtIG1ldGguZGIyW2FwcGx5KG1ldGguZGIyWywgYyg0OjE1KV0sIE1BUkdJTiA9IDEsIGZ1bmN0aW9uKHgpIGFsbCh4ID4gNSkpLCBdCnRvdGNvdi5kYjMgPC0gdG90Y292LmRiMlthcHBseSh0b3Rjb3YuZGIyWywgYyg0OjE1KV0sIE1BUkdJTiA9IDEsIGZ1bmN0aW9uKHgpIGFsbCh4ID4gNSkpLCBdCgptZXRoLmRiNCA8LSBhcy5kYXRhLnRhYmxlKGNiaW5kKHBhc3RlMChtZXRoLmRiMyRgI0NIUk9NYCwgIi0iLCBtZXRoLmRiMyRQT1MpLCBtZXRoLmRiM1ssNDpuY29sKG1ldGguZGIzKV0pKQpjb2xuYW1lcyhtZXRoLmRiNClbMV0gPC0gIlNpdGUiCnRvdGNvdi5kYjQgPC0gYXMuZGF0YS50YWJsZShjYmluZChwYXN0ZTAodG90Y292LmRiMyRgI0NIUk9NYCwgIi0iLCB0b3Rjb3YuZGIzJFBPUyksIHRvdGNvdi5kYjNbLDQ6bmNvbCh0b3Rjb3YuZGIzKV0pKQpjb2xuYW1lcyh0b3Rjb3YuZGI0KVsxXSA8LSAiU2l0ZSIKCnRvdGNvdi5kYjUgPC0gdG90Y292LmRiNFt0b3Rjb3YuZGI0JFNpdGUgJWluJSBtZXRoLmRiNCRTaXRlLF0KCm5yb3cobWV0aC5kYjQpCm5yb3codG90Y292LmRiNSkKbGVuZ3RoKHRvdGNvdi5kYjUkU2l0ZSAlaW4lIG1ldGguZGI0JFNpdGUpCgp3cml0ZS50YWJsZShtZXRoLmRiNCwgZmlsZSA9ICJmaXZleC5tYWNhdS5tZXRoLnR4dCIsIHNlcCA9ICIgIiwgcXVvdGUgPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UpCndyaXRlLnRhYmxlKHRvdGNvdi5kYjUsIGZpbGUgPSAiZml2ZXgubWFjYXUudG90YWxjb3YudHh0Iiwgc2VwID0gIiAiLCBxdW90ZSA9IEZBTFNFLCByb3cubmFtZXMgPSBGQUxTRSkKCnN5c3RlbSgiaGVhZCBmaXZleC5tYWNhdS5tZXRoLnR4dCIpCnN5c3RlbSgiaGVhZCBmaXZleC5tYWNhdS50b3RhbGNvdi50eHQiKQpgYGAKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS8iKQpzeXN0ZW0oIi9ob21lL3NoYXJlZC9tYWNhdS9tYWNhdSAtZyBmaXZleC5tYWNhdS5tZXRoLnR4dCAtdCBmaXZleC5tYWNhdS50b3RhbGNvdi50eHQgLXAgUHJlZGljdG9yLmNzdiAtayBkYXkxMzUtcmVsYXRlLWZpbmlzaGVkLmNzdiAtbyB0aHJlZXgiKQoKYGBgCgpgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUvIikKcmVzdWx0X2Fzc29jIDwtIHJlYWRfZGVsaW0oIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUvb3V0cHV0L3NldmVueC5hc3NvYy50eHQiLCAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFKQoKc2lnLnJlc3VsdHMgPC0gcmVzdWx0X2Fzc29jW3Jlc3VsdF9hc3NvYyRwdmFsdWUgPD0gMC4wNSxdCgogZm9yKGkgaW4gMTpucm93KHNpZy5yZXN1bHRzKSkgICB7CiAgIHRlbXAgPC0gc3Ryc3BsaXQoc2lnLnJlc3VsdHMkaWRbaV0sICItIikgCiAgIHNpZy5yZXN1bHRzW2ksMTNdIDwtIHRlbXBbWzFdXVsxXQogICBzaWcucmVzdWx0c1tpLDE0XSA8LSB0ZW1wW1sxXV1bMl0KICAgCiB9CiAKIGNvbG5hbWVzKHNpZy5yZXN1bHRzKVtjKDEzLDE0KV0gPC0gYygiU2NhZmZvbGQiLCAiTG9jIikKIAogYmVkLnRlc3QgPC0gYXMuZGF0YS5mcmFtZShjYmluZChzaWcucmVzdWx0c1ssMTNdLCAoc2lnLnJlc3VsdHNbLDE0XSksIChzaWcucmVzdWx0c1ssMTRdKSwgc2lnLnJlc3VsdHMkYmV0YSkpCiBjb2xuYW1lcyhiZWQudGVzdClbNF0gPC0gImJldGEiCiB3cml0ZS50YWJsZShiZWQudGVzdCwgZmlsZSA9ICJmaXZleC5EaWZmTWV0aFJlZ2lvbnMuYmVkIiwgc2VwID0gIlx0IiwgcXVvdGUgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQoKYGBgCgpgYGB7cn0KIHNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIpCiAKIGxpc3QuZmlsZXMocGF0aCA9ICIuIikKIAoKYGBgCgpgYGB7cn0KIGxpYnJhcnkoZGF0YS50YWJsZSkKIGxpYnJhcnkocmVhZHIpCiBEaWZmTWV0aFJlZ2lvbnMgPC0gcmVhZF9kZWxpbSgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdS9maXZleC5EaWZmTWV0aFJlZ2lvbnMuYmVkIiwgCiAgICAgIlx0IiwgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLCBjb2xfbmFtZXMgPSBGQUxTRSwgCiAgICAgdHJpbV93cyA9IFRSVUUpCiAKIERpZmZNZXRoUmVnaW9ucyRMb2MgPC0gcGFzdGUwKERpZmZNZXRoUmVnaW9ucyRYMSwgIi0iLCBEaWZmTWV0aFJlZ2lvbnMkWDIpCiAKIGhlYWQoRGlmZk1ldGhSZWdpb25zKQogCiBzYW1wbGUuZmlsZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvIiwgcGF0dGVybiA9ICIqLmJlZGdyYXBoIikKIAogcHJpbnQoc2FtcGxlLmZpbGVzKQoKYGBgCgpgYGB7cn0KCiBFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoIDwtIHJlYWRfZGVsaW0oIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvRVBJLTE1MS1wZXJjbWV0aC5iZWRncmFwaCIsIAogICAgICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgY29sX25hbWVzID0gRkFMU0UsIAogICAgIGNvbF90eXBlcyA9IGNvbHMoWDQgPSBjb2xfZG91YmxlKCkpLCAKICAgICB0cmltX3dzID0gVFJVRSkKIAogRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaCA8LSBhcy5kYXRhLnRhYmxlKEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGgpCiAKIGhlYWQoRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaCkKIAogcHJpbnQoRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaFs3LF0pCgpgYGAKCmBgYHtyfQoKRVBJXzEwM19ETVJzIDwtIEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGhbRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaCRYMSAlaW4lIERpZmZNZXRoUmVnaW9ucyRYMSxdCgoKRVBJXzEwM19ETVJzJExvYyA8LSBwYXN0ZTAoRVBJXzEwM19ETVJzJFgxLCAiLSIsIEVQSV8xMDNfRE1ScyRYMikKCgpoZWFkKEVQSV8xMDNfRE1ScykKCkVQSV8xMDNfRE1ScyA8LSBFUElfMTAzX0RNUnNbRVBJXzEwM19ETVJzJExvYyAlaW4lIERpZmZNZXRoUmVnaW9ucyRMb2MsXQoKaGVhZChFUElfMTAzX0RNUnMpCgpFUElfRE1ScyA8LSBhcy5kYXRhLnRhYmxlKGNiaW5kKEVQSV8xMDNfRE1ScyRMb2MsIEVQSV8xMDNfRE1ScyRYNCkpCgoKCmNvbG5hbWVzKEVQSV9ETVJzKVsxXSA8LSAiRE1STG9jIgpjb2xuYW1lcyhFUElfRE1ScylbMl0gPC0gIkVQSV8xNTEiCmhlYWQoRVBJX0RNUnMpCgpgYGAKCmBgYHtyfQoKZm9yKGkgaW4gMjpsZW5ndGgoc2FtcGxlLmZpbGVzKSkgICB7CgogIHRlbXAgPC0gcmVhZF9kZWxpbShwYXN0ZTAoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvIiwgc2FtcGxlLmZpbGVzW2ldKSwKICAgICJcdCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgY29sX25hbWVzID0gRkFMU0UsCiAgICBjb2xfdHlwZXMgPSBjb2xzKFg0ID0gY29sX2RvdWJsZSgpKSwKICAgIHRyaW1fd3MgPSBUUlVFKQoKICB0ZW1wIDwtIGFzLmRhdGEudGFibGUodGVtcCkKCiAgdGVtcF9ETVJzIDwtIHRlbXBbdGVtcCRYMSAlaW4lIERpZmZNZXRoUmVnaW9ucyRYMSxdCgoKICB0ZW1wX0RNUnMkTG9jIDwtIHBhc3RlMCh0ZW1wX0RNUnMkWDEsICItIiwgdGVtcF9ETVJzJFgyKQoKCiAgdGVtcF9ETVJzIDwtIHRlbXBfRE1Sc1t0ZW1wX0RNUnMkTG9jICVpbiUgRGlmZk1ldGhSZWdpb25zJExvYyxdCgogIEVQSV9ETVJzJHRlbXAgPC0gdGVtcF9ETVJzJFg0CgogIGNvbG5hbWVzKEVQSV9ETVJzKVtuY29sKEVQSV9ETVJzKV0gPC0gc3Vic3RyKHNhbXBsZS5maWxlc1tpXSwgMSwgNykKCgp9CgpoZWFkKEVQSV9ETVJzKQoKIyMgVGhpcyBpcyBoZXJlIGJlY2F1c2UgZm9yIG9zbWUgcmVhc29uIEVQSV8xMDMgZ2V0cyBicnVnaHQgaW4gYXMgY2hhcmFjdGVycyBhcyBvcHBvc2VkIHRvIGRvdWJsZXMuIE5lZWQgdG8gZmlndXJlIG91dCB3aHksIGJ1dCB0aGlzIGZpeGVzIGl0IGZvciBub3cKRVBJX0RNUnMkRVBJXzE1MSA8LSBhcy5udW1lcmljKEVQSV9ETVJzJEVQSV8xNTEpCgpgYGAKCmBgYHtyfQoKdHJlYXRtZW50Lm1lYW5zIDwtIGFzLmRhdGEuZnJhbWUoRVBJX0RNUnMkRE1STG9jKQoKdHJlYXRtZW50Lm1lYW5zJEFtYmllbnQgPC0gYXBwbHkoY2JpbmQoRVBJX0RNUnMkYEVQSS0xNTFgLCBFUElfRE1ScyRgRVBJLTE1MmAsIEVQSV9ETVJzJGBFUEktMTUzYCwgRVBJX0RNUnMkYEVQSS0xNTRgKSAsTUFSR0lOID0gMSwgRlVOID0gbWVhbikKCnRyZWF0bWVudC5tZWFucyRMb3cgPC0gYXBwbHkoY2JpbmQoRVBJX0RNUnMkYEVQSS0xNTlgLCBFUElfRE1ScyRgRVBJLTE2MGAsIEVQSV9ETVJzJGBFUEktMTYxYCwgRVBJX0RNUnMkYEVQSS0xNjJgKSAsTUFSR0lOID0gMSwgRlVOID0gbWVhbikKCnRyZWF0bWVudC5tZWFucyRTdXBlckxvdyA8LSBhcHBseShjYmluZChFUElfRE1ScyRgRVBJLTE2N2AsIEVQSV9ETVJzJGBFUEktMTY4YCwgRVBJX0RNUnMkYEVQSS0xNjlgLCBFUElfRE1ScyRgRVBJLTE3MGApICxNQVJHSU4gPSAxLCBGVU4gPSBtZWFuKQoKaGVhZCh0cmVhdG1lbnQubWVhbnMpCmBgYAoKYGBge3J9CgoKCiBmb3IoaSBpbiAxOm5yb3codHJlYXRtZW50Lm1lYW5zKSkgICB7CiAgIAoKICBib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSwyXSwgRVBJX0RNUnNbaSwzXSwgRVBJX0RNUnNbaSw0XSwgRVBJX0RNUnNbaSw1XSkpLHhsaW0gPSBjKDAuNSwgMy41KSwgeWxpbSA9IGMobWluKEVQSV9ETVJzW2ksMjoxM10pLCBtYXgoRVBJX0RNUnNbaSwyOjEzXSkpLCBib3hmaWxsID0gImJsdWUiLCBuYW1lcyA9ICJBbWJpZW50Iiwgc2hvdy5uYW1lcyA9IFRSVUUsIHlsYWIgPSAiUHJvcG9ydGlvbiBvZiByZWFkcyBtZXRoeWxhdGVkIikKCmJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDZdLCBFUElfRE1Sc1tpLDddLCBFUElfRE1Sc1tpLDhdLCBFUElfRE1Sc1tpLDldKSksIHhheHQgPSAibiIsIGFkZCA9IFRSVUUsIGF0ID0gMiwgYm94ZmlsbCA9ICJncmVlbiIpCgpib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSwxMF0sIEVQSV9ETVJzW2ksMTFdLCBFUElfRE1Sc1tpLDEyXSwgRVBJX0RNUnNbaSwxM10pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAzLCBib3hmaWxsID0gInJlZCIpCgpheGlzKHNpZGUgPSAxLCBhdCA9IDIsIGxhYmVscyA9ICJMb3ciKQpheGlzKHNpZGUgPSAxLCBhdCA9IDMsIGxhYmVscyA9ICJTdXBlciBMb3ciKQoKdGl0bGUocGFzdGUwKCJQcm9wb3J0aW9uIG9mIE1ldGh5bGF0ZWQgcmVhZHMgZm9yIERNUiBcbiBsb2NhdGVkIGF0ICIsIEVQSV9ETVJzW2ksMV0pKQoKCn0KCgpwZGYoZmlsZSA9ICJmaXZleC1ETVItQm94LVBsb3RzLnBkZiIpCgpmb3IoaSBpbiAxOm5yb3codHJlYXRtZW50Lm1lYW5zKSkgICB7CgoKICBib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSw2XSwgRVBJX0RNUnNbaSw3XSwgRVBJX0RNUnNbaSwxMF0sIEVQSV9ETVJzW2ksMTFdKSkseGxpbSA9IGMoMC41LCAzLjUpLCB5bGltID0gYyhtaW4oRVBJX0RNUnNbaSwyOjEzXSksIG1heChFUElfRE1Sc1tpLDI6MTNdKSksIGJveGZpbGwgPSAiYmx1ZSIsIG5hbWVzID0gIkFtYmllbnQiLCBzaG93Lm5hbWVzID0gVFJVRSwgeWxhYiA9ICJQcm9wb3J0aW9uIG9mIHJlYWRzIG1ldGh5bGF0ZWQiKQoKYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksMl0sIEVQSV9ETVJzW2ksM10sIEVQSV9ETVJzW2ksOF0sIEVQSV9ETVJzW2ksOV0pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAyLCBib3hmaWxsID0gImdyZWVuIikKCmJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDRdLCBFUElfRE1Sc1tpLDVdLCBFUElfRE1Sc1tpLDEyXSwgRVBJX0RNUnNbaSwxM10pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAzLCBib3hmaWxsID0gInJlZCIpCgpheGlzKHNpZGUgPSAxLCBhdCA9IDIsIGxhYmVscyA9ICJMb3ciKQpheGlzKHNpZGUgPSAxLCBhdCA9IDMsIGxhYmVscyA9ICJTdXBlciBMb3ciKQoKdGl0bGUocGFzdGUwKCJQcm9wb3J0aW9uIG9mIE1ldGh5bGF0ZWQgcmVhZHMgZm9yIERNUiBcbiBsb2NhdGVkIGF0ICIsIEVQSV9ETVJzW2ksMV0pKQoKCn0KCmRldi5vZmYoKQoKYGBgCgoqKioKM3ggQ292ZXJhZ2UgQ29kZSAgCi0tLQoKYGBge3J9CnNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIpCgpzYW1wbGVzLnZlYyA8LSBjKCJFUEktMTUxIiwgIkVQSS0xNTIiLCAiRVBJLTE1MyIsICJFUEktMTU0IiwgIkVQSS0xNTkiLCAiRVBJLTE2MCIsICJFUEktMTYxIiwgIkVQSS0xNjIiLCAiRVBJLTE2NyIsICJFUEktMTY4IiwgIkVQSS0xNjkiLCAiRVBJLTE3MCIpCgpgYGAKCgpgYGB7cn0KCmxpYnJhcnkocmVhZHIpCnNldHdkKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0NHb3V0cHV0IikKCmRhdGEgPC0gbGlzdC5maWxlcyhwYXRoID0gIi4iLCBwYXR0ZXJuID0gIioub3V0cHV0IikKcHJpbnQoZGF0YSkKCmRiIDwtIHJlYWRfZGVsaW0oIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvQ0dvdXRwdXQvRVBJLTE1MV9DRy5vdXRwdXQiLCAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFLCBuYSA9ICIuIikKCmRiIDwtIGFzLmRhdGEudGFibGUoZGIpCgpkYiRFUEkxMDNNZXRoIDwtIHJvd1N1bXMoY2JpbmQoZGJbLDRdLCBkYlssN10pLCBuYS5ybSA9IFRSVUUpCmRiJEVQSTEwM1RvdENvdiA8LSByb3dTdW1zKGNiaW5kKGRiWyw1XSwgZGJbLDhdKSwgbmEucm0gPSBUUlVFKQptZXRoLmRiIDwtIGRiWyxjKDEsMiwzLDEwKV0KdG90Y292LmRiIDwtIGRiWyxjKDEsMiwzLDExKV0KCmZvcihpIGluIDI6bGVuZ3RoKGRhdGEpKSAgIHsKICAKICB0ZW1wIDwtIHJlYWRfZGVsaW0ocGFzdGUwKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0NHb3V0cHV0LyIsIGRhdGFbaV0pLCAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFLCBuYSA9ICIuIikKICB0ZW1wIDwtIGFzLmRhdGEudGFibGUodGVtcCkKICB0ZW1wJE1ldGggPC0gcm93U3VtcyhjYmluZCh0ZW1wWyw0XSwgdGVtcFssN10pLCBuYS5ybSA9IFRSVUUpCiAgdGVtcCRUb3RDb3YgPC0gcm93U3VtcyhjYmluZCh0ZW1wWyw1XSwgdGVtcFssOF0pLCBuYS5ybSA9IFRSVUUpCgogIG1ldGguZGIgPC0gbWVyZ2UobWV0aC5kYiwgdGVtcFssYygxLDIsMywxMCldLCBieSA9IG5hbWVzKG1ldGguZGJbLGMoMSwyLDMpXSksIGFsbCA9IFRSVUUpCiAgY29sbmFtZXMobWV0aC5kYilbbmNvbChtZXRoLmRiKV0gPC0gcGFzdGUwKHN1YnN0cihkYXRhW2ldLCAxLCA3KSwgIk1ldGgiKQogIG1ldGguZGIgPC0gYXMuZGF0YS50YWJsZShtZXRoLmRiKQogIAogIHRvdGNvdi5kYiA8LSBtZXJnZSh0b3Rjb3YuZGIsIHRlbXBbLGMoMSwyLDMsMTEpXSwgYnkgPSBuYW1lcyh0b3Rjb3YuZGJbLGMoMSwyLDMpXSksIGFsbCA9IFRSVUUpCiAgY29sbmFtZXModG90Y292LmRiKVtuY29sKHRvdGNvdi5kYildIDwtIHBhc3RlMChzdWJzdHIoZGF0YVtpXSwgMSwgNyksICJUb3RDb3YiKQogIHRvdGNvdi5kYiA8LSBhcy5kYXRhLnRhYmxlKHRvdGNvdi5kYikKfQoKCgpgYGAKCmBgYHtyfQpzZXR3ZCgifi9Eb2N1bWVudHMvRGF5MTM1L0RheTEzNUN1dG9mZi9tYWNhdSIpCm1ldGguZGIyIDwtIG1ldGguZGJbY29tcGxldGUuY2FzZXMobWV0aC5kYlssYyg0OjE1KV0pLF0KCnRvdGNvdi5kYjIgPC0gdG90Y292LmRiW2NvbXBsZXRlLmNhc2VzKHRvdGNvdi5kYlssYyg0OjE1KV0pLF0KCm1ldGguZGIzIDwtIG1ldGguZGIyW2FwcGx5KG1ldGguZGIyWywgYyg0OjE1KV0sIE1BUkdJTiA9IDEsIGZ1bmN0aW9uKHgpIGFsbCh4ID4gMykpLCBdCnRvdGNvdi5kYjMgPC0gdG90Y292LmRiMlthcHBseSh0b3Rjb3YuZGIyWywgYyg0OjE1KV0sIE1BUkdJTiA9IDEsIGZ1bmN0aW9uKHgpIGFsbCh4ID4gMykpLCBdCgptZXRoLmRiNCA8LSBhcy5kYXRhLnRhYmxlKGNiaW5kKHBhc3RlMChtZXRoLmRiMyRgI0NIUk9NYCwgIi0iLCBtZXRoLmRiMyRQT1MpLCBtZXRoLmRiM1ssNDpuY29sKG1ldGguZGIzKV0pKQpjb2xuYW1lcyhtZXRoLmRiNClbMV0gPC0gIlNpdGUiCnRvdGNvdi5kYjQgPC0gYXMuZGF0YS50YWJsZShjYmluZChwYXN0ZTAodG90Y292LmRiMyRgI0NIUk9NYCwgIi0iLCB0b3Rjb3YuZGIzJFBPUyksIHRvdGNvdi5kYjNbLDQ6bmNvbCh0b3Rjb3YuZGIzKV0pKQpjb2xuYW1lcyh0b3Rjb3YuZGI0KVsxXSA8LSAiU2l0ZSIKCnRvdGNvdi5kYjUgPC0gdG90Y292LmRiNFt0b3Rjb3YuZGI0JFNpdGUgJWluJSBtZXRoLmRiNCRTaXRlLF0KCm5yb3cobWV0aC5kYjQpCm5yb3codG90Y292LmRiNSkKbGVuZ3RoKHRvdGNvdi5kYjUkU2l0ZSAlaW4lIG1ldGguZGI0JFNpdGUpCgp3cml0ZS50YWJsZShtZXRoLmRiNCwgZmlsZSA9ICJ0aHJlZXgubWFjYXUubWV0aC50eHQiLCBzZXAgPSAiICIsIHF1b3RlID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQp3cml0ZS50YWJsZSh0b3Rjb3YuZGI1LCBmaWxlID0gInRocmVleC5tYWNhdS50b3RhbGNvdi50eHQiLCBzZXAgPSAiICIsIHF1b3RlID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQoKc3lzdGVtKCJoZWFkIHRocmVleC5tYWNhdS5tZXRoLnR4dCIpCnN5c3RlbSgiaGVhZCB0aHJlZXgubWFjYXUudG90YWxjb3YudHh0IikKYGBgCgpgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUvIikKc3lzdGVtKCIvaG9tZS9zaGFyZWQvbWFjYXUvbWFjYXUgLWcgdGhyZWV4Lm1hY2F1Lm1ldGgudHh0IC10IHRocmVleC5tYWNhdS50b3RhbGNvdi50eHQgLXAgUHJlZGljdG9yLmNzdiAtayBkYXkxMzUtcmVsYXRlLWZpbmlzaGVkLmNzdiAtbyB0aHJlZXgiKQoKYGBgCgpgYGB7cn0Kc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvbWFjYXUvIikKCnRocmVleF9hc3NvYyA8LSByZWFkX2RlbGltKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL21hY2F1L291dHB1dC90aHJlZXguYXNzb2MudHh0IiwgCiAgICAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFKQoKc2lnLnJlc3VsdHMgPC0gdGhyZWV4X2Fzc29jW3RocmVleF9hc3NvYyRwdmFsdWUgPD0gMC4wNSxdCgogZm9yKGkgaW4gMTpucm93KHNpZy5yZXN1bHRzKSkgICB7CiAgIHRlbXAgPC0gc3Ryc3BsaXQoc2lnLnJlc3VsdHMkaWRbaV0sICItIikgCiAgIHNpZy5yZXN1bHRzW2ksMTNdIDwtIHRlbXBbWzFdXVsxXQogICBzaWcucmVzdWx0c1tpLDE0XSA8LSB0ZW1wW1sxXV1bMl0KICAgCiB9CiAKIGNvbG5hbWVzKHNpZy5yZXN1bHRzKVtjKDEzLDE0KV0gPC0gYygiU2NhZmZvbGQiLCAiTG9jIikKIAogYmVkLnRlc3QgPC0gYXMuZGF0YS5mcmFtZShjYmluZChzaWcucmVzdWx0c1ssMTNdLCAoc2lnLnJlc3VsdHNbLDE0XSksIChzaWcucmVzdWx0c1ssMTRdKSwgc2lnLnJlc3VsdHMkYmV0YSkpCiBjb2xuYW1lcyhiZWQudGVzdClbNF0gPC0gImJldGEiCiB3cml0ZS50YWJsZShiZWQudGVzdCwgZmlsZSA9ICJ0aHJlZXguRGlmZk1ldGhSZWdpb25zLmJlZCIsIHNlcCA9ICIsIiwgcXVvdGUgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHJvdy5uYW1lcyA9IEZBTFNFKQoKYGBgCgoKYGBge3J9CiAKc2V0d2QoIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvIikKIAogbGlzdC5maWxlcyhwYXRoID0gIi4iKQogCmBgYAoKYGBge3J9CiBsaWJyYXJ5KGRhdGEudGFibGUpCiBsaWJyYXJ5KHJlYWRyKQogRGlmZk1ldGhSZWdpb25zIDwtIHJlYWRfZGVsaW0oIn4vRG9jdW1lbnRzL0RheTEzNS9EYXkxMzVDdXRvZmYvdGhyZWV4LkRpZmZNZXRoUmVnaW9ucy5iZWQiLCAKICAgICAiLCIsIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwgY29sX25hbWVzID0gRkFMU0UsIAogICAgIHRyaW1fd3MgPSBUUlVFKQogCiBEaWZmTWV0aFJlZ2lvbnMkTG9jIDwtIHBhc3RlMChEaWZmTWV0aFJlZ2lvbnMkWDEsICItIiwgRGlmZk1ldGhSZWdpb25zJFgyKQogCiBoZWFkKERpZmZNZXRoUmVnaW9ucykKIAogc2FtcGxlLmZpbGVzIDwtIGxpc3QuZmlsZXMocGF0aCA9ICJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIsIHBhdHRlcm4gPSAiKi5iZWRncmFwaCIpCiAKIHByaW50KHNhbXBsZS5maWxlcykKCmBgYAoKYGBge3J9CgogRVBJXzEwM19wZXJjbWV0aF9iZWRncmFwaCA8LSByZWFkX2RlbGltKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmL0VQSS0xNTEtcGVyY21ldGguYmVkZ3JhcGgiLCAKICAgICAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIGNvbF9uYW1lcyA9IEZBTFNFLCAKICAgICBjb2xfdHlwZXMgPSBjb2xzKFg0ID0gY29sX2RvdWJsZSgpKSwgCiAgICAgdHJpbV93cyA9IFRSVUUpCiAKIEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGggPC0gYXMuZGF0YS50YWJsZShFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoKQogCiBoZWFkKEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGgpCiAKIHByaW50KEVQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGhbNyxdKQoKYGBgCgpgYGB7cn0KCkVQSV8xMDNfRE1ScyA8LSBFUElfMTAzX3BlcmNtZXRoX2JlZGdyYXBoW0VQSV8xMDNfcGVyY21ldGhfYmVkZ3JhcGgkWDEgJWluJSBEaWZmTWV0aFJlZ2lvbnMkWDEsXQoKCkVQSV8xMDNfRE1ScyRMb2MgPC0gcGFzdGUwKEVQSV8xMDNfRE1ScyRYMSwgIi0iLCBFUElfMTAzX0RNUnMkWDIpCgoKaGVhZChFUElfMTAzX0RNUnMpCgpFUElfMTAzX0RNUnMgPC0gRVBJXzEwM19ETVJzW0VQSV8xMDNfRE1ScyRMb2MgJWluJSBEaWZmTWV0aFJlZ2lvbnMkTG9jLF0KCmhlYWQoRVBJXzEwM19ETVJzKQoKRVBJX0RNUnMgPC0gYXMuZGF0YS50YWJsZShjYmluZChFUElfMTAzX0RNUnMkTG9jLCBFUElfMTAzX0RNUnMkWDQpKQoKCgpjb2xuYW1lcyhFUElfRE1ScylbMV0gPC0gIkRNUkxvYyIKY29sbmFtZXMoRVBJX0RNUnMpWzJdIDwtICJFUElfMTUxIgpoZWFkKEVQSV9ETVJzKQoKYGBgCgpgYGB7cn0KCmZvcihpIGluIDI6bGVuZ3RoKHNhbXBsZS5maWxlcykpICAgewoKICB0ZW1wIDwtIHJlYWRfZGVsaW0ocGFzdGUwKCJ+L0RvY3VtZW50cy9EYXkxMzUvRGF5MTM1Q3V0b2ZmLyIsIHNhbXBsZS5maWxlc1tpXSksCiAgICAiXHQiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIGNvbF9uYW1lcyA9IEZBTFNFLAogICAgY29sX3R5cGVzID0gY29scyhYNCA9IGNvbF9kb3VibGUoKSksCiAgICB0cmltX3dzID0gVFJVRSkKCiAgdGVtcCA8LSBhcy5kYXRhLnRhYmxlKHRlbXApCgogIHRlbXBfRE1ScyA8LSB0ZW1wW3RlbXAkWDEgJWluJSBEaWZmTWV0aFJlZ2lvbnMkWDEsXQoKCiAgdGVtcF9ETVJzJExvYyA8LSBwYXN0ZTAodGVtcF9ETVJzJFgxLCAiLSIsIHRlbXBfRE1ScyRYMikKCgogIHRlbXBfRE1ScyA8LSB0ZW1wX0RNUnNbdGVtcF9ETVJzJExvYyAlaW4lIERpZmZNZXRoUmVnaW9ucyRMb2MsXQoKICBFUElfRE1ScyR0ZW1wIDwtIHRlbXBfRE1ScyRYNAoKICBjb2xuYW1lcyhFUElfRE1ScylbbmNvbChFUElfRE1ScyldIDwtIHN1YnN0cihzYW1wbGUuZmlsZXNbaV0sIDEsIDcpCgoKfQoKaGVhZChFUElfRE1ScykKCiMjIFRoaXMgaXMgaGVyZSBiZWNhdXNlIGZvciBvc21lIHJlYXNvbiBFUElfMTAzIGdldHMgYnJ1Z2h0IGluIGFzIGNoYXJhY3RlcnMgYXMgb3Bwb3NlZCB0byBkb3VibGVzLiBOZWVkIHRvIGZpZ3VyZSBvdXQgd2h5LCBidXQgdGhpcyBmaXhlcyBpdCBmb3Igbm93CkVQSV9ETVJzJEVQSV8xNTEgPC0gYXMubnVtZXJpYyhFUElfRE1ScyRFUElfMTUxKQoKYGBgCgpgYGB7cn0KCnRyZWF0bWVudC5tZWFucyA8LSBhcy5kYXRhLmZyYW1lKEVQSV9ETVJzJERNUkxvYykKCnRyZWF0bWVudC5tZWFucyRBbWJpZW50IDwtIGFwcGx5KGNiaW5kKEVQSV9ETVJzJGBFUEktMTUxYCwgRVBJX0RNUnMkYEVQSS0xNTJgLCBFUElfRE1ScyRgRVBJLTE1M2AsIEVQSV9ETVJzJGBFUEktMTU0YCkgLE1BUkdJTiA9IDEsIEZVTiA9IG1lYW4pCgp0cmVhdG1lbnQubWVhbnMkTG93IDwtIGFwcGx5KGNiaW5kKEVQSV9ETVJzJGBFUEktMTU5YCwgRVBJX0RNUnMkYEVQSS0xNjBgLCBFUElfRE1ScyRgRVBJLTE2MWAsIEVQSV9ETVJzJGBFUEktMTYyYCkgLE1BUkdJTiA9IDEsIEZVTiA9IG1lYW4pCgp0cmVhdG1lbnQubWVhbnMkU3VwZXJMb3cgPC0gYXBwbHkoY2JpbmQoRVBJX0RNUnMkYEVQSS0xNjdgLCBFUElfRE1ScyRgRVBJLTE2OGAsIEVQSV9ETVJzJGBFUEktMTY5YCwgRVBJX0RNUnMkYEVQSS0xNzBgKSAsTUFSR0lOID0gMSwgRlVOID0gbWVhbikKCmhlYWQodHJlYXRtZW50Lm1lYW5zKQoKYGBgCgpgYGB7cn0KCgoKIyAgZm9yKGkgaW4gMTpucm93KHRyZWF0bWVudC5tZWFucykpICAgewojICAgIAojIAojICAgYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksMl0sIEVQSV9ETVJzW2ksM10sIEVQSV9ETVJzW2ksNF0sIEVQSV9ETVJzW2ksNV0pKSx4bGltID0gYygwLjUsIDMuNSksIHlsaW0gPSBjKG1pbihFUElfRE1Sc1tpLDI6MTNdKSwgbWF4KEVQSV9ETVJzW2ksMjoxM10pKSwgYm94ZmlsbCA9ICJibHVlIiwgbmFtZXMgPSAiQW1iaWVudCIsIHNob3cubmFtZXMgPSBUUlVFLCB5bGFiID0gIlByb3BvcnRpb24gb2YgcmVhZHMgbWV0aHlsYXRlZCIpCiMgCiMgYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksNl0sIEVQSV9ETVJzW2ksN10sIEVQSV9ETVJzW2ksOF0sIEVQSV9ETVJzW2ksOV0pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAyLCBib3hmaWxsID0gImdyZWVuIikKIyAKIyBib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSwxMF0sIEVQSV9ETVJzW2ksMTFdLCBFUElfRE1Sc1tpLDEyXSwgRVBJX0RNUnNbaSwxM10pKSwgeGF4dCA9ICJuIiwgYWRkID0gVFJVRSwgYXQgPSAzLCBib3hmaWxsID0gInJlZCIpCiMgCiMgYXhpcyhzaWRlID0gMSwgYXQgPSAyLCBsYWJlbHMgPSAiTG93IikKIyBheGlzKHNpZGUgPSAxLCBhdCA9IDMsIGxhYmVscyA9ICJTdXBlciBMb3ciKQojIAojIHRpdGxlKHBhc3RlMCgiUHJvcG9ydGlvbiBvZiBNZXRoeWxhdGVkIHJlYWRzIGZvciBETVIgXG4gbG9jYXRlZCBhdCAiLCBFUElfRE1Sc1tpLDFdKSkKIyAKIyAKIyB9CgoKcGRmKGZpbGUgPSAidGhyZWV4LURNUi1Cb3gtUGxvdHMucGRmIikKCmZvcihpIGluIDE6bnJvdyh0cmVhdG1lbnQubWVhbnMpKSAgIHsKCgogIGJveHBsb3QodChjYmluZChFUElfRE1Sc1tpLDZdLCBFUElfRE1Sc1tpLDddLCBFUElfRE1Sc1tpLDEwXSwgRVBJX0RNUnNbaSwxMV0pKSx4bGltID0gYygwLjUsIDMuNSksIHlsaW0gPSBjKG1pbihFUElfRE1Sc1tpLDI6MTNdKSwgbWF4KEVQSV9ETVJzW2ksMjoxM10pKSwgYm94ZmlsbCA9ICJibHVlIiwgbmFtZXMgPSAiQW1iaWVudCIsIHNob3cubmFtZXMgPSBUUlVFLCB5bGFiID0gIlByb3BvcnRpb24gb2YgcmVhZHMgbWV0aHlsYXRlZCIpCgpib3hwbG90KHQoY2JpbmQoRVBJX0RNUnNbaSwyXSwgRVBJX0RNUnNbaSwzXSwgRVBJX0RNUnNbaSw4XSwgRVBJX0RNUnNbaSw5XSkpLCB4YXh0ID0gIm4iLCBhZGQgPSBUUlVFLCBhdCA9IDIsIGJveGZpbGwgPSAiZ3JlZW4iKQoKYm94cGxvdCh0KGNiaW5kKEVQSV9ETVJzW2ksNF0sIEVQSV9ETVJzW2ksNV0sIEVQSV9ETVJzW2ksMTJdLCBFUElfRE1Sc1tpLDEzXSkpLCB4YXh0ID0gIm4iLCBhZGQgPSBUUlVFLCBhdCA9IDMsIGJveGZpbGwgPSAicmVkIikKCmF4aXMoc2lkZSA9IDEsIGF0ID0gMiwgbGFiZWxzID0gIkxvdyIpCmF4aXMoc2lkZSA9IDEsIGF0ID0gMywgbGFiZWxzID0gIlN1cGVyIExvdyIpCgp0aXRsZShwYXN0ZTAoIlByb3BvcnRpb24gb2YgTWV0aHlsYXRlZCByZWFkcyBmb3IgRE1SIFxuIGxvY2F0ZWQgYXQgIiwgRVBJX0RNUnNbaSwxXSkpCgoKfQoKZGV2Lm9mZigpCgpgYGAKCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4K