Plot contrasts of
interest
One suggestion I received recently was to set the axes for these
volcano plots to be static rather than let ggplot choose its own. I am
assuming this is only relevant for pairs of contrasts, but that might
not be true.
Individual zymodemes
vs. uninfected
z23nosb_vs_uninf_volcano <- plot_volcano_de(
table = hs_macrophage_table[["data"]][["z23nosb_vs_uninf"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23nosb_vs_uninf_volcano$plot)
## Error in plotly::ggplotly(z23nosb_vs_uninf_volcano$plot): object 'z23nosb_vs_uninf_volcano' not found
z22nosb_vs_uninf_volcano <- plot_volcano_de(
table = hs_macrophage_table[["data"]][["z22nosb_vs_uninf"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z22nosb_vs_uninf_volcano$plot)
## Error in plotly::ggplotly(z22nosb_vs_uninf_volcano$plot): object 'z22nosb_vs_uninf_volcano' not found
Zymodeme 2.3
without drug vs. uninfected
z23nosb_vs_uninf_volcano$plot +
xlim(-10, 25) +
ylim(0, 40)
## Error in eval(expr, envir, enclos): object 'z23nosb_vs_uninf_volcano' not found
pp(file="images/z23_uninf_reactome_up.png", image=all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23_uninf_reactome_up.png", image = all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_uninf_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_uninf_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z22nosb_vs_uninf_volcano$plot +
xlim(-10, 25) +
ylim(0, 40)
## Error in eval(expr, envir, enclos): object 'z22nosb_vs_uninf_volcano' not found
pp(file="images/z22_uninf_reactome_up.png", image=all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z22_uninf_reactome_up.png", image = all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.2 without drug vs. uninfected without drug, up.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.2 without drug vs. uninfected without drug, down.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.2 without drug vs. uninfected without drug, down.
all_gp[["z22nosb_vs_uninf_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
Check that my perception of the number of significant up/down genes
matches what the table/venn says.
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_uninf"]]),
"nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23nosb_vs_uninf"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z23_vs_uninf_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png
## 2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
## I see 910 z23sb/uninf and 670 no z23nosb/uninf genes in the venn diagram.
length(shared@IntersectionSets[["10"]]) + length(shared@IntersectionSets[["11"]])
## Error in eval(expr, envir, enclos): object 'shared' not found
dim(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_uninf"]])
## Error in eval(expr, envir, enclos): object 'hs_macrophage_sig' not found
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_uninf"]]),
"nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22nosb_vs_uninf"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z22_vs_uninf_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png
## 2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
length(shared@IntersectionSets[["10"]]) + length(shared@IntersectionSets[["11"]])
## Error in eval(expr, envir, enclos): object 'shared' not found
dim(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_uninf"]])
## Error in eval(expr, envir, enclos): object 'hs_macrophage_sig' not found
Note to self: There is an error in my volcano plot code
which takes effect when the numerator and denominator of the
all_pairwise contrasts are different than those in combine_de_tables. It
is putting the ups/downs on the correct sides of the plot, but calling
the down genes ‘up’ and vice-versa. The reason for this is that I did a
check for this happening, but used the wrong argument to handle it.
A likely bit of text for these volcano plots:
The set of genes differentially expressed between the zymodeme 2.3
and uninfected samples without druge treatment was quantified with
DESeq2 and included surrogate estimates from SVA. Given the criteria of
significance of a abs(logFC) >= 1.0 and false discovery rate adjusted
p-value <= 0.05, 670 genes were observed as significantly increased
between the infected and uninfected samples and 386 were observed as
decreased. The most increased genes from the uninfected samples include
some which are potentially indicative of a strong innate immune response
and the inflammatory response.
In contrast, when the set of genes differentially expressed between
the zymodeme 2.2 and uninfected samples was visualized, only 7 genes
were observed as decreased and 435 increased. The inflammatory response
was significantly less apparent in this set, but instead included genes
related to transporter activity and oxidoreductases.
Direct zymodeme
comparisons
An orthogonal comparison to that performed above is to directly
compare the zymodeme 2.3 and 2.2 samples with and without antimonial
treatment.
z23nosb_vs_z22nosb_volcano <- plot_volcano_de(
table = hs_macrophage_table[["data"]][["z23nosb_vs_z22nosb"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23nosb_vs_z22nosb_volcano$plot)
## Error in plotly::ggplotly(z23nosb_vs_z22nosb_volcano$plot): object 'z23nosb_vs_z22nosb_volcano' not found
z23sb_vs_z22sb_volcano <- plot_volcano_de(
table = hs_macrophage_table[["data"]][["z23sb_vs_z22sb"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23sb_vs_z22sb_volcano$plot)
## Error in plotly::ggplotly(z23sb_vs_z22sb_volcano$plot): object 'z23sb_vs_z22sb_volcano' not found
z23nosb_vs_z22nosb_volcano$plot +
xlim(-10, 10) +
ylim(0, 60)
## Error in eval(expr, envir, enclos): object 'z23nosb_vs_z22nosb_volcano' not found
pp(file="images/z23nosb_vs_z22nosb_reactome_up.png", image=all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23nosb_vs_z22nosb_reactome_up.png", image = all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23nosb_vs_z22nosb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23nosb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z23sb_vs_z22sb_volcano$plot +
xlim(-10, 10) +
ylim(0, 60)
## Error in eval(expr, envir, enclos): object 'z23sb_vs_z22sb_volcano' not found
pp(file="images/z23sb_vs_z22sb_reactome_up.png", image=all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23sb_vs_z22sb_reactome_up.png", image = all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z22sb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z22sb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_z22sb"]]),
"nodrug" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23nosb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/drug_nodrug_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png
## 2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
shared <- Vennerable::Venn(list("drug" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23sb_vs_z22sb"]]),
"nodrug" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23nosb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/drug_nodrug_venn_down.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png
## 2
A slightly different way of looking at the differences between the
two zymodeme infections is to directly compare the infected samples with
and without drug. Thus, when a volcano plot showing the comparison of
the zymodeme 2.3 vs. 2.2 samples was plotted, 484 genes were observed as
increased and 422 decreased; these groups include many of the same
inflammatory (up) and membrane (down) genes.
Similar patterns were observed when the antimonial was included.
Thus, when a Venn diagram of the two sets of increased genes was
plotted, a significant number of the genes was observed as increased
(313) and decreased (244) in both the untreated and antimonial treated
samples.
Drug effects on each
zymodeme infection
Another likely question is to directly compare the treated vs
untreated samples for each zymodeme infection in order to visualize the
effects of antimonial.
z23sb_vs_z23nosb_volcano <- plot_volcano_de(
table = hs_macrophage_table[["data"]][["z23sb_vs_z23nosb"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z23sb_vs_z23nosb_volcano$plot)
## Error in plotly::ggplotly(z23sb_vs_z23nosb_volcano$plot): object 'z23sb_vs_z23nosb_volcano' not found
z22sb_vs_z22nosb_volcano <- plot_volcano_de(
table = hs_macrophage_table[["data"]][["z22sb_vs_z22nosb"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
## Error in is.data.frame(x): object 'hs_macrophage_table' not found
plotly::ggplotly(z22sb_vs_z22nosb_volcano$plot)
## Error in plotly::ggplotly(z22sb_vs_z22nosb_volcano$plot): object 'z22sb_vs_z22nosb_volcano' not found
z23sb_vs_z23nosb_volcano$plot +
xlim(-8, 8) +
ylim(0, 210)
## Error in eval(expr, envir, enclos): object 'z23sb_vs_z23nosb_volcano' not found
pp(file="images/z23sb_vs_z23nosb_reactome_up.png",
image=all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z23sb_vs_z23nosb_reactome_up.png", image = all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z23sb_vs_z23nosb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z23sb_vs_z23nosb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
z22sb_vs_z22nosb_volcano$plot +
xlim(-8, 8) +
ylim(0, 210)
## Error in eval(expr, envir, enclos): object 'z22sb_vs_z22nosb_volcano' not found
pp(file="images/z22sb_vs_z22nosb_reactome_up.png",
image=all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], height=12, width=9)
## Error in pp(file = "images/z22sb_vs_z22nosb_reactome_up.png", image = all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["REAC"]], : object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["KEGG"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## KEGG, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["pvalue_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## WikiPathways, zymodeme2.3 without drug vs. uninfected without drug, up.
all_gp[["z22sb_vs_z22nosb_up"]][["interactive_plots"]][["WP"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["REAC"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## Reactome, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["MF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## MF, zymodeme2.3 without drug vs. uninfected without drug, down.
all_gp[["z22sb_vs_z22nosb_down"]][["pvalue_plots"]][["TF"]]
## Error in eval(expr, envir, enclos): object 'all_gp' not found
## TF, zymodeme2.3 without drug vs. uninfected without drug, down.
shared <- Vennerable::Venn(list("z23" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z23sb_vs_z23nosb"]]),
"z22" = rownames(hs_macrophage_sig[["deseq"]][["ups"]][["z22sb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z23_z22_drug_venn_up.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png
## 2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
shared <- Vennerable::Venn(list("z23" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z23sb_vs_z23nosb"]]),
"z22" = rownames(hs_macrophage_sig[["deseq"]][["downs"]][["z22sb_vs_z22nosb"]])))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'hs_macrophage_sig' not found
pp(file="images/z23_z22_drug_venn_down.png")
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
dev.off()
## png
## 2
Vennerable::plot(shared)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'shared' not found
Note: I am settig the x and y-axis boundaries by allowing the plotter
to pick its own axis the first time, writing down the ranges I observe,
and then setting them to the largest of the pair. It is therefore
possible that I missed one or more genes which lies outside that
range.
The previous plotted contrasts sought to show changes between the two
strains z2.3 and z2.2. Conversely, the previous volcano plots seek to
directly compare each strain before/after drug treatment.
LRT of the Human
Macrophage
tmrc2_lrt_strain_drug <- deseq_lrt(hs_macr, interactor_column = "drug",
interest_column = "macrophagezymodeme", factors = c("drug", "macrophagezymodeme"))
## converting counts to integer mode
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
## -- replacing outliers and refitting for 517 genes
## -- DESeq argument 'minReplicatesForReplace' = 7
## -- original counts are preserved in counts(dds)
## estimating dispersions
## fitting model and testing
## rlog() may take a long time with 50 or more samples,
## vst() is a much faster transformation
## Working with 138 genes.
## Working with 138 genes after filtering: minc > 3
## Joining, by = "merge"
## Joining, by = "merge"

tmrc2_lrt_strain_drug$cluster_data$plot

Parasite
lp_macrophage_de <- all_pairwise(lp_macrophage,
model_batch="svaseq", filter=TRUE)
## This DE analysis will perform all pairwise comparisons among:
##
## z2.2 z2.3
## 11 9
## This analysis will include surrogate estimates from: svaseq.
## This will pre-filter the input data using normalize_expt's: TRUE argument.
## Removing 0 low-count genes (8541 remaining).
## Setting 134 low elements to zero.
## transform_counts: Found 134 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
tmrc2_parasite_keepers <- list(
"z23_vs_z22" = c("z23", "z22"))
lp_macrophage_table <- combine_de_tables(
lp_macrophage_de, keepers = tmrc2_parasite_keepers,
excel=glue::glue("excel/macrophage_parasite_infection_de-v{ver}.xlsx"))
## Deleting the file excel/macrophage_parasite_infection_de-v202301.xlsx before writing the tables.
## Starting combine_extracted_plots() with do_inverse as: FALSE.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
lp_macrophage_sig <- extract_significant_genes(
lp_macrophage_table,
excel=glue::glue("excel/macrophage_parasite_sig-v{ver}.xlsx"))
## Deleting the file excel/macrophage_parasite_sig-v202301.xlsx before writing the tables.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and FDR using the expressionset colors.
## Plotting volcano plot of the DE results of z23_vs_z22 according to the columns: logFC and adj.P.Val using the expressionset colors.
pp(file="images/lp_macrophage_z23_z22.png",
image=lp_macrophage_table[["plots"]][["z23nosb_vs_z22nosb"]][["deseq_vol_plots"]][["plot"]])
up_genes <- lp_macrophage_sig[["deseq"]][["ups"]][[1]]
dim(up_genes)
## [1] 47 58
down_genes <- lp_macrophage_sig[["deseq"]][["downs"]][[1]]
dim(down_genes)
## [1] 88 58
lp_z23sb_vs_z22sb_volcano <- plot_volcano_de(
table = lp_macrophage_table[["data"]][["z23_vs_z22"]],
fc_col = "deseq_logfc", p_col = "deseq_adjp",
shapes_by_state = FALSE, color_by = "fc", label = 10, label_column = "hgncsymbol")
plotly::ggplotly(lp_z23sb_vs_z22sb_volcano$plot)
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
## If you'd like to see this geom implemented,
## Please open an issue with your example code at
## https://github.com/ropensci/plotly/issues
## Warning in geom2trace.default(dots[[1L]][[2L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomTextRepel() has yet to be implemented in plotly.
## If you'd like to see this geom implemented,
## Please open an issue with your example code at
## https://github.com/ropensci/plotly/issues
lp_z23nosb_vs_z22nosb_volcano$plot
## Error in eval(expr, envir, enclos): object 'lp_z23nosb_vs_z22nosb_volcano' not found
up_goseq <- simple_goseq(up_genes, go_db=lp_go, length_db=lp_lengths)
## Found 16 go_db genes and 47 length_db genes out of 47.
## Testing that go categories are defined.
## Removing undefined categories.
## Gathering synonyms.
## Gathering category definitions.
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category" "over_represented_pvalue"
## [3] "under_represented_pvalue" "numDEInCat"
## [5] "numInCat" "term"
## [7] "ontology" "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term" "pvalue" "score" "num_de" "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category" "over_represented_pvalue"
## [3] "under_represented_pvalue" "numDEInCat"
## [5] "numInCat" "term"
## [7] "ontology" "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term" "pvalue" "score" "num_de" "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category" "over_represented_pvalue"
## [3] "under_represented_pvalue" "numDEInCat"
## [5] "numInCat" "term"
## [7] "ontology" "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term" "pvalue" "score" "num_de" "num_cat"
## View categories over represented in the 2.3 samples
up_goseq$pvalue_plots$bpp_plot_over

down_goseq <- simple_goseq(down_genes, go_db=lp_go, length_db=lp_lengths)
## Found 28 go_db genes and 88 length_db genes out of 88.
## Testing that go categories are defined.
## Removing undefined categories.
## Gathering synonyms.
## Gathering category definitions.
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category" "over_represented_pvalue"
## [3] "under_represented_pvalue" "numDEInCat"
## [5] "numInCat" "term"
## [7] "ontology" "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term" "pvalue" "score" "num_de" "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category" "over_represented_pvalue"
## [3] "under_represented_pvalue" "numDEInCat"
## [5] "numInCat" "term"
## [7] "ontology" "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term" "pvalue" "score" "num_de" "num_cat"
## The score column is null, defaulting to score.
## Possible columns are:
## [1] "category" "over_represented_pvalue"
## [3] "under_represented_pvalue" "numDEInCat"
## [5] "numInCat" "term"
## [7] "ontology" "qvalue"
## The over_represented_pvalue column is null, defaulting to score.
## Possible columns are:
## [1] "term" "pvalue" "score" "num_de" "num_cat"
## View categories over represented in the 2.2 samples
down_goseq$pvalue_plots$bpp_plot_over

LS0tCnRpdGxlOiAiVE1SQzIgMjAyMzAxOiBNYWNyb3BoYWdlIERpZmZlcmVudGlhbCBFeHByZXNzaW9uLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgIGNvbGxhcHNlZDogZmFsc2UKICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZSA9IEZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoSGVhdHBsdXMpCmxpYnJhcnkoaHBnbHRvb2xzKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3MgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSA5MCwKICAgICAgICAgICAgICAgICAgICAgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGggPSA4LAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDgsCiAgICAgICAgICAgICAgICAgICAgICBkcGkgPSA5NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gIjIwMjMwMSIKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lID0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gZ2x1ZTo6Z2x1ZSgidG1yYzJfbWFjcm9waGFnZV9kaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl97dmVyfS5SbWQiKQpsb2FkZWQgPC0gbG9hZChmaWxlPWdsdWU6OmdsdWUoInJkYS90bXJjMl9kYXRhX3N0cnVjdHVyZXMtdnt2ZXJ9LnJkYSIpKQpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBybWRfZmlsZSkKYGBgCgojIEludHJvZHVjdGlvbgoKSGF2aW5nIGVzdGFibGlzaGVkIHRoYXQgdGhlIFRNUkMyIG1hY3JvcGhhZ2UgZGF0YSBsb29rcyByb2J1c3QgYW5kCmlsbHVzdHJhdGl2ZSBvZiBhIGNvdXBsZSBvZiBpbnRlcmVzdGluZyBxdWVzdGlvbnMsIGxldCB1cyBwZXJmb3JtIGEKY291cGxlIG9mIGRpZmZlcmVudGlhbCBhbmFseXNlcyBvZiBpdC4KCkFsc28gbm90ZSB0aGF0IGFzIG9mIDIwMjIxMiwgd2UgcmVjZWl2ZWQgYSBuZXcgc2V0IG9mIHNhbXBsZXMgd2hpY2gKbm93IGluY2x1ZGUgc29tZSB3aGljaCBhcmUgb2YgYSBjb21wbGV0ZWx5IGRpZmZlcmVudCBjZWxsIHR5cGUsClU5MzcuIEFzIHRoZWlyIEFUQ0MgcGFnZSBzdGF0ZXMsIHRoZXkgYXJlIG1hbGlnbmFudCBjZWxscyB0YWtlbiBmcm9tCnRoZSBwbGV1cmFsIGVmZnVzaW9uIG9mIGEgMzcgeWVhciBvbGQgd2hpdGUgbWFsZSB3aXRoIGhpc3Rpb2N5dGljCmx5bXBob21hIGFuZCB3aGljaCBleGhpYml0IHRoZSBtb3JwaG9sb2d5IG9mIG1vbm9jeXRlcy4gIFRodXMsIHRoaXMKZG9jdW1lbnQgbm93IGluY2x1ZGVzIHNvbWUgY29tcGFyaXNvbnMgb2YgdGhlIGNlbGwgdHlwZXMgYXMgd2VsbCBhcwp0aGUgdmFyaW91cyBtYWNyb3BoYWdlIGRvbm9ycyAoZ2l2ZW4gdGhhdCB0aGVyZSBhcmUgbm93IG1vcmUgZG9ub3JzCnRvbykuCgojIFRPRE8KCiogUXVlcnkgb3ZlcmxhcCBvZiBtYWNyb3BoYWdlIDIuMy8yLjIgU2IgYW5kIG5vU2IuIChkb25lPykKKiBSZXBlYXQgd2l0aCBVOTM3CgojIyBIdW1hbiBkYXRhCgpJIGFtIG1vdmluZyB0aGUgZGF0YXNldCBtYW5pcHVsYXRpb25zIGhlcmUgc28gdGhhdCBJIGNhbiBsb29rIGF0IHRoZW0KYWxsIHRvZ2V0aGVyIGJlZm9yZSBydW5uaW5nIHRoZSB2YXJpb3VzIERFIGFuYWx5c2VzLgoKIyMgQ3JlYXRlIHNldHMgZm9jdXNlZCBvbiBkcnVnLCBjZWxsdHlwZSwgc3RyYWluLCBhbmQgY29tYmluYXRpb25zCgpMZXQgdXMgc3RhcnQgYnkgcGxheWluZyB3aXRoIHRoZSBtZXRhZGF0YSBhIGxpdHRsZSBhbmQgY3JlYXRlIHNldHMKd2l0aCB0aGUgY29uZGl0aW9uIHNldCB0bzoKCiogRHJ1ZyB0cmVhdG1lbnQKKiBDZWxsIHR5cGUgKG1hY3JvcGhhZ2Ugb3IgVTkzNykKKiBEb25vcgoqIEluZmVjdGlvbiBTdHJhaW4KKiBTb21lIHVzZWZ1bCBjb21iaW5hdGlvbnMgdGhlcmVvZgoKSW4gYWRkaXRpb24sIGtlZXAgbWVudGFsIHRyYWNrIG9mIHdoaWNoIGRhdGFzZXRzIGFyZSBjb21wcmlzZWQgb2YgYWxsCnNhbXBsZXMgdnMuIHRob3NlIHdoaWNoIGFyZSBvbmx5IG1hY3JvcGhhZ2UgdnMuIHRob3NlIHdoaWNoIGFyZSBvbmx5ClU5MzcuICAoVGh1cywgdGhlIHVzYWdlIG9mIGFsbF9odW1hbiB2cy4gaHNfbWFjciB2cy4gdTkzNyBhcyBwcmVmaXhlcwpmb3IgdGhlIGRhdGEgc3RydWN0dXJlcy4pCgpgYGB7ciBkZV9kYXRhc2V0c30KYWxsX2h1bWFuIDwtIHNhbml0aXplX2V4cHRfbWV0YWRhdGEoaHNfbWFjcm9waGFnZSwgY29sdW1ucyA9ICJkcnVnIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0ID0gImRydWciKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3QgPSAidHlwZW9mY2VsbHMiKQoKYWxsX2h1bWFuX3R5cGVzIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoYWxsX2h1bWFuLCBmYWN0ID0gInR5cGVvZmNlbGxzIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImRydWciKQoKdHlwZV96eW1vX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJjb25kaXRpb24iXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJtYWNyb3BoYWdlenltb2RlbWUiXV0pCnR5cGVfenltbyA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGFsbF9odW1hbl90eXBlcywgZmFjdCA9IHR5cGVfenltb19mYWN0KQoKdHlwZV9kcnVnX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJjb25kaXRpb24iXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHBEYXRhKGFsbF9odW1hbl90eXBlcylbWyJkcnVnIl1dKQp0eXBlX2RydWcgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhhbGxfaHVtYW5fdHlwZXMsIGZhY3Q9dHlwZV9kcnVnX2ZhY3QpCgpuZXdfY29uZGl0aW9ucyA8LSBwYXN0ZTAocERhdGEoaHNfbWFjcm9waGFnZSlbWyJtYWNyb3BoYWdldHJlYXRtZW50Il1dLCAiXyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBwRGF0YShoc19tYWNyb3BoYWdlKVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKIyMgTm90ZSB0aGUgc2FuaXRpemUoKSBjYWxsIGlzIHJlZHVuZGFudCB3aXRoIHRoZSBhZGRpdGlvbiBvZiBzYW5pdGl6ZSgpIGluIHRoZQojIyBkYXRhc3RydWN0dXJlcyBmaWxlLCBidXQgSSBkb24ndCB3YW50IHRvIHdhaXQgdG8gcmVydW4gdGhhdC4KaHNfbWFjciA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX21hY3JvcGhhZ2UsIGZhY3QgPSBuZXdfY29uZGl0aW9ucykgJT4lCiAgc2FuaXRpemVfZXhwdF9tZXRhZGF0YShjb2x1bW4gPSAiZHJ1ZyIpCgpuZXdfY29uZGl0aW9ucyA8LSBwYXN0ZTAocERhdGEoaHNfdTkzNylbWyJtYWNyb3BoYWdldHJlYXRtZW50Il1dLCAiXyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBwRGF0YShoc191OTM3KVtbIm1hY3JvcGhhZ2V6eW1vZGVtZSJdXSkKdTkzN19leHB0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoaHNfdTkzNywgZmFjdD1uZXdfY29uZGl0aW9ucykKYGBgCgpUaGVyZSBpcyBhIHNldCBvZiBjb250cmFzdHMgaW4gd2hpY2ggd2UgYXJlIHByaW1hcmlseSBpbnRlcmVzdGVkIGluCnRoaXMgZGF0YSwgdGhlc2UgZm9sbG93LiAgSSBjcmVhdGVkIG9uZSByYXRpbyBvZiByYXRpb3MgY29udHJhc3Qgd2hpY2gKSSB0aGluayBoYXMgdGhlIHBvdGVudGlhbCB0byBhc2sgb3VyIGJpZ2dlc3QgcXVlc3Rpb24uCgpgYGB7ciB0dW1yYzJfaHVtYW5fa2VlcGVyc30KdG1yYzJfaHVtYW5fZXh0cmEgPC0gInoyM2RydWdub2RydWdfdnNfejIyZHJ1Z25vZHJ1ZyA9IChpbmZzYnoyMyAtIGluZnoyMykgLSAoaW5mc2J6MjIgLSBpbmZ6MjIpLAp6MjN6MjJkcnVnX3ZzX3oyM3oyMm5vZHJ1ZyA9IChpbnNiejIzIC0gaW5mc2J6MjIpIC0gKGluZnoyMyAtIGluZnoyMikiCnRtcmMyX2h1bWFuX2tlZXBlcnMgPC0gbGlzdCgKICAgICJ6MjNub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMyIsICJ1bmluZm5vbmUiKSwKICAgICJ6MjJub3NiX3ZzX3VuaW5mIiA9IGMoImluZnoyMiIsICJ1bmluZm5vbmUiKSwKICAgICJ6MjNub3NiX3ZzX3oyMm5vc2IiID0gYygiaW5mejIzIiwgImluZnoyMiIpLAogICAgInoyM3NiX3ZzX3oyMnNiIiA9IGMoImluZnNiejIzIiwgImluZnNiejIyIiksCiAgICAiejIzc2JfdnNfejIzbm9zYiIgPSBjKCJpbmZzYnoyMyIsICJpbmZ6MjMiKSwKICAgICJ6MjJzYl92c196MjJub3NiIiA9IGMoImluZnNiejIyIiwgImluZnoyMiIpLAogICAgInoyM3NiX3ZzX3NiIiA9IGMoImluZnoyMyIsICJ1bmluZnNibm9uZSIpLAogICAgInoyMnNiX3ZzX3NiIiA9IGMoImluZnoyMiIsICJ1bmluZnNibm9uZSIpLAogICAgInoyM3NiX3ZzX3VuaW5mIiA9IGMoImluZnNiejIzIiwgInVuaW5mbm9uZSIpLAogICAgInoyMnNiX3ZzX3VuaW5mIiA9IGMoImluZnNiejIyIiwgInVuaW5mbm9uZSIpLAogICAgInNiX3ZzX3VuaW5mIiA9IGMoInVuaW5mc2Jub25lIiwgInVuaW5mbm9uZSIpLAogICAgImV4dHJhX3oyMzIyIiA9IGMoInoyM2RydWdub2RydWciLCAiejIyZHJ1Z25vZHJ1ZyIpLAogICAgImV4dHJhX2RydWdub2RydWciID0gYygiejIzejIyZHJ1ZyIsICJ6MjN6MjJub2RydWciKSkKdG1yYzJfZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgICAiZHJ1ZyIgPSBjKCJhbnRpbW9ueSIsICJub25lIikpCnRtcmMyX3R5cGVfa2VlcGVycyA8LSBsaXN0KAogICAgInR5cGUiID0gYygiVTkzNyIsICJNYWNyb3BoYWdlcyIpKQp0bXJjMl9zdHJhaW5fa2VlcGVycyA8LSBsaXN0KAogICAgInN0cmFpbiIgPSBjKCJ6MjMiLCAiejIyIikpCnR5cGVfenltb19leHRyYSA8LSAienltb3NfdnNfdHlwZXMgPSAoVTkzN196Mi4zIC0gVTkzN196Mi4yKSAtIChNYWNyb3BoYWdlc196Mi4zIC0gTWFjcm9waGFnZXNfejIuMikiCnRtcmMyX3R5cGV6eW1vX2tlZXBlcnMgPC0gbGlzdCgKICAgICJ1OTM3X21hY3IiID0gYygiTWFjcm9waGFnZXNub25lIiwgIlU5Mzdub25lIiksCiAgICAienltb19tYWNyIiA9IGMoIk1hY3JvcGhhZ2VzejIzIiwgIk1hY3JvcGhhZ2VzejIyIiksCiAgICAienltb191OTM3IiA9IGMoIlU5Mzd6MjMiLCAiVTkzN3oyMiIpLAogICAgInoyM190eXBlcyIgPSBjKCJVOTM3ejIzIiwgIk1hY3JvcGhhZ2VzejIzIiksCiAgICAiejIyX3R5cGVzIiA9IGMoIlU5Mzd6MjIiLCAiTWFjcm9waGFnZXN6MjIiKSwKICAgICJ6eW1vc190eXBlcyIgPSBjKCJ6eW1vc192c190eXBlcyIpKQp0bXJjMl90eXBlZHJ1Z19rZWVwZXJzIDwtIGxpc3QoCiAgICAidHlwZV9ub2RydWciID0gYygiVTkzN25vbmUiLCAiTWFjcm9waGFnZXNub25lIiksCiAgICAidHlwZV9kcnVnIiA9IGMoIlU5MzdhbnRpbW9ueSIsICJNYWNyb3BoYWdlc2FudGltb255IiksCiAgICAibWFjcl9kcnVncyIgPSBjKCJNYWNyb3BoYWdlc2FudGltb255IiwgIk1hY3JvcGhhZ2Vzbm9uZSIpLAogICAgInU5MzdfZHJ1Z3MiID0gYygiVTkzN2FudGltb255IiwgIlU5Mzdub25lIikpCnU5Mzdfa2VlcGVycyA8LSBsaXN0KAogICAgInoyM25vc2JfdnNfdW5pbmYiID0gYygiaW5mejIzIiwgInVuaW5mbm9uZSIpLAogICAgInoyMm5vc2JfdnNfdW5pbmYiID0gYygiaW5mejIyIiwgInVuaW5mbm9uZSIpLAogICAgInoyM25vc2JfdnNfejIybm9zYiIgPSBjKCJpbmZ6MjMiLCAiaW5mejIyIiksCiAgICAiejIzc2JfdnNfejIyc2IiID0gYygiaW5mc2J6MjMiLCAiaW5mc2J6MjIiKSwKICAgICJ6MjNzYl92c196MjNub3NiIiA9IGMoImluZnNiejIzIiwgImluZnoyMyIpLAogICAgInoyMnNiX3ZzX3oyMm5vc2IiID0gYygiaW5mc2J6MjIiLCAiaW5mejIyIiksCiAgICAiejIzc2JfdnNfc2IiID0gYygiaW5mejIzIiwgInVuaW5mc2Jub25lIiksCiAgICAiejIyc2JfdnNfc2IiID0gYygiaW5mejIyIiwgInVuaW5mc2Jub25lIiksCiAgICAiejIzc2JfdnNfdW5pbmYiID0gYygiaW5mc2J6MjMiLCAidW5pbmZub25lIiksCiAgICAiejIyc2JfdnNfdW5pbmYiID0gYygiaW5mc2J6MjIiLCAidW5pbmZub25lIiksCiAgICAic2JfdnNfdW5pbmYiID0gYygidW5pbmZzYm5vbmUiLCAidW5pbmZub25lIikpCmBgYAoKIyMjIFByaW1hcnkgcXVlcmllcwoKVGhlcmUgaXMgYSBzZXJpZXMgb2YgaW5pdGlhbCBxdWVzdGlvbnMgd2hpY2ggbWFrZSBzb21lIHNlbnNlCnRvIG1lLCBidXQgdGhlc2UgZG8gbm90IG5lY2Vzc2FyaWx5IG1hdGNoIHRoZSBzZXQgb2YgcXVlc3Rpb25zIHdoaWNoCmFyZSBtb3N0IHByZXNzaW5nLiAgSSBhbSBob3BpbmcgdG8gcHVsbCBib3RoIG9mIHRoZXNlIHNldHMgb2YKcXVlcmllcyBpbiBvbmUuCgpCZWZvcmUgZXh0cmFjdGluZyB0aGVzZSBncm91cHMgb2YgcXVlcmllcywgbGV0IHVzIGludm9rZSB0aGUKYWxsX3BhaXJ3aXNlKCkgZnVuY3Rpb24gYW5kIGdldCBhbGwgb2YgdGhlIGxpa2VseSBjb250cmFzdHMgYWxvbmcgd2l0aApvbmUgb3IgbW9yZSBleHRyYXMgdGhhdCBtaWdodCBwcm92ZSB1c2VmdWwgKHRoZSAnZXh0cmEnIGFyZ3VtZW50KS4KCiMjIyBDb21iaW5lZCBVOTM3IGFuZCBNYWNyb3BoYWdlczogQ29tcGFyZSBkcnVnIGVmZmVjdHMKCldoZW4gd2UgaGF2ZSB0aGUgdTkzNyBjZWxscyBpbiB0aGUgc2FtZSBkYXRhc2V0IGFzIHRoZSBtYWNyb3BoYWdlcywKdGhhdCBwcm92aWRlcyBhbiBpbnRlcmVzdGluZyBvcHBvcnR1bml0eSB0byBzZWUgaWYgd2UgY2FuIG9ic2VydmUKZHJ1Zy1kZXBlbmRhbnQgZWZmZWN0cyB3aGljaCBhcmUgc2hhcmVkIGFjcm9zcyBib3RoIGNlbGwgdHlwZXMuCgpgYGB7ciBib3RoX3R5cGVzX2RydWd9CmRydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKGFsbF9odW1hbiwgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGRydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl9kcnVnX2tlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3RtcmMyX21hY3JvcGhhZ2VfZHJ1Z19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIENvbWJpbmVkIFU5MzcgYW5kIE1hY3JvcGhhZ2VzOiBjb21wYXJlIGNlbGwgdHlwZXMKClRoZXJlIGFyZSBhIGNvdXBsZSBvZiB3YXlzIG9uZSBtaWdodCB3YW50IHRvIGRpcmVjdGx5IGNvbXBhcmUgdGhlIHR3bwpjZWxsIHR5cGVzLgoKKiBHaXZlbiB0aGF0IHRoZSB2YXJpYW5jZSBiZXR3ZWVuIHRoZSB0d28gY2VsbHR5cGVzIGlzIHNvIGh1Z2UsIGp1c3QKICBjb21wYXJlIGFsbCBzYW1wbGVzLgoqIE9uZSBtaWdodCB3YW50IHRvIGNvbXBhcmUgdGhlbSB3aXRoIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3RzIG9mIGRydWcvenltb2RlbWUuCgpgYGB7ciBib3RoX3R5cGVzX2NvbXBhcmV9CnR5cGVfZGUgPC0gYWxsX3BhaXJ3aXNlKGFsbF9odW1hbl90eXBlcywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKdHlwZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHR5cGVfZGUsIGtlZXBlcnMgPSB0bXJjMl90eXBlX2tlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3RtcmMyX21hY3JvcGhhZ2VfdHlwZV9jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBDb21iaW5lZCBmYWN0b3JzIG9mIGludGVyZXN0OiBjZWxsdHlwZSt6eW1vZGVtZSwgY2VsbHR5cGUrZHJ1ZwoKR2l2ZW4gdGhlIGFib3ZlIGV4cGxpY2l0IGNvbXBhcmlzb24gb2YgYWxsIHNhbXBsZXMgY29tcHJpc2luZyB0aGUgdHdvCmNlbGwgdHlwZXMsIG5vdyBsZXQgdXMgbG9vayBhdCB0aGUgZHJ1ZyB0cmVhdG1lbnQrenltb2RlbWUgc3RhdHVzIHdpdGgKYWxsIHNhbXBsZXMsIG1hY3JvcGhhZ2VzIGFuZCBVOTM3LgoKYGBge3IgYWxsX3NhbXBsZXNfenltb190eXBlfQp0eXBlX3p5bW9fZGUgPC0gYWxsX3BhaXJ3aXNlKHR5cGVfenltbywgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKdHlwZV96eW1vX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdHlwZV96eW1vX2RlLCBrZWVwZXJzID0gdG1yYzJfdHlwZXp5bW9fa2VlcGVycywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvdG1yYzJfbWFjcm9waGFnZV90eXBlX3p5bW9fY29tcGFyaXNvbi12e3Zlcn0ueGxzeCIpKQoKdHlwZV9kcnVnX2RlIDwtIGFsbF9wYWlyd2lzZSh0eXBlX2RydWcsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnR5cGVfZHJ1Z190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHR5cGVfZHJ1Z19kZSwga2VlcGVycyA9IHRtcmMyX3R5cGVkcnVnX2tlZXBlcnMsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC90bXJjMl9tYWNyb3BoYWdlX3R5cGVfZHJ1Z19jb21wYXJpc29uLXZ7dmVyfS54bHN4IikpCmBgYAoKIyBJbmRpdmlkdWFsIGNlbGwgdHlwZXMKCkF0IHRoaXMgcG9pbnQsIEkgdGhpbmsgaXQgaXMgZmFpciB0byBzYXkgdGhhdCB0aGUgdHdvIGNlbGwgdHlwZXMgYXJlCnN1ZmZpY2llbnRseSBkaWZmZXJlbnQgdGhhdCB0aGV5IGRvIG5vdCByZWFsbHkgYmVsb25nIHRvZ2V0aGVyIGluIGEKc2luZ2xlIGFuYWx5c2lzLgoKIyMgZHJ1ZyBvciBzdHJhaW4gZWZmZWN0cywgc2luZ2xlIGNlbGwgdHlwZQoKT25lIG9mIHRoZSBxdWVyaWVzIE5hamliIGFza2VkIHdoaWNoIEkgdGhpbmsgSSBtaXNpbnRlcnByZXRlZCB3YXMgdG8KbG9vayBhdCBkcnVnIGFuZC9vciBzdHJhaW4gZWZmZWN0cy4gIE15IGludGVycHJldGF0aW9uIGlzIHNvbWV3aGVyZQpiZWxvdyBhbmQgd2FzIG5vdCB3aGF0IGhlIHdhcyBsb29raW5nIGZvci4gIEluc3RlYWQsIGhlIHdhcyBsb29raW5nIHRvCnNlZSBhbGwobWFjcm9waGFnZSkgZHJ1Zy9ub2RydWcgYW5kIGFsbChtYWNyb3BoYWdlKSB6MjMvejIyIGFuZApjb21wYXJlIHRoZW0gdG8gZWFjaCBvdGhlci4gIEl0IG1heSBiZSB0aGF0IHRoaXMgaXMgc3RpbGwgYSB3cm9uZwppbnRlcnByZXRhdGlvbiwgaWYgc28gdGhlIG1vc3QgbGlrZWx5IGNvbXBhcmlzb24gaXMgZWl0aGVyOgoKKiAgKHoyM2RydWcvejIyZHJ1ZykgLyAoejIzbm9kcnVnL3oyMm5vZHJ1ZyksIG9yIHBlcmhhcHMKKiAgKHoyM2RydWcvejIzbm9kcnVnKSAvICh6MjJkcnVnL3oyMm5vZHJ1ZyksCgpJIGFtIG5vdCBzdXJlIHRob3NlIGNvbmZ1c2UgbWUsIGFuZCBhdCBsZWFzdCBvbmUgb2YgdGhlbSBpcyBiZWxvdwoKIyMjIE1hY3JvcGhhZ2VzCgpgYGB7ciBoc19tYWNyX2RydWdfc3RyYWlufQpoc19tYWNyX2RydWdfZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGhzX21hY3IsIGZhY3QgPSAiZHJ1ZyIpCgpoc19tYWNyX3N0cmFpbl9leHB0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoaHNfbWFjciwgZmFjdCA9ICJtYWNyb3BoYWdlenltb2RlbWUiKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQgPSAibWFjcm9waGFnZXp5bW9kZW1lICE9ICdub25lJyIpCgpoc19tYWNyX2RydWdfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX21hY3JfZHJ1Z19leHB0LCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiKQpoc19tYWNyX2RydWdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBoc19tYWNyX2RydWdfZGUsIGtlZXBlcnMgPSB0bXJjMl9kcnVnX2tlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3RtcmMyX21hY3JvcGhhZ2Vfb25seWRydWdfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9kcnVnX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgaHNfbWFjcl9kcnVnX3RhYmxlKQpoc19tYWNyX3N0cmFpbl9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbWFjcl9zdHJhaW5fZXhwdCwgZmlsdGVyID0gVFJVRSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIikKaHNfbWFjcl9zdHJhaW5fdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBoc19tYWNyX3N0cmFpbl9kZSwga2VlcGVycyA9IHRtcmMyX3N0cmFpbl9rZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC90bXJjMl9tYWNyb3BoYWdlX29ubHlzdHJhaW5fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKaHNfbWFjcl9zdHJhaW5fc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBoc19tYWNyX3N0cmFpbl90YWJsZSkKZHJ1Z19zdHJhaW5fY29tcF9kZiA8LSBtZXJnZShoc19tYWNyX2RydWdfdGFibGVbWyJkYXRhIl1dW1siZHJ1ZyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19tYWNyX3N0cmFpbl90YWJsZVtbImRhdGEiXV1bWyJzdHJhaW4iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicm93Lm5hbWVzIikKZHJ1Z19zdHJhaW5fY29tcF9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZHJ1Z19zdHJhaW5fY29tcF9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKIyMgQ29udHJhc3RzOiBhbnRpbW9ueS9ub25lLCB6MjMvejIyOyB4LWF4aXM6IGRydWcsIHktYXhpczogc3RyYWluCiMjIHRvcCBsZWZ0OiBoaWdoZXIgbm8gZHJ1ZywgejIzOyB0b3AgcmlnaHQ6IGhpZ2hlciBkcnVnIHoyMwojIyBib3R0b20gbGVmdDogaGlnaGVyIG5vIGRydWcsIHoyMjsgYm90dG9tIHJpZ2h0OiBoaWdoZXIgZHJ1ZyB6MjIKZHJ1Z19zdHJhaW5fY29tcF9wbG90JHNjYXR0ZXIKCmxpYnJhcnkoVXBTZXRSKQpoaWdoZXJfZHJ1ZyA8LSBoc19tYWNyX2RydWdfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCmhpZ2hlcl9ub2RydWcgPC0gaHNfbWFjcl9kcnVnX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KaGlnaGVyX3oyMyA8LSBoc19tYWNyX3N0cmFpbl9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dCmhpZ2hlcl96MjIgPC0gaHNfbWFjcl9zdHJhaW5fc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCnN1bShyb3duYW1lcyhoaWdoZXJfZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIzKSkKc3VtKHJvd25hbWVzKGhpZ2hlcl9kcnVnKSAlaW4lIHJvd25hbWVzKGhpZ2hlcl96MjIpKQpzdW0ocm93bmFtZXMoaGlnaGVyX25vZHJ1ZykgJWluJSByb3duYW1lcyhoaWdoZXJfejIzKSkKc3VtKHJvd25hbWVzKGhpZ2hlcl9ub2RydWcpICVpbiUgcm93bmFtZXMoaGlnaGVyX3oyMikpCgpkcnVnX3oyM19sc3QgPC0gbGlzdCgiZHJ1ZyIgPSByb3duYW1lcyhoaWdoZXJfZHJ1ZyksCiAgICAgICAgICAgICAgICAgICAgICJ6MjMiID0gcm93bmFtZXMoaGlnaGVyX3oyMykpCmhpZ2hlcl9kcnVnX3oyMyA8LSB1cHNldChVcFNldFI6OmZyb21MaXN0KGRydWdfejIzX2xzdCksIHRleHQuc2NhbGUgPSAyKQpoaWdoZXJfZHJ1Z196MjMKCnNoYXJlZF9nZW5lX2xzdCA8LSBvdmVybGFwX2dyb3VwcyhkcnVnX3oyM19sc3QpCnNoYXJlZF9nZW5lcyA8LSBhdHRyKHNoYXJlZF9nZW5lX2xzdCwgImVsZW1lbnRzIilbc2hhcmVkX2dlbmVfbHN0W1siZHJ1Zzp6MjMiXV1dCnNoYXJlZF9kcnVnX3oyM19ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0Kc2hhcmVkX2RydWdfejIzX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQoKZHJ1Z196MjJfbHN0IDwtIGxpc3QoImRydWciID0gcm93bmFtZXMoaGlnaGVyX2RydWcpLAogICAgICAgICAgICAgICAgICAgICAiejIyIiA9IHJvd25hbWVzKGhpZ2hlcl96MjIpKQpoaWdoZXJfZHJ1Z196MjIgPC0gdXBzZXQoVXBTZXRSOjpmcm9tTGlzdChkcnVnX3oyMl9sc3QpLCB0ZXh0LnNjYWxlID0gMikKaGlnaGVyX2RydWdfejIyCgpzaGFyZWRfZ2VuZV9sc3QgPC0gb3ZlcmxhcF9ncm91cHMoZHJ1Z196MjJfbHN0KQpzaGFyZWRfZ2VuZXMgPC0gYXR0cihzaGFyZWRfZ2VuZV9sc3QsICJlbGVtZW50cyIpW3NoYXJlZF9nZW5lX2xzdFtbImRydWc6ejIyIl1dXQpzaGFyZWRfZHJ1Z196MjJfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9kcnVnX3oyMl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCmBgYAoKIyMgT3VyIG1haW4gcXVlc3Rpb24gb2YgaW50ZXJlc3QKClRoZSBkYXRhIHN0cnVjdHVyZSBoc19tYWNyIGNvbnRhaW5zIG91ciBwcmltYXJ5IG1hY3JvcGhhZ2VzLCB3aGljaAphcmUsIGFzIHNob3duIGFib3ZlLCB0aGUgZGF0YSB3ZSBjYW4gcmVhbGx5IHNpbmsgb3VyIHRlZXRoIGludG8uCgpgYGB7ciBoc19kZX0KaHNfbWFjcl9kZSA8LSBhbGxfcGFpcndpc2UoCiAgICBoc19tYWNyLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLAogICAgZmlsdGVyID0gVFJVRSwKICAgIGV4dHJhX2NvbnRyYXN0cyA9IHRtcmMyX2h1bWFuX2V4dHJhKQpoc19tYWNyX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgaHNfbWFjcl9kZSwKICAgIGtlZXBlcnMgPSB0bXJjMl9odW1hbl9rZWVwZXJzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9oc19tYWNyX2RydWdfenltb190YWJsZS12e3Zlcn0ueGxzeCIpKQpoc19tYWNyX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgaHNfbWFjcl90YWJsZSwKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvaHNfbWFjcl9kcnVnX3p5bW9fc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIE91ciBtYWluIHF1ZXN0aW9ucyBpbiBVOTM3CgpgYGB7ciBoc191OTM3X2RlfQp1OTM3X2RlIDwtIGFsbF9wYWlyd2lzZSh1OTM3X2V4cHQsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCnU5MzdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICB1OTM3X2RlLAogICAga2VlcGVycyA9IHU5Mzdfa2VlcGVycywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvdTkzN19kcnVnX3p5bW9fdGFibGUtdnt2ZXJ9Lnhsc3giKSkKdTkzN19zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHU5MzdfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3U5MzdfZHJ1Z196eW1vX3NpZy12e3Zlcn0ueGxzeCIpKQpgYGAKCiMjIyMgQ29tcGFyZSAobm8pU2IgejIuMy96Mi4yIHRyZWF0bWVudHMgYW1vbmcgbWFjcm9waGFnZXMKCmBgYHtyIGNvbXBhcmVfZHJ1Z196MjMyMn0KdXBzZXRfcGxvdHNfaHNfbWFjciA8LSB1cHNldHJfc2lnKAogICAgaHNfbWFjcl9zaWcsIGJvdGggPSBUUlVFLAogICAgY29udHJhc3RzID0gYygiejIzc2JfdnNfejIyc2IiLCAiejIzbm9zYl92c196MjJub3NiIikpCnVwc2V0X3Bsb3RzX2hzX21hY3JbWyJib3RoIl1dCmdyb3VwcyA8LSB1cHNldF9wbG90c19oc19tYWNyW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzJdXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCmxlbmd0aChzaGFyZWRfZ2VuZXMpCgpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIkJQIl1dCnNoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KCmRydWdfZ2VuZXMgPC0gYXR0cihncm91cHMsICJlbGVtZW50cyIpW2dyb3Vwc1tbInoyM3NiX3ZzX3oyMnNiIl1dXSAlPiUKICAgIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpkcnVnb25seV9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGRydWdfZ2VuZXMpCmRydWdvbmx5X2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siQlAiXV0KYGBgCgpJIHdhbnQgdG8gdHJ5IHNvbWV0aGluZywgZGlyZWN0bHkgaW5jbHVkZSB0aGUgdTkzNyBkYXRhIGluIHRoaXMuLi4KCmBgYHtyIGFkZF91OTM3fQpib3RoX3NpZyA8LSBoc19tYWNyX3NpZwpuYW1lcyhib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dKSA8LSBwYXN0ZTAoIm1hY3JfIiwgbmFtZXMoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSkpCm5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXSkgPC0gcGFzdGUwKCJtYWNyXyIsIG5hbWVzKGJvdGhfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXSkpCnU5MzdfZGVzZXEgPC0gdTkzN19zaWdbWyJkZXNlcSJdXQpuYW1lcyh1OTM3X2Rlc2VxW1sidXBzIl1dKSA8LSBwYXN0ZTAoInU5MzdfIiwgbmFtZXModTkzN19kZXNlcVtbInVwcyJdXSkpCm5hbWVzKHU5MzdfZGVzZXFbWyJkb3ducyJdXSkgPC0gcGFzdGUwKCJ1OTM3XyIsIG5hbWVzKHU5MzdfZGVzZXFbWyJkb3ducyJdXSkpCmJvdGhfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV0gPC0gYyhib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dLCB1OTM3X2Rlc2VxW1sidXBzIl1dKQpib3RoX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV0gPC0gYyhib3RoX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dLCB1OTM3X2Rlc2VxW1siZG93bnMiXV0pCnN1bW1hcnkoYm90aF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXSkKCnVwc2V0X3Bsb3RzX2JvdGggPC0gdXBzZXRyX3NpZygKICAgIGJvdGhfc2lnLCBib3RoPVRSVUUsCiAgICBjb250cmFzdHM9YygibWFjcl96MjNzYl92c196MjJzYiIsICJtYWNyX3oyM25vc2JfdnNfejIybm9zYiIsCiAgICAgICAgICAgICAgICAidTkzN196MjNzYl92c196MjJzYiIsICJ1OTM3X3oyM25vc2JfdnNfejIybm9zYiIpKQp1cHNldF9wbG90c19ib3RoJGJvdGgKYGBgCgojIyMjIENvbXBhcmUgREUgcmVzdWx0cyBmcm9tIG1hY3JvcGhhZ2VzIGFuZCBVOTM3IHNhbXBsZXMKCkxvb2tpbmcgYSBiaXQgbW9yZSBjbG9zZWx5IGF0IHRoZXNlLCBJIHRoaW5rIHRoZSB1OTM3IGRhdGEgaXMgdG9vCnNwYXJzZSB0byBlZmZlY3RpdmVseSBjb21wYXJlLgoKYGBge3IgY29tcGFyZV9kZV91OTM3X21hY3JvfQptYWNyX3U5MzdfY29tcGFyaXNvbiA8LSBjb21wYXJlX2RlX3Jlc3VsdHMoaHNfbWFjcl90YWJsZSwgdTkzN190YWJsZSkKbWFjcl91OTM3X2NvbXBhcmlzb24kbGZjX2hlYXQKCm1hY3JfdTkzN192ZW5ucyA8LSBjb21wYXJlX3NpZ25pZmljYW50X2NvbnRyYXN0cyhoc19tYWNyX3NpZywgc2Vjb25kX3NpZ190YWJsZXMgPSB1OTM3X3NpZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9ICJ6MjNzYl92c196MjNub3NiIikKbWFjcl91OTM3X3Zlbm5zJHVwX3Bsb3QKbWFjcl91OTM3X3Zlbm5zJGRvd25fcGxvdAoKbWFjcl91OTM3X3Zlbm5zX3YyIDwtIGNvbXBhcmVfc2lnbmlmaWNhbnRfY29udHJhc3RzKGhzX21hY3Jfc2lnLCBzZWNvbmRfc2lnX3RhYmxlcyA9IHU5Mzdfc2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gInoyMnNiX3ZzX3oyMm5vc2IiKQptYWNyX3U5MzdfdmVubnNfdjIkdXBfcGxvdAptYWNyX3U5MzdfdmVubnNfdjIkZG93bl9wbG90CgptYWNyX3U5MzdfdmVubnNfdjMgPC0gY29tcGFyZV9zaWduaWZpY2FudF9jb250cmFzdHMoaHNfbWFjcl9zaWcsIHNlY29uZF9zaWdfdGFibGVzID0gdTkzN19zaWcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cmFzdHMgPSAic2JfdnNfdW5pbmYiKQptYWNyX3U5MzdfdmVubnNfdjMkdXBfcGxvdAptYWNyX3U5MzdfdmVubnNfdjMkZG93bl9wbG90CmBgYAoKIyMjIENvbXBhcmUgbWFjcm9waGFnZS91OTM3IHdpdGggcmVzcGVjdCB0byB6Mi4zL3oyLjIKCmBgYHtyIG1hY3JfdTkzN196MjN6MjJ9CmNvbXBhcmlzb25fZGYgPC0gbWVyZ2UoaHNfbWFjcl90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjJzYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICB1OTM3X3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInJvdy5uYW1lcyIpCm1hY3J1OTM3X3oyM3oyMl9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoY29tcGFyaXNvbl9kZlssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKbWFjcnU5MzdfejIzejIyX3Bsb3Qkc2NhdHRlcgoKY29tcGFyaXNvbl9kZiA8LSBtZXJnZShoc19tYWNyX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICB1OTM3X3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyb3cubmFtZXMiKQptYWNydTkzN196MjN6MjJfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGNvbXBhcmlzb25fZGZbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCm1hY3J1OTM3X3oyM3oyMl9wbG90JHNjYXR0ZXIKYGBgCgojIyMjIEFkZCBkb25vciB0byB0aGUgY29udHJhc3RzLCBubyBzdmEKCmBgYHtyIG5vcG93ZXJfbm9zdmF9Cm5vX3Bvd2VyX2ZhY3QgPC0gcGFzdGUwKHBEYXRhKGhzX21hY3IpW1siZG9ub3IiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoaHNfbWFjcilbWyJjb25kaXRpb24iXV0pCmhzX25vcG93ZXIgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhoc19tYWNyLCBmYWN0ID0gbm9fcG93ZXJfZmFjdCkKaHNfbm9wb3dlciA8LSBzdWJzZXRfZXhwdChoc19ub3Bvd2VyLCBzdWJzZXQ9Im1hY3JvcGhhZ2V6eW1vZGVtZSE9J25vbmUnIikKaHNfbm9wb3dlcl9ub3N2YV9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbm9wb3dlciwgbW9kZWxfYmF0Y2ggPSBGQUxTRSwgZmlsdGVyID0gVFJVRSkKbm9wb3dlcl9rZWVwZXJzIDwtIGxpc3QoCiAgICAiZDAxX3p5bW8iID0gYygiZDAxaW5mejIzIiwgImQwMWluZnoyMiIpLAogICAgImQwMV9zYnp5bW8iID0gYygiZDAxaW5mc2J6MjMiLCAiZDAxaW5mc2J6MjIiKSwKICAgICJkMDJfenltbyIgPSBjKCJkMDJpbmZ6MjMiLCAiZDAyaW5mejIyIiksCiAgICAiZDAyX3NienltbyIgPSBjKCJkMDJpbmZzYnoyMyIsICJkMDJpbmZzYnoyMiIpLAogICAgImQwOV96eW1vIiA9IGMoImQwOWluZnoyMyIsICJkMDlpbmZ6MjIiKSwKICAgICJkMDlfc2J6eW1vIiA9IGMoImQwOWluZnNiejIzIiwgImQwOWluZnNiejIyIiksCiAgICAiZDgxX3p5bW8iID0gYygiZDgxaW5mejIzIiwgImQ4MWluZnoyMiIpLAogICAgImQ4MV9zYnp5bW8iID0gYygiZDgxaW5mc2J6MjMiLCAiZDgxaW5mc2J6MjIiKSkKaHNfbm9wb3dlcl9ub3N2YV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGhzX25vcG93ZXJfbm9zdmFfZGUsIGtlZXBlcnMgPSBub3Bvd2VyX2tlZXBlcnMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2hzX25vcG93ZXJfdGFibGUtdnt2ZXJ9Lnhsc3giKSkKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXh0cmFfY29udHJhc3RzID0gZXh0cmEpCmhzX25vcG93ZXJfbm9zdmFfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9oc19ub3Bvd2VyX25vc3ZhX3NpZy12e3Zlcn0ueGxzeCIpKQoKZDAxZDAyX3p5bW9fbm9zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgIGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDAyX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQwMl96eW1vX25vc3ZhX2NvbXBbLCBjKCJkZXNlcV9sb2dmYy54IiwgImRlc2VxX2xvZ2ZjLnkiKV0pCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCRzY2F0dGVyCmQwMTAyX3p5bW9fbm9zdmFfcGxvdCRjb3JyZWxhdGlvbgpkMDEwMl96eW1vX25vc3ZhX3Bsb3QkbG1fcnNxCgpkMDlkODFfenltb19ub3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfbm9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDA5X3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZDA5ODFfenltb19ub3N2YV9wbG90IDwtIHBsb3RfbGluZWFyX3NjYXR0ZXIoZDA5ZDgxX3p5bW9fbm9zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDA5ODFfenltb19ub3N2YV9wbG90JHNjYXR0ZXIKZDA5ODFfenltb19ub3N2YV9wbG90JGNvcnJlbGF0aW9uCmQwOTgxX3p5bW9fbm9zdmFfcGxvdCRsbV9yc3EKCmQwMWQ4MV96eW1vX25vc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9ub3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX25vc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQ4MV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSJyb3cubmFtZXMiKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19ub3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDE4MV96eW1vX25vc3ZhX3Bsb3Qkc2NhdHRlcgpkMDE4MV96eW1vX25vc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDAxODFfenltb19ub3N2YV9wbG90JGxtX3JzcQoKdXBzZXRfcGxvdHNfbm9zdmEgPC0gdXBzZXRyX3NpZyhoc19ub3Bvd2VyX25vc3ZhX3NpZywgYm90aD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cz1jKCJkMDFfenltbyIsICJkMDJfenltbyIsICJkMDlfenltbyIsICJkODFfenltbyIpKQp1cHNldF9wbG90c19ub3N2YSR1cAp1cHNldF9wbG90c19ub3N2YSRkb3duCnVwc2V0X3Bsb3RzX25vc3ZhJGJvdGgKIyMgVGhlIDd0aCBlbGVtZW50IGluIHRoZSBib3RoIGdyb3VwcyBsaXN0IGlzIHRoZSBzZXQgc2hhcmVkIGFtb25nIGFsbCBkb25vcnMuCiMjIEkgZG9uJ3QgZmVlbCBsaWtlIHdyaXRpbmcgb3V0IHg6eTp6OmEKZ3JvdXBzIDwtIHVwc2V0X3Bsb3RzX25vc3ZhW1siYm90aF9ncm91cHMiXV0Kc2hhcmVkX2dlbmVzIDwtIGF0dHIoZ3JvdXBzLCAiZWxlbWVudHMiKVtncm91cHNbWzddXV0gJT4lCiAgZ3N1YihwYXR0ZXJuID0gIl5nZW5lOiIsIHJlcGxhY2VtZW50ID0gIiIpCnNoYXJlZF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNoYXJlZF9nZW5lcykKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRNRgpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJEJQCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkUkVBQwpzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJFdQCmBgYAoKIyMjIyBBZGQgZG9ub3IgdG8gdGhlIGNvbnRyYXN0cywgc3ZhCgpgYGB7ciBkb25vcl9kcnVnX3p5bW9fZXRjfQpoc19ub3Bvd2VyX3N2YV9kZSA8LSBhbGxfcGFpcndpc2UoaHNfbm9wb3dlciwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSkKbm9wb3dlcl9rZWVwZXJzIDwtIGxpc3QoCiAgICAiZDAxX3p5bW8iID0gYygiZDAxaW5mejIzIiwgImQwMWluZnoyMiIpLAogICAgImQwMV9zYnp5bW8iID0gYygiZDAxaW5mc2J6MjMiLCAiZDAxaW5mc2J6MjIiKSwKICAgICJkMDJfenltbyIgPSBjKCJkMDJpbmZ6MjMiLCAiZDAyaW5mejIyIiksCiAgICAiZDAyX3NienltbyIgPSBjKCJkMDJpbmZzYnoyMyIsICJkMDJpbmZzYnoyMiIpLAogICAgImQwOV96eW1vIiA9IGMoImQwOWluZnoyMyIsICJkMDlpbmZ6MjIiKSwKICAgICJkMDlfc2J6eW1vIiA9IGMoImQwOWluZnNiejIzIiwgImQwOWluZnNiejIyIiksCiAgICAiZDgxX3p5bW8iID0gYygiZDgxaW5mejIzIiwgImQ4MWluZnoyMiIpLAogICAgImQ4MV9zYnp5bW8iID0gYygiZDgxaW5mc2J6MjMiLCAiZDgxaW5mc2J6MjIiKSkKaHNfbm9wb3dlcl9zdmFfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBoc19ub3Bvd2VyX3N2YV9kZSwga2VlcGVycyA9IG5vcG93ZXJfa2VlcGVycywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvaHNfbm9wb3dlcl90YWJsZS12e3Zlcn0ueGxzeCIpKQojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYV9jb250cmFzdHMgPSBleHRyYSkKaHNfbm9wb3dlcl9zdmFfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBoc19ub3Bvd2VyX3N2YV90YWJsZSwKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvaHNfbm9wb3dlcl9zdmFfc2lnLXZ7dmVyfS54bHN4IikpCgpkMDFkMDJfenltb19zdmFfY29tcCA8LSBtZXJnZShoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkMDJfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICBieT0icm93Lm5hbWVzIikKZDAxMDJfenltb19zdmFfcGxvdCA8LSBwbG90X2xpbmVhcl9zY2F0dGVyKGQwMWQwMl96eW1vX3N2YV9jb21wWywgYygiZGVzZXFfbG9nZmMueCIsICJkZXNlcV9sb2dmYy55IildKQpkMDEwMl96eW1vX3N2YV9wbG90JHNjYXR0ZXIKZDAxMDJfenltb19zdmFfcGxvdCRjb3JyZWxhdGlvbgpkMDEwMl96eW1vX3N2YV9wbG90JGxtX3JzcQoKZDA5ZDgxX3p5bW9fc3ZhX2NvbXAgPC0gbWVyZ2UoaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDA5X3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgaHNfbm9wb3dlcl9zdmFfdGFibGVbWyJkYXRhIl1dW1siZDgxX3p5bW8iXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwOTgxX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDlkODFfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDA5ODFfenltb19zdmFfcGxvdCRzY2F0dGVyCmQwOTgxX3p5bW9fc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDA5ODFfenltb19zdmFfcGxvdCRsbV9yc3EKCmQwMWQ4MV96eW1vX3N2YV9jb21wIDwtIG1lcmdlKGhzX25vcG93ZXJfc3ZhX3RhYmxlW1siZGF0YSJdXVtbImQwMV96eW1vIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoc19ub3Bvd2VyX3N2YV90YWJsZVtbImRhdGEiXV1bWyJkODFfenltbyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCmQwMTgxX3p5bW9fc3ZhX3Bsb3QgPC0gcGxvdF9saW5lYXJfc2NhdHRlcihkMDFkODFfenltb19zdmFfY29tcFssIGMoImRlc2VxX2xvZ2ZjLngiLCAiZGVzZXFfbG9nZmMueSIpXSkKZDAxODFfenltb19zdmFfcGxvdCRzY2F0dGVyCmQwMTgxX3p5bW9fc3ZhX3Bsb3QkY29ycmVsYXRpb24KZDAxODFfenltb19zdmFfcGxvdCRsbV9yc3EKCnVwc2V0X3Bsb3RzX3N2YSA8LSB1cHNldHJfc2lnKGhzX25vcG93ZXJfc3ZhX3NpZywgYm90aD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cz1jKCJkMDFfenltbyIsICJkMDJfenltbyIsICJkMDlfenltbyIsICJkODFfenltbyIpKQp1cHNldF9wbG90c19zdmEkdXAKdXBzZXRfcGxvdHNfc3ZhJGRvd24KdXBzZXRfcGxvdHNfc3ZhJGJvdGgKIyMgVGhlIDd0aCBlbGVtZW50IGluIHRoZSBib3RoIGdyb3VwcyBsaXN0IGlzIHRoZSBzZXQgc2hhcmVkIGFtb25nIGFsbCBkb25vcnMuCiMjIEkgZG9uJ3QgZmVlbCBsaWtlIHdyaXRpbmcgb3V0IHg6eTp6OmEKZ3JvdXBzIDwtIHVwc2V0X3Bsb3RzX3N2YVtbImJvdGhfZ3JvdXBzIl1dCnNoYXJlZF9nZW5lcyA8LSBhdHRyKGdyb3VwcywgImVsZW1lbnRzIilbZ3JvdXBzW1s3XV1dICU+JQogIGdzdWIocGF0dGVybiA9ICJeZ2VuZToiLCByZXBsYWNlbWVudCA9ICIiKQpzaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihzaGFyZWRfZ2VuZXMpCnNoYXJlZF9ncCRwdmFsdWVfcGxvdHMkTUYKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRCUApzaGFyZWRfZ3AkcHZhbHVlX3Bsb3RzJFJFQUMKc2hhcmVkX2dwJHB2YWx1ZV9wbG90cyRXUApgYGAKCiMjIyBEb25vciBjb21wYXJpc29uCgpgYGB7ciBkb25vcl9kZX0KZG9ub3JfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX2Rvbm9ycywgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQpkb25vcl90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGRvbm9yX2RlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvZG9ub3JfdGFibGVzLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBQcmltYXJ5IHF1ZXJ5IGNvbnRyYXN0cwoKVGhlIGZpbmFsIGNvbnRyYXN0IGluIHRoaXMgbGlzdCBpcyBpbnRlcmVzdGluZyBiZWNhdXNlIGl0IGRlcGVuZHMgb24KdGhlIGV4dHJhIGNvbnRyYXN0cyBhcHBsaWVkIHRvIHRoZSBhbGxfcGFpcndpc2UoKSBhYm92ZS4gIEluIG15IHdheSBvZgp0aGlua2luZywgdGhlIHByaW1hcnkgY29tcGFyaXNvbnMgdG8gY29uc2lkZXIgYXJlIGVpdGhlciBjcm9zcy1kcnVnIG9yCmNyb3NzLXN0cmFpbiwgYnV0IG5vdCBib3RoLiAgSG93ZXZlciBJIHRoaW5rIGluIGF0IGxlYXN0IGEgZmV3Cmluc3RhbmNlcyBPbGdhIGlzIGludGVyZXN0ZWQgaW4gc3RyYWluK2RydWcgLyB1bmluZmVjdGVkK25vZHJ1Zy4KCiMjIyMgV3JpdGUgY29udHJhc3QgcmVzdWx0cwoKTm93IGxldCB1cyB3cml0ZSBvdXQgdGhlIHhsc3ggZmlsZSBjb250YWluaW5nIHRoZSBhYm92ZSBjb250cmFzdHMuClRoZSBmaWxlIHdpdGggdGhlIHN1ZmZpeCBfdGFibGUtdmVyc2lvbiB3aWxsIHRoZXJlZm9yZSBjb250YWluIGFsbApnZW5lcyBhbmQgdGhlIGZpbGUgd2l0aCB0aGUgc3VmZml4IF9zaWctdmVyc2lvbiB3aWxsIGNvbnRhaW4gb25seQp0aG9zZSBkZWVtZWQgc2lnbmlmaWNhbnQgdmlhIG91ciBkZWZhdWx0IGNyaXRlcmlhIG9mIERFU2VxMiB8bG9nRkN8ID49IDEuMAphbmQgYWRqdXN0ZWQgcC12YWx1ZSA8PSAwLjA1LgoKYGBge3IgbWFrZV90YWJsZXNfdG1yYzJ9CmhzX21hY3JfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBoc19tYWNyX2RlLAogICAga2VlcGVycyA9IHRtcmMyX2h1bWFuX2tlZXBlcnMsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9tYWNyb3BoYWdlX2h1bWFuX3RhYmxlLXZ7dmVyfS54bHN4IikpCmhzX21hY3Jfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBoc19tYWNyX3RhYmxlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9odW1hbl9zaWctdnt2ZXJ9Lnhsc3giKSkKCnU5MzdfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICB1OTM3X2RlLAogICAga2VlcGVycyA9IHRtcmMyX2h1bWFuX2tlZXBlcnMsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC91OTM3X2h1bWFuX3RhYmxlLXZ7dmVyfS54bHN4IikpCnU5Mzdfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICB1OTM3X3RhYmxlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvdTkzN19odW1hbl9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIE92ZXIgcmVwcmVzZW50YXRpb24gc2VhcmNoZXMKCkkgZGVjaWRlZCB0byBtYWtlIG9uZSBpbml0aWFsbHkgc21hbGwsIGJ1dCBJIHRoaW5rIHF1aWNrbHkgYmlnIGNoYW5nZQp0byB0aGUgb3JnYW5pemF0aW9uIG9mIHRoaXMgZG9jdW1lbnQ6ICBJIGFtIG1vdmluZyB0aGUgR1NFQSBzZWFyY2hlcwp1cCB0byBpbW1lZGlhdGVseSBhZnRlciB0aGUgREUuICBJIHdpbGwgdGhlbiBtb3ZlIHRoZSBwbG90cyBvZiB0aGUKZ3Byb2ZpbGVyIHJlc3VsdHMgdG8gaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIHZhcmlvdXMgdm9sY2FubyBwbG90cyBzbwp0aGF0IGl0IGlzIGVhc2llciB0byBpbnRlcnByZXQgdGhlbS4KCmBgYHtyIG92ZXJfcmVwcmVzZW50X2RhdGF9CmFsbF9ncCA8LSBhbGxfZ3Byb2ZpbGVyKGhzX21hY3Jfc2lnKQpgYGAKCiMgUGxvdCBjb250cmFzdHMgb2YgaW50ZXJlc3QKCk9uZSBzdWdnZXN0aW9uIEkgcmVjZWl2ZWQgcmVjZW50bHkgd2FzIHRvIHNldCB0aGUgYXhlcyBmb3IgdGhlc2UKdm9sY2FubyBwbG90cyB0byBiZSBzdGF0aWMgcmF0aGVyIHRoYW4gbGV0IGdncGxvdCBjaG9vc2UgaXRzIG93bi4gIEkKYW0gYXNzdW1pbmcgdGhpcyBpcyBvbmx5IHJlbGV2YW50IGZvciBwYWlycyBvZiBjb250cmFzdHMsIGJ1dCB0aGF0Cm1pZ2h0IG5vdCBiZSB0cnVlLgoKIyMgSW5kaXZpZHVhbCB6eW1vZGVtZXMgdnMuIHVuaW5mZWN0ZWQKCmBgYHtyIGhzX21hY3JvcGhhZ2Vfc2lnX2dlbmVzXzIzMjJ2c3VuaW5mfQp6MjNub3NiX3ZzX3VuaW5mX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM25vc2JfdnNfdW5pbmYiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCgpwbG90bHk6OmdncGxvdGx5KHoyM25vc2JfdnNfdW5pbmZfdm9sY2FubyRwbG90KQp6MjJub3NiX3ZzX3VuaW5mX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyMm5vc2JfdnNfdW5pbmYiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIybm9zYl92c191bmluZl92b2xjYW5vJHBsb3QpCmBgYAoKIyMjIFp5bW9kZW1lIDIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQKCmBgYHtyIHp5bW8yM192c191bmluZn0KejIzbm9zYl92c191bmluZl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTEwLCAyNSkgKwogIHlsaW0oMCwgNDApCgpwcChmaWxlPSJpbWFnZXMvejIzX3VuaW5mX3JlYWN0b21lX3VwLnBuZyIsIGltYWdlPWFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3VuaW5mX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzbm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM25vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCmBgYHtyIHoyMm5vc2JfdnNfdW5pbmZfcGxvdHN9CnoyMm5vc2JfdnNfdW5pbmZfdm9sY2FubyRwbG90ICsKICB4bGltKC0xMCwgMjUpICsKICB5bGltKDAsIDQwKQoKcHAoZmlsZT0iaW1hZ2VzL3oyMl91bmluZl9yZWFjdG9tZV91cC5wbmciLCBpbWFnZT1hbGxfZ3BbWyJ6MjJub3NiX3ZzX3VuaW5mX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwgaGVpZ2h0PTEyLCB3aWR0aD05KQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgoKYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjIgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIybm9zYl92c191bmluZl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4yIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMm5vc2JfdnNfdW5pbmZfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCkNoZWNrIHRoYXQgbXkgcGVyY2VwdGlvbiBvZiB0aGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IHVwL2Rvd24gZ2VuZXMKbWF0Y2hlcyB3aGF0IHRoZSB0YWJsZS92ZW5uIHNheXMuCgpgYGB7ciBjaGVja19zaWdfdmVubjAxfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c191bmluZiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c191bmluZiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvejIzX3ZzX3VuaW5mX3Zlbm5fdXAucG5nIikKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKIyMgSSBzZWUgOTEwIHoyM3NiL3VuaW5mIGFuZCA2NzAgbm8gejIzbm9zYi91bmluZiBnZW5lcyBpbiB0aGUgdmVubiBkaWFncmFtLgpsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMCJdXSkgKyBsZW5ndGgoc2hhcmVkQEludGVyc2VjdGlvblNldHNbWyIxMSJdXSkKZGltKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c191bmluZiJdXSkKCnNoYXJlZCA8LSBWZW5uZXJhYmxlOjpWZW5uKGxpc3QoImRydWciID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3VuaW5mIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjJub3NiX3ZzX3VuaW5mIl1dKSkpCnBwKGZpbGU9ImltYWdlcy96MjJfdnNfdW5pbmZfdmVubl91cC5wbmciKQpWZW5uZXJhYmxlOjpwbG90KHNoYXJlZCkKZGV2Lm9mZigpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQoKbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTAiXV0pICsgbGVuZ3RoKHNoYXJlZEBJbnRlcnNlY3Rpb25TZXRzW1siMTEiXV0pCmRpbShoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyc2JfdnNfdW5pbmYiXV0pCmBgYAoKKk5vdGUgdG8gc2VsZio6IFRoZXJlIGlzIGFuIGVycm9yIGluIG15IHZvbGNhbm8gcGxvdCBjb2RlIHdoaWNoIHRha2VzCmVmZmVjdCB3aGVuIHRoZSBudW1lcmF0b3IgYW5kIGRlbm9taW5hdG9yIG9mIHRoZSBhbGxfcGFpcndpc2UKY29udHJhc3RzIGFyZSBkaWZmZXJlbnQgdGhhbiB0aG9zZSBpbiBjb21iaW5lX2RlX3RhYmxlcy4gIEl0IGlzCnB1dHRpbmcgdGhlIHVwcy9kb3ducyBvbiB0aGUgY29ycmVjdCBzaWRlcyBvZiB0aGUgcGxvdCwgYnV0IGNhbGxpbmcKdGhlIGRvd24gZ2VuZXMgJ3VwJyBhbmQgdmljZS12ZXJzYS4gIFRoZSByZWFzb24gZm9yIHRoaXMgaXMgdGhhdCBJIGRpZAphIGNoZWNrIGZvciB0aGlzIGhhcHBlbmluZywgYnV0IHVzZWQgdGhlIHdyb25nIGFyZ3VtZW50IHRvIGhhbmRsZSBpdC4KCkEgbGlrZWx5IGJpdCBvZiB0ZXh0IGZvciB0aGVzZSB2b2xjYW5vIHBsb3RzOgoKVGhlIHNldCBvZiBnZW5lcyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2VlbiB0aGUgenltb2RlbWUgMi4zCmFuZCB1bmluZmVjdGVkIHNhbXBsZXMgd2l0aG91dCBkcnVnZSB0cmVhdG1lbnQgd2FzIHF1YW50aWZpZWQgd2l0aApERVNlcTIgYW5kIGluY2x1ZGVkIHN1cnJvZ2F0ZSBlc3RpbWF0ZXMgZnJvbSBTVkEuICBHaXZlbiB0aGUgY3JpdGVyaWEKb2Ygc2lnbmlmaWNhbmNlIG9mIGEgYWJzKGxvZ0ZDKSA+PSAxLjAgYW5kIGZhbHNlIGRpc2NvdmVyeSByYXRlCmFkanVzdGVkIHAtdmFsdWUgPD0gMC4wNSwgNjcwIGdlbmVzIHdlcmUgb2JzZXJ2ZWQgYXMgc2lnbmlmaWNhbnRseQppbmNyZWFzZWQgYmV0d2VlbiB0aGUgaW5mZWN0ZWQgYW5kIHVuaW5mZWN0ZWQgc2FtcGxlcyBhbmQgMzg2IHdlcmUKb2JzZXJ2ZWQgYXMgZGVjcmVhc2VkLiBUaGUgbW9zdCBpbmNyZWFzZWQgZ2VuZXMgZnJvbSB0aGUgdW5pbmZlY3RlZApzYW1wbGVzIGluY2x1ZGUgc29tZSB3aGljaCBhcmUgcG90ZW50aWFsbHkgaW5kaWNhdGl2ZSBvZiBhIHN0cm9uZwppbm5hdGUgaW1tdW5lIHJlc3BvbnNlIGFuZCB0aGUgaW5mbGFtbWF0b3J5IHJlc3BvbnNlLgoKSW4gY29udHJhc3QsIHdoZW4gdGhlIHNldCBvZiBnZW5lcyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2Vlbgp0aGUgenltb2RlbWUgMi4yIGFuZCB1bmluZmVjdGVkIHNhbXBsZXMgd2FzIHZpc3VhbGl6ZWQsIG9ubHkgNyBnZW5lcwp3ZXJlIG9ic2VydmVkIGFzIGRlY3JlYXNlZCBhbmQgNDM1IGluY3JlYXNlZC4gIFRoZSBpbmZsYW1tYXRvcnkKcmVzcG9uc2Ugd2FzIHNpZ25pZmljYW50bHkgbGVzcyBhcHBhcmVudCBpbiB0aGlzIHNldCwgYnV0IGluc3RlYWQKaW5jbHVkZWQgZ2VuZXMgcmVsYXRlZCB0byB0cmFuc3BvcnRlciBhY3Rpdml0eSBhbmQgb3hpZG9yZWR1Y3Rhc2VzLgoKIyMgRGlyZWN0IHp5bW9kZW1lIGNvbXBhcmlzb25zCgpBbiBvcnRob2dvbmFsIGNvbXBhcmlzb24gdG8gdGhhdCBwZXJmb3JtZWQgYWJvdmUgaXMgdG8gZGlyZWN0bHkKY29tcGFyZSB0aGUgenltb2RlbWUgMi4zIGFuZCAyLjIgc2FtcGxlcyB3aXRoIGFuZCB3aXRob3V0IGFudGltb25pYWwKdHJlYXRtZW50LgoKYGBge3IgejIyejIzX2NvbXBhcmlzb25fcGxvdHN9CnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICAgIHRhYmxlID0gaHNfbWFjcm9waGFnZV90YWJsZVtbImRhdGEiXV1bWyJ6MjNub3NiX3ZzX3oyMm5vc2IiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm8kcGxvdCkKCnoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dLAogICAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8kcGxvdCkKYGBgCgpgYGB7ciB6MjNub3NiX3ZzX3oyMm5vc2JfcGxvdHN9CnoyM25vc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTEwLCAxMCkgKwogIHlsaW0oMCwgNjApCgpwcChmaWxlPSJpbWFnZXMvejIzbm9zYl92c196MjJub3NiX3JlYWN0b21lX3VwLnBuZyIsIGltYWdlPWFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0sIGhlaWdodD0xMiwgd2lkdGg9OSkKIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM25vc2JfdnNfejIybm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzbm9zYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjNub3NiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCmBgYHtyIHoyM192c196MjJzYl9wbG90c30KejIzc2JfdnNfejIyc2Jfdm9sY2FubyRwbG90ICsKICB4bGltKC0xMCwgMTApICsKICB5bGltKDAsIDYwKQoKcHAoZmlsZT0iaW1hZ2VzL3oyM3NiX3ZzX3oyMnNiX3JlYWN0b21lX3VwLnBuZyIsIGltYWdlPWFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwgaGVpZ2h0PTEyLCB3aWR0aD05KQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siS0VHRyJdXQojIyBLRUdHLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjJzYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIldQIl1dCiMjIFdpa2lQYXRod2F5cywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyMnNiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIyc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCgpgYGB7ciB6MjNzYl92c196MjJzYl92ZW5ufQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ6MjNzYl92c196MjJzYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vZHJ1ZyIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzbm9zYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGU9ImltYWdlcy9kcnVnX25vZHJ1Z192ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJkcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM3NiX3ZzX3oyMnNiIl1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9kcnVnIiA9IHJvd25hbWVzKGhzX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXSkpKQpwcChmaWxlPSJpbWFnZXMvZHJ1Z19ub2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKYGBgCgpBIHNsaWdodGx5IGRpZmZlcmVudCB3YXkgb2YgbG9va2luZyBhdCB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdHdvCnp5bW9kZW1lIGluZmVjdGlvbnMgaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgaW5mZWN0ZWQgc2FtcGxlcyB3aXRoCmFuZCB3aXRob3V0IGRydWcuICBUaHVzLCB3aGVuIGEgdm9sY2FubyBwbG90IHNob3dpbmcgdGhlIGNvbXBhcmlzb24gb2YKdGhlIHp5bW9kZW1lIDIuMyB2cy4gMi4yIHNhbXBsZXMgd2FzIHBsb3R0ZWQsIDQ4NCBnZW5lcyB3ZXJlIG9ic2VydmVkCmFzIGluY3JlYXNlZCBhbmQgNDIyIGRlY3JlYXNlZDsgdGhlc2UgZ3JvdXBzIGluY2x1ZGUgbWFueSBvZiB0aGUgc2FtZQppbmZsYW1tYXRvcnkgKHVwKSBhbmQgbWVtYnJhbmUgKGRvd24pIGdlbmVzLgoKU2ltaWxhciBwYXR0ZXJucyB3ZXJlIG9ic2VydmVkIHdoZW4gdGhlIGFudGltb25pYWwgd2FzIGluY2x1ZGVkLgpUaHVzLCB3aGVuIGEgVmVubiBkaWFncmFtIG9mIHRoZSB0d28gc2V0cyBvZiBpbmNyZWFzZWQgZ2VuZXMgd2FzCnBsb3R0ZWQsIGEgc2lnbmlmaWNhbnQgbnVtYmVyIG9mIHRoZSBnZW5lcyB3YXMgb2JzZXJ2ZWQgYXMgaW5jcmVhc2VkCigzMTMpIGFuZCBkZWNyZWFzZWQgKDI0NCkgaW4gYm90aCB0aGUgdW50cmVhdGVkIGFuZCBhbnRpbW9uaWFsIHRyZWF0ZWQKc2FtcGxlcy4KCiMjIERydWcgZWZmZWN0cyBvbiBlYWNoIHp5bW9kZW1lIGluZmVjdGlvbgoKQW5vdGhlciBsaWtlbHkgcXVlc3Rpb24gaXMgdG8gZGlyZWN0bHkgY29tcGFyZSB0aGUgdHJlYXRlZCB2cwp1bnRyZWF0ZWQgc2FtcGxlcyBmb3IgZWFjaCB6eW1vZGVtZSBpbmZlY3Rpb24gaW4gb3JkZXIgdG8gdmlzdWFsaXplCnRoZSBlZmZlY3RzIG9mIGFudGltb25pYWwuCgpgYGB7ciB6MjNkcnVnX3oyM25vZHJ1Z196MjJkcnVnX3oyMm5vZHJ1Z19wbG90c30KejIzc2JfdnNfejIzbm9zYl92b2xjYW5vIDwtIHBsb3Rfdm9sY2Fub19kZSgKICAgIHRhYmxlID0gaHNfbWFjcm9waGFnZV90YWJsZVtbImRhdGEiXV1bWyJ6MjNzYl92c196MjNub3NiIl1dLAogICAgZmNfY29sID0gImRlc2VxX2xvZ2ZjIiwgcF9jb2wgPSAiZGVzZXFfYWRqcCIsCiAgICBzaGFwZXNfYnlfc3RhdGUgPSBGQUxTRSwgY29sb3JfYnkgPSAiZmMiLCAgbGFiZWwgPSAxMCwgbGFiZWxfY29sdW1uID0gImhnbmNzeW1ib2wiKQpwbG90bHk6OmdncGxvdGx5KHoyM3NiX3ZzX3oyM25vc2Jfdm9sY2FubyRwbG90KQp6MjJzYl92c196MjJub3NiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBoc19tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkoejIyc2JfdnNfejIybm9zYl92b2xjYW5vJHBsb3QpCmBgYAoKYGBge3IgejIzc2JfdnNfejIzbm9zYl9wbG90c30KejIzc2JfdnNfejIzbm9zYl92b2xjYW5vJHBsb3QgKwogIHhsaW0oLTgsIDgpICsKICB5bGltKDAsIDIxMCkKCnBwKGZpbGU9ImltYWdlcy96MjNzYl92c196MjNub3NiX3JlYWN0b21lX3VwLnBuZyIsCiAgIGltYWdlPWFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJSRUFDIl1dLCBoZWlnaHQ9MTIsIHdpZHRoPTkpCiMjIFJlYWN0b21lLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl91cCJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIktFR0ciXV0KIyMgS0VHRywgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJNRiJdXQojIyBNRiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJXUCJdXQojIyBXaWtpUGF0aHdheXMsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjNzYl92c196MjNub3NiX3VwIl1dW1siaW50ZXJhY3RpdmVfcGxvdHMiXV1bWyJXUCJdXQoKYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYWxsX2dwW1siejIzc2JfdnNfejIzbm9zYl9kb3duIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyM3NiX3ZzX3oyM25vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlRGIl1dCiMjIFRGLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgpgYGAKCmBgYHtyIHoyMnNiX3ZzX3oyMm5vc2JfcGxvdHN9CnoyMnNiX3ZzX3oyMm5vc2Jfdm9sY2FubyRwbG90ICsKICB4bGltKC04LCA4KSArCiAgeWxpbSgwLCAyMTApCgpwcChmaWxlPSJpbWFnZXMvejIyc2JfdnNfejIybm9zYl9yZWFjdG9tZV91cC5wbmciLAogICBpbWFnZT1hbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siUkVBQyJdXSwgaGVpZ2h0PTEyLCB3aWR0aD05KQojIyBSZWFjdG9tZSwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgdXAuCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfdXAiXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJLRUdHIl1dCiMjIEtFR0csIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siTUYiXV0KIyMgTUYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siVEYiXV0KIyMgVEYsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIHVwLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX3VwIl1dW1sicHZhbHVlX3Bsb3RzIl1dW1siV1AiXV0KIyMgV2lraVBhdGh3YXlzLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCB1cC4KYWxsX2dwW1siejIyc2JfdnNfejIybm9zYl91cCJdXVtbImludGVyYWN0aXZlX3Bsb3RzIl1dW1siV1AiXV0KCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIlJFQUMiXV0KIyMgUmVhY3RvbWUsIHp5bW9kZW1lMi4zIHdpdGhvdXQgZHJ1ZyB2cy4gdW5pbmZlY3RlZCB3aXRob3V0IGRydWcsIGRvd24uCmFsbF9ncFtbInoyMnNiX3ZzX3oyMm5vc2JfZG93biJdXVtbInB2YWx1ZV9wbG90cyJdXVtbIk1GIl1dCiMjIE1GLCB6eW1vZGVtZTIuMyB3aXRob3V0IGRydWcgdnMuIHVuaW5mZWN0ZWQgd2l0aG91dCBkcnVnLCBkb3duLgphbGxfZ3BbWyJ6MjJzYl92c196MjJub3NiX2Rvd24iXV1bWyJwdmFsdWVfcGxvdHMiXV1bWyJURiJdXQojIyBURiwgenltb2RlbWUyLjMgd2l0aG91dCBkcnVnIHZzLiB1bmluZmVjdGVkIHdpdGhvdXQgZHJ1ZywgZG93bi4KYGBgCgpgYGB7ciB6MjJzYl92c196MjJub3NiX3Zlbm5zfQpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM3NiX3ZzX3oyM25vc2IiXV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ6MjIiID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMnNiX3ZzX3oyMm5vc2IiXV0pKSkKcHAoZmlsZT0iaW1hZ2VzL3oyM196MjJfZHJ1Z192ZW5uX3VwLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCgpzaGFyZWQgPC0gVmVubmVyYWJsZTo6VmVubihsaXN0KCJ6MjMiID0gcm93bmFtZXMoaHNfbWFjcm9waGFnZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzc2JfdnNfejIzbm9zYiJdXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInoyMiIgPSByb3duYW1lcyhoc19tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ6MjJzYl92c196MjJub3NiIl1dKSkpCnBwKGZpbGU9ImltYWdlcy96MjNfejIyX2RydWdfdmVubl9kb3duLnBuZyIpClZlbm5lcmFibGU6OnBsb3Qoc2hhcmVkKQpkZXYub2ZmKCkKVmVubmVyYWJsZTo6cGxvdChzaGFyZWQpCmBgYAoKTm90ZTogSSBhbSBzZXR0aWcgdGhlIHggYW5kIHktYXhpcyBib3VuZGFyaWVzIGJ5IGFsbG93aW5nIHRoZSBwbG90dGVyCnRvIHBpY2sgaXRzIG93biBheGlzIHRoZSBmaXJzdCB0aW1lLCB3cml0aW5nIGRvd24gdGhlIHJhbmdlcyBJCm9ic2VydmUsIGFuZCB0aGVuIHNldHRpbmcgdGhlbSB0byB0aGUgbGFyZ2VzdCBvZiB0aGUgcGFpci4gIEl0IGlzCnRoZXJlZm9yZSBwb3NzaWJsZSB0aGF0IEkgbWlzc2VkIG9uZSBvciBtb3JlIGdlbmVzIHdoaWNoIGxpZXMgb3V0c2lkZQp0aGF0IHJhbmdlLgoKVGhlIHByZXZpb3VzIHBsb3R0ZWQgY29udHJhc3RzIHNvdWdodCB0byBzaG93IGNoYW5nZXMgYmV0d2VlbiB0aGUgdHdvCnN0cmFpbnMgejIuMyBhbmQgejIuMi4gIENvbnZlcnNlbHksIHRoZSBwcmV2aW91cyB2b2xjYW5vIHBsb3RzIHNlZWsgdG8KZGlyZWN0bHkgY29tcGFyZSBlYWNoIHN0cmFpbiBiZWZvcmUvYWZ0ZXIgZHJ1ZyB0cmVhdG1lbnQuCgojIyBMUlQgb2YgdGhlIEh1bWFuIE1hY3JvcGhhZ2UKCmBgYHtyIGxydF90bXJjMl9tYWNyfQp0bXJjMl9scnRfc3RyYWluX2RydWcgPC0gZGVzZXFfbHJ0KGhzX21hY3IsIGludGVyYWN0b3JfY29sdW1uID0gImRydWciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyZXN0X2NvbHVtbiA9ICJtYWNyb3BoYWdlenltb2RlbWUiLCBmYWN0b3JzID0gYygiZHJ1ZyIsICJtYWNyb3BoYWdlenltb2RlbWUiKSkKdG1yYzJfbHJ0X3N0cmFpbl9kcnVnJGNsdXN0ZXJfZGF0YSRwbG90CmBgYAoKIyMgUGFyYXNpdGUKCmBgYHtyIGxwX2RlfQpscF9tYWNyb3BoYWdlX2RlIDwtIGFsbF9wYWlyd2lzZShscF9tYWNyb3BoYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCnRtcmMyX3BhcmFzaXRlX2tlZXBlcnMgPC0gbGlzdCgKICAgICJ6MjNfdnNfejIyIiA9IGMoInoyMyIsICJ6MjIiKSkKbHBfbWFjcm9waGFnZV90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICBscF9tYWNyb3BoYWdlX2RlLCBrZWVwZXJzID0gdG1yYzJfcGFyYXNpdGVfa2VlcGVycywKICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9tYWNyb3BoYWdlX3BhcmFzaXRlX2luZmVjdGlvbl9kZS12e3Zlcn0ueGxzeCIpKQpscF9tYWNyb3BoYWdlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgbHBfbWFjcm9waGFnZV90YWJsZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL21hY3JvcGhhZ2VfcGFyYXNpdGVfc2lnLXZ7dmVyfS54bHN4IikpCgpwcChmaWxlPSJpbWFnZXMvbHBfbWFjcm9waGFnZV96MjNfejIyLnBuZyIsCiAgIGltYWdlPWxwX21hY3JvcGhhZ2VfdGFibGVbWyJwbG90cyJdXVtbInoyM25vc2JfdnNfejIybm9zYiJdXVtbImRlc2VxX3ZvbF9wbG90cyJdXVtbInBsb3QiXV0pCgp1cF9nZW5lcyA8LSBscF9tYWNyb3BoYWdlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0KZGltKHVwX2dlbmVzKQpkb3duX2dlbmVzIDwtIGxwX21hY3JvcGhhZ2Vfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dCmRpbShkb3duX2dlbmVzKQpgYGAKCmBgYHtyIHBhcmFzaXRlX3ZvbGNhbm99CmxwX3oyM3NiX3ZzX3oyMnNiX3ZvbGNhbm8gPC0gcGxvdF92b2xjYW5vX2RlKAogICAgdGFibGUgPSBscF9tYWNyb3BoYWdlX3RhYmxlW1siZGF0YSJdXVtbInoyM192c196MjIiXV0sCiAgICBmY19jb2wgPSAiZGVzZXFfbG9nZmMiLCBwX2NvbCA9ICJkZXNlcV9hZGpwIiwKICAgIHNoYXBlc19ieV9zdGF0ZSA9IEZBTFNFLCBjb2xvcl9ieSA9ICJmYyIsICBsYWJlbCA9IDEwLCBsYWJlbF9jb2x1bW4gPSAiaGduY3N5bWJvbCIpCnBsb3RseTo6Z2dwbG90bHkobHBfejIzc2JfdnNfejIyc2Jfdm9sY2FubyRwbG90KQoKbHBfejIzbm9zYl92c196MjJub3NiX3ZvbGNhbm8kcGxvdApgYGAKCmBgYHtyIGdvc2VxX2xwfQp1cF9nb3NlcSA8LSBzaW1wbGVfZ29zZXEodXBfZ2VuZXMsIGdvX2RiPWxwX2dvLCBsZW5ndGhfZGI9bHBfbGVuZ3RocykKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMyBzYW1wbGVzCnVwX2dvc2VxJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmRvd25fZ29zZXEgPC0gc2ltcGxlX2dvc2VxKGRvd25fZ2VuZXMsIGdvX2RiPWxwX2dvLCBsZW5ndGhfZGI9bHBfbGVuZ3RocykKIyMgVmlldyBjYXRlZ29yaWVzIG92ZXIgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMiBzYW1wbGVzCmRvd25fZ29zZXEkcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKYGBgCgojIEdTVkEKCmBgYHtyIGdzdmF9CmhzX2luZmVjdGVkIDwtIHN1YnNldF9leHB0KGhzX21hY3JvcGhhZ2UsIHN1YnNldD0ibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mJyIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0ibWFjcm9waGFnZXRyZWF0bWVudCE9J3VuaW5mX3NiJyIpCmhzX2dzdmFfYzIgPC0gc2ltcGxlX2dzdmEoaHNfaW5mZWN0ZWQpCmhzX2dzdmFfYzJfbWV0YSA8LSBnZXRfbXNpZ2RiX21ldGFkYXRhKGhzX2dzdmFfYzIsIG1zaWdfeG1sPSJyZWZlcmVuY2UvbXNpZ2RiX3Y3LjIueG1sIikKaHNfZ3N2YV9jMl9zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoaHNfZ3N2YV9jMl9tZXRhLCBleGNlbCA9ICJleGNlbC9oc19tYWNyb3BoYWdlX2dzdmFfYzJfc2lnLnhsc3giKQpoc19nc3ZhX2MyX3NpZyRyYXdfcGxvdAoKaHNfZ3N2YV9jNyA8LSBzaW1wbGVfZ3N2YShoc19pbmZlY3RlZCwgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM3IikKaHNfZ3N2YV9jN19tZXRhIDwtIGdldF9tc2lnZGJfbWV0YWRhdGEoaHNfZ3N2YV9jNywgbXNpZ194bWw9InJlZmVyZW5jZS9tc2lnZGJfdjcuMi54bWwiKTQKaHNfZ3N2YV9jN19zaWcgPC0gZ2V0X3NpZ19nc3ZhX2NhdGVnb3JpZXMoaHNfZ3N2YV9jNywgZXhjZWwgPSAiZXhjZWwvaHNfbWFjcm9waGFnZV9nc3ZhX2M3X3NpZy54bHN4IikKaHNfZ3N2YV9jN19zaWckcmF3X3Bsb3QKYGBgCgojIFRyeSBvdXQgYSBuZXcgdG9vbAoKVHdvIHJlYXNvbnM6IE5hamliIGxvdmVzIGhpbSBzb21lIFBDQSwgdGhpcyB1c2VzIHdpa2lwYXRod2F5cywgd2hpY2ggaXMgc29tZXRoaW5nIEkgdGhpbmsgaXMgbmVhdC4KCk9rLCBJIHNwZW50IHNvbWUgdGltZSBsb29raW5nIHRocm91Z2ggdGhlIGNvZGUgYW5kIEkgaGF2ZSBzb21lCnByb2JsZW1zIHdpdGggc29tZSBvZiB0aGUgZGVzaWduIGRlY2lzaW9ucy4KCk1vc3QgaW1wb3J0YW50bHksIGl0IHJlcXVpcmVzIGEgZGF0YS5mcmFtZSgpIHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGZvcm1hdDoKCjEuICBObyByb3duYW1lcywgaW5zdGVhZCBjb2x1bW4gIzEgaXMgdGhlIHNhbXBsZSBJRC4KMi4gIENvbHVtbnMgMi1tIGFyZSB0aGUgY2F0ZWdvcmljYWwvc3Vydml2YWwvZXRjIG1ldHJpY3MuCjMuICBDb2x1bW5zIG0tbiBhcmUgMSBnZW5lLXBlci1jb2x1bW4gd2l0aCBsb2cyIHZhbHVlcy4KCkJ1dCB3aGVuIEkgdGhpbmsgYWJvdXQgaXQgSSB0aGluayBJIGdldCB0aGUgaWRlYSwgdGhleSB3YW50IHRvIGJlIGFibGUgdG8gZG8gbW9kZWxsaW5nIHN0dWZmCm1vcmUgZWFzaWx5IHdpdGggcmVzcG9uc2UgZmFjdG9ycy4KCmBgYHtyIHBhdGh3YXlQQ0EsIGV2YWw9RkFMU0V9CmxpYnJhcnkocGF0aHdheVBDQSkKbGlicmFyeShyV2lraVBhdGh3YXlzKQoKZG93bmxvYWRlZCA8LSBkb3dubG9hZFBhdGh3YXlBcmNoaXZlKG9yZ2FuaXNtID0gIkhvbW8gc2FwaWVucyIsIGZvcm1hdCA9ICJnbXQiKQpkYXRhX3BhdGggPC0gc3lzdGVtLmZpbGUoImV4dGRhdGEiLCBwYWNrYWdlPSJwYXRod2F5UENBIikKd2lraXBhdGh3YXlzIDwtIHJlYWRfZ210KHBhc3RlMChkYXRhX3BhdGgsICIvd2lraXBhdGh3YXlzX2h1bWFuX3N5bWJvbC5nbXQiKSwgZGVzY3JpcHRpb249VFJVRSkKCmV4cHQgPC0gc3Vic2V0X2V4cHQoaHNfbWFjcm9waGFnZSwgc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmYnIikgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJtYWNyb3BoYWdldHJlYXRtZW50IT0ndW5pbmZfc2InIikKZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGV4cHQsIGZhY3Q9Im1hY3JvcGhhZ2V6eW1vZGVtZSIpCgpzeW1ib2xfdmVjdG9yIDwtIGZEYXRhKGV4cHQpW1tzeW1ib2xfY29sdW1uXV0KbmFtZXMoc3ltYm9sX3ZlY3RvcikgPC0gcm93bmFtZXMoZkRhdGEoZXhwdCkpCnN5bWJvbF9kZiA8LSBhcy5kYXRhLmZyYW1lKHN5bWJvbF92ZWN0b3IpCgphc3NheV9kZiA8LSBtZXJnZShzeW1ib2xfZGYsIGFzLmRhdGEuZnJhbWUoZXhwcnMoZXhwdCkpLCBieSA9ICJyb3cubmFtZXMiKQphc3NheV9kZltbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCnJvd25hbWVzKGFzc2F5X2RmKSA8LSBtYWtlLm5hbWVzKGFzc2F5X2RmW1sic3ltYm9sX3ZlY3RvciJdXSwgdW5pcXVlID0gVFJVRSkKYXNzYXlfZGZbWyJzeW1ib2xfdmVjdG9yIl1dIDwtIE5VTEwKYXNzYXlfZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGFzc2F5X2RmKSkKYXNzYXlfZGZbWyJTYW1wbGVJRCJdXSA8LSByb3duYW1lcyhhc3NheV9kZikKYXNzYXlfZGYgPC0gZHBseXI6OnNlbGVjdChhc3NheV9kZiwgIlNhbXBsZUlEIiwgZXZlcnl0aGluZygpKQoKZmFjdG9yX2RmIDwtIGFzLmRhdGEuZnJhbWUocERhdGEoZXhwdCkpCmZhY3Rvcl9kZltbIlNhbXBsZUlEIl1dIDwtIHJvd25hbWVzKGZhY3Rvcl9kZikKZmFjdG9yX2RmIDwtIGRwbHlyOjpzZWxlY3QoZmFjdG9yX2RmLCAiU2FtcGxlSUQiLCBldmVyeXRoaW5nKCkpCmZhY3Rvcl9kZiA8LSBmYWN0b3JfZGZbLCBjKCJTYW1wbGVJRCIsIGZhY3RvcnMpXQoKdHQgPC0gQ3JlYXRlT21pY3MoCiAgICBhc3NheURhdGFfZGYgPSBhc3NheV9kZiwKICAgIHBhdGh3YXlDb2xsZWN0aW9uX2xzID0gd2lraXBhdGh3YXlzLAogICAgcmVzcG9uc2UgPSBmYWN0b3JfZGYsCiAgICByZXNwVHlwZSA9ICJjYXRlZ29yaWNhbCIsCiAgICBtaW5QYXRoU2l6ZT01KQoKc3VwZXIgPC0gQUVTUENBX3BWYWxzKAogICAgb2JqZWN0ID0gdHQsCiAgICBudW1QQ3MgPSAyLAogICAgcGFyYWxsZWwgPSBGQUxTRSwKICAgIG51bUNvcmVzID0gOCwKICAgIG51bVJlcHMgPSAyLAogICAgYWRqdXN0bWVudCA9ICJCSCIpCmBgYAoKYGBge3Igc2F2ZW1lfQppZiAoIWlzVFJVRShnZXQwKCJza2lwX2xvYWQiKSkpIHsKICBwYW5kZXI6OnBhbmRlcihzZXNzaW9uSW5mbygpKQogIG1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQogIG1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgc2F2ZWZpbGUpKQogIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWUgPSBzYXZlZmlsZSkpCn0KYGBgCgpgYGB7ciBsb2FkbWVfYWZ0ZXIsIGV2YWwgPSBGQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAK