Data
Read the previous merged data
datPre <- read_tsv("../output/20220614-mar22-batch-bg-sub-data.tsv", col_types = "cccfdddddll") %>%
mutate(host = ordered(host))
list.mutations <- as.character(c(215, 209, 211, 210, 217, 218, 220, 221, 223, 224, 222, 227, 230, 229, 231, 233, 240, 241, 250:255, 257, 258))
exptPre <- datPre %>%
group_by(date, plasmid, host) %>%
summarize(n = n(), n_filter = sum(!low_event_count), .groups = "drop") %>%
mutate(flag = ifelse(plasmid %in% list.mutations, "mutation", ""))
Read the new batches of data
raw <- list(
"05/12/22" = read_tsv("../data/20220512-EO-repeat-batch-1/20220512-gated-median-out.txt", show_col_types = FALSE),
"05/17/22" = read_tsv("../data/20220517-EO-repeat-batch-2/20220517-gated-median-out.txt", show_col_types = FALSE),
"05/19/22" = read_tsv("../data/20220519-EO-repeat-batch-3/20220519-gated-median-out.txt", show_col_types = FALSE),
"05/31/22" = read_tsv("../data/20220531-EO-repeat-batch-4/20220531-gated-median-out.txt", show_col_types = FALSE),
"06/02/22" = read_tsv("../data/20220602-EO-repeat-batch-5/20220602-gated-median-out.txt", show_col_types = FALSE)
)
dat <- bind_rows(raw, .id = "date") %>%
#separate(col = well, sep = 1, into = c("row", "col")) %>%
separate(col = sample, sep = "-", into = c("plasmid", "host", "rep")) %>%
mutate(plasmid = na_if(plasmid, "NA"))
QC
1. Number of events per sample
dat %>% ggplot(aes(x = n_induction/1000)) + geom_histogram(bins = 30, fill = "forestgreen") +
xlab("# events x 1000") +
facet_grid(host~date, scales = "free_y") + theme_bw(base_size = 14) #+ panel_border()

Majority of the experimental wells (not blank) have > 10000
events, with the exception of a few samples
dat %>% filter(host != "blank", n_induction < 10000)
Nearly all samples with a low event count were in the 555 background.
Emily repeated many of them. Will remove all samples with lower than
7,000 events in the final gated population from further analysis.
Flag samples that have a low event count, contain mutations or show
multiple populations.
event.th <- 7000
dat <- dat %>%
mutate(
low_event_count = n_induction < event.th,
# Emily labeled the old plasmids with mutations with an "o" in the flow sample name column
mutation = ifelse(grepl("o$", name), TRUE, FALSE)
) %>%
filter(host != "blank")
2. Background subtraction
Check the background fluorescence levels across different days.
dat %>% filter(host == "156") %>%
mutate(date = gsub("/22", "", date)) %>%
pivot_longer(BL1.H:nRFP, names_to = "parameter", values_to = "intensity") %>%
mutate(parameter = ordered(parameter, levels = c("BL1.H", "YL2.H", "nGFP", "nRFP"))) %>%
ggplot(aes(x = date, y = intensity)) + geom_point(aes(shape = well)) +
stat_summary(fun.data = "mean_se", geom = "pointrange", color = "red", position = position_nudge(x = 0.1)) +
facet_wrap(~parameter, scale = "free_y") +
theme_bw(base_size = 14)

06/02 run had smaller FSC values (~ cell volume) compared with the
other days, while the background fluorescence doesn’t appear to be a lot
higher, resulting in higher normalized values.
Subtract the background
bg <- dat %>%
filter(host == "156") %>%
group_by(date) %>%
summarize(across(FSC.H:nRFP, ~ round(mean(.x),1))) %>%
column_to_rownames(var = "date")
dat1 <- dat %>%
filter(host != "blank") %>%
select(date:host, FSC.H:nRFP, low_event_count:mutation) %>%
mutate(
BL1.H = BL1.H - bg[date, "BL1.H"],
YL2.H = YL2.H - bg[date, "YL2.H"],
nGFP = nGFP - bg[date, "nGFP"],
nRFP = nRFP - bg[date, "nRFP"],
)
Double check that the subtraction worked correctly
dat1 %>% filter(host == "156") %>%
pivot_longer(BL1.H:nRFP, names_to = "parameter", values_to = "intensity") %>%
mutate(
parameter = ordered(parameter, levels = c("BL1.H", "YL2.H", "nGFP", "nRFP")),
date = gsub("\\/22$", "", date)
) %>%
ggplot(aes(x = date, y = intensity)) + geom_point(aes(shape = well)) +
stat_summary(fun.data = "mean_se", geom = "pointrange", color = "red", position = position_nudge(x = 0.1)) +
facet_wrap(~parameter, scale = "free_y") +
theme_bw(base_size = 14)

# remove the yH156 samples
dat1 <- dat1 %>%
filter(host != "156") %>%
mutate(host = ordered(host, levels = c("555", "373"), labels = c("PHO2", "pho2∆")))
3. Well position
Rationale
In my plate design, I placed a positive control strain (CgPho4-mNeon
in PHO2 background) in the control columns (1, 5, 9) on every
other row (A, C, E, G). The rationale for this is to use it to identify
any well position effect on the fluorescence readings. In this round of
repeat experiments, Emily followed this design and put pH188-yH323 in
these wells. Now we can properly assess the well position effect.
For this analysis, we will combine and compare the May/Jun batch with
the Mar batch
datM <- bind_rows(datPre, dat1)
datM %>%
filter(plasmid == "188", host == "PHO2") %>%
separate(well, into = c("row", "col"), sep = 1) %>%
pivot_longer(BL1.H:YL2.H, names_to = "parameter", values_to = "intensity") %>%
ggplot(aes(x = col, y = intensity, group = date)) +
geom_point(aes(color = date), size = 1) +
#geom_line(aes(color = date), size = 0.4) +
stat_summary(aes(color = date), geom = "line", fun = mean) +
scale_color_brewer(type = "qual", palette = 2) +
xlab("Column") +
facet_grid(parameter~row, scales = "free_y") +
theme_bw(base_size = 14)

- no obvious trend between the rows or columns
- a clear correlation between YL2.H and BL1.H.
Same plot for normalized fluorescence
datM %>%
filter(plasmid == "188", host == "PHO2") %>%
separate(well, into = c("row", "col"), sep = 1) %>%
pivot_longer(c(nGFP, nRFP), names_to = "parameter", values_to = "intensity") %>%
ggplot(aes(x = col, y = intensity, group = date)) +
geom_point(aes(color = date), size = 1) +
#geom_line(aes(color = date), size = 0.4) +
stat_summary(aes(color = date), geom = "line", fun = mean) +
scale_color_brewer(type = "qual", palette = 2) +
xlab("Column") +
facet_grid(parameter~row, scales = "free_y") +
theme_bw(base_size = 14)

- What we care about is the ratio between Pho4-mNeon and
PHO5pr-mCherry
datM %>%
filter(plasmid == "188", host == "PHO2") %>%
separate(well, into = c("row", "col"), sep = 1) %>%
ggplot(aes(x = BL1.H, y = YL2.H)) +
geom_point(aes(color = date, shape = row), size = 3) +
stat_smooth(method = "lm", se = FALSE, color = "gray50", size = 0.5) +
scale_color_brewer(type = "qual", palette = 2) +
#scale_color_viridis_d() +
#scale_shape_manual(values = c(15:17, 23, 25)) +
theme_bw(base_size = 14)
`geom_smooth()` using formula 'y ~ x'

- There is variation in BL1.H and correspondingly in YL2.H, but the
ratio between the two are very consistent
4. Run effect
How does the same control strain behave in different runs
(represented as date variable here)? Is there a strong run effect?
Let’s check both ScPho4 (pH194) and CgPho4 (pH188) to see if their
behaviors are consistent across days and between this and the last
(03/30) batch.
datM %>%
filter(plasmid %in% c("188", "194")) %>%
mutate(
date = gsub("/22$", "", date),
`YL2.H / BL1.H` = YL2.H / BL1.H,
Pho4 = factor(plasmid, levels = c("194", "188"), labels = c("ScPho4", "CgPho4"))
) %>%
separate(well, into = c("row", "col"), sep = 1) %>%
ggplot(aes(x = date, y = `YL2.H / BL1.H`, group = host)) +
geom_point(aes(color = host), position = position_jitter(0.1), alpha = 0.8, size = 1) +
scale_color_viridis_d(begin = 0.2, end = 0.6) +
stat_summary(fun.data = "mean_se", geom = "pointrange", shape = 16, color = "red") +
ylim(0, 30) + facet_grid(Pho4~.) + theme_bw(base_size = 14)

while the characteristic behaviors of ScPho4 and CgPho4 are
consistent across runs, there are also clear variability in the RFP/GFP
ratios between plates for the same genotype.
Next we examine the underlying background-subtracted fluorescence
values for pH188 and pH194 in the yH555 background, which are present on
each plate.
datM %>%
filter(plasmid %in% c("188", "194"), host == "PHO2") %>%
mutate(
date = gsub("/22$", "", date),
plasmid = factor(plasmid, levels = c("188", "194"), labels = c("CgPho4", "ScPho4"))
) %>%
pivot_longer(BL1.H:YL2.H, names_to = "parameter", values_to = "intensity") %>%
ggplot(aes(x = date, y = intensity, group = plasmid)) +
geom_point(aes(color = plasmid), alpha = 0.7, size = 1,
position = position_jitterdodge(jitter.width = 0.1, dodge.width = 0.7)) +
scale_color_manual(values = c("ScPho4" = "blue3", "CgPho4" = "forestgreen")) +
stat_summary(aes(color = plasmid), fun.data = "mean_se", geom = "crossbar", width = 0.4,
position = position_dodge(0.7)) +
facet_grid(parameter~., scale = "free_y") +
expand_limits(y = 0) +
theme_bw(base_size = 14) + labs(subtitle = "in PHO2 background")# +

#theme(plot.subtitle = element_markdown())
CgPho4 and ScPho4 values track each other – on days (runs) where one
is high, the other one also tends to be high. On the 05/31 run, ScPho4
is significantly higher than CgPho4.
datM %>%
filter(plasmid %in% c("188", "194"), host == "PHO2") %>%
mutate(
date = gsub("/22$", "", date),
plasmid = factor(plasmid, levels = c("188", "194"), labels = c("CgPho4", "ScPho4"))
) %>%
pivot_longer(nGFP:nRFP, names_to = "parameter", values_to = "intensity") %>%
ggplot(aes(x = date, y = intensity, group = plasmid)) +
geom_point(aes(color = plasmid), alpha = 0.7, size = 1,
position = position_jitterdodge(jitter.width = 0.1, dodge.width = 0.7)) +
scale_color_manual(values = c("ScPho4" = "blue3", "CgPho4" = "forestgreen")) +
stat_summary(aes(color = plasmid), fun.data = "mean_se", geom = "crossbar", width = 0.4,
position = position_dodge(0.7)) +
facet_grid(parameter~., scale = "free_y") +
expand_limits(y = 0) +
theme_bw(base_size = 14) + labs(subtitle = "in PHO2 background")# +

#theme(plot.subtitle = element_markdown())
The size normalized values show lower variance but a similar
correlated pattern. Here, however, ScPho4 overtakes CgPho4 on the 03/22
and 05/17 runs.
How about the RFP/GFP ratios?
datM %>%
filter(plasmid %in% c("188", "194"), host == "PHO2") %>%
mutate(
date = gsub("/22$", "", date),
plasmid = factor(plasmid, levels = c("188", "194"), labels = c("CgPho4", "ScPho4")),
`YL2 / BL1` = YL2.H / BL1.H,
`nRFP / nGFP` = nRFP / nGFP
) %>%
pivot_longer(`YL2 / BL1`:`nRFP / nGFP`, names_to = "parameter", values_to = "ratio") %>%
ggplot(aes(x = date, y = ratio, group = plasmid)) +
geom_point(aes(color = plasmid), alpha = 0.6, size = 1,
position = position_jitterdodge(jitter.width = 0.1, dodge.width = 0.7)) +
stat_summary(aes(color = plasmid), fun.data = "mean_se", geom = "crossbar", width = 0.4,
position = position_dodge(0.7)) +
scale_color_manual(values = c("ScPho4" = "blue3", "CgPho4" = "forestgreen")) +
facet_grid(parameter~.) + expand_limits(y = c(0,30)) +
theme_bw(base_size = 14) + labs(subtitle = "in PHO2 background")# +

#theme(plot.subtitle = element_markdown())
5. Statistical tests for confounding factors
Testing for run (date) as well as well (block) position effects on
fluorescence values. Using the nest-map-unnest
workflow
Note that in order to maintain a balanced design (same number of
replicates in each group), we will restrict the analysis to batches 1-4
in the May/Jun dataset. The March dataset had a different plate design,
while batch 5 of the May/Jun dataset is incomplete w.r.t. the controls
(because only half of the plate was used).
tmp <- filter(dat1, plasmid == "188", host == "PHO2", date != "06/02/22") %>%
separate(well, into = c("row", "col"), sep = 1, remove = FALSE) %>%
select(date, block = well, row, col, BL1.H:nRFP) %>%
mutate(RvG = YL2.H / BL1.H, nRvG = nRFP / nGFP)
tmp %>%
pivot_longer(cols = BL1.H:nRvG, names_to = "parameter", values_to = "value") %>%
nest(data = c(-parameter)) %>%
mutate(
fit = map(data, ~anova(lm(value ~ date + row + col, data = .x))),
tidied = map(fit, broom::tidy)
) %>%
unnest(tidied) %>%
mutate(
significant = case_when(
p.value < 0.001 ~ "***",
p.value < 0.01 ~ "**",
p.value < 0.05 ~ "*",
p.value < 0.1 ~ ".",
TRUE ~ " "
)) %>%
filter(term != "Residuals") %>%
select(parameter, term, df, statistic, p.value, significant)
There is a highly significant run (date) effect for all variables.
The R/G and nR/G ratios show significant column effects. I also tried
using block (12 blocks on the plate) and most of the block effects are
significant.
Use dummy encoding in linear regression to view the effects of run
and well position.
tmp %>%
mutate(row = factor(row, levels = c("G", "E", "C", "A"))) %>%
pivot_longer(cols = BL1.H:nRvG, names_to = "parameter", values_to = "value") %>%
nest(data = c(-parameter)) %>%
mutate(
fit = map(data, ~lm(value ~ date + row + col, dat = .x)),
tidied = map(fit, broom::tidy)
) %>%
unnest(tidied) %>%
mutate(
term = gsub("/22$", "", term),
estimate = round(estimate, digits = 2),
significant = case_when(
p.value < 0.001 ~ "***",
p.value < 0.01 ~ "**",
p.value < 0.05 ~ "*",
p.value < 0.1 ~ ".",
TRUE ~ " "
),
eff = paste(estimate, significant, sep = " ")
) %>%
select(parameter, term, eff) %>%
pivot_wider(names_from = parameter, values_from = eff)# %>%
#mutate(across(e_BL1:e_nRFP, ~ round(.x, digits = 0)))
- There is a significant run (date) effect for all variables. RvG
ratio appears to be better than nRvG in terms of being less affected by
either run or well positions.
- Row A has a higher fluorescence values overall. But the RvG ratios
are not significantly higher in row A.
- Column 9 has a significantly higher RvG, because, for some reason,
the RFP is higher but not the GFP.
With the above observations, it is yet unclear to me (1) whether it
is necessary to account for the run and position effects (if the effect
sizes we are interested in are much larger than these, we may not care)
and (2) if necessary, what’s the best way to account for it. One idea I
have is to use the common strains on each plate, e.g., the host strains
(no Pho4) or CgPho4 and ScPho4 with and without Pho2, as normalizing
factors. One can think of several ways of normalization, e.g., setting
ScPho4 w/ Pho2’s RvG as 100%. Will explore these ideas below.
Main
1. Mutation effects
Here we examine the effects of the mutations on the chimera activity.
Emily remade 26 chimeric constructs to correct the non-synonymous
mutations in them and reran those constructs in the May/Jun batch. While
doing that, she encountered some issues with certain samples not growing
well or the flow data showing multiple populations. She repeated some of
those strains. As a result, we have more than two measurements for some
of the strains. The goal in this analysis is to compare their
measurements both with and without mutations, and also across the
repeats.
Read in the experimental flags for the May/Jun batch, for the
multiple population labels
multipop <- read_tsv("../data/20220614-EO-repeat-experiment-info.tsv", col_types = cols()) %>%
filter(flag == "multi pop") %>% select(-flag) %>%
separate(sample, into = c("plasmid", "host"), sep = "-") %>%
mutate(host = ordered(host, levels = c("555", "373"), labels = c("PHO2", "pho2∆")), multi_pop = TRUE)
Create a flag variable
datN <- datM %>%
mutate(multi_pop = FALSE) %>%
rows_update(multipop, by = c("date", "plasmid", "host")) %>%
mutate(
RvG = ifelse(BL1.H > 0, YL2.H/BL1.H, NA),
#RvG = num(RvG, digits = 2),
flag = factor(mutation + multi_pop*2,
levels = as.character(0:3),
labels = c("pass", "mutation", "multi_pop", "mutation;multi_pop"))
) %>% relocate(RvG, .after = nRFP)
Emily has included two old samples containing mutations (pH209, 210)
along with the remade, mutation-free plasmids, in the new batch. Let’s
see how they compare with each other and with the March batch (with
mutations).
tmp <- filter(datN, plasmid %in% c("209", "210")) %>%
mutate(
month = str_sub(date, 1, 2),
sample = ifelse(month == "03", "03-old", ifelse(mutation, "05-old", "05-new")),
sample = factor(sample, levels = c("03-old", "05-old", "05-new"))
)
First compare the same plasmids (with mutations) measured on
different days
tmp %>%
select(-FSC.H) %>%
pivot_longer(BL1.H:RvG, names_to = "parameter", values_to = "value") %>%
mutate(parameter = factor(parameter, levels = c("BL1.H", "YL2.H", "nGFP", "nRFP", "RvG"))) %>%
ggplot(aes(x = plasmid, y = value, group = sample)) +
geom_point(aes(color = sample), size = 1, position = position_dodge(0.7)) +
#stat_summary(aes(color = sample), fun.data = "mean_se", geom = "crossbar", width = 0.1,
# position = position_dodge(0.7)) +
scale_color_manual(values = c("03-old" = "gray50", "05-old" = "gray30", "05-new" = "red2")) +
scale_y_continuous(n.breaks = 3) + expand_limits(y = 0) +
facet_grid(parameter~host, scales = "free_y") +
theme_bw(base_size = 14) + background_grid(major = "y")

tmp %>%
select(-FSC.H) %>%
pivot_longer(BL1.H:RvG, names_to = "parameter", values_to = "value") %>%
mutate(parameter = factor(parameter, levels = c("BL1.H", "YL2.H", "nGFP", "nRFP", "RvG"))) %>%
nest(data = c(-parameter)) %>%
mutate(
fit = map(data, ~anova(lm(value ~ sample + host, data = .x))),
tidied = map(fit, broom::tidy)
) %>%
unnest(tidied) %>%
mutate(
significant = case_when(
p.value < 0.001 ~ "***",
p.value < 0.01 ~ "**",
p.value < 0.05 ~ "*",
p.value < 0.1 ~ ".",
TRUE ~ " "
)) %>%
filter(term != "Residuals") %>%
select(parameter, term, df, statistic, p.value, significant)
For the RvG ratio, there is no significant difference between the
03-old, 05-old and 05-new. In other words, we don’t have evidence that
either the different runs or the correction of mutations impacted the
behavior of the chimera in the case of pH209 and pH210.
We will now move on to the rest of the plasmids that have been
remade.
pp <- theme(axis.title.x = element_blank(), legend.position = "none")
myPlotMutEffect <- function(l){
even_numbers <- seq(2, length(l), 2) # used to draw stripes on even numbered x-values
df_tile <- tibble(plasmid = rep(sort(l)[even_numbers], times = 2),
host = factor(rep(c("PHO2", "pho2∆"), each = length(even_numbers))))
datN %>%
#mutate(date = gsub("/22$", "", date)) %>%
filter(!low_event_count, plasmid %in% l) %>%
select(date:host, RvG, flag) %>%
ggplot(aes(x = plasmid, y = RvG)) +
# draw stripes on even columns,
# from: https://stackoverflow.com/questions/56961744/draw-alternate-rectangles-in-boxplots-with-facets-r-ggplot2'
geom_tile(aes(x = plasmid, y = 1), height = Inf, width = 1, data = df_tile, alpha = 0.3) +
#ymin = -Inf, ymax = Inf, fill = "grey80", color = NA, alpha = 0.5) +
geom_point(aes(color = flag, group = date), size = 1.5, shape = 19,
position = position_jitterdodge(jitter.width = 0.1, dodge.width = 0.7)) +
#stat_summary(aes(color = sample), fun.data = "mean_se", geom = "crossbar", width = 0.1,
# position = position_dodge(0.7)) +
scale_color_manual(values = c("pass" = "forestgreen", "mutation" = "purple", "multi_pop" = "steelblue3")) +
scale_y_continuous(n.breaks = 4) + expand_limits(y = 0) +
facet_grid(host~., scales = "free_y") +
theme_cowplot() + panel_border(color = "gray30") +
theme(strip.text = element_text(face = 3))
}
lst <- split(list.mutations, f = ceiling(seq_along(list.mutations)/9))
p <- lapply(lst, myPlotMutEffect)
legend_p <- get_legend(p[[1]] + theme(legend.position = "bottom", legend.justification = "center"))
plot_grid(p[[1]] + pp, p[[2]] + pp, p[[3]] + theme(legend.position = "none"), legend_p, ncol = 1, rel_heights = c(1,1,1,.15))

Samples showing multiple populations mostly agree with the latter
measurements where the issue was ressolved, with the exception of one of
the samples of 231 in PHO2 background.
Here are the ones that show obvious differences between the old and
corrected constructs:
ll <- c("215", "218", "227", "233", "241", "252", "257")
myPlotMutEffect(ll) + scale_y_log10()
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.
Warning: Transformation introduced infinite values in continuous y-axis

2. Summarize results per chimera
We will remove all the measurements made of chimeras with mutations.
For the measurements made of remade, corrected chimeras, we will remove
one sample for pH231 from the 05/19 batch (well C2, the
other 2 replicates of the same strain in that batch were removed due to
the presence of multiple populations and low event count in the gated
population), as well as one sample for pH233 from the 06/02
batch (well D4, which showed overexpression of the
chimera).
Number of replicates measured for each chimera x host
combination:
# load genotype information
meta <- read_tsv("../data/20220621-chimera-Pho4-makeup.tsv", col_types = "ccccc") %>%
rename(genotype = full) %>% select(-plasmid_wrong)
datN %>%
filter(!low_event_count, !mutation) %>%
count(plasmid, host) %>%
pivot_wider(names_from = host, values_from = n) %>%
full_join(meta, by = "plasmid") %>%
select(-letter, -genotype)
pH211 was measured 9 times in the PHO2 background. The
results were consistent.
For each chimera, we would like to calculate three
values:
- RvG in pho2∆: this is its base activity without Pho2
- RvG in PHO2: this is its full activity with Pho2
- RvG_PHO2 / RvG_pho2∆: this is the Pho2 enhancement of activity
The first two values are further normalized against the corresponding
ScPho4 measurements on the same plate.
# filter data
tmp <- filter(datN, !low_event_count, !mutation, !is.na(plasmid)) %>% select(date:host, BL1.H:RvG)
# calculate the ScPho4 values per plate
mScPho4 <- tmp %>% filter(plasmid == "194") %>% group_by(date, host) %>% summarize(mean = mean(RvG), .groups = "drop") %>%
pivot_wider(names_from = host, values_from = mean) %>% column_to_rownames(var = "date")
# normalize the values for non-ScPho4 with those of ScPho4 per plate
datO <- tmp %>% mutate(sRvG = RvG / mScPho4[cbind(date, as.character(host))])
# summarize
datsum <- datO %>%
group_by(plasmid, host) %>%
summarize(across(RvG:sRvG, mean), .groups = "drop") %>%
pivot_wider(names_from = host, values_from = RvG:sRvG) %>%
rename(`A_PHO2` = `RvG_PHO2`, `A_pho2` = `RvG_pho2∆`, full = sRvG_PHO2, base = `sRvG_pho2∆`) %>%
mutate(boost = `A_PHO2` / `A_pho2`, across(`A_PHO2`:boost, ~ round(.x, digits = 3))) %>%
full_join(meta, by = "plasmid")
Export the summary data
write_tsv(datsum, file = "../output/20220619-chimera-summary-result.tsv")
Here are the chimera that have little full activity (with Pho2):
| 229 |
1.154 |
1.288 |
0.045 |
0.910 |
0.896 |
SSSCS |
Sc(1-176) Cg(283-458) Sc(243-312) |
| 250 |
1.695 |
1.873 |
0.071 |
1.632 |
0.905 |
CSSCS |
Cg(1-44) Sc(43-176) Cg(283-458) Sc(243-312) |
| 224 |
2.750 |
1.473 |
0.108 |
1.040 |
1.868 |
SCSCS |
Sc(1-42) Cg(45-112) Sc(100-176) Cg(283-458)
Sc(243-312) |
| 235 |
2.169 |
2.188 |
0.109 |
2.211 |
0.991 |
SSCCS |
Sc(1-99) Cg(113-458) Sc(243-312) |
| 220 |
2.979 |
2.839 |
0.116 |
2.005 |
1.049 |
SCSCC |
Sc(1-42) Cg(45-112) Sc(100-176) Cg(283-533) |
| 240 |
3.093 |
2.582 |
0.125 |
2.093 |
1.198 |
CCSCS |
Cg(1-112) Sc(100-176) Cg(283-458) Sc(243-312) |
| 216 |
3.774 |
3.704 |
0.139 |
2.519 |
1.019 |
SCCCS |
Sc(1-42) Cg(45-458) Sc(243-312) |
| 227 |
3.722 |
2.763 |
0.155 |
2.409 |
1.347 |
SSSCC |
Sc(1-176) Cg(283-533) |
| 253 |
3.287 |
3.396 |
0.175 |
3.309 |
0.968 |
CSCCS |
Cg(1-44) Sc(43-99) Cg(113-458) Sc(243-312) |
Here are the ones with the highest base activity (without Pho2):
| 188 |
20.771 |
17.674 |
0.899 |
14.709 |
1.175 |
CCCCC |
Cg(1-533) |
| 257 |
40.497 |
20.073 |
1.583 |
14.174 |
2.017 |
CCCscC |
Cg (1-282) Sc(177-204) Cg(328-533) |
| 213 |
13.974 |
11.972 |
0.700 |
12.097 |
1.167 |
CSCCC |
Cg(1-44) Sc(43-99) Cg(113-533) |
| 212 |
17.570 |
13.155 |
0.646 |
8.945 |
1.336 |
SCCCC |
Sc(1-42) Cg(45-533) |
| 209 |
10.920 |
8.746 |
0.456 |
7.624 |
1.249 |
CCSCC |
Cg(1-112) Sc(100-176) Cg(283-533) |
| 255 |
18.337 |
7.505 |
0.765 |
6.541 |
2.443 |
CSSscC |
Cg(1-44) Sc(43-204) Cg(328-533) |
| 219 |
47.187 |
9.115 |
1.734 |
6.198 |
5.177 |
CCCSS |
Cg(1-282) Sc(177-312) |
| 215 |
8.904 |
7.686 |
0.348 |
5.427 |
1.159 |
SSCCC |
Sc(1-99) Cg(113-533) |
| 210 |
6.359 |
5.536 |
0.265 |
4.825 |
1.149 |
CCCCS |
Cg(1-458) Sc(243-312) |
| 266 |
6.546 |
5.438 |
0.273 |
4.740 |
1.204 |
SSscCC |
Sc(1-153) Cg(250-533) |
3. Plotting functions
The goal here is to develop a set of plotting functions to visualize
the results.
For testing purposes, we will select a set of chimera along with the
endogenous ScPho4 and CgPho4.
# extract ximera names
refs <- c("CCCCC","SSSSS")
ximeras <- setdiff(meta$symbol, refs)
# make a test set
test <- c(refs, filter(meta, plasmid %in% c("211", "229", "250", "224", "257", "219", "266")) %>% pull(symbol))
# subset data
datT <- meta %>%
filter(symbol %in% test) %>%
inner_join(datO, by = "plasmid") %>%
mutate(symbol = factor(symbol, levels = test))
Design a set of color palettes:
# for two groups, e.g., with vs w/o Pho2
cols.two <- c("PHO2" = "#457dbc", "pho2∆" = "#ea9e25")
Plot individual components and the normalized activity (RvG
ratio)
datT %>%
pivot_longer(c(nGFP, nRFP, RvG), names_to = "parameter", values_to = "intensity") %>%
mutate(parameter = ordered(parameter, levels = c("nGFP", "nRFP", "RvG"),
labels = c("Pho4-GFP", "_PHO5pr_ => RFP", "Activity = RFP/GFP"))) %>%
#pivot_longer(BL1.H:YL2.H, names_to = "parameter", values_to = "intensity") %>%
#mutate(parameter = ordered(parameter, levels = c("YL2.H", "BL1.H"))) %>%
ggplot(aes(x = symbol, y = intensity, group = host)) +
geom_bar(aes(fill = host), width = 0.5,# alpha = 0.8,
stat = "summary", fun = "mean", position = position_dodge(0.5)) +
geom_point(aes(color = host), size = 1, alpha = 0.9, shape = 3,
position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.5)) +
scale_color_manual("co-TF", values = c("PHO2" = "gray30", "pho2∆" = "gray40")) +
scale_fill_manual("co-TF", values = cols.two) +
#stat_summary(fun = "mean", geom = "crossbar", color = "red", width = 0.25,
# position = position_dodge(0.75), ) +
facet_wrap(~parameter, scale = "free_y", ncol = 1) +
xlab("Pho4 chimera") + expand_limits(y = 0) +
theme_bw(base_size = 14) +
theme(axis.text.x = element_text(angle = 30, hjust = 1, family = "mono"),
strip.text = element_markdown())

Plot the RvG values normalized against the corresponding ScPho4
construct on the same plate, to obtain a relative measure.
# useful to group the plasmids
ximera.grp <- datsum %>%
mutate(group = case_when(
full < 0.2 ~ "defective",
base > 5 ~ "less Pho2-dep.",
TRUE ~ "others"
)) %>% select(plasmid, symbol, group)
p0 <- datT %>%
left_join(ximera.grp, by = c("symbol", "plasmid")) %>%
ggplot(aes(x = symbol, y = sRvG, group = host)) +
geom_bar(aes(fill = host), width = 0.5,# alpha = 0.8,
stat = "summary", fun = "mean", position = position_dodge(0.5)) +
geom_point(aes(color = host), size = 1, alpha = 0.9, shape = 3,
position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.5)) +
scale_color_manual(values = c("PHO2" = "gray30", "pho2∆" = "gray40"), guide = "none") +
scale_fill_manual(values = cols.two, guide = "none") +
#stat_summary(fun = "mean", geom = "crossbar", color = "red", width = 0.25,
# position = position_dodge(0.75), ) +
facet_grid(host~group, scale = "free") +
xlab("Pho4 chimera") + ylab("A<sub>chimera</sub> / A<sub>ScPho4</sub>") +
theme_bw(base_size = 14) + background_grid(minor = "none") +
theme(axis.text.x = element_text(angle = 30, hjust = 1, family = "mono"),
strip.text = element_markdown(), axis.title.y = element_markdown())
p1 <- datsum %>%
filter(symbol %in% test) %>%
left_join(ximera.grp, by = c("plasmid", "symbol")) %>%
ggplot(aes(x = symbol, y = boost)) +
geom_col(width = 0.3, color = "black", fill = "gray80") +
geom_hline(yintercept = 1, linetype = 2, color = "gray30") +
facet_wrap(~group, scales = "free_x") +
scale_y_log10() +
xlab("Pho4 chimera") + ylab("A<sub>PHO2</sub> / A<sub>pho2∆</sub>") +
theme_bw(base_size = 14) + background_grid(minor = "none") +
theme(axis.text.x = element_text(angle = 30, hjust = 1, family = "mono"),
strip.text = element_blank(), axis.title.y = element_markdown())
set_null_device("png") # from https://github.com/wilkelab/cowplot/issues/174
plot_grid(p0 + theme(axis.title.x = element_blank()),
p1, ncol = 1, rel_heights = c(3,2))

