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==