index.html annotation.html sample_estimations.html differential_expression.html

In this document, we will perform a series of differential expression analyses using the data which survived sample estimation.

1 Gene Ontology searches

Lets set up some simple data sets for goseq/clusterProfiler/topGO

I think a bunch of the material in this sheet is actually now obsolete.

1.1 Extracting ontology annotations from the TriTrypDB

I need to extract the ontology/pFAM data from the Tcruzi annotation tables.

I have a perl script ‘dump_tritryp_GO.pl’ which can do this for me.

cd $LAB/ref_data/gene_ontology/
./dump_tritryp_GO.pl $LAB/ref_data/tritryp_text/Tcruzi.txt > tcruzi_go.tab
## The actual commands were slightly different, just because I didn't feel like copy/pasting the filenames.

1.2 Preparing to use goseq

I need a couple vectors before being able to use goseq I also need some rda files generated for clusterProfiler and topGO but I will do those later…

## goseq uses the gene lengths, clusterprofiler and topgo don't
## gene_lengths <- all_genes[,c("geneid","genesize")]
## colnames(gene_lengths) <- c("ID", "width")
colnames(all_lengths) <- c("ID", "width")
## go_ids needs to be a 2 column data frame with names 'ID', 'GO' which are
## gene names and GO names respectively.  I actually think I made my goseq() function
## smart enough that this is no longer needed, but nonetheless.

## go_ids <- read.table("reference/go/tcruzi_all_go.tab.gz", header=0, sep="\t")
## colnames(go_ids) <- c("ID","GO","ontology","term","source")
## Since there are multiple sources, I am doing a unique of the table...
## go_ids <- unique(go_ids[,c("ID","GO")])
## goid_file <- "reference/go/topgo_goids.tab.gz"

colnames(all_go) <- c("ID", "GO")
clbr_up_a96tryp_goseq <- sm(simple_goseq(sig_genes=clbr_times_sigfilt$limma$ups$clbr_a96_to_tryp,
                                         go_db=all_go, length_db=all_lengths))

clbr_up_a96tryp_goseq$pvalue_plots$bpp_plot_over

clbr_up_a96tryp_excel <- sm(write_goseq_data(clbr_up_a96tryp_goseq,
                                             excel=paste0("excel/clbr_up_a96tryp_goseq-v", ver, ".xlsx")))

clbr_down_a96tryp_goseq <- sm(simple_goseq(sig_genes=clbr_times_sigfilt$limma$downs$clbr_a96_to_tryp,
                                           go_db=all_go, length_db=all_lengths))

clbr_down_a96tryp_goseq$pvalue_plots$bpp_plot_over

clbr_down_a96tryp_excel <- sm(write_goseq_data(clbr_down_a96tryp_goseq,
                                               excel=paste0("excel/clbr_down_a96tryp_goseq-v", ver, ".xlsx")))

clbr_up_a60a96_goseq <- sm(simple_goseq(sig_genes=clbr_times_sigfilt$limma$ups$clbr_a60_to_a96,
                                        go_db=all_go, length_db=all_lengths))

clbr_up_a60a96_goseq$pvalue_plots$bpp_plot_over

clbr_up_a60a96_excel <- sm(write_goseq_data(clbr_up_a60a96_goseq,
                                            excel=paste0("excel/clbr_up_a60a96_goseq-v", ver, ".xlsx")))

clbr_down_a60a96_goseq <- sm(simple_goseq(sig_genes=clbr_times_sigfilt$limma$downs$clbr_a60_to_a96,
                                          go_db=all_go, length_db=all_lengths))

clbr_down_a60a96_goseq$pvalue_plots$bpp_plot_over

clbr_down_a60a96_excel <- sm(write_goseq_data(clbr_down_a60a96_goseq,
                                              excel=paste0("excel/clbr_down_a60a96_goseq-v", ver, ".xlsx")))

clbr_up_trypa60_goseq <- sm(simple_goseq(sig_genes=clbr_times_sigfilt$limma$ups$clbr_tryp_to_a60,
                                         go_db=all_go, length_db=all_lengths))

clbr_up_trypa60_goseq$pvalue_plots$bpp_plot_over

clbr_up_trypa60_excel <- sm(write_goseq_data(clbr_up_trypa60_goseq,
                                             excel=paste0("excel/clbr_up_trypa60_goseq-v", ver, ".xlsx")))

clbr_down_trypa60_goseq <- sm(simple_goseq(sig_genes=clbr_times_sigfilt$limma$downs$clbr_tryp_to_a60,
                                           go_db=all_go, length_db=all_lengths))

clbr_down_trypa60_goseq$pvalue_plots$bpp_plot_over

clbr_down_trypa60_excel <- sm(write_goseq_data(clbr_down_trypa60_goseq,
                                               excel=paste0("excel/clbr_down_trypa60_goseq-v", ver, ".xlsx")))

cl14_up_a96tryp_goseq <- sm(simple_goseq(sig_genes=cl14_times_sigfilt$limma$ups$cl14_a96_to_tryp,
                                         go_db=all_go, length_db=all_lengths))

cl14_up_a96tryp_goseq$pvalue_plots$bpp_plot_over

cl14_up_a96tryp_excel <- sm(write_goseq_data(cl14_up_a96tryp_goseq,
                                             excel=paste0("excel/cl14_up_a96tryp_goseq-v", ver, ".xlsx")))

cl14_down_a96tryp_goseq <- sm(simple_goseq(sig_genes=cl14_times_sigfilt$limma$downs$cl14_a96_to_tryp,
                                           go_db=all_go, length_db=all_lengths))

cl14_down_a96tryp_goseq$pvalue_plots$bpp_plot_over

cl14_down_a96tryp_excel <- sm(write_goseq_data(cl14_down_a96tryp_goseq,
                                               excel=paste0("excel/cl14_down_a96tryp_goseq-v", ver, ".xlsx")))

cl14_up_a60a96_goseq <- sm(simple_goseq(sig_genes=cl14_times_sigfilt$limma$ups$cl14_a60_to_a96,
                                        go_db=all_go, length_db=all_lengths))

cl14_up_a60a96_goseq$pvalue_plots$bpp_plot_over

cl14_up_a60a96_excel <- sm(write_goseq_data(cl14_up_a60a96_goseq,
                                            excel=paste0("excel/cl14_up_a60a96_goseq-v", ver, ".xlsx")))

cl14_down_a60a96_goseq <- sm(simple_goseq(sig_genes=cl14_times_sigfilt$limma$downs$cl14_a60_to_a96,
                                          go_db=all_go, length_db=all_lengths))

cl14_down_a60a96_goseq$pvalue_plots$bpp_plot_over

cl14_down_a60a96_excel <- sm(write_goseq_data(cl14_down_a60a96_goseq,
                                              excel=paste0("excel/cl14_down_a60a96_goseq-v", ver, ".xlsx")))

cl14_up_trypa60_goseq <- sm(simple_goseq(sig_genes=cl14_times_sigfilt$limma$ups$cl14_tryp_to_a60,
                                         go_db=all_go, length_db=all_lengths))

cl14_up_trypa60_goseq$pvalue_plots$bpp_plot_over

cl14_up_trypa60_excel <- sm(write_goseq_data(cl14_up_trypa60_goseq,
                                             excel=paste0("excel/cl14_up_trypa60_goseq-v", ver, ".xlsx")))

cl14_down_trypa60_goseq <- sm(simple_goseq(sig_genes=cl14_times_sigfilt$limma$downs$cl14_tryp_to_a60,
                                           go_db=all_go, length_db=all_lengths))

cl14_down_trypa60_goseq$pvalue_plots$bpp_plot_over

cl14_down_trypa60_excel <- sm(write_goseq_data(cl14_down_trypa60_goseq,
                                               excel=paste0("excel/cl14_down_trypa60_goseq-v", ver, ".xlsx")))

strains_up_a60_goseq <- sm(simple_goseq(sig_genes=strains_sigfilt$limma$ups$a60_clbr_over_cl14,
                                        go_db=all_go, length_db=all_lengths))

strains_up_a96_goseq <- sm(simple_goseq(sig_genes=strains_sigfilt$limma$ups$a96_clbr_over_cl14,
                                        go_db=all_go, length_db=all_lengths))

strains_up_tryp_goseq <- sm(simple_goseq(sig_genes=strains_sigfilt$limma$ups$tryp_clbr_over_cl14,
                                         go_db=all_go, length_db=all_lengths))

strains_up_a60_excel <- sm(write_goseq_data(strains_up_a60_goseq,
                                            excel=paste0("excel/strains_upa60_goseq-v", ver, ".xlsx")))

strains_up_a96_excel <- sm(write_goseq_data(strains_up_a96_goseq,
                                            excel=paste0("excel/strains_upa96_goseq-v", ver, ".xlsx")))

strains_up_tryp_excel <- sm(write_goseq_data(strains_up_tryp_goseq,
                                             excel=paste0("excel/strains_uptryp_goseq-v", ver, ".xlsx")))

strains_down_a60_goseq <- sm(simple_goseq(sig_genes=strains_sigfilt$limma$downs$a60_clbr_over_cl14,
                                          go_db=all_go, length_db=all_lengths))

strains_down_a96_goseq <- sm(simple_goseq(sig_genes=strains_sigfilt$limma$downs$a96_clbr_over_cl14,
                                          go_db=all_go, length_db=all_lengths))

strains_down_tryp_goseq <- sm(simple_goseq(sig_genes=strains_sigfilt$limma$downs$tryp_clbr_over_cl14,
                                           go_db=all_go, length_db=all_lengths))

strains_down_a60_excel <- sm(write_goseq_data(strains_down_a60_goseq,
                                            excel=paste0("excel/strains_downa60_goseq-v", ver, ".xlsx")))

strains_down_a96_excel <- sm(write_goseq_data(strains_down_a96_goseq,
                                            excel=paste0("excel/strains_downa96_goseq-v", ver, ".xlsx")))

strains_down_tryp_excel <- sm(write_goseq_data(strains_down_tryp_goseq,
                                             excel=paste0("excel/strains_downtryp_goseq-v", ver, ".xlsx")))

1.3 Compare Epimastigotes between CL14 and CLBr, high expression

One important note here, I needed to modify the data structure from readGff() in clusterProfiler before it was able to successfully generate the file ‘geneTable.rda’ Unfortunately, I was watching a movie at the time and didn’t properly write down what I did. However, I did write it out in the function myr::Gff2GeneTable() but in order to make it work one must load readGff() from clusterProfiler. I think the real solution is for me to grab a version of readGff() from clusterProfiler and make it exportable so that it will work consistently.

## Changes in epimastigotes from CLBrener to CL14
pval_thresh <- 0.0001
epi_cl14clbr_table <- all_tables$epi_cl14clbr
epi_cl14clbr_summary <- summary(epi_cl14clbr_table$logFC)
epi_cl14clbr_pvals <- epi_cl14clbr_table$adj.P.Val
names(epi_cl14clbr_pvals) <- rownames(epi_cl14clbr_table)
## Extract the genes with high expression in CL14 compared to Brener and very low pvalues
epi_cl14clbr_high <- subset(epi_cl14clbr_table, logFC >= epi_cl14clbr_summary[5] & adj.P.Val <= pval_thresh)
## Do a goseq comparison of the high genes
epi_cl14clbr_high_go <- simple_goseq(epi_cl14clbr_high, lengths=gene_lengths, goids=go_ids)
epi_cl14clbr_high_go$pvalue_histogram
epi_cl14clbr_high_go$bpp_plot

summary(epi_cl14clbr_high_go)
fun <- epi_cl14clbr_high_go$godata_interesting
goseq_annotation <- goseq_table(fun)
## Oh crap, I cannot make trees until I generate a id2go R mapping, I will need to check my previous
## script for how to do that (I think I do it automatically in simple_topgo()...
##epi_cl14clbr_high_trees = goseq_trees(degenes=epi_cl14clbr_high, epi_cl14clbr_high_go)
## I had to hack the geneTable() function in order to make it not take infinite memory because it
## was trying to do some stupid merge of every gff column against every other column...
## Once the geneTable.rda file exists and included real information, this seems to work fine, though.
epi_cl14clbr_high_cl <- simple_clusterprofiler(epi_cl14clbr_high)
epi_cl14clbr_high_cl$bp_all_barplot
## The first time this is run in a fresh directory, it needs to be run like this:
## simple_topgo(epi_cl14clbr_high, goids_df=go_ids)
## setting goids_df will tell it to generate a table of genes->GO<-genes in the format expected.
epi_cl14clbr_high_top <- simple_topgo(epi_cl14clbr_high, goids=goid_file, pvals=epi_cl14clbr_pvals)

topgo_pval <- topgo_pval_plot(epi_cl14clbr_high_top)
topgo_pval$BP
top_trees <- topgo_trees(epi_cl14clbr_high_top)
top_trees$bp_fisher_tree

1.4 Compare Epimastigotes between CL14 and CLBr, low expression

## Extract the genes with low expression in CL14 compared to Brener and very low pvalues
epi_cl14clbr_low = subset(epi_cl14clbr_table, logFC <= epi_cl14clbr_summary[2] & adj.P.Val <= pval_thresh)
epi_cl14clbr_low_go = simple_goseq(de_genes=epi_cl14clbr_low, lengths=gene_lengths, goids=go_ids)
epi_cl14clbr_low_go$pvalue_histogram
epi_cl14clbr_low_go$bpp_plot
##epi_cl14clbr_low_cl = simple_clusterprofiler(epi_cl14clbr_low, gff="reference/gff/clbrener_8.1_complete_genes.gff.gz")
##epi_cl14clbr_low_cl$bp_all_barplot
epi_cl14clbr_low_top = simple_topgo(epi_cl14clbr_low, goids=goid_file, pvals=epi_cl14clbr_pvals)
topgo_pval = topgo_pval_plot(epi_cl14clbr_high_top)
topgo_pval$BP
top_trees = topgo_trees(epi_cl14clbr_low_top)
top_trees$bp_fisher_tree

1.5 Compare trypo CL14/CLBr

## Changes in epimastigotes from CLBrener to CL14
tryp_cl14clbr_table = all_tables$tryp_cl14clbr
tryp_cl14clbr_summary = summary(tryp_cl14clbr_table$logFC)
tryp_cl14clbr_pvals = tryp_cl14clbr_table$adj.P.Val
names(tryp_cl14clbr_pvals) = rownames(tryp_cl14clbr_table)
## Extract the genes with high expression in CL14 compared to Brener and very low pvalues
tryp_cl14clbr_high = subset(tryp_cl14clbr_table, logFC >= tryp_cl14clbr_summary[5] & adj.P.Val <= pval_thresh)
## Do a goseq comparison of the high genes
tryp_cl14clbr_high_go = simple_goseq(tryp_cl14clbr_high, lengths=gene_lengths, goids=go_ids)
tryp_cl14clbr_high_go$pvalue_histogram
tryp_cl14clbr_high_go$bpp_plot
tryp_cl14clbr_high_cl = simple_clusterprofiler(tryp_cl14clbr_high)
tryp_cl14clbr_high_cl$bp_all_barplot
tryp_cl14clbr_high_top = simple_topgo(tryp_cl14clbr_high, goids=goid_file, pvals=tryp_cl14clbr_pvals)

topgo_pval = topgo_pval_plot(tryp_cl14clbr_high_top)
topgo_pval$BP
top_trees = topgo_trees(tryp_cl14clbr_high_top)
top_trees$bp_fisher_tree

1.6 Compare cl14/clbr tryp other side

## Changes in epimastigotes from CLBrener to CL14
tryp_cl14clbr_table = all_tables$tryp_cl14clbr
tryp_cl14clbr_summary = summary(tryp_cl14clbr_table$logFC)
tryp_cl14clbr_pvals = tryp_cl14clbr_table$adj.P.Val
names(tryp_cl14clbr_pvals) = rownames(tryp_cl14clbr_table)
## Extract the genes with low expression in CL14 compared to Brener and very low pvalues
tryp_cl14clbr_low = subset(tryp_cl14clbr_table, logFC <= tryp_cl14clbr_summary[2] & adj.P.Val <= pval_thresh)
## Do a goseq comparison of the low genes
tryp_cl14clbr_low_go = simple_goseq(tryp_cl14clbr_low, lengths=gene_lengths, goids=go_ids)
tryp_cl14clbr_low_go$pvalue_histogram
tryp_cl14clbr_low_go$bpp_plot
tryp_cl14clbr_low_cl = simple_clusterprofiler(tryp_cl14clbr_low)
tryp_cl14clbr_low_cl$bp_all_barplot
tryp_cl14clbr_low_top = simple_topgo(tryp_cl14clbr_low, goids=goid_file, pvals=tryp_cl14clbr_pvals)

topgo_pval = topgo_pval_plot(tryp_cl14clbr_low_top)
topgo_pval$BP
top_trees = topgo_trees(tryp_cl14clbr_low_top)
top_trees$bp_fisher_tree

1.7 Amastigote a96 cl14/clbr

## Changes in epimastigotes from CLBrener to CL14
a96_cl14clbr_table = all_tables$a96_cl14clbr
a96_cl14clbr_summary = summary(a96_cl14clbr_table$logFC)
a96_cl14clbr_pvals = a96_cl14clbr_table$adj.P.Val
names(a96_cl14clbr_pvals) = rownames(a96_cl14clbr_table)
## Extract the genes with low expression in CL14 compared to Brener and very low pvalues
a96_cl14clbr_low = subset(a96_cl14clbr_table, logFC >= a96_cl14clbr_summary[5] & adj.P.Val <= pval_thresh)
## Do a goseq comparison of the low genes
a96_cl14clbr_low_go = simple_goseq(a96_cl14clbr_low, lengths=gene_lengths, goids=go_ids)
a96_cl14clbr_low_go$pvalue_histogram
a96_cl14clbr_low_go$bpp_plot
a96_cl14clbr_low_cl = simple_clusterprofiler(a96_cl14clbr_low)
a96_cl14clbr_low_cl$bp_all_barplot
a96_cl14clbr_low_top = simple_topgo(a96_cl14clbr_low, goids=goid_file, pvals=a96_cl14clbr_pvals)