save the data objects for the interactive data plotter
save(datO, datsum, meta, file = "../shinyapp/20220620-data-for-interactive-plotting.RData")
Design the plot
tmpsum %>%
mutate(Activity = ifelse(`R/G_PHO2` < 2*low.act.th["R/G_pho2∆"], "low", "pass")) %>%
ggplot(aes(x = symbol, y = `pho2∆/PHO2`)) +
geom_col(aes(group = date, fill = `R/G_PHO2`), width = 0.75, color = "gray50",
position = position_dodge(0.9)) +
#geom_point(aes(color = host), position = position_jitterdodge(dodge.width = 0.5)) +
scale_fill_gradient2("Activity") +
#scale_color_manual(values = c(alpha("black",0), "red3")) +
#stat_summary(fun = "mean", color = "red", geom = "crossbar", width = 0.2,
# position = position_dodge(0.75), ) +
facet_grid(.~Activity, scales = "free_x", space = "free_x", labeller = "label_both") +
theme_bw(base_size = 14) + xlab("Pho4 chimera") +
theme(axis.text.x = element_text(angle = 30, hjust = 1, family = "mono"))
X-Y plot
p3 <- tmpsum %>%
mutate(`nR/G_PHO2` = signif(`nR/G_PHO2`, digits = 2),
`nR/G_pho2∆` = signif(`nR/G_pho2∆`, digits = 2)) %>%
ggplot(aes(x = `nR/G_PHO2`, y = `nR/G_pho2∆`, label = symbol)) +
geom_point(size = 2.5) + geom_abline(slope = 1) +
theme_gray(base_size = 14)
ggplotly(p3, tooltip = c("label", "x", "y"))
LS0tCnRpdGxlOiAiRTAxMyBQaG80IGNoaW1lcmEgYWN0aXZpdHkgYW5hbHlzaXMsIG5ldyBob3N0LCBjb25zdHJ1Y3RzIHdpdGggbXV0YXRpb25zIHJlcGxhY2VkIgphdXRob3I6IEJpbiBIZQpkYXRlOiAiMjAyMi0wMy0zMCAodXBkYXRlZCBgciBTeXMuRGF0ZSgpYCkiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMocmVxdWlyZShwbG90bHkpKQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMocmVxdWlyZSh0aWR5dmVyc2UpKQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMocmVxdWlyZShjb3dwbG90KSkKc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHJlcXVpcmUoZ2d0ZXh0KSkKYGBgCgojIEJhY2tncm91bmQKRW1pbHkgZm91bmQgb3V0IHRoYXQgYSBudW1iZXIgb2YgY29uc3RydWN0cyBpbmNsdWRlZCBpbiB0aGUgbGFzdCBiYXRjaCBvZiBleHBlcmltZW50cyBoYWQgbm9uc3lub255bW91cyBtdXRhdGlvbnMuIFRvIGVuc3VyZSB0aGF0IHRoZSByZXN1bHRzIHdlcmUgbm90IGR1ZSB0byBtdXRhdGlvbnMsIHNoZSByZW1hZGUgdGhvc2UgY29uc3RydWN0cyB1c2luZyBoaWdoZXIgZmlkZWxpdHkgZW56eW1lcy4KCiMgR29hbAotIFF1YWxpdHkgY29udHJvbCBmb3IgdGhlIG5ldyBiYXRjaCBvZiByZXBlYXQgZXhwZXJpbWVudHMuIERldGVybWluZSBpZiB0aGVyZSBpcyBhbnkgd2VsbCBwb3NpdGlvbiBlZmZlY3QgYW5kIGhvdyB3ZWxsIHRoZSB2YWx1ZXMgYWdyZWUgYWNyb3NzIG11bHRpcGxlIGRheXMgb2YgZXhwZXJpbWVudHMuCi0gT25jZSBRQyBpcyBkb25lLCBtZXJnZSB0aGUgbmV3LCByZXBlYXQgZGF0YXNldCB3aXRoIHRoZSBvbGQgb25lLCByZXBsYWNpbmcgdGhlIHJlc3VsdHMgZm9yIHRoZSBvbGQgY29uc3RydWN0cyB3aXRoIG11dGF0aW9ucy4KLSBJbXBsZW1lbnQgdGhlIGlkZWEgb2Ygc2VwYXJhdGluZyB0aGUgYmFzYWwgYWN0aXZpdHkgYW5kIFBobzItYm9vc3QgdHJhaXRzLgoKIyBEYXRhClJlYWQgdGhlIHByZXZpb3VzIG1lcmdlZCBkYXRhCmBgYHtyfQpkYXRQcmUgPC0gcmVhZF90c3YoIi4uL291dHB1dC8yMDIyMDYxNC1tYXIyMi1iYXRjaC1iZy1zdWItZGF0YS50c3YiLCBjb2xfdHlwZXMgPSAiY2NjZmRkZGRkbGwiKSAlPiUgCiAgbXV0YXRlKGhvc3QgPSBvcmRlcmVkKGhvc3QpKQoKbGlzdC5tdXRhdGlvbnMgPC0gYXMuY2hhcmFjdGVyKGMoMjE1LCAyMDksIDIxMSwgMjEwLCAyMTcsIDIxOCwgMjIwLCAyMjEsIDIyMywgMjI0LCAyMjIsIDIyNywgMjMwLCAyMjksIDIzMSwgMjMzLCAyNDAsIDI0MSwgMjUwOjI1NSwgMjU3LCAyNTgpKQoKZXhwdFByZSA8LSBkYXRQcmUgJT4lIAogIGdyb3VwX2J5KGRhdGUsIHBsYXNtaWQsIGhvc3QpICU+JSAKICBzdW1tYXJpemUobiA9IG4oKSwgbl9maWx0ZXIgPSBzdW0oIWxvd19ldmVudF9jb3VudCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBtdXRhdGUoZmxhZyA9IGlmZWxzZShwbGFzbWlkICVpbiUgbGlzdC5tdXRhdGlvbnMsICJtdXRhdGlvbiIsICIiKSkKYGBgCgpSZWFkIHRoZSBuZXcgYmF0Y2hlcyBvZiBkYXRhCmBgYHtyfQpyYXcgPC0gbGlzdCgKICAiMDUvMTIvMjIiID0gcmVhZF90c3YoIi4uL2RhdGEvMjAyMjA1MTItRU8tcmVwZWF0LWJhdGNoLTEvMjAyMjA1MTItZ2F0ZWQtbWVkaWFuLW91dC50eHQiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSwKICAiMDUvMTcvMjIiID0gcmVhZF90c3YoIi4uL2RhdGEvMjAyMjA1MTctRU8tcmVwZWF0LWJhdGNoLTIvMjAyMjA1MTctZ2F0ZWQtbWVkaWFuLW91dC50eHQiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSwKICAiMDUvMTkvMjIiID0gcmVhZF90c3YoIi4uL2RhdGEvMjAyMjA1MTktRU8tcmVwZWF0LWJhdGNoLTMvMjAyMjA1MTktZ2F0ZWQtbWVkaWFuLW91dC50eHQiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSwKICAiMDUvMzEvMjIiID0gcmVhZF90c3YoIi4uL2RhdGEvMjAyMjA1MzEtRU8tcmVwZWF0LWJhdGNoLTQvMjAyMjA1MzEtZ2F0ZWQtbWVkaWFuLW91dC50eHQiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSwKICAiMDYvMDIvMjIiID0gcmVhZF90c3YoIi4uL2RhdGEvMjAyMjA2MDItRU8tcmVwZWF0LWJhdGNoLTUvMjAyMjA2MDItZ2F0ZWQtbWVkaWFuLW91dC50eHQiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQopCmRhdCA8LSBiaW5kX3Jvd3MocmF3LCAuaWQgPSAiZGF0ZSIpICU+JSAKICAjc2VwYXJhdGUoY29sID0gd2VsbCwgc2VwID0gMSwgaW50byA9IGMoInJvdyIsICJjb2wiKSkgJT4lIAogIHNlcGFyYXRlKGNvbCA9IHNhbXBsZSwgc2VwID0gIi0iLCBpbnRvID0gYygicGxhc21pZCIsICJob3N0IiwgInJlcCIpKSAlPiUgCiAgbXV0YXRlKHBsYXNtaWQgPSBuYV9pZihwbGFzbWlkLCAiTkEiKSkKYGBgCgoKIyBRQwojIyAxLiBOdW1iZXIgb2YgZXZlbnRzIHBlciBzYW1wbGUKYGBge3J9CmRhdCAlPiUgZ2dwbG90KGFlcyh4ID0gbl9pbmR1Y3Rpb24vMTAwMCkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBmaWxsID0gImZvcmVzdGdyZWVuIikgKyAKICB4bGFiKCIjIGV2ZW50cyB4IDEwMDAiKSArCiAgZmFjZXRfZ3JpZChob3N0fmRhdGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KSAjKyBwYW5lbF9ib3JkZXIoKQpgYGAKCj4gTWFqb3JpdHkgb2YgdGhlIGV4cGVyaW1lbnRhbCB3ZWxscyAobm90IGJsYW5rKSBoYXZlID4gMTAwMDAgZXZlbnRzLCB3aXRoIHRoZSBleGNlcHRpb24gb2YgYSBmZXcgc2FtcGxlcwoKYGBge3J9CmRhdCAlPiUgZmlsdGVyKGhvc3QgIT0gImJsYW5rIiwgbl9pbmR1Y3Rpb24gPCAxMDAwMCkKYGBgCj4gTmVhcmx5IGFsbCBzYW1wbGVzIHdpdGggYSBsb3cgZXZlbnQgY291bnQgd2VyZSBpbiB0aGUgNTU1IGJhY2tncm91bmQuIEVtaWx5IHJlcGVhdGVkIG1hbnkgb2YgdGhlbS4KPiBXaWxsIHJlbW92ZSBhbGwgc2FtcGxlcyB3aXRoIGxvd2VyIHRoYW4gNywwMDAgZXZlbnRzIGluIHRoZSBmaW5hbCBnYXRlZCBwb3B1bGF0aW9uIGZyb20gZnVydGhlciBhbmFseXNpcy4KCkZsYWcgc2FtcGxlcyB0aGF0IGhhdmUgYSBsb3cgZXZlbnQgY291bnQsIGNvbnRhaW4gbXV0YXRpb25zIG9yIHNob3cgbXVsdGlwbGUgcG9wdWxhdGlvbnMuCmBgYHtyfQpldmVudC50aCA8LSA3MDAwCgpkYXQgPC0gZGF0ICU+JSAKICBtdXRhdGUoCiAgICBsb3dfZXZlbnRfY291bnQgPSBuX2luZHVjdGlvbiA8IGV2ZW50LnRoLAogICAgIyBFbWlseSBsYWJlbGVkIHRoZSBvbGQgcGxhc21pZHMgd2l0aCBtdXRhdGlvbnMgd2l0aCBhbiAibyIgaW4gdGhlIGZsb3cgc2FtcGxlIG5hbWUgY29sdW1uCiAgICBtdXRhdGlvbiA9IGlmZWxzZShncmVwbCgibyQiLCBuYW1lKSwgVFJVRSwgRkFMU0UpCiAgKSAlPiUgCiAgZmlsdGVyKGhvc3QgIT0gImJsYW5rIikKYGBgCgojIyAyLiBCYWNrZ3JvdW5kIHN1YnRyYWN0aW9uCgpDaGVjayB0aGUgYmFja2dyb3VuZCBmbHVvcmVzY2VuY2UgbGV2ZWxzIGFjcm9zcyBkaWZmZXJlbnQgZGF5cy4KYGBge3J9CmRhdCAlPiUgZmlsdGVyKGhvc3QgPT0gIjE1NiIpICU+JSAKICBtdXRhdGUoZGF0ZSA9IGdzdWIoIi8yMiIsICIiLCBkYXRlKSkgJT4lIAogIHBpdm90X2xvbmdlcihCTDEuSDpuUkZQLCBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCB2YWx1ZXNfdG8gPSAiaW50ZW5zaXR5IikgJT4lIAogIG11dGF0ZShwYXJhbWV0ZXIgPSBvcmRlcmVkKHBhcmFtZXRlciwgbGV2ZWxzID0gYygiQkwxLkgiLCAiWUwyLkgiLCAibkdGUCIsICJuUkZQIikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGludGVuc2l0eSkpICsgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSB3ZWxsKSkgKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9ICJtZWFuX3NlIiwgZ2VvbSA9ICJwb2ludHJhbmdlIiwgY29sb3IgPSAicmVkIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4ID0gMC4xKSkgKwogIGZhY2V0X3dyYXAofnBhcmFtZXRlciwgc2NhbGUgPSAiZnJlZV95IikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQpgYGAKCj4gMDYvMDIgcnVuIGhhZCBzbWFsbGVyIEZTQyB2YWx1ZXMgKH4gY2VsbCB2b2x1bWUpIGNvbXBhcmVkIHdpdGggdGhlIG90aGVyIGRheXMsIHdoaWxlIHRoZSBiYWNrZ3JvdW5kIGZsdW9yZXNjZW5jZSBkb2Vzbid0IGFwcGVhciB0byBiZSBhIGxvdCBoaWdoZXIsIHJlc3VsdGluZyBpbiBoaWdoZXIgbm9ybWFsaXplZCB2YWx1ZXMuCgpTdWJ0cmFjdCB0aGUgYmFja2dyb3VuZApgYGB7cn0KYmcgPC0gZGF0ICU+JSAKICBmaWx0ZXIoaG9zdCA9PSAiMTU2IikgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpemUoYWNyb3NzKEZTQy5IOm5SRlAsIH4gcm91bmQobWVhbigueCksMSkpKSAlPiUgCiAgY29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJkYXRlIikKCmRhdDEgPC0gZGF0ICU+JSAKICBmaWx0ZXIoaG9zdCAhPSAiYmxhbmsiKSAlPiUgCiAgc2VsZWN0KGRhdGU6aG9zdCwgRlNDLkg6blJGUCwgbG93X2V2ZW50X2NvdW50Om11dGF0aW9uKSAlPiUKICBtdXRhdGUoCiAgICBCTDEuSCA9IEJMMS5IIC0gYmdbZGF0ZSwgIkJMMS5IIl0sCiAgICBZTDIuSCA9IFlMMi5IIC0gYmdbZGF0ZSwgIllMMi5IIl0sCiAgICBuR0ZQID0gbkdGUCAtIGJnW2RhdGUsICJuR0ZQIl0sCiAgICBuUkZQID0gblJGUCAtIGJnW2RhdGUsICJuUkZQIl0sCiAgKQpgYGAKCkRvdWJsZSBjaGVjayB0aGF0IHRoZSBzdWJ0cmFjdGlvbiB3b3JrZWQgY29ycmVjdGx5CmBgYHtyfQpkYXQxICU+JSBmaWx0ZXIoaG9zdCA9PSAiMTU2IikgJT4lIAogIHBpdm90X2xvbmdlcihCTDEuSDpuUkZQLCBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCB2YWx1ZXNfdG8gPSAiaW50ZW5zaXR5IikgJT4lIAogIG11dGF0ZSgKICAgIHBhcmFtZXRlciA9IG9yZGVyZWQocGFyYW1ldGVyLCBsZXZlbHMgPSBjKCJCTDEuSCIsICJZTDIuSCIsICJuR0ZQIiwgIm5SRlAiKSksCiAgICBkYXRlID0gZ3N1YigiXFwvMjIkIiwgIiIsIGRhdGUpCiAgKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGludGVuc2l0eSkpICsgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSB3ZWxsKSkgKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9ICJtZWFuX3NlIiwgZ2VvbSA9ICJwb2ludHJhbmdlIiwgY29sb3IgPSAicmVkIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4ID0gMC4xKSkgKwogIGZhY2V0X3dyYXAofnBhcmFtZXRlciwgc2NhbGUgPSAiZnJlZV95IikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQoKIyByZW1vdmUgdGhlIHlIMTU2IHNhbXBsZXMKZGF0MSA8LSBkYXQxICU+JSAKICBmaWx0ZXIoaG9zdCAhPSAiMTU2IikgJT4lCiAgbXV0YXRlKGhvc3QgPSBvcmRlcmVkKGhvc3QsIGxldmVscyA9IGMoIjU1NSIsICIzNzMiKSwgbGFiZWxzID0gYygiUEhPMiIsICJwaG8y4oiGIikpKQpgYGAKCgojIyAzLiBXZWxsIHBvc2l0aW9uCgoqKl9SYXRpb25hbGVfKioKCkluIG15IHBsYXRlIGRlc2lnbiwgSSBwbGFjZWQgYSBwb3NpdGl2ZSBjb250cm9sIHN0cmFpbiAoQ2dQaG80LW1OZW9uIGluIF9QSE8yXyBiYWNrZ3JvdW5kKSBpbiB0aGUgY29udHJvbCBjb2x1bW5zICgxLCA1LCA5KSBvbiBldmVyeSBvdGhlciByb3cgKEEsIEMsIEUsIEcpLiBUaGUgcmF0aW9uYWxlIGZvciB0aGlzIGlzIHRvIHVzZSBpdCB0byBpZGVudGlmeSBhbnkgd2VsbCBwb3NpdGlvbiBlZmZlY3Qgb24gdGhlIGZsdW9yZXNjZW5jZSByZWFkaW5ncy4gSW4gdGhpcyByb3VuZCBvZiByZXBlYXQgZXhwZXJpbWVudHMsIEVtaWx5IGZvbGxvd2VkIHRoaXMgZGVzaWduIGFuZCBwdXQgcEgxODgteUgzMjMgaW4gdGhlc2Ugd2VsbHMuIE5vdyB3ZSBjYW4gcHJvcGVybHkgYXNzZXNzIHRoZSB3ZWxsIHBvc2l0aW9uIGVmZmVjdC4KCkZvciB0aGlzIGFuYWx5c2lzLCB3ZSB3aWxsIGNvbWJpbmUgYW5kIGNvbXBhcmUgdGhlIE1heS9KdW4gYmF0Y2ggd2l0aCB0aGUgTWFyIGJhdGNoCmBgYHtyfQpkYXRNIDwtIGJpbmRfcm93cyhkYXRQcmUsIGRhdDEpCmBgYAoKYGBge3J9CmRhdE0gJT4lIAogIGZpbHRlcihwbGFzbWlkID09ICIxODgiLCBob3N0ID09ICJQSE8yIikgJT4lIAogIHNlcGFyYXRlKHdlbGwsIGludG8gPSBjKCJyb3ciLCAiY29sIiksIHNlcCA9IDEpICU+JSAKICBwaXZvdF9sb25nZXIoQkwxLkg6WUwyLkgsIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIHZhbHVlc190byA9ICJpbnRlbnNpdHkiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sLCB5ID0gaW50ZW5zaXR5LCBncm91cCA9IGRhdGUpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gZGF0ZSksIHNpemUgPSAxKSArIAogICNnZW9tX2xpbmUoYWVzKGNvbG9yID0gZGF0ZSksIHNpemUgPSAwLjQpICsKICBzdGF0X3N1bW1hcnkoYWVzKGNvbG9yID0gZGF0ZSksIGdlb20gPSAibGluZSIsIGZ1biA9IG1lYW4pICsKICBzY2FsZV9jb2xvcl9icmV3ZXIodHlwZSA9ICJxdWFsIiwgcGFsZXR0ZSA9IDIpICsKICB4bGFiKCJDb2x1bW4iKSArCiAgZmFjZXRfZ3JpZChwYXJhbWV0ZXJ+cm93LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQpgYGAKCj4gLSBubyBvYnZpb3VzIHRyZW5kIGJldHdlZW4gdGhlIHJvd3Mgb3IgY29sdW1ucwo+IC0gYSBjbGVhciBjb3JyZWxhdGlvbiBiZXR3ZWVuIFlMMi5IIGFuZCBCTDEuSC4KClNhbWUgcGxvdCBmb3Igbm9ybWFsaXplZCBmbHVvcmVzY2VuY2UKYGBge3J9CmRhdE0gJT4lIAogIGZpbHRlcihwbGFzbWlkID09ICIxODgiLCBob3N0ID09ICJQSE8yIikgJT4lIAogIHNlcGFyYXRlKHdlbGwsIGludG8gPSBjKCJyb3ciLCAiY29sIiksIHNlcCA9IDEpICU+JSAKICBwaXZvdF9sb25nZXIoYyhuR0ZQLCBuUkZQKSwgbmFtZXNfdG8gPSAicGFyYW1ldGVyIiwgdmFsdWVzX3RvID0gImludGVuc2l0eSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb2wsIHkgPSBpbnRlbnNpdHksIGdyb3VwID0gZGF0ZSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBkYXRlKSwgc2l6ZSA9IDEpICsgCiAgI2dlb21fbGluZShhZXMoY29sb3IgPSBkYXRlKSwgc2l6ZSA9IDAuNCkgKwogIHN0YXRfc3VtbWFyeShhZXMoY29sb3IgPSBkYXRlKSwgZ2VvbSA9ICJsaW5lIiwgZnVuID0gbWVhbikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcih0eXBlID0gInF1YWwiLCBwYWxldHRlID0gMikgKwogIHhsYWIoIkNvbHVtbiIpICsKICBmYWNldF9ncmlkKHBhcmFtZXRlcn5yb3csIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpCmBgYAoKPiAtIFdoYXQgd2UgY2FyZSBhYm91dCBpcyB0aGUgcmF0aW8gYmV0d2VlbiBQaG80LW1OZW9uIGFuZCBfUEhPNXByXy1tQ2hlcnJ5CgpgYGB7cn0KZGF0TSAlPiUgCiAgZmlsdGVyKHBsYXNtaWQgPT0gIjE4OCIsIGhvc3QgPT0gIlBITzIiKSAlPiUgCiAgc2VwYXJhdGUod2VsbCwgaW50byA9IGMoInJvdyIsICJjb2wiKSwgc2VwID0gMSkgJT4lIAogIGdncGxvdChhZXMoeCA9IEJMMS5ILCB5ID0gWUwyLkgpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gZGF0ZSwgc2hhcGUgPSByb3cpLCBzaXplID0gMykgKyAKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJncmF5NTAiLCBzaXplID0gMC41KSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHR5cGUgPSAicXVhbCIsIHBhbGV0dGUgPSAyKSArCiAgI3NjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsKICAjc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTU6MTcsIDIzLCAyNSkpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCkKYGBgCgo+IC0gVGhlcmUgaXMgdmFyaWF0aW9uIGluIEJMMS5IIGFuZCBjb3JyZXNwb25kaW5nbHkgaW4gWUwyLkgsIGJ1dCB0aGUgcmF0aW8gYmV0d2VlbiB0aGUgdHdvIGFyZSB2ZXJ5IGNvbnNpc3RlbnQKCiMjIDQuIFJ1biBlZmZlY3QKCkhvdyBkb2VzIHRoZSBzYW1lIGNvbnRyb2wgc3RyYWluIGJlaGF2ZSBpbiBkaWZmZXJlbnQgcnVucyAocmVwcmVzZW50ZWQgYXMgZGF0ZSB2YXJpYWJsZSBoZXJlKT8gSXMgdGhlcmUgYSBzdHJvbmcgcnVuIGVmZmVjdD8KCkxldCdzIGNoZWNrIGJvdGggU2NQaG80IChwSDE5NCkgYW5kIENnUGhvNCAocEgxODgpIHRvIHNlZSBpZiB0aGVpciBiZWhhdmlvcnMgYXJlIGNvbnNpc3RlbnQgYWNyb3NzIGRheXMgYW5kIGJldHdlZW4gdGhpcyBhbmQgdGhlIGxhc3QgKDAzLzMwKSBiYXRjaC4KYGBge3J9CmRhdE0gJT4lIAogIGZpbHRlcihwbGFzbWlkICVpbiUgYygiMTg4IiwgIjE5NCIpKSAlPiUgCiAgbXV0YXRlKAogICAgZGF0ZSA9IGdzdWIoIi8yMiQiLCAiIiwgZGF0ZSksCiAgICBgWUwyLkggLyBCTDEuSGAgPSBZTDIuSCAvIEJMMS5ILAogICAgUGhvNCA9IGZhY3RvcihwbGFzbWlkLCBsZXZlbHMgPSBjKCIxOTQiLCAiMTg4IiksIGxhYmVscyA9IGMoIlNjUGhvNCIsICJDZ1BobzQiKSkKICApICU+JSAKICBzZXBhcmF0ZSh3ZWxsLCBpbnRvID0gYygicm93IiwgImNvbCIpLCBzZXAgPSAxKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGBZTDIuSCAvIEJMMS5IYCwgZ3JvdXAgPSBob3N0KSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGhvc3QpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEpLCBhbHBoYSA9IDAuOCwgc2l6ZSA9IDEpICsgCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKGJlZ2luID0gMC4yLCBlbmQgPSAwLjYpICsKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSAibWVhbl9zZSIsIGdlb20gPSAicG9pbnRyYW5nZSIsIHNoYXBlID0gMTYsIGNvbG9yID0gInJlZCIpICsKICB5bGltKDAsIDMwKSArIGZhY2V0X2dyaWQoUGhvNH4uKSArIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQpgYGAKPiB3aGlsZSB0aGUgY2hhcmFjdGVyaXN0aWMgYmVoYXZpb3JzIG9mIFNjUGhvNCBhbmQgQ2dQaG80IGFyZSBjb25zaXN0ZW50IGFjcm9zcyBydW5zLCB0aGVyZSBhcmUgYWxzbyBjbGVhciB2YXJpYWJpbGl0eSBpbiB0aGUgUkZQL0dGUCByYXRpb3MgYmV0d2VlbiBwbGF0ZXMgZm9yIHRoZSBzYW1lIGdlbm90eXBlLgoKTmV4dCB3ZSBleGFtaW5lIHRoZSB1bmRlcmx5aW5nIGJhY2tncm91bmQtc3VidHJhY3RlZCBmbHVvcmVzY2VuY2UgdmFsdWVzIGZvciBwSDE4OCBhbmQgcEgxOTQgaW4gdGhlIHlINTU1IGJhY2tncm91bmQsIHdoaWNoIGFyZSBwcmVzZW50IG9uIGVhY2ggcGxhdGUuCgpgYGB7cn0KZGF0TSAlPiUgCiAgZmlsdGVyKHBsYXNtaWQgJWluJSBjKCIxODgiLCAiMTk0IiksIGhvc3QgPT0gIlBITzIiKSAlPiUgCiAgbXV0YXRlKAogICAgZGF0ZSA9IGdzdWIoIi8yMiQiLCAiIiwgZGF0ZSksCiAgICBwbGFzbWlkID0gZmFjdG9yKHBsYXNtaWQsIGxldmVscyA9IGMoIjE4OCIsICIxOTQiKSwgbGFiZWxzID0gYygiQ2dQaG80IiwgIlNjUGhvNCIpKQogICkgJT4lIAogIHBpdm90X2xvbmdlcihCTDEuSDpZTDIuSCwgbmFtZXNfdG8gPSAicGFyYW1ldGVyIiwgdmFsdWVzX3RvID0gImludGVuc2l0eSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gaW50ZW5zaXR5LCBncm91cCA9IHBsYXNtaWQpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcGxhc21pZCksIGFscGhhID0gMC43LCBzaXplID0gMSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBkb2RnZS53aWR0aCA9IDAuNykpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlNjUGhvNCIgPSAiYmx1ZTMiLCAiQ2dQaG80IiA9ICJmb3Jlc3RncmVlbiIpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhjb2xvciA9IHBsYXNtaWQpLCBmdW4uZGF0YSA9ICJtZWFuX3NlIiwgZ2VvbSA9ICJjcm9zc2JhciIsIHdpZHRoID0gMC40LAogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNykpICsKICBmYWNldF9ncmlkKHBhcmFtZXRlcn4uLCBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZXhwYW5kX2xpbWl0cyh5ID0gMCkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KSArIGxhYnMoc3VidGl0bGUgPSAiaW4gUEhPMiBiYWNrZ3JvdW5kIikjICsKICAjdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oKSkKYGBgCgo+IENnUGhvNCBhbmQgU2NQaG80IHZhbHVlcyB0cmFjayBlYWNoIG90aGVyIC0tIG9uIGRheXMgKHJ1bnMpIHdoZXJlIG9uZSBpcyBoaWdoLCB0aGUgb3RoZXIgb25lIGFsc28gdGVuZHMgdG8gYmUgaGlnaC4gT24gdGhlIDA1LzMxIHJ1biwgU2NQaG80IGlzIHNpZ25pZmljYW50bHkgaGlnaGVyIHRoYW4gQ2dQaG80LgoKYGBge3J9CmRhdE0gJT4lIAogIGZpbHRlcihwbGFzbWlkICVpbiUgYygiMTg4IiwgIjE5NCIpLCBob3N0ID09ICJQSE8yIikgJT4lIAogIG11dGF0ZSgKICAgIGRhdGUgPSBnc3ViKCIvMjIkIiwgIiIsIGRhdGUpLAogICAgcGxhc21pZCA9IGZhY3RvcihwbGFzbWlkLCBsZXZlbHMgPSBjKCIxODgiLCAiMTk0IiksIGxhYmVscyA9IGMoIkNnUGhvNCIsICJTY1BobzQiKSkKICApICU+JSAKICBwaXZvdF9sb25nZXIobkdGUDpuUkZQLCBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCB2YWx1ZXNfdG8gPSAiaW50ZW5zaXR5IikgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSBpbnRlbnNpdHksIGdyb3VwID0gcGxhc21pZCkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBwbGFzbWlkKSwgYWxwaGEgPSAwLjcsIHNpemUgPSAxLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGRvZGdlLndpZHRoID0gMC43KSkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiU2NQaG80IiA9ICJibHVlMyIsICJDZ1BobzQiID0gImZvcmVzdGdyZWVuIikpICsKICBzdGF0X3N1bW1hcnkoYWVzKGNvbG9yID0gcGxhc21pZCksIGZ1bi5kYXRhID0gIm1lYW5fc2UiLCBnZW9tID0gImNyb3NzYmFyIiwgd2lkdGggPSAwLjQsCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC43KSkgKwogIGZhY2V0X2dyaWQocGFyYW1ldGVyfi4sIHNjYWxlID0gImZyZWVfeSIpICsKICBleHBhbmRfbGltaXRzKHkgPSAwKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpICsgbGFicyhzdWJ0aXRsZSA9ICJpbiBQSE8yIGJhY2tncm91bmQiKSMgKwogICN0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF9tYXJrZG93bigpKQpgYGAKPiBUaGUgc2l6ZSBub3JtYWxpemVkIHZhbHVlcyBzaG93IGxvd2VyIHZhcmlhbmNlIGJ1dCBhIHNpbWlsYXIgY29ycmVsYXRlZCBwYXR0ZXJuLiBIZXJlLCBob3dldmVyLCBTY1BobzQgb3ZlcnRha2VzIENnUGhvNCBvbiB0aGUgMDMvMjIgYW5kIDA1LzE3IHJ1bnMuCgpIb3cgYWJvdXQgdGhlIFJGUC9HRlAgcmF0aW9zPwpgYGB7cn0KZGF0TSAlPiUgCiAgZmlsdGVyKHBsYXNtaWQgJWluJSBjKCIxODgiLCAiMTk0IiksIGhvc3QgPT0gIlBITzIiKSAlPiUgCiAgbXV0YXRlKAogICAgZGF0ZSA9IGdzdWIoIi8yMiQiLCAiIiwgZGF0ZSksCiAgICBwbGFzbWlkID0gZmFjdG9yKHBsYXNtaWQsIGxldmVscyA9IGMoIjE4OCIsICIxOTQiKSwgbGFiZWxzID0gYygiQ2dQaG80IiwgIlNjUGhvNCIpKSwKICAgIGBZTDIgLyBCTDFgID0gWUwyLkggLyBCTDEuSCwKICAgIGBuUkZQIC8gbkdGUGAgPSBuUkZQIC8gbkdGUAogICkgJT4lIAogIHBpdm90X2xvbmdlcihgWUwyIC8gQkwxYDpgblJGUCAvIG5HRlBgLCBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCB2YWx1ZXNfdG8gPSAicmF0aW8iKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHJhdGlvLCBncm91cCA9IHBsYXNtaWQpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcGxhc21pZCksIGFscGhhID0gMC42LCBzaXplID0gMSwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgZG9kZ2Uud2lkdGggPSAwLjcpKSArIAogIHN0YXRfc3VtbWFyeShhZXMoY29sb3IgPSBwbGFzbWlkKSwgZnVuLmRhdGEgPSAibWVhbl9zZSIsIGdlb20gPSAiY3Jvc3NiYXIiLCB3aWR0aCA9IDAuNCwKICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlNjUGhvNCIgPSAiYmx1ZTMiLCAiQ2dQaG80IiA9ICJmb3Jlc3RncmVlbiIpKSArCiAgZmFjZXRfZ3JpZChwYXJhbWV0ZXJ+LikgKyBleHBhbmRfbGltaXRzKHkgPSBjKDAsMzApKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpICsgbGFicyhzdWJ0aXRsZSA9ICJpbiBQSE8yIGJhY2tncm91bmQiKSMgKwogICN0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF9tYXJrZG93bigpKQpgYGAKCiAKIyMgNS4gU3RhdGlzdGljYWwgdGVzdHMgZm9yIGNvbmZvdW5kaW5nIGZhY3RvcnMKVGVzdGluZyBmb3IgcnVuIChkYXRlKSBhcyB3ZWxsIGFzIHdlbGwgKGJsb2NrKSBwb3NpdGlvbiBlZmZlY3RzIG9uIGZsdW9yZXNjZW5jZSB2YWx1ZXMuIFVzaW5nIHRoZSBbbmVzdC1tYXAtdW5uZXN0IHdvcmtmbG93XShodHRwczovL3d3dy50aWR5bW9kZWxzLm9yZy9sZWFybi9zdGF0aXN0aWNzL3RpZHktYW5hbHlzaXMvKQoKTm90ZSB0aGF0IGluIG9yZGVyIHRvIG1haW50YWluIGEgYmFsYW5jZWQgZGVzaWduIChzYW1lIG51bWJlciBvZiByZXBsaWNhdGVzIGluIGVhY2ggZ3JvdXApLCB3ZSB3aWxsIHJlc3RyaWN0IHRoZSBhbmFseXNpcyB0byBiYXRjaGVzIDEtNCBpbiB0aGUgTWF5L0p1biBkYXRhc2V0LiBUaGUgTWFyY2ggZGF0YXNldCBoYWQgYSBkaWZmZXJlbnQgcGxhdGUgZGVzaWduLCB3aGlsZSBiYXRjaCA1IG9mIHRoZSBNYXkvSnVuIGRhdGFzZXQgaXMgaW5jb21wbGV0ZSB3LnIudC4gdGhlIGNvbnRyb2xzIChiZWNhdXNlIG9ubHkgaGFsZiBvZiB0aGUgcGxhdGUgd2FzIHVzZWQpLgoKYGBge3J9CnRtcCA8LSBmaWx0ZXIoZGF0MSwgcGxhc21pZCA9PSAiMTg4IiwgaG9zdCA9PSAiUEhPMiIsIGRhdGUgIT0gIjA2LzAyLzIyIikgJT4lICAgCiAgc2VwYXJhdGUod2VsbCwgaW50byA9IGMoInJvdyIsICJjb2wiKSwgc2VwID0gMSwgcmVtb3ZlID0gRkFMU0UpICU+JSAKICBzZWxlY3QoZGF0ZSwgYmxvY2sgPSB3ZWxsLCByb3csIGNvbCwgQkwxLkg6blJGUCkgJT4lIAogIG11dGF0ZShSdkcgPSBZTDIuSCAvIEJMMS5ILCBuUnZHID0gblJGUCAvIG5HRlApCmBgYAoKYGBge3J9CnRtcCAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBCTDEuSDpuUnZHLCBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUgCiAgbmVzdChkYXRhID0gYygtcGFyYW1ldGVyKSkgJT4lIAogIG11dGF0ZSgKICAgIGZpdCA9IG1hcChkYXRhLCB+YW5vdmEobG0odmFsdWUgfiBkYXRlICsgcm93ICsgY29sLCBkYXRhID0gLngpKSksCiAgICB0aWRpZWQgPSBtYXAoZml0LCBicm9vbTo6dGlkeSkKICApICU+JSAKICB1bm5lc3QodGlkaWVkKSAlPiUgCiAgbXV0YXRlKAogICAgc2lnbmlmaWNhbnQgPSBjYXNlX3doZW4oCiAgICAgIHAudmFsdWUgPCAwLjAwMSB+ICIqKioiLAogICAgICBwLnZhbHVlIDwgMC4wMSAgfiAiKioiLAogICAgICBwLnZhbHVlIDwgMC4wNSAgfiAiKiIsCiAgICAgIHAudmFsdWUgPCAwLjEgICB+ICIuIiwKICAgICAgVFJVRSB+ICIgIgogICAgKSkgJT4lIAogIGZpbHRlcih0ZXJtICE9ICJSZXNpZHVhbHMiKSAlPiUgCiAgc2VsZWN0KHBhcmFtZXRlciwgdGVybSwgZGYsIHN0YXRpc3RpYywgcC52YWx1ZSwgc2lnbmlmaWNhbnQpCmBgYAo+IFRoZXJlIGlzIGEgaGlnaGx5IHNpZ25pZmljYW50IHJ1biAoZGF0ZSkgZWZmZWN0IGZvciBhbGwgdmFyaWFibGVzLiBUaGUgUi9HIGFuZCBuUi9HIHJhdGlvcyBzaG93IHNpZ25pZmljYW50IGNvbHVtbiBlZmZlY3RzLgo+IEkgYWxzbyB0cmllZCB1c2luZyBibG9jayAoMTIgYmxvY2tzIG9uIHRoZSBwbGF0ZSkgYW5kIG1vc3Qgb2YgdGhlIGJsb2NrIGVmZmVjdHMgYXJlIHNpZ25pZmljYW50LgoKVXNlIGR1bW15IGVuY29kaW5nIGluIGxpbmVhciByZWdyZXNzaW9uIHRvIHZpZXcgdGhlIGVmZmVjdHMgb2YgcnVuIGFuZCB3ZWxsIHBvc2l0aW9uLgpgYGB7cn0KdG1wICU+JSAKICBtdXRhdGUocm93ID0gZmFjdG9yKHJvdywgbGV2ZWxzID0gYygiRyIsICJFIiwgIkMiLCAiQSIpKSkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gQkwxLkg6blJ2RywgbmFtZXNfdG8gPSAicGFyYW1ldGVyIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIAogIG5lc3QoZGF0YSA9IGMoLXBhcmFtZXRlcikpICU+JSAKICBtdXRhdGUoCiAgICBmaXQgPSBtYXAoZGF0YSwgfmxtKHZhbHVlIH4gZGF0ZSArIHJvdyArIGNvbCwgZGF0ID0gLngpKSwKICAgIHRpZGllZCA9IG1hcChmaXQsIGJyb29tOjp0aWR5KQogICkgJT4lIAogIHVubmVzdCh0aWRpZWQpICU+JSAKICBtdXRhdGUoCiAgICB0ZXJtID0gZ3N1YigiLzIyJCIsICIiLCB0ZXJtKSwKICAgIGVzdGltYXRlID0gcm91bmQoZXN0aW1hdGUsIGRpZ2l0cyA9IDIpLAogICAgc2lnbmlmaWNhbnQgPSBjYXNlX3doZW4oCiAgICAgIHAudmFsdWUgPCAwLjAwMSB+ICIqKioiLAogICAgICBwLnZhbHVlIDwgMC4wMSAgfiAiKioiLAogICAgICBwLnZhbHVlIDwgMC4wNSAgfiAiKiIsCiAgICAgIHAudmFsdWUgPCAwLjEgICB+ICIuIiwKICAgICAgVFJVRSB+ICIgIgogICAgKSwKICAgIGVmZiA9IHBhc3RlKGVzdGltYXRlLCBzaWduaWZpY2FudCwgc2VwID0gIiAgIikKICApICU+JSAKICBzZWxlY3QocGFyYW1ldGVyLCB0ZXJtLCBlZmYpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGFyYW1ldGVyLCB2YWx1ZXNfZnJvbSA9IGVmZikjICU+JSAKICAjbXV0YXRlKGFjcm9zcyhlX0JMMTplX25SRlAsIH4gcm91bmQoLngsIGRpZ2l0cyA9IDApKSkKYGBgCj4gLSBUaGVyZSBpcyBhIHNpZ25pZmljYW50IHJ1biAoZGF0ZSkgZWZmZWN0IGZvciBhbGwgdmFyaWFibGVzLiBSdkcgcmF0aW8gYXBwZWFycyB0byBiZSBiZXR0ZXIgdGhhbiBuUnZHIGluIHRlcm1zIG9mIGJlaW5nIGxlc3MgYWZmZWN0ZWQgYnkgZWl0aGVyIHJ1biBvciB3ZWxsIHBvc2l0aW9ucy4KPiAtIFJvdyBBIGhhcyBhIGhpZ2hlciBmbHVvcmVzY2VuY2UgdmFsdWVzIG92ZXJhbGwuIEJ1dCB0aGUgUnZHIHJhdGlvcyBhcmUgbm90IHNpZ25pZmljYW50bHkgaGlnaGVyIGluIHJvdyBBLgo+IC0gQ29sdW1uIDkgaGFzIGEgc2lnbmlmaWNhbnRseSBoaWdoZXIgUnZHLCBiZWNhdXNlLCBmb3Igc29tZSByZWFzb24sIHRoZSBSRlAgaXMgaGlnaGVyIGJ1dCBub3QgdGhlIEdGUC4KCldpdGggdGhlIGFib3ZlIG9ic2VydmF0aW9ucywgaXQgaXMgeWV0IHVuY2xlYXIgdG8gbWUgKDEpIHdoZXRoZXIgaXQgaXMgbmVjZXNzYXJ5IHRvIGFjY291bnQgZm9yIHRoZSBydW4gYW5kIHBvc2l0aW9uIGVmZmVjdHMgKGlmIHRoZSBlZmZlY3Qgc2l6ZXMgd2UgYXJlIGludGVyZXN0ZWQgaW4gYXJlIG11Y2ggbGFyZ2VyIHRoYW4gdGhlc2UsIHdlIG1heSBub3QgY2FyZSkgYW5kICgyKSBpZiBuZWNlc3NhcnksIHdoYXQncyB0aGUgYmVzdCB3YXkgdG8gYWNjb3VudCBmb3IgaXQuIE9uZSBpZGVhIEkgaGF2ZSBpcyB0byB1c2UgdGhlIGNvbW1vbiBzdHJhaW5zIG9uIGVhY2ggcGxhdGUsIGUuZy4sIHRoZSBob3N0IHN0cmFpbnMgKG5vIFBobzQpIG9yIENnUGhvNCBhbmQgU2NQaG80IHdpdGggYW5kIHdpdGhvdXQgUGhvMiwgYXMgbm9ybWFsaXppbmcgZmFjdG9ycy4gT25lIGNhbiB0aGluayBvZiBzZXZlcmFsIHdheXMgb2Ygbm9ybWFsaXphdGlvbiwgZS5nLiwgc2V0dGluZyBTY1BobzQgdy8gUGhvMidzIFJ2RyBhcyAxMDAlLiBXaWxsIGV4cGxvcmUgdGhlc2UgaWRlYXMgYmVsb3cuCgojIE1haW4KIyMgMS4gTXV0YXRpb24gZWZmZWN0cwpIZXJlIHdlIGV4YW1pbmUgdGhlIGVmZmVjdHMgb2YgdGhlIG11dGF0aW9ucyBvbiB0aGUgY2hpbWVyYSBhY3Rpdml0eS4gRW1pbHkgcmVtYWRlIGByIGxlbmd0aChsaXN0Lm11dGF0aW9ucylgIGNoaW1lcmljIGNvbnN0cnVjdHMgdG8gY29ycmVjdCB0aGUgbm9uLXN5bm9ueW1vdXMgbXV0YXRpb25zIGluIHRoZW0gYW5kIHJlcmFuIHRob3NlIGNvbnN0cnVjdHMgaW4gdGhlIE1heS9KdW4gYmF0Y2guIFdoaWxlIGRvaW5nIHRoYXQsIHNoZSBlbmNvdW50ZXJlZCBzb21lIGlzc3VlcyB3aXRoIGNlcnRhaW4gc2FtcGxlcyBub3QgZ3Jvd2luZyB3ZWxsIG9yIHRoZSBmbG93IGRhdGEgc2hvd2luZyBtdWx0aXBsZSBwb3B1bGF0aW9ucy4gU2hlIHJlcGVhdGVkIHNvbWUgb2YgdGhvc2Ugc3RyYWlucy4gQXMgYSByZXN1bHQsIHdlIGhhdmUgbW9yZSB0aGFuIHR3byBtZWFzdXJlbWVudHMgZm9yIHNvbWUgb2YgdGhlIHN0cmFpbnMuIFRoZSBnb2FsIGluIHRoaXMgYW5hbHlzaXMgaXMgdG8gY29tcGFyZSB0aGVpciBtZWFzdXJlbWVudHMgYm90aCB3aXRoIGFuZCB3aXRob3V0IG11dGF0aW9ucywgYW5kIGFsc28gYWNyb3NzIHRoZSByZXBlYXRzLgoKUmVhZCBpbiB0aGUgZXhwZXJpbWVudGFsIGZsYWdzIGZvciB0aGUgTWF5L0p1biBiYXRjaCwgZm9yIHRoZSBtdWx0aXBsZSBwb3B1bGF0aW9uIGxhYmVscwpgYGB7cn0KbXVsdGlwb3AgPC0gcmVhZF90c3YoIi4uL2RhdGEvMjAyMjA2MTQtRU8tcmVwZWF0LWV4cGVyaW1lbnQtaW5mby50c3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpICU+JSAKICBmaWx0ZXIoZmxhZyA9PSAibXVsdGkgcG9wIikgJT4lIHNlbGVjdCgtZmxhZykgJT4lIAogIHNlcGFyYXRlKHNhbXBsZSwgaW50byA9IGMoInBsYXNtaWQiLCAiaG9zdCIpLCBzZXAgPSAiLSIpICU+JSAKICBtdXRhdGUoaG9zdCA9IG9yZGVyZWQoaG9zdCwgbGV2ZWxzID0gYygiNTU1IiwgIjM3MyIpLCBsYWJlbHMgPSBjKCJQSE8yIiwgInBobzLiiIYiKSksIG11bHRpX3BvcCA9IFRSVUUpCmBgYAoKQ3JlYXRlIGEgZmxhZyB2YXJpYWJsZQpgYGB7cn0KZGF0TiA8LSBkYXRNICU+JSAKICBtdXRhdGUobXVsdGlfcG9wID0gRkFMU0UpICU+JSAKICByb3dzX3VwZGF0ZShtdWx0aXBvcCwgYnkgPSBjKCJkYXRlIiwgInBsYXNtaWQiLCAiaG9zdCIpKSAlPiUgCiAgbXV0YXRlKAogICAgUnZHID0gaWZlbHNlKEJMMS5IID4gMCwgWUwyLkgvQkwxLkgsIE5BKSwKICAgICNSdkcgPSBudW0oUnZHLCBkaWdpdHMgPSAyKSwKICAgIGZsYWcgPSBmYWN0b3IobXV0YXRpb24gKyBtdWx0aV9wb3AqMiwKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYXMuY2hhcmFjdGVyKDA6MyksCiAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoInBhc3MiLCAibXV0YXRpb24iLCAibXVsdGlfcG9wIiwgIm11dGF0aW9uO211bHRpX3BvcCIpKQogICkgJT4lIHJlbG9jYXRlKFJ2RywgLmFmdGVyID0gblJGUCkKYGBgCgpFbWlseSBoYXMgaW5jbHVkZWQgdHdvIG9sZCBzYW1wbGVzIGNvbnRhaW5pbmcgbXV0YXRpb25zIChwSDIwOSwgMjEwKSBhbG9uZyB3aXRoIHRoZSByZW1hZGUsIG11dGF0aW9uLWZyZWUgcGxhc21pZHMsIGluIHRoZSBuZXcgYmF0Y2guIExldCdzIHNlZSBob3cgdGhleSBjb21wYXJlIHdpdGggZWFjaCBvdGhlciBhbmQgd2l0aCB0aGUgTWFyY2ggYmF0Y2ggKHdpdGggbXV0YXRpb25zKS4KYGBge3J9CnRtcCA8LSBmaWx0ZXIoZGF0TiwgcGxhc21pZCAlaW4lIGMoIjIwOSIsICIyMTAiKSkgJT4lIAogIG11dGF0ZSgKICAgIG1vbnRoID0gc3RyX3N1YihkYXRlLCAxLCAyKSwKICAgIHNhbXBsZSA9IGlmZWxzZShtb250aCA9PSAiMDMiLCAiMDMtb2xkIiwgaWZlbHNlKG11dGF0aW9uLCAiMDUtb2xkIiwgIjA1LW5ldyIpKSwKICAgIHNhbXBsZSA9IGZhY3RvcihzYW1wbGUsIGxldmVscyA9IGMoIjAzLW9sZCIsICIwNS1vbGQiLCAiMDUtbmV3IikpCiAgKQpgYGAKCkZpcnN0IGNvbXBhcmUgdGhlIHNhbWUgcGxhc21pZHMgKHdpdGggbXV0YXRpb25zKSBtZWFzdXJlZCBvbiBkaWZmZXJlbnQgZGF5cwpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQp0bXAgJT4lIAogIHNlbGVjdCgtRlNDLkgpICU+JSAKICBwaXZvdF9sb25nZXIoQkwxLkg6UnZHLCBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBtdXRhdGUocGFyYW1ldGVyID0gZmFjdG9yKHBhcmFtZXRlciwgbGV2ZWxzID0gYygiQkwxLkgiLCAiWUwyLkgiLCAibkdGUCIsICJuUkZQIiwgIlJ2RyIpKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHBsYXNtaWQsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBzYW1wbGUpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBzYW1wbGUpLCBzaXplID0gMSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgI3N0YXRfc3VtbWFyeShhZXMoY29sb3IgPSBzYW1wbGUpLCBmdW4uZGF0YSA9ICJtZWFuX3NlIiwgZ2VvbSA9ICJjcm9zc2JhciIsIHdpZHRoID0gMC4xLAogICMgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAzLW9sZCIgPSAiZ3JheTUwIiwgIjA1LW9sZCIgPSAiZ3JheTMwIiwgIjA1LW5ldyIgPSAicmVkMiIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG4uYnJlYWtzID0gMykgKyBleHBhbmRfbGltaXRzKHkgPSAwKSArCiAgZmFjZXRfZ3JpZChwYXJhbWV0ZXJ+aG9zdCwgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCkgKyBiYWNrZ3JvdW5kX2dyaWQobWFqb3IgPSAieSIpCmBgYAoKYGBge3J9CnRtcCAlPiUgCiAgc2VsZWN0KC1GU0MuSCkgJT4lIAogIHBpdm90X2xvbmdlcihCTDEuSDpSdkcsIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIG11dGF0ZShwYXJhbWV0ZXIgPSBmYWN0b3IocGFyYW1ldGVyLCBsZXZlbHMgPSBjKCJCTDEuSCIsICJZTDIuSCIsICJuR0ZQIiwgIm5SRlAiLCAiUnZHIikpKSAlPiUgCiAgbmVzdChkYXRhID0gYygtcGFyYW1ldGVyKSkgJT4lIAogIG11dGF0ZSgKICAgIGZpdCA9IG1hcChkYXRhLCB+YW5vdmEobG0odmFsdWUgfiBzYW1wbGUgKyBob3N0LCBkYXRhID0gLngpKSksCiAgICB0aWRpZWQgPSBtYXAoZml0LCBicm9vbTo6dGlkeSkKICApICU+JSAKICB1bm5lc3QodGlkaWVkKSAlPiUgCiAgbXV0YXRlKAogICAgc2lnbmlmaWNhbnQgPSBjYXNlX3doZW4oCiAgICAgIHAudmFsdWUgPCAwLjAwMSB+ICIqKioiLAogICAgICBwLnZhbHVlIDwgMC4wMSAgfiAiKioiLAogICAgICBwLnZhbHVlIDwgMC4wNSAgfiAiKiIsCiAgICAgIHAudmFsdWUgPCAwLjEgICB+ICIuIiwKICAgICAgVFJVRSB+ICIgIgogICAgKSkgJT4lIAogIGZpbHRlcih0ZXJtICE9ICJSZXNpZHVhbHMiKSAlPiUgCiAgc2VsZWN0KHBhcmFtZXRlciwgdGVybSwgZGYsIHN0YXRpc3RpYywgcC52YWx1ZSwgc2lnbmlmaWNhbnQpCmBgYAo+IEZvciB0aGUgUnZHIHJhdGlvLCB0aGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIDAzLW9sZCwgMDUtb2xkIGFuZCAwNS1uZXcuIEluIG90aGVyIHdvcmRzLCB3ZSBkb24ndCBoYXZlIGV2aWRlbmNlIHRoYXQgZWl0aGVyIHRoZSBkaWZmZXJlbnQgcnVucyBvciB0aGUgY29ycmVjdGlvbiBvZiBtdXRhdGlvbnMgaW1wYWN0ZWQgdGhlIGJlaGF2aW9yIG9mIHRoZSBjaGltZXJhIGluIHRoZSBjYXNlIG9mIHBIMjA5IGFuZCBwSDIxMC4KCldlIHdpbGwgbm93IG1vdmUgb24gdG8gdGhlIHJlc3Qgb2YgdGhlIHBsYXNtaWRzIHRoYXQgaGF2ZSBiZWVuIHJlbWFkZS4KYGBge3J9CnBwIDwtIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpteVBsb3RNdXRFZmZlY3QgPC0gZnVuY3Rpb24obCl7CiAgZXZlbl9udW1iZXJzIDwtIHNlcSgyLCBsZW5ndGgobCksIDIpICMgdXNlZCB0byBkcmF3IHN0cmlwZXMgb24gZXZlbiBudW1iZXJlZCB4LXZhbHVlcwogIGRmX3RpbGUgPC0gdGliYmxlKHBsYXNtaWQgPSByZXAoc29ydChsKVtldmVuX251bWJlcnNdLCB0aW1lcyA9IDIpLAogICAgICAgICAgICAgICAgICAgIGhvc3QgPSBmYWN0b3IocmVwKGMoIlBITzIiLCAicGhvMuKIhiIpLCBlYWNoID0gbGVuZ3RoKGV2ZW5fbnVtYmVycykpKSkKICBkYXROICU+JSAKICAgICNtdXRhdGUoZGF0ZSA9IGdzdWIoIi8yMiQiLCAiIiwgZGF0ZSkpICU+JSAKICAgIGZpbHRlcighbG93X2V2ZW50X2NvdW50LCBwbGFzbWlkICVpbiUgbCkgJT4lIAogICAgc2VsZWN0KGRhdGU6aG9zdCwgUnZHLCBmbGFnKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IHBsYXNtaWQsIHkgPSBSdkcpKSArCiAgICAjIGRyYXcgc3RyaXBlcyBvbiBldmVuIGNvbHVtbnMsCiAgICAjIGZyb206IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzU2OTYxNzQ0L2RyYXctYWx0ZXJuYXRlLXJlY3RhbmdsZXMtaW4tYm94cGxvdHMtd2l0aC1mYWNldHMtci1nZ3Bsb3QyJwogICAgZ2VvbV90aWxlKGFlcyh4ID0gcGxhc21pZCwgeSA9IDEpLCBoZWlnaHQgPSBJbmYsIHdpZHRoID0gMSwgZGF0YSA9IGRmX3RpbGUsIGFscGhhID0gMC4zKSArCiAgICAgICAgICAgICAgI3ltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyZXk4MCIsIGNvbG9yID0gTkEsIGFscGhhID0gMC41KSArCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGZsYWcsIGdyb3VwID0gZGF0ZSksIHNpemUgPSAxLjUsIHNoYXBlID0gMTksCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBkb2RnZS53aWR0aCA9IDAuNykpICsKICAgICNzdGF0X3N1bW1hcnkoYWVzKGNvbG9yID0gc2FtcGxlKSwgZnVuLmRhdGEgPSAibWVhbl9zZSIsIGdlb20gPSAiY3Jvc3NiYXIiLCB3aWR0aCA9IDAuMSwKICAgICMgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicGFzcyIgPSAiZm9yZXN0Z3JlZW4iLCAibXV0YXRpb24iID0gInB1cnBsZSIsICJtdWx0aV9wb3AiID0gInN0ZWVsYmx1ZTMiKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKG4uYnJlYWtzID0gNCkgKyBleHBhbmRfbGltaXRzKHkgPSAwKSArCiAgICBmYWNldF9ncmlkKGhvc3R+Liwgc2NhbGVzID0gImZyZWVfeSIpICsKICAgIHRoZW1lX2Nvd3Bsb3QoKSArIHBhbmVsX2JvcmRlcihjb2xvciA9ICJncmF5MzAiKSArIAogICAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gMykpCn0KYGBgCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGggPSA1LCBmaWcuaGVpZ2h0ID0gN30KbHN0IDwtIHNwbGl0KGxpc3QubXV0YXRpb25zLCBmID0gY2VpbGluZyhzZXFfYWxvbmcobGlzdC5tdXRhdGlvbnMpLzkpKQpwIDwtIGxhcHBseShsc3QsIG15UGxvdE11dEVmZmVjdCkKbGVnZW5kX3AgPC0gZ2V0X2xlZ2VuZChwW1sxXV0gKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIikpCnBsb3RfZ3JpZChwW1sxXV0gKyBwcCwgcFtbMl1dICsgcHAsIHBbWzNdXSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIGxlZ2VuZF9wLCBuY29sID0gMSwgcmVsX2hlaWdodHMgPSBjKDEsMSwxLC4xNSkpCmBgYAo+IFNhbXBsZXMgc2hvd2luZyBtdWx0aXBsZSBwb3B1bGF0aW9ucyBtb3N0bHkgYWdyZWUgd2l0aCB0aGUgbGF0dGVyIG1lYXN1cmVtZW50cyB3aGVyZSB0aGUgaXNzdWUgd2FzIHJlc3NvbHZlZCwgd2l0aCB0aGUgZXhjZXB0aW9uIG9mIG9uZSBvZiB0aGUgc2FtcGxlcyBvZiAyMzEgaW4gX1BITzJfIGJhY2tncm91bmQuCj4gCgpIZXJlIGFyZSB0aGUgb25lcyB0aGF0IHNob3cgb2J2aW91cyBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBvbGQgYW5kIGNvcnJlY3RlZCBjb25zdHJ1Y3RzOgpgYGB7cn0KbGwgPC0gYygiMjE1IiwgIjIxOCIsICIyMjciLCAiMjMzIiwgIjI0MSIsICIyNTIiLCAiMjU3IikKbXlQbG90TXV0RWZmZWN0KGxsKSArIHNjYWxlX3lfbG9nMTAoKQpgYGAKCiMjIDIuIFN1bW1hcml6ZSByZXN1bHRzIHBlciBjaGltZXJhCldlIHdpbGwgcmVtb3ZlIGFsbCB0aGUgbWVhc3VyZW1lbnRzIG1hZGUgb2YgY2hpbWVyYXMgd2l0aCBtdXRhdGlvbnMuIEZvciB0aGUgbWVhc3VyZW1lbnRzIG1hZGUgb2YgcmVtYWRlLCBjb3JyZWN0ZWQgY2hpbWVyYXMsIHdlIHdpbGwgcmVtb3ZlICoqb25lIHNhbXBsZSBmb3IgcEgyMzEgZnJvbSB0aGUgMDUvMTkgYmF0Y2gqKiAod2VsbCBDMiwgdGhlIG90aGVyIDIgcmVwbGljYXRlcyBvZiB0aGUgc2FtZSBzdHJhaW4gaW4gdGhhdCBiYXRjaCB3ZXJlIHJlbW92ZWQgZHVlIHRvIHRoZSBwcmVzZW5jZSBvZiBtdWx0aXBsZSBwb3B1bGF0aW9ucyBhbmQgbG93IGV2ZW50IGNvdW50IGluIHRoZSBnYXRlZCBwb3B1bGF0aW9uKSwgYXMgd2VsbCBhcyBvbmUgc2FtcGxlIGZvciAqKnBIMjMzIGZyb20gdGhlIDA2LzAyIGJhdGNoKiogKHdlbGwgRDQsIHdoaWNoIHNob3dlZCBvdmVyZXhwcmVzc2lvbiBvZiB0aGUgY2hpbWVyYSkuCgpOdW1iZXIgb2YgcmVwbGljYXRlcyBtZWFzdXJlZCBmb3IgZWFjaCBjaGltZXJhIHggaG9zdCBjb21iaW5hdGlvbjoKYGBge3J9CiMgbG9hZCBnZW5vdHlwZSBpbmZvcm1hdGlvbgptZXRhIDwtIHJlYWRfdHN2KCIuLi9kYXRhLzIwMjIwNjIxLWNoaW1lcmEtUGhvNC1tYWtldXAudHN2IiwgY29sX3R5cGVzID0gImNjY2NjIikgJT4lIAogIHJlbmFtZShnZW5vdHlwZSA9IGZ1bGwpICU+JSBzZWxlY3QoLXBsYXNtaWRfd3JvbmcpCgpkYXROICU+JSAKICBmaWx0ZXIoIWxvd19ldmVudF9jb3VudCwgIW11dGF0aW9uKSAlPiUgCiAgY291bnQocGxhc21pZCwgaG9zdCkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBob3N0LCB2YWx1ZXNfZnJvbSA9IG4pICU+JSAKICBmdWxsX2pvaW4obWV0YSwgYnkgPSAicGxhc21pZCIpICU+JSAKICBzZWxlY3QoLWxldHRlciwgLWdlbm90eXBlKQpgYGAKPiBwSDIxMSB3YXMgbWVhc3VyZWQgOSB0aW1lcyBpbiB0aGUgX1BITzJfIGJhY2tncm91bmQuIFRoZSByZXN1bHRzIHdlcmUgY29uc2lzdGVudC4KCkZvciBlYWNoIGNoaW1lcmEsIHdlIHdvdWxkIGxpa2UgdG8gY2FsY3VsYXRlICoqdGhyZWUgdmFsdWVzKio6CgoxLiBSdkcgaW4gX3BobzLiiIZfOiB0aGlzIGlzIGl0cyBiYXNlIGFjdGl2aXR5IHdpdGhvdXQgUGhvMgoxLiBSdkcgaW4gX1BITzJfOiB0aGlzIGlzIGl0cyBmdWxsIGFjdGl2aXR5IHdpdGggUGhvMgoxLiBSdkdfUEhPMiAvIFJ2R19waG8y4oiGOiB0aGlzIGlzIHRoZSBQaG8yIGVuaGFuY2VtZW50IG9mIGFjdGl2aXR5CgpUaGUgZmlyc3QgdHdvIHZhbHVlcyBhcmUgZnVydGhlciBub3JtYWxpemVkIGFnYWluc3QgdGhlIGNvcnJlc3BvbmRpbmcgU2NQaG80IG1lYXN1cmVtZW50cyBvbiB0aGUgc2FtZSBwbGF0ZS4KYGBge3J9CiMgZmlsdGVyIGRhdGEKdG1wIDwtIGZpbHRlcihkYXROLCAhbG93X2V2ZW50X2NvdW50LCAhbXV0YXRpb24sICFpcy5uYShwbGFzbWlkKSkgJT4lIHNlbGVjdChkYXRlOmhvc3QsIEJMMS5IOlJ2RykKCiMgY2FsY3VsYXRlIHRoZSBTY1BobzQgdmFsdWVzIHBlciBwbGF0ZQptU2NQaG80IDwtIHRtcCAlPiUgZmlsdGVyKHBsYXNtaWQgPT0gIjE5NCIpICU+JSBncm91cF9ieShkYXRlLCBob3N0KSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKFJ2RyksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gaG9zdCwgdmFsdWVzX2Zyb20gPSBtZWFuKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJkYXRlIikKCiMgbm9ybWFsaXplIHRoZSB2YWx1ZXMgZm9yIG5vbi1TY1BobzQgd2l0aCB0aG9zZSBvZiBTY1BobzQgcGVyIHBsYXRlCmRhdE8gPC0gdG1wICU+JSBtdXRhdGUoc1J2RyA9IFJ2RyAvIG1TY1BobzRbY2JpbmQoZGF0ZSwgYXMuY2hhcmFjdGVyKGhvc3QpKV0pCgojIHN1bW1hcml6ZQpkYXRzdW0gPC0gZGF0TyAlPiUgCiAgZ3JvdXBfYnkocGxhc21pZCwgaG9zdCkgJT4lIAogIHN1bW1hcml6ZShhY3Jvc3MoUnZHOnNSdkcsIG1lYW4pLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGhvc3QsIHZhbHVlc19mcm9tID0gUnZHOnNSdkcpICU+JSAKICByZW5hbWUoYEFfUEhPMmAgPSBgUnZHX1BITzJgLCBgQV9waG8yYCA9IGBSdkdfcGhvMuKIhmAsIGZ1bGwgPSBzUnZHX1BITzIsIGJhc2UgPSBgc1J2R19waG8y4oiGYCkgJT4lIAogIG11dGF0ZShib29zdCA9IGBBX1BITzJgIC8gYEFfcGhvMmAsIGFjcm9zcyhgQV9QSE8yYDpib29zdCwgfiByb3VuZCgueCwgZGlnaXRzID0gMykpKSAlPiUgCiAgZnVsbF9qb2luKG1ldGEsIGJ5ID0gInBsYXNtaWQiKQpgYGAKCkV4cG9ydCB0aGUgc3VtbWFyeSBkYXRhCmBgYHtyfQp3cml0ZV90c3YoZGF0c3VtLCBmaWxlID0gIi4uL291dHB1dC8yMDIyMDYxOS1jaGltZXJhLXN1bW1hcnktcmVzdWx0LnRzdiIpCmBgYAoKSGVyZSBhcmUgdGhlIGNoaW1lcmEgdGhhdCBoYXZlIGxpdHRsZSBmdWxsIGFjdGl2aXR5ICh3aXRoIFBobzIpOgpgciBkYXRzdW0gJT4lIGZpbHRlcihmdWxsIDwgMC4yKSAlPiUgYXJyYW5nZShmdWxsKSAlPiUgc2VsZWN0KC1sZXR0ZXIpICU+JSBrbml0cjo6a2FibGUoKWAKCkhlcmUgYXJlIHRoZSBvbmVzIHdpdGggdGhlIGhpZ2hlc3QgYmFzZSBhY3Rpdml0eSAod2l0aG91dCBQaG8yKToKYHIgZGF0c3VtICU+JSBhcnJhbmdlKGRlc2MoYmFzZSkpICU+JSBzZWxlY3QoLWxldHRlcikgJT4lIGhlYWQoMTApICU+JSAga25pdHI6OmthYmxlKClgCgojIyAzLiBQbG90dGluZyBmdW5jdGlvbnMKVGhlIGdvYWwgaGVyZSBpcyB0byBkZXZlbG9wIGEgc2V0IG9mIHBsb3R0aW5nIGZ1bmN0aW9ucyB0byB2aXN1YWxpemUgdGhlIHJlc3VsdHMuCgpGb3IgdGVzdGluZyBwdXJwb3Nlcywgd2Ugd2lsbCBzZWxlY3QgYSBzZXQgb2YgY2hpbWVyYSBhbG9uZyB3aXRoIHRoZSBlbmRvZ2Vub3VzIFNjUGhvNCBhbmQgQ2dQaG80LgpgYGB7cn0KIyBleHRyYWN0IHhpbWVyYSBuYW1lcwpyZWZzIDwtIGMoIkNDQ0NDIiwiU1NTU1MiKQp4aW1lcmFzIDwtIHNldGRpZmYobWV0YSRzeW1ib2wsIHJlZnMpCiMgbWFrZSBhIHRlc3Qgc2V0CnRlc3QgPC0gYyhyZWZzLCBmaWx0ZXIobWV0YSwgcGxhc21pZCAlaW4lIGMoIjIxMSIsICIyMjkiLCAiMjUwIiwgIjIyNCIsICIyNTciLCAiMjE5IiwgIjI2NiIpKSAlPiUgcHVsbChzeW1ib2wpKQojIHN1YnNldCBkYXRhCmRhdFQgPC0gbWV0YSAlPiUgCiAgZmlsdGVyKHN5bWJvbCAlaW4lIHRlc3QpICU+JSAKICBpbm5lcl9qb2luKGRhdE8sIGJ5ID0gInBsYXNtaWQiKSAlPiUgCiAgbXV0YXRlKHN5bWJvbCA9IGZhY3RvcihzeW1ib2wsIGxldmVscyA9IHRlc3QpKQpgYGAKCkRlc2lnbiBhIHNldCBvZiBjb2xvciBwYWxldHRlczoKYGBge3J9CiMgZm9yIHR3byBncm91cHMsIGUuZy4sIHdpdGggdnMgdy9vIFBobzIKY29scy50d28gPC0gYygiUEhPMiIgPSAiIzQ1N2RiYyIsICJwaG8y4oiGIiA9ICIjZWE5ZTI1IikKYGBgCgpQbG90IGluZGl2aWR1YWwgY29tcG9uZW50cyBhbmQgdGhlIG5vcm1hbGl6ZWQgYWN0aXZpdHkgKFJ2RyByYXRpbykKYGBge3IgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9Nn0KZGF0VCAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMobkdGUCwgblJGUCwgUnZHKSwgbmFtZXNfdG8gPSAicGFyYW1ldGVyIiwgdmFsdWVzX3RvID0gImludGVuc2l0eSIpICU+JSAKICBtdXRhdGUocGFyYW1ldGVyID0gb3JkZXJlZChwYXJhbWV0ZXIsIGxldmVscyA9IGMoIm5HRlAiLCAiblJGUCIsICJSdkciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQaG80LUdGUCIsICJfUEhPNXByXyA9PiBSRlAiLCAiQWN0aXZpdHkgPSBSRlAvR0ZQIikpKSAlPiUgCiAgI3Bpdm90X2xvbmdlcihCTDEuSDpZTDIuSCwgbmFtZXNfdG8gPSAicGFyYW1ldGVyIiwgdmFsdWVzX3RvID0gImludGVuc2l0eSIpICU+JSAKICAjbXV0YXRlKHBhcmFtZXRlciA9IG9yZGVyZWQocGFyYW1ldGVyLCBsZXZlbHMgPSBjKCJZTDIuSCIsICJCTDEuSCIpKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN5bWJvbCwgeSA9IGludGVuc2l0eSwgZ3JvdXAgPSBob3N0KSkgKyAKICBnZW9tX2JhcihhZXMoZmlsbCA9IGhvc3QpLCB3aWR0aCA9IDAuNSwjIGFscGhhID0gMC44LAogICAgICAgICAgIHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjUpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBob3N0KSwgc2l6ZSA9IDEsIGFscGhhID0gMC45LCBzaGFwZSA9IDMsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMiwgZG9kZ2Uud2lkdGggPSAwLjUpKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCgiY28tVEYiLCB2YWx1ZXMgPSBjKCJQSE8yIiA9ICJncmF5MzAiLCAicGhvMuKIhiIgPSAiZ3JheTQwIikpICsKICBzY2FsZV9maWxsX21hbnVhbCgiY28tVEYiLCB2YWx1ZXMgPSBjb2xzLnR3bykgKwogICNzdGF0X3N1bW1hcnkoZnVuID0gIm1lYW4iLCBnZW9tID0gImNyb3NzYmFyIiwgY29sb3IgPSAicmVkIiwgd2lkdGggPSAwLjI1LAogICMgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjc1KSwgKSArCiAgZmFjZXRfd3JhcCh+cGFyYW1ldGVyLCBzY2FsZSA9ICJmcmVlX3kiLCBuY29sID0gMSkgKwogIHhsYWIoIlBobzQgY2hpbWVyYSIpICsgZXhwYW5kX2xpbWl0cyh5ID0gMCkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPSAxLCBmYW1pbHkgPSAibW9ubyIpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X21hcmtkb3duKCkpCmBgYAoKUGxvdCB0aGUgUnZHIHZhbHVlcyBub3JtYWxpemVkIGFnYWluc3QgdGhlIGNvcnJlc3BvbmRpbmcgU2NQaG80IGNvbnN0cnVjdCBvbiB0aGUgc2FtZSBwbGF0ZSwgdG8gb2J0YWluIGEgcmVsYXRpdmUgbWVhc3VyZS4KYGBge3J9CiMgdXNlZnVsIHRvIGdyb3VwIHRoZSBwbGFzbWlkcwp4aW1lcmEuZ3JwIDwtIGRhdHN1bSAlPiUgCiAgbXV0YXRlKGdyb3VwID0gY2FzZV93aGVuKAogICAgZnVsbCA8IDAuMiB+ICJkZWZlY3RpdmUiLAogICAgYmFzZSA+IDUgICB+ICJsZXNzIFBobzItZGVwLiIsCiAgICBUUlVFICAgICAgIH4gIm90aGVycyIKICApKSAlPiUgc2VsZWN0KHBsYXNtaWQsIHN5bWJvbCwgZ3JvdXApCmBgYAoKYGBge3IgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9Nn0KcDAgPC0gZGF0VCAlPiUgCiAgbGVmdF9qb2luKHhpbWVyYS5ncnAsIGJ5ID0gYygic3ltYm9sIiwgInBsYXNtaWQiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN5bWJvbCwgeSA9IHNSdkcsIGdyb3VwID0gaG9zdCkpICsgCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSBob3N0KSwgd2lkdGggPSAwLjUsIyBhbHBoYSA9IDAuOCwKICAgICAgICAgICBzdGF0ID0gInN1bW1hcnkiLCBmdW4gPSAibWVhbiIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC41KSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gaG9zdCksIHNpemUgPSAxLCBhbHBoYSA9IDAuOSwgc2hhcGUgPSAzLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjIsIGRvZGdlLndpZHRoID0gMC41KSkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUEhPMiIgPSAiZ3JheTMwIiwgInBobzLiiIYiID0gImdyYXk0MCIpLCBndWlkZSA9ICJub25lIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbHMudHdvLCBndWlkZSA9ICJub25lIikgKwogICNzdGF0X3N1bW1hcnkoZnVuID0gIm1lYW4iLCBnZW9tID0gImNyb3NzYmFyIiwgY29sb3IgPSAicmVkIiwgd2lkdGggPSAwLjI1LAogICMgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjc1KSwgKSArCiAgZmFjZXRfZ3JpZChob3N0fmdyb3VwLCBzY2FsZSA9ICJmcmVlIikgKwogIHhsYWIoIlBobzQgY2hpbWVyYSIpICsgeWxhYigiQTxzdWI+Y2hpbWVyYTwvc3ViPiAvIEE8c3ViPlNjUGhvNDwvc3ViPiIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCkgKyBiYWNrZ3JvdW5kX2dyaWQobWlub3IgPSAibm9uZSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLCBoanVzdCA9IDEsIGZhbWlseSA9ICJtb25vIiksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfbWFya2Rvd24oKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9tYXJrZG93bigpKQoKcDEgPC0gZGF0c3VtICU+JSAKICBmaWx0ZXIoc3ltYm9sICVpbiUgdGVzdCkgJT4lIAogIGxlZnRfam9pbih4aW1lcmEuZ3JwLCBieSA9IGMoInBsYXNtaWQiLCAic3ltYm9sIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzeW1ib2wsIHkgPSBib29zdCkpICsgIAogIGdlb21fY29sKHdpZHRoID0gMC4zLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZ3JheTgwIikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gImdyYXkzMCIpICsKICBmYWNldF93cmFwKH5ncm91cCwgc2NhbGVzID0gImZyZWVfeCIpICsgCiAgc2NhbGVfeV9sb2cxMCgpICsKICB4bGFiKCJQaG80IGNoaW1lcmEiKSArIHlsYWIoIkE8c3ViPlBITzI8L3N1Yj4gLyBBPHN1Yj5waG8y4oiGPC9zdWI+IikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KSArIGJhY2tncm91bmRfZ3JpZChtaW5vciA9ICJub25lIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSwgZmFtaWx5ID0gIm1vbm8iKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X21hcmtkb3duKCkpCgpzZXRfbnVsbF9kZXZpY2UoInBuZyIpICMgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vd2lsa2VsYWIvY293cGxvdC9pc3N1ZXMvMTc0CnBsb3RfZ3JpZChwMCArIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSksIAogICAgICAgICAgcDEsIG5jb2wgPSAxLCByZWxfaGVpZ2h0cyA9IGMoMywyKSkKYGBgCgpzYXZlIHRoZSBkYXRhIG9iamVjdHMgZm9yIHRoZSBpbnRlcmFjdGl2ZSBkYXRhIHBsb3R0ZXIKYGBge3J9CnNhdmUoZGF0TywgZGF0c3VtLCBtZXRhLCBmaWxlID0gIi4uL3NoaW55YXBwLzIwMjIwNjIwLWRhdGEtZm9yLWludGVyYWN0aXZlLXBsb3R0aW5nLlJEYXRhIikKYGBgCgpEZXNpZ24gdGhlIHBsb3QKYGBge3J9CnRtcHN1bSAlPiUgCiAgbXV0YXRlKEFjdGl2aXR5ID0gaWZlbHNlKGBSL0dfUEhPMmAgPCAyKmxvdy5hY3QudGhbIlIvR19waG8y4oiGIl0sICJsb3ciLCAicGFzcyIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3ltYm9sLCB5ID0gYHBobzLiiIYvUEhPMmApKSArIAogIGdlb21fY29sKGFlcyhncm91cCA9IGRhdGUsIGZpbGwgPSBgUi9HX1BITzJgKSwgd2lkdGggPSAwLjc1LCBjb2xvciA9ICJncmF5NTAiLAogICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKwogICNnZW9tX3BvaW50KGFlcyhjb2xvciA9IGhvc3QpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGRvZGdlLndpZHRoID0gMC41KSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50MigiQWN0aXZpdHkiKSArCiAgI3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKGFscGhhKCJibGFjayIsMCksICJyZWQzIikpICsKICAjc3RhdF9zdW1tYXJ5KGZ1biA9ICJtZWFuIiwgY29sb3IgPSAicmVkIiwgZ2VvbSA9ICJjcm9zc2JhciIsIHdpZHRoID0gMC4yLAogICMgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjc1KSwgKSArCiAgZmFjZXRfZ3JpZCgufkFjdGl2aXR5LCBzY2FsZXMgPSAiZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IiwgbGFiZWxsZXIgPSAibGFiZWxfYm90aCIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCkgKyB4bGFiKCJQaG80IGNoaW1lcmEiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPSAxLCBmYW1pbHkgPSAibW9ubyIpKQpgYGAKClgtWSBwbG90CmBgYHtyfQpwMyA8LSB0bXBzdW0gJT4lIAogIG11dGF0ZShgblIvR19QSE8yYCA9IHNpZ25pZihgblIvR19QSE8yYCwgZGlnaXRzID0gMiksCiAgICAgICAgIGBuUi9HX3BobzLiiIZgID0gc2lnbmlmKGBuUi9HX3BobzLiiIZgLCBkaWdpdHMgPSAyKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGBuUi9HX1BITzJgLCB5ID0gYG5SL0dfcGhvMuKIhmAsIGxhYmVsID0gc3ltYm9sKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLjUpICsgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxKSArCiAgdGhlbWVfZ3JheShiYXNlX3NpemUgPSAxNCkKZ2dwbG90bHkocDMsIHRvb2x0aXAgPSBjKCJsYWJlbCIsICJ4IiwgInkiKSkKYGBgCgo=