Setup and data
source("../utils/utils.R")
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.2 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.4 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Attaching package: 'magrittr'
The following object is masked from 'package:purrr':
set_names
The following object is masked from 'package:tidyr':
extract
Loading required package: GenomicRanges
Loading required package: stats4
Loading required package: BiocGenerics
Attaching package: 'BiocGenerics'
The following objects are masked from 'package:lubridate':
intersect, setdiff, union
The following objects are masked from 'package:dplyr':
combine, intersect, setdiff, union
The following objects are masked from 'package:stats':
IQR, mad, sd, var, xtabs
The following objects are masked from 'package:base':
anyDuplicated, aperm, append, as.data.frame, basename, cbind,
colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find,
get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply,
match, mget, order, paste, pmax, pmax.int, pmin, pmin.int,
Position, rank, rbind, Reduce, rownames, sapply, setdiff, sort,
table, tapply, union, unique, unsplit, which.max, which.min
Loading required package: S4Vectors
Attaching package: 'S4Vectors'
The following objects are masked from 'package:lubridate':
second, second<-
The following objects are masked from 'package:dplyr':
first, rename
The following object is masked from 'package:tidyr':
expand
The following objects are masked from 'package:base':
expand.grid, I, unname
Loading required package: IRanges
Attaching package: 'IRanges'
The following object is masked from 'package:lubridate':
%within%
The following objects are masked from 'package:dplyr':
collapse, desc, slice
The following object is masked from 'package:purrr':
reduce
Loading required package: GenomeInfoDb
Attaching package: 'GenomicRanges'
The following object is masked from 'package:magrittr':
subtract
Loading required package: grid
Loading required package: Biostrings
Loading required package: XVector
Attaching package: 'XVector'
The following object is masked from 'package:purrr':
compact
Attaching package: 'Biostrings'
The following object is masked from 'package:grid':
pattern
The following object is masked from 'package:base':
strsplit
Attaching package: 'gridExtra'
The following object is masked from 'package:BiocGenerics':
combine
The following object is masked from 'package:dplyr':
combine
Attaching package: 'data.table'
The following object is masked from 'package:GenomicRanges':
shift
The following object is masked from 'package:IRanges':
shift
The following objects are masked from 'package:S4Vectors':
first, second
The following objects are masked from 'package:lubridate':
hour, isoweek, mday, minute, month, quarter, second, wday, week,
yday, year
The following objects are masked from 'package:dplyr':
between, first, last
The following object is masked from 'package:purrr':
transpose
Registered S3 method overwritten by 'gplots':
method from
reorder.factor gdata
ChIPseeker v1.34.1 For help: https://guangchuangyu.github.io/software/ChIPseeker
If you use ChIPseeker in published research, please cite:
Qianwen Wang, Ming Li, Tianzhi Wu, Li Zhan, Lin Li, Meijun Chen, Wenqin Xie, Zijing Xie, Erqiang Hu, Shuangbin Xu, Guangchuang Yu. Exploring epigenomic datasets by ChIPseeker. Current Protocols 2022, 2(10): e585
Loading required package: graph
Attaching package: 'graph'
The following object is masked from 'package:Biostrings':
complement
The following object is masked from 'package:stringr':
boundary
Loading required package: Biobase
Welcome to Bioconductor
Vignettes contain introductory material; view with
'browseVignettes()'. To cite Bioconductor, see
'citation("Biobase")', and for packages 'citation("pkgname")'.
Loading required package: GO.db
Loading required package: AnnotationDbi
Attaching package: 'AnnotationDbi'
The following object is masked from 'package:dplyr':
select
Loading required package: SparseM
Attaching package: 'SparseM'
The following object is masked from 'package:base':
backsolve
groupGOTerms: GOBPTerm, GOMFTerm, GOCCTerm environments built.
Attaching package: 'topGO'
The following object is masked from 'package:grid':
depth
The following object is masked from 'package:IRanges':
members
Loading required package: GenomicFeatures
Attaching package: 'GenomicFeatures'
The following object is masked from 'package:topGO':
genes
config = load_config()
# load CHT results
cht_full = lapply(ab_tp_list, function(ab_tp) load_cht_results(ab_tp, remove_chr = F)) %>% bind_rows()
cht = cht_full %>% filter(!TEST.SNP.CHROM %in% c("chrX", "chrY", "chrM"))
cht_sign = cht %>% filter(signif_strongAI)
# genes and promoters
genes = load_genes()
promoters = resize(genes, width = 1000, fix = "start")
# combined motif set (all TFs, peaks + alleles)
fimo = get_full_motif_sets(cht, ab_tp_list)
# only alleles
fimo_alleles = lapply(ab_tp_list, function(ab_tp) parse_motifs_in_two_alleles(ab_tp, cht)) %>% bind_rows()
Figure S4A
# get variants distance to motifs (excluding peaks without motifs)
res_df = lapply(ab_tp_list, function(ab_tp) get_variant_distance2TFmotif(ab_tp, cht, fimo, same_peak = T) %>%
mutate(condition = ab_tp)) %>% bind_rows()
dist_breaks = c(-1, 0, 20, 40, 60, 80, 100, 3000)
dist_labels = c("in motif", "1-20 bp", "21-40 bp", "41-60 bp", "61-80 bp", "81-100 bp", ">100 bp")
res_full = data.frame(matrix(ncol = 6, nrow = 0))
names(res_full) = c("dist_bin", "n", "share", "sd", "type", "condition")
background_sum_all_cond = data.frame(matrix(ncol = 7, nrow = 0))
names(background_sum_all_cond) = c("dist_bin", "n", "share", "share_full", "type", "condition", "i")
for(ab_tp in ab_tp_list) {
# all variants
df_sel = res_df %>% dplyr::filter(condition == ab_tp)
N_var = length(unique(df_sel$snp_id)) # number of variants in peaks with motifs
N_peak = length(unique(df_sel$peak_id)) # number of peaks with motifs
# significant variants
df_sign = df_sel %>% filter(signif_strongAI)
N_var_sign = length(unique(df_sign$snp_id)) # number of significant variants in peaks with motifs
N_peak_sign = length(unique(df_sign$peak_id)) # number of AI peaks with motifs
sign_sum = df_sign %>%
dplyr::group_by(peak_id) %>%
dplyr::mutate(min_dist = min(dist2motif)) %>%
dplyr::filter(dist2motif == min_dist) %>%
dplyr::select(peak_id, dist2motif) %>% unique() %>% ungroup() %>%
dplyr::mutate(N_tot = n(), dist_bin = cut(dist2motif, breaks = dist_breaks, labels = dist_labels)) %>%
dplyr::group_by(dist_bin) %>%
dplyr::summarize(n = n(), share = n / mean(N_tot), sd = sd(n), type = "real", condition = ab_tp)
df_non_sign = df_sel %>% dplyr::group_by(peak_id) %>% dplyr::mutate(AI_peak = any(signif_strongAI)) %>% dplyr::filter(!AI_peak) %>% ungroup()
background_sum_all = lapply(1:10000, function(i) {
#print(i)
# 1. select same number of peaks as in AI peaks
peak_ids = sample(unique(df_non_sign$peak_id), N_peak_sign)
df_bg = df_non_sign %>% dplyr::filter(peak_id %in% peak_ids)
# 2. select same number of variants as for AI peaks
variant_ids = sample(unique(df_bg$snp_id), N_var_sign)
df_bg %<>% filter(snp_id %in% variant_ids)
N_peak_bg = length(unique(df_bg$peak_id))
bg_sum = df_bg %>%
dplyr::group_by(peak_id) %>%
dplyr::mutate(min_dist = min(dist2motif)) %>%
dplyr::filter(dist2motif == min_dist) %>%
dplyr::select(peak_id, dist2motif) %>% unique() %>% ungroup() %>%
dplyr::mutate(N_tot = n(), dist_bin = cut(dist2motif, breaks = dist_breaks, labels = dist_labels)) %>%
dplyr::group_by(dist_bin) %>%
dplyr::summarize(n = n(), share = n / mean(N_tot), share_full = n / N_peak_bg) %>%
dplyr::mutate(condition = ab_tp, i = i)
bg_sum$type = "background"
bg_sum
}) %>% bind_rows()
background_sum_all_cond = rbind(background_sum_all_cond, background_sum_all)
background_sum = background_sum_all %>%
dplyr::group_by(dist_bin) %>%
dplyr::summarize(n = mean(n),
share = mean(share),
sd = sd(share_full),
type = "background",
condition = ab_tp)
res = rbind.data.frame(sign_sum, background_sum)
res_full = rbind.data.frame(res_full, res)
}
res_full$dist_bin = factor(res_full$dist_bin, levels = rev(dist_labels))
res_full$tf_labels = ab_tp_labels[res_full$condition]
res_full$tf_labels = factor(res_full$tf_labels, levels = ab_tp_labels)
shares_in_motif = res_full %>%
arrange(tf_labels) %>%
filter(dist_bin == "in motif", type == "real") %>%
select(share) %>% unlist() %>% unique() %>% round(2)
res_full$dist_bin = factor(res_full$dist_bin, levels = dist_labels)
res_full$type = factor(res_full$type, levels = unique(res_full$type))
p = ggplot(res_full, aes(x = dist_bin, y = share, color = type, group = type)) +
facet_wrap(~tf_labels, ncol = 3) +
geom_ribbon(data=subset(res_full, type=="background"), aes(x=dist_bin, y = share, ymin = share - sd * 2, ymax = share + sd * 2, group = type), fill = "grey70", colour=NA, alpha = .4) +
geom_point(size = 2) +
geom_line(linewidth = 1) +
scale_color_manual(values = c("grey", "darkblue"), name = "", labels = c("AI peaks with motifs", "background")) +
theme_bw() +
ylab("Share of peaks") +
xlab("Distance from TF motif") +
theme(axis.text.y = element_text(size=14), axis.text.x = element_text(size=14, angle = 45, hjust = 1),
axis.title.x = element_text(size=16), axis.title.y = element_text(size=16),
legend.text=element_text(size=16), legend.title=element_text(size=16))
p

outf = file.path(outdir_fig_suppl, paste0("FigS4A_dist2motif_vs_background.pdf"))
ggsave(outf, p, width = 12, height = 6)
Empirical p-values for the test: real share is larger than background share
In motif
1-20 bp
21-40 bp
41-60 bp
61-80 bp
81-100 bp
>100 bp
Figure S4B - Fisher’s tests: enrichments of significant variants in motiifs in / outside peaks
out_df = data.frame(matrix(ncol = 10, nrow = 0))
names(out_df) = c("condition", "motif", "N_sign", "N_ns", "N_sign_motif", "N_ns_motif", "N_motif", "group", "odd_ratio", "pvalue")
i = 1
for(ab_tp in ab_tp_list) {
tf = TFs[ab_tp]
print(ab_tp)
cht_sel = cht %>% filter(condition == ab_tp)
# all signif variants - all, in and outside peaks
N1 = cht_sel %>% filter(signif_strongAI) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N1_a = cht_sel %>% filter(signif_strongAI & dist2summit < 250) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N1_b = cht_sel %>% filter(signif_strongAI & dist2summit >= 250) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
# all n.s. variants - in and outside peaks
N2 = cht_sel %>% filter(!signif_strongAI) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N2_a = cht_sel %>% filter(!signif_strongAI & dist2summit < 250) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N2_b = cht_sel %>% filter(!signif_strongAI & dist2summit >= 250) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
# variants in the motifs of selected TFs
fimo_selected = parse_motifs_in_two_alleles(ab_tp, cht_sel, radius = 15, path2_base1 = "/all_variants_alleles/FIMO/",
path2_base2 = "combined_motifs/fimo.tsv",
peak_radius = 250, subset_motif = F, subset_cht = T)
# 1. Enrichment in cognate motifs
print("1. Enrichment in cognate motifs")
#fimo_sel = fimo_selected %>% filter(motif_alt_id == tf & snp_id %in% cht_sel$snp_id)
fimo_sel = fimo_selected %>% filter(motif_alt_id == tf) # equivalent
cognate_motif_ids = unique(fimo_sel$snp_id)
# number of significant variants in motifs - all, in and outside peaks
N3 = fimo_sel %>% filter(signif_strongAI) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N3_a = fimo_sel %>% filter(signif_strongAI & in_peak) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N3_b = fimo_sel %>% filter(signif_strongAI & !in_peak) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
# number of n.s. variants in motifs - all, in and outside peaks
N4 = fimo_sel %>% filter(!signif_strongAI) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N4_a = fimo_sel %>% filter(!signif_strongAI & in_peak) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
N4_b = fimo_sel %>% filter(!signif_strongAI & !in_peak) %>% select(snp_id) %>% unique() %>% tally() %>% unlist()
# mat = matrix(c(N3, N4, N1, N2), nrow = 2)
# ft = fisher.test(mat)
# out_df[i, ] = c(ab_tp, tf, N1, N2, N3, N4, N3 + N4, "all variants", ft$estimate, ft$p.value)
# i = i + 1
# print("1a. All variants")
# print(ft)
mat = matrix(c(N3_a, N4_a, N1_a, N2_a), nrow = 2)
ft = fisher.test(mat)
out_df[i, ] = c(ab_tp, tf, N1_a, N2_a, N3_a, N4_a, N3_a + N4_a, "in peaks", ft$estimate, ft$p.value)
i = i + 1
print("1b. Variants in peaks")
print(ft)
mat = matrix(c(N3_b, N4_b, N1_b, N2_b), nrow = 2)
ft = fisher.test(mat)
out_df[i, ] = c(ab_tp, tf, N1_b, N2_b, N3_b, N4_b, N3_b + N4_b, "outside peaks", ft$estimate, ft$p.value)
i = i + 1
print("1c. Variants outside peaks")
print(ft)
}
[1] "twi/24"
[1] "1. Enrichment in cognate motifs"
[1] "1b. Variants in peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 2.4e-11
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
1.7026 2.5660
sample estimates:
odds ratio
2.0982
[1] "1c. Variants outside peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 0.0076
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
1.0463 1.3476
sample estimates:
odds ratio
1.1895
[1] "ctcf/68"
[1] "1. Enrichment in cognate motifs"
[1] "1b. Variants in peaks"
Fisher's Exact Test for Count Data
data: mat
p-value <2e-16
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
2.3256 3.3831
sample estimates:
odds ratio
2.8113
[1] "1c. Variants outside peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 0.92
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
0.87304 1.12213
sample estimates:
odds ratio
0.9914
[1] "mef2/68"
[1] "1. Enrichment in cognate motifs"
[1] "1b. Variants in peaks"
Fisher's Exact Test for Count Data
data: mat
p-value <2e-16
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
2.2275 3.3489
sample estimates:
odds ratio
2.7412
[1] "1c. Variants outside peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 0.78
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
0.86807 1.19931
sample estimates:
odds ratio
1.0234
[1] "mef2/1012"
[1] "1. Enrichment in cognate motifs"
[1] "1b. Variants in peaks"
Fisher's Exact Test for Count Data
data: mat
p-value <2e-16
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
2.2876 3.3341
sample estimates:
odds ratio
2.7702
[1] "1c. Variants outside peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 0.18
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
0.95347 1.25785
sample estimates:
odds ratio
1.0975
[1] "bin/68"
[1] "1. Enrichment in cognate motifs"
[1] "1b. Variants in peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 4.7e-12
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
2.1427 3.6830
sample estimates:
odds ratio
2.8278
[1] "1c. Variants outside peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 0.95
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
0.75705 1.24591
sample estimates:
odds ratio
0.97841
[1] "bin/1012"
[1] "1. Enrichment in cognate motifs"
[1] "1b. Variants in peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 2.1e-13
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
2.407 4.254
sample estimates:
odds ratio
3.2233
[1] "1c. Variants outside peaks"
Fisher's Exact Test for Count Data
data: mat
p-value = 0.044
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
0.99598 1.66680
sample estimates:
odds ratio
1.2986
out_df$label = rep(ab_tp_labels, each = 2)
out_df$label = factor(out_df$label, levels = ab_tp_labels)
out_df$pvalue = as.numeric(out_df$pvalue)
out_df$odd_ratio = as.numeric(out_df$odd_ratio)
p = ggplot(out_df, aes(x = label, y = odd_ratio)) +
facet_wrap(~group) +
geom_hline(yintercept = 1, color = "darkred") +
geom_bar(aes(fill = -log10(pvalue)), color = "darkblue", stat = "identity", position = "dodge", width = 0.5) +
#scale_fill_manual(name = "", values = c("darkblue", "darkgrey"), labels = c("AI peaks", "non-AI peaks")) +
#geom_text(aes(label = round(r1, 2), x = label, y = odds_ratio + 0.07), data = df, size = 6) +
ylab("Enrichment in cognate TF motifs \nFisher's Test Odds Ratio") +
theme_bw() +
theme(axis.text.x = element_text(size = 14, angle = 45, hjust = 1, colour = TFcols),
axis.text.y = element_text(size = 12),
axis.title.x = element_blank(),
axis.title.y = element_text(size = 16),
legend.text = element_text(size=14),
legend.title = element_text(size=14))
Warning: Vectorized input to `element_text()` is not officially supported.
ℹ Results may be unexpected or may change in future versions of ggplot2.

outf = file.path(outdir_fig_suppl, paste0("FigS4B_motifs_in_peaks_fisher.pdf"))
ggsave(outf, p, width = 10, height = 6)
Figure S4C - Motif prediction of AI
# Correlation between AI and delta_score
score_thres = 1
df_shared = fimo_alleles %>% filter(in_peak & !is.na(score.ref) & !is.na(score.alt)) %>%
mutate(delta_score = as.numeric(score.ref) - as.numeric(score.alt),
type = ifelse((AI > 0.5 & delta_score > 0) | (AI < 0.5 & delta_score < 0), "concordant", "discordant"))
df_shared %>%
group_by(condition, is_indel) %>%
summarize(min(abs(delta_score)), max(dist2summit), cor(delta_score, AI), share_concordant = sum(type == "concordant") / n(), n())
`summarise()` has grouped output by 'condition'. You can override using the
`.groups` argument.
df_sum = df_shared %>% filter(abs(delta_score) > score_thres & dist2summit < 250) %>%
summarize(min(abs(delta_score)), max(dist2summit), cor = cor(delta_score, AI), share_concordant = sum(type == "concordant") / n(), n())
cor = round(df_sum$cor, 2)
n_conc = round(df_sum$share_concordant, 2) * 100
n_disc = (1 - round(df_sum$share_concordant, 2)) * 100
p = ggplot(df_shared %>% filter(abs(delta_score) > score_thres ), aes(x = delta_score, y = AI, color = type)) +
geom_point(size = 1, color = cbPalette[2]) +
geom_smooth(method = "lm", se = F, color = "darkblue", size = 0.5) +
geom_vline(xintercept = -score_thres, color = "grey", size = 0.7) +
geom_vline(xintercept = score_thres, color = "grey", size = 0.7) +
geom_hline(yintercept = 0.5, color = "grey", size = 0.7) +
#geom_hline(yintercept = 0.4, color = "grey", size = 0.7) +
theme_bw() +
annotate(geom = "text", x = -3.5, y = 0.95, label = paste("R=", cor)) +
annotate(geom = "text", x = -3.5, y = 0.88, label = paste("% concordant: ", n_conc), size = 4) +
xlab("Motif score change (REF-ALT)") +
ylab("Allele Imbalamce") +
#scale_color_manual(values = c(cbPalette[2], "darkgrey"), labels = c(paste0("concordant, ", n_conc, "%"), paste0("discordant, ", n_disc, "%")), name = "Variant type") +
theme(axis.text=element_text(size=12),
axis.title=element_text(size=14),
legend.text = element_text(size=12),
legend.title = element_text(size=12))
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
generated.
`geom_smooth()` using formula = 'y ~ x'

outf = file.path(outdir_fig_suppl, paste0("FigS4C_motifs_AI_prediction.pdf"))
ggsave(outf, p, width = 4, height = 4)
`geom_smooth()` using formula = 'y ~ x'
LS0tCnRpdGxlOiAiRmlndXJlX1M0IgpvdXRwdXQ6CiAgIEJpb2NTdHlsZTo6aHRtbF9kb2N1bWVudDoKICAgICAgdG9jOiB0cnVlCiAgICAgIGRmX3ByaW50OiBwYWdlZAogICAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KI2JpYmxpb2dyYXBoeToga25uX21sX2ludHJvLmJpYgplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCmBgYHtyIHN0eWxlLCBlY2hvPUZBTFNFLCByZXN1bHRzPSJhc2lzIn0KbGlicmFyeSgia25pdHIiKQpvcHRpb25zKGRpZ2l0cyA9IDIsIHdpZHRoID0gODApCm9wdGlvbnMoYml0bWFwVHlwZSA9ICdjYWlybycpCmdvbGRlbl9yYXRpbyA8LSAoMSArIHNxcnQoNSkpIC8gMgpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgdGlkeSA9IEZBTFNFLCBpbmNsdWRlID0gVFJVRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgZGV2PWMoJ3BuZycsICdwZGYnKSwgY29tbWVudCA9ICcgICcsIGRwaSA9IDMwMCkKCm9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGU9RkFMU0UpCm9wdGlvbnMoZGlnaXRzID0gNSkgICAgICAgICAKYGBgCgojIFNldHVwIGFuZCBkYXRhCgpgYGB7cn0Kc291cmNlKCIuLi91dGlscy91dGlscy5SIikKY29uZmlnID0gbG9hZF9jb25maWcoKQoKIyBsb2FkIENIVCByZXN1bHRzCmNodF9mdWxsID0gbGFwcGx5KGFiX3RwX2xpc3QsIGZ1bmN0aW9uKGFiX3RwKSBsb2FkX2NodF9yZXN1bHRzKGFiX3RwLCByZW1vdmVfY2hyID0gRikpICU+JSBiaW5kX3Jvd3MoKQpjaHQgPSBjaHRfZnVsbCAlPiUgZmlsdGVyKCFURVNULlNOUC5DSFJPTSAlaW4lIGMoImNoclgiLCAiY2hyWSIsICJjaHJNIikpCmNodF9zaWduID0gY2h0ICU+JSBmaWx0ZXIoc2lnbmlmX3N0cm9uZ0FJKSAKCiMgZ2VuZXMgYW5kIHByb21vdGVycwpnZW5lcyA9IGxvYWRfZ2VuZXMoKQpwcm9tb3RlcnMgPSByZXNpemUoZ2VuZXMsIHdpZHRoID0gMTAwMCwgZml4ID0gInN0YXJ0IikKCiMgY29tYmluZWQgbW90aWYgc2V0IChhbGwgVEZzLCBwZWFrcyArIGFsbGVsZXMpCmZpbW8gPSBnZXRfZnVsbF9tb3RpZl9zZXRzKGNodCwgYWJfdHBfbGlzdCkKIyBvbmx5IGFsbGVsZXMKZmltb19hbGxlbGVzICA9IGxhcHBseShhYl90cF9saXN0LCBmdW5jdGlvbihhYl90cCkgcGFyc2VfbW90aWZzX2luX3R3b19hbGxlbGVzKGFiX3RwLCBjaHQpKSAlPiUgYmluZF9yb3dzKCkgCgpgYGAKCgoKIyBGaWd1cmUgUzRBCgpgYGB7ciwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9M30KCiMgZ2V0IHZhcmlhbnRzIGRpc3RhbmNlIHRvIG1vdGlmcyAoZXhjbHVkaW5nIHBlYWtzIHdpdGhvdXQgbW90aWZzKQpyZXNfZGYgPSBsYXBwbHkoYWJfdHBfbGlzdCwgZnVuY3Rpb24oYWJfdHApIGdldF92YXJpYW50X2Rpc3RhbmNlMlRGbW90aWYoYWJfdHAsIGNodCwgZmltbywgc2FtZV9wZWFrID0gVCkgJT4lIAogICAgICAgICAgICAgICAgICBtdXRhdGUoY29uZGl0aW9uID0gYWJfdHApKSAlPiUgYmluZF9yb3dzKCkKCmRpc3RfYnJlYWtzID0gYygtMSwgMCwgMjAsIDQwLCA2MCwgODAsIDEwMCwgMzAwMCkKZGlzdF9sYWJlbHMgPSBjKCJpbiBtb3RpZiIsICIxLTIwIGJwIiwgIjIxLTQwIGJwIiwgIjQxLTYwIGJwIiwgIjYxLTgwIGJwIiwgIjgxLTEwMCBicCIsICI+MTAwIGJwIikKCnJlc19mdWxsID0gZGF0YS5mcmFtZShtYXRyaXgobmNvbCA9IDYsIG5yb3cgPSAwKSkKbmFtZXMocmVzX2Z1bGwpID0gYygiZGlzdF9iaW4iLCAibiIsICJzaGFyZSIsICJzZCIsICJ0eXBlIiwgImNvbmRpdGlvbiIpCmJhY2tncm91bmRfc3VtX2FsbF9jb25kID0gZGF0YS5mcmFtZShtYXRyaXgobmNvbCA9IDcsIG5yb3cgPSAwKSkKbmFtZXMoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQpID0gYygiZGlzdF9iaW4iLCAibiIsICJzaGFyZSIsICJzaGFyZV9mdWxsIiwgICJ0eXBlIiwgImNvbmRpdGlvbiIsICJpIikKCmZvcihhYl90cCBpbiBhYl90cF9saXN0KSB7CiAgCiAgIyBhbGwgdmFyaWFudHMKICBkZl9zZWwgPSByZXNfZGYgJT4lIGRwbHlyOjpmaWx0ZXIoY29uZGl0aW9uID09IGFiX3RwKQogIE5fdmFyID0gbGVuZ3RoKHVuaXF1ZShkZl9zZWwkc25wX2lkKSkgIyBudW1iZXIgb2YgdmFyaWFudHMgaW4gcGVha3Mgd2l0aCBtb3RpZnMKICBOX3BlYWsgPSBsZW5ndGgodW5pcXVlKGRmX3NlbCRwZWFrX2lkKSkgIyBudW1iZXIgb2YgcGVha3Mgd2l0aCBtb3RpZnMKICAKICAjIHNpZ25pZmljYW50IHZhcmlhbnRzCiAgZGZfc2lnbiA9IGRmX3NlbCAlPiUgZmlsdGVyKHNpZ25pZl9zdHJvbmdBSSkKICBOX3Zhcl9zaWduID0gbGVuZ3RoKHVuaXF1ZShkZl9zaWduJHNucF9pZCkpICMgbnVtYmVyIG9mIHNpZ25pZmljYW50IHZhcmlhbnRzIGluIHBlYWtzIHdpdGggbW90aWZzCiAgTl9wZWFrX3NpZ24gPSBsZW5ndGgodW5pcXVlKGRmX3NpZ24kcGVha19pZCkpICMgbnVtYmVyIG9mIEFJIHBlYWtzIHdpdGggbW90aWZzCgogIHNpZ25fc3VtID0gZGZfc2lnbiAlPiUgCiAgICBkcGx5cjo6Z3JvdXBfYnkocGVha19pZCkgJT4lIAogICAgZHBseXI6Om11dGF0ZShtaW5fZGlzdCA9IG1pbihkaXN0Mm1vdGlmKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKGRpc3QybW90aWYgPT0gbWluX2Rpc3QpICU+JQogICAgZHBseXI6OnNlbGVjdChwZWFrX2lkLCBkaXN0Mm1vdGlmKSAlPiUgdW5pcXVlKCkgJT4lIHVuZ3JvdXAoKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoTl90b3QgPSBuKCksIGRpc3RfYmluID0gY3V0KGRpc3QybW90aWYsIGJyZWFrcyA9IGRpc3RfYnJlYWtzLCBsYWJlbHMgPSBkaXN0X2xhYmVscykpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KGRpc3RfYmluKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobiA9IG4oKSwgc2hhcmUgPSBuIC8gbWVhbihOX3RvdCksIHNkID0gc2QobiksIHR5cGUgPSAicmVhbCIsIGNvbmRpdGlvbiA9IGFiX3RwKQogIAogIAogIGRmX25vbl9zaWduID0gZGZfc2VsICU+JSBkcGx5cjo6Z3JvdXBfYnkocGVha19pZCkgJT4lIGRwbHlyOjptdXRhdGUoQUlfcGVhayA9IGFueShzaWduaWZfc3Ryb25nQUkpKSAlPiUgZHBseXI6OmZpbHRlcighQUlfcGVhaykgJT4lIHVuZ3JvdXAoKQogIAogIGJhY2tncm91bmRfc3VtX2FsbCA9IGxhcHBseSgxOjEwMDAwLCBmdW5jdGlvbihpKSB7CiAgICAKICAgICNwcmludChpKQogICAgCiAgICAjIDEuIHNlbGVjdCBzYW1lIG51bWJlciBvZiBwZWFrcyBhcyBpbiBBSSBwZWFrcwogICAgcGVha19pZHMgPSBzYW1wbGUodW5pcXVlKGRmX25vbl9zaWduJHBlYWtfaWQpLCBOX3BlYWtfc2lnbikKICAgIGRmX2JnID0gZGZfbm9uX3NpZ24gJT4lIGRwbHlyOjpmaWx0ZXIocGVha19pZCAlaW4lIHBlYWtfaWRzKQogICAgCiAgICAjIDIuIHNlbGVjdCBzYW1lIG51bWJlciBvZiB2YXJpYW50cyBhcyBmb3IgQUkgcGVha3MKICAgIHZhcmlhbnRfaWRzID0gc2FtcGxlKHVuaXF1ZShkZl9iZyRzbnBfaWQpLCBOX3Zhcl9zaWduKQogICAgZGZfYmcgJTw+JSBmaWx0ZXIoc25wX2lkICVpbiUgdmFyaWFudF9pZHMpCiAgICAKICAgIE5fcGVha19iZyA9IGxlbmd0aCh1bmlxdWUoZGZfYmckcGVha19pZCkpIAogICAgCiAgICBiZ19zdW0gPSBkZl9iZyAlPiUgCiAgICAgIGRwbHlyOjpncm91cF9ieShwZWFrX2lkKSAlPiUgCiAgICAgIGRwbHlyOjptdXRhdGUobWluX2Rpc3QgPSBtaW4oZGlzdDJtb3RpZikpICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKGRpc3QybW90aWYgPT0gbWluX2Rpc3QpICU+JQogICAgICBkcGx5cjo6c2VsZWN0KHBlYWtfaWQsIGRpc3QybW90aWYpICU+JSB1bmlxdWUoKSAlPiUgdW5ncm91cCgpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKE5fdG90ID0gbigpLCBkaXN0X2JpbiA9IGN1dChkaXN0Mm1vdGlmLCBicmVha3MgPSBkaXN0X2JyZWFrcywgbGFiZWxzID0gZGlzdF9sYWJlbHMpKSAlPiUKICAgICAgZHBseXI6Omdyb3VwX2J5KGRpc3RfYmluKSAlPiUKICAgICAgZHBseXI6OnN1bW1hcml6ZShuID0gbigpLCBzaGFyZSA9IG4gLyBtZWFuKE5fdG90KSwgc2hhcmVfZnVsbCA9IG4gLyBOX3BlYWtfYmcpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKGNvbmRpdGlvbiA9IGFiX3RwLCBpID0gaSkKICAgIAogICAgCiAgICBiZ19zdW0kdHlwZSA9ICJiYWNrZ3JvdW5kIgogICAgYmdfc3VtCiAgICAKICB9KSAlPiUgYmluZF9yb3dzKCkKICAKICBiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCA9IHJiaW5kKGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBiYWNrZ3JvdW5kX3N1bV9hbGwpCiAgCiAgYmFja2dyb3VuZF9zdW0gPSBiYWNrZ3JvdW5kX3N1bV9hbGwgJT4lIAogICAgZHBseXI6Omdyb3VwX2J5KGRpc3RfYmluKSAlPiUgCiAgICBkcGx5cjo6c3VtbWFyaXplKG4gPSBtZWFuKG4pLCAKICAgICAgICAgICAgICAgICAgICAgc2hhcmUgPSBtZWFuKHNoYXJlKSwgCiAgICAgICAgICAgICAgICAgICAgIHNkID0gc2Qoc2hhcmVfZnVsbCksCiAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAiYmFja2dyb3VuZCIsIAogICAgICAgICAgICAgICAgICAgICBjb25kaXRpb24gPSBhYl90cCkKICAKICAKICByZXMgPSByYmluZC5kYXRhLmZyYW1lKHNpZ25fc3VtLCBiYWNrZ3JvdW5kX3N1bSkKICAKICByZXNfZnVsbCA9IHJiaW5kLmRhdGEuZnJhbWUocmVzX2Z1bGwsIHJlcykKCn0KCgpyZXNfZnVsbCRkaXN0X2JpbiA9IGZhY3RvcihyZXNfZnVsbCRkaXN0X2JpbiwgbGV2ZWxzID0gcmV2KGRpc3RfbGFiZWxzKSkKcmVzX2Z1bGwkdGZfbGFiZWxzID0gYWJfdHBfbGFiZWxzW3Jlc19mdWxsJGNvbmRpdGlvbl0gIApyZXNfZnVsbCR0Zl9sYWJlbHMgPSBmYWN0b3IocmVzX2Z1bGwkdGZfbGFiZWxzLCBsZXZlbHMgPSBhYl90cF9sYWJlbHMpCgpzaGFyZXNfaW5fbW90aWYgPSByZXNfZnVsbCAlPiUgCiAgYXJyYW5nZSh0Zl9sYWJlbHMpICU+JSAKICBmaWx0ZXIoZGlzdF9iaW4gPT0gImluIG1vdGlmIiwgdHlwZSA9PSAicmVhbCIpICU+JSAKICBzZWxlY3Qoc2hhcmUpICU+JSB1bmxpc3QoKSAlPiUgdW5pcXVlKCkgJT4lIHJvdW5kKDIpCgoKcmVzX2Z1bGwkZGlzdF9iaW4gPSBmYWN0b3IocmVzX2Z1bGwkZGlzdF9iaW4sIGxldmVscyA9IGRpc3RfbGFiZWxzKQpyZXNfZnVsbCR0eXBlID0gZmFjdG9yKHJlc19mdWxsJHR5cGUsIGxldmVscyA9IHVuaXF1ZShyZXNfZnVsbCR0eXBlKSkKCnAgPSBnZ3Bsb3QocmVzX2Z1bGwsIGFlcyh4ID0gZGlzdF9iaW4sIHkgPSBzaGFyZSwgY29sb3IgPSB0eXBlLCBncm91cCA9IHR5cGUpKSArCiAgZmFjZXRfd3JhcCh+dGZfbGFiZWxzLCBuY29sID0gMykgKwogIGdlb21fcmliYm9uKGRhdGE9c3Vic2V0KHJlc19mdWxsLCB0eXBlPT0iYmFja2dyb3VuZCIpLCBhZXMoeD1kaXN0X2JpbiwgeSA9IHNoYXJlLCB5bWluID0gc2hhcmUgLSBzZCAqIDIsIHltYXggPSBzaGFyZSArIHNkICogMiwgZ3JvdXAgPSB0eXBlKSwgZmlsbCA9ICJncmV5NzAiLCBjb2xvdXI9TkEsIGFscGhhID0gLjQpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImdyZXkiLCAiZGFya2JsdWUiKSwgbmFtZSA9ICIiLCBsYWJlbHMgPSBjKCJBSSBwZWFrcyB3aXRoIG1vdGlmcyIsICJiYWNrZ3JvdW5kIikpICsKICB0aGVtZV9idygpICsKICB5bGFiKCJTaGFyZSBvZiBwZWFrcyIpICsKICB4bGFiKCJEaXN0YW5jZSBmcm9tIFRGIG1vdGlmIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLAogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE2KSwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSkKCgpwCm91dGYgPSBmaWxlLnBhdGgob3V0ZGlyX2ZpZ19zdXBwbCwgcGFzdGUwKCJGaWdTNEFfZGlzdDJtb3RpZl92c19iYWNrZ3JvdW5kLnBkZiIpKQpnZ3NhdmUob3V0ZiwgcCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNikKCmBgYAoKKipFbXBpcmljYWwgcC12YWx1ZXMgZm9yIHRoZSB0ZXN0OiByZWFsIHNoYXJlIGlzIGxhcmdlciB0aGFuIGJhY2tncm91bmQgc2hhcmUqKgoKPGJyPgoKKipJbiBtb3RpZioqCgp8IENvbmRpdGlvbiB8IHAtdmFsdWUgfAp8IDotLS0tLS0tLS0tLSB8IDotLS0tLS0tLS0tLTogfAp8IFR3aSAyLTRoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iaW4gbW90aWYiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJ0d2kvMjQiICYgZGlzdF9iaW49PSJpbiBtb3RpZiIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iaW4gbW90aWYiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUpICsgMSlgIHwKfCBDVENGIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSJpbiBtb3RpZiIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJjdGNmLzY4IiAmIGRpc3RfYmluPT0iaW4gbW90aWYiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09ImluIG1vdGlmIiAmIGNvbmRpdGlvbj09ImN0Y2YvNjgiKSRzaGFyZSkgKyAxKWAgfAp8IE1lZjIgNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09ImluIG1vdGlmIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiICYgZGlzdF9iaW49PSJpbiBtb3RpZiIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iaW4gbW90aWYiICYgY29uZGl0aW9uPT0ibWVmMi82OCIpJHNoYXJlKSArIDEpYCB8CnwgTWVmMiAxMC0xMmggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSJpbiBtb3RpZiIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvMTAxMiIgJiBkaXN0X2Jpbj09ImluIG1vdGlmIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSJpbiBtb3RpZiIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSkgKyAxKWAgfAp8IEJpbiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iaW4gbW90aWYiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJiaW4vNjgiICYgZGlzdF9iaW49PSJpbiBtb3RpZiIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iaW4gbW90aWYiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBCaW4gMTAtMTJoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iaW4gbW90aWYiICYgY29uZGl0aW9uPT0iYmluLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIiAmIGRpc3RfYmluPT0iaW4gbW90aWYiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09ImluIG1vdGlmIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIikkc2hhcmUpICsgMSlgIHwKCgo8YnI+CgoqKjEtMjAgYnAqKgoKfCBDb25kaXRpb24gfCBwLXZhbHVlIHwKfCA6LS0tLS0tLS0tLS0gfCA6LS0tLS0tLS0tLS06IHwKfCBUd2kgMi00aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjEtMjAgYnAiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJ0d2kvMjQiICYgZGlzdF9iaW49PSIxLTIwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIxLTIwIGJwIiAmIGNvbmRpdGlvbj09InR3aS8yNCIpJHNoYXJlKSArIDEpYCB8CnwgQ1RDRiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMS0yMCBicCIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJjdGNmLzY4IiAmIGRpc3RfYmluPT0iMS0yMCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMS0yMCBicCIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBNZWYyIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIxLTIwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiICYgZGlzdF9iaW49PSIxLTIwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIxLTIwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSkgKyAxKWAgfAp8IE1lZjIgMTAtMTJoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMS0yMCBicCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvMTAxMiIgJiBkaXN0X2Jpbj09IjEtMjAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjEtMjAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi8xMDEyIikkc2hhcmUpICsgMSlgIHwKfCBCaW4gNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjEtMjAgYnAiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJiaW4vNjgiICYgZGlzdF9iaW49PSIxLTIwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIxLTIwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi82OCIpJHNoYXJlKSArIDEpYCB8CnwgQmluIDEwLTEyaCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjEtMjAgYnAiICYgY29uZGl0aW9uPT0iYmluLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIiAmIGRpc3RfYmluPT0iMS0yMCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMS0yMCBicCIgJiBjb25kaXRpb249PSJiaW4vMTAxMiIpJHNoYXJlKSArIDEpYCB8Cgo8YnI+CgoqKjIxLTQwIGJwKioKCnwgQ29uZGl0aW9uIHwgcC12YWx1ZSB8CnwgOi0tLS0tLS0tLS0tIHwgOi0tLS0tLS0tLS0tOiB8CnwgVHdpIDItNGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIyMS00MCBicCIgJiBjb25kaXRpb249PSJ0d2kvMjQiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09InR3aS8yNCIgJiBkaXN0X2Jpbj09IjIxLTQwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIyMS00MCBicCIgJiBjb25kaXRpb249PSJ0d2kvMjQiKSRzaGFyZSkgKyAxKWAgfAp8IENUQ0YgNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjIxLTQwIGJwIiAmIGNvbmRpdGlvbj09ImN0Y2YvNjgiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09ImN0Y2YvNjgiICYgZGlzdF9iaW49PSIyMS00MCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMjEtNDAgYnAiICYgY29uZGl0aW9uPT0iY3RjZi82OCIpJHNoYXJlKSArIDEpYCB8CnwgTWVmMiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMjEtNDAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi82OCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0ibWVmMi82OCIgJiBkaXN0X2Jpbj09IjIxLTQwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIyMS00MCBicCIgJiBjb25kaXRpb249PSJtZWYyLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBNZWYyIDEwLTEyaCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjIxLTQwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvMTAxMiIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0ibWVmMi8xMDEyIiAmIGRpc3RfYmluPT0iMjEtNDAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjIxLTQwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvMTAxMiIpJHNoYXJlKSArIDEpYCB8CnwgQmluIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIyMS00MCBicCIgJiBjb25kaXRpb249PSJiaW4vNjgiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09ImJpbi82OCIgJiBkaXN0X2Jpbj09IjIxLTQwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIyMS00MCBicCIgJiBjb25kaXRpb249PSJiaW4vNjgiKSRzaGFyZSkgKyAxKWAgfAp8IEJpbiAxMC0xMmggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSIyMS00MCBicCIgJiBjb25kaXRpb249PSJiaW4vMTAxMiIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0iYmluLzEwMTIiICYgZGlzdF9iaW49PSIyMS00MCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iMjEtNDAgYnAiICYgY29uZGl0aW9uPT0iYmluLzEwMTIiKSRzaGFyZSkgKyAxKWAgfAoKCjxicj4KCioqNDEtNjAgYnAqKgoKfCBDb25kaXRpb24gfCBwLXZhbHVlIHwKfCA6LS0tLS0tLS0tLS0gfCA6LS0tLS0tLS0tLS06IHwKfCBUd2kgMi00aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjQxLTYwIGJwIiAmIGNvbmRpdGlvbj09InR3aS8yNCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0idHdpLzI0IiAmIGRpc3RfYmluPT0iNDEtNjAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjQxLTYwIGJwIiAmIGNvbmRpdGlvbj09InR3aS8yNCIpJHNoYXJlKSArIDEpYCB8CnwgQ1RDRiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNDEtNjAgYnAiICYgY29uZGl0aW9uPT0iY3RjZi82OCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0iY3RjZi82OCIgJiBkaXN0X2Jpbj09IjQxLTYwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI0MS02MCBicCIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBNZWYyIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI0MS02MCBicCIgJiBjb25kaXRpb249PSJtZWYyLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJtZWYyLzY4IiAmIGRpc3RfYmluPT0iNDEtNjAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjQxLTYwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSkgKyAxKWAgfAp8IE1lZjIgMTAtMTJoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNDEtNjAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi8xMDEyIikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiICYgZGlzdF9iaW49PSI0MS02MCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNDEtNjAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi8xMDEyIikkc2hhcmUpICsgMSlgIHwKfCBCaW4gNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjQxLTYwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi82OCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0iYmluLzY4IiAmIGRpc3RfYmluPT0iNDEtNjAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjQxLTYwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi82OCIpJHNoYXJlKSArIDEpYCB8CnwgQmluIDEwLTEyaCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjQxLTYwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJiaW4vMTAxMiIgJiBkaXN0X2Jpbj09IjQxLTYwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI0MS02MCBicCIgJiBjb25kaXRpb249PSJiaW4vMTAxMiIpJHNoYXJlKSArIDEpYCB8CgoKPGJyPgoKKio2MS04MCBicCoqCgp8IENvbmRpdGlvbiB8IHAtdmFsdWUgfAp8IDotLS0tLS0tLS0tLSB8IDotLS0tLS0tLS0tLTogfAp8IFR3aSAyLTRoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNjEtODAgYnAiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJ0d2kvMjQiICYgZGlzdF9iaW49PSI2MS04MCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNjEtODAgYnAiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUpICsgMSlgIHwKfCBDVENGIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI2MS04MCBicCIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJjdGNmLzY4IiAmIGRpc3RfYmluPT0iNjEtODAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjYxLTgwIGJwIiAmIGNvbmRpdGlvbj09ImN0Y2YvNjgiKSRzaGFyZSkgKyAxKWAgfAp8IE1lZjIgNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjYxLTgwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiICYgZGlzdF9iaW49PSI2MS04MCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNjEtODAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi82OCIpJHNoYXJlKSArIDEpYCB8CnwgTWVmMiAxMC0xMmggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI2MS04MCBicCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvMTAxMiIgJiBkaXN0X2Jpbj09IjYxLTgwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI2MS04MCBicCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSkgKyAxKWAgfAp8IEJpbiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNjEtODAgYnAiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJiaW4vNjgiICYgZGlzdF9iaW49PSI2MS04MCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNjEtODAgYnAiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBCaW4gMTAtMTJoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iNjEtODAgYnAiICYgY29uZGl0aW9uPT0iYmluLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIiAmIGRpc3RfYmluPT0iNjEtODAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjYxLTgwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIikkc2hhcmUpICsgMSlgIHwKCgo8YnI+CgoqKjgxLTEwMCBicCoqCgp8IENvbmRpdGlvbiB8IHAtdmFsdWUgfAp8IDotLS0tLS0tLS0tLSB8IDotLS0tLS0tLS0tLTogfAp8IFR3aSAyLTRoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iODEtMTAwIGJwIiAmIGNvbmRpdGlvbj09InR3aS8yNCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0idHdpLzI0IiAmIGRpc3RfYmluPT0iODEtMTAwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI4MS0xMDAgYnAiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUpICsgMSlgIHwKfCBDVENGIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI4MS0xMDAgYnAiICYgY29uZGl0aW9uPT0iY3RjZi82OCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0iY3RjZi82OCIgJiBkaXN0X2Jpbj09IjgxLTEwMCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iODEtMTAwIGJwIiAmIGNvbmRpdGlvbj09ImN0Y2YvNjgiKSRzaGFyZSkgKyAxKWAgfAp8IE1lZjIgNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjgxLTEwMCBicCIgJiBjb25kaXRpb249PSJtZWYyLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJtZWYyLzY4IiAmIGRpc3RfYmluPT0iODEtMTAwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI4MS0xMDAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi82OCIpJHNoYXJlKSArIDEpYCB8CnwgTWVmMiAxMC0xMmggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI4MS0xMDAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi8xMDEyIikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiICYgZGlzdF9iaW49PSI4MS0xMDAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09IjgxLTEwMCBicCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSkgKyAxKWAgfAp8IEJpbiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iODEtMTAwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi82OCIpJHNoYXJlID49IHN1YnNldChyZXNfZnVsbCwgdHlwZT09InJlYWwiICYgY29uZGl0aW9uPT0iYmluLzY4IiAmIGRpc3RfYmluPT0iODEtMTAwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI4MS0xMDAgYnAiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBCaW4gMTAtMTJoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iODEtMTAwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJiaW4vMTAxMiIgJiBkaXN0X2Jpbj09IjgxLTEwMCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iODEtMTAwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIikkc2hhcmUpICsgMSlgIHwKCgo8YnI+CgoqKj4xMDAgYnAqKgoKfCBDb25kaXRpb24gfCBwLXZhbHVlIHwKfCA6LS0tLS0tLS0tLS0gfCA6LS0tLS0tLS0tLS06IHwKfCBUd2kgMi00aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09Ij4xMDAgYnAiICYgY29uZGl0aW9uPT0idHdpLzI0Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJ0d2kvMjQiICYgZGlzdF9iaW49PSI+MTAwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI+MTAwIGJwIiAmIGNvbmRpdGlvbj09InR3aS8yNCIpJHNoYXJlKSArIDEpYCB8CnwgQ1RDRiA2LThoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iPjEwMCBicCIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJjdGNmLzY4IiAmIGRpc3RfYmluPT0iPjEwMCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iPjEwMCBicCIgJiBjb25kaXRpb249PSJjdGNmLzY4Iikkc2hhcmUpICsgMSlgIHwKfCBNZWYyIDYtOGggfCBgciAoc3VtKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI+MTAwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiICYgZGlzdF9iaW49PSI+MTAwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI+MTAwIGJwIiAmIGNvbmRpdGlvbj09Im1lZjIvNjgiKSRzaGFyZSkgKyAxKWAgfAp8IE1lZjIgMTAtMTJoIHwgYHIgKHN1bShzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iPjEwMCBicCIgJiBjb25kaXRpb249PSJtZWYyLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09Im1lZjIvMTAxMiIgJiBkaXN0X2Jpbj09Ij4xMDAgYnAiKSRzaGFyZSkgKyAxKSAvIChsZW5ndGgoc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09Ij4xMDAgYnAiICYgY29uZGl0aW9uPT0ibWVmMi8xMDEyIikkc2hhcmUpICsgMSlgIHwKfCBCaW4gNi04aCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09Ij4xMDAgYnAiICYgY29uZGl0aW9uPT0iYmluLzY4Iikkc2hhcmUgPj0gc3Vic2V0KHJlc19mdWxsLCB0eXBlPT0icmVhbCIgJiBjb25kaXRpb249PSJiaW4vNjgiICYgZGlzdF9iaW49PSI+MTAwIGJwIikkc2hhcmUpICsgMSkgLyAobGVuZ3RoKHN1YnNldChiYWNrZ3JvdW5kX3N1bV9hbGxfY29uZCwgZGlzdF9iaW49PSI+MTAwIGJwIiAmIGNvbmRpdGlvbj09ImJpbi82OCIpJHNoYXJlKSArIDEpYCB8CnwgQmluIDEwLTEyaCB8IGByIChzdW0oc3Vic2V0KGJhY2tncm91bmRfc3VtX2FsbF9jb25kLCBkaXN0X2Jpbj09Ij4xMDAgYnAiICYgY29uZGl0aW9uPT0iYmluLzEwMTIiKSRzaGFyZSA+PSBzdWJzZXQocmVzX2Z1bGwsIHR5cGU9PSJyZWFsIiAmIGNvbmRpdGlvbj09ImJpbi8xMDEyIiAmIGRpc3RfYmluPT0iPjEwMCBicCIpJHNoYXJlKSArIDEpIC8gKGxlbmd0aChzdWJzZXQoYmFja2dyb3VuZF9zdW1fYWxsX2NvbmQsIGRpc3RfYmluPT0iPjEwMCBicCIgJiBjb25kaXRpb249PSJiaW4vMTAxMiIpJHNoYXJlKSArIDEpYCB8CgoKCgojIEZpZ3VyZSBTNEIgLSBGaXNoZXIncyB0ZXN0czogZW5yaWNobWVudHMgb2Ygc2lnbmlmaWNhbnQgdmFyaWFudHMgaW4gbW90aWlmcyBpbiAvIG91dHNpZGUgcGVha3MKCmBgYHtyfQpvdXRfZGYgPSBkYXRhLmZyYW1lKG1hdHJpeChuY29sID0gMTAsIG5yb3cgPSAwKSkKbmFtZXMob3V0X2RmKSA9IGMoImNvbmRpdGlvbiIsICJtb3RpZiIsICJOX3NpZ24iLCAiTl9ucyIsICJOX3NpZ25fbW90aWYiLCAiTl9uc19tb3RpZiIsICJOX21vdGlmIiwgImdyb3VwIiwgIm9kZF9yYXRpbyIsICJwdmFsdWUiKQppID0gMQoKZm9yKGFiX3RwIGluIGFiX3RwX2xpc3QpIHsKICAKICB0ZiA9IFRGc1thYl90cF0KICBwcmludChhYl90cCkKICBjaHRfc2VsID0gY2h0ICU+JSBmaWx0ZXIoY29uZGl0aW9uID09IGFiX3RwKQogIAogICMgYWxsIHNpZ25pZiB2YXJpYW50cyAtIGFsbCwgaW4gYW5kIG91dHNpZGUgcGVha3MKICBOMSA9IGNodF9zZWwgJT4lIGZpbHRlcihzaWduaWZfc3Ryb25nQUkpICU+JSBzZWxlY3Qoc25wX2lkKSAlPiUgdW5pcXVlKCkgJT4lIHRhbGx5KCkgJT4lIHVubGlzdCgpCiAgTjFfYSA9IGNodF9zZWwgJT4lIGZpbHRlcihzaWduaWZfc3Ryb25nQUkgJiBkaXN0MnN1bW1pdCA8IDI1MCkgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICBOMV9iID0gY2h0X3NlbCAlPiUgZmlsdGVyKHNpZ25pZl9zdHJvbmdBSSAmIGRpc3Qyc3VtbWl0ID49IDI1MCkgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICAKICAjIGFsbCBuLnMuIHZhcmlhbnRzIC0gaW4gYW5kIG91dHNpZGUgcGVha3MKICBOMiA9IGNodF9zZWwgJT4lIGZpbHRlcighc2lnbmlmX3N0cm9uZ0FJKSAlPiUgc2VsZWN0KHNucF9pZCkgJT4lIHVuaXF1ZSgpICU+JSB0YWxseSgpICU+JSB1bmxpc3QoKQogIE4yX2EgPSBjaHRfc2VsICU+JSBmaWx0ZXIoIXNpZ25pZl9zdHJvbmdBSSAmIGRpc3Qyc3VtbWl0IDwgMjUwKSAlPiUgc2VsZWN0KHNucF9pZCkgJT4lIHVuaXF1ZSgpICU+JSB0YWxseSgpICU+JSB1bmxpc3QoKQogIE4yX2IgPSBjaHRfc2VsICU+JSBmaWx0ZXIoIXNpZ25pZl9zdHJvbmdBSSAmIGRpc3Qyc3VtbWl0ID49IDI1MCkgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICAKICAKICAjIHZhcmlhbnRzIGluIHRoZSBtb3RpZnMgb2Ygc2VsZWN0ZWQgVEZzCiAgZmltb19zZWxlY3RlZCA9IHBhcnNlX21vdGlmc19pbl90d29fYWxsZWxlcyhhYl90cCwgY2h0X3NlbCwgcmFkaXVzID0gMTUsIHBhdGgyX2Jhc2UxID0gIi9hbGxfdmFyaWFudHNfYWxsZWxlcy9GSU1PLyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoMl9iYXNlMiA9ICJjb21iaW5lZF9tb3RpZnMvZmltby50c3YiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlYWtfcmFkaXVzID0gMjUwLCBzdWJzZXRfbW90aWYgPSBGLCBzdWJzZXRfY2h0ID0gVCkgCiAgCiAgCiAgIyAxLiBFbnJpY2htZW50IGluIGNvZ25hdGUgbW90aWZzCiAgcHJpbnQoIjEuIEVucmljaG1lbnQgaW4gY29nbmF0ZSBtb3RpZnMiKQogICNmaW1vX3NlbCA9IGZpbW9fc2VsZWN0ZWQgJT4lIGZpbHRlcihtb3RpZl9hbHRfaWQgPT0gdGYgJiBzbnBfaWQgJWluJSBjaHRfc2VsJHNucF9pZCkKICBmaW1vX3NlbCA9IGZpbW9fc2VsZWN0ZWQgJT4lIGZpbHRlcihtb3RpZl9hbHRfaWQgPT0gdGYpICAjIGVxdWl2YWxlbnQKICBjb2duYXRlX21vdGlmX2lkcyA9IHVuaXF1ZShmaW1vX3NlbCRzbnBfaWQpCiAgCiAgIyBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgdmFyaWFudHMgaW4gbW90aWZzIC0gYWxsLCBpbiBhbmQgb3V0c2lkZSBwZWFrcwogIE4zID0gZmltb19zZWwgJT4lIGZpbHRlcihzaWduaWZfc3Ryb25nQUkpICU+JSBzZWxlY3Qoc25wX2lkKSAlPiUgdW5pcXVlKCkgJT4lIHRhbGx5KCkgJT4lIHVubGlzdCgpCiAgTjNfYSA9IGZpbW9fc2VsICU+JSBmaWx0ZXIoc2lnbmlmX3N0cm9uZ0FJICYgaW5fcGVhaykgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICBOM19iID0gZmltb19zZWwgJT4lIGZpbHRlcihzaWduaWZfc3Ryb25nQUkgJiAhaW5fcGVhaykgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICAKICAjIG51bWJlciBvZiBuLnMuIHZhcmlhbnRzIGluIG1vdGlmcyAtIGFsbCwgaW4gYW5kIG91dHNpZGUgcGVha3MKICBONCA9IGZpbW9fc2VsICU+JSBmaWx0ZXIoIXNpZ25pZl9zdHJvbmdBSSkgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICBONF9hID0gZmltb19zZWwgJT4lIGZpbHRlcighc2lnbmlmX3N0cm9uZ0FJICYgaW5fcGVhaykgJT4lIHNlbGVjdChzbnBfaWQpICU+JSB1bmlxdWUoKSAlPiUgdGFsbHkoKSAlPiUgdW5saXN0KCkKICBONF9iID0gZmltb19zZWwgJT4lIGZpbHRlcighc2lnbmlmX3N0cm9uZ0FJICYgIWluX3BlYWspICU+JSBzZWxlY3Qoc25wX2lkKSAlPiUgdW5pcXVlKCkgJT4lIHRhbGx5KCkgJT4lIHVubGlzdCgpCiAgCiAgIyBtYXQgPSBtYXRyaXgoYyhOMywgTjQsIE4xLCBOMiksIG5yb3cgPSAyKQogICMgZnQgPSBmaXNoZXIudGVzdChtYXQpCiAgIyBvdXRfZGZbaSwgXSA9IGMoYWJfdHAsIHRmLCBOMSwgTjIsIE4zLCBONCwgTjMgKyBONCwgImFsbCB2YXJpYW50cyIsIGZ0JGVzdGltYXRlLCBmdCRwLnZhbHVlKQogICMgaSA9IGkgKyAxCiAgIyBwcmludCgiMWEuIEFsbCB2YXJpYW50cyIpCiAgIyBwcmludChmdCkKICAKICBtYXQgPSBtYXRyaXgoYyhOM19hLCBONF9hLCBOMV9hLCBOMl9hKSwgbnJvdyA9IDIpCiAgZnQgPSBmaXNoZXIudGVzdChtYXQpCiAgb3V0X2RmW2ksIF0gPSBjKGFiX3RwLCB0ZiwgTjFfYSwgTjJfYSwgTjNfYSwgTjRfYSwgTjNfYSArIE40X2EsICJpbiBwZWFrcyIsIGZ0JGVzdGltYXRlLCBmdCRwLnZhbHVlKQogIGkgPSBpICsgMQogIHByaW50KCIxYi4gVmFyaWFudHMgaW4gcGVha3MiKQogIHByaW50KGZ0KQogIAogIG1hdCA9IG1hdHJpeChjKE4zX2IsIE40X2IsIE4xX2IsIE4yX2IpLCBucm93ID0gMikKICBmdCA9IGZpc2hlci50ZXN0KG1hdCkKICBvdXRfZGZbaSwgXSA9IGMoYWJfdHAsIHRmLCBOMV9iLCBOMl9iLCBOM19iLCBONF9iLCBOM19iICsgTjRfYiwgIm91dHNpZGUgcGVha3MiLCBmdCRlc3RpbWF0ZSwgZnQkcC52YWx1ZSkKICBpID0gaSArIDEKICBwcmludCgiMWMuIFZhcmlhbnRzIG91dHNpZGUgcGVha3MiKQogIHByaW50KGZ0KQoKfQoKCm91dF9kZiRsYWJlbCA9IHJlcChhYl90cF9sYWJlbHMsIGVhY2ggPSAyKQpvdXRfZGYkbGFiZWwgPSBmYWN0b3Iob3V0X2RmJGxhYmVsLCBsZXZlbHMgPSBhYl90cF9sYWJlbHMpCm91dF9kZiRwdmFsdWUgPSBhcy5udW1lcmljKG91dF9kZiRwdmFsdWUpCm91dF9kZiRvZGRfcmF0aW8gPSBhcy5udW1lcmljKG91dF9kZiRvZGRfcmF0aW8pCgoKCnAgPSBnZ3Bsb3Qob3V0X2RmLCBhZXMoeCA9IGxhYmVsLCB5ID0gb2RkX3JhdGlvKSkgKwogIGZhY2V0X3dyYXAofmdyb3VwKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgY29sb3IgPSAiZGFya3JlZCIpICsKICBnZW9tX2JhcihhZXMoZmlsbCA9IC1sb2cxMChwdmFsdWUpKSwgY29sb3IgPSAiZGFya2JsdWUiLCBzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuNSkgKwogICNzY2FsZV9maWxsX21hbnVhbChuYW1lID0gIiIsIHZhbHVlcyA9IGMoImRhcmtibHVlIiwgImRhcmtncmV5IiksIGxhYmVscyA9IGMoIkFJIHBlYWtzIiwgIm5vbi1BSSBwZWFrcyIpKSArCiAgI2dlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChyMSwgMiksIHggPSBsYWJlbCwgeSA9IG9kZHNfcmF0aW8gKyAwLjA3KSwgZGF0YSA9IGRmLCBzaXplID0gNikgKwogIHlsYWIoIkVucmljaG1lbnQgaW4gY29nbmF0ZSBURiBtb3RpZnMgXG5GaXNoZXIncyBUZXN0IE9kZHMgUmF0aW8iKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIGNvbG91ciA9IFRGY29scyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkKCgpwCgpvdXRmID0gZmlsZS5wYXRoKG91dGRpcl9maWdfc3VwcGwsIHBhc3RlMCgiRmlnUzRCX21vdGlmc19pbl9wZWFrc19maXNoZXIucGRmIikpCmdnc2F2ZShvdXRmLCBwLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA2KQpgYGAKCgojIEZpZ3VyZSBTNEMgLSBNb3RpZiBwcmVkaWN0aW9uIG9mIEFJCgpgYGB7cn0KCiMgQ29ycmVsYXRpb24gYmV0d2VlbiBBSSBhbmQgZGVsdGFfc2NvcmUKCnNjb3JlX3RocmVzID0gMQpkZl9zaGFyZWQgPSBmaW1vX2FsbGVsZXMgJT4lIGZpbHRlcihpbl9wZWFrICYgIWlzLm5hKHNjb3JlLnJlZikgJiAhaXMubmEoc2NvcmUuYWx0KSkgJT4lCiAgbXV0YXRlKGRlbHRhX3Njb3JlID0gYXMubnVtZXJpYyhzY29yZS5yZWYpIC0gYXMubnVtZXJpYyhzY29yZS5hbHQpLAogICAgICAgICB0eXBlID0gaWZlbHNlKChBSSA+IDAuNSAmIGRlbHRhX3Njb3JlID4gMCkgfCAoQUkgPCAwLjUgJiBkZWx0YV9zY29yZSA8IDApLCAiY29uY29yZGFudCIsICJkaXNjb3JkYW50IikpCgpkZl9zaGFyZWQgJT4lIAogIGdyb3VwX2J5KGNvbmRpdGlvbiwgaXNfaW5kZWwpICU+JSAKICBzdW1tYXJpemUobWluKGFicyhkZWx0YV9zY29yZSkpLCBtYXgoZGlzdDJzdW1taXQpLCBjb3IoZGVsdGFfc2NvcmUsIEFJKSwgc2hhcmVfY29uY29yZGFudCA9IHN1bSh0eXBlID09ICJjb25jb3JkYW50IikgLyBuKCksIG4oKSkKCmRmX3N1bSA9IGRmX3NoYXJlZCAlPiUgZmlsdGVyKGFicyhkZWx0YV9zY29yZSkgPiBzY29yZV90aHJlcyAgJiBkaXN0MnN1bW1pdCA8IDI1MCkgJT4lIAogIHN1bW1hcml6ZShtaW4oYWJzKGRlbHRhX3Njb3JlKSksIG1heChkaXN0MnN1bW1pdCksIGNvciA9IGNvcihkZWx0YV9zY29yZSwgQUkpLCBzaGFyZV9jb25jb3JkYW50ID0gc3VtKHR5cGUgPT0gImNvbmNvcmRhbnQiKSAvIG4oKSwgbigpKQoKY29yID0gcm91bmQoZGZfc3VtJGNvciwgMikKbl9jb25jID0gcm91bmQoZGZfc3VtJHNoYXJlX2NvbmNvcmRhbnQsIDIpICogMTAwCm5fZGlzYyA9ICgxIC0gcm91bmQoZGZfc3VtJHNoYXJlX2NvbmNvcmRhbnQsIDIpKSAqIDEwMAoKCnAgPSBnZ3Bsb3QoZGZfc2hhcmVkICU+JSBmaWx0ZXIoYWJzKGRlbHRhX3Njb3JlKSA+IHNjb3JlX3RocmVzICksIGFlcyh4ID0gZGVsdGFfc2NvcmUsIHkgPSBBSSwgY29sb3IgPSB0eXBlKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAxLCBjb2xvciA9IGNiUGFsZXR0ZVsyXSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGNvbG9yID0gImRhcmtibHVlIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IC1zY29yZV90aHJlcywgY29sb3IgPSAiZ3JleSIsIHNpemUgPSAwLjcpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBzY29yZV90aHJlcywgY29sb3IgPSAiZ3JleSIsIHNpemUgPSAwLjcpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjUsIGNvbG9yID0gImdyZXkiLCBzaXplID0gMC43KSArCiAgI2dlb21faGxpbmUoeWludGVyY2VwdCA9IDAuNCwgY29sb3IgPSAiZ3JleSIsIHNpemUgPSAwLjcpICsKICB0aGVtZV9idygpICsKICBhbm5vdGF0ZShnZW9tID0gInRleHQiLCB4ID0gLTMuNSwgeSA9IDAuOTUsIGxhYmVsID0gcGFzdGUoIlI9IiwgY29yKSkgKwogIGFubm90YXRlKGdlb20gPSAidGV4dCIsIHggPSAtMy41LCB5ID0gMC44OCwgbGFiZWwgPSBwYXN0ZSgiJSBjb25jb3JkYW50OiAiLCBuX2NvbmMpLCBzaXplID0gNCkgKwogIHhsYWIoIk1vdGlmIHNjb3JlIGNoYW5nZSAoUkVGLUFMVCkiKSArCiAgeWxhYigiQWxsZWxlIEltYmFsYW1jZSIpICsKICAjc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoY2JQYWxldHRlWzJdLCAiZGFya2dyZXkiKSwgbGFiZWxzID0gYyhwYXN0ZTAoImNvbmNvcmRhbnQsICIsIG5fY29uYywgIiUiKSwgcGFzdGUwKCJkaXNjb3JkYW50LCAiLCBuX2Rpc2MsICIlIikpLCBuYW1lID0gIlZhcmlhbnQgdHlwZSIpICsKICB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTQpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKCgpwCm91dGYgPSBmaWxlLnBhdGgob3V0ZGlyX2ZpZ19zdXBwbCwgcGFzdGUwKCJGaWdTNENfbW90aWZzX0FJX3ByZWRpY3Rpb24ucGRmIikpCmdnc2F2ZShvdXRmLCBwLCB3aWR0aCA9IDQsIGhlaWdodCA9IDQpCgpgYGAKCgoKIyBGaWd1cmUgUzREIC0gUHJvQm91bmQgc2NvcmVzIG9uIEFJIGFuZCBub24tQUkgdmFyaWFudHMKCmBgYHtyfQpQcm9Cb3VuZF9DVENGID0gcmVhZC50YWJsZSgiL2cvZnVybG9uZy9wcm9qZWN0LzY4X0YxX2Npc3JlZ19pY2hpcC9hbmFseXNpcy9Qcm9Cb3VuZC9Qcm9Cb3VuZF9DVENGX1JFRl9zZXF1ZW5jZV8xNWJwX2Fyb3VuZF92YXJpYW50cy50eHQiLCBoZWFkZXI9VFJVRSkKUHJvQm91bmRfQ1RDRiRURiA9ICJDVENGIgpQcm9Cb3VuZF9CaW4gPSByZWFkLnRhYmxlKCIvZy9mdXJsb25nL3Byb2plY3QvNjhfRjFfY2lzcmVnX2ljaGlwL2FuYWx5c2lzL1Byb0JvdW5kL1Byb0JvdW5kX0Jpbl9SRUZfc2VxdWVuY2VfMTVicF9hcm91bmRfdmFyaWFudHMudHh0IiwgaGVhZGVyPVRSVUUpClByb0JvdW5kX0JpbiRURiA9ICJCaW4iClByb0JvdW5kX01lZjIgPSByZWFkLnRhYmxlKCIvZy9mdXJsb25nL3Byb2plY3QvNjhfRjFfY2lzcmVnX2ljaGlwL2FuYWx5c2lzL1Byb0JvdW5kL1Byb0JvdW5kX01lZjJfUkVGX3NlcXVlbmNlXzE1YnBfYXJvdW5kX3ZhcmlhbnRzLnR4dCIsIGhlYWRlcj1UUlVFKQpQcm9Cb3VuZF9NZWYyJFRGID0gIk1lZjIiClByb0JvdW5kX1R3aSA9IHJlYWQudGFibGUoIi9nL2Z1cmxvbmcvcHJvamVjdC82OF9GMV9jaXNyZWdfaWNoaXAvYW5hbHlzaXMvUHJvQm91bmQvUHJvQm91bmRfVHdpX1JFRl9zZXF1ZW5jZV8xNWJwX2Fyb3VuZF92YXJpYW50cy50eHQiLCBoZWFkZXI9VFJVRSkKUHJvQm91bmRfVHdpJFRGID0gIlR3aSIKClByb0JvdW5kX3Jlc3VsdHNfUkVGID0gcmJpbmQoUHJvQm91bmRfQ1RDRiwgUHJvQm91bmRfQmluLCBQcm9Cb3VuZF9NZWYyLCBQcm9Cb3VuZF9Ud2kpCmNvbG5hbWVzKFByb0JvdW5kX3Jlc3VsdHNfUkVGKSA9IGMoInZhcmlhbnRfY2hyIiwgInZhcmlhbnRfcG9zIiwgIlJFRiIsICJBTFQiLCAiUHJvQm91bmRfYmVkX1JFRiIsICJQcm9Cb3VuZF9zZXFfUkVGIiwgIlByb0JvdW5kX3Njb3JlX1JFRiIsICJURiIpClByb0JvdW5kX3Jlc3VsdHNfUkVGID0gUHJvQm91bmRfcmVzdWx0c19SRUYgJT4lCiAgICAgICAgZ3JvdXBfYnkoVEYpICU+JQogICAgICAgIG11dGF0ZShQcm9Cb3VuZF9zY29yZV9zY2FsZWRfUkVGID0gUHJvQm91bmRfc2NvcmVfUkVGIC8gbWF4KFByb0JvdW5kX3Njb3JlX1JFRikpCgoKUHJvQm91bmRfQUxUX0NUQ0YgPSByZWFkLnRhYmxlKCIvZy9mdXJsb25nL3Byb2plY3QvNjhfRjFfY2lzcmVnX2ljaGlwL2FuYWx5c2lzL1Byb0JvdW5kL1Byb0JvdW5kX0NUQ0ZfQUxUX3NlcXVlbmNlXzE1YnBfYXJvdW5kX3ZhcmlhbnRzLnR4dCIsIGhlYWRlcj1UUlVFKQpQcm9Cb3VuZF9BTFRfQ1RDRiRURiA9ICJDVENGIgpQcm9Cb3VuZF9BTFRfQmluID0gcmVhZC50YWJsZSgiL2cvZnVybG9uZy9wcm9qZWN0LzY4X0YxX2Npc3JlZ19pY2hpcC9hbmFseXNpcy9Qcm9Cb3VuZC9Qcm9Cb3VuZF9CaW5fQUxUX3NlcXVlbmNlXzE1YnBfYXJvdW5kX3ZhcmlhbnRzLnR4dCIsIGhlYWRlcj1UUlVFKQpQcm9Cb3VuZF9BTFRfQmluJFRGID0gIkJpbiIKUHJvQm91bmRfQUxUX01lZjIgPSByZWFkLnRhYmxlKCIvZy9mdXJsb25nL3Byb2plY3QvNjhfRjFfY2lzcmVnX2ljaGlwL2FuYWx5c2lzL1Byb0JvdW5kL1Byb0JvdW5kX01lZjJfQUxUX3NlcXVlbmNlXzE1YnBfYXJvdW5kX3ZhcmlhbnRzLnR4dCIsIGhlYWRlcj1UUlVFKQpQcm9Cb3VuZF9BTFRfTWVmMiRURiA9ICJNZWYyIgpQcm9Cb3VuZF9BTFRfVHdpID0gcmVhZC50YWJsZSgiL2cvZnVybG9uZy9wcm9qZWN0LzY4X0YxX2Npc3JlZ19pY2hpcC9hbmFseXNpcy9Qcm9Cb3VuZC9Qcm9Cb3VuZF9Ud2lfQUxUX3NlcXVlbmNlXzE1YnBfYXJvdW5kX3ZhcmlhbnRzLnR4dCIsIGhlYWRlcj1UUlVFKQpQcm9Cb3VuZF9BTFRfVHdpJFRGID0gIlR3aSIKClByb0JvdW5kX3Jlc3VsdHNfQUxUID0gcmJpbmQoUHJvQm91bmRfQUxUX0NUQ0YsIFByb0JvdW5kX0FMVF9CaW4sIFByb0JvdW5kX0FMVF9NZWYyLCBQcm9Cb3VuZF9BTFRfVHdpKQpjb2xuYW1lcyhQcm9Cb3VuZF9yZXN1bHRzX0FMVCkgPSBjKCJ2YXJpYW50X2NociIsICJ2YXJpYW50X3BvcyIsICJSRUYiLCAiQUxUIiwgIlByb0JvdW5kX2JlZF9BTFQiLCAiUHJvQm91bmRfc2VxX0FMVCIsICJQcm9Cb3VuZF9zY29yZV9BTFQiLCAiVEYiKQpQcm9Cb3VuZF9yZXN1bHRzX0FMVCA9IFByb0JvdW5kX3Jlc3VsdHNfQUxUICU+JQogICAgICAgIGdyb3VwX2J5KFRGKSAlPiUKICAgICAgICBtdXRhdGUoUHJvQm91bmRfc2NvcmVfc2NhbGVkX0FMVCA9IFByb0JvdW5kX3Njb3JlX0FMVCAvIG1heChQcm9Cb3VuZF9zY29yZV9BTFQpKQoKClByb0JvdW5kX3Jlc3VsdHMgPSBtZXJnZShQcm9Cb3VuZF9yZXN1bHRzX1JFRiwgUHJvQm91bmRfcmVzdWx0c19BTFQsIGJ5ID0gYygidmFyaWFudF9jaHIiLCAidmFyaWFudF9wb3MiLCAiUkVGIiwgIkFMVCIsICJURiIpLCBhbGwueD1UUlVFKQpQcm9Cb3VuZF9yZXN1bHRzJHZhcmlhbnRfSUQgPSBwYXN0ZShQcm9Cb3VuZF9yZXN1bHRzJHZhcmlhbnRfY2hyLCBQcm9Cb3VuZF9yZXN1bHRzJHZhcmlhbnRfcG9zLCBQcm9Cb3VuZF9yZXN1bHRzJFRGLCBzZXA9Il8iKQpQcm9Cb3VuZF9yZXN1bHRzJFByb0JvdW5kX3Njb3JlX21heCA9IHBtYXgoUHJvQm91bmRfcmVzdWx0cyRQcm9Cb3VuZF9zY29yZV9BTFQsIFByb0JvdW5kX3Jlc3VsdHMkUHJvQm91bmRfc2NvcmVfUkVGKQoKCmNodCR2YXJpYW50X0lEID0gcGFzdGUoY2h0JHNucF9pZCwgY2h0JGFiLCBzZXA9Il8iKQpjaHRfUHJvQm91bmQgPSBtZXJnZShjaHQsIFByb0JvdW5kX3Jlc3VsdHMsIGJ5PSJ2YXJpYW50X0lEIikKY2h0X1Byb0JvdW5kJHNpZ25pZl9zdHJvbmdBSSA9IGZhY3RvcihjaHRfUHJvQm91bmQkc2lnbmlmX3N0cm9uZ0FJLCBsZXZlbHM9YyhUUlVFLCBGQUxTRSkpCgoKcCA9IGdncGxvdChjaHRfUHJvQm91bmQsIGFlcyh4PXNpZ25pZl9zdHJvbmdBSSwgeT1Qcm9Cb3VuZF9zY29yZV9tYXgsIGZpbGw9c2lnbmlmX3N0cm9uZ0FJKSkgKyAKICAgICAgZmFjZXRfd3JhcCh+Y29uZGl0aW9uKSArCiAgICAgIGdlb21fdmlvbGluKGZpbGwgPSAiZGFya2JsdWUiLCBhbHBoYSA9IDAuMykgKwogICAgICBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjQsIG91dGxpZXIuc2l6ZSA9IDAuMSwgZmlsbCA9ICJkYXJrYmx1ZSIsIGFscGhhID0gMC41KSArCiAgICAgIHNjYWxlX3lfbG9nMTAoKSArIAogICAgICBzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveCIpICsKICAgICAgeGxhYigiU2lnbmlmaWNhbnQgYWxsZWxpYyBpbWJhbGFuY2UiKSArCiAgICAgIHlsYWIoIi1sb2coMTApIFByb0JvdW5kIHNzY2FsZWQgY29yZSIpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCm91dGYgPSBmaWxlLnBhdGgob3V0ZGlyX2ZpZ19zdXBwbCwgcGFzdGUwKCJGaWdTNERfUHJvQm91bmRfbWF4X3Njb3Jlc19vbl9BSV92YXJpYW50cy5wZGYiKSkKZ2dzYXZlKG91dGYsIHAsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCkKYGBgCg==