Background
This is the flow cytometry data for miglog phase Cg stained with
PI/PI+SYTO9/ SYTO+PI in different staining orders, and run through flow
cytometry (details in ELN). The goal is to establish FungaLight’s
distinguishing power with different staining protocols.
require(tidyverse)
require(flowCore)
require(flowClust)
require(openCyto)
require(ggcyto)
require(cowplot)
require(ggridges)
old <- theme_set(theme_minimal())
Import data
FCS files are stored in RDSS/user/flow cytometry, FCS is read and
write into an input tsv table. The tsv file is avaliable from the Input
folder.
# use relative path to make it easier for collaboration
data.path = "/Volumes/rdss_bhe2/User/Hanxi Tang/Flow Cytometry/20240109_0116 Dye order/"
dat0 <- read.flowSet(path = data.path, transformation = FALSE, # the original values are already linearized.
emptyValue = FALSE, alter.names = TRUE, # change parameter names to R format
column.pattern = ".H|FSC|SSC") # only load the height variables for the fluorescent parameters
Simplify the sample names
#require(PTXQC)
#source("../script/20220326-simplify-names-subroutine.R")
oriNames <- sampleNames(dat0)
tmp <- str_split(oriNames, pattern = "[ _]+", simplify = TRUE)[,c(1, 6, 7)]
colnames(tmp) <- c("Date", "Treatment", "Dye")
sample <- data.frame(tmp) %>%
mutate(
Dye = case_match(
Dye,
"p.fcs" ~ "PI alone",
"pf.fcs" ~ "PI first",
"sf.fcs" ~ "SYTO9+PI",
.default = NA
)
)
rownames(sample) <- oriNames
pData(dat0) <- sample
dat <- dat0[!is.na(sample$Dye)]
print(pData(dat) %>% as_tibble())
write_tsv(pData(dat), file = "../data/10.01-sample-list.tsv")
Basic gating
Outlier
The following gaphing steps are used to gate singlets by FSC and SSC
values. Only singlets are included in analysis.
outlier.gate <- rectangleGate(filterId = "-outlier", "FSC.H" = c(1.2e5, 1e6), "SSC.H" = c(1e2, 1e6))
ggcyto(dat[c(2,20)], aes(x = FSC.H, y = SSC.H), subset = "root") +
geom_hex(bins = 64) + geom_gate(outlier.gate) + facet_wrap(~name, ncol = 2) + ggcyto_par_set(limits = "instrument")
Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Add gate to GS
# shorten the names of the samples for plotting
shortNames <- with(pData(dat),
paste(substr(Date, 1, 4), paste0(Treatment, " mM")
, Dye, sep = "_"))
names(shortNames) <- sampleNames(dat)
gs <- GatingSet(dat) # create a GatingSet
# rename the GatingSet
if(all(sampleNames(gs) == names(shortNames)))
pData(gs)$name <- shortNames
# repair the Date column in pData
pData(gs)$Date = paste0("0", pData(gs)$Date)
# add the outlier gate
gs_pop_add(gs, outlier.gate, parent = "root")
[1] 2
# compute
recompute(gs)
done!
Gate for singlets
scPars <- ggcyto_par_set(limits = list(x = c(0,1e6), y = c(30,300)))
ex <- Subset(dat[[1]], outlier.gate)
polygon <- matrix(c(1e5, 1e5, 1e6, 1e6,
60, 105, 135,60), ncol = 2)
colnames(polygon) <- c("FSC.H", "FSC.W")
singlet.gate <- polygonGate(filterId = "singlet", .gate = polygon)
ggcyto(ex, aes(x = FSC.H, y = FSC.W)) + geom_hex(bins = 128) + geom_gate(singlet.gate) + geom_stats() + scPars
Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Add this gate to the gatingSet
gs_pop_add(gs, singlet.gate, parent = "-outlier", name = "singlet")
[1] 3
recompute(gs)
done!
scPars <- ggcyto_par_set(limits = list(x = c(0,1e6), y = c(30,200)))
test <- sample(1:length(gs), 8)
ggcyto(gs[test], aes(x = FSC.H, y = FSC.W), subset = "-outlier") +
geom_hex(bins = 128) + geom_gate("singlet") + facet_wrap(~name, ncol = 4) +
scPars# + theme(strip.text = element_blank())
Coordinate system already present. Adding new coordinate system, which will replace the existing one.

FSC and SSC vs treatment and dye
FSC
mult_format <- function() {
function(x) format(x/10000,digits = 2)
}
for(date in c("011124", "011524", "011624")){
p <- ggcyto(gs[pData(gs)$Date == date], aes(x = FSC.H), subset = "singlet") +
geom_density_ridges(aes(y = Treatment), fill = "forestgreen", alpha = 0.8) +
scale_x_continuous(labels = mult_format(), name = "FSC.H x 10000") +
facet_wrap(~Dye) + labs(title = paste0("Date: ", date))
print(p)
}



Mock treated sample stands out - the three H2O2 treated samples show
a trend of decreasing FSC with increasing ROS Mock has a FSC in between
10 and 100 mM
FSC vs BL1.H (green staining)
for(date in c("011124", "011524", "011624")){
p <- ggcyto(gs[pData(gs)$Date == date], aes(x = BL1.H, y = FSC.H), subset = "singlet") +
geom_hex(bins = 128) +
#geom_gate(live.gate) +
#geom_stats(location = "data", adjust = c(0.1, 0.8), digits = 2) +
labs(title = paste0("Date: ", date)) +
facet_grid(Dye ~ Treatment) +
scale_x_logicle() + #scale_y_logicle() +
theme(strip.text = element_text(size = rel(1.1), color = "steelblue", face = 2))
print(p)
}



SSC
for(date in c("011124", "011524", "011624")){
p <- ggcyto(gs[pData(gs)$Date == date], aes(x = SSC.H), subset = "singlet") +
geom_density_ridges(aes(y = Treatment), fill = "forestgreen", alpha = 0.8) +
scale_x_continuous(labels = mult_format(), name = "FSC.H x 10000") +
facet_wrap(~Dye) + labs(title = paste0("Date: ", date))
print(p)
}



