library(dplyr)
library(ggplot2);
library(RMySQL)
db <- dbConnect(MySQL(), host='', user='', password='', dbname='')
Custom Theme (based on https://rpubs.com/Koundy/71792)
theme_Publication <- function(base_size=10, base_family="Helvetica") {
library(grid)
library(ggthemes)
(theme_foundation(base_size=base_size, base_family=base_family)
+ theme(plot.title = element_text(face = "bold",
size = rel(1), hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5),
text = element_text(),
panel.background = element_rect(colour = NA),
plot.background = element_rect(colour = NA),
panel.border = element_rect(colour = NA),
axis.title = element_text(face = "bold",size = rel(1)),
axis.title.y = element_text(angle=90,vjust =2),
axis.title.x = element_text(vjust = -0.2),
axis.text = element_text(),
axis.line = element_line(colour="black"),
axis.ticks = element_line(),
panel.grid.major = element_line(colour="#f0f0f0"),
panel.grid.minor = element_blank(),
legend.key = element_rect(colour = NA),
legend.position = "bottom",
legend.direction = "horizontal",
legend.key.size= unit(0.2, "cm"),
legend.spacing = unit(0, "cm"),
legend.title = element_text(face = "italic", size = rel(1)),
plot.margin=unit(c(1,2,1,2),"mm"),
strip.background=element_rect(colour="#f0f0f0",fill="#f0f0f0"),
strip.text = element_text(face="bold")
))
}
theme_set(theme_Publication())
scale_colour_discrete <- function(...) scale_color_brewer(..., palette="Set2")
legendInBox <- function(pos = c(0,0)) theme(legend.position = pos, legend.direction = "vertical", legend.box.background = element_rect(colour = "#000000"), legend.key.size = unit(0.9, "lines"))
update_geom_defaults("point", list(size = 0.7))
CA:VSIDS vs CA:RND
df <- dbGetQuery(db, "
SELECT * FROM Experiment as main
inner join Instance
on Instance.`ID-Instance` = main.`ID-Instance`
inner join Configuration
on Configuration.`ID-configuration` = main.`ID-configuration`
where
`RE-value` in ('lbd', 'luE3')
and `VD-value` in ('df95', 'df80')
and `PH-value` in ('std')
and `CE-value` in ('lin', 'glu', 'min')
and `CA-value` in ('vsids', 'lbd', 'rnd')
and `CL-value` in ('1uip')
and `PR-value` in ('on', 'off')
and `SH-value` in ('off');")
df$`RE-value` <- as.factor(df$`RE-value`)
df$`VD-value` <- as.factor(df$`VD-value`)
df$`PH-value` <- as.factor(df$`PH-value`)
df$`CE-value` <- as.factor(df$`CE-value`)
df$`CA-value` <- as.factor(df$`CA-value`)
df$`CL-value` <- as.factor(df$`CL-value`)
df$`PR-value` <- as.factor(df$`PR-value`)
df$`SH-value` <- as.factor(df$`SH-value`)
df <- df[, !duplicated(colnames(df))]
library(ggplot2)
data = df %>% filter(Subfamily == "domset_4", `RE-value` == "lbd", `VD-value` == "df95", `PH-value` == "std", `CE-value` == "glu", `PR-value` == "on")
plot <- ggplot(data, aes(
x = `Variables`,
y = `CPU-time`,
color = `CA-value`)) + geom_point() + geom_line() +
labs(x = "Number of variables", y = "CPU time", color = "Clause assessment", title = "Dominating set formulas (k=4)") +
legendInBox(c(0.25,0.6))
ggsave(filename = "plots/ca_rnd_vs_vsidis_single.pdf", units = "cm", device = "pdf", width = 10, height = 5)
plot

data = df %>% filter()
timeouts = data %>%
group_by(Subfamily, `RE-value`, `VD-value`, `PH-value`, `CE-value`, `CA-value`, `CL-value`, `PR-value`, `SH-value`) %>%
summarize(
timeout = sum(`Solver-answer` == "INDETERMINATE"),
outofmem = sum(`Solver-answer` == "OUTOFMEMORY" ),
unsolved = sum(`Solver-answer` %in% c("OUTOFMEMORY", "INDETERMINATE") ),
n = n())
rndVsLbd = inner_join(
timeouts %>% filter(`CA-value` == "rnd"),
timeouts %>% filter(`CA-value` == "lbd"),
by = c("Subfamily", "RE-value", "VD-value", "PH-value", "CE-value", "CL-value", "PR-value", "SH-value"),
suffix = c(".rnd", ".other"))
rndVsLbd = rndVsLbd %>% mutate(diff = unsolved.rnd - unsolved.other, other = factor("lbd", c("lbd", "vsids")))
rndVsVsids = inner_join(
timeouts %>% filter(`CA-value` == "rnd"),
timeouts %>% filter(`CA-value` == "vsids"),
by = c("Subfamily", "RE-value", "VD-value", "PH-value", "CE-value", "CL-value", "PR-value", "SH-value"),
suffix = c(".rnd", ".other"))
rndVsVsids = rndVsVsids %>% mutate(diff = unsolved.rnd - unsolved.other, other = factor("vsids", c("lbd", "vsids")))
data = union(rndVsLbd, rndVsVsids)
print("lbd - rnd")
[1] "lbd - rnd"
summary(data %>% filter(other == "lbd") %>% pull(diff))
Min. 1st Qu. Median Mean 3rd Qu. Max.
-38.00 0.00 1.00 3.12 6.00 33.00
print("vsids - rnd")
[1] "vsids - rnd"
summary(data %>% filter(other == "vsids") %>% pull(diff))
Min. 1st Qu. Median Mean 3rd Qu. Max.
-14.0000 0.0000 0.0000 0.8029 1.0000 33.0000
plot <- ggplot(data, aes(x = `other`, y = `diff`)) +
geom_boxplot(outlier.shape = 4) +
stat_boxplot(geom ='errorbar', width = 0.2) +
labs(x = "", y = "Difference in number of timeouts", title = "All formula families") +
scale_x_discrete(labels = c('random - LBD','random - activity-based')) +
theme(plot.margin=unit(c(2,2,-3,2),"mm")) +
ggsave(filename = "plots/ca_rnd_boxplot.pdf", units = "cm", device = "pdf", width = 10, height = 6.5)
plot

Each data point is a configuration for a subfamily, the difference is optained by only varying the clause assesment strategie.
The plot shows that there is a difference between vsids and rnd, especially the lower quartiel on the difference is zero, i.e. in less then 25% of the cases rnd is better (for no differnece one would expect more). Especially, when comparing this difference to lbd, it shows that it is not very relevant.
Decay Factor
Load Variable Decay Batch
df <- dbGetQuery(db, "
SELECT * FROM Experiment as main
inner join Instance
on Instance.`ID-Instance` = main.`ID-Instance`
inner join Configuration
on Configuration.`ID-configuration` = main.`ID-configuration`
where
`RE-value` in ('lbd', 'luE3')
and `VD-value` in ('df99', 'df95', 'df80', 'df65', 'rnd', 'lrb')
and `PH-value` in ('fix0', 'std')
and `CE-value` in ('glu', 'min')
and `CA-value` in ('vsids', 'lbd')
and `CL-value` in ('1uip')
and `PR-value` in ('on', 'off')
and `SH-value` in ('off');")
df$`RE-value` <- as.factor(df$`RE-value`)
df$`VD-value` <- as.factor(df$`VD-value`)
df$`PH-value` <- as.factor(df$`PH-value`)
df$`CE-value` <- as.factor(df$`CE-value`)
df$`CA-value` <- as.factor(df$`CA-value`)
df$`CL-value` <- as.factor(df$`CL-value`)
df$`PR-value` <- as.factor(df$`PR-value`)
df$`SH-value` <- as.factor(df$`SH-value`)
df <- df[, !duplicated(colnames(df))]
data = df %>% filter(Subfamily == "op_partial", `CE-value` == "glu", `RE-value` == "lbd", `PH-value` == "std", `PR-value` == "off", `CA-value` == "lbd", !`VD-value` %in% c("lrb", "rnd"))
plot <- ggplot(data,
aes(x = `Variables`,
y = `CPU-time`, color = `VD-value`)
) +
geom_point() + geom_line() +
legendInBox(c(0.75,0.53)) +
labs(x = "Number of variables", y = "CPU time", color = "VSIDS decay factor", title = "Partial ordering principle formulas") +
scale_colour_discrete(labels = c("0.65", "0.80", "0.95", "0.99"))
ggsave(filename = "plots/vd_op_partial.pdf", units = "cm", device = "pdf", width = 10, height = 5.2)
plot

LRB
data = df %>% filter()
timeouts = data %>%
group_by(Subfamily, `RE-value`, `VD-value`, `PH-value`, `CE-value`, `CA-value`, `CL-value`, `PR-value`, `SH-value`) %>%
summarize(
timeout = sum(`Solver-answer` == "INDETERMINATE"),
outofmem = sum(`Solver-answer` == "OUTOFMEMORY" ),
unsolved = sum(`Solver-answer` %in% c("OUTOFMEMORY", "INDETERMINATE") ),
n = n())
lrbVs65 = inner_join(
timeouts %>% filter(`VD-value` == "lrb"),
timeouts %>% filter(`VD-value` == "df65"),
by = c("Subfamily", "RE-value", "PH-value", "CE-value", "CL-value", "PR-value", "SH-value", "CA-value"))
lrbVs65 = lrbVs65 %>% mutate(diff = unsolved.x - unsolved.y, other = "df65")
lrbVs99 = inner_join(
timeouts %>% filter(`VD-value` == "lrb"),
timeouts %>% filter(`VD-value` == "df99"),
by = c("Subfamily", "RE-value", "PH-value", "CE-value", "CL-value", "PR-value", "SH-value", "CA-value"))
lrbVs99 = lrbVs99 %>% mutate(diff = unsolved.x - unsolved.y, other = "df99")
df99Vsdf65 = inner_join(
timeouts %>% filter(`VD-value` == "df99"),
timeouts %>% filter(`VD-value` == "df65"),
by = c("Subfamily", "RE-value", "PH-value", "CE-value", "CL-value", "PR-value", "SH-value", "CA-value"))
df99Vsdf65 = df99Vsdf65 %>% mutate(diff = unsolved.x - unsolved.y, other = "df")
data <- union(lrbVs65, lrbVs99)
data <- union(data, df99Vsdf65)
print("df65 - lrb")
[1] "df65 - lrb"
summary(data %>% filter(other == "df65") %>% pull(diff))
Min. 1st Qu. Median Mean 3rd Qu. Max.
-25.0000 -2.0000 0.0000 -0.6743 0.0000 26.0000
print("df99 - lrb")
[1] "df99 - lrb"
summary(data %>% filter(other == "df99") %>% pull(diff))
Min. 1st Qu. Median Mean 3rd Qu. Max.
-27.0000 -1.0000 0.0000 -0.8606 1.0000 11.0000
print("df99 - df65")
[1] "df99 - df65"
summary(data %>% filter(other == "df") %>% pull(diff))
Min. 1st Qu. Median Mean 3rd Qu. Max.
-27.0000 -3.0000 0.0000 0.1863 1.0000 31.0000
plot <- ggplot(data, aes(x = `other`, y = `diff`)) +
geom_boxplot(outlier.shape = 4) +
stat_boxplot(geom ='errorbar', width = 0.2) +
labs(x = "", y = "Difference in number of timeouts", title = "All formula families") +
theme(plot.margin=unit(c(2,2,-3,2),"mm")) +
scale_x_discrete(labels = c('VSIDS .99 - .65', 'LRB - VSIDS .65','LRB - VSIDS .99'))
ggsave(filename = "plots/vd_lrb_vs_vsids.pdf", units = "cm", device = "pdf", width = 10, height = 6.5)
plot

Restarts
Load main Batch
library(RMySQL)
df <- dbGetQuery(db, "
SELECT * FROM Experiment as main
inner join Instance
on Instance.`ID-Instance` = main.`ID-Instance`
inner join Configuration
on Configuration.`ID-configuration` = main.`ID-configuration`
where
`RE-value` in ('no', 'lbd', 'luE2', 'luE3')
and `VD-value` in ('df95', 'df80', 'lrb')
and `PH-value` in ('fix0', 'std')
and `CE-value` in ('no', 'lin', 'glu', 'min')
and `CA-value` in ('vsids', 'lbd', 'none')
and `CL-value` in ('1uip')
and `PR-value` in ('on', 'off')
and `SH-value` in ('off');")
df$`RE-value` <- as.factor(df$`RE-value`)
df$`VD-value` <- as.factor(df$`VD-value`)
df$`PH-value` <- as.factor(df$`PH-value`)
df$`CE-value` <- as.factor(df$`CE-value`)
df$`CA-value` <- as.factor(df$`CA-value`)
df$`CL-value` <- as.factor(df$`CL-value`)
df$`PR-value` <- as.factor(df$`PR-value`)
df$`SH-value` <- as.factor(df$`SH-value`)
df <- df[, !duplicated(colnames(df))]
data = df %>% filter(Subfamily == "stone_width3chain_nhalfmarkers", `CE-value` == "glu", `PH-value` == "std", `PR-value` == "off", `CA-value` == "lbd", `VD-value` == "df95")
plot <- ggplot(data,
aes(x = `Variables`,
y = `CPU-time`, color = `RE-value`)
) +
geom_point() + geom_line() +
theme(legend.position = c(1.2,0.5), legend.direction = "vertical", legend.key.size = unit(1, "lines"), plot.margin=unit(c(1,25,1,2),"mm")) +
scale_colour_discrete(labels = c("LBD", "Luby 100", "Luby 1000", "no restarts")) +
labs(x = "Number of variables", y = "CPU time", color = "Restarts", title = "Stone formulas", subtitle = "on width 3 chain, #stones = #nodes / 2")
ggsave(filename = "plots/restarts.pdf", units = "cm", device = "pdf", width = 10, height = 5.2)
plot + theme(legend.position = "bottom", legend.direction = "horizontal")

data = df %>% filter(Subfamily == "peb_pyrofpyr_neq3", `CE-value` == "glu", `PH-value` == "std", `PR-value` == "off", `CA-value` == "lbd", `VD-value` == "df80")
plot <- ggplot(data,
aes(x = `Variables`,
y = `CPU-time`, color = `RE-value`)
) +
geom_point() + geom_line() +
scale_colour_discrete(labels = c("LBD", "Luby 100", "Luby 1000", "no restarts")) +
theme(legend.position = c(1.2,0.5), legend.direction = "vertical", legend.key.size = unit(1, "lines"), plot.margin=unit(c(1,25,1,2),"mm")) +
labs(x = "Number of variables", y = "CPU time", color = "Restarts", title = "Pebbling on pyramid-of-pyramids graphs")
ggsave(filename = "plots/restarts2.pdf", units = "cm", device = "pdf", width = 10, height = 5)
plot + theme(legend.position = "bottom", legend.direction = "horizontal")

Database Size
data = df %>% filter(Subfamily == "tseitin_reggrid_5", `CA-value` == "lbd", `RE-value` == "lbd", `VD-value` == "df80", `PH-value` == "std", `PR-value` == "off")
ggplot(data,
aes(x = `Variables`,
y = `CPU-time`, color = `CE-value`, group = `ID-configuration`)
) +
geom_point() + geom_line() +
labs(x = "Number of variables", y = "CPU time", color = "Clause erasure:")

ggplot(data %>% filter(`Solver-answer` == "UNSATISFIABLE"),
aes(x = `Variables`,
y = `Conflicts` / 1000000, color = `CE-value`, group = `ID-configuration`)
) +
geom_point() + geom_line() +
labs(x = "Number of variables", y = "Million conflicts")

Fancy Arrangement
library(gridExtra)
library(cowplot)
data = df %>% filter(Subfamily == "tseitin_reggrid_5", `CA-value` == "lbd", `RE-value` == "lbd", `VD-value` == "df80", `PH-value` == "std", `PR-value` == "off")
plot1 <- ggplot(data,
aes(x = `Variables`,
y = `CPU-time`, color = `CE-value`, group = `ID-configuration`)
) +
geom_point() + geom_line() +
theme(plot.margin=unit(c(0,2,0,2),"mm"), legend.position = "bottom") +
scale_colour_discrete(labels = c("glucose", "linear", "minisat")) +
labs(x = "Number of variables", y = "CPU time", color = "Clause erasure:")
legend <- get_legend(plot1)
plot1 <- plot1 + theme(legend.position = "none")
plot2 <- ggplot(data %>% filter(`Solver-answer` == "UNSATISFIABLE"),
aes(x = `Variables`,
y = `Conflicts` / 1000000, color = `CE-value`, group = `ID-configuration`)
) +
geom_point() + geom_line() +
theme(plot.margin=unit(c(0,2,0,3),"mm"), legend.position = "none")+
labs(x = "Number of variables", y = "Million conflicts")
titlePlot <- ggplot() + labs(title = "Tseitin formulas on grid graphs (5 rows)") +
theme(plot.margin=unit(c(2,2,0,2),"mm"))
arrange <- arrangeGrob(plot1,plot2, ncol = 2)
arrange <- arrangeGrob(titlePlot, arrange, legend, heights = c(0.8,5,0.8) ,nrow = 3)
ggsave(filename = "plots/clauseErasure.pdf", arrange, units = "cm", device = "pdf", width = 10, height = 6)
Phase Saving
Load Phase Saving Batch
df <- dbGetQuery(db, "
SELECT * FROM Experiment as main
inner join Instance
on Instance.`ID-Instance` = main.`ID-Instance`
inner join Configuration
on Configuration.`ID-configuration` = main.`ID-configuration`
where
`Subfamily` = 'stone_width3chain_nhalfmarkers'
and `RE-value` in ('lbd', 'luE3')
and `VD-value` in ('df95', 'df80')
and `PH-value` in ('fix0', 'std', 'dynrnd', 'fixrnd', 'ctr')
and `CE-value` in ('glu', 'min')
and `CA-value` in ('vsids', 'lbd')
and `CL-value` in ('1uip')
and `PR-value` in ('on', 'off')
and `SH-value` in ('off');")
df$`RE-value` <- as.factor(df$`RE-value`)
df$`VD-value` <- as.factor(df$`VD-value`)
df$`PH-value` <- as.factor(df$`PH-value`)
df$`CE-value` <- as.factor(df$`CE-value`)
df$`CA-value` <- as.factor(df$`CA-value`)
df$`CL-value` <- as.factor(df$`CL-value`)
df$`PR-value` <- as.factor(df$`PR-value`)
df$`SH-value` <- as.factor(df$`SH-value`)
df <- df[, !duplicated(colnames(df))]
data = df %>% filter(Subfamily == "stone_width3chain_nhalfmarkers", `CE-value` == "glu", `PR-value` == "off", `CA-value` == "lbd", `VD-value` == "df95", `RE-value` == "lbd")
plot <- ggplot(data,
aes(x = `Variables`,
y = `CPU-time`, color = `PH-value`)
) +
geom_point() + geom_line() +
theme(legend.position = c(1.2,0.5), legend.direction = "vertical", legend.key.size = unit(1.2, "lines"), plot.margin=unit(c(1,25,1,2),"mm")) +
scale_colour_discrete(labels = c("counter", "dynamic\nrandom", "fix zero", "fix random", "standard")) +
labs(x = "Number of variables", y = "CPU time", color = "Phase:", title = "Stone formulas", subtitle = "on width 3 chain, #stones = #nodes / 2")
ggsave(filename = "plots/phase.pdf", units = "cm", device = "pdf", width = 10, height = 5.2)
plot + theme(legend.position = "bottom", legend.direction = "horizontal")

LS0tCnRpdGxlOiAiUGxvdHMgZm9yIFNlZWtpbmcgUHJhY3RpY2FsIENEQ0wgSW5zaWdodHMgZnJvbSBUaGVvcmV0aWNhbCBTQVQgQmVuY2htYXJrcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90Mik7CmxpYnJhcnkoUk15U1FMKQpkYiA8LSBkYkNvbm5lY3QoTXlTUUwoKSwgaG9zdD0nbXNxbDAxLmNzYy5rdGguc2UnLCB1c2VyPSdnaXJhbGRlel91c2VyJywgcGFzc3dvcmQ9J3VrYm01RklIdk51aycsIGRibmFtZT0nZ2lyYWxkZXonKQpgYGAKCkN1c3RvbSBUaGVtZSAoYmFzZWQgb24gaHR0cHM6Ly9ycHVicy5jb20vS291bmR5LzcxNzkyKQpgYGB7cn0KdGhlbWVfUHVibGljYXRpb24gPC0gZnVuY3Rpb24oYmFzZV9zaXplPTEwLCBiYXNlX2ZhbWlseT0iSGVsdmV0aWNhIikgewogICAgICBsaWJyYXJ5KGdyaWQpCiAgICAgIGxpYnJhcnkoZ2d0aGVtZXMpCiAgICAgICh0aGVtZV9mb3VuZGF0aW9uKGJhc2Vfc2l6ZT1iYXNlX3NpemUsIGJhc2VfZmFtaWx5PWJhc2VfZmFtaWx5KQogICAgICAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IHJlbCgxKSwgaGp1c3QgPSAwLjUpLAogICAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dCgpLAogICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5BKSwKICAgICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5BKSwKICAgICAgICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5BKSwKICAgICAgICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLHNpemUgPSByZWwoMSkpLAogICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsdmp1c3QgPTIpLAogICAgICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQodmp1c3QgPSAtMC4yKSwKICAgICAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KCksIAogICAgICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyPSJibGFjayIpLAogICAgICAgICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKCksCiAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyPSIjZjBmMGYwIiksCiAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTkEpLAogICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwKICAgICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplPSB1bml0KDAuMiwgImNtIiksCiAgICAgICAgICAgICAgIGxlZ2VuZC5zcGFjaW5nID0gdW5pdCgwLCAiY20iKSwKICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IHJlbCgxKSksCiAgICAgICAgICAgICAgIHBsb3QubWFyZ2luPXVuaXQoYygxLDIsMSwyKSwibW0iKSwKICAgICAgICAgICAgICAgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoY29sb3VyPSIjZjBmMGYwIixmaWxsPSIjZjBmMGYwIiksCiAgICAgICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpCiAgICAgICAgICApKQogICAgICAKfQoKdGhlbWVfc2V0KHRoZW1lX1B1YmxpY2F0aW9uKCkpCnNjYWxlX2NvbG91cl9kaXNjcmV0ZSA8LSBmdW5jdGlvbiguLi4pIHNjYWxlX2NvbG9yX2JyZXdlciguLi4sIHBhbGV0dGU9IlNldDIiKQpsZWdlbmRJbkJveCA8LSBmdW5jdGlvbihwb3MgPSBjKDAsMCkpIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IHBvcywgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC5ib3guYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiIzAwMDAwMCIpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuOSwgImxpbmVzIikpCnVwZGF0ZV9nZW9tX2RlZmF1bHRzKCJwb2ludCIsIGxpc3Qoc2l6ZSA9IDAuNykpCmBgYAoKCiMgQ0E6VlNJRFMgdnMgQ0E6Uk5ECgpgYGB7cn0KZGYgPC0gZGJHZXRRdWVyeShkYiwgIgogIFNFTEVDVCAqIEZST00gRXhwZXJpbWVudCBhcyBtYWluCiAgaW5uZXIgam9pbiBJbnN0YW5jZQogIAlvbiBJbnN0YW5jZS5gSUQtSW5zdGFuY2VgID0gbWFpbi5gSUQtSW5zdGFuY2VgCiAgaW5uZXIgam9pbiBDb25maWd1cmF0aW9uCiAgCW9uIENvbmZpZ3VyYXRpb24uYElELWNvbmZpZ3VyYXRpb25gID0gbWFpbi5gSUQtY29uZmlndXJhdGlvbmAKd2hlcmUKIGBSRS12YWx1ZWAgaW4gKCdsYmQnLCAnbHVFMycpCiBhbmQgYFZELXZhbHVlYCBpbiAoJ2RmOTUnLCAnZGY4MCcpCiBhbmQgYFBILXZhbHVlYCBpbiAoJ3N0ZCcpCiBhbmQgYENFLXZhbHVlYCBpbiAoJ2xpbicsICdnbHUnLCAnbWluJykKIGFuZCBgQ0EtdmFsdWVgIGluICgndnNpZHMnLCAnbGJkJywgJ3JuZCcpCiBhbmQgYENMLXZhbHVlYCBpbiAoJzF1aXAnKQogYW5kIGBQUi12YWx1ZWAgaW4gKCdvbicsICdvZmYnKQogYW5kIGBTSC12YWx1ZWAgaW4gKCdvZmYnKTsiKQpkZiRgUkUtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgUkUtdmFsdWVgKQpkZiRgVkQtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgVkQtdmFsdWVgKQpkZiRgUEgtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgUEgtdmFsdWVgKQpkZiRgQ0UtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgQ0UtdmFsdWVgKQpkZiRgQ0EtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgQ0EtdmFsdWVgKQpkZiRgQ0wtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgQ0wtdmFsdWVgKQpkZiRgUFItdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgUFItdmFsdWVgKQpkZiRgU0gtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgU0gtdmFsdWVgKQpkZiA8LSBkZlssICFkdXBsaWNhdGVkKGNvbG5hbWVzKGRmKSldCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKZGF0YSA9IGRmICU+JSBmaWx0ZXIoU3ViZmFtaWx5ID09ICJkb21zZXRfNCIsIGBSRS12YWx1ZWAgPT0gImxiZCIsIGBWRC12YWx1ZWAgPT0gImRmOTUiLCBgUEgtdmFsdWVgID09ICJzdGQiLCBgQ0UtdmFsdWVgID09ICJnbHUiLCBgUFItdmFsdWVgID09ICJvbiIpCgpwbG90IDwtIGdncGxvdChkYXRhLCBhZXMoCiAgeCA9IGBWYXJpYWJsZXNgLAogIHkgPSBgQ1BVLXRpbWVgLAogIGNvbG9yID0gYENBLXZhbHVlYCkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKCkgKwogIGxhYnMoeCA9ICJOdW1iZXIgb2YgdmFyaWFibGVzIiwgeSA9ICJDUFUgdGltZSIsIGNvbG9yID0gIkNsYXVzZSBhc3Nlc3NtZW50IiwgdGl0bGUgPSAiRG9taW5hdGluZyBzZXQgZm9ybXVsYXMgKGs9NCkiKSArCiAgbGVnZW5kSW5Cb3goYygwLjI1LDAuNikpCgpnZ3NhdmUoZmlsZW5hbWUgPSAicGxvdHMvY2Ffcm5kX3ZzX3ZzaWRpc19zaW5nbGUucGRmIiwgdW5pdHMgPSAiY20iLCBkZXZpY2UgPSAicGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNSkKcGxvdApgYGAKCmBgYHtyfQpkYXRhID0gZGYgJT4lIGZpbHRlcigpCnRpbWVvdXRzID0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkoU3ViZmFtaWx5LCBgUkUtdmFsdWVgLCBgVkQtdmFsdWVgLCBgUEgtdmFsdWVgLCBgQ0UtdmFsdWVgLCBgQ0EtdmFsdWVgLCBgQ0wtdmFsdWVgLCBgUFItdmFsdWVgLCBgU0gtdmFsdWVgKSAlPiUgCiAgc3VtbWFyaXplKAogICAgdGltZW91dCA9IHN1bShgU29sdmVyLWFuc3dlcmAgPT0gIklOREVURVJNSU5BVEUiKSwKICAgIG91dG9mbWVtID0gc3VtKGBTb2x2ZXItYW5zd2VyYCA9PSAiT1VUT0ZNRU1PUlkiICksCiAgICB1bnNvbHZlZCA9IHN1bShgU29sdmVyLWFuc3dlcmAgJWluJSBjKCJPVVRPRk1FTU9SWSIsICJJTkRFVEVSTUlOQVRFIikgKSwKICAgIG4gPSBuKCkpCgpybmRWc0xiZCA9IGlubmVyX2pvaW4oCiAgdGltZW91dHMgJT4lIGZpbHRlcihgQ0EtdmFsdWVgID09ICJybmQiKSwKICB0aW1lb3V0cyAlPiUgZmlsdGVyKGBDQS12YWx1ZWAgPT0gImxiZCIpLAogIGJ5ID0gYygiU3ViZmFtaWx5IiwgIlJFLXZhbHVlIiwgIlZELXZhbHVlIiwgIlBILXZhbHVlIiwgIkNFLXZhbHVlIiwgIkNMLXZhbHVlIiwgIlBSLXZhbHVlIiwgIlNILXZhbHVlIiksCiAgc3VmZml4ID0gYygiLnJuZCIsICIub3RoZXIiKSkKcm5kVnNMYmQgPSBybmRWc0xiZCAlPiUgbXV0YXRlKGRpZmYgPSB1bnNvbHZlZC5ybmQgLSB1bnNvbHZlZC5vdGhlciwgb3RoZXIgPSBmYWN0b3IoImxiZCIsIGMoImxiZCIsICJ2c2lkcyIpKSkKCnJuZFZzVnNpZHMgPSBpbm5lcl9qb2luKAogIHRpbWVvdXRzICU+JSBmaWx0ZXIoYENBLXZhbHVlYCA9PSAicm5kIiksCiAgdGltZW91dHMgJT4lIGZpbHRlcihgQ0EtdmFsdWVgID09ICJ2c2lkcyIpLAogIGJ5ID0gYygiU3ViZmFtaWx5IiwgIlJFLXZhbHVlIiwgIlZELXZhbHVlIiwgIlBILXZhbHVlIiwgIkNFLXZhbHVlIiwgIkNMLXZhbHVlIiwgIlBSLXZhbHVlIiwgIlNILXZhbHVlIiksCiAgc3VmZml4ID0gYygiLnJuZCIsICIub3RoZXIiKSkKcm5kVnNWc2lkcyA9IHJuZFZzVnNpZHMgJT4lIG11dGF0ZShkaWZmID0gdW5zb2x2ZWQucm5kIC0gdW5zb2x2ZWQub3RoZXIsIG90aGVyID0gZmFjdG9yKCJ2c2lkcyIsIGMoImxiZCIsICJ2c2lkcyIpKSkKCmRhdGEgPSB1bmlvbihybmRWc0xiZCwgcm5kVnNWc2lkcykKICAgICAgICAgICAKcHJpbnQoImxiZCAtIHJuZCIpCnN1bW1hcnkoZGF0YSAlPiUgZmlsdGVyKG90aGVyID09ICJsYmQiKSAlPiUgcHVsbChkaWZmKSkKcHJpbnQoInZzaWRzIC0gcm5kIikKc3VtbWFyeShkYXRhICU+JSBmaWx0ZXIob3RoZXIgPT0gInZzaWRzIikgJT4lIHB1bGwoZGlmZikpCnBsb3QgPC0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gYG90aGVyYCwgeSA9IGBkaWZmYCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IDQpICsKICBzdGF0X2JveHBsb3QoZ2VvbSA9J2Vycm9yYmFyJywgd2lkdGggPSAwLjIpICsKICBsYWJzKHggPSAiIiwgeSA9ICJEaWZmZXJlbmNlIGluIG51bWJlciBvZiB0aW1lb3V0cyIsIHRpdGxlID0gIkFsbCBmb3JtdWxhIGZhbWlsaWVzIikgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygncmFuZG9tIC0gTEJEJywncmFuZG9tIC0gYWN0aXZpdHktYmFzZWQnKSkgKyAKICB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMiwyLC0zLDIpLCJtbSIpKSArCmdnc2F2ZShmaWxlbmFtZSA9ICJwbG90cy9jYV9ybmRfYm94cGxvdC5wZGYiLCB1bml0cyA9ICJjbSIsIGRldmljZSA9ICJwZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA2LjUpCnBsb3QKYGBgCgpFYWNoIGRhdGEgcG9pbnQgaXMgYSBjb25maWd1cmF0aW9uIGZvciBhIHN1YmZhbWlseSwgdGhlIGRpZmZlcmVuY2UgaXMgb3B0YWluZWQgYnkgb25seSB2YXJ5aW5nIHRoZSBjbGF1c2UgYXNzZXNtZW50IHN0cmF0ZWdpZS4KClRoZSBwbG90IHNob3dzIHRoYXQgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGJldHdlZW4gdnNpZHMgYW5kIHJuZCwgZXNwZWNpYWxseSB0aGUgbG93ZXIgcXVhcnRpZWwgb24gdGhlIGRpZmZlcmVuY2UgaXMgemVybywKaS5lLiBpbiBsZXNzIHRoZW4gMjUlIG9mIHRoZSBjYXNlcyBybmQgaXMgYmV0dGVyIChmb3Igbm8gZGlmZmVybmVjZSBvbmUgd291bGQgZXhwZWN0IG1vcmUpLiBFc3BlY2lhbGx5LCB3aGVuIGNvbXBhcmluZwp0aGlzIGRpZmZlcmVuY2UgdG8gbGJkLCBpdCBzaG93cyB0aGF0IGl0IGlzIG5vdCB2ZXJ5IHJlbGV2YW50LgoKCiMgRGVjYXkgRmFjdG9yCgpMb2FkIFZhcmlhYmxlIERlY2F5IEJhdGNoCgpgYGB7cn0KZGYgPC0gZGJHZXRRdWVyeShkYiwgIgogIFNFTEVDVCAqIEZST00gRXhwZXJpbWVudCBhcyBtYWluCiAgaW5uZXIgam9pbiBJbnN0YW5jZQogIAlvbiBJbnN0YW5jZS5gSUQtSW5zdGFuY2VgID0gbWFpbi5gSUQtSW5zdGFuY2VgCiAgaW5uZXIgam9pbiBDb25maWd1cmF0aW9uCiAgCW9uIENvbmZpZ3VyYXRpb24uYElELWNvbmZpZ3VyYXRpb25gID0gbWFpbi5gSUQtY29uZmlndXJhdGlvbmAKd2hlcmUKICAgICBgUkUtdmFsdWVgIGluICgnbGJkJywgJ2x1RTMnKQogYW5kIGBWRC12YWx1ZWAgaW4gKCdkZjk5JywgJ2RmOTUnLCAnZGY4MCcsICdkZjY1JywgJ3JuZCcsICdscmInKQogYW5kIGBQSC12YWx1ZWAgaW4gKCdmaXgwJywgJ3N0ZCcpCiBhbmQgYENFLXZhbHVlYCBpbiAoJ2dsdScsICdtaW4nKQogYW5kIGBDQS12YWx1ZWAgaW4gKCd2c2lkcycsICdsYmQnKQogYW5kIGBDTC12YWx1ZWAgaW4gKCcxdWlwJykKIGFuZCBgUFItdmFsdWVgIGluICgnb24nLCAnb2ZmJykKIGFuZCBgU0gtdmFsdWVgIGluICgnb2ZmJyk7IikKZGYkYFJFLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFJFLXZhbHVlYCkKZGYkYFZELXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFZELXZhbHVlYCkKZGYkYFBILXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFBILXZhbHVlYCkKZGYkYENFLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYENFLXZhbHVlYCkKZGYkYENBLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYENBLXZhbHVlYCkKZGYkYENMLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYENMLXZhbHVlYCkKZGYkYFBSLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFBSLXZhbHVlYCkKZGYkYFNILXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFNILXZhbHVlYCkKZGYgPC0gZGZbLCAhZHVwbGljYXRlZChjb2xuYW1lcyhkZikpXQpgYGAKCgpgYGB7cn0KZGF0YSA9IGRmICU+JSBmaWx0ZXIoU3ViZmFtaWx5ID09ICJvcF9wYXJ0aWFsIiwgYENFLXZhbHVlYCA9PSAiZ2x1IiwgYFJFLXZhbHVlYCA9PSAibGJkIiwgYFBILXZhbHVlYCA9PSAic3RkIiwgYFBSLXZhbHVlYCA9PSAib2ZmIiwgYENBLXZhbHVlYCA9PSAibGJkIiwgIWBWRC12YWx1ZWAgJWluJSBjKCJscmIiLCAicm5kIikpCgpwbG90IDwtIGdncGxvdChkYXRhLCAKICAgICAgIGFlcyh4ID0gYFZhcmlhYmxlc2AsCiAgICAgICAgICAgeSA9IGBDUFUtdGltZWAsIGNvbG9yID0gYFZELXZhbHVlYCkKICAgICAgICkgKyAKICBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKSArIAogIGxlZ2VuZEluQm94KGMoMC43NSwwLjUzKSkgKwogIGxhYnMoeCA9ICJOdW1iZXIgb2YgdmFyaWFibGVzIiwgeSA9ICJDUFUgdGltZSIsIGNvbG9yID0gIlZTSURTIGRlY2F5IGZhY3RvciIsIHRpdGxlID0gIlBhcnRpYWwgb3JkZXJpbmcgcHJpbmNpcGxlIGZvcm11bGFzIikgKwogIHNjYWxlX2NvbG91cl9kaXNjcmV0ZShsYWJlbHMgPSBjKCIwLjY1IiwgIjAuODAiLCAiMC45NSIsICIwLjk5IikpCmdnc2F2ZShmaWxlbmFtZSA9ICJwbG90cy92ZF9vcF9wYXJ0aWFsLnBkZiIsIHVuaXRzID0gImNtIiwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUuMikKcGxvdApgYGAKIyMgTFJCCgpgYGB7cn0KZGF0YSA9IGRmICU+JSBmaWx0ZXIoKQp0aW1lb3V0cyA9IGRhdGEgJT4lIAogIGdyb3VwX2J5KFN1YmZhbWlseSwgYFJFLXZhbHVlYCwgYFZELXZhbHVlYCwgYFBILXZhbHVlYCwgYENFLXZhbHVlYCwgYENBLXZhbHVlYCwgYENMLXZhbHVlYCwgYFBSLXZhbHVlYCwgYFNILXZhbHVlYCkgJT4lIAogIHN1bW1hcml6ZSgKICAgIHRpbWVvdXQgPSBzdW0oYFNvbHZlci1hbnN3ZXJgID09ICJJTkRFVEVSTUlOQVRFIiksCiAgICBvdXRvZm1lbSA9IHN1bShgU29sdmVyLWFuc3dlcmAgPT0gIk9VVE9GTUVNT1JZIiApLAogICAgdW5zb2x2ZWQgPSBzdW0oYFNvbHZlci1hbnN3ZXJgICVpbiUgYygiT1VUT0ZNRU1PUlkiLCAiSU5ERVRFUk1JTkFURSIpICksCiAgICBuID0gbigpKQoKbHJiVnM2NSA9IGlubmVyX2pvaW4oCiAgdGltZW91dHMgJT4lIGZpbHRlcihgVkQtdmFsdWVgID09ICJscmIiKSwKICB0aW1lb3V0cyAlPiUgZmlsdGVyKGBWRC12YWx1ZWAgPT0gImRmNjUiKSwKICBieSA9IGMoIlN1YmZhbWlseSIsICJSRS12YWx1ZSIsICJQSC12YWx1ZSIsICJDRS12YWx1ZSIsICJDTC12YWx1ZSIsICJQUi12YWx1ZSIsICJTSC12YWx1ZSIsICJDQS12YWx1ZSIpKQpscmJWczY1ID0gbHJiVnM2NSAlPiUgbXV0YXRlKGRpZmYgPSB1bnNvbHZlZC54IC0gdW5zb2x2ZWQueSwgb3RoZXIgPSAiZGY2NSIpCgpscmJWczk5ID0gaW5uZXJfam9pbigKICB0aW1lb3V0cyAlPiUgZmlsdGVyKGBWRC12YWx1ZWAgPT0gImxyYiIpLAogIHRpbWVvdXRzICU+JSBmaWx0ZXIoYFZELXZhbHVlYCA9PSAiZGY5OSIpLAogIGJ5ID0gYygiU3ViZmFtaWx5IiwgIlJFLXZhbHVlIiwgIlBILXZhbHVlIiwgIkNFLXZhbHVlIiwgIkNMLXZhbHVlIiwgIlBSLXZhbHVlIiwgIlNILXZhbHVlIiwgIkNBLXZhbHVlIikpCmxyYlZzOTkgPSBscmJWczk5ICU+JSBtdXRhdGUoZGlmZiA9IHVuc29sdmVkLnggLSB1bnNvbHZlZC55LCBvdGhlciA9ICJkZjk5IikKCmRmOTlWc2RmNjUgPSBpbm5lcl9qb2luKAogIHRpbWVvdXRzICU+JSBmaWx0ZXIoYFZELXZhbHVlYCA9PSAiZGY5OSIpLAogIHRpbWVvdXRzICU+JSBmaWx0ZXIoYFZELXZhbHVlYCA9PSAiZGY2NSIpLAogIGJ5ID0gYygiU3ViZmFtaWx5IiwgIlJFLXZhbHVlIiwgIlBILXZhbHVlIiwgIkNFLXZhbHVlIiwgIkNMLXZhbHVlIiwgIlBSLXZhbHVlIiwgIlNILXZhbHVlIiwgIkNBLXZhbHVlIikpCmRmOTlWc2RmNjUgPSBkZjk5VnNkZjY1ICU+JSBtdXRhdGUoZGlmZiA9IHVuc29sdmVkLnggLSB1bnNvbHZlZC55LCBvdGhlciA9ICJkZiIpCgoKZGF0YSA8LSB1bmlvbihscmJWczY1LCBscmJWczk5KQpkYXRhIDwtIHVuaW9uKGRhdGEsIGRmOTlWc2RmNjUpCiAgICAgICAgICAgCnByaW50KCJkZjY1IC0gbHJiIikKc3VtbWFyeShkYXRhICU+JSBmaWx0ZXIob3RoZXIgPT0gImRmNjUiKSAlPiUgcHVsbChkaWZmKSkKcHJpbnQoImRmOTkgLSBscmIiKQpzdW1tYXJ5KGRhdGEgJT4lIGZpbHRlcihvdGhlciA9PSAiZGY5OSIpICU+JSBwdWxsKGRpZmYpKQpwcmludCgiZGY5OSAtIGRmNjUiKQpzdW1tYXJ5KGRhdGEgJT4lIGZpbHRlcihvdGhlciA9PSAiZGYiKSAlPiUgcHVsbChkaWZmKSkKCnBsb3QgPC0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gYG90aGVyYCwgeSA9IGBkaWZmYCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IDQpICsKICBzdGF0X2JveHBsb3QoZ2VvbSA9J2Vycm9yYmFyJywgd2lkdGggPSAwLjIpICsKICBsYWJzKHggPSAiIiwgeSA9ICJEaWZmZXJlbmNlIGluIG51bWJlciBvZiB0aW1lb3V0cyIsIHRpdGxlID0gIkFsbCBmb3JtdWxhIGZhbWlsaWVzIikgKwogIHRoZW1lKHBsb3QubWFyZ2luPXVuaXQoYygyLDIsLTMsMiksIm1tIikpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoJ1ZTSURTIC45OSAtIC42NScsICdMUkIgLSBWU0lEUyAuNjUnLCdMUkIgLSBWU0lEUyAuOTknKSkKZ2dzYXZlKGZpbGVuYW1lID0gInBsb3RzL3ZkX2xyYl92c192c2lkcy5wZGYiLCB1bml0cyA9ICJjbSIsIGRldmljZSA9ICJwZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA2LjUpCnBsb3QKYGBgCgoKIyBSZXN0YXJ0cwoKTG9hZCBtYWluIEJhdGNoCgpgYGB7cn0KbGlicmFyeShSTXlTUUwpCmRmIDwtIGRiR2V0UXVlcnkoZGIsICIKICBTRUxFQ1QgKiBGUk9NIEV4cGVyaW1lbnQgYXMgbWFpbgogIGlubmVyIGpvaW4gSW5zdGFuY2UKICAJb24gSW5zdGFuY2UuYElELUluc3RhbmNlYCA9IG1haW4uYElELUluc3RhbmNlYAogIGlubmVyIGpvaW4gQ29uZmlndXJhdGlvbgogIAlvbiBDb25maWd1cmF0aW9uLmBJRC1jb25maWd1cmF0aW9uYCA9IG1haW4uYElELWNvbmZpZ3VyYXRpb25gCndoZXJlCiBgUkUtdmFsdWVgIGluICgnbm8nLCAnbGJkJywgJ2x1RTInLCAnbHVFMycpCiBhbmQgYFZELXZhbHVlYCBpbiAoJ2RmOTUnLCAnZGY4MCcsICdscmInKQogYW5kIGBQSC12YWx1ZWAgaW4gKCdmaXgwJywgJ3N0ZCcpCiBhbmQgYENFLXZhbHVlYCBpbiAoJ25vJywgJ2xpbicsICdnbHUnLCAnbWluJykKIGFuZCBgQ0EtdmFsdWVgIGluICgndnNpZHMnLCAnbGJkJywgJ25vbmUnKQogYW5kIGBDTC12YWx1ZWAgaW4gKCcxdWlwJykKIGFuZCBgUFItdmFsdWVgIGluICgnb24nLCAnb2ZmJykKIGFuZCBgU0gtdmFsdWVgIGluICgnb2ZmJyk7IikKZGYkYFJFLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFJFLXZhbHVlYCkKZGYkYFZELXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFZELXZhbHVlYCkKZGYkYFBILXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFBILXZhbHVlYCkKZGYkYENFLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYENFLXZhbHVlYCkKZGYkYENBLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYENBLXZhbHVlYCkKZGYkYENMLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYENMLXZhbHVlYCkKZGYkYFBSLXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFBSLXZhbHVlYCkKZGYkYFNILXZhbHVlYCA8LSBhcy5mYWN0b3IoZGYkYFNILXZhbHVlYCkKZGYgPC0gZGZbLCAhZHVwbGljYXRlZChjb2xuYW1lcyhkZikpXQpgYGAKCmBgYHtyfQpkYXRhID0gZGYgJT4lIGZpbHRlcihTdWJmYW1pbHkgPT0gInN0b25lX3dpZHRoM2NoYWluX25oYWxmbWFya2VycyIsIGBDRS12YWx1ZWAgPT0gImdsdSIsIGBQSC12YWx1ZWAgPT0gInN0ZCIsIGBQUi12YWx1ZWAgPT0gIm9mZiIsIGBDQS12YWx1ZWAgPT0gImxiZCIsIGBWRC12YWx1ZWAgPT0gImRmOTUiKQoKcGxvdCA8LSBnZ3Bsb3QoZGF0YSwgCiAgICAgICBhZXMoeCA9IGBWYXJpYWJsZXNgLAogICAgICAgICAgIHkgPSBgQ1BVLXRpbWVgLCBjb2xvciA9IGBSRS12YWx1ZWApCiAgICAgICApICsgCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDEuMiwwLjUpLCBsZWdlbmQuZGlyZWN0aW9uID0gInZlcnRpY2FsIiwgbGVnZW5kLmtleS5zaXplID0gdW5pdCgxLCAibGluZXMiKSwgcGxvdC5tYXJnaW49dW5pdChjKDEsMjUsMSwyKSwibW0iKSkgKwogIHNjYWxlX2NvbG91cl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJMQkQiLCAiTHVieSAxMDAiLCAiTHVieSAxMDAwIiwgIm5vIHJlc3RhcnRzIikpICsKICBsYWJzKHggPSAiTnVtYmVyIG9mIHZhcmlhYmxlcyIsIHkgPSAiQ1BVIHRpbWUiLCBjb2xvciA9ICJSZXN0YXJ0cyIsIHRpdGxlID0gIlN0b25lIGZvcm11bGFzIiwgc3VidGl0bGUgPSAib24gd2lkdGggMyBjaGFpbiwgI3N0b25lcyA9ICNub2RlcyAvIDIiKQpnZ3NhdmUoZmlsZW5hbWUgPSAicGxvdHMvcmVzdGFydHMucGRmIiwgdW5pdHMgPSAiY20iLCBkZXZpY2UgPSAicGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNS4yKQpwbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIpCmBgYAoKYGBge3J9CmRhdGEgPSBkZiAlPiUgZmlsdGVyKFN1YmZhbWlseSA9PSAicGViX3B5cm9mcHlyX25lcTMiLCBgQ0UtdmFsdWVgID09ICJnbHUiLCBgUEgtdmFsdWVgID09ICJzdGQiLCBgUFItdmFsdWVgID09ICJvZmYiLCBgQ0EtdmFsdWVgID09ICJsYmQiLCBgVkQtdmFsdWVgID09ICJkZjgwIikKCnBsb3QgPC0gZ2dwbG90KGRhdGEsIAogICAgICAgYWVzKHggPSBgVmFyaWFibGVzYCwKICAgICAgICAgICB5ID0gYENQVS10aW1lYCwgY29sb3IgPSBgUkUtdmFsdWVgKQogICAgICAgKSArIAogIGdlb21fcG9pbnQoKSArIGdlb21fbGluZSgpICsgCiAgc2NhbGVfY29sb3VyX2Rpc2NyZXRlKGxhYmVscyA9IGMoIkxCRCIsICJMdWJ5IDEwMCIsICJMdWJ5IDEwMDAiLCAibm8gcmVzdGFydHMiKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMS4yLDAuNSksIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsICJsaW5lcyIpLCBwbG90Lm1hcmdpbj11bml0KGMoMSwyNSwxLDIpLCJtbSIpKSArCiAgbGFicyh4ID0gIk51bWJlciBvZiB2YXJpYWJsZXMiLCB5ID0gIkNQVSB0aW1lIiwgY29sb3IgPSAiUmVzdGFydHMiLCB0aXRsZSA9ICJQZWJibGluZyBvbiBweXJhbWlkLW9mLXB5cmFtaWRzIGdyYXBocyIpCmdnc2F2ZShmaWxlbmFtZSA9ICJwbG90cy9yZXN0YXJ0czIucGRmIiwgdW5pdHMgPSAiY20iLCBkZXZpY2UgPSAicGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNSkKcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKQpgYGAKCgojIERhdGFiYXNlIFNpemUKYGBge3J9CmRhdGEgPSBkZiAlPiUgZmlsdGVyKFN1YmZhbWlseSA9PSAidHNlaXRpbl9yZWdncmlkXzUiLCBgQ0EtdmFsdWVgID09ICJsYmQiLCBgUkUtdmFsdWVgID09ICJsYmQiLCBgVkQtdmFsdWVgID09ICJkZjgwIiwgYFBILXZhbHVlYCA9PSAic3RkIiwgYFBSLXZhbHVlYCA9PSAib2ZmIikKCmdncGxvdChkYXRhLCAKICAgICAgIGFlcyh4ID0gYFZhcmlhYmxlc2AsCiAgICAgICAgICAgeSA9IGBDUFUtdGltZWAsIGNvbG9yID0gYENFLXZhbHVlYCwgZ3JvdXAgPSBgSUQtY29uZmlndXJhdGlvbmApCiAgICAgICApICsgCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKCkgKwogIGxhYnMoeCA9ICJOdW1iZXIgb2YgdmFyaWFibGVzIiwgeSA9ICJDUFUgdGltZSIsIGNvbG9yID0gIkNsYXVzZSBlcmFzdXJlOiIpCgpnZ3Bsb3QoZGF0YSAlPiUgZmlsdGVyKGBTb2x2ZXItYW5zd2VyYCA9PSAiVU5TQVRJU0ZJQUJMRSIpLCAKICAgICAgIGFlcyh4ID0gYFZhcmlhYmxlc2AsCiAgICAgICAgICAgeSA9IGBDb25mbGljdHNgIC8gMTAwMDAwMCwgY29sb3IgPSBgQ0UtdmFsdWVgLCBncm91cCA9IGBJRC1jb25maWd1cmF0aW9uYCkKICAgICAgICkgKyAKICBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh4ID0gIk51bWJlciBvZiB2YXJpYWJsZXMiLCB5ID0gIk1pbGxpb24gY29uZmxpY3RzIikKYGBgCgoKIyMgRmFuY3kgQXJyYW5nZW1lbnQKYGBge3J9CmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGNvd3Bsb3QpCmRhdGEgPSBkZiAlPiUgZmlsdGVyKFN1YmZhbWlseSA9PSAidHNlaXRpbl9yZWdncmlkXzUiLCBgQ0EtdmFsdWVgID09ICJsYmQiLCBgUkUtdmFsdWVgID09ICJsYmQiLCBgVkQtdmFsdWVgID09ICJkZjgwIiwgYFBILXZhbHVlYCA9PSAic3RkIiwgYFBSLXZhbHVlYCA9PSAib2ZmIikKCnBsb3QxIDwtIGdncGxvdChkYXRhLCAKICAgICAgIGFlcyh4ID0gYFZhcmlhYmxlc2AsCiAgICAgICAgICAgeSA9IGBDUFUtdGltZWAsIGNvbG9yID0gYENFLXZhbHVlYCwgZ3JvdXAgPSBgSUQtY29uZmlndXJhdGlvbmApCiAgICAgICApICsgCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKCkgKwogIHRoZW1lKHBsb3QubWFyZ2luPXVuaXQoYygwLDIsMCwyKSwibW0iKSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBzY2FsZV9jb2xvdXJfZGlzY3JldGUobGFiZWxzID0gYygiZ2x1Y29zZSIsICJsaW5lYXIiLCAibWluaXNhdCIpKSArCiAgbGFicyh4ID0gIk51bWJlciBvZiB2YXJpYWJsZXMiLCB5ID0gIkNQVSB0aW1lIiwgY29sb3IgPSAiQ2xhdXNlIGVyYXN1cmU6IikKCmxlZ2VuZCA8LSBnZXRfbGVnZW5kKHBsb3QxKQpwbG90MSA8LSBwbG90MSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCnBsb3QyIDwtIGdncGxvdChkYXRhICU+JSBmaWx0ZXIoYFNvbHZlci1hbnN3ZXJgID09ICJVTlNBVElTRklBQkxFIiksIAogICAgICAgYWVzKHggPSBgVmFyaWFibGVzYCwKICAgICAgICAgICB5ID0gYENvbmZsaWN0c2AgLyAxMDAwMDAwLCBjb2xvciA9IGBDRS12YWx1ZWAsIGdyb3VwID0gYElELWNvbmZpZ3VyYXRpb25gKQogICAgICAgKSArIAogIGdlb21fcG9pbnQoKSArIGdlb21fbGluZSgpICsKICB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMCwyLDAsMyksIm1tIiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrCiAgbGFicyh4ID0gIk51bWJlciBvZiB2YXJpYWJsZXMiLCB5ID0gIk1pbGxpb24gY29uZmxpY3RzIikKCnRpdGxlUGxvdCA8LSBnZ3Bsb3QoKSArIGxhYnModGl0bGUgPSAiVHNlaXRpbiBmb3JtdWxhcyBvbiBncmlkIGdyYXBocyAoNSByb3dzKSIpICsKICB0aGVtZShwbG90Lm1hcmdpbj11bml0KGMoMiwyLDAsMiksIm1tIikpCgphcnJhbmdlIDwtIGFycmFuZ2VHcm9iKHBsb3QxLHBsb3QyLCBuY29sID0gMikKYXJyYW5nZSA8LSBhcnJhbmdlR3JvYih0aXRsZVBsb3QsIGFycmFuZ2UsIGxlZ2VuZCwgaGVpZ2h0cyA9IGMoMC44LDUsMC44KSAsbnJvdyA9IDMpCiAgICAKZ2dzYXZlKGZpbGVuYW1lID0gInBsb3RzL2NsYXVzZUVyYXN1cmUucGRmIiwgYXJyYW5nZSwgdW5pdHMgPSAiY20iLCBkZXZpY2UgPSAicGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNikKYGBgCgojIFBoYXNlIFNhdmluZwoKTG9hZCBQaGFzZSBTYXZpbmcgQmF0Y2gKCmBgYHtyfQpkZiA8LSBkYkdldFF1ZXJ5KGRiLCAiCiAgU0VMRUNUICogRlJPTSBFeHBlcmltZW50IGFzIG1haW4KICBpbm5lciBqb2luIEluc3RhbmNlCiAgCW9uIEluc3RhbmNlLmBJRC1JbnN0YW5jZWAgPSBtYWluLmBJRC1JbnN0YW5jZWAKICBpbm5lciBqb2luIENvbmZpZ3VyYXRpb24KICAJb24gQ29uZmlndXJhdGlvbi5gSUQtY29uZmlndXJhdGlvbmAgPSBtYWluLmBJRC1jb25maWd1cmF0aW9uYAp3aGVyZQogICAgYFN1YmZhbWlseWAgPSAnc3RvbmVfd2lkdGgzY2hhaW5fbmhhbGZtYXJrZXJzJwogYW5kIGBSRS12YWx1ZWAgaW4gKCdsYmQnLCAnbHVFMycpCiBhbmQgYFZELXZhbHVlYCBpbiAoJ2RmOTUnLCAnZGY4MCcpCiBhbmQgYFBILXZhbHVlYCBpbiAoJ2ZpeDAnLCAnc3RkJywgJ2R5bnJuZCcsICdmaXhybmQnLCAnY3RyJykKIGFuZCBgQ0UtdmFsdWVgIGluICgnZ2x1JywgJ21pbicpCiBhbmQgYENBLXZhbHVlYCBpbiAoJ3ZzaWRzJywgJ2xiZCcpCiBhbmQgYENMLXZhbHVlYCBpbiAoJzF1aXAnKQogYW5kIGBQUi12YWx1ZWAgaW4gKCdvbicsICdvZmYnKQogYW5kIGBTSC12YWx1ZWAgaW4gKCdvZmYnKTsiKQpkZiRgUkUtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgUkUtdmFsdWVgKQpkZiRgVkQtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgVkQtdmFsdWVgKQpkZiRgUEgtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgUEgtdmFsdWVgKQpkZiRgQ0UtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgQ0UtdmFsdWVgKQpkZiRgQ0EtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgQ0EtdmFsdWVgKQpkZiRgQ0wtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgQ0wtdmFsdWVgKQpkZiRgUFItdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgUFItdmFsdWVgKQpkZiRgU0gtdmFsdWVgIDwtIGFzLmZhY3RvcihkZiRgU0gtdmFsdWVgKQpkZiA8LSBkZlssICFkdXBsaWNhdGVkKGNvbG5hbWVzKGRmKSldCmBgYAoKYGBge3J9CmRhdGEgPSBkZiAlPiUgZmlsdGVyKFN1YmZhbWlseSA9PSAic3RvbmVfd2lkdGgzY2hhaW5fbmhhbGZtYXJrZXJzIiwgYENFLXZhbHVlYCA9PSAiZ2x1IiwgYFBSLXZhbHVlYCA9PSAib2ZmIiwgYENBLXZhbHVlYCA9PSAibGJkIiwgYFZELXZhbHVlYCA9PSAiZGY5NSIsIGBSRS12YWx1ZWAgPT0gImxiZCIpCgpwbG90IDwtIGdncGxvdChkYXRhLCAKICAgICAgIGFlcyh4ID0gYFZhcmlhYmxlc2AsCiAgICAgICAgICAgeSA9IGBDUFUtdGltZWAsIGNvbG9yID0gYFBILXZhbHVlYCkKICAgICAgICkgKyAKICBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMS4yLDAuNSksIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEuMiwgImxpbmVzIiksIHBsb3QubWFyZ2luPXVuaXQoYygxLDI1LDEsMiksIm1tIikpICsKICBzY2FsZV9jb2xvdXJfZGlzY3JldGUobGFiZWxzID0gYygiY291bnRlciIsICJkeW5hbWljXG5yYW5kb20iLCAiZml4IHplcm8iLCAiZml4IHJhbmRvbSIsICJzdGFuZGFyZCIpKSArCiAgbGFicyh4ID0gIk51bWJlciBvZiB2YXJpYWJsZXMiLCB5ID0gIkNQVSB0aW1lIiwgY29sb3IgPSAiUGhhc2U6IiwgdGl0bGUgPSAiU3RvbmUgZm9ybXVsYXMiLCBzdWJ0aXRsZSA9ICJvbiB3aWR0aCAzIGNoYWluLCAjc3RvbmVzID0gI25vZGVzIC8gMiIpCmdnc2F2ZShmaWxlbmFtZSA9ICJwbG90cy9waGFzZS5wZGYiLCB1bml0cyA9ICJjbSIsIGRldmljZSA9ICJwZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA1LjIpCnBsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikKYGBgCg==