Some Other Topics

Some topics we did not have time to look at:

Visualizing Uncertainty: Hurricanes

All estimates from data are associated with some degree of uncertainty.

Effectively communicating that uncertainty in visualizations is challenging and an active area of research.

The cone of uncertainty: (From Cairo (2019); images from a blog post by the author.)

The NHC forecast cone is designed so that two-thirds of historical official forecast errors over a 5-year sample fall within the cone for a particular time point..

When published in the media these visualizations are routinely misinterpreted something like this:

A more effective representation might be something like this, showing an ensemble of possible tracks:

An animated version may be more effective, if the presentation medium permits.

Developing better visualizations for hurricane forecasting, especially targeting the public, is an active area of research.

Visualizing Uncertainty: Chocolate Bars

Expert ratings, on a scale from 0 to 5, for chocolate bars manufactured in several countries:

The standard deviations of the data distributions are comparable, but the lengths of confidence intervals for the mean vary because of the different sample sizes:

The same plot with a reduced horizontal range:

A more elaborate display with confidence intervals at several levels:

Confidence densities, or confidence distributions, as proposed in

Adrian W. Bowman. Graphics for Uncertainty. J. R. Statist. Soc. A 182:1-16, 2018. Link

One drawback of all of these methods:

The least precise measurement draws the most attention.

These examples from Wilke’s book use the ungeviz package available on GitHub.

Another package providing some tools for uncertainty visualization is ggdist package.

Visualizing Uncertainty: Old Cars

Using the very old mtcars data set to illustrate estimating a smooth relationship:

A default geom_smooth shows an estimate along with a point-wise confidence band.

This may not give the best sense of the joint uncertainty: if the curve is higher on some places it may need to be lower in others.

Showing an ensemble of curves that all are plausible can be a better choice.

This approach was shown earlier for visualizing possible hurricane paths.

This ensemble is generated using a case-based bootstrap.

These plots are called ensemble plots (also spaghetti plots, for obvious reasons).

If animation is available, an alternative is to show the curves one at a time in an animation.

Again, a bootstrap is used to produce the estimates.

This is an example of a hypothetical outcomes plot, or HOP, as introduced in

Hullman, Jessica, Paul Resnick, and Eytan Adar. “Hypothetical outcome plots outperform error bars and violin plots for inferences about reliability of variable ordering.” PLOS ONE 10, no. 11 (2015).

Data Quality and Integrity

A visualization can accurately reflect data but still be misleading if the data are faulty.

A NY Times article from May 2021 shows a choropleth map of the estimated share of adults who would “definitely” or “probably” get the COVID-19 vaccine.

Cutoffs: 49 60 65 70 75 80 91 %

The map may accurately reflect the estimates, but the estimates have obvious problems.

The data used for the map are available here.

Discussions on social media suggest that the state level data may be more reasonable:

Data Science Ethics

Some issues:

Some references:

Plot Annotation, Plot Ensembles, and Dashboards

Plot annotations can create popout and help focus the viewer’s attention.

They may be increasingly important as images are shared on line without context.

Here is an examples for the mpg data:

Plot Ensembles: Coffee

It is often useful to use several graphics to present an analysis.

Collections of related graphs are sometimes called ensemble graphics.

On line presentations of analyses involving multiple visualizations and, typically, some interactive features are also called dashboards.

To aid the viewer it is usually best to design these visualizations together, with common axis choices and color mappings.

Fig 12.1 in Unwin (2015) provides a simple example:

library(ggplot2)
library(GGally)
library(gridExtra)

coffee_thm <- theme(text = element_text(size = 14))

data(coffee, package = "pgmm")
coffee <- within(coffee, Type <- ifelse(Variety == 1,
                                        "Arabica", "Robusta"))
names(coffee) <- abbreviate(names(coffee), 8)
a <- ggplot(coffee, aes(x = Type)) + geom_bar(aes(fill = Type)) +
    scale_fill_manual(values = c("grey70", "red")) +
    guides(fill = "none") + ylab("") +
    coffee_thm
b <- ggplot(coffee, aes(x = Fat, y = Caffine, colour = Type)) +
    geom_point(size = 3) +
    scale_colour_manual(values = c("grey70", "red")) +
    coffee_thm
c <- ggparcoord(coffee[order(coffee$Type), ], columns = 3 : 14,
                groupColumn = "Type", scale = "uniminmax") +
    xlab("") + ylab("") +
    theme(legend.position = "none") +
    scale_colour_manual(values = c("grey", "red")) +
    theme(axis.ticks.y = element_blank(),
          axis.text.y = element_blank()) +
    coffee_thm
grid.arrange(arrangeGrob(a, b, ncol = 2, widths = c(1, 2)),
             c, nrow = 2)

A dashboard with three plots. A bar chart shows there are about 4 times as many Arabica samples ad Rubusta samples. A scatterplot of Caffeine against Fat content shows clear separation of the two groups. A parallel coordinates plot shows the 12 values measured on each group.

Data on the chemical composition of coffee samples collected from around the world, comprising 43 samples from 29 countries. Each sample is either of the Arabica or Robusta variety. Twelve of the thirteen chemical constituents reported in the study are given. The omitted variable is total chlorogenic acid; it is generally the sum of the chlorogenic, neochlorogenic and isochlorogenic acid values.

Streuli, H. (1973). Der heutige stand der kaffeechemie. In Association Scientifique International du Cafe, 6th International Colloquium on Coffee Chemisrty, Bogata, Columbia, pp. 61-72.

Making a Point and Telling a Story

In a report, make sure each plot has a point and makes its point.

Make sure to think about:

It is often good to make sure a figure can stand on its own without asking the reader to search the text for explanations.

Communicating with data is like telling a story, with a starting point, a journey, and an end.

Sometimes a single visualization can capture the full story.

More often, several visualizations will be needed.

Often it is good to:

With multiple visualizations it is good make sure that:

There is a chapter of Wilke, 2019 with more advice on this.

A recent book length treatment is

Deborah Nolan and Sara Stoudt (2021) Communicating with Data, Oxford Univerity Press.

Wrapping Up

Some of the areas we covered:

Visualization

Many different types of graphs.

  • Strengths, weaknesses.
  • Pitfalls.
  • Scalability.
  • Creating these graphs in R.

Perception

  • Channels and mappings; relative effectiveness.
  • Using to assess, design visualizations.
  • Effective use of color.

A little on interaction, animation.

Emphasis on techniques useful for exploration, scientific reporting.

Data Technologies

Reading different data formats.

Scraping data from the web.

Cleaning data.

Rearranging data for analysis.

Merging data from several sources.

Reproducible research tools

rmarkdown for integrating code and reporting.

Version control, git, GitLab.

Learning More

Class notes will remain available, in some form, at the class web site.

Some books to look at:

Some blogs to check out:

Keep a critical eye out for good (and not so good) uses of data visualization in the media.

LS0tCnRpdGxlOiAiRmluYWwgTm90ZXMiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9CnNvdXJjZShoZXJlOjpoZXJlKCJzZXR1cC5SIikpCm9wdGlvbnMoaHRtbHRvb2xzLmRpci52ZXJzaW9uID0gRkFMU0UpCmxpYnJhcnkoZ2dwbG90MikKa25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbGxhcHNlID0gVFJVRSwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSIsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSArCiAgICAgICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpICsKICAgICAgICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmV5MzAiLCBmaWxsID0gTkEpKSkKc2V0LnNlZWQoMTIzNDUpCmBgYAoKCiMjIFNvbWUgT3RoZXIgVG9waWNzCgpTb21lIHRvcGljcyB3ZSBkaWQgbm90IGhhdmUgdGltZSB0byBsb29rIGF0OgoKKiBXb3JraW5nIHdpdGggbW9kZWxzIChbQ2hhcHRlciA2IGluIEhlYWx5LAogIDIwMThdKGh0dHBzOi8vc29jdml6LmNvL21vZGVsaW5nLmh0bWwpOyBbQ2hhcHRlciAyNSBpbgogIFI0RFNdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovbWFueS1tb2RlbHMuaHRtbCkpLgoKKiBbVmlzdWFsaXppbmcgbWlzc2luZwogIHZhbHVlc10oaHR0cDovL25hbmlhci5uanRpZXJuZXkuY29tL2FydGljbGVzL25hbmlhci12aXN1YWxpc2F0aW9uLmh0bWwpLgoKKiBWaXN1YWxpemluZyB1bmNlcnRhaW50eSAoW0NoYXB0ZXIgMTYgb2YgV2lsa2UsCiAgMjAxOV0oaHR0cHM6Ly9jbGF1c3dpbGtlLmNvbS9kYXRhdml6L3Zpc3VhbGl6aW5nLXVuY2VydGFpbnR5Lmh0bWwpCiAgYW5kIFtiZWxvd10oI3Zpc3VhbGl6aW5nLXVuY2VydGFpbnR5KSkKCiogUGxvdCBhbm5vdGF0aW9uLCBwbG90IGVuc2VtYmxlcywgYW5kIGRhc2hib2FyZHMuIChbUGFydCBJSSBvZiBXaWxrZSwKICAyMDE5XShodHRwczovL2NsYXVzd2lsa2UuY29tL2RhdGF2aXovcHJvcG9ydGlvbmFsLWluay5odG1sKTsKICBbQ2hhcHRlciA1IG9mIEhlYWx5LCAyMDE4XShodHRwczovL3NvY3Zpei5jby93b3JrZ2VvbXMuaHRtbCk7CiAgW2JlbG93XSgjcGxvdC1hbm5vdGF0aW9uLXBsb3QtZW5zZW1ibGVzLWFuZC1kYXNoYm9hcmRzKSkuCgoqIERhdGEgU2NpZW5jZSBFdGhpY3MgKFtiZWxvd10oI2RhdGEtc2NpZW5jZS1ldGhpY3MpKS4KCgojIyBWaXN1YWxpemluZyBVbmNlcnRhaW50eTogSHVycmljYW5lcwoKQWxsIGVzdGltYXRlcyBmcm9tIGRhdGEgYXJlIGFzc29jaWF0ZWQgd2l0aCBzb21lIGRlZ3JlZSBvZiB1bmNlcnRhaW50eS4KCkVmZmVjdGl2ZWx5IGNvbW11bmljYXRpbmcgdGhhdCB1bmNlcnRhaW50eSBpbiB2aXN1YWxpemF0aW9ucyBpcwpjaGFsbGVuZ2luZyBhbmQgYW4gYWN0aXZlIGFyZWEgb2YKW3Jlc2VhcmNoXShodHRwOi8vc3BhY2UudWNtZXJjZWQuZWR1L2NoYXB0ZXIpLgoKVGhlIF9jb25lIG9mIHVuY2VydGFpbnR5XzogKEZyb20gQ2Fpcm8gKDIwMTkpOyBpbWFnZXMgZnJvbSBhIFtibG9nCnBvc3RdKGh0dHA6Ly93d3cudGhlZnVuY3Rpb25hbGFydC5jb20vMjAyMC8wMS9hbGwtZ3JhcGhpY3MtZnJvbS1ob3ctY2hhcnRzLWxpZS1mcmVlbHkuaHRtbCkKYnkgdGhlIGF1dGhvci4pCgo8IS0tCmh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3NoL2Qxa2IwamRyaGtiNDNqOS9BQURUQmZSdkFoLW14bVN4QlJOWnBMSmphLzUuQ0hBUFRFUjU/ZGw9MCZwcmV2aWV3PVBERjEwLlRyb3BpY2Fsc3Rvcm0ucGRmJnN1YmZvbGRlcl9uYXZfdHJhY2tpbmc9MQotLT4KYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoSU1HKCJQREYxMC5Ucm9waWNhbHN0b3JtLnBuZyIpKQpgYGAKClRoZSBbTkhDIGZvcmVjYXN0IGNvbmVdKGh0dHBzOi8vd3d3Lm5oYy5ub2FhLmdvdi9hYm91dGNvbmUuc2h0bWwpIGlzCmRlc2lnbmVkIHNvIHRoYXQgdHdvLXRoaXJkcyBvZiBoaXN0b3JpY2FsIG9mZmljaWFsIGZvcmVjYXN0IGVycm9ycyBvdmVyCmEgNS15ZWFyIHNhbXBsZSBmYWxsIHdpdGhpbiB0aGUgY29uZSBmb3IgYSBwYXJ0aWN1bGFyIHRpbWUgcG9pbnQuLgoKV2hlbiBwdWJsaXNoZWQgaW4gdGhlIG1lZGlhIHRoZXNlIHZpc3VhbGl6YXRpb25zIGFyZSByb3V0aW5lbHkKbWlzaW50ZXJwcmV0ZWQgc29tZXRoaW5nIGxpa2UgdGhpczoKCjwhLS0KaHR0cHM6Ly93d3cuZHJvcGJveC5jb20vc2gvZDFrYjBqZHJoa2I0M2o5L0FBRFRCZlJ2QWgtbXhtU3hCUk5acExKamEvNS5DSEFQVEVSNT9kbD0wJnByZXZpZXc9UERGMTEuU3Rvcm1XUk9OR1NpemUucGRmJnN1YmZvbGRlcl9uYXZfdHJhY2tpbmc9MQotLT4KCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKElNRygiUERGMTEuU3Rvcm1XUk9OR1NpemUucG5nIikpCmBgYAoKQSBtb3JlIGVmZmVjdGl2ZSByZXByZXNlbnRhdGlvbiBtaWdodCBiZSBzb21ldGhpbmcgbGlrZSB0aGlzLCBzaG93aW5nCmFuIF9lbnNlbWJsZV8gb2YgcG9zc2libGUgdHJhY2tzOgoKPCEtLQpodHRwczovL3d3dy5kcm9wYm94LmNvbS9zaC9kMWtiMGpkcmhrYjQzajkvQUFEVEJmUnZBaC1teG1TeEJSTlpwTEpqYS81LkNIQVBURVI1P2RsPTAmcHJldmlldz1QREYxMy5TdG9ybUxpbmVzLnBkZiZzdWJmb2xkZXJfbmF2X3RyYWNraW5nPTEKLS0+CgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhJTUcoIlBERjEzLlN0b3JtTGluZXMucG5nIikpCmBgYAoKQW4gYW5pbWF0ZWQgdmVyc2lvbiBtYXkgYmUgbW9yZSBlZmZlY3RpdmUsIGlmIHRoZSBwcmVzZW50YXRpb24gbWVkaXVtCnBlcm1pdHMuCgpEZXZlbG9waW5nIGJldHRlciB2aXN1YWxpemF0aW9ucyBmb3IgaHVycmljYW5lIGZvcmVjYXN0aW5nLCBlc3BlY2lhbGx5CnRhcmdldGluZyB0aGUgcHVibGljLCBpcyBhbiBhY3RpdmUgYXJlYSBvZiByZXNlYXJjaC4KCgojIyBWaXN1YWxpemluZyBVbmNlcnRhaW50eTogQ2hvY29sYXRlIEJhcnMKCltFeHBlcnQgcmF0aW5nc10oaHR0cDovL2ZsYXZvcnNvZmNhY2FvLmNvbSksIG9uIGEgc2NhbGUgZnJvbSAwIHRvIDUsCmZvciBjaG9jb2xhdGUgYmFycyBtYW51ZmFjdHVyZWQgaW4gc2V2ZXJhbCBjb3VudHJpZXM6CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpkYXRhKGNhY2FvLCBwYWNrYWdlID0gImR2aXouc3VwcCIpCmxpYnJhcnkoY29sb3JzcGFjZSkKY291bnRyaWVzIDwtIGMoIlUuUy5BLiIsICJBdXN0cmlhIiwgIkJlbGdpdW0iLCAiQ2FuYWRhIiwgIlBlcnUiLCAiU3dpdHplcmxhbmQiKQoKY29sODAgPC0gZGVzYXR1cmF0ZShkYXJrZW4oIiMwMDcyQjIiLCAuMiksIC4zKQpjb2w5NSA8LSBkZXNhdHVyYXRlKGxpZ2h0ZW4oIiMwMDcyQjIiLCAuMiksIC4zKQpjb2w5OSA8LSBkZXNhdHVyYXRlKGxpZ2h0ZW4oIiMwMDcyQjIiLCAuNCksIC4zKQpjb2xQIDwtIGNvbDk1CmNvbE0gPC0gIiNENTVFMDAiCgpjMSA8LSBmaWx0ZXIoY2FjYW8sIGxvY2F0aW9uICVpbiUgY291bnRyaWVzKQpjMXN1bXMgPC0gZ3JvdXBfYnkoYzEsIGxvY2F0aW9uKSAlPiUKICAgIHN1bW1hcml6ZShtID0gbWVhbihyYXRpbmcpLAogICAgICAgICAgICAgIHMgPSBzZChyYXRpbmcpLAogICAgICAgICAgICAgIG4gPSBuKCkpICU+JQogICAgdW5ncm91cCgpCgpjMUNJIDwtIG11dGF0ZShkYXRhLmZyYW1lKGxldmVsID0gYygwLjgsIDAuOTUsIDAuOTkpKSwKICAgICAgICAgICAgICAgZGYgPSBsYXBwbHkobGV2ZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGxldikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpdGgoYzFzdW1zLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaCA8LSBzICogcXQoMSAtICgxIC0gbGV2KSAvIDIsIG4gLSAxKSAvCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNxcnQobikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYmluZChjMXN1bXMsIGRhdGEuZnJhbWUoeG1pbiA9IG0gLSBoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWF4ID0gbSArIGgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpKSAlPiUKICAgIHVubmVzdCgiZGYiKQoKZ2dwbG90KGMxLCBhZXMocmF0aW5nLCByZW9yZGVyKGxvY2F0aW9uLCByYXRpbmcpKSkgKwogICAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcihoZWlnaHQgPSAwLjMsIHdpZHRoID0gMC4wNSksCiAgICAgICAgICAgICAgIHNpemUgPSAwLjUsIGNvbG9yID0gY29sUCkgKwogICAgIyNnZW9tX3BvaW50KGFlcyhtLCBsb2NhdGlvbiksIGRhdGEgPSBjMXN1bXMsIHNpemUgPSAyLjUsIGNvbG9yID0gY29sTSkgKwogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gbSwgeGVuZCA9IG0sCiAgICAgICAgICAgICAgICAgICAgIHkgPSBhcy5pbnRlZ2VyKHJlb3JkZXIobG9jYXRpb24sIG0pKSAtIDAuMywKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGFzLmludGVnZXIocmVvcmRlcihsb2NhdGlvbiwgbSkpICsgMC4zKSwKICAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLCBjb2xvciA9IGNvbE0sIGRhdGEgPSBjMXN1bXMpICsKICAgIHlsYWIoIiIpICsKICAgIGdndGl0bGUoIlJhdGluZ3MgZm9yIENob2NvbGF0ZSBCYXJzIiwgIkJhcnMgYXJlIHNhbXBsZSBtZWFucy4iKQpgYGAKClRoZSBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIHRoZSBkYXRhIGRpc3RyaWJ1dGlvbnMgYXJlIGNvbXBhcmFibGUsIGJ1dAp0aGUgbGVuZ3RocyBvZiBjb25maWRlbmNlIGludGVydmFscyBmb3IgdGhlIG1lYW4gdmFyeSBiZWNhdXNlIG9mIHRoZQpkaWZmZXJlbnQgc2FtcGxlIHNpemVzOgoKYGBge3IsIGVjaG8gPSBGQUxTRX0KcCA8LSBnZ3Bsb3QoZmlsdGVyKGMxQ0ksIGxldmVsID09IDAuOTUpLAogICAgICAgICAgICBhZXMobSwgcmVvcmRlcihsb2NhdGlvbiwgbSksIHhtaW4gPSB4bWluLCB4bWF4ID0geG1heCkpICsKICAgIGdlb21fZXJyb3JiYXJoKGhlaWdodCA9IDApICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDIuNSwgY29sb3IgPSBjb2xNKSArCiAgICB5bGFiKCIiKSArCiAgICBnZ3RpdGxlKCJDb25maWRlbmNlIEludGVydmFscyBmb3IgdGhlIE1lYW4iLCAiQ29uZmlkZW5jZSBsZXZlbCA5NSUiKQoKcCArIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDEsIDQpLCBuYW1lID0gIm1lYW4gcmF0aW5nIikKYGBgCgpUaGUgc2FtZSBwbG90IHdpdGggYSByZWR1Y2VkIGhvcml6b250YWwgcmFuZ2U6CgpgYGB7ciwgZWNobyA9IEZBTFNFfQpwICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMi41LCAzLjgpLCBuYW1lID0gIm1lYW4gcmF0aW5nIikKYGBgCgpBIG1vcmUgZWxhYm9yYXRlIGRpc3BsYXkgd2l0aCBjb25maWRlbmNlIGludGVydmFscyBhdCBzZXZlcmFsIGxldmVsczoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CiN8IHdhcm5pbmc6IGZhbHNlCiMjIGJhc2VkIG9uIGNvZGUgZm9yIFdpbGtlJ3MgRmlnLiAxNi43CmFycmFuZ2UoYzFDSSwgZGVzYyhsZXZlbCkpICU+JQogICAgbXV0YXRlKGxldmVsID0gcGFzdGUwKDEwMCAqIGxldmVsLCAiJSIpLAogICAgICAgICAgIGxvY2F0aW9uID0gcmVvcmRlcihsb2NhdGlvbiwgbSkpICU+JQogICAgZ2dwbG90KGFlcyhtLCBsb2NhdGlvbiwgeG1pbiA9IHhtaW4sIHhtYXggPSB4bWF4KSkgKwogICAgZ2VvbV9lcnJvcmJhcmgoYWVzKHNpemUgPSBsZXZlbCwgY29sb3IgPSBsZXZlbCksIGhlaWdodCA9IDApICsKICAgIGdlb21fZXJyb3JiYXJoKGFlcyhjb2xvciA9IGxldmVsKSwgaGVpZ2h0ID0gMC4xKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAyLjUsIGNvbG9yID0gY29sTSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMi41LCAzLjgpLCBuYW1lID0gIm1lYW4gcmF0aW5nIikgKwogICAgc2NhbGVfc2l6ZV9tYW51YWwobmFtZSA9ICJjb25maWRlbmNlIGxldmVsIiwKICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGMoYDgwJWAgPSAyLjI1LCBgOTUlYCA9IDEuNSwgYDk5JWAgPSAwLjc1KSwKICAgICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfbGVnZW5kKGRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC5wb3NpdGlvbiA9ICJib3R0b20iKSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAiY29uZmlkZW5jZSBsZXZlbCIsCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYyhgODAlYCA9IGNvbDgwLCBgOTUlYCA9IGNvbDk1LCBgOTklYCA9IGNvbDk5KSwKICAgICAgICAgICAgICAgICAgICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZChkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUucG9zaXRpb24gPSAidG9wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC5wb3NpdGlvbiA9ICJib3R0b20iKSkgKwoKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMSwgMC4wMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLCAwKSkgKwogICAgeWxhYigiIikgKwogICAgZ2d0aXRsZSgiQ29uZmlkZW5jZSBJbnRlcnZhbHMgZm9yIHRoZSBNZWFuIikKYGBgCgpDb25maWRlbmNlIGRlbnNpdGllcywgb3IgY29uZmlkZW5jZSBkaXN0cmlidXRpb25zLCBhcyBwcm9wb3NlZCBpbgoKPiBBZHJpYW4gVy4gQm93bWFuLiBHcmFwaGljcyBmb3IgVW5jZXJ0YWludHkuIEouIFIuIFN0YXRpc3QuIFNvYy4gQQo+IDE4MjoxLTE2LCAyMDE4LiBbTGlua10oaHR0cHM6Ly9yc3Mub25saW5lbGlicmFyeS53aWxleS5jb20vZG9pL2Z1bGwvMTAuMTExMS9yc3NhLjEyMzc5KQoKYGBge3IsIGVjaG8gPSBGQUxTRX0KIyMgYmFzZWQgb24gY29kZSBmb3IgV2lsa2UncyBGaWcuIDE2LjkgKGUpCmxpYnJhcnkodW5nZXZpeikKZ2dwbG90KGZpbHRlcihjMUNJLCBsZXZlbCA9PSAwLjk1KSwKICAgICAgIGFlcyh4ID0gbSwgeSA9IHJlb3JkZXIobG9jYXRpb24sIG0pKSkgKwogICAgc3RhdF9jb25maWRlbmNlX2RlbnNpdHkoYWVzKG1vZSA9IHhtYXggLSBtLCBmaWxsID0gYWZ0ZXJfc3RhdChuZGVuc2l0eSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMC43LCBjb25maWRlbmNlID0gMC45NSwgYWxwaGEgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSkgKwogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gbSwgeGVuZCA9IG0sCiAgICAgICAgICAgICAgICAgICAgIHkgPSBhcy5pbnRlZ2VyKHJlb3JkZXIobG9jYXRpb24sIG0pKSAtIDAuMzUsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhcy5pbnRlZ2VyKHJlb3JkZXIobG9jYXRpb24sIG0pKSArIDAuMzUpLAogICAgICAgICAgICAgICAgIHNpemUgPSAyLCBjb2xvciA9IGNvbE0pICsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIiM4MUE3RDYwMCIsIGhpZ2ggPSAiIzM0NUE3RkQwIikgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMi41LCAzLjgpLCBuYW1lID0gIm1lYW4gcmF0aW5nIikgKwogICAgeWxhYigiIikKYGBgCgpPbmUgZHJhd2JhY2sgb2YgYWxsIG9mIHRoZXNlIG1ldGhvZHM6Cgo+IFRoZSBsZWFzdCBwcmVjaXNlIG1lYXN1cmVtZW50IGRyYXdzIHRoZSBtb3N0IGF0dGVudGlvbi4KClRoZXNlIGV4YW1wbGVzIGZyb20gV2lsa2UncyBib29rIHVzZSB0aGUgW2B1bmdldml6YApwYWNrYWdlXShodHRwczovL2dpdGh1Yi5jb20vd2lsa2VsYWIvdW5nZXZpeikgYXZhaWxhYmxlIG9uIEdpdEh1Yi4KCkFub3RoZXIgcGFja2FnZSBwcm92aWRpbmcgc29tZSB0b29scyBmb3IgdW5jZXJ0YWludHkgdmlzdWFsaXphdGlvbiBpcwpbYGdnZGlzdGAgcGFja2FnZV0oaHR0cHM6Ly9tanNrYXkuZ2l0aHViLmlvL2dnZGlzdC8pLgoKCiMjIFZpc3VhbGl6aW5nIFVuY2VydGFpbnR5OiBPbGQgQ2FycwoKVXNpbmcgdGhlIHZlcnkgb2xkIGBtdGNhcnNgIGRhdGEgc2V0IHRvIGlsbHVzdHJhdGUgZXN0aW1hdGluZyBhIHNtb290aApyZWxhdGlvbnNoaXA6CgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CnAgPC0gZ2dwbG90KG10Y2FycywgYWVzKGRpc3AsIG1wZykpICsKICAgIGdlb21fcG9pbnQoKQoKcCArIGdlb21fc21vb3RoKCkKYGBgCgpBIGRlZmF1bHQgYGdlb21fc21vb3RoYCBzaG93cyBhbiBlc3RpbWF0ZSBhbG9uZyB3aXRoIGEgcG9pbnQtd2lzZQpjb25maWRlbmNlIGJhbmQuCgpUaGlzIG1heSBub3QgZ2l2ZSB0aGUgYmVzdCBzZW5zZSBvZiB0aGUgam9pbnQgdW5jZXJ0YWludHk6IGlmIHRoZSBjdXJ2ZQppcyBoaWdoZXIgb24gc29tZSBwbGFjZXMgaXQgbWF5IG5lZWQgdG8gYmUgbG93ZXIgaW4gb3RoZXJzLgoKU2hvd2luZyBhbiBfZW5zZW1ibGVfIG9mIGN1cnZlcyB0aGF0IGFsbCBhcmUgcGxhdXNpYmxlIGNhbiBiZSBhIGJldHRlcgpjaG9pY2UuCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9Cm10cyA8LSBsYXBwbHkoc2VxX2xlbigxMCksCiAgICAgICAgICAgICAgZnVuY3Rpb24oaSkgbXV0YXRlKHNhbXBsZV9mcmFjKG10Y2FycywgMSwgcmVwbGFjZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGUgPSBpKSkgJT4lCiAgICBiaW5kX3Jvd3MKCnAyIDwtIHAgKwogICAgZ2VvbV9zbW9vdGgoY29sb3IgPSBOQSkgKwogICAgZ2VvbV9zbW9vdGgoYWVzKGdyb3VwID0gc2FtcGxlKSwKICAgICAgICAgICAgICAgIHNlID0gRkFMU0UsIHNpemUgPSAwLjMsIGNvbG9yID0gIiMzMzY2RkYiLCBkYXRhID0gbXRzKQpwMgpgYGAKClRoaXMgYXBwcm9hY2ggd2FzIHNob3duIGVhcmxpZXIgZm9yIHZpc3VhbGl6aW5nIHBvc3NpYmxlIGh1cnJpY2FuZSBwYXRocy4KClRoaXMgZW5zZW1ibGUgaXMgZ2VuZXJhdGVkIHVzaW5nIGEgX2Nhc2UtYmFzZWQgYm9vdHN0cmFwXy4KClRoZXNlIHBsb3RzIGFyZSBjYWxsZWQgX2Vuc2VtYmxlIHBsb3RzXyAoYWxzbyBzcGFnaGV0dGkgcGxvdHMsIGZvcgpvYnZpb3VzIHJlYXNvbnMpLgoKSWYgYW5pbWF0aW9uIGlzIGF2YWlsYWJsZSwgYW4gYWx0ZXJuYXRpdmUgaXMgdG8gc2hvdyB0aGUgY3VydmVzIG9uZSBhdAphIHRpbWUgaW4gYW4gYW5pbWF0aW9uLgoKYGBge3IsIGNhY2hlID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CmxpYnJhcnkoZ2dhbmltYXRlKQphbmltYXRlKHAyICsKICAgICAgICB0cmFuc2l0aW9uX3N0YXRlcyhzYW1wbGUsIHRyYW5zaXRpb25fbGVuZ3RoID0gMiwgc3RhdGVfbGVuZ3RoID0gMSkpCmBgYAoKQWdhaW4sIGEgYm9vdHN0cmFwIGlzIHVzZWQgdG8gcHJvZHVjZSB0aGUgZXN0aW1hdGVzLgoKVGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgX2h5cG90aGV0aWNhbCBvdXRjb21lcyBwbG90Xywgb3IgX0hPUF8sIGFzCmludHJvZHVjZWQgaW4KCj4gSHVsbG1hbiwgSmVzc2ljYSwgUGF1bCBSZXNuaWNrLCBhbmQgRXl0YW4gQWRhci4gIkh5cG90aGV0aWNhbAo+IG91dGNvbWUgcGxvdHMgb3V0cGVyZm9ybSBlcnJvciBiYXJzIGFuZCB2aW9saW4gcGxvdHMgZm9yIGluZmVyZW5jZXMKPiBhYm91dCByZWxpYWJpbGl0eSBvZiB2YXJpYWJsZSBvcmRlcmluZy4iIFBMT1MgT05FIDEwLCBuby4gMTEgKDIwMTUpLgoKCiMjIERhdGEgUXVhbGl0eSBhbmQgSW50ZWdyaXR5CgpBIHZpc3VhbGl6YXRpb24gY2FuIGFjY3VyYXRlbHkgcmVmbGVjdCBkYXRhIGJ1dCBzdGlsbCBiZSBtaXNsZWFkaW5nIGlmCnRoZSBkYXRhIGFyZSBmYXVsdHkuCgpBIFtOWSBUaW1lcwphcnRpY2xlXShodHRwczovL3d3dy5ueXRpbWVzLmNvbS8yMDIxLzA1LzAzL2hlYWx0aC9jb3ZpZC1oZXJkLWltbXVuaXR5LXZhY2NpbmUuaHRtbCkKZnJvbSBNYXkgMjAyMSBzaG93cyBhIGNob3JvcGxldGggbWFwIG9mIHRoZSBlc3RpbWF0ZWQgc2hhcmUgb2YgYWR1bHRzCndobyB3b3VsZCAiZGVmaW5pdGVseSIgb3IgInByb2JhYmx5IiBnZXQgdGhlIENPVklELTE5IHZhY2NpbmUuCgpDdXRvZmZzOiA0OSAgNjAgICA2NSAgNzAgIDc1ICA4MCAgOTEgJQoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gNTAwfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhJTUcoIm1hcC0xMDUwLnBuZyIpKQpgYGAKClRoZSBtYXAgbWF5IGFjY3VyYXRlbHkgcmVmbGVjdCB0aGUgZXN0aW1hdGVzLCBidXQgdGhlIGVzdGltYXRlcyBoYXZlCm9idmlvdXMgcHJvYmxlbXMuCgpUaGUgZGF0YSB1c2VkIGZvciB0aGUgbWFwIGFyZSBhdmFpbGFibGUKW2hlcmVdKGh0dHBzOi8vYXNwZS5oaHMuZ292L3BkZi1yZXBvcnQvdmFjY2luZS1oZXNpdGFuY3kpLgoKRGlzY3Vzc2lvbnMgb24gc29jaWFsIG1lZGlhIHN1Z2dlc3QgdGhhdCB0aGUgc3RhdGUgbGV2ZWwgZGF0YSBtYXkgYmUKbW9yZSByZWFzb25hYmxlOgoKPCEtLSAjIyBub2xpbnQgc3RhcnQ6IGxpbmVfbGVuZ3RoIC0tPgo8IS0tIGh0dHBzOi8vdHdpdHRlci5jb20vY3RfYmVyZ3N0cm9tL3N0YXR1cy8xMzkwNTA5Mjk4Mzg4NjYwMjMxP3M9MTEgLS0+CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodCA9IDEwfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKZGF0YSA8LSByZWFkLmNzdigiaHR0cDovL3d3dy5zdGF0LnVpb3dhLmVkdS9+bHVrZS9kYXRhL1ZhY2NpbmVIZXNpdGFuY3ktMjAyMS0wNC0wNi5jc3YiKSAlPiUKICAgIHNldE5hbWVzKGMoImZpcHMiLCAic3RhdGUiLCAiSGVzaXRhbnQiLCAiU3Ryb25nbHlIZXNpdGFudCIpKSAlPiUKICAgIG11dGF0ZShhY3Jvc3MoMzo0LCBwYXJzZV9udW1iZXIpKSAlPiUKICAgIG11dGF0ZShXaWxsaW5nID0gMTAwIC0gSGVzaXRhbnQgLSBTdHJvbmdseUhlc2l0YW50KQoKbWFwIDwtIHVzbWFwOjp1c19tYXAoKSAlPiUKICAgIG11dGF0ZShmaXBzID0gYXMubnVtZXJpYyhmaXBzKSkKCm1hcF9kYXRhIDwtIGxlZnRfam9pbihtYXAsIGRhdGEsICJmaXBzIikKCmdncGxvdChtYXBfZGF0YSwKICAgICAgIGFlcyh4LCB5LAogICAgICAgICAgIGdyb3VwID0gZ3JvdXAsCiAgICAgICAgICAgZmlsbCA9IFdpbGxpbmcpKSArCiAgICBnZW9tX3BvbHlnb24oY29sb3IgPSAiYmxhY2siKSArCiAgICBjb29yZF9maXhlZCgpICsKICAgIGdndGhlbWVzOjp0aGVtZV9tYXAoKSArCiAgICBzY2FsZV9maWxsX2Rpc3RpbGxlcihwYWxldHRlID0gIlB1cnBsZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bGFiZWxfcGVyY2VudChzY2FsZSA9IDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGUgPSBndWlkZV9jb2xvcmJhcih0aXRsZS5oanVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUucG9zaXRpb24gPSAidG9wIikpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuNSwKICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsKICAgIGxhYnModGl0bGUgPSAiVW5ldmVuIFdpbGxpbmduZXNzIHRvIEdldCBWYWNjaW5hdGVkIENvdWxkIEFmZmVjdCBIZXJkIEltbXVuaXR5IiwKICAgICAgICAgc3VidGl0bGUgPSAiSW4gc29tZSBwYXJ0cyBvZiB0aGUgVW5pdGVkIFN0YXRlcywgaW5vY3VsYXRpb24gcmF0ZXMgbWF5IG5vdCByZWFjaCB0aGUgdGhyZXNob2xkIG5lZWRlZFxudG8gcHJldmVudCB0aGUgY29yb25hdmlydXMgZnJvbSBzcHJlYWRpbmcgZWFzaWx5LiIsCiAgICAgICAgIGNhcHRpb24gPSAiRGF0YTogaHR0cHM6Ly9hc3BlLmhocy5nb3YvcGRmLXJlcG9ydC92YWNjaW5lLWhlc2l0YW5jeSIsCiAgICAgICAgIGZpbGwgPSAiRXN0aW1hdGVkIHNoYXJlIG9mIGFkdWx0cyB3aG8gd291bGRcblwiZGVmaW5pdGVseVwiIG9yIFwicHJvYmFibHlcIiBnZXQgdGhlIHZhY2NpbmUiKQpgYGAKPCEtLSAjIyBub2xpbnQgZW5kIC0tPgoKPCEtLSBub3QgYmVpbmcgYWJsZSB0byBjZW50ZXIgYSBsb25nIGxlZ2VuZCB0aWx0ZSBzZWVtcyB0byBiZSBhCmN1cnJlbnQgZ2dwbG90IGJ1ZyAtLT4KCjxkaXYgaWQ9ImRhdGEtc2NpZW5jZS1ldGhpY3MiPjwvZGl2PgoKIyMgRGF0YSBTY2llbmNlIEV0aGljcwoKU29tZSBpc3N1ZXM6CgoqIERhdGEgbWlzcmVwcmVzZW50YXRpb24KCiogRGF0YSBmYWxzaWZpY2F0aW9uCgoqIERhdGEgcHJpdmFjeQoKKiBEYXRhIHNjcmFwaW5nIGFuZCB0ZXJtcyBvZiB1c2UKCiogQWxnb3JpdGhtaWMgYmlhcwoKU29tZSByZWZlcmVuY2VzOgoKPCEtLSBodHRwczovL2FyeGl2Lm9yZy9hYnMvMTkwOC4wNjE2NiAtLT4KCiogW0RhdGEgc2NpZW5jZQogIGV0aGljc10oaHR0cHM6Ly9tZHNyLWJvb2suZ2l0aHViLmlvL21kc3IyZS9jaC1ldGhpY3MuaHRtbCkgY2hhcHRlcgogIGluOiBCZW5qYW1pbiBTLiBCYXVtZXIsIERhbmllbCBULiBLYXBsYW4sIGFuZCBOaWNob2xhcyBKLiBIb3J0b24KICAoMjAyMSkgIAogIFtfTW9kZXJuIERhdGEgU2NpZW5jZSB3aXRoIFIsIDJuZCBlZGl0aW9uX10oaHR0cHM6Ly9tZHNyLWJvb2suZ2l0aHViLmlvL21kc3IyZS8pLgoKKiBbRGF0YSBzY2llbmNlIGV0aGljc10oaHR0cHM6Ly9kYXRhc2NpZW5jZWJveC5vcmcvMDItZXRoaWNzLmh0bWwpIHNlY3Rpb24gb2YKICB0aGUgb25saW5lIGJvb2sKICBbRGF0YSBTY2llbmNlIGluIGEgQm94XShodHRwczovL2RhdGFzY2llbmNlYm94Lm9yZy9pbmRleC5odG1sKQogIGJ5IE1pbmUgw4dldGlua2F5YS1SdW5kZWwuLgoKKiBBbGJlcnRvIENhaXJvICgyMDE5KSBfSG93IENoYXJ0cyBMaWU6IEdldHRpbmcgU21hcnRlciBhYm91dCBWaXN1YWwKICBJbmZvcm1hdGlvbl8sIFcuIFcuIE5vcnRvbiAmIENvbXBhbnkuCgo8ZGl2IGlkPSJwbG90LWFubm90YXRpb24tcGxvdC1lbnNlbWJsZXMtYW5kLWRhc2hib2FyZHMiPjwvZGl2PgoKCiMjIFBsb3QgQW5ub3RhdGlvbiwgUGxvdCBFbnNlbWJsZXMsIGFuZCBEYXNoYm9hcmRzCgpQbG90IGFubm90YXRpb25zIGNhbiBjcmVhdGUgcG9wb3V0IGFuZCBoZWxwIGZvY3VzIHRoZSB2aWV3ZXIncwphdHRlbnRpb24uCgpUaGV5IG1heSBiZSBpbmNyZWFzaW5nbHkgaW1wb3J0YW50IGFzIGltYWdlcyBhcmUgc2hhcmVkIG9uIGxpbmUKd2l0aG91dCBjb250ZXh0LgoKSGVyZSBpcyBhbiBleGFtcGxlcyBmb3IgdGhlIGBtcGdgIGRhdGE6Cgo8IS0tICMjIG5vbGludCBzdGFydDogbGluZV9sZW5ndGggLS0+CmBgYHtyLCBlY2hvID0gRkFMU0V9CiN8IHdhcm5pbmc6IGZhbHNlCmxpYnJhcnkoZ2dmb3JjZSkKZ2dwbG90KG1wZywgYWVzKGRpc3BsLCBod3kpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgZ2VvbV9tYXJrX2h1bGwoYWVzKGZpbHRlciA9IGNsYXNzID09ICIyc2VhdGVyIiksCiAgICAgICAgICAgICAgICAgICBmaWxsID0gImJsdWUiLAogICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAiMi1TZWF0ZXJzIGhhdmUgaGlnaCBkaXNwbGFjZW1lbnQgdmFsdWVzLCBidXQgYWxzbyBoaWdoIGZ1ZWwgZWZmaWNpZW5jeSBmb3IgdGhlaXIgZGlzcGxhY2VtZW50LiIpICsKICAgIGdlb21fbWFya19yZWN0KGFlcyhmaWx0ZXIgPSBod3kgPiA0MCksCiAgICAgICAgICAgICAgICAgICBmaWxsID0gImdyZWVuIiwKICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uID0gIlRoZXNlIGFyZSBWb2xrc3dhZ2VucyIpICsKICAgIGdlb21fbWFya19jaXJjbGUoYWVzKGZpbHRlciA9IGh3eSA9PSAxMiksCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSAicmVkIiwKICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAiVGhyZWUgcGlja3VwcyBhbmQgYW4gc3V2LiIpCmBgYAo8IS0tICMjIG5vbGludCBlbmQgLS0+CgoKIyMgUGxvdCBFbnNlbWJsZXM6IENvZmZlZQoKSXQgaXMgb2Z0ZW4gdXNlZnVsIHRvIHVzZSBzZXZlcmFsIGdyYXBoaWNzIHRvIHByZXNlbnQgYW4gYW5hbHlzaXMuCgpDb2xsZWN0aW9ucyBvZiByZWxhdGVkIGdyYXBocyBhcmUgc29tZXRpbWVzIGNhbGxlZCBfZW5zZW1ibGUgZ3JhcGhpY3NfLgoKT24gbGluZSBwcmVzZW50YXRpb25zIG9mIGFuYWx5c2VzIGludm9sdmluZyBtdWx0aXBsZSB2aXN1YWxpemF0aW9ucwphbmQsIHR5cGljYWxseSwgc29tZSBpbnRlcmFjdGl2ZSBmZWF0dXJlcyBhcmUgYWxzbyBjYWxsZWQKX2Rhc2hib2FyZHNfLgoKVG8gYWlkIHRoZSB2aWV3ZXIgaXQgaXMgdXN1YWxseSBiZXN0IHRvIGRlc2lnbiB0aGVzZSB2aXN1YWxpemF0aW9ucwp0b2dldGhlciwgd2l0aCBjb21tb24gYXhpcyBjaG9pY2VzIGFuZCBjb2xvciBtYXBwaW5ncy4KCkZpZyAxMi4xIGluIFVud2luICgyMDE1KSBwcm92aWRlcyBhIHNpbXBsZSBleGFtcGxlOgoKPCEtLSAjIyBub2xpbnQgc3RhcnQ6IGxpbmVfbGVuZ3RoIC0tPgpgYGB7ciwgb3V0LndpZHRoPSAiNjUlIiwgb3V0LmV4dHJhPSdzdHlsZT0iZmxvYXQ6cmlnaHQ7IHBhZGRpbmc6MTBweCInfQojfCBmaWcud2lkdGg6IDkKI3wgZmlnLmhlaWdodDogNi41CiN8IGZpZy1yZXRpbmE6IHRydWUKI3wgZmlnLWFsdDogIkEgZGFzaGJvYXJkIHdpdGggdGhyZWUgcGxvdHMuIEEgYmFyIGNoYXJ0IHNob3dzIHRoZXJlIGFyZSBhYm91dCA0IHRpbWVzIGFzIG1hbnkgQXJhYmljYSBzYW1wbGVzIGFkIFJ1YnVzdGEgc2FtcGxlcy4gQSBzY2F0dGVycGxvdCBvZiBDYWZmZWluZSBhZ2FpbnN0IEZhdCBjb250ZW50IHNob3dzIGNsZWFyIHNlcGFyYXRpb24gb2YgdGhlIHR3byBncm91cHMuIEEgcGFyYWxsZWwgY29vcmRpbmF0ZXMgcGxvdCBzaG93cyB0aGUgMTIgdmFsdWVzIG1lYXN1cmVkIG9uIGVhY2ggZ3JvdXAuIgoKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShncmlkRXh0cmEpCgpjb2ZmZWVfdGhtIDwtIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKCmRhdGEoY29mZmVlLCBwYWNrYWdlID0gInBnbW0iKQpjb2ZmZWUgPC0gd2l0aGluKGNvZmZlZSwgVHlwZSA8LSBpZmVsc2UoVmFyaWV0eSA9PSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFyYWJpY2EiLCAiUm9idXN0YSIpKQpuYW1lcyhjb2ZmZWUpIDwtIGFiYnJldmlhdGUobmFtZXMoY29mZmVlKSwgOCkKYSA8LSBnZ3Bsb3QoY29mZmVlLCBhZXMoeCA9IFR5cGUpKSArIGdlb21fYmFyKGFlcyhmaWxsID0gVHlwZSkpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImdyZXk3MCIsICJyZWQiKSkgKwogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgeWxhYigiIikgKwogICAgY29mZmVlX3RobQpiIDwtIGdncGxvdChjb2ZmZWUsIGFlcyh4ID0gRmF0LCB5ID0gQ2FmZmluZSwgY29sb3VyID0gVHlwZSkpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiZ3JleTcwIiwgInJlZCIpKSArCiAgICBjb2ZmZWVfdGhtCmMgPC0gZ2dwYXJjb29yZChjb2ZmZWVbb3JkZXIoY29mZmVlJFR5cGUpLCBdLCBjb2x1bW5zID0gMyA6IDE0LAogICAgICAgICAgICAgICAgZ3JvdXBDb2x1bW4gPSAiVHlwZSIsIHNjYWxlID0gInVuaW1pbm1heCIpICsKICAgIHhsYWIoIiIpICsgeWxhYigiIikgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoImdyZXkiLCAicmVkIikpICsKICAgIHRoZW1lKGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBjb2ZmZWVfdGhtCmdyaWQuYXJyYW5nZShhcnJhbmdlR3JvYihhLCBiLCBuY29sID0gMiwgd2lkdGhzID0gYygxLCAyKSksCiAgICAgICAgICAgICBjLCBucm93ID0gMikKYGBgCjwhLS0gIyMgbm9saW50IGVuZCAtLT4KCkRhdGEgb24gdGhlIGNoZW1pY2FsIGNvbXBvc2l0aW9uIG9mIGNvZmZlZSBzYW1wbGVzIGNvbGxlY3RlZCBmcm9tCmFyb3VuZCB0aGUgd29ybGQsIGNvbXByaXNpbmcgNDMgc2FtcGxlcyBmcm9tIDI5IGNvdW50cmllcy4gRWFjaCBzYW1wbGUKaXMgZWl0aGVyIG9mIHRoZSBBcmFiaWNhIG9yIFJvYnVzdGEgdmFyaWV0eS4gVHdlbHZlIG9mIHRoZSB0aGlydGVlbgpjaGVtaWNhbCBjb25zdGl0dWVudHMgcmVwb3J0ZWQgaW4gdGhlIHN0dWR5IGFyZSBnaXZlbi4gIFRoZSBvbWl0dGVkCnZhcmlhYmxlIGlzIHRvdGFsIGNobG9yb2dlbmljIGFjaWQ7IGl0IGlzIGdlbmVyYWxseSB0aGUgc3VtIG9mIHRoZQpjaGxvcm9nZW5pYywgbmVvY2hsb3JvZ2VuaWMgYW5kIGlzb2NobG9yb2dlbmljIGFjaWQgdmFsdWVzLgoKU3RyZXVsaSwgSC4gKDE5NzMpLiBEZXIgaGV1dGlnZSBzdGFuZCBkZXIga2FmZmVlY2hlbWllLiBJbgpfQXNzb2NpYXRpb24gU2NpZW50aWZpcXVlIEludGVybmF0aW9uYWwgZHUgQ2FmZSwgNnRoIEludGVybmF0aW9uYWwKQ29sbG9xdWl1bSBvbiBDb2ZmZWUgQ2hlbWlzcnR5XywgQm9nYXRhLCBDb2x1bWJpYSwgcHAuICA2MS03Mi4KCgojIyBNYWtpbmcgYSBQb2ludCBhbmQgVGVsbGluZyBhIFN0b3J5CgpJbiBhIHJlcG9ydCwgbWFrZSBzdXJlIGVhY2ggcGxvdCBoYXMgYSBwb2ludCBhbmQgbWFrZXMgaXRzIHBvaW50LgoKTWFrZSBzdXJlIHRvIHRoaW5rIGFib3V0OgoKKiBheGlzIGxhYmVsczsKCiogdGl0bGVzIGFuZCBzdWJ0aXRsZXM7CgoqIGNhcHRpb25zOwoKKiBoaWdobGlnaHRpbmcga2V5IGZlYXR1cmVzOyA8IS0tIGdnaGlnaGxpZ2h0IC0tPgoKKiBhY2Nlc3NpYmlsaXR5IChlLmcuIGNvbG9yIGNob2ljZTsgYWx0LXRleHQpLgoKSXQgaXMgb2Z0ZW4gZ29vZCB0byBtYWtlIHN1cmUgYSBmaWd1cmUgY2FuIHN0YW5kIG9uIGl0cyBvd24Kd2l0aG91dCBhc2tpbmcgdGhlIHJlYWRlciB0byBzZWFyY2ggdGhlIHRleHQgZm9yIGV4cGxhbmF0aW9ucy4KCkNvbW11bmljYXRpbmcgd2l0aCBkYXRhIGlzIGxpa2UgdGVsbGluZyBhIHN0b3J5LCB3aXRoIGEgc3RhcnRpbmcKcG9pbnQsIGEgam91cm5leSwgYW5kIGFuIGVuZC4KClNvbWV0aW1lcyBhIHNpbmdsZSB2aXN1YWxpemF0aW9uIGNhbiBjYXB0dXJlIHRoZSBmdWxsIHN0b3J5LgoKTW9yZSBvZnRlbiwgc2V2ZXJhbCB2aXN1YWxpemF0aW9ucyB3aWxsIGJlIG5lZWRlZC4KCk9mdGVuIGl0IGlzIGdvb2QgdG86CgoqIHN0YXJ0IHdpdGggYSBoaWdoIGxldmVsIG92ZXJ2aWV3OwoKKiBzaG93IGhvdyB0byBsb29rIGF0IHNvbWUgcGFydGljdWxhciBjYXNlcywgZS5nLiB3aXRoIGEgc2luZ2xlIHBsb3Q7CgoqIGJ1aWxkIHVwIHRvIGEgbW9yZSBjb21wbGV0ZSBhbmFseXNpcywgZS5nLiB3aXRoIGEgbXVsdGktcGFuZWwgcGxvdC4KCldpdGggbXVsdGlwbGUgdmlzdWFsaXphdGlvbnMgaXQgaXMgZ29vZCBtYWtlIHN1cmUgdGhhdDoKCiogZWFjaCBvbmUgd29ya3Mgd2VsbCBvbiBpdHMgb3duOwoKKiB0aGV5IHdvcmsgd2VsbCB0b2dldGhlciAoZS5nLiB1c2UgY29uc2lzdGVudCBzdHlsaW5nLCBjb2xvcnMpLgoKVGhlcmUgaXMgYSBbY2hhcHRlciBvZiBXaWxrZSwKMjAxOV0oaHR0cHM6Ly9jbGF1c3dpbGtlLmNvbS9kYXRhdml6L3RlbGxpbmctYS1zdG9yeS5odG1sKSB3aXRoIG1vcmUKYWR2aWNlIG9uIHRoaXMuCgpBIHJlY2VudCBib29rIGxlbmd0aCB0cmVhdG1lbnQgaXMKCj4gRGVib3JhaCBOb2xhbiBhbmQgU2FyYSBTdG91ZHQgKDIwMjEpIF9Db21tdW5pY2F0aW5nIHdpdGggRGF0YV8sCj4gT3hmb3JkIFVuaXZlcml0eSBQcmVzcy4KCgojIyBXcmFwcGluZyBVcAoKU29tZSBvZiB0aGUgYXJlYXMgd2UgY292ZXJlZDoKCgojIyMgVmlzdWFsaXphdGlvbgoKTWFueSBkaWZmZXJlbnQgdHlwZXMgb2YgZ3JhcGhzLgoKKiBTdHJlbmd0aHMsIHdlYWtuZXNzZXMuCiogUGl0ZmFsbHMuCiogU2NhbGFiaWxpdHkuCiogQ3JlYXRpbmcgdGhlc2UgZ3JhcGhzIGluIFIuCgpQZXJjZXB0aW9uCgoqIENoYW5uZWxzIGFuZCBtYXBwaW5nczsgcmVsYXRpdmUgZWZmZWN0aXZlbmVzcy4KKiBVc2luZyB0byBhc3Nlc3MsIGRlc2lnbiB2aXN1YWxpemF0aW9ucy4KKiBFZmZlY3RpdmUgdXNlIG9mIGNvbG9yLgoKQSBsaXR0bGUgb24gaW50ZXJhY3Rpb24sIGFuaW1hdGlvbi4KCkVtcGhhc2lzIG9uIHRlY2huaXF1ZXMgdXNlZnVsIGZvciBleHBsb3JhdGlvbiwgc2NpZW50aWZpYyByZXBvcnRpbmcuCgoKIyMjIERhdGEgVGVjaG5vbG9naWVzCgpSZWFkaW5nIGRpZmZlcmVudCBkYXRhIGZvcm1hdHMuCgpTY3JhcGluZyBkYXRhIGZyb20gdGhlIHdlYi4KCkNsZWFuaW5nIGRhdGEuCgpSZWFycmFuZ2luZyBkYXRhIGZvciBhbmFseXNpcy4KCk1lcmdpbmcgZGF0YSBmcm9tIHNldmVyYWwgc291cmNlcy4KCgojIyMgUmVwcm9kdWNpYmxlIHJlc2VhcmNoIHRvb2xzCgpgcm1hcmtkb3duYCBmb3IgaW50ZWdyYXRpbmcgY29kZSBhbmQgcmVwb3J0aW5nLgoKVmVyc2lvbiBjb250cm9sLCBgZ2l0YCwgYEdpdExhYmAuCgoKIyMgTGVhcm5pbmcgTW9yZQoKQ2xhc3Mgbm90ZXMgd2lsbCByZW1haW4gYXZhaWxhYmxlLCBpbiBzb21lIGZvcm0sIGF0IHRoZSBjbGFzcyB3ZWIgc2l0ZS4KClNvbWUgYm9va3MgdG8gbG9vayBhdDoKCiogQWxiZXJ0byBDYWlybyAoMjAxOSkgX0hvdyBDaGFydHMgTGllOiBHZXR0aW5nIFNtYXJ0ZXIgYWJvdXQgVmlzdWFsCiAgSW5mb3JtYXRpb25fLCBXLiBXLiBOb3J0b24gJiBDb21wYW55LgoKKiBDbGF1cyBPLiBXaWxrZSAoMjAxOSkgW19GdW5kYW1lbnRhbHMgb2YgRGF0YQogIFZpc3VhbGl6YXRpb25fXShodHRwczovL2NsYXVzd2lsa2UuY29tL2RhdGF2aXovKSwgT+KAmVJlaWxseSwKICBJbmMuIChbQm9vayBzb3VyY2Ugb24KICBHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9jbGF1c3dpbGtlL2RhdGF2aXopOyBbc3VwcG9ydGluZwogIG1hdGVyaWFscyBvbiBHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9jbGF1c3dpbGtlL2R2aXouc3VwcCkpCgoqIEtpZXJhbiBIZWFseSAoMjAxOCkgW19EYXRhIFZpc3VhbGl6YXRpb246IEEgcHJhY3RpY2FsCiAgaW50cm9kdWN0aW9uX10oaHR0cHM6Ly9zb2N2aXouY28vKSwgUHJpbmNldG9uCgoqIFdpbnN0b24gQ2hhbmcgKDIwMTgpIFtfUiBHcmFwaGljcyBDb29rYm9va18sIDJuZAogIGVkaXRpb25dKGh0dHBzOi8vci1ncmFwaGljcy5vcmcvKSwgT+KAmVJlaWxseS4gKFtCb29rIHNvdXJjZSBvbgogIEdpdEh1Yl0oaHR0cHM6Ly9naXRodWIuY29tL3djaC9yZ2Nvb2tib29rKSkKClNvbWUgYmxvZ3MgdG8gY2hlY2sgb3V0OgoKKiBbSnVuayBDaGFydHNdKGh0dHBzOi8vanVua2NoYXJ0cy50eXBlcGFkLmNvbS8pCgoqIFtUaGUgRnVuY3Rpb25hbCBBcnQgQmxvZ10oaHR0cDovL3d3dy50aGVmdW5jdGlvbmFsYXJ0LmNvbS8pCgoqIFtGbG93aW5nIERhdGFdKGh0dHBzOi8vZmxvd2luZ2RhdGEuY29tLykKCktlZXAgYSBjcml0aWNhbCBleWUgb3V0IGZvciBnb29kIChhbmQgbm90IHNvIGdvb2QpIHVzZXMgb2YgZGF0YQp2aXN1YWxpemF0aW9uIGluIHRoZSBtZWRpYS4K