SSC (complexity of cell, roughly) decreases with increasing H2O2
concentration Mock again show a different pattern.
Gate for scoring
Live = red negative
This is the live population with red fluorescence below 10^2.2
Important: I changed the Red top boundary to
10^2.3 from 10^2.2
Main takeaway
From 10mM to 1M treated samples, %live decreases and the change
is much more obvious in the dual stain (PI first or simultaneous) than
PI alone
The mock treated sample has a visible high red high green (not as
high and prominent as the 100 mM treated) than 10 mM treated. It doesn’t
follow the trend above.
#scPars <- ggcyto_par_set(limits = list(x = c(0,1e6), y = c(0,1e5)))
polygon <- matrix(c(0, 10^5, 10^5, 0,
10^2.3, 10^2.3, 0, 0), ncol = 2)
colnames(polygon) <- c("BL1.H", "BL3.H")
live.gate <- polygonGate(filterId = "live", .gate = polygon)
for(date in c("011124", "011524", "011624")){
p <- ggcyto(gs[pData(gs)$Date == date], aes(x = BL1.H, y = BL3.H), subset = "singlet") +
geom_hex(bins = 128) +
geom_gate(live.gate) +
geom_stats(location = "data", adjust = c(0.1, 0.8), digits = 2) +
labs(title = paste0("Date: ", date)) +
facet_grid(Dye ~ Treatment) +
scale_x_logicle() + scale_y_logicle() +
theme(strip.text = element_text(size = rel(1.1), color = "steelblue", face = 2))
print(p)
}



Notice the higher percentage of events in the live gate in 10 mM vs
mock.
Add this gate to the gatingSet
Dead = High red low green
We don’t need to set the dead gate because all we want is the percent
of events in that gate, not the MFI for either channel. The percentage
can be calculated by subtracting the percent of events in the previous
two gates from 100%.
Exported gate stats
% of events in each of the three gates
gated_stats <- gs_pop_get_stats(gs, type = "count") %>%
as_tibble() %>%
mutate(pop = gsub(".*/", "", pop), pop = gsub("-outlier", "cells", pop)) %>%
pivot_wider(names_from = pop, names_prefix = "n_", values_from = count) %>%
mutate(
#p_singlet = n_singlet / n_cells,
p_live = n_live / n_singlet,
p_intermediate = n_intermediate / n_singlet,
p_dead = 1 - p_live - p_intermediate
)
#write_tsv(gated_data, file = "../Input/20240124-fig-2-Dye-Order-gated-ht.tsv")
#print(gated_data)
MFI in the live and intermediate gates
popMFI <- gs_pop_get_stats(gs, nodes = c("live", "intermediate"), type = pop.MFI) %>%
as_tibble() %>%
select(sample, pop, FSC = `FSC-H`, BL1 = `Fungalight Green-H`) %>%
pivot_wider(names_from = pop, values_from = c(FSC, BL1))
Combine the data and meta data
final <- select(pData(dat), sample = name, everything()) %>%
left_join(select(gated_stats, -starts_with("n_")), by = "sample") %>%
left_join(popMFI, by = "sample")
write_tsv(final, file = "../data/12.01-gated-output-20240117.tsv")
print(final %>% select(-sample))
Exploratory comparison between PI alone and combo
PI alone
p1 <- final %>%
dplyr::filter(Dye == "PI alone") %>%
ggplot(aes(x = Treatment, y = 1-p_live)) +
geom_point(size = 2, shape = 21, position = position_jitter(0.05)) +
#stat_summary(fun = "mean", geom = "point", color = "red") +
labs(x = bquote(H[2]*O[2]~(mM)), y = "1 - %Live") +
theme_cowplot()
inset <- final %>%
dplyr::filter(Dye == "PI alone", Treatment != "1000") %>%
ggplot(aes(x = Treatment, y = 1-p_live)) +
geom_bar(stat = "summary", fun = "mean", fill = "skyblue2", alpha = 0.7) +
geom_point(size = 2, position = position_jitter(0.05)) +
#stat_summary(fun = "mean", geom = "point", size = 15, shape = "-", color = "red") +
labs(x = bquote(H[2]*O[2]~(mM)), y = "1 - %Live") +
theme_minimal_hgrid(11)
ggdraw(p1 + labs(subtitle = "PI alone, doesn't disguish 10 vs 100 mM")) +
draw_plot(inset, .2, .8, .4, .5, vjust = 1) +
draw_plot_label(c("A", "B"), c(0, 0.18), c(1, 0.85))
ggsave("../output/12.01-PI-alone-one-minus-perc-live.png", width = 5, height = 4)

PI+SYTO9
p2 <- final %>%
dplyr::filter(Dye != "PI alone", Treatment != "0") %>%
ggplot(aes(x = Treatment, y = 1-p_live)) +
geom_bar(stat = "summary", fun = "mean", fill = "gray", alpha = 0.7) +
geom_point(size = 2, position = position_jitter(0.05)) +
#stat_summary(fun = "mean", geom = "point", shape = "-",
# size = 15, color = "red", position = position_nudge(x = 0.2)) +
labs(x = bquote(H[2]*O[2]~(mM)), y = "1 - %Live") +
facet_wrap(~Dye) +
theme_cowplot() +
theme(strip.text = element_text(size = rel(1.2), face = 2),
strip.background = element_blank())
p2
ggsave("../output/12.01-PI+SYTO9-one-minus-plive.png")
Saving 7.29 x 4.51 in image

Plot % Dead and Compare
```r
pf1g <- gated_data %>%
dplyr::filter(!(Dye %in% c(\PI\))) %>%
dplyr::filter(!(Treatment %in% c(\1000 mM\))) %>%
#mutate(Dilution = factor(Dilution, levels = c(\250 x\, \500 x\, \1000 x\, \2000 x\))) %>%
ggplot(aes(x = Treatment, y = percent_Live)) +
facet_wrap(~ Dye, scale = \free_y\) +
geom_boxplot() +
geom_point(stroke = 1, size = 2, position = position_jitter(0.2)) +
scale_y_continuous(labels = scales::percent) +
theme_minimal()
pf1g +
labs(x = \Hydrogen Peroxide Treatment Concentration\, y = \Gated Live Cells\) +
panel_border(color = \black\, size = 1.5) +
theme(axis.line = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(size = 12, face = \bold\, color = \black\), # Adjust size and face (bold)
axis.text.y = element_text(size = 16, face = \bold\, color = \black\),
axis.title.x = element_text(size = 16, face = \bold\),
axis.title.y = element_text(size = 16, face = \bold\)
)+
theme(strip.text = element_text(size = 16, face = \bold\))
#ggsave(\../output/20240104-PI-Dilutions-Gated_RP-Plot.png\, width = 7, height = 5)
```
LS0tCnRpdGxlOiAiRHllIE9yZGVyICYgRGlzdGluZ3Vpc2hpbmcgUG93ZXIiCmF1dGhvcjogSGFueGkgVGFuZywgQmluIEhlCmRhdGU6ICIyMDI0LTAxLTE3ICh1cGRhdGVkIGByIFN5cy50aW1lKClgKSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKIyBCYWNrZ3JvdW5kClRoaXMgaXMgdGhlIGZsb3cgY3l0b21ldHJ5IGRhdGEgZm9yIG1pZ2xvZyBwaGFzZSBDZyBzdGFpbmVkIHdpdGggUEkvUEkrU1lUTzkvIFNZVE8rUEkgaW4gZGlmZmVyZW50IHN0YWluaW5nIG9yZGVycywgYW5kIHJ1biB0aHJvdWdoIGZsb3cgY3l0b21ldHJ5IChkZXRhaWxzIGluIEVMTikuIFRoZSBnb2FsIGlzIHRvIGVzdGFibGlzaCBGdW5nYUxpZ2h0J3MgZGlzdGluZ3Vpc2hpbmcgcG93ZXIgd2l0aCBkaWZmZXJlbnQgc3RhaW5pbmcgcHJvdG9jb2xzLgoKYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0V9CnJlcXVpcmUodGlkeXZlcnNlKQpyZXF1aXJlKGZsb3dDb3JlKQpyZXF1aXJlKGZsb3dDbHVzdCkKcmVxdWlyZShvcGVuQ3l0bykKcmVxdWlyZShnZ2N5dG8pCnJlcXVpcmUoY293cGxvdCkKcmVxdWlyZShnZ3JpZGdlcykKYGBgCgpgYGB7cn0Kb2xkIDwtIHRoZW1lX3NldCh0aGVtZV9taW5pbWFsKCkpCmBgYAoKIyBJbXBvcnQgZGF0YQoKPiBGQ1MgZmlsZXMgYXJlIHN0b3JlZCBpbiBSRFNTL3VzZXIvZmxvdyBjeXRvbWV0cnksIEZDUyBpcyByZWFkIGFuZCB3cml0ZSBpbnRvIGFuIGlucHV0IHRzdiB0YWJsZS4gVGhlIHRzdiBmaWxlIGlzIGF2YWxpYWJsZSBmcm9tIHRoZSBJbnB1dCBmb2xkZXIuCgpgYGB7cn0KIyB1c2UgcmVsYXRpdmUgcGF0aCB0byBtYWtlIGl0IGVhc2llciBmb3IgY29sbGFib3JhdGlvbgpkYXRhLnBhdGggPSAiL1ZvbHVtZXMvcmRzc19iaGUyL1VzZXIvSGFueGkgVGFuZy9GbG93IEN5dG9tZXRyeS8yMDI0MDEwOV8wMTE2IER5ZSBvcmRlci8iCmRhdDAgPC0gcmVhZC5mbG93U2V0KHBhdGggPSBkYXRhLnBhdGgsIHRyYW5zZm9ybWF0aW9uID0gRkFMU0UsICAjIHRoZSBvcmlnaW5hbCB2YWx1ZXMgYXJlIGFscmVhZHkgbGluZWFyaXplZC4gCiAgICAgICAgICAgICAgICAgICAgIGVtcHR5VmFsdWUgPSBGQUxTRSwgIGFsdGVyLm5hbWVzID0gVFJVRSwgICAjIGNoYW5nZSBwYXJhbWV0ZXIgbmFtZXMgdG8gUiBmb3JtYXQKICAgICAgICAgICAgICAgICAgICAgY29sdW1uLnBhdHRlcm4gPSAiLkh8RlNDfFNTQyIpICMgb25seSBsb2FkIHRoZSBoZWlnaHQgdmFyaWFibGVzIGZvciB0aGUgZmx1b3Jlc2NlbnQgcGFyYW1ldGVycwpgYGAKCiMjIFNpbXBsaWZ5IHRoZSBzYW1wbGUgbmFtZXMKCmBgYHtyfQojcmVxdWlyZShQVFhRQykKI3NvdXJjZSgiLi4vc2NyaXB0LzIwMjIwMzI2LXNpbXBsaWZ5LW5hbWVzLXN1YnJvdXRpbmUuUiIpCm9yaU5hbWVzIDwtIHNhbXBsZU5hbWVzKGRhdDApCnRtcCA8LSBzdHJfc3BsaXQob3JpTmFtZXMsIHBhdHRlcm4gPSAiWyBfXSsiLCBzaW1wbGlmeSA9IFRSVUUpWyxjKDEsIDYsIDcpXQpjb2xuYW1lcyh0bXApIDwtIGMoIkRhdGUiLCAiVHJlYXRtZW50IiwgIkR5ZSIpCnNhbXBsZSA8LSBkYXRhLmZyYW1lKHRtcCkgJT4lIAogIG11dGF0ZSgKICAgIER5ZSA9IGNhc2VfbWF0Y2goCiAgICAgIER5ZSwKICAgICAgInAuZmNzIiB+ICJQSSBhbG9uZSIsCiAgICAgICJwZi5mY3MiIH4gIlBJIGZpcnN0IiwKICAgICAgInNmLmZjcyIgfiAiU1lUTzkrUEkiLAogICAgICAuZGVmYXVsdCA9IE5BCiAgICApCiAgKQpyb3duYW1lcyhzYW1wbGUpIDwtIG9yaU5hbWVzCnBEYXRhKGRhdDApIDwtIHNhbXBsZQpkYXQgPC0gZGF0MFshaXMubmEoc2FtcGxlJER5ZSldCnByaW50KHBEYXRhKGRhdCkgJT4lIGFzX3RpYmJsZSgpKQp3cml0ZV90c3YocERhdGEoZGF0KSwgZmlsZSA9ICIuLi9kYXRhLzEyLjAxLXNhbXBsZS1saXN0LTIwMjQwMTE3LnRzdiIpCmBgYAoKIyBCYXNpYyBnYXRpbmcKIyMgT3V0bGllcgpUaGUgZm9sbG93aW5nIGdhcGhpbmcgc3RlcHMgYXJlIHVzZWQgdG8gZ2F0ZSBzaW5nbGV0cyBieSBGU0MgYW5kIFNTQyB2YWx1ZXMuIE9ubHkgc2luZ2xldHMgYXJlIGluY2x1ZGVkIGluIGFuYWx5c2lzLgoKYGBge3J9Cm91dGxpZXIuZ2F0ZSA8LSByZWN0YW5nbGVHYXRlKGZpbHRlcklkID0gIi1vdXRsaWVyIiwgIkZTQy5IIiA9IGMoMS4yZTUsIDFlNiksICJTU0MuSCIgPSBjKDFlMiwgMWU2KSkKZ2djeXRvKGRhdFtjKDIsMjApXSwgYWVzKHggPSBGU0MuSCwgeSA9IFNTQy5IKSwgc3Vic2V0ID0gInJvb3QiKSArCiAgZ2VvbV9oZXgoYmlucyA9IDY0KSArIGdlb21fZ2F0ZShvdXRsaWVyLmdhdGUpICsgZmFjZXRfd3JhcCh+bmFtZSwgbmNvbCA9IDIpICsgZ2djeXRvX3Bhcl9zZXQobGltaXRzID0gImluc3RydW1lbnQiKQpgYGAKQWRkIGdhdGUgdG8gR1MKYGBge3J9CiMgc2hvcnRlbiB0aGUgbmFtZXMgb2YgdGhlIHNhbXBsZXMgZm9yIHBsb3R0aW5nCnNob3J0TmFtZXMgPC0gd2l0aChwRGF0YShkYXQpLCAKICAgICAgICAgICAgICAgICAgIHBhc3RlKHN1YnN0cihEYXRlLCAxLCA0KSwgcGFzdGUwKFRyZWF0bWVudCwgIiBtTSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAsIER5ZSwgc2VwID0gIl8iKSkKbmFtZXMoc2hvcnROYW1lcykgPC0gc2FtcGxlTmFtZXMoZGF0KQpncyA8LSBHYXRpbmdTZXQoZGF0KSAjIGNyZWF0ZSBhIEdhdGluZ1NldAojIHJlbmFtZSB0aGUgR2F0aW5nU2V0CmlmKGFsbChzYW1wbGVOYW1lcyhncykgPT0gbmFtZXMoc2hvcnROYW1lcykpKQogIHBEYXRhKGdzKSRuYW1lIDwtIHNob3J0TmFtZXMKIyByZXBhaXIgdGhlIERhdGUgY29sdW1uIGluIHBEYXRhCnBEYXRhKGdzKSREYXRlID0gcGFzdGUwKCIwIiwgcERhdGEoZ3MpJERhdGUpCiMgYWRkIHRoZSBvdXRsaWVyIGdhdGUKZ3NfcG9wX2FkZChncywgb3V0bGllci5nYXRlLCBwYXJlbnQgPSAicm9vdCIpCiMgY29tcHV0ZQpyZWNvbXB1dGUoZ3MpCmBgYAoKIyMgR2F0ZSBmb3Igc2luZ2xldHMKCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTR9CnNjUGFycyA8LSBnZ2N5dG9fcGFyX3NldChsaW1pdHMgPSBsaXN0KHggPSBjKDAsMWU2KSwgeSA9IGMoMzAsMzAwKSkpCmV4IDwtIFN1YnNldChkYXRbWzFdXSwgb3V0bGllci5nYXRlKQpwb2x5Z29uIDwtIG1hdHJpeChjKDFlNSwgMWU1LCAxZTYsIDFlNiwgCiAgICAgICAgICAgICAgICAgICAgNjAsIDEwNSwgMTM1LDYwKSwgbmNvbCA9IDIpCmNvbG5hbWVzKHBvbHlnb24pIDwtIGMoIkZTQy5IIiwgIkZTQy5XIikKc2luZ2xldC5nYXRlIDwtIHBvbHlnb25HYXRlKGZpbHRlcklkID0gInNpbmdsZXQiLCAuZ2F0ZSA9IHBvbHlnb24pCmdnY3l0byhleCwgYWVzKHggPSBGU0MuSCwgeSA9IEZTQy5XKSkgKyBnZW9tX2hleChiaW5zID0gMTI4KSArIGdlb21fZ2F0ZShzaW5nbGV0LmdhdGUpICsgZ2VvbV9zdGF0cygpICsgc2NQYXJzCmBgYAoKCkFkZCB0aGlzIGdhdGUgdG8gdGhlIGdhdGluZ1NldApgYGB7cn0KZ3NfcG9wX2FkZChncywgc2luZ2xldC5nYXRlLCBwYXJlbnQgPSAiLW91dGxpZXIiLCBuYW1lID0gInNpbmdsZXQiKQpyZWNvbXB1dGUoZ3MpCmBgYApgYGB7ciBmaWcud2lkdGg9Nn0Kc2NQYXJzIDwtIGdnY3l0b19wYXJfc2V0KGxpbWl0cyA9IGxpc3QoeCA9IGMoMCwxZTYpLCB5ID0gYygzMCwyMDApKSkKdGVzdCA8LSBzYW1wbGUoMTpsZW5ndGgoZ3MpLCA4KQpnZ2N5dG8oZ3NbdGVzdF0sIGFlcyh4ID0gRlNDLkgsIHkgPSBGU0MuVyksIHN1YnNldCA9ICItb3V0bGllciIpICsKICBnZW9tX2hleChiaW5zID0gMTI4KSArIGdlb21fZ2F0ZSgic2luZ2xldCIpICsgZmFjZXRfd3JhcCh+bmFtZSwgbmNvbCA9IDQpICsgCiAgc2NQYXJzIyArIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpCgpgYGAKIyMgRlNDIGFuZCBTU0MgdnMgdHJlYXRtZW50IGFuZCBkeWUgey50YWJzZXR9CgojIyMgRlNDCgpgYGB7cn0KbXVsdF9mb3JtYXQgPC0gZnVuY3Rpb24oKSB7CiAgICAgZnVuY3Rpb24oeCkgZm9ybWF0KHgvMTAwMDAsZGlnaXRzID0gMikgCn0KZm9yKGRhdGUgaW4gYygiMDExMTI0IiwgIjAxMTUyNCIsICIwMTE2MjQiKSl7CiAgcCA8LSBnZ2N5dG8oZ3NbcERhdGEoZ3MpJERhdGUgPT0gZGF0ZV0sIGFlcyh4ID0gRlNDLkgpLCBzdWJzZXQgPSAic2luZ2xldCIpICsgCiAgICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFlcyh5ID0gVHJlYXRtZW50KSwgZmlsbCA9ICJmb3Jlc3RncmVlbiIsIGFscGhhID0gMC44KSArIAogICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IG11bHRfZm9ybWF0KCksIG5hbWUgPSAiRlNDLkggeCAxMDAwMCIpICsKICAgIGZhY2V0X3dyYXAofkR5ZSkgKyBsYWJzKHRpdGxlID0gcGFzdGUwKCJEYXRlOiAiLCBkYXRlKSkKICBwcmludChwKQp9CmBgYAo+IE1vY2sgdHJlYXRlZCBzYW1wbGUgc3RhbmRzIG91dCAtIHRoZSB0aHJlZSBIMk8yIHRyZWF0ZWQgc2FtcGxlcyBzaG93IGEgdHJlbmQgb2YgZGVjcmVhc2luZyBGU0Mgd2l0aCBpbmNyZWFzaW5nIFJPUwo+IE1vY2sgaGFzIGEgRlNDIGluIGJldHdlZW4gMTAgYW5kIDEwMCBtTQoKIyMjIEZTQyB2cyBCTDEuSCAoZ3JlZW4gc3RhaW5pbmcpCmBgYHtyfQpmb3IoZGF0ZSBpbiBjKCIwMTExMjQiLCAiMDExNTI0IiwgIjAxMTYyNCIpKXsKICBwIDwtIGdnY3l0byhnc1twRGF0YShncykkRGF0ZSA9PSBkYXRlXSwgYWVzKHggPSBCTDEuSCwgeSA9IEZTQy5IKSwgc3Vic2V0ID0gInNpbmdsZXQiKSArIAogICAgZ2VvbV9oZXgoYmlucyA9IDEyOCkgKyAKICAgICNnZW9tX2dhdGUobGl2ZS5nYXRlKSArIAogICAgI2dlb21fc3RhdHMobG9jYXRpb24gPSAiZGF0YSIsIGFkanVzdCA9IGMoMC4xLCAwLjgpLCBkaWdpdHMgPSAyKSArIAogICAgbGFicyh0aXRsZSA9IHBhc3RlMCgiRGF0ZTogIiwgZGF0ZSkpICsKICAgIGZhY2V0X2dyaWQoRHllIH4gVHJlYXRtZW50KSArCiAgICBzY2FsZV94X2xvZ2ljbGUoKSArICNzY2FsZV95X2xvZ2ljbGUoKSArIAogICAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMSksIGNvbG9yID0gInN0ZWVsYmx1ZSIsIGZhY2UgPSAyKSkKICBwcmludChwKQp9CmBgYAoKCiMjIyBTU0MKCmBgYHtyfQpmb3IoZGF0ZSBpbiBjKCIwMTExMjQiLCAiMDExNTI0IiwgIjAxMTYyNCIpKXsKICBwIDwtIGdnY3l0byhnc1twRGF0YShncykkRGF0ZSA9PSBkYXRlXSwgYWVzKHggPSBTU0MuSCksIHN1YnNldCA9ICJzaW5nbGV0IikgKyAKICAgIGdlb21fZGVuc2l0eV9yaWRnZXMoYWVzKHkgPSBUcmVhdG1lbnQpLCBmaWxsID0gImZvcmVzdGdyZWVuIiwgYWxwaGEgPSAwLjgpICsgCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gbXVsdF9mb3JtYXQoKSwgbmFtZSA9ICJGU0MuSCB4IDEwMDAwIikgKwogICAgZmFjZXRfd3JhcCh+RHllKSArIGxhYnModGl0bGUgPSBwYXN0ZTAoIkRhdGU6ICIsIGRhdGUpKQogIHByaW50KHApCn0KYGBgCj4gU1NDIChjb21wbGV4aXR5IG9mIGNlbGwsIHJvdWdobHkpIGRlY3JlYXNlcyB3aXRoIGluY3JlYXNpbmcgSDJPMiBjb25jZW50cmF0aW9uCj4gTW9jayBhZ2FpbiBzaG93IGEgZGlmZmVyZW50IHBhdHRlcm4uCgoKIyBHYXRlIGZvciBzY29yaW5nIHsudGFic2V0fQoKIyMgTGl2ZSA9IHJlZCBuZWdhdGl2ZQoKVGhpcyBpcyB0aGUgbGl2ZSBwb3B1bGF0aW9uIHdpdGggcmVkIGZsdW9yZXNjZW5jZSBiZWxvdyAxMF4yLjIKCj4gPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+SW1wb3J0YW50OiBJIGNoYW5nZWQgdGhlIFJlZCB0b3AgYm91bmRhcnkgdG8gMTBeMi4zIGZyb20gMTBeMi4yPC9zcGFuPgoKPiAqKk1haW4gdGFrZWF3YXkqKgo+Cj4gMS4gRnJvbSAxMG1NIHRvIDFNIHRyZWF0ZWQgc2FtcGxlcywgJWxpdmUgZGVjcmVhc2VzIGFuZCB0aGUgY2hhbmdlIGlzIG11Y2ggbW9yZSBvYnZpb3VzIGluIHRoZSBkdWFsIHN0YWluIChQSSBmaXJzdCBvciBzaW11bHRhbmVvdXMpIHRoYW4gUEkgYWxvbmUKPgo+IDIuIFRoZSBtb2NrIHRyZWF0ZWQgc2FtcGxlIGhhcyBhIHZpc2libGUgaGlnaCByZWQgaGlnaCBncmVlbiAobm90IGFzIGhpZ2ggYW5kIHByb21pbmVudCBhcyB0aGUgMTAwIG1NIHRyZWF0ZWQpIHRoYW4gMTAgbU0gdHJlYXRlZC4gSXQgZG9lc24ndCBmb2xsb3cgdGhlIHRyZW5kIGFib3ZlLgoKYGBge3IsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTV9CiNzY1BhcnMgPC0gZ2djeXRvX3Bhcl9zZXQobGltaXRzID0gbGlzdCh4ID0gYygwLDFlNiksIHkgPSBjKDAsMWU1KSkpCnBvbHlnb24gPC0gbWF0cml4KGMoMCwgMTBeNSwgMTBeNSwgMCwKICAgICAgICAgICAgICAgICAgICAxMF4yLjMsIDEwXjIuMywgMCwgMCksIG5jb2wgPSAyKQpjb2xuYW1lcyhwb2x5Z29uKSA8LSBjKCJCTDEuSCIsICJCTDMuSCIpCmxpdmUuZ2F0ZSA8LSBwb2x5Z29uR2F0ZShmaWx0ZXJJZCA9ICJsaXZlIiwgLmdhdGUgPSBwb2x5Z29uKQpmb3IoZGF0ZSBpbiBjKCIwMTExMjQiLCAiMDExNTI0IiwgIjAxMTYyNCIpKXsKICBwIDwtIGdnY3l0byhnc1twRGF0YShncykkRGF0ZSA9PSBkYXRlXSwgYWVzKHggPSBCTDEuSCwgeSA9IEJMMy5IKSwgc3Vic2V0ID0gInNpbmdsZXQiKSArIAogICAgZ2VvbV9oZXgoYmlucyA9IDEyOCkgKyAKICAgIGdlb21fZ2F0ZShsaXZlLmdhdGUpICsgCiAgICBnZW9tX3N0YXRzKGxvY2F0aW9uID0gImRhdGEiLCBhZGp1c3QgPSBjKDAuMSwgMC44KSwgZGlnaXRzID0gMikgKyAKICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoIkRhdGU6ICIsIGRhdGUpKSArCiAgICBmYWNldF9ncmlkKER5ZSB+IFRyZWF0bWVudCkgKwogICAgc2NhbGVfeF9sb2dpY2xlKCkgKyBzY2FsZV95X2xvZ2ljbGUoKSArIAogICAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMSksIGNvbG9yID0gInN0ZWVsYmx1ZSIsIGZhY2UgPSAyKSkKICBwcmludChwKQp9CmBgYAo+IE5vdGljZSB0aGUgaGlnaGVyIHBlcmNlbnRhZ2Ugb2YgZXZlbnRzIGluIHRoZSBsaXZlIGdhdGUgaW4gMTAgbU0gdnMgbW9jay4KCkFkZCB0aGlzIGdhdGUgdG8gdGhlIGdhdGluZ1NldAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZ3NfcG9wX2FkZChncywgbGl2ZS5nYXRlLCBwYXJlbnQgPSAic2luZ2xldCIsIG5hbWUgPSAibGl2ZSIpCnJlY29tcHV0ZShncykKYGBgCgojIyBJbnRlcm1lZGlhdGUgPSBoaWdoIEcvUgpUaGlzIGlzIHRoZSBpbnRlcm1lZGlhdGUgcG9wdWxhdGlvbiB3aXRoIGhpZ2ggUmVkIGFuZCBHcmVlbi4gV2UgaHlwb3RoZXNpemUgdGhhdCB0aGV5IHJlcHJlc2VudCB0aGUgCgo+IDxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPkltcG9ydGFudDogSSBjaGFuZ2VkIHRoZSBib3R0b20gYm91bmRhcnkgZnJvbSAxMF4yLjIgdG8gMTBeMi4zLCBhbmQgdGhlIGxlZnQgYm91bmRhcnkgZnJvbSAxMF4zIHRvIDIqMTBeMzwvc3Bhbj4KCj4gKipNYWluIHRha2Vhd2F5KioKPgo+IDEuIERpZmZlcmVudCBmcm9tIHRoZSAlbGl2ZSBnYXRlLCB0aGUgaW50ZXJtZWRpYXRlIHBvcHVsYXRpb24gaXMgbW9zdCBvYnZpb3VzIGluIHRoZSAKPiAxMDAgbU0gdHJlYXRlZCBzYW1wbGUsIGFuZCBhYnNlbnQgaW4gYm90aCB0aGUgMTAgbU0gYW5kIDFNIHRyZWF0ZWQgb25lcy4gVGhpcyBzdWdnZXN0cwo+IHRoYXQgdGhpcyBwb3B1bGF0aW9uIGNvdWxkIGJlIHVzZWZ1bCBmb3IgZGlzdGluZ3Vpc2hpbmcgc3RyZXNzIGxldmVscyBiZWxvdyB0aGUgbGV0aGFsIGNvbmNlbnRyYXRpb24KPiBidXQgYWJvdmUgdGhlIHRvbGVyYW5jZSBsZXZlbHMgb2YgdGhlIHNwZWNpZXMgLSBpbiB0aGlzIGNhc2UsIDwgMU0gYW5kID4gMTAgbU0uCj4KPiAyLiBUaGUgbW9jayB0cmVhdGVkIHNhbXBsZSBzaG93ZWQgYW4gaW50ZXJtZWRpYXRlIHBvcHVsYXRpb24uIFdhcyB1bmV4cGVjdGVkLgoKYGBge3IsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTV9CiNzY1BhcnMgPC0gZ2djeXRvX3Bhcl9zZXQobGltaXRzID0gbGlzdCh4ID0gYygwLDFlNiksIHkgPSBjKDAsMWU2KSkpCiNleCA8LSBTdWJzZXQoZGF0LmYxZ1tbOV1dLCBzaW5nbGV0LmdhdGUpCnBvbHlnb24gPC0gbWF0cml4KGMoMTBeNSwgMioxMF4zLCAxMF41LAogICAgICAgICAgICAgICAgICAgIDEwXjIuMywgMTBeMi4zLCAxMF40KSwgbmNvbCA9IDIpCmNvbG5hbWVzKHBvbHlnb24pIDwtIGMoIkJMMS5IIiwgIkJMMy5IIikKaW50ZXIuZ2F0ZSA8LSBwb2x5Z29uR2F0ZShmaWx0ZXJJZCA9ICJpbnRlciIsIC5nYXRlID0gcG9seWdvbikKZm9yKGRhdGUgaW4gYygiMDExMTI0IiwgIjAxMTUyNCIsICIwMTE2MjQiKSl7CiAgcCA8LSBnZ2N5dG8oZ3NbcERhdGEoZ3MpJERhdGUgPT0gZGF0ZV0sIGFlcyh4ID0gQkwxLkgsIHkgPSBCTDMuSCksIHN1YnNldCA9ICJzaW5nbGV0IikgKyAKICAgIGdlb21faGV4KGJpbnMgPSAxMjgpICsgCiAgICBnZW9tX2dhdGUoaW50ZXIuZ2F0ZSkgKyAKICAgIGdlb21fc3RhdHMobG9jYXRpb24gPSAiZGF0YSIsICBhZGp1c3QgPSBjKDAuMSwgMC44KSwgZGlnaXRzID0gMikgKyAKICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoIkRhdGU6ICIsIGRhdGUpKSArCiAgICBmYWNldF9ncmlkKER5ZSB+IFRyZWF0bWVudCkgKwogICAgc2NhbGVfeF9sb2dpY2xlKCkgKyBzY2FsZV95X2xvZ2ljbGUoKSArIAogICAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMSksIGNvbG9yID0gInN0ZWVsYmx1ZSIsIGZhY2UgPSAyKSkKICBwcmludChwKQp9CmBgYAoKCkFkZCB0aGlzIGdhdGUgdG8gdGhlIGdhdGluZ1NldAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZ3NfcG9wX2FkZChncywgaW50ZXIuZ2F0ZSwgcGFyZW50ID0gInNpbmdsZXQiLCBuYW1lID0gImludGVybWVkaWF0ZSIpCnJlY29tcHV0ZShncykKYGBgCgojIyBEZWFkID0gSGlnaCByZWQgbG93IGdyZWVuCldlIGRvbid0IG5lZWQgdG8gc2V0IHRoZSBkZWFkIGdhdGUgYmVjYXVzZSBhbGwgd2Ugd2FudCBpcyB0aGUgcGVyY2VudCBvZiBldmVudHMgaW4gdGhhdCBnYXRlLCBub3QgdGhlIE1GSSBmb3IgZWl0aGVyIGNoYW5uZWwuIFRoZSBwZXJjZW50YWdlIGNhbiBiZSBjYWxjdWxhdGVkIGJ5IHN1YnRyYWN0aW5nIHRoZSBwZXJjZW50IG9mIGV2ZW50cyBpbiB0aGUgcHJldmlvdXMgdHdvIGdhdGVzIGZyb20gMTAwJS4KCgojIEV4cG9ydGVkIGdhdGUgc3RhdHMKCiUgb2YgZXZlbnRzIGluIGVhY2ggb2YgdGhlIHRocmVlIGdhdGVzCmBgYHtyfQpnYXRlZF9zdGF0cyA8LSBnc19wb3BfZ2V0X3N0YXRzKGdzLCB0eXBlID0gImNvdW50IikgJT4lIAogIGFzX3RpYmJsZSgpICU+JSAKICBtdXRhdGUocG9wID0gZ3N1YigiLiovIiwgIiIsIHBvcCksIHBvcCA9IGdzdWIoIi1vdXRsaWVyIiwgImNlbGxzIiwgcG9wKSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwb3AsIG5hbWVzX3ByZWZpeCA9ICJuXyIsIHZhbHVlc19mcm9tID0gY291bnQpICU+JSAKICBtdXRhdGUoCiAgICAjcF9zaW5nbGV0ID0gbl9zaW5nbGV0IC8gbl9jZWxscywKICAgIHBfbGl2ZSA9IG5fbGl2ZSAvIG5fc2luZ2xldCwKICAgIHBfaW50ZXJtZWRpYXRlID0gbl9pbnRlcm1lZGlhdGUgLyBuX3NpbmdsZXQsCiAgICBwX2RlYWQgPSAxIC0gcF9saXZlIC0gcF9pbnRlcm1lZGlhdGUKICApCiN3cml0ZV90c3YoZ2F0ZWRfZGF0YSwgZmlsZSA9ICIuLi9JbnB1dC8yMDI0MDEyNC1maWctMi1EeWUtT3JkZXItZ2F0ZWQtaHQudHN2IikKI3ByaW50KGdhdGVkX2RhdGEpCmBgYAoKTUZJIGluIHRoZSBsaXZlIGFuZCBpbnRlcm1lZGlhdGUgZ2F0ZXMKYGBge3J9CnBvcE1GSSA8LSBnc19wb3BfZ2V0X3N0YXRzKGdzLCBub2RlcyA9IGMoImxpdmUiLCAiaW50ZXJtZWRpYXRlIiksIHR5cGUgPSBwb3AuTUZJKSAlPiUgCiAgYXNfdGliYmxlKCkgJT4lIAogIHNlbGVjdChzYW1wbGUsIHBvcCwgRlNDID0gYEZTQy1IYCwgQkwxID0gYEZ1bmdhbGlnaHQgR3JlZW4tSGApICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcG9wLCB2YWx1ZXNfZnJvbSA9IGMoRlNDLCBCTDEpKQpgYGAKCkNvbWJpbmUgdGhlIGRhdGEgYW5kIG1ldGEgZGF0YQpgYGB7cn0KZmluYWwgPC0gc2VsZWN0KHBEYXRhKGRhdCksIHNhbXBsZSA9IG5hbWUsIGV2ZXJ5dGhpbmcoKSkgJT4lIAogIGxlZnRfam9pbihzZWxlY3QoZ2F0ZWRfc3RhdHMsIC1zdGFydHNfd2l0aCgibl8iKSksICBieSA9ICJzYW1wbGUiKSAlPiUgCiAgbGVmdF9qb2luKHBvcE1GSSwgYnkgPSAic2FtcGxlIikKCndyaXRlX3RzdihmaW5hbCwgZmlsZSA9ICIuLi9kYXRhLzEyLjAxLWdhdGVkLW91dHB1dC0yMDI0MDExNy50c3YiKQpwcmludChmaW5hbCAlPiUgc2VsZWN0KC1zYW1wbGUpKQpgYGAKCgojIEV4cGxvcmF0b3J5IGNvbXBhcmlzb24gYmV0d2VlbiBQSSBhbG9uZSBhbmQgY29tYm8KClBJIGFsb25lCmBgYHtyfQpwMSA8LSBmaW5hbCAlPiUgCiAgZHBseXI6OmZpbHRlcihEeWUgPT0gIlBJIGFsb25lIikgJT4lIAogIGdncGxvdChhZXMoeCA9IFRyZWF0bWVudCwgeSA9IDEtcF9saXZlKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBzaGFwZSA9IDIxLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjA1KSkgKyAKICAjc3RhdF9zdW1tYXJ5KGZ1biA9ICJtZWFuIiwgZ2VvbSA9ICJwb2ludCIsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHggPSBicXVvdGUoSFsyXSpPWzJdfihtTSkpLCB5ID0gIjEgLSAlTGl2ZSIpICsKICB0aGVtZV9jb3dwbG90KCkKCmluc2V0IDwtIGZpbmFsICU+JSAKICBkcGx5cjo6ZmlsdGVyKER5ZSA9PSAiUEkgYWxvbmUiLCBUcmVhdG1lbnQgIT0gIjEwMDAiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gMS1wX2xpdmUpKSArIAogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgZmlsbCA9ICJza3libHVlMiIsIGFscGhhID0gMC43KSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4wNSkpICsgCiAgI3N0YXRfc3VtbWFyeShmdW4gPSAibWVhbiIsIGdlb20gPSAicG9pbnQiLCBzaXplID0gMTUsIHNoYXBlID0gIi0iLCBjb2xvciA9ICJyZWQiKSArCiAgbGFicyh4ID0gYnF1b3RlKEhbMl0qT1syXX4obU0pKSwgeSA9ICIxIC0gJUxpdmUiKSArCiAgdGhlbWVfbWluaW1hbF9oZ3JpZCgxMSkKCmdnZHJhdyhwMSArIGxhYnMoc3VidGl0bGUgPSAiUEkgYWxvbmUsIGRvZXNuJ3QgZGlzZ3Vpc2ggMTAgdnMgMTAwIG1NIikpICsgCiAgZHJhd19wbG90KGluc2V0LCAuMiwgLjgsIC40LCAuNSwgdmp1c3QgPSAxKSArCiAgZHJhd19wbG90X2xhYmVsKGMoIkEiLCAiQiIpLCBjKDAsIDAuMTgpLCBjKDEsIDAuODUpKQoKZ2dzYXZlKCIuLi9vdXRwdXQvMTIuMDEtUEktYWxvbmUtb25lLW1pbnVzLXBlcmMtbGl2ZS5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDQpCmBgYAoKUEkrU1lUTzkKYGBge3J9CnAyIDwtIGZpbmFsICU+JSAKICBkcGx5cjo6ZmlsdGVyKER5ZSAhPSAiUEkgYWxvbmUiLCBUcmVhdG1lbnQgIT0gIjAiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gMS1wX2xpdmUpKSArIAogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIiwgZmlsbCA9ICJncmF5IiwgYWxwaGEgPSAwLjcpICsKICBnZW9tX3BvaW50KHNpemUgPSAyLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjA1KSkgKyAKICAjc3RhdF9zdW1tYXJ5KGZ1biA9ICJtZWFuIiwgZ2VvbSA9ICJwb2ludCIsIHNoYXBlID0gIi0iLCAKICAjICAgICAgICAgICAgIHNpemUgPSAxNSwgY29sb3IgPSAicmVkIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4ID0gMC4yKSkgKwogIGxhYnMoeCA9IGJxdW90ZShIWzJdKk9bMl1+KG1NKSksIHkgPSAiMSAtICVMaXZlIikgKwogIGZhY2V0X3dyYXAofkR5ZSkgKwogIHRoZW1lX2Nvd3Bsb3QoKSArCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMiksIGZhY2UgPSAyKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQoKcDIKZ2dzYXZlKCIuLi9vdXRwdXQvMTIuMDEtUEkrU1lUTzktb25lLW1pbnVzLXBsaXZlLnBuZyIpCmBgYAo+IFBsb3QgJSBEZWFkIGFuZCBDb21wYXJlCgpgYGB7cn0KcGYxZyA8LSBnYXRlZF9kYXRhICU+JQogIGRwbHlyOjpmaWx0ZXIoIShEeWUgJWluJSBjKCJQSSIpKSkgJT4lIAogIGRwbHlyOjpmaWx0ZXIoIShUcmVhdG1lbnQgJWluJSBjKCIxMDAwIG1NIikpKSAgJT4lCiAgI211dGF0ZShEaWx1dGlvbiA9IGZhY3RvcihEaWx1dGlvbiwgbGV2ZWxzID0gYygiMjUwIHgiLCAiNTAwIHgiLCAiMTAwMCB4IiwgIjIwMDAgeCIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gcGVyY2VudF9MaXZlKSkgKwogIGZhY2V0X3dyYXAofiBEeWUsIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9wb2ludChzdHJva2UgPSAxLCBzaXplID0gMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4yKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICB0aGVtZV9taW5pbWFsKCkKcGYxZyArCiAgbGFicyh4ID0gIkh5ZHJvZ2VuIFBlcm94aWRlIFRyZWF0bWVudCBDb25jZW50cmF0aW9uIiwgeSA9ICJHYXRlZCBMaXZlIENlbGxzIikgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIiksICAjIEFkanVzdCBzaXplIGFuZCBmYWNlIChib2xkKQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKQogICAgICAgICkrIAogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LCBmYWNlID0gImJvbGQiKSkgCiNnZ3NhdmUoIi4uL291dHB1dC8yMDI0MDEwNC1QSS1EaWx1dGlvbnMtR2F0ZWRfUlAtUGxvdC5wbmciLCB3aWR0aCA9IDcsIGhlaWdodCA9IDUpCmBgYA==