topgo_pval = topgo_pval_plot(a96_cl14clbr_low_top)
topgo_pval$BP
top_trees = topgo_trees(a96_cl14clbr_low_top)
top_trees$bp_fisher_tree
## Changes in epimastigotes from CLBrener to CL14
a96_cl14clbr_table = strain_comparisons$data$a96_clbr_over_cl14
a96_cl14clbr_summary = summary(a96_cl14clbr_table$logFC)
a96_cl14clbr_pvals = a96_cl14clbr_table$adj.P.Val
names(a96_cl14clbr_pvals) = rownames(a96_cl14clbr_table)
## Extract the genes with low expression in CL14 compared to Brener and very low pvalues
a96_cl14clbr_low = subset(a96_cl14clbr_table, logFC <= a96_cl14clbr_summary[2] & adj.P.Val <= pval_thresh)
## Do a goseq comparison of the low genes
a96_cl14clbr_low_go = simple_goseq(a96_cl14clbr_low, lengths=gene_lengths, goids=go_ids)
a96_cl14clbr_low_go$pvalue_histogram
a96_cl14clbr_low_go$bpp_plot
a96_cl14clbr_low_cl = simple_clusterprofiler(a96_cl14clbr_low)
a96_cl14clbr_low_cl$bp_all_barplot
a96_cl14clbr_low_top = simple_topgo(a96_cl14clbr_low, goids=goid_file, pvals=a96_cl14clbr_pvals)

topgo_pval = topgo_pval_plot(a96_cl14clbr_low_top)
topgo_pval$BP
top_trees = topgo_trees(a96_cl14clbr_low_top)
top_trees$bp_fisher_tree

## Ways to look
a60_cl14clbr_table = all_tables$a60_cl14clbr
tmp = merge(a60_cl14clbr_table, a96_cl14clbr_table, by="row.names")
tmp_b_t = data.frame(a60=tmp$B.x, a96=tmp$B.y)
tt = hpgl_linear_scatter(tmp_b_t)
tt$scatter
a60_cl14clbr_table = all_tables$a60_cl14clbr
tmp = merge(a60_cl14clbr_table, a96_cl14clbr_table, by="row.names")
tmp_b_t = data.frame(a60=tmp$t.x, a96=tmp$t.y)
tt = hpgl_scatter(tmp_b_t)
tt$scatter

2 KG

Oh yeah, I wrote a toy to wrap KEGG pathway stuff, lets try that. The KEGG abbreviation for t. cruzi is tcr

In theory, the _paths data structure returned by hpgl_pathview() should be a table of the numer of up/down genes observed in each KEGG path. However, there are some weird NAs getting returned. Effing hippies. – fixed.

kegg_list <- ""
##names(kegg_list) = rownames(epi_cl14clbr_table)
##epi_cl14clbr_paths = hpgl_pathview(kegg_list, species="tcr", indir="pathview_in", outdir="pathview_epi_cl14clbr", string_from="TcCLB.", string_to="")
##head(epi_cl14clbr_paths)


##a60_cl14clbr_table = all_tables$a60_cl14clbr
a60_cl14clbr_table <- strain_comparisons$data$a60_clbr_over_cl14
##kegg_list <- a60_cl14clbr_table$logFC
kegg_list <- a60_cl14clbr_table$limma_logfc
names(kegg_list) <- rownames(a60_cl14clbr_table)
a60_cl14clbr_paths <- hpgl_pathview(kegg_list, species="tcr",
                                    indir="pathview_in", outdir="pathview_a60_cl14clbr",
                                    from_list="TcCLB.", to_list="")
head(a60_cl14clbr_paths)

a96_cl14clbr_table = all_tables$a96_cl14clbr
kegg_list = a96_cl14clbr_table$logFC
names(kegg_list) = rownames(a96_cl14clbr_table)
a96_cl14clbr_paths = hpgl_pathview(kegg_list, species="tcr", indir="pathview_in", outdir="pathview_a96_cl14clbr", string_from="TcCLB.", string_to="")
head(a96_cl14clbr_paths)

tryp_cl14clbr_table = all_tables$a96_cl14clbr
kegg_list = tryp_cl14clbr_table$logFC
names(kegg_list) = rownames(tryp_cl14clbr_table)
tryp_cl14clbr_paths = hpgl_pathview(kegg_list, species="tcr", indir="pathview_in", outdir="pathview_tryp_cl14clbr", string_from="TcCLB.", string_to="")
head(tryp_cl14clbr_paths)
LS0tCnRpdGxlOiAiUk5Bc2VxIG9mIFQuY3J1emkgQ0wxNC9DTEJyOiBHZW5lIE9udG9sb2d5LiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCjxzdHlsZT4KICA8IS0tIERvY3VtZW50IHByZWx1ZGUgcmV2aXNpb24gMjAxNi0xMCAtLT4KYm9keSAubWFpbi1jb250YWluZXIgewptYXgtd2lkdGg6IDE2MDBweDsKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KIyMgVGhlc2UgYXJlIHRoZSBvcHRpb25zIEkgdGVuZCB0byBmYXZvcgpsaWJyYXJ5KCJocGdsdG9vbHMiKQp0dCA8LSBzbShkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KAogICAgcHJvZ3Jlc3MgPSBUUlVFLAogICAgdmVyYm9zZSA9IFRSVUUsCiAgICB3aWR0aCA9IDkwLAogICAgZWNobyA9IE5VTEwpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVycm9yID0gVFJVRSwKICAgIGZpZy53aWR0aCA9IDgsCiAgICBmaWcuaGVpZ2h0ID0gOCwKICAgIGRwaSA9IDk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKAogICAgZXJyb3IgPSBOVUxMLAogICAgZGlnaXRzID0gNCwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpzZXQuc2VlZCgxKQpwcmV2aW91c19maWxlIDwtICJkaWZmZXJlbnRpYWxfZXhwcmVzc2lvbi5SbWQiCnJtZF9maWxlIDwtICJnZW5lX29udG9sb2d5LlJtZCIKdmVyIDwtICIyMDE3MDMwMiIKcHJldmlvdXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIucmRhLnh6IiwgeD1wcmV2aW91c19maWxlKSkKdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9Ii5yZGEueHoiLCB4PXJtZF9maWxlKSkKYGBgCgpbaW5kZXguaHRtbF0oaW5kZXguaHRtbCkgW2Fubm90YXRpb24uaHRtbF0oYW5ub3RhdGlvbi5odG1sKQpbc2FtcGxlX2VzdGltYXRpb25zLmh0bWxdKHNhbXBsZV9lc3RpbWF0aW9ucy5odG1sKSBbZGlmZmVyZW50aWFsX2V4cHJlc3Npb24uaHRtbF0oZGlmZmVyZW50aWFsX2V4cHJlc3Npb24uaHRtbCkKCmBgYHtyIHJlbmRlcmluZywgaW5jbHVkZT1GQUxTRSwgZXZhbD1GQUxTRX0KIyMgVGhpcyBibG9jayBpcyB1c2VkIHRvIHJlbmRlciBhIGRvY3VtZW50IGZyb20gd2l0aGluIGl0LgpybWFya2Rvd246OnJlbmRlcihybWRfZmlsZSkKCiMjIEFuIGV4dHJhIHJlbmRlcmVyIGZvciBwZGYgb3V0cHV0CnJtYXJrZG93bjo6cmVuZGVyKHJtZF9maWxlLCBvdXRwdXRfZm9ybWF0PSJwZGZfZG9jdW1lbnQiLCBvdXRwdXRfb3B0aW9ucz1jKCJza2lwX2h0bWwiKSkKIyMgT3IgdG8gc2F2ZS9sb2FkIGxhcmdlIFJkYXRhIGZpbGVzLgpocGdsdG9vbHM6OjpzYXZlbWUoKQpocGdsdG9vbHM6Ojpsb2FkbWUoKQpybShsaXN0PWxzKCkpCmBgYAoKSW4gdGhpcyBkb2N1bWVudCwgd2Ugd2lsbCBwZXJmb3JtIGEgc2VyaWVzIG9mIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2VzIHVzaW5nIHRoZSBkYXRhIHdoaWNoIHN1cnZpdmVkIHNhbXBsZSBlc3RpbWF0aW9uLgoKYGBge3IgbG9hZG1lLCBpbmNsdWRlPUZBTFNFfQp0bXAgPC0gc20obG9hZG1lKGZpbGVuYW1lPXByZXZpb3VzX3NhdmUpKQpgYGAKCiMgR2VuZSBPbnRvbG9neSBzZWFyY2hlcwoKTGV0cyBzZXQgdXAgc29tZSBzaW1wbGUgZGF0YSBzZXRzIGZvciBnb3NlcS9jbHVzdGVyUHJvZmlsZXIvdG9wR08KCkkgdGhpbmsgYSBidW5jaCBvZiB0aGUgbWF0ZXJpYWwgaW4gdGhpcyBzaGVldCBpcyBhY3R1YWxseSBub3cgb2Jzb2xldGUuCgojIyBFeHRyYWN0aW5nIG9udG9sb2d5IGFubm90YXRpb25zIGZyb20gdGhlIFRyaVRyeXBEQgoKSSBuZWVkIHRvIGV4dHJhY3QgdGhlIG9udG9sb2d5L3BGQU0gZGF0YSBmcm9tIHRoZSBUY3J1emkgYW5ub3RhdGlvbgp0YWJsZXMuCgpJIGhhdmUgYSBwZXJsIHNjcmlwdCAnZHVtcF90cml0cnlwX0dPLnBsJyB3aGljaCBjYW4gZG8gdGhpcyBmb3IgbWUuCgpgYGB7ciBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQpjZCAkTEFCL3JlZl9kYXRhL2dlbmVfb250b2xvZ3kvCi4vZHVtcF90cml0cnlwX0dPLnBsICRMQUIvcmVmX2RhdGEvdHJpdHJ5cF90ZXh0L1RjcnV6aS50eHQgPiB0Y3J1emlfZ28udGFiCiMjIFRoZSBhY3R1YWwgY29tbWFuZHMgd2VyZSBzbGlnaHRseSBkaWZmZXJlbnQsIGp1c3QgYmVjYXVzZSBJIGRpZG4ndCBmZWVsIGxpa2UgY29weS9wYXN0aW5nIHRoZSBmaWxlbmFtZXMuCmBgYAoKIyMgUHJlcGFyaW5nIHRvIHVzZSBnb3NlcQoKSSBuZWVkIGEgY291cGxlIHZlY3RvcnMgYmVmb3JlIGJlaW5nIGFibGUgdG8gdXNlIGdvc2VxCkkgYWxzbyBuZWVkIHNvbWUgcmRhIGZpbGVzIGdlbmVyYXRlZCBmb3IgY2x1c3RlclByb2ZpbGVyIGFuZCB0b3BHTwpidXQgSSB3aWxsIGRvIHRob3NlIGxhdGVyLi4uCgpgYGB7ciBnb3NlcV9wcmVwYXJhdGlvbn0KIyMgZ29zZXEgdXNlcyB0aGUgZ2VuZSBsZW5ndGhzLCBjbHVzdGVycHJvZmlsZXIgYW5kIHRvcGdvIGRvbid0CiMjIGdlbmVfbGVuZ3RocyA8LSBhbGxfZ2VuZXNbLGMoImdlbmVpZCIsImdlbmVzaXplIildCiMjIGNvbG5hbWVzKGdlbmVfbGVuZ3RocykgPC0gYygiSUQiLCAid2lkdGgiKQpjb2xuYW1lcyhhbGxfbGVuZ3RocykgPC0gYygiSUQiLCAid2lkdGgiKQojIyBnb19pZHMgbmVlZHMgdG8gYmUgYSAyIGNvbHVtbiBkYXRhIGZyYW1lIHdpdGggbmFtZXMgJ0lEJywgJ0dPJyB3aGljaCBhcmUKIyMgZ2VuZSBuYW1lcyBhbmQgR08gbmFtZXMgcmVzcGVjdGl2ZWx5LiAgSSBhY3R1YWxseSB0aGluayBJIG1hZGUgbXkgZ29zZXEoKSBmdW5jdGlvbgojIyBzbWFydCBlbm91Z2ggdGhhdCB0aGlzIGlzIG5vIGxvbmdlciBuZWVkZWQsIGJ1dCBub25ldGhlbGVzcy4KCiMjIGdvX2lkcyA8LSByZWFkLnRhYmxlKCJyZWZlcmVuY2UvZ28vdGNydXppX2FsbF9nby50YWIuZ3oiLCBoZWFkZXI9MCwgc2VwPSJcdCIpCiMjIGNvbG5hbWVzKGdvX2lkcykgPC0gYygiSUQiLCJHTyIsIm9udG9sb2d5IiwidGVybSIsInNvdXJjZSIpCiMjIFNpbmNlIHRoZXJlIGFyZSBtdWx0aXBsZSBzb3VyY2VzLCBJIGFtIGRvaW5nIGEgdW5pcXVlIG9mIHRoZSB0YWJsZS4uLgojIyBnb19pZHMgPC0gdW5pcXVlKGdvX2lkc1ssYygiSUQiLCJHTyIpXSkKIyMgZ29pZF9maWxlIDwtICJyZWZlcmVuY2UvZ28vdG9wZ29fZ29pZHMudGFiLmd6IgoKY29sbmFtZXMoYWxsX2dvKSA8LSBjKCJJRCIsICJHTyIpCmBgYAoKYGBge3IgZ29zZXFfY2xicl90aW1lczF9CmNsYnJfdXBfYTk2dHJ5cF9nb3NlcSA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPWNsYnJfdGltZXNfc2lnZmlsdCRsaW1tYSR1cHMkY2xicl9hOTZfdG9fdHJ5cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb19kYj1hbGxfZ28sIGxlbmd0aF9kYj1hbGxfbGVuZ3RocykpCmNsYnJfdXBfYTk2dHJ5cF9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbGJyX3VwX2E5NnRyeXBfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShjbGJyX3VwX2E5NnRyeXBfZ29zZXEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvY2xicl91cF9hOTZ0cnlwX2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKY2xicl9kb3duX2E5NnRyeXBfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1jbGJyX3RpbWVzX3NpZ2ZpbHQkbGltbWEkZG93bnMkY2xicl9hOTZfdG9fdHJ5cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKY2xicl9kb3duX2E5NnRyeXBfZ29zZXEkcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKY2xicl9kb3duX2E5NnRyeXBfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShjbGJyX2Rvd25fYTk2dHJ5cF9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL2NsYnJfZG93bl9hOTZ0cnlwX2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKY2xicl91cF9hNjBhOTZfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1jbGJyX3RpbWVzX3NpZ2ZpbHQkbGltbWEkdXBzJGNsYnJfYTYwX3RvX2E5NiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKY2xicl91cF9hNjBhOTZfZ29zZXEkcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKY2xicl91cF9hNjBhOTZfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShjbGJyX3VwX2E2MGE5Nl9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL2NsYnJfdXBfYTYwYTk2X2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKY2xicl9kb3duX2E2MGE5Nl9nb3NlcSA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPWNsYnJfdGltZXNfc2lnZmlsdCRsaW1tYSRkb3ducyRjbGJyX2E2MF90b19hOTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKY2xicl9kb3duX2E2MGE5Nl9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbGJyX2Rvd25fYTYwYTk2X2V4Y2VsIDwtIHNtKHdyaXRlX2dvc2VxX2RhdGEoY2xicl9kb3duX2E2MGE5Nl9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvY2xicl9kb3duX2E2MGE5Nl9nb3NlcS12IiwgdmVyLCAiLnhsc3giKSkpCmNsYnJfdXBfdHJ5cGE2MF9nb3NlcSA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPWNsYnJfdGltZXNfc2lnZmlsdCRsaW1tYSR1cHMkY2xicl90cnlwX3RvX2E2MCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb19kYj1hbGxfZ28sIGxlbmd0aF9kYj1hbGxfbGVuZ3RocykpCmNsYnJfdXBfdHJ5cGE2MF9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbGJyX3VwX3RyeXBhNjBfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShjbGJyX3VwX3RyeXBhNjBfZ29zZXEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvY2xicl91cF90cnlwYTYwX2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKY2xicl9kb3duX3RyeXBhNjBfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1jbGJyX3RpbWVzX3NpZ2ZpbHQkbGltbWEkZG93bnMkY2xicl90cnlwX3RvX2E2MCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKY2xicl9kb3duX3RyeXBhNjBfZ29zZXEkcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKY2xicl9kb3duX3RyeXBhNjBfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShjbGJyX2Rvd25fdHJ5cGE2MF9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL2NsYnJfZG93bl90cnlwYTYwX2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKY2wxNF91cF9hOTZ0cnlwX2dvc2VxIDwtIHNtKHNpbXBsZV9nb3NlcShzaWdfZ2VuZXM9Y2wxNF90aW1lc19zaWdmaWx0JGxpbW1hJHVwcyRjbDE0X2E5Nl90b190cnlwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKY2wxNF91cF9hOTZ0cnlwX2dvc2VxJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmNsMTRfdXBfYTk2dHJ5cF9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKGNsMTRfdXBfYTk2dHJ5cF9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9jbDE0X3VwX2E5NnRyeXBfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpjbDE0X2Rvd25fYTk2dHJ5cF9nb3NlcSA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPWNsMTRfdGltZXNfc2lnZmlsdCRsaW1tYSRkb3ducyRjbDE0X2E5Nl90b190cnlwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29fZGI9YWxsX2dvLCBsZW5ndGhfZGI9YWxsX2xlbmd0aHMpKQpjbDE0X2Rvd25fYTk2dHJ5cF9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbDE0X2Rvd25fYTk2dHJ5cF9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKGNsMTRfZG93bl9hOTZ0cnlwX2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvY2wxNF9kb3duX2E5NnRyeXBfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpjbDE0X3VwX2E2MGE5Nl9nb3NlcSA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPWNsMTRfdGltZXNfc2lnZmlsdCRsaW1tYSR1cHMkY2wxNF9hNjBfdG9fYTk2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29fZGI9YWxsX2dvLCBsZW5ndGhfZGI9YWxsX2xlbmd0aHMpKQpjbDE0X3VwX2E2MGE5Nl9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbDE0X3VwX2E2MGE5Nl9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKGNsMTRfdXBfYTYwYTk2X2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvY2wxNF91cF9hNjBhOTZfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpjbDE0X2Rvd25fYTYwYTk2X2dvc2VxIDwtIHNtKHNpbXBsZV9nb3NlcShzaWdfZ2VuZXM9Y2wxNF90aW1lc19zaWdmaWx0JGxpbW1hJGRvd25zJGNsMTRfYTYwX3RvX2E5NiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29fZGI9YWxsX2dvLCBsZW5ndGhfZGI9YWxsX2xlbmd0aHMpKQpjbDE0X2Rvd25fYTYwYTk2X2dvc2VxJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmNsMTRfZG93bl9hNjBhOTZfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShjbDE0X2Rvd25fYTYwYTk2X2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9jbDE0X2Rvd25fYTYwYTk2X2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKY2wxNF91cF90cnlwYTYwX2dvc2VxIDwtIHNtKHNpbXBsZV9nb3NlcShzaWdfZ2VuZXM9Y2wxNF90aW1lc19zaWdmaWx0JGxpbW1hJHVwcyRjbDE0X3RyeXBfdG9fYTYwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKY2wxNF91cF90cnlwYTYwX2dvc2VxJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmNsMTRfdXBfdHJ5cGE2MF9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKGNsMTRfdXBfdHJ5cGE2MF9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9jbDE0X3VwX3RyeXBhNjBfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpjbDE0X2Rvd25fdHJ5cGE2MF9nb3NlcSA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPWNsMTRfdGltZXNfc2lnZmlsdCRsaW1tYSRkb3ducyRjbDE0X3RyeXBfdG9fYTYwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29fZGI9YWxsX2dvLCBsZW5ndGhfZGI9YWxsX2xlbmd0aHMpKQpjbDE0X2Rvd25fdHJ5cGE2MF9nb3NlcSRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbDE0X2Rvd25fdHJ5cGE2MF9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKGNsMTRfZG93bl90cnlwYTYwX2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvY2wxNF9kb3duX3RyeXBhNjBfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQoKc3RyYWluc191cF9hNjBfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1zdHJhaW5zX3NpZ2ZpbHQkbGltbWEkdXBzJGE2MF9jbGJyX292ZXJfY2wxNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKc3RyYWluc191cF9hOTZfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1zdHJhaW5zX3NpZ2ZpbHQkbGltbWEkdXBzJGE5Nl9jbGJyX292ZXJfY2wxNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKc3RyYWluc191cF90cnlwX2dvc2VxIDwtIHNtKHNpbXBsZV9nb3NlcShzaWdfZ2VuZXM9c3RyYWluc19zaWdmaWx0JGxpbW1hJHVwcyR0cnlwX2NsYnJfb3Zlcl9jbDE0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvX2RiPWFsbF9nbywgbGVuZ3RoX2RiPWFsbF9sZW5ndGhzKSkKc3RyYWluc191cF9hNjBfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShzdHJhaW5zX3VwX2E2MF9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL3N0cmFpbnNfdXBhNjBfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpzdHJhaW5zX3VwX2E5Nl9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKHN0cmFpbnNfdXBfYTk2X2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvc3RyYWluc191cGE5Nl9nb3NlcS12IiwgdmVyLCAiLnhsc3giKSkpCnN0cmFpbnNfdXBfdHJ5cF9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKHN0cmFpbnNfdXBfdHJ5cF9nb3NlcSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9zdHJhaW5zX3VwdHJ5cF9nb3NlcS12IiwgdmVyLCAiLnhsc3giKSkpCnN0cmFpbnNfZG93bl9hNjBfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1zdHJhaW5zX3NpZ2ZpbHQkbGltbWEkZG93bnMkYTYwX2NsYnJfb3Zlcl9jbDE0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb19kYj1hbGxfZ28sIGxlbmd0aF9kYj1hbGxfbGVuZ3RocykpCnN0cmFpbnNfZG93bl9hOTZfZ29zZXEgPC0gc20oc2ltcGxlX2dvc2VxKHNpZ19nZW5lcz1zdHJhaW5zX3NpZ2ZpbHQkbGltbWEkZG93bnMkYTk2X2NsYnJfb3Zlcl9jbDE0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb19kYj1hbGxfZ28sIGxlbmd0aF9kYj1hbGxfbGVuZ3RocykpCnN0cmFpbnNfZG93bl90cnlwX2dvc2VxIDwtIHNtKHNpbXBsZV9nb3NlcShzaWdfZ2VuZXM9c3RyYWluc19zaWdmaWx0JGxpbW1hJGRvd25zJHRyeXBfY2xicl9vdmVyX2NsMTQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb19kYj1hbGxfZ28sIGxlbmd0aF9kYj1hbGxfbGVuZ3RocykpCnN0cmFpbnNfZG93bl9hNjBfZXhjZWwgPC0gc20od3JpdGVfZ29zZXFfZGF0YShzdHJhaW5zX2Rvd25fYTYwX2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPXBhc3RlMCgiZXhjZWwvc3RyYWluc19kb3duYTYwX2dvc2VxLXYiLCB2ZXIsICIueGxzeCIpKSkKc3RyYWluc19kb3duX2E5Nl9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKHN0cmFpbnNfZG93bl9hOTZfZ29zZXEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9zdHJhaW5zX2Rvd25hOTZfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpzdHJhaW5zX2Rvd25fdHJ5cF9leGNlbCA8LSBzbSh3cml0ZV9nb3NlcV9kYXRhKHN0cmFpbnNfZG93bl90cnlwX2dvc2VxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1wYXN0ZTAoImV4Y2VsL3N0cmFpbnNfZG93bnRyeXBfZ29zZXEtdiIsIHZlciwgIi54bHN4IikpKQpgYGAKCiMjIENvbXBhcmUgRXBpbWFzdGlnb3RlcyBiZXR3ZWVuIENMMTQgYW5kIENMQnIsIGhpZ2ggZXhwcmVzc2lvbgoKT25lIGltcG9ydGFudCBub3RlIGhlcmUsIEkgbmVlZGVkIHRvIG1vZGlmeSB0aGUgZGF0YSBzdHJ1Y3R1cmUgZnJvbSByZWFkR2ZmKCkgaW4gY2x1c3RlclByb2ZpbGVyCmJlZm9yZSBpdCB3YXMgYWJsZSB0byBzdWNjZXNzZnVsbHkgZ2VuZXJhdGUgdGhlIGZpbGUgJ2dlbmVUYWJsZS5yZGEnClVuZm9ydHVuYXRlbHksIEkgd2FzIHdhdGNoaW5nIGEgbW92aWUgYXQgdGhlIHRpbWUgYW5kIGRpZG4ndCBwcm9wZXJseSB3cml0ZSBkb3duIHdoYXQgSSBkaWQuCkhvd2V2ZXIsIEkgZGlkIHdyaXRlIGl0IG91dCBpbiB0aGUgZnVuY3Rpb24gbXlyOjpHZmYyR2VuZVRhYmxlKCkKYnV0IGluIG9yZGVyIHRvIG1ha2UgaXQgd29yayBvbmUgbXVzdCBsb2FkIHJlYWRHZmYoKSBmcm9tIGNsdXN0ZXJQcm9maWxlci4KSSB0aGluayB0aGUgcmVhbCBzb2x1dGlvbiBpcyBmb3IgbWUgdG8gZ3JhYiBhIHZlcnNpb24gb2YgcmVhZEdmZigpIGZyb20gY2x1c3RlclByb2ZpbGVyCmFuZCBtYWtlIGl0IGV4cG9ydGFibGUgc28gdGhhdCBpdCB3aWxsIHdvcmsgY29uc2lzdGVudGx5LgoKYGBge3Igb250b2xvZ3lfZXBpX2NsMTRjbHJfaGlnaCwgZXZhbD1GQUxTRX0KIyMgQ2hhbmdlcyBpbiBlcGltYXN0aWdvdGVzIGZyb20gQ0xCcmVuZXIgdG8gQ0wxNApwdmFsX3RocmVzaCA8LSAwLjAwMDEKZXBpX2NsMTRjbGJyX3RhYmxlIDwtIGFsbF90YWJsZXMkZXBpX2NsMTRjbGJyCmVwaV9jbDE0Y2xicl9zdW1tYXJ5IDwtIHN1bW1hcnkoZXBpX2NsMTRjbGJyX3RhYmxlJGxvZ0ZDKQplcGlfY2wxNGNsYnJfcHZhbHMgPC0gZXBpX2NsMTRjbGJyX3RhYmxlJGFkai5QLlZhbApuYW1lcyhlcGlfY2wxNGNsYnJfcHZhbHMpIDwtIHJvd25hbWVzKGVwaV9jbDE0Y2xicl90YWJsZSkKIyMgRXh0cmFjdCB0aGUgZ2VuZXMgd2l0aCBoaWdoIGV4cHJlc3Npb24gaW4gQ0wxNCBjb21wYXJlZCB0byBCcmVuZXIgYW5kIHZlcnkgbG93IHB2YWx1ZXMKZXBpX2NsMTRjbGJyX2hpZ2ggPC0gc3Vic2V0KGVwaV9jbDE0Y2xicl90YWJsZSwgbG9nRkMgPj0gZXBpX2NsMTRjbGJyX3N1bW1hcnlbNV0gJiBhZGouUC5WYWwgPD0gcHZhbF90aHJlc2gpCiMjIERvIGEgZ29zZXEgY29tcGFyaXNvbiBvZiB0aGUgaGlnaCBnZW5lcwplcGlfY2wxNGNsYnJfaGlnaF9nbyA8LSBzaW1wbGVfZ29zZXEoZXBpX2NsMTRjbGJyX2hpZ2gsIGxlbmd0aHM9Z2VuZV9sZW5ndGhzLCBnb2lkcz1nb19pZHMpCmVwaV9jbDE0Y2xicl9oaWdoX2dvJHB2YWx1ZV9oaXN0b2dyYW0KZXBpX2NsMTRjbGJyX2hpZ2hfZ28kYnBwX3Bsb3QKCnN1bW1hcnkoZXBpX2NsMTRjbGJyX2hpZ2hfZ28pCmZ1biA8LSBlcGlfY2wxNGNsYnJfaGlnaF9nbyRnb2RhdGFfaW50ZXJlc3RpbmcKZ29zZXFfYW5ub3RhdGlvbiA8LSBnb3NlcV90YWJsZShmdW4pCiMjIE9oIGNyYXAsIEkgY2Fubm90IG1ha2UgdHJlZXMgdW50aWwgSSBnZW5lcmF0ZSBhIGlkMmdvIFIgbWFwcGluZywgSSB3aWxsIG5lZWQgdG8gY2hlY2sgbXkgcHJldmlvdXMKIyMgc2NyaXB0IGZvciBob3cgdG8gZG8gdGhhdCAoSSB0aGluayBJIGRvIGl0IGF1dG9tYXRpY2FsbHkgaW4gc2ltcGxlX3RvcGdvKCkuLi4KIyNlcGlfY2wxNGNsYnJfaGlnaF90cmVlcyA9IGdvc2VxX3RyZWVzKGRlZ2VuZXM9ZXBpX2NsMTRjbGJyX2hpZ2gsIGVwaV9jbDE0Y2xicl9oaWdoX2dvKQojIyBJIGhhZCB0byBoYWNrIHRoZSBnZW5lVGFibGUoKSBmdW5jdGlvbiBpbiBvcmRlciB0byBtYWtlIGl0IG5vdCB0YWtlIGluZmluaXRlIG1lbW9yeSBiZWNhdXNlIGl0CiMjIHdhcyB0cnlpbmcgdG8gZG8gc29tZSBzdHVwaWQgbWVyZ2Ugb2YgZXZlcnkgZ2ZmIGNvbHVtbiBhZ2FpbnN0IGV2ZXJ5IG90aGVyIGNvbHVtbi4uLgojIyBPbmNlIHRoZSBnZW5lVGFibGUucmRhIGZpbGUgZXhpc3RzIGFuZCBpbmNsdWRlZCByZWFsIGluZm9ybWF0aW9uLCB0aGlzIHNlZW1zIHRvIHdvcmsgZmluZSwgdGhvdWdoLgplcGlfY2wxNGNsYnJfaGlnaF9jbCA8LSBzaW1wbGVfY2x1c3RlcnByb2ZpbGVyKGVwaV9jbDE0Y2xicl9oaWdoKQplcGlfY2wxNGNsYnJfaGlnaF9jbCRicF9hbGxfYmFycGxvdAojIyBUaGUgZmlyc3QgdGltZSB0aGlzIGlzIHJ1biBpbiBhIGZyZXNoIGRpcmVjdG9yeSwgaXQgbmVlZHMgdG8gYmUgcnVuIGxpa2UgdGhpczoKIyMgc2ltcGxlX3RvcGdvKGVwaV9jbDE0Y2xicl9oaWdoLCBnb2lkc19kZj1nb19pZHMpCiMjIHNldHRpbmcgZ29pZHNfZGYgd2lsbCB0ZWxsIGl0IHRvIGdlbmVyYXRlIGEgdGFibGUgb2YgZ2VuZXMtPkdPPC1nZW5lcyBpbiB0aGUgZm9ybWF0IGV4cGVjdGVkLgplcGlfY2wxNGNsYnJfaGlnaF90b3AgPC0gc2ltcGxlX3RvcGdvKGVwaV9jbDE0Y2xicl9oaWdoLCBnb2lkcz1nb2lkX2ZpbGUsIHB2YWxzPWVwaV9jbDE0Y2xicl9wdmFscykKCnRvcGdvX3B2YWwgPC0gdG9wZ29fcHZhbF9wbG90KGVwaV9jbDE0Y2xicl9oaWdoX3RvcCkKdG9wZ29fcHZhbCRCUAp0b3BfdHJlZXMgPC0gdG9wZ29fdHJlZXMoZXBpX2NsMTRjbGJyX2hpZ2hfdG9wKQp0b3BfdHJlZXMkYnBfZmlzaGVyX3RyZWUKYGBgCgojIyBDb21wYXJlIEVwaW1hc3RpZ290ZXMgYmV0d2VlbiBDTDE0IGFuZCBDTEJyLCBsb3cgZXhwcmVzc2lvbgoKYGBge3Igb250b2xvZ3lfZXBpX2NsMTRjbGJyX2xvdywgZXZhbD1GQUxTRX0KIyMgRXh0cmFjdCB0aGUgZ2VuZXMgd2l0aCBsb3cgZXhwcmVzc2lvbiBpbiBDTDE0IGNvbXBhcmVkIHRvIEJyZW5lciBhbmQgdmVyeSBsb3cgcHZhbHVlcwplcGlfY2wxNGNsYnJfbG93ID0gc3Vic2V0KGVwaV9jbDE0Y2xicl90YWJsZSwgbG9nRkMgPD0gZXBpX2NsMTRjbGJyX3N1bW1hcnlbMl0gJiBhZGouUC5WYWwgPD0gcHZhbF90aHJlc2gpCmVwaV9jbDE0Y2xicl9sb3dfZ28gPSBzaW1wbGVfZ29zZXEoZGVfZ2VuZXM9ZXBpX2NsMTRjbGJyX2xvdywgbGVuZ3Rocz1nZW5lX2xlbmd0aHMsIGdvaWRzPWdvX2lkcykKZXBpX2NsMTRjbGJyX2xvd19nbyRwdmFsdWVfaGlzdG9ncmFtCmVwaV9jbDE0Y2xicl9sb3dfZ28kYnBwX3Bsb3QKIyNlcGlfY2wxNGNsYnJfbG93X2NsID0gc2ltcGxlX2NsdXN0ZXJwcm9maWxlcihlcGlfY2wxNGNsYnJfbG93LCBnZmY9InJlZmVyZW5jZS9nZmYvY2xicmVuZXJfOC4xX2NvbXBsZXRlX2dlbmVzLmdmZi5neiIpCiMjZXBpX2NsMTRjbGJyX2xvd19jbCRicF9hbGxfYmFycGxvdAplcGlfY2wxNGNsYnJfbG93X3RvcCA9IHNpbXBsZV90b3BnbyhlcGlfY2wxNGNsYnJfbG93LCBnb2lkcz1nb2lkX2ZpbGUsIHB2YWxzPWVwaV9jbDE0Y2xicl9wdmFscykKdG9wZ29fcHZhbCA9IHRvcGdvX3B2YWxfcGxvdChlcGlfY2wxNGNsYnJfaGlnaF90b3ApCnRvcGdvX3B2YWwkQlAKdG9wX3RyZWVzID0gdG9wZ29fdHJlZXMoZXBpX2NsMTRjbGJyX2xvd190b3ApCnRvcF90cmVlcyRicF9maXNoZXJfdHJlZQpgYGAKCiMjIENvbXBhcmUgdHJ5cG8gQ0wxNC9DTEJyCgpgYGB7ciB0cnlwX2NsMTRjbGJyX2hpZ2hfZ29zZXEsIGV2YWw9RkFMU0V9CiMjIENoYW5nZXMgaW4gZXBpbWFzdGlnb3RlcyBmcm9tIENMQnJlbmVyIHRvIENMMTQKdHJ5cF9jbDE0Y2xicl90YWJsZSA9IGFsbF90YWJsZXMkdHJ5cF9jbDE0Y2xicgp0cnlwX2NsMTRjbGJyX3N1bW1hcnkgPSBzdW1tYXJ5KHRyeXBfY2wxNGNsYnJfdGFibGUkbG9nRkMpCnRyeXBfY2wxNGNsYnJfcHZhbHMgPSB0cnlwX2NsMTRjbGJyX3RhYmxlJGFkai5QLlZhbApuYW1lcyh0cnlwX2NsMTRjbGJyX3B2YWxzKSA9IHJvd25hbWVzKHRyeXBfY2wxNGNsYnJfdGFibGUpCiMjIEV4dHJhY3QgdGhlIGdlbmVzIHdpdGggaGlnaCBleHByZXNzaW9uIGluIENMMTQgY29tcGFyZWQgdG8gQnJlbmVyIGFuZCB2ZXJ5IGxvdyBwdmFsdWVzCnRyeXBfY2wxNGNsYnJfaGlnaCA9IHN1YnNldCh0cnlwX2NsMTRjbGJyX3RhYmxlLCBsb2dGQyA+PSB0cnlwX2NsMTRjbGJyX3N1bW1hcnlbNV0gJiBhZGouUC5WYWwgPD0gcHZhbF90aHJlc2gpCiMjIERvIGEgZ29zZXEgY29tcGFyaXNvbiBvZiB0aGUgaGlnaCBnZW5lcwp0cnlwX2NsMTRjbGJyX2hpZ2hfZ28gPSBzaW1wbGVfZ29zZXEodHJ5cF9jbDE0Y2xicl9oaWdoLCBsZW5ndGhzPWdlbmVfbGVuZ3RocywgZ29pZHM9Z29faWRzKQp0cnlwX2NsMTRjbGJyX2hpZ2hfZ28kcHZhbHVlX2hpc3RvZ3JhbQp0cnlwX2NsMTRjbGJyX2hpZ2hfZ28kYnBwX3Bsb3QKdHJ5cF9jbDE0Y2xicl9oaWdoX2NsID0gc2ltcGxlX2NsdXN0ZXJwcm9maWxlcih0cnlwX2NsMTRjbGJyX2hpZ2gpCnRyeXBfY2wxNGNsYnJfaGlnaF9jbCRicF9hbGxfYmFycGxvdAp0cnlwX2NsMTRjbGJyX2hpZ2hfdG9wID0gc2ltcGxlX3RvcGdvKHRyeXBfY2wxNGNsYnJfaGlnaCwgZ29pZHM9Z29pZF9maWxlLCBwdmFscz10cnlwX2NsMTRjbGJyX3B2YWxzKQoKdG9wZ29fcHZhbCA9IHRvcGdvX3B2YWxfcGxvdCh0cnlwX2NsMTRjbGJyX2hpZ2hfdG9wKQp0b3Bnb19wdmFsJEJQCnRvcF90cmVlcyA9IHRvcGdvX3RyZWVzKHRyeXBfY2wxNGNsYnJfaGlnaF90b3ApCnRvcF90cmVlcyRicF9maXNoZXJfdHJlZQpgYGAKCiMjIENvbXBhcmUgY2wxNC9jbGJyIHRyeXAgb3RoZXIgc2lkZQoKYGBge3IgdHJ5cF9jbDE0Y2xicl9sb3dfZ29zZXEsIGV2YWw9RkFMU0V9CiMjIENoYW5nZXMgaW4gZXBpbWFzdGlnb3RlcyBmcm9tIENMQnJlbmVyIHRvIENMMTQKdHJ5cF9jbDE0Y2xicl90YWJsZSA9IGFsbF90YWJsZXMkdHJ5cF9jbDE0Y2xicgp0cnlwX2NsMTRjbGJyX3N1bW1hcnkgPSBzdW1tYXJ5KHRyeXBfY2wxNGNsYnJfdGFibGUkbG9nRkMpCnRyeXBfY2wxNGNsYnJfcHZhbHMgPSB0cnlwX2NsMTRjbGJyX3RhYmxlJGFkai5QLlZhbApuYW1lcyh0cnlwX2NsMTRjbGJyX3B2YWxzKSA9IHJvd25hbWVzKHRyeXBfY2wxNGNsYnJfdGFibGUpCiMjIEV4dHJhY3QgdGhlIGdlbmVzIHdpdGggbG93IGV4cHJlc3Npb24gaW4gQ0wxNCBjb21wYXJlZCB0byBCcmVuZXIgYW5kIHZlcnkgbG93IHB2YWx1ZXMKdHJ5cF9jbDE0Y2xicl9sb3cgPSBzdWJzZXQodHJ5cF9jbDE0Y2xicl90YWJsZSwgbG9nRkMgPD0gdHJ5cF9jbDE0Y2xicl9zdW1tYXJ5WzJdICYgYWRqLlAuVmFsIDw9IHB2YWxfdGhyZXNoKQojIyBEbyBhIGdvc2VxIGNvbXBhcmlzb24gb2YgdGhlIGxvdyBnZW5lcwp0cnlwX2NsMTRjbGJyX2xvd19nbyA9IHNpbXBsZV9nb3NlcSh0cnlwX2NsMTRjbGJyX2xvdywgbGVuZ3Rocz1nZW5lX2xlbmd0aHMsIGdvaWRzPWdvX2lkcykKdHJ5cF9jbDE0Y2xicl9sb3dfZ28kcHZhbHVlX2hpc3RvZ3JhbQp0cnlwX2NsMTRjbGJyX2xvd19nbyRicHBfcGxvdAp0cnlwX2NsMTRjbGJyX2xvd19jbCA9IHNpbXBsZV9jbHVzdGVycHJvZmlsZXIodHJ5cF9jbDE0Y2xicl9sb3cpCnRyeXBfY2wxNGNsYnJfbG93X2NsJGJwX2FsbF9iYXJwbG90CnRyeXBfY2wxNGNsYnJfbG93X3RvcCA9IHNpbXBsZV90b3Bnbyh0cnlwX2NsMTRjbGJyX2xvdywgZ29pZHM9Z29pZF9maWxlLCBwdmFscz10cnlwX2NsMTRjbGJyX3B2YWxzKQoKdG9wZ29fcHZhbCA9IHRvcGdvX3B2YWxfcGxvdCh0cnlwX2NsMTRjbGJyX2xvd190b3ApCnRvcGdvX3B2YWwkQlAKdG9wX3RyZWVzID0gdG9wZ29fdHJlZXModHJ5cF9jbDE0Y2xicl9sb3dfdG9wKQp0b3BfdHJlZXMkYnBfZmlzaGVyX3RyZWUKYGBgCgojIyBBbWFzdGlnb3RlIGE5NiBjbDE0L2NsYnIKCmBgYHtyIG9udG9sb2d5X2E5Nl9jbDE0Y2xicl9oaWdoLCBldmFsPUZBTFNFfQojIyBDaGFuZ2VzIGluIGVwaW1hc3RpZ290ZXMgZnJvbSBDTEJyZW5lciB0byBDTDE0CmE5Nl9jbDE0Y2xicl90YWJsZSA9IGFsbF90YWJsZXMkYTk2X2NsMTRjbGJyCmE5Nl9jbDE0Y2xicl9zdW1tYXJ5ID0gc3VtbWFyeShhOTZfY2wxNGNsYnJfdGFibGUkbG9nRkMpCmE5Nl9jbDE0Y2xicl9wdmFscyA9IGE5Nl9jbDE0Y2xicl90YWJsZSRhZGouUC5WYWwKbmFtZXMoYTk2X2NsMTRjbGJyX3B2YWxzKSA9IHJvd25hbWVzKGE5Nl9jbDE0Y2xicl90YWJsZSkKIyMgRXh0cmFjdCB0aGUgZ2VuZXMgd2l0aCBsb3cgZXhwcmVzc2lvbiBpbiBDTDE0IGNvbXBhcmVkIHRvIEJyZW5lciBhbmQgdmVyeSBsb3cgcHZhbHVlcwphOTZfY2wxNGNsYnJfbG93ID0gc3Vic2V0KGE5Nl9jbDE0Y2xicl90YWJsZSwgbG9nRkMgPj0gYTk2X2NsMTRjbGJyX3N1bW1hcnlbNV0gJiBhZGouUC5WYWwgPD0gcHZhbF90aHJlc2gpCiMjIERvIGEgZ29zZXEgY29tcGFyaXNvbiBvZiB0aGUgbG93IGdlbmVzCmE5Nl9jbDE0Y2xicl9sb3dfZ28gPSBzaW1wbGVfZ29zZXEoYTk2X2NsMTRjbGJyX2xvdywgbGVuZ3Rocz1nZW5lX2xlbmd0aHMsIGdvaWRzPWdvX2lkcykKYTk2X2NsMTRjbGJyX2xvd19nbyRwdmFsdWVfaGlzdG9ncmFtCmE5Nl9jbDE0Y2xicl9sb3dfZ28kYnBwX3Bsb3QKYTk2X2NsMTRjbGJyX2xvd19jbCA9IHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoYTk2X2NsMTRjbGJyX2xvdykKYTk2X2NsMTRjbGJyX2xvd19jbCRicF9hbGxfYmFycGxvdAphOTZfY2wxNGNsYnJfbG93X3RvcCA9IHNpbXBsZV90b3BnbyhhOTZfY2wxNGNsYnJfbG93LCBnb2lkcz1nb2lkX2ZpbGUsIHB2YWxzPWE5Nl9jbDE0Y2xicl9wdmFscykKCnRvcGdvX3B2YWwgPSB0b3Bnb19wdmFsX3Bsb3QoYTk2X2NsMTRjbGJyX2xvd190b3ApCnRvcGdvX3B2YWwkQlAKdG9wX3RyZWVzID0gdG9wZ29fdHJlZXMoYTk2X2NsMTRjbGJyX2xvd190b3ApCnRvcF90cmVlcyRicF9maXNoZXJfdHJlZQpgYGAKCmBgYHtyIG9udG9sb2d5X2E5Nl9jbDE0Y2xicl9sb3csIGV2YWw9RkFMU0V9CiMjIENoYW5nZXMgaW4gZXBpbWFzdGlnb3RlcyBmcm9tIENMQnJlbmVyIHRvIENMMTQKYTk2X2NsMTRjbGJyX3RhYmxlID0gc3RyYWluX2NvbXBhcmlzb25zJGRhdGEkYTk2X2NsYnJfb3Zlcl9jbDE0CmE5Nl9jbDE0Y2xicl9zdW1tYXJ5ID0gc3VtbWFyeShhOTZfY2wxNGNsYnJfdGFibGUkbG9nRkMpCmE5Nl9jbDE0Y2xicl9wdmFscyA9IGE5Nl9jbDE0Y2xicl90YWJsZSRhZGouUC5WYWwKbmFtZXMoYTk2X2NsMTRjbGJyX3B2YWxzKSA9IHJvd25hbWVzKGE5Nl9jbDE0Y2xicl90YWJsZSkKIyMgRXh0cmFjdCB0aGUgZ2VuZXMgd2l0aCBsb3cgZXhwcmVzc2lvbiBpbiBDTDE0IGNvbXBhcmVkIHRvIEJyZW5lciBhbmQgdmVyeSBsb3cgcHZhbHVlcwphOTZfY2wxNGNsYnJfbG93ID0gc3Vic2V0KGE5Nl9jbDE0Y2xicl90YWJsZSwgbG9nRkMgPD0gYTk2X2NsMTRjbGJyX3N1bW1hcnlbMl0gJiBhZGouUC5WYWwgPD0gcHZhbF90aHJlc2gpCiMjIERvIGEgZ29zZXEgY29tcGFyaXNvbiBvZiB0aGUgbG93IGdlbmVzCmE5Nl9jbDE0Y2xicl9sb3dfZ28gPSBzaW1wbGVfZ29zZXEoYTk2X2NsMTRjbGJyX2xvdywgbGVuZ3Rocz1nZW5lX2xlbmd0aHMsIGdvaWRzPWdvX2lkcykKYTk2X2NsMTRjbGJyX2xvd19nbyRwdmFsdWVfaGlzdG9ncmFtCmE5Nl9jbDE0Y2xicl9sb3dfZ28kYnBwX3Bsb3QKYTk2X2NsMTRjbGJyX2xvd19jbCA9IHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoYTk2X2NsMTRjbGJyX2xvdykKYTk2X2NsMTRjbGJyX2xvd19jbCRicF9hbGxfYmFycGxvdAphOTZfY2wxNGNsYnJfbG93X3RvcCA9IHNpbXBsZV90b3BnbyhhOTZfY2wxNGNsYnJfbG93LCBnb2lkcz1nb2lkX2ZpbGUsIHB2YWxzPWE5Nl9jbDE0Y2xicl9wdmFscykKCnRvcGdvX3B2YWwgPSB0b3Bnb19wdmFsX3Bsb3QoYTk2X2NsMTRjbGJyX2xvd190b3ApCnRvcGdvX3B2YWwkQlAKdG9wX3RyZWVzID0gdG9wZ29fdHJlZXMoYTk2X2NsMTRjbGJyX2xvd190b3ApCnRvcF90cmVlcyRicF9maXNoZXJfdHJlZQoKIyMgV2F5cyB0byBsb29rCmE2MF9jbDE0Y2xicl90YWJsZSA9IGFsbF90YWJsZXMkYTYwX2NsMTRjbGJyCnRtcCA9IG1lcmdlKGE2MF9jbDE0Y2xicl90YWJsZSwgYTk2X2NsMTRjbGJyX3RhYmxlLCBieT0icm93Lm5hbWVzIikKdG1wX2JfdCA9IGRhdGEuZnJhbWUoYTYwPXRtcCRCLngsIGE5Nj10bXAkQi55KQp0dCA9IGhwZ2xfbGluZWFyX3NjYXR0ZXIodG1wX2JfdCkKdHQkc2NhdHRlcgphNjBfY2wxNGNsYnJfdGFibGUgPSBhbGxfdGFibGVzJGE2MF9jbDE0Y2xicgp0bXAgPSBtZXJnZShhNjBfY2wxNGNsYnJfdGFibGUsIGE5Nl9jbDE0Y2xicl90YWJsZSwgYnk9InJvdy5uYW1lcyIpCnRtcF9iX3QgPSBkYXRhLmZyYW1lKGE2MD10bXAkdC54LCBhOTY9dG1wJHQueSkKdHQgPSBocGdsX3NjYXR0ZXIodG1wX2JfdCkKdHQkc2NhdHRlcgpgYGAKCiMgS0cKCk9oIHllYWgsIEkgd3JvdGUgYSB0b3kgdG8gd3JhcCBLRUdHIHBhdGh3YXkgc3R1ZmYsIGxldHMgdHJ5IHRoYXQuClRoZSBLRUdHIGFiYnJldmlhdGlvbiBmb3IgdC4gY3J1emkgaXMgdGNyCgpJbiB0aGVvcnksIHRoZSBfcGF0aHMgZGF0YSBzdHJ1Y3R1cmUgcmV0dXJuZWQgYnkgaHBnbF9wYXRodmlldygpIHNob3VsZCBiZSBhIHRhYmxlCm9mIHRoZSBudW1lciBvZiB1cC9kb3duIGdlbmVzIG9ic2VydmVkIGluIGVhY2ggS0VHRyBwYXRoLiAgSG93ZXZlciwgdGhlcmUgYXJlIHNvbWUKd2VpcmQgTkFzIGdldHRpbmcgcmV0dXJuZWQuICAgRWZmaW5nIGhpcHBpZXMuIC0tIGZpeGVkLgoKYGBge3Iga2VnZ19mdW5fdjF9CmtlZ2dfbGlzdCA8LSAiIgpgYGAKCmBgYHtyIGtlZ2dfZnVuX3YyLCBldmFsPUZBTFNFfQojI25hbWVzKGtlZ2dfbGlzdCkgPSByb3duYW1lcyhlcGlfY2wxNGNsYnJfdGFibGUpCiMjZXBpX2NsMTRjbGJyX3BhdGhzID0gaHBnbF9wYXRodmlldyhrZWdnX2xpc3QsIHNwZWNpZXM9InRjciIsIGluZGlyPSJwYXRodmlld19pbiIsIG91dGRpcj0icGF0aHZpZXdfZXBpX2NsMTRjbGJyIiwgc3RyaW5nX2Zyb209IlRjQ0xCLiIsIHN0cmluZ190bz0iIikKIyNoZWFkKGVwaV9jbDE0Y2xicl9wYXRocykKCgojI2E2MF9jbDE0Y2xicl90YWJsZSA9IGFsbF90YWJsZXMkYTYwX2NsMTRjbGJyCmE2MF9jbDE0Y2xicl90YWJsZSA8LSBzdHJhaW5fY29tcGFyaXNvbnMkZGF0YSRhNjBfY2xicl9vdmVyX2NsMTQKIyNrZWdnX2xpc3QgPC0gYTYwX2NsMTRjbGJyX3RhYmxlJGxvZ0ZDCmtlZ2dfbGlzdCA8LSBhNjBfY2wxNGNsYnJfdGFibGUkbGltbWFfbG9nZmMKbmFtZXMoa2VnZ19saXN0KSA8LSByb3duYW1lcyhhNjBfY2wxNGNsYnJfdGFibGUpCmE2MF9jbDE0Y2xicl9wYXRocyA8LSBocGdsX3BhdGh2aWV3KGtlZ2dfbGlzdCwgc3BlY2llcz0idGNyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kaXI9InBhdGh2aWV3X2luIiwgb3V0ZGlyPSJwYXRodmlld19hNjBfY2wxNGNsYnIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tX2xpc3Q9IlRjQ0xCLiIsIHRvX2xpc3Q9IiIpCmhlYWQoYTYwX2NsMTRjbGJyX3BhdGhzKQoKYTk2X2NsMTRjbGJyX3RhYmxlID0gYWxsX3RhYmxlcyRhOTZfY2wxNGNsYnIKa2VnZ19saXN0ID0gYTk2X2NsMTRjbGJyX3RhYmxlJGxvZ0ZDCm5hbWVzKGtlZ2dfbGlzdCkgPSByb3duYW1lcyhhOTZfY2wxNGNsYnJfdGFibGUpCmE5Nl9jbDE0Y2xicl9wYXRocyA9IGhwZ2xfcGF0aHZpZXcoa2VnZ19saXN0LCBzcGVjaWVzPSJ0Y3IiLCBpbmRpcj0icGF0aHZpZXdfaW4iLCBvdXRkaXI9InBhdGh2aWV3X2E5Nl9jbDE0Y2xiciIsIHN0cmluZ19mcm9tPSJUY0NMQi4iLCBzdHJpbmdfdG89IiIpCmhlYWQoYTk2X2NsMTRjbGJyX3BhdGhzKQoKdHJ5cF9jbDE0Y2xicl90YWJsZSA9IGFsbF90YWJsZXMkYTk2X2NsMTRjbGJyCmtlZ2dfbGlzdCA9IHRyeXBfY2wxNGNsYnJfdGFibGUkbG9nRkMKbmFtZXMoa2VnZ19saXN0KSA9IHJvd25hbWVzKHRyeXBfY2wxNGNsYnJfdGFibGUpCnRyeXBfY2wxNGNsYnJfcGF0aHMgPSBocGdsX3BhdGh2aWV3KGtlZ2dfbGlzdCwgc3BlY2llcz0idGNyIiwgaW5kaXI9InBhdGh2aWV3X2luIiwgb3V0ZGlyPSJwYXRodmlld190cnlwX2NsMTRjbGJyIiwgc3RyaW5nX2Zyb209IlRjQ0xCLiIsIHN0cmluZ190bz0iIikKaGVhZCh0cnlwX2NsMTRjbGJyX3BhdGhzKQpgYGAK