1 Which genes are DE in human macrophages at 4 hours upon infection with L. major?

2 Gather annotation data

I want to perform a series of comparisons among the host cells: human and mouse. Thus I need to collect annotation data for both species and get the set of orthologs between them.

2.2 Generate expressionsets

The question is reasonably self-contained. I want to compare the uninfected human samples against any samples which were infected for 4 hours. So let us first pull those samples and then poke at them a bit.

## Reading the sample metadata.
## The sample definitions comprises: 437 rows(samples) and 55 columns(metadata fields).
## Reading count tables.
## Using the transcript to gene mapping.
## Reading salmon data with tximport.
## Finished reading count tables.
## Matched 19629 annotations and counts.
## Bringing together the count matrix and gene information.
## The mapped IDs are not the rownames of your gene information, changing them now.
## Some annotations were lost in merging, setting them to 'undefined'.
## There were 267, now there are 247 samples.
## There were 247, now there are 64 samples.
## 
## bead   no stim  yes 
##    3   18   35    8
## 
## lps-timecourse       m-gm-csf           mbio 
##              8             39             17

2.3 Examine t4h vs uninfected

## This function will replace the expt$expressionset slot with:
## log2(svaseq(cpm(quant(cbcb(data)))))
## It backs up the current data into a slot named:
##  expt$backup_expressionset. It will also save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep the libsizes in mind
##  when invoking limma.  The appropriate libsize is the non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Warning in normalize_expt(hs_t4h_expt, norm = "quant", convert = "cpm", :
## Quantile normalization and sva do not always play well together.
## Step 1: performing count filter with option: cbcb
## Removing 7360 low-count genes (12269 remaining).
## Step 2: normalizing the data with quant.
## Using normalize.quantiles.robust due to a thread error in preprocessCore.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 3822 values equal to 0, adding 1 to the matrix.
## Step 5: doing batch correction with svaseq.
## Note to self:  If you get an error like 'x contains missing values' The data has too many 0's and needs a stronger low-count filter applied.
## Passing off to all_adjusters.
## batch_counts: Before batch/surrogate estimation, 711279 entries are x>1: 90.6%.
## batch_counts: Before batch/surrogate estimation, 3822 entries are x==0: 0.487%.
## batch_counts: Before batch/surrogate estimation, 70115 entries are 0<x<1: 8.93%.
## The be method chose 12 surrogate variable(s).
## Attempting svaseq estimation with 12 surrogates.
## There are 1760 (0.224%) elements which are < 0 after batch correction.

2.4 Remove stimulated samples

## There were 64, now there are 29 samples.
## This function will replace the expt$expressionset slot with:
## log2(svaseq(cpm(cbcb(data))))
## It backs up the current data into a slot named:
##  expt$backup_expressionset. It will also save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep the libsizes in mind
##  when invoking limma.  The appropriate libsize is the non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Leaving the data unnormalized.  This is necessary for DESeq, but
##  EdgeR/limma might benefit from normalization.  Good choices include quantile,
##  size-factor, tmm, etc.
## Step 1: performing count filter with option: cbcb
## Removing 7759 low-count genes (11870 remaining).
## Step 2: not normalizing the data.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 3276 values equal to 0, adding 1 to the matrix.
## Step 5: doing batch correction with svaseq.
## Note to self:  If you get an error like 'x contains missing values' The data has too many 0's and needs a stronger low-count filter applied.
## Passing off to all_adjusters.
## batch_counts: Before batch/surrogate estimation, 319013 entries are x>1: 92.7%.
## batch_counts: Before batch/surrogate estimation, 3276 entries are x==0: 0.952%.
## batch_counts: Before batch/surrogate estimation, 21941 entries are 0<x<1: 6.37%.
## The be method chose 6 surrogate variable(s).
## Attempting svaseq estimation with 6 surrogates.
## There are 557 (0.162%) elements which are < 0 after batch correction.

## batch_counts: Before batch/surrogate estimation, 339179 entries are x>1: 98.5%.
## batch_counts: Before batch/surrogate estimation, 3276 entries are x==0: 0.952%.
## batch_counts: Before batch/surrogate estimation, 216 entries are 0<x<1: 0.0627%.
## The be method chose 5 surrogate variable(s).
## Attempting svaseq estimation with 5 surrogates.
## This function will replace the expt$expressionset slot with:
## log2(cpm(quant(cbcb(data))))
## It backs up the current data into a slot named:
##  expt$backup_expressionset. It will also save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep the libsizes in mind
##  when invoking limma.  The appropriate libsize is the non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: performing count filter with option: cbcb
## Removing 0 low-count genes (11870 remaining).
## Step 2: normalizing the data with quant.
## Using normalize.quantiles.robust due to a thread error in preprocessCore.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 1964 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.
## Plotting a PCA before surrogates/batch inclusion.
## Using svaseq to visualize before/after batch inclusion.
## Performing a test normalization with: raw
## This function will replace the expt$expressionset slot with:
## log2(svaseq(cpm(cbcb(data))))
## It backs up the current data into a slot named:
##  expt$backup_expressionset. It will also save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep the libsizes in mind
##  when invoking limma.  The appropriate libsize is the non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Leaving the data unnormalized.  This is necessary for DESeq, but
##  EdgeR/limma might benefit from normalization.  Good choices include quantile,
##  size-factor, tmm, etc.
## Step 1: performing count filter with option: cbcb
## Removing 0 low-count genes (11870 remaining).
## Step 2: not normalizing the data.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 3276 values equal to 0, adding 1 to the matrix.
## Step 5: doing batch correction with svaseq.
## Note to self:  If you get an error like 'x contains missing values' The data has too many 0's and needs a stronger low-count filter applied.
## Passing off to all_adjusters.
## batch_counts: Before batch/surrogate estimation, 319013 entries are x>1: 92.7%.
## batch_counts: Before batch/surrogate estimation, 3276 entries are x==0: 0.952%.
## batch_counts: Before batch/surrogate estimation, 21941 entries are 0<x<1: 6.37%.
## The be method chose 6 surrogate variable(s).
## Attempting svaseq estimation with 6 surrogates.
## There are 557 (0.162%) elements which are < 0 after batch correction.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

## Writing a legend of columns.
## Working on 1/1: infection which is: yes/no.
## Found table with yes_vs_no
## 20181210 a pthread error in normalize.quantiles leads me to robust.
## Used Bon Ferroni corrected t test(s) between columns.
## Used Bon Ferroni corrected t test(s) between columns.
## Used Bon Ferroni corrected t test(s) between columns.

3 Which genes are DE in mouse macrophages at 4 hours upon infection with L. major?

4 Gather annotation data

I want to perform a series of comparisons among the host cells: human and mouse. Thus I need to collect annotation data for both species and get the set of orthologs between them.

4.2 Generate expressionsets

The question is reasonably self-contained. I want to compare the uninfected human samples against any samples which were infected for 4 hours. So let us first pull those samples and then poke at them a bit.

## Reading the sample metadata.
## The sample definitions comprises: 437 rows(samples) and 55 columns(metadata fields).
## Reading count tables.
## Using the transcript to gene mapping.
## Reading salmon data with tximport.
## Finished reading count tables.
## Matched 19660 annotations and counts.
## Bringing together the count matrix and gene information.
## The mapped IDs are not the rownames of your gene information, changing them now.
## Some annotations were lost in merging, setting them to 'undefined'.
## There were 105, now there are 41 samples.
## 
##   no stim  yes 
##   11   24    6
## 
## undefined 
##        41

4.3 Examine t4h vs uninfected

## This function will replace the expt$expressionset slot with:
## log2(svaseq(cpm(quant(cbcb(data)))))
## It backs up the current data into a slot named:
##  expt$backup_expressionset. It will also save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep the libsizes in mind
##  when invoking limma.  The appropriate libsize is the non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Warning in normalize_expt(mm_t4h_expt, norm = "quant", convert = "cpm", :
## Quantile normalization and sva do not always play well together.
## Step 1: performing count filter with option: cbcb
## Removing 9350 low-count genes (10310 remaining).
## Step 2: normalizing the data with quant.
## Using normalize.quantiles.robust due to a thread error in preprocessCore.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 38 values equal to 0, adding 1 to the matrix.
## Step 5: doing batch correction with svaseq.
## Note to self:  If you get an error like 'x contains missing values' The data has too many 0's and needs a stronger low-count filter applied.
## Passing off to all_adjusters.
## batch_counts: Before batch/surrogate estimation, 390888 entries are x>1: 92.5%.
## batch_counts: Before batch/surrogate estimation, 38 entries are x==0: 0.00899%.
## batch_counts: Before batch/surrogate estimation, 31784 entries are 0<x<1: 7.52%.
## The be method chose 8 surrogate variable(s).
## Attempting svaseq estimation with 8 surrogates.
## There are 807 (0.191%) elements which are < 0 after batch correction.

5 Compare this to the previous result.

Let us see if our human differential expression result is similar to that obtained in Table S2.

6 Compare the previous human and these human results.

## Error in eval(expr, envir, enclos): object 'previous_hs_lfc' not found
## Error in eval(expr, envir, enclos): object 'previous_hs_lfc' not found
## Error in eval(expr, envir, enclos): object 'previous_hs_lfc' not found
## Error in eval(expr, envir, enclos): object 'previous_hs_lfc' not found
## Error in merge(previous_hs_lfc, hs_t4h_table$data[[1]], by.x = "ID", by.y = "row.names"): object 'previous_hs_lfc' not found
## Error in cor.test(merged[["limma_logfc"]], merged[["Fold change"]]): object 'merged' not found

7 Compare the previous mouse and these mouse results.

## 
##  Pearson's product-moment correlation
## 
## data:  merged[["limma_logfc"]] and merged[["Fold change"]]
## t = 220, df = 5700, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.9445 0.9498
## sample estimates:
##    cor 
## 0.9472

First get the set of orthologs.

Side note: a different way of addressing this question resides in 20190220_host_comparisons.Rmd.

## 
##  Pearson's product-moment correlation
## 
## data:  both_table_hs[["limma_logfc.x"]] and both_table_hs[["limma_logfc.y"]]
## t = 34, df = 14000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.2656 0.2964
## sample estimates:
##    cor 
## 0.2811
## 
##  Pearson's product-moment correlation
## 
## data:  both_table_mm[["limma_logfc.x"]] and both_table_mm[["limma_logfc.y"]]
## t = 34, df = 22000, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.2135 0.2387
## sample estimates:
##    cor 
## 0.2261

8 Compare the above with Table S7 from the Laura and Cecilia paper.

Table S7 has a set of genes from human which are also up-regulated in mouse upon infection.

R version 3.5.3 (2019-03-11)

Platform: x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.utf8, LC_NUMERIC=C, LC_TIME=en_US.utf8, LC_COLLATE=en_US.utf8, LC_MONETARY=en_US.utf8, LC_MESSAGES=en_US.utf8, LC_PAPER=en_US.utf8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.utf8 and LC_IDENTIFICATION=C

attached base packages: parallel, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: ruv(v.0.9.7), hpgltools(v.1.0), Biobase(v.2.42.0) and BiocGenerics(v.0.28.0)

loaded via a namespace (and not attached): tidyselect(v.0.2.5), lme4(v.1.1-21), htmlwidgets(v.1.3), RSQLite(v.2.1.1), AnnotationDbi(v.1.44.0), grid(v.3.5.3), BiocParallel(v.1.16.6), Rtsne(v.0.15), devtools(v.2.0.1), munsell(v.0.5.0), codetools(v.0.2-16), preprocessCore(v.1.45.0), withr(v.2.1.2), colorspace(v.1.4-0), GOSemSim(v.2.8.0), knitr(v.1.22), rstudioapi(v.0.9.0), stats4(v.3.5.3), Vennerable(v.3.1.0.9000), robustbase(v.0.93-3), DOSE(v.3.8.2), labeling(v.0.3), urltools(v.1.7.2), tximport(v.1.10.1), GenomeInfoDbData(v.1.2.0), polyclip(v.1.9-1), bit64(v.0.9-7), farver(v.1.1.0), rprojroot(v.1.3-2), xfun(v.0.5), R6(v.2.4.0), doParallel(v.1.0.14), GenomeInfoDb(v.1.18.2), locfit(v.1.5-9.1), bitops(v.1.0-6), fgsea(v.1.8.0), gridGraphics(v.0.3-0), DelayedArray(v.0.8.0), assertthat(v.0.2.0), scales(v.1.0.0), ggraph(v.1.0.2), nnet(v.7.3-12), enrichplot(v.1.2.0), gtable(v.0.2.0), sva(v.3.30.1), processx(v.3.3.0), rlang(v.0.3.1), genefilter(v.1.64.0), splines(v.3.5.3), rtracklayer(v.1.42.2), lazyeval(v.0.2.1), acepack(v.1.4.1), checkmate(v.1.9.1), europepmc(v.0.3), yaml(v.2.2.0), reshape2(v.1.4.3), GenomicFeatures(v.1.34.4), backports(v.1.1.3), qvalue(v.2.14.1), Hmisc(v.4.2-0), RBGL(v.1.58.1), clusterProfiler(v.3.10.1), tools(v.3.5.3), usethis(v.1.4.0), ggplotify(v.0.0.3), ggplot2(v.3.1.0), gplots(v.3.0.1.1), RColorBrewer(v.1.1-2), sessioninfo(v.1.1.1), ggridges(v.0.5.1), Rcpp(v.1.0.1), plyr(v.1.8.4), base64enc(v.0.1-3), progress(v.1.2.0), zlibbioc(v.1.28.0), purrr(v.0.3.1), RCurl(v.1.95-4.12), ps(v.1.3.0), prettyunits(v.1.0.2), rpart(v.4.1-13), viridis(v.0.5.1), cowplot(v.0.9.4), S4Vectors(v.0.20.1), SummarizedExperiment(v.1.12.0), ggrepel(v.0.8.0), cluster(v.2.0.7-1), colorRamps(v.2.3), fs(v.1.2.6), variancePartition(v.1.12.1), magrittr(v.1.5), data.table(v.1.12.0), DO.db(v.2.9), openxlsx(v.4.1.0), triebeard(v.0.3.0), packrat(v.0.5.0), matrixStats(v.0.54.0), pkgload(v.1.0.2), hms(v.0.4.2), evaluate(v.0.13), xtable(v.1.8-3), pbkrtest(v.0.4-7), XML(v.3.98-1.19), readxl(v.1.3.0), IRanges(v.2.16.0), gridExtra(v.2.3), testthat(v.2.0.1), compiler(v.3.5.3), biomaRt(v.2.38.0), tibble(v.2.0.1), KernSmooth(v.2.23-15), crayon(v.1.3.4), minqa(v.1.2.4), htmltools(v.0.3.6), mgcv(v.1.8-27), corpcor(v.1.6.9), Formula(v.1.2-3), geneplotter(v.1.60.0), tidyr(v.0.8.3), DBI(v.1.0.0), tweenr(v.1.0.1), MASS(v.7.3-51.1), boot(v.1.3-20), Matrix(v.1.2-16), readr(v.1.3.1), cli(v.1.0.1), quadprog(v.1.5-5), gdata(v.2.18.0), igraph(v.1.2.4), GenomicRanges(v.1.34.0), pkgconfig(v.2.0.2), rvcheck(v.0.1.3), GenomicAlignments(v.1.18.1), foreign(v.0.8-71), xml2(v.1.2.0), foreach(v.1.4.4), annotate(v.1.60.1), XVector(v.0.22.0), stringr(v.1.4.0), callr(v.3.1.1), digest(v.0.6.18), graph(v.1.60.0), Biostrings(v.2.50.2), cellranger(v.1.1.0), rmarkdown(v.1.11), fastmatch(v.1.1-0), htmlTable(v.1.13.1), edgeR(v.3.24.3), directlabels(v.2018.05.22), curl(v.3.3), Rsamtools(v.1.34.1), gtools(v.3.8.1), nloptr(v.1.2.1), nlme(v.3.1-137), jsonlite(v.1.6), desc(v.1.2.0), viridisLite(v.0.3.0), limma(v.3.38.3), pillar(v.1.3.1), lattice(v.0.20-38), DEoptimR(v.1.0-8), httr(v.1.4.0), pkgbuild(v.1.0.2), survival(v.2.43-3), GO.db(v.3.7.0), glue(v.1.3.1), remotes(v.2.0.2), zip(v.2.0.1), UpSetR(v.1.3.3), iterators(v.1.0.10), pander(v.0.6.3), bit(v.1.1-14), ggforce(v.0.2.1), stringi(v.1.4.3), blob(v.1.1.1), DESeq2(v.1.22.2), latticeExtra(v.0.6-28), caTools(v.1.17.1.2), memoise(v.1.1.0) and dplyr(v.0.8.0.1)

## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset dcf2a1659165dacca91ade9f3f8e56f234633e55
## This is hpgltools commit: Thu Apr 4 14:58:27 2019 -0400: dcf2a1659165dacca91ade9f3f8e56f234633e55
LS0tCnRpdGxlOiAiMjAxOTAzMjYgQW4gYXR0ZW1wdCB0byBhbnN3ZXIgb25lIG9mIHRoZSBiaWcgcXVlc3Rpb25zIGZyb20gTmFqaWIuIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB3aWR0aDogMzAwCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCiAgQmlvY1N0eWxlOjpodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSwgdGQgewogIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNnB4Owp9CnByZSB7CiBmb250LXNpemU6IDE2cHgKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCnR0IDwtIHNtKGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKSkKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICB3aWR0aD0xMjAsCiAgICAgICAgICAgICAgICAgICAgIGVjaG89VFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQ9OCwKICAgICAgICAgICAgICAgICAgICAgIGRwaT05NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbD0iYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEyKSkKdmVyIDwtICIyMDE5MDMyNiIKcnVuZGF0ZSA8LSBmb3JtYXQoU3lzLkRhdGUoKSwgZm9ybWF0PSIlWSVtJWQiKQpybWRfZmlsZSA8LSBwYXN0ZTAoIjIwMTkwMzI2X2h1bWFuX21hY3JvcGhhZ2VzLlJtZCIpCmBgYAoKIyBXaGljaCBnZW5lcyBhcmUgREUgaW4gaHVtYW4gbWFjcm9waGFnZXMgYXQgNCBob3VycyB1cG9uIGluZmVjdGlvbiB3aXRoIEwuIG1ham9yPwoKIyBHYXRoZXIgYW5ub3RhdGlvbiBkYXRhCgpJIHdhbnQgdG8gcGVyZm9ybSBhIHNlcmllcyBvZiBjb21wYXJpc29ucyBhbW9uZyB0aGUgaG9zdCBjZWxsczogaHVtYW4gYW5kIG1vdXNlLgpUaHVzIEkgbmVlZCB0byBjb2xsZWN0IGFubm90YXRpb24gZGF0YSBmb3IgYm90aCBzcGVjaWVzIGFuZCBnZXQgdGhlIHNldCBvZgpvcnRob2xvZ3MgYmV0d2VlbiB0aGVtLgoKIyMgU3RhcnQgd2l0aCB0aGUgaHVtYW4gYW5ub3RhdGlvbiBkYXRhCgpgYGB7ciBodW1hbl9hbm5vdGF0aW9uc30KaHNfYW5ub3QgPC0gbG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKCkkYW5ub3RhdGlvbgpyb3duYW1lcyhoc19hbm5vdCkgPC0gbWFrZS5uYW1lcygKICBwYXN0ZTAoaHNfYW5ub3RbWyJlbnNlbWJsX3RyYW5zY3JpcHRfaWQiXV0sICIuIiwKICAgICAgICAgaHNfYW5ub3RbWyJ0cmFuc2NyaXB0X3ZlcnNpb24iXV0pLAogIHVuaXF1ZT1UUlVFKQpoc190eF9nZW5lIDwtIGhzX2Fubm90WywgYygiZW5zZW1ibF9nZW5lX2lkIiwgImVuc2VtYmxfdHJhbnNjcmlwdF9pZCIpXQpoc190eF9nZW5lW1siaWQiXV0gPC0gcm93bmFtZXMoaHNfdHhfZ2VuZSkKaHNfdHhfZ2VuZSA8LSBoc190eF9nZW5lWywgYygiaWQiLCAiZW5zZW1ibF9nZW5lX2lkIildCm5ld19oc19hbm5vdCA8LSBoc19hbm5vdApyb3duYW1lcyhuZXdfaHNfYW5ub3QpIDwtIG1ha2UubmFtZXMoaHNfYW5ub3RbWyJlbnNlbWJsX2dlbmVfaWQiXV0sIHVuaXF1ZT1UUlVFKQpgYGAKCiMjIEdlbmVyYXRlIGV4cHJlc3Npb25zZXRzCgpUaGUgcXVlc3Rpb24gaXMgcmVhc29uYWJseSBzZWxmLWNvbnRhaW5lZC4gIEkgd2FudCB0byBjb21wYXJlIHRoZSB1bmluZmVjdGVkCmh1bWFuIHNhbXBsZXMgYWdhaW5zdCBhbnkgc2FtcGxlcyB3aGljaCB3ZXJlIGluZmVjdGVkIGZvciA0IGhvdXJzLgpTbyBsZXQgdXMgZmlyc3QgcHVsbCB0aG9zZSBzYW1wbGVzIGFuZCB0aGVuIHBva2UgYXQgdGhlbSBhIGJpdC4KCmBgYHtyIGV4cHRzfQpzYW1wbGVfc2hlZXQgPC0gInNhbXBsZV9zaGVldHMvbGVpc2htYW5pYV9ob3N0X21ldGFzaGVldF8yMDE5MDQwMS54bHN4Igpoc19leHB0IDwtIGNyZWF0ZV9leHB0KHNhbXBsZV9zaGVldCwKICAgICAgICAgICAgICAgICAgICAgICBmaWxlX2NvbHVtbj0iaHNhcGllbnNmaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89bmV3X2hzX2Fubm90LAogICAgICAgICAgICAgICAgICAgICAgIHR4X2dlbmVfbWFwPWhzX3R4X2dlbmUpCgpoc19leHB0X25vc2tpcHBlZCA8LSBzdWJzZXRfZXhwdChoc19leHB0LCBzdWJzZXQ9InNraXBwZWQhPSd5ZXMnIikKaHNfdDRoX2V4cHQgPC0gc3Vic2V0X2V4cHQoaHNfZXhwdF9ub3NraXBwZWQsIHN1YnNldD0iZXhwdHRpbWU9PSd0NGgnIikKaHNfdDRoX2V4cHQgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhoc190NGhfZXhwdCwgZmFjdD0iaW5mZWN0c3RhdGUiKQpoc190NGhfZXhwdCA8LSBzZXRfZXhwdF9iYXRjaGVzKGhzX3Q0aF9leHB0LCBmYWN0PSJzdHVkeSIpCnRhYmxlKGhzX3Q0aF9leHB0JGNvbmRpdGlvbnMpCnRhYmxlKGhzX3Q0aF9leHB0JGJhdGNoZXMpCmBgYAoKIyMgRXhhbWluZSB0NGggdnMgdW5pbmZlY3RlZAoKYGBge3IgaHNfZXhhbWluZV90NGgsIGZpZy5zaG93PSdoaWRlJ30KaHNfdDRoX3Bsb3RzIDwtIHNtKGdyYXBoX21ldHJpY3MoaHNfdDRoX2V4cHQpKQoKaHNfdDRoX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoaHNfdDRoX2V4cHQsIG5vcm09InF1YW50IiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtPSJsb2cyIiwgZmlsdGVyPVRSVUUsIGJhdGNoPSJzdmFzZXEiKQpoc190NGhfbm9ybV9wbG90cyA8LSBzbShncmFwaF9tZXRyaWNzKGhzX3Q0aF9ub3JtKSkKYGBgCgojIyMgUHJpbnQgc29tZSBvZiB0aGUgcGxvdHMKCmBgYHtyIGhzX2V4YW1pbmVfcGxvdHN9CmhzX3Q0aF9wbG90cyRsZWdlbmQKaHNfdDRoX3Bsb3RzJGxpYnNpemUKaHNfdDRoX3Bsb3RzJGJveHBsb3QKCmhzX3Q0aF9ub3JtX3Bsb3RzJHBjX3Bsb3QKYGBgCgojIyBSZW1vdmUgc3RpbXVsYXRlZCBzYW1wbGVzCgpgYGB7ciBoc190NGhfbm91bnN0aW19CmhzX3Q0aF9pbmYgPC0gc3Vic2V0X2V4cHQoaHNfdDRoX2V4cHQsIHN1YnNldD0iY29uZGl0aW9uIT0nc3RpbSciKQpoc190NGhfaW5mX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoaHNfdDRoX2luZiwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcj1UUlVFLCBiYXRjaD0ic3Zhc2VxIikKCmhzX3Q0aF9wY2EgPC0gcGxvdF9wY2EoaHNfdDRoX2luZl9ub3JtLCBwbG90X3RpdGxlPSJILiBzYXBpZW5zLCBMLiBtYWpvciwgdDRoIikKaHNfdDRoX3BjYSRwbG90CgprZWVwZXJzIDwtIGxpc3QoImluZmVjdGlvbiIgPSBjKCJ5ZXMiLCAibm8iKSkKaHNfdDRoX2RlIDwtIGFsbF9wYWlyd2lzZShoc190NGhfaW5mLCBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUsIGZvcmNlPVRSVUUpCmhzX3Q0aF90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcyhoc190NGhfZGUsIGtlZXBlcnM9a2VlcGVycykKYGBgCgojIFdoaWNoIGdlbmVzIGFyZSBERSBpbiBtb3VzZSBtYWNyb3BoYWdlcyBhdCA0IGhvdXJzIHVwb24gaW5mZWN0aW9uIHdpdGggTC4gbWFqb3I/CgojIEdhdGhlciBhbm5vdGF0aW9uIGRhdGEKCkkgd2FudCB0byBwZXJmb3JtIGEgc2VyaWVzIG9mIGNvbXBhcmlzb25zIGFtb25nIHRoZSBob3N0IGNlbGxzOiBodW1hbiBhbmQgbW91c2UuClRodXMgSSBuZWVkIHRvIGNvbGxlY3QgYW5ub3RhdGlvbiBkYXRhIGZvciBib3RoIHNwZWNpZXMgYW5kIGdldCB0aGUgc2V0IG9mCm9ydGhvbG9ncyBiZXR3ZWVuIHRoZW0uCgojIyBTdGFydCB3aXRoIHRoZSBodW1hbiBhbm5vdGF0aW9uIGRhdGEKCmBgYHtyIG1vdXNlX2Fubm90YXRpb25zfQptbV9hbm5vdCA8LSBsb2FkX2Jpb21hcnRfYW5ub3RhdGlvbnMoc3BlY2llcz0ibW11c2N1bHVzIikkYW5ub3RhdGlvbgpyb3duYW1lcyhtbV9hbm5vdCkgPC0gbWFrZS5uYW1lcygKICBwYXN0ZTAobW1fYW5ub3RbWyJlbnNlbWJsX3RyYW5zY3JpcHRfaWQiXV0sICIuIiwKICAgICAgICAgbW1fYW5ub3RbWyJ0cmFuc2NyaXB0X3ZlcnNpb24iXV0pLAogIHVuaXF1ZT1UUlVFKQptbV90eF9nZW5lIDwtIG1tX2Fubm90WywgYygiZW5zZW1ibF9nZW5lX2lkIiwgImVuc2VtYmxfdHJhbnNjcmlwdF9pZCIpXQptbV90eF9nZW5lW1siaWQiXV0gPC0gcm93bmFtZXMobW1fdHhfZ2VuZSkKbW1fdHhfZ2VuZSA8LSBtbV90eF9nZW5lWywgYygiaWQiLCAiZW5zZW1ibF9nZW5lX2lkIildCm5ld19tbV9hbm5vdCA8LSBtbV9hbm5vdApyb3duYW1lcyhuZXdfbW1fYW5ub3QpIDwtIG1ha2UubmFtZXMobW1fYW5ub3RbWyJlbnNlbWJsX2dlbmVfaWQiXV0sIHVuaXF1ZT1UUlVFKQpgYGAKCiMjIEdlbmVyYXRlIGV4cHJlc3Npb25zZXRzCgpUaGUgcXVlc3Rpb24gaXMgcmVhc29uYWJseSBzZWxmLWNvbnRhaW5lZC4gIEkgd2FudCB0byBjb21wYXJlIHRoZSB1bmluZmVjdGVkCmh1bWFuIHNhbXBsZXMgYWdhaW5zdCBhbnkgc2FtcGxlcyB3aGljaCB3ZXJlIGluZmVjdGVkIGZvciA0IGhvdXJzLgpTbyBsZXQgdXMgZmlyc3QgcHVsbCB0aG9zZSBzYW1wbGVzIGFuZCB0aGVuIHBva2UgYXQgdGhlbSBhIGJpdC4KCmBgYHtyIG1vdXNlX2V4cHRzfQptbV9leHB0IDwtIGNyZWF0ZV9leHB0KHNhbXBsZV9zaGVldCwKICAgICAgICAgICAgICAgICAgICAgICBmaWxlX2NvbHVtbj0ibW11c2N1bHVzZmlsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvPW5ld19tbV9hbm5vdCwKICAgICAgICAgICAgICAgICAgICAgICB0eF9nZW5lX21hcD1tbV90eF9nZW5lKQptbV90NGhfZXhwdCA8LSBzdWJzZXRfZXhwdChtbV9leHB0LCBzdWJzZXQ9ImV4cHR0aW1lPT0ndDRoJyIpCm1tX3Q0aF9leHB0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMobW1fdDRoX2V4cHQsIGZhY3Q9ImluZmVjdHN0YXRlIikKdGFibGUobW1fdDRoX2V4cHQkY29uZGl0aW9ucykKdGFibGUobW1fdDRoX2V4cHQkYmF0Y2hlcykKYGBgCgojIyBFeGFtaW5lIHQ0aCB2cyB1bmluZmVjdGVkCgpgYGB7ciBleGFtaW5lX3Q0aCwgZmlnLnNob3c9J2hpZGUnfQptbV90NGhfcGxvdHMgPC0gc20oZ3JhcGhfbWV0cmljcyhtbV90NGhfZXhwdCkpCm1tX3Q0aF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG1tX3Q0aF9leHB0LCBub3JtPSJxdWFudCIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybT0ibG9nMiIsIGZpbHRlcj1UUlVFLCBiYXRjaD0ic3Zhc2VxIikKbW1fdDRoX25vcm1fcGxvdHMgPC0gc20oZ3JhcGhfbWV0cmljcyhtbV90NGhfbm9ybSkpCmBgYAoKIyMjIFByaW50IHNvbWUgb2YgdGhlIHBsb3RzCgpgYGB7ciBtbV9leGFtaW5lX3Bsb3RzfQptbV90NGhfcGxvdHMkbGVnZW5kCm1tX3Q0aF9wbG90cyRsaWJzaXplCm1tX3Q0aF9wbG90cyRib3hwbG90CgptbV90NGhfbm9ybV9wbG90cyRwY19wbG90CmBgYAoKYGBge3IgbW1fdDRoX2RlfQptbV90NGhfaW5mX25vcm0gPC0gbm9ybWFsaXplX2V4cHQobW1fdDRoX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXI9VFJVRSwgYmF0Y2g9InN2YXNlcSIpCgptbV90NGhfcGNhIDwtIHBsb3RfcGNhKG1tX3Q0aF9pbmZfbm9ybSwgcGxvdF90aXRsZT0iTS4gbXVzY3VsdXMsIEwuIG1ham9yLCB0NGgiKQptbV90NGhfcGNhJHBsb3QKCm1tX3Q0aF9kZSA8LSBhbGxfcGFpcndpc2UobW1fdDRoX2V4cHQsIG1vZGVsX2JhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSwgZm9yY2U9VFJVRSkKbW1fdDRoX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKG1tX3Q0aF9kZSwga2VlcGVycz1rZWVwZXJzKQpgYGAKCiMgQ29tcGFyZSB0aGlzIHRvIHRoZSBwcmV2aW91cyByZXN1bHQuCgpMZXQgdXMgc2VlIGlmIG91ciBodW1hbiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiByZXN1bHQgaXMgc2ltaWxhciB0byB0aGF0Cm9idGFpbmVkIGluIFRhYmxlIFMyLgoKIyBDb21wYXJlIHRoZSBwcmV2aW91cyBodW1hbiBhbmQgdGhlc2UgaHVtYW4gcmVzdWx0cy4KCmBgYHtyIGNvbXBhcmVfcHJldmlvdXNfaHN9CnByZXZpb3VzX2hzIDwtIHJlYWR4bDo6cmVhZF9leGNlbCgiZXhjZWwvaW5saW5lLXN1cHBsZW1lbnRhcnktbWF0ZXJpYWwtNS54bHMiLCBzaGVldD0yKQpwcmV2aW91c19oc19sZmMgPC0gcHJldmlvdXNfaHNfbGZjWywgYygiSUQiLCAiRm9sZCBjaGFuZ2UiKV0KbmVnX2lkeCA8LSBwcmV2aW91c19oc19sZmNbWzJdXSA8IDAKcHJldmlvdXNfaHNfbGZjW25lZ19pZHgsIDJdIDwtIC0xICogKDEgLyBwcmV2aW91c19oc19sZmNbbmVnX2lkeCwgMl0pCnByZXZpb3VzX2hzX2xmY1tbMl1dIDwtIGxvZzIocHJldmlvdXNfaHNfbGZjW1syXV0pCgptZXJnZWQgPC0gbWVyZ2UocHJldmlvdXNfaHNfbGZjLCBoc190NGhfdGFibGUkZGF0YVtbMV1dLCBieS54PSJJRCIsIGJ5Lnk9InJvdy5uYW1lcyIpCmNvci50ZXN0KG1lcmdlZFtbImxpbW1hX2xvZ2ZjIl1dLCBtZXJnZWRbWyJGb2xkIGNoYW5nZSJdXSkKYGBgCgojIENvbXBhcmUgdGhlIHByZXZpb3VzIG1vdXNlIGFuZCB0aGVzZSBtb3VzZSByZXN1bHRzLgoKYGBge3IgY29tcGFyZV9wcmV2aW91c19tbX0KcHJldmlvdXNfbW0gPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJleGNlbC8xMjg2NF8yMDE1XzIyMzdfTU9FU00zX0VTTS54bHMiLCBzaGVldD0yLCBza2lwPTEpCnByZXZpb3VzX21tX2xmYyA8LSBwcmV2aW91c19tbVssIGMoIklEIiwgIkZvbGQgY2hhbmdlIildCm5lZ19pZHggPC0gcHJldmlvdXNfbW1fbGZjW1syXV0gPCAwCnByZXZpb3VzX21tX2xmY1tuZWdfaWR4LCAyXSA8LSAtMSAqICgxIC8gcHJldmlvdXNfbW1fbGZjW25lZ19pZHgsIDJdKQpwcmV2aW91c19tbV9sZmNbWzJdXSA8LSBsb2cyKHByZXZpb3VzX21tX2xmY1tbMl1dKQoKbWVyZ2VkIDwtIG1lcmdlKHByZXZpb3VzX21tX2xmYywgbW1fdDRoX3RhYmxlJGRhdGFbWzFdXSwgYnkueD0iSUQiLCBieS55PSJyb3cubmFtZXMiKQpjb3IudGVzdChtZXJnZWRbWyJsaW1tYV9sb2dmYyJdXSwgbWVyZ2VkW1siRm9sZCBjaGFuZ2UiXV0pCmBgYAoKRmlyc3QgZ2V0IHRoZSBzZXQgb2Ygb3J0aG9sb2dzLgoKU2lkZSBub3RlOiBhIGRpZmZlcmVudCB3YXkgb2YgYWRkcmVzc2luZyB0aGlzIHF1ZXN0aW9uIHJlc2lkZXMgaW4gMjAxOTAyMjBfaG9zdF9jb21wYXJpc29ucy5SbWQuCgpgYGB7ciBtbV9oc19vcnRob2xvZ3N9CiMjIFRoZSBkZWZhdWx0cyBvZiB0aGlzIGZ1bmN0aW9uIGFyZSBzdWl0YWJsZSBmb3IgbW91c2UvaHVtYW4gcXVlcmllcy4KbW1faHNfb3J0aG8gPC0gbG9hZF9iaW9tYXJ0X29ydGhvbG9ncygpJGFsbF9saW5rZWRfZ2VuZXMKCm1tX3RhYmxlIDwtIG1tX3Q0aF90YWJsZSRkYXRhW1sxXV0KaHNfdGFibGUgPC0gaHNfdDRoX3RhYmxlJGRhdGFbWzFdXQoKbW1fdGFibGUgPC0gbWVyZ2UobW1faHNfb3J0aG8sIG1tX3RhYmxlLCBieS54PSJtbXVzY3VsdXMiLCBieS55PSJyb3cubmFtZXMiLCBhbGwueT1UUlVFKQpoc190YWJsZSA8LSBtZXJnZShtbV9oc19vcnRobywgaHNfdGFibGUsIGJ5Lng9ImhzYXBpZW5zIiwgYnkueT0icm93Lm5hbWVzIiwgYWxsLnk9VFJVRSkKYm90aF90YWJsZV9ocyA8LSBtZXJnZShoc190YWJsZSwgbW1fdGFibGUsIGJ5Lng9ImhzYXBpZW5zIiwgYnkueT0iaHNhcGllbnMiKQpib3RoX3RhYmxlX21tIDwtIG1lcmdlKGhzX3RhYmxlLCBtbV90YWJsZSwgYnkueD0ibW11c2N1bHVzIiwgYnkueT0ibW11c2N1bHVzIikKCmNvci50ZXN0KGJvdGhfdGFibGVfaHNbWyJsaW1tYV9sb2dmYy54Il1dLCBib3RoX3RhYmxlX2hzW1sibGltbWFfbG9nZmMueSJdXSkKY29yLnRlc3QoYm90aF90YWJsZV9tbVtbImxpbW1hX2xvZ2ZjLngiXV0sIGJvdGhfdGFibGVfbW1bWyJsaW1tYV9sb2dmYy55Il1dKQp0dCA8LSBwbG90X3NjYXR0ZXIoYm90aF90YWJsZV9oc1ssIGMoImxpbW1hX2xvZ2ZjLngiLCAibGltbWFfbG9nZmMueSIpXSkKdHQKYGBgCgojIENvbXBhcmUgdGhlIGFib3ZlIHdpdGggVGFibGUgUzcgZnJvbSB0aGUgTGF1cmEgYW5kIENlY2lsaWEgcGFwZXIuCgpUYWJsZSBTNyBoYXMgYSBzZXQgb2YgZ2VuZXMgZnJvbSBodW1hbiB3aGljaCBhcmUgYWxzbyB1cC1yZWd1bGF0ZWQgaW4gbW91c2UgdXBvbgppbmZlY3Rpb24uCgpgYGB7ciBvcGVuX2ZpZ3M3fQpmaWdfczdfdXAgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJleGNlbC9pbmxpbmUtc3VwcGxlbWVudGFyeS1tYXRlcmlhbC03LnhscyIsIHNoZWV0PTMpCmZpZ19zN19oc191cCA8LSB1bmlxdWUoZmlnX3M3X3VwW1s1XV0pCgpmaWdfczdfZG93biA8LSByZWFkeGw6OnJlYWRfZXhjZWwoImV4Y2VsL2lubGluZS1zdXBwbGVtZW50YXJ5LW1hdGVyaWFsLTcueGxzIiwgc2hlZXQ9NCkKZmlnX3M3X2hzX2Rvd24gPC0gdW5pcXVlKGZpZ19zN19kb3duW1s1XV0pCgpib3RoX3VwX2lkeCA8LSBib3RoX3RhYmxlX2hzW1sibGltbWFfbG9nZmMueCJdXSA+PSAwLjggJgogIGJvdGhfdGFibGVfaHNbWyJsaW1tYV9sb2dmYy55Il1dID49IDAuOCAmCiAgYm90aF90YWJsZV9oc1tbImxpbW1hX2FkanAueCJdXSA8PSAwLjEgJgogIGJvdGhfdGFibGVfaHNbWyJsaW1tYV9hZGpwLnkiXV0gPD0gMC4xCmJvdGhfdXBfaWRzIDwtIGJvdGhfdGFibGVfaHNbYm90aF91cF9pZHgsICJoc2FwaWVucyJdCnVwX3Zlbm4gPC0gVmVubmVyYWJsZTo6VmVubihTZXRzPWxpc3QoImZpZ3M3IiA9IGZpZ19zN19oc191cCwgInRhYmxlcyIgPSBib3RoX3VwX2lkcykpClZlbm5lcmFibGU6OnBsb3QodXBfdmVubikKCmJvdGhfZG93bl9pZHggPC0gYm90aF90YWJsZV9oc1tbImxpbW1hX2xvZ2ZjLngiXV0gPD0gLTAuOCAmCiAgYm90aF90YWJsZV9oc1tbImxpbW1hX2xvZ2ZjLnkiXV0gPD0gLTAuOCAmCiAgYm90aF90YWJsZV9oc1tbImxpbW1hX2FkanAueCJdXSA8PSAwLjEgJgogIGJvdGhfdGFibGVfaHNbWyJsaW1tYV9hZGpwLnkiXV0gPD0gMC4xCmJvdGhfZG93bl9pZHMgPC0gYm90aF90YWJsZV9oc1tib3RoX2Rvd25faWR4LCAiaHNhcGllbnMiXQpkb3duX3Zlbm4gPC0gVmVubmVyYWJsZTo6VmVubihTZXRzPWxpc3QoImZpZ3M3IiA9IGZpZ19zN19oc19kb3duLCAidGFibGVzIiA9IGJvdGhfZG93bl9pZHMpKQpWZW5uZXJhYmxlOjpwbG90KGRvd25fdmVubikKYGBgCgpgYGB7ciBzYXZlbWV9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkKIyMgbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCBzYXZlZmlsZSkpCiMjIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9c2F2ZWZpbGUpKQpgYGAK