Associated Material
Zoom notes: Zoom Notes 06 -
Communicate
Readings:
Introducing RMarkdown
So far through this course we’ve been using Rscripts for analysis
which lets us save and run our R code, including comments about what
we’re doing along the way. We’re now going to introduce RMarkdown
documents - which are like Rscripts on steroids!
RMarkdown is a framework that enables the creation of reproducible
documents which are a combination of text, R code, and the evaluated
output from the code all embedded in a single document. Not only that,
but from a single RMarkdown source document, multiple different output
formats can be produced such as HTML, PDF, and Word docs.
In fact this entire course has been written using RMarkdown! At the
top right of each page is a Code
button that will let you
download the RMarkdown code that created the page.
Below is an example of an RMarkdown source document
---
title: "Abridged Gapminder Analysis"
date: 2022-04-13
output: html_document
---
```{r setup, include = FALSE}
library(tidyverse)
```
# Introduction
Load in the Gapminder dataset so that it is ready for analysis
```{r read.csv}
# Save an imported data frame into a named variable
gapminder_data <- read_csv("gapminder_data_2007.csv")
```
There are `r nrow(gapminder_data)` rows to the dataset.
## Visualise Life Expectancy
This is a histogram of the life expectancy.
```{r hist}
# Histogram of life expectancy values from gapminder
gapminder_data %>%
ggplot(aes(x = lifeExp)) +
geom_histogram()
```
There are three main components to this document
- The YAML header which is surrounded by
---
s and provides information for the compiling
process
- R code chunks which are surrounded by
```
s
- Text which can be formatted using the Markdown language.
A reference guide of RMarkdown syntax can be found through
Help
-> Cheat Sheets
->
R Markdown Reference Guide
in the RStudio menu.
Example RMarkdown
Before we delve into explaining each part of the RMarkdown file we’re
going to create our own from the included template that comes with
RStudio.
Lets create our own RMarkdown document now from the template. To do
this go File
-> New File
->
R Markdown
. You’ll then be presented with a window that
looks like this
Take the opportunity to fill in your name and title then click
OK
.
You should now have a document that looks like the following:
---
title: "My First Rmd"
author: "Murray"
date: '2022-04-13'
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
RStudio Visual Editor
From Rstudio v1.2 there has been the inclusion of a live-preview
editor that can be turned on that provides a graphical point-and-click
method of editing Markdown.
Documentation for how to use the editor and its functionality can be
found at https://rstudio.github.io/visual-markdown-editing/
Knitting
In order to get our output document, we need to do a compiling step
or knit the document - behind the scenes the text
portions are formatted based on the markdown syntax, the R code is run
and the results generated, and then the formatted text, code, and
results are “knitted” together as a single output.
One of the key benefits on a reproducibility side is that RMarkdown
is evaluated from top to bottom externally from your session and so it
needs to be self-reliant and have all the commands from reading your
data in, processing it, and making your awesome tables and plots like in
the Visualisation Module.
To knit the document look for the knit
button in the top
left of the “source” panel. The keyboard shortcut is Ctrl +
Shift + K on PC or Apple +
Shift + K on MacOS.
You will then be prompted to save this script, call it
“r_markdown_example.Rmd” as save it in your scripts/
directory within your project directory. Once you have knitted a window
should pop-up containing your brand new analysis document!
RMarkdown scripts generally have the file extension
.Rmd
.
Take a few minutes to read from top to bottom through your script and
identifying the same features in your outputted HTML document.
Markdown syntax
Markdown is a simplified language that uses symbols to encode
formatting of text in a compiled document. Markdown documents can be
converted to HTML or LaTeX (used for PDF) through Pandoc (which comes
bundled with RStudio).
Headings
Headers - these use the # for the largest heading (header 1) through
to ###### the smallest heading (level 6) and correspond to the h1 to h6
heading tags in HTML.
# Level 1 heading
## level 2 heading
### level 3 heading
#### level 4 heading
##### level 5 heading
###### level 6 heading
We’ll cover some more of the common text formatting now, where you’ll
see the rendered paragraph followed by the markdown syntax that was used
to generate it:
Bold/Italics
Italics is encoded by surrounding word(s) with with a single
asterisk (*) or underscore (_), bold uses double
asterisks ** or underscores __. To superscript something,
surround it with carets (^), and to subscript surround it
with tilde (~). Surrounding with double tildes will
strikethrough.
*Italics* is encoded by surrounding word(s) with with a single asterisk (\*) or underscore (_), **bold** uses double asterisks ** or underscores __. To ^super^script something, surround it with carets (^), and to ~sub~script surround it with tilde (~). Surrounding with double tildes will ~~strikethrough~~.
Lists
Unordered lists can be made by starting a line with either a dash (-)
or an asterisk (*) and if you want to nest items use a tab or two spaces
to indent per layer.
- item 1
- item 2
- item 3
- item 4
- item 1
- item 2
- item 3
- subitem 1
- subitem 2
- sub sub item 1
- item 4
Ordered lists start the line with a number followed by a fullstop. It
is possible to nest unordered and ordered lists within the same list
- item 1
- item 2
- item 3
1. item 1
2. item 2
3. item 3
Block quotes
block quotes are a way of including blocks of text from someone else.
To use these that the line with a > angle bracket
> block quotes are a way of including blocks of text from someone else. To use these begin the line with a > angle bracket
Links
Links can be done as either the full url e.g. https://www.google.com, or
you can link words by surrounding
them with [] followed immediately by the url in parentheses.
Links can be done as either the full url e.g. https://www.google.com, or you can [link words](https://www.google.com) by surrounding them with [] followed immediately by the url in parentheses.
Verbatim code
If you want to include code in your document, the use of verbatim blocks will stop the symbols being interpreted for markdown and will be reproduced asis in the document.
These blocks are started and ended with three backticks ```
```
If you want to include code in your document as has been done to demonstrate the markdown code that generated each of the example paragraphs, the use of verbatim blocks will stop the symbols being interpreted for markdown and will be reproduced as is in the document.
Theses blocks are started and ended with three backticks ```
```
You can also do inline verbatim
by surrounding the text
with a single backtick
You can also do `inline verbatim` by surrounding the text with a single backtick
Code Chunks
Markdown provides verbatim code chunks, however where RMarkdown
really comes into its own is the ability to have the code that is
included evaluated and the results also embedded directly below the code
that was created them. While it’s called RMarkdown you’re also not just
limited to R but other languages can be included and run (so long as the
underlying engines are set up)
A code chunk takes this format, similar to to the verbatim code chunk
but following the first three backticks are curly braces, and inside the
name of the language in lower case - in this case “r”
```{r}
1 + 2
```
Would produce
1 + 2
#> [1] 3
Working directory
The working directory or location that R is going to start looking
for specified files (e.g. a csv to read in) for an RMarkdown will
default to the location the RMarkdown file is saved. This can be a
common source of errors in compiling an RMarkdown document if your
RMarkdown is saved in a subdirectory and you don’t have your file paths
correct.
Don’t use setwd()
in an RMarkdown. It will cause
issues.
If you are using an RStudio project and structure as introduced in Introducing R and Rstudio you can make use of
the here
package which provides a nice way of dealing with relative file paths as
if you were navigating from the top of your project directory.
For instance given the following project setup:
my_project/
|- data/
\- my_csv.csv
|- docs/
|- outputs/
|- scripts/
\- my_rmd.Rmd
\ - my_project.Rproj
If we were working on the file my_rmd.Rmd
without the
use of here
we would need to use relative paths from
scripts/
(we want to use relative paths within our project
because they aren’t dependant on any particular computer making our
project transferable) and the command to read data in would look like
this:
my_data <- read_csv("../data/my_csv.csv")
Using here
everything is relative from the
.Rproj
file which can be easier to think of since it
follows a relative path the same structure as the project, not relative
to where the file you’re currently working on lives - here
works all that out for you:
library(here)
my_data <- read_csv(here("data/my_csv.csv"))
Code Chunk Options
The behaviour of the code chunks can be modified with options. These
options are provided inside the {}’s of the code chunk and are comma
separated.
The defaults for a chunk are:
```{r, eval=TRUE, echo=TRUE, message=TRUE, include=TRUE, warning=TRUE}
1 + 2
```
echo=TRUE
will “echo” the code that is run above the
results
eval=TRUE
means the code inside the chunk will be
evaluated (run)
include=TRUE
means the code and the results will be
included in the document
warning=TRUE
will include any warnings as output in the
document
message=TRUE
will include messages as output in the
document
These can individually be specified and set to FALSE
to
disable the specific behaviour.
Citations
Citations can be inserted into an RMarkdown document. This
document from RStudio goes through how to do it using ether Markdown
or with the visual editor which can be linked with a citation manager
such as Zotero, or by searching DOIs and more.
Conclusion
This module has only scratched the surface of what is possible with
the highly versatile format that is RMarkdown. The main benefit that
RMarkdown is that it provides a mechanism to create reproducible
analysis documents that include prose, code, and generated outputs.
Make sure to check out RMarkdown - the definitive
guide for a comprehensive introduction and guide to the
possibilities of RMarkdown. There are also packages for creating
multi-document RMarkdown outputs such as entire websites
(packagedown
, distill
), blogs
(blogdown
), and books (bookdown
).
LS0tCnRpdGxlOiAiQ29tbXVuaWNhdGUiCmRhdGU6ICJTZW1lc3RlciAyLCAyMDIyIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbW1lbnQgPSAiIz4iLAogIGZpZy5wYXRoID0gImZpZ3VyZXMvMDYvIiwgIyB1c2Ugb25seSBmb3Igc2luZ2xlIFJtZCBmaWxlcwogIGNvbGxhcHNlID0gVFJVRSwKICBlY2hvID0gVFJVRQopCgoKYGBgCgo+ICMjIyMgQXNzb2NpYXRlZCBNYXRlcmlhbAo+Cj4gWm9vbSBub3RlczogW1pvb20gTm90ZXMgMDYgLSBDb21tdW5pY2F0ZV0oem9vbV9ub3Rlc18wNi5odG1sKQo+Cj4gUmVhZGluZ3M6Cj4KPiAtICAgW1IgZm9yIERhdGEgU2NpZW5jZSAtIENoYXB0ZXIgMjddKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovci1tYXJrZG93bi5odG1sKQo+IC0gICBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciAyOV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9yLW1hcmtkb3duLWZvcm1hdHMuaHRtbCkKPiAtICAgW1JlZmVyZW5jZTogUk1hcmtkb3duIC0gdGhlIGRlZmluaXRpdmUgZ3VpZGVdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi8pCj4gLSAgIFtSTWFya2Rvd24gUmVmZXJlbmNlIEd1aWRlXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMy9ybWFya2Rvd24tcmVmZXJlbmNlLnBkZikKCmBgYHs9aHRtbH0KPCEtLQpUaGlzIG1vZHVsZSBpcyBnb2luZyB0byBjb3ZlcjogCgotIHVzaW5nIHRoZSB7aGVyZX0gcGFja2FnZSB0byBtYW5hZ2UgcGF0aHMgZm9yIHNjcmlwdHMgYW5kIHJtYXJrZG93bgoKLSBVc2luZyB0aGUgZG9jdW1lbnQgb3V0bGluZS9jb2xsYXBzaW5nIGNvZGUgaW4gUnNjcmlwdHMKLSAoYnJpZWZseSkgY29udmVydGluZyBhIFIgc2NyaXB0IGludG8gYSBub3RlYm9vawoKVGhlIG1haW4gZm9jdXMgd2lsbCBiZSBvbiBjb3ZlcmluZyB0aGUgdXNlZnVsbmVzcyBvZiBSbWFya2Rvd24gaW4gY3JlYXRpbmcgZGVzY3JpcHRpdmUgYW5hbHlzaXMgZG9jdW1lbnRzCgpDb3ZlciB0aGUgYmFzaWNzIG9mIHRoZSAzIGNvbXBvbmVudHMgb2YgYW4gUm1hcmtkb3duIGRvY3VtZW50Ci0geWFtbAotIG1hcmtkb3duCi0gY29kZSBjaHVua3MKCkludHJvZHVjZSB0aGUgYmFzaWMgc3ludGF4IG9mIE1hcmtkb3duCi0gaGVhZGVycwotIGJvbGQvaXRhbGljcwotIGxpc3RzCi0gdmVyYmF0aW0gY29kZQoKCk9wdGlvbnMgb2YgYSBjb2RlIGNodW5rCi0gZWNobwotIGV2YWwKLSBpbmNsdWRlCi0gd2FybmluZwotIG1lc3NhZ2UKLSBmaWcKLSByZXN1bHRzCi0gaW5saW5lIGNvZGUKCkVtYmVkZGluZyBpbWFnZXMKLSBpbWFnZXMKICAtIGtuaXRyOjppbmNsdWRlX2dyYXBoaWNzCiAgLSBgIVtdKClgCiAgCkVtYmVkZGluZyBwbG90cwoKCk1ha2luZyB0YWJsZXMKLSBtYXJrZG93bgotIGtuaXRyOjprYWJsZQogIC0gY3VzdG9taXNpbmcgdGFibGVzIHdpdGggdGhlIHtrYWJsZUV4dHJhfSBwYWNrYWdlCgotLS0tLQotLT4KYGBgCiMjIEludHJvZHVjaW5nIFJNYXJrZG93bgoKU28gZmFyIHRocm91Z2ggdGhpcyBjb3Vyc2Ugd2UndmUgYmVlbiB1c2luZyBSc2NyaXB0cyBmb3IgYW5hbHlzaXMgd2hpY2ggbGV0cyB1cyBzYXZlIGFuZCBydW4gb3VyIFIgY29kZSwgaW5jbHVkaW5nIGNvbW1lbnRzIGFib3V0IHdoYXQgd2UncmUgZG9pbmcgYWxvbmcgdGhlIHdheS4gV2UncmUgbm93IGdvaW5nIHRvIGludHJvZHVjZSBSTWFya2Rvd24gZG9jdW1lbnRzIC0gd2hpY2ggYXJlIGxpa2UgUnNjcmlwdHMgb24gc3Rlcm9pZHMhCgpSTWFya2Rvd24gaXMgYSBmcmFtZXdvcmsgdGhhdCBlbmFibGVzIHRoZSBjcmVhdGlvbiBvZiByZXByb2R1Y2libGUgZG9jdW1lbnRzIHdoaWNoIGFyZSBhIGNvbWJpbmF0aW9uIG9mIHRleHQsIFIgY29kZSwgYW5kIHRoZSBldmFsdWF0ZWQgb3V0cHV0IGZyb20gdGhlIGNvZGUgYWxsIGVtYmVkZGVkIGluIGEgc2luZ2xlIGRvY3VtZW50LiBOb3Qgb25seSB0aGF0LCBidXQgZnJvbSBhIHNpbmdsZSBSTWFya2Rvd24gc291cmNlIGRvY3VtZW50LCBtdWx0aXBsZSBkaWZmZXJlbnQgb3V0cHV0IGZvcm1hdHMgY2FuIGJlIHByb2R1Y2VkIHN1Y2ggYXMgSFRNTCwgUERGLCBhbmQgV29yZCBkb2NzLgoKSW4gZmFjdCB0aGlzIGVudGlyZSBjb3Vyc2UgaGFzIGJlZW4gd3JpdHRlbiB1c2luZyBSTWFya2Rvd24hIEF0IHRoZSB0b3AgcmlnaHQgb2YgZWFjaCBwYWdlIGlzIGEgYENvZGVgIGJ1dHRvbiB0aGF0IHdpbGwgbGV0IHlvdSBkb3dubG9hZCB0aGUgUk1hcmtkb3duIGNvZGUgdGhhdCBjcmVhdGVkIHRoZSBwYWdlLgoKXAoKQmVsb3cgaXMgYW4gZXhhbXBsZSBvZiBhbiBSTWFya2Rvd24gc291cmNlIGRvY3VtZW50CgpgYGB7ciBlY2hvID0gRkFMU0UsIGNvbW1lbnQgPSAiIn0KY2F0KGh0bWx0b29sczo6aW5jbHVkZVRleHQoInNjcmlwdHMvZ2FwbWluZGVyX2FuYWx5c2lzLlJtZCIpKQpgYGAKClRoZXJlIGFyZSB0aHJlZSBtYWluIGNvbXBvbmVudHMgdG8gdGhpcyBkb2N1bWVudAoKMS4gIFRoZSAqKllBTUwqKiBoZWFkZXIgd2hpY2ggaXMgc3Vycm91bmRlZCBieSBgLS0tYHMgYW5kIHByb3ZpZGVzIGluZm9ybWF0aW9uIGZvciB0aGUgY29tcGlsaW5nIHByb2Nlc3MKMi4gIFIgY29kZSAqKmNodW5rcyoqIHdoaWNoIGFyZSBzdXJyb3VuZGVkIGJ5IGBgYGAgYGBgIGBgYGBzCjMuICBUZXh0IHdoaWNoIGNhbiBiZSBmb3JtYXR0ZWQgdXNpbmcgdGhlIE1hcmtkb3duIGxhbmd1YWdlLgoKCkEgcmVmZXJlbmNlIGd1aWRlIG9mIFJNYXJrZG93biBzeW50YXggY2FuIGJlIGZvdW5kIHRocm91Z2ggYEhlbHBgIC0+IGBDaGVhdCBTaGVldHNgIC0+IGBSIE1hcmtkb3duIFJlZmVyZW5jZSBHdWlkZWAgaW4gdGhlIFJTdHVkaW8gbWVudS4KClwKCiMjIyBFeGFtcGxlIFJNYXJrZG93bgoKQmVmb3JlIHdlIGRlbHZlIGludG8gZXhwbGFpbmluZyBlYWNoIHBhcnQgb2YgdGhlIFJNYXJrZG93biBmaWxlIHdlJ3JlIGdvaW5nIHRvIGNyZWF0ZSBvdXIgb3duIGZyb20gdGhlIGluY2x1ZGVkIHRlbXBsYXRlIHRoYXQgY29tZXMgd2l0aCBSU3R1ZGlvLgoKTGV0cyBjcmVhdGUgb3VyIG93biBSTWFya2Rvd24gZG9jdW1lbnQgbm93IGZyb20gdGhlIHRlbXBsYXRlLiBUbyBkbyB0aGlzIGdvIGBGaWxlYCAtXD4gYE5ldyBGaWxlYCAtXD4gYFIgTWFya2Rvd25gLiBZb3UnbGwgdGhlbiBiZSBwcmVzZW50ZWQgd2l0aCBhIHdpbmRvdyB0aGF0IGxvb2tzIGxpa2UgdGhpcwoKYGBge3IsIG91dC53aWR0aD0iMTAwJSIsIGVjaG8gPSBGQUxTRX0KaW5jbHVkZV9ncmFwaGljcygiaW1hZ2VzLzA2LW5ld19ybWQucG5nIikKYGBgCgpUYWtlIHRoZSBvcHBvcnR1bml0eSB0byBmaWxsIGluIHlvdXIgbmFtZSBhbmQgdGl0bGUgdGhlbiBjbGljayBgT0tgLgoKWW91IHNob3VsZCBub3cgaGF2ZSBhIGRvY3VtZW50IHRoYXQgbG9va3MgbGlrZSB0aGUgZm9sbG93aW5nOgoKYGBge3IgZWNobyA9IEZBTFNFLCBjb21tZW50ID0gIiJ9CmNhdChodG1sdG9vbHM6OmluY2x1ZGVUZXh0KCJzY3JpcHRzL3JtZF90ZW1wbGF0ZS5SbWQiKSkKYGBgCgojIyMgUlN0dWRpbyBWaXN1YWwgRWRpdG9yCgpGcm9tIFJzdHVkaW8gdjEuMiB0aGVyZSBoYXMgYmVlbiB0aGUgaW5jbHVzaW9uIG9mIGEgbGl2ZS1wcmV2aWV3IGVkaXRvciB0aGF0IGNhbiBiZSB0dXJuZWQgb24gdGhhdCBwcm92aWRlcyBhIGdyYXBoaWNhbCBwb2ludC1hbmQtY2xpY2sgbWV0aG9kIG9mIGVkaXRpbmcgTWFya2Rvd24uCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJTb3VyY2UgdmlldyJ9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wNi1ybWQtZWRpdG9yLnBuZyIpCmBgYAoKXAoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjkwJSIsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmNhcD0iVmlzdWFsIHZpZXcifQppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvMDYtcnN0dWRpby1ybWQtdmlzdWFsLnBuZyIpCmBgYAoKClwKCkRvY3VtZW50YXRpb24gZm9yIGhvdyB0byB1c2UgdGhlIGVkaXRvciBhbmQgaXRzIGZ1bmN0aW9uYWxpdHkgY2FuIGJlIGZvdW5kIGF0IFtodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL3Zpc3VhbC1tYXJrZG93bi1lZGl0aW5nL10oaHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby92aXN1YWwtbWFya2Rvd24tZWRpdGluZy8pCgpcCgojIyMgS25pdHRpbmcKCkluIG9yZGVyIHRvIGdldCBvdXIgb3V0cHV0IGRvY3VtZW50LCB3ZSBuZWVkIHRvIGRvIGEgY29tcGlsaW5nIHN0ZXAgb3IgKiprbml0KiogdGhlIGRvY3VtZW50IC0gYmVoaW5kIHRoZSBzY2VuZXMgdGhlIHRleHQgcG9ydGlvbnMgYXJlIGZvcm1hdHRlZCBiYXNlZCBvbiB0aGUgbWFya2Rvd24gc3ludGF4LCB0aGUgUiBjb2RlIGlzIHJ1biBhbmQgdGhlIHJlc3VsdHMgZ2VuZXJhdGVkLCBhbmQgdGhlbiB0aGUgZm9ybWF0dGVkIHRleHQsIGNvZGUsIGFuZCByZXN1bHRzIGFyZSAiKiprbml0dGVkKioiIHRvZ2V0aGVyIGFzIGEgc2luZ2xlIG91dHB1dC4KCk9uZSBvZiB0aGUga2V5IGJlbmVmaXRzIG9uIGEgcmVwcm9kdWNpYmlsaXR5IHNpZGUgaXMgdGhhdCBSTWFya2Rvd24gaXMgZXZhbHVhdGVkIGZyb20gdG9wIHRvIGJvdHRvbSBleHRlcm5hbGx5IGZyb20geW91ciBzZXNzaW9uIGFuZCBzbyBpdCBuZWVkcyB0byBiZSBzZWxmLXJlbGlhbnQgYW5kIGhhdmUgYWxsIHRoZSBjb21tYW5kcyBmcm9tIHJlYWRpbmcgeW91ciBkYXRhIGluLCBwcm9jZXNzaW5nIGl0LCBhbmQgbWFraW5nIHlvdXIgYXdlc29tZSB0YWJsZXMgYW5kIHBsb3RzIGxpa2UgaW4gdGhlIFtWaXN1YWxpc2F0aW9uIE1vZHVsZV0oMDItdmlzdWFsaXNlLmh0bWwpLgoKVG8ga25pdCB0aGUgZG9jdW1lbnQgbG9vayBmb3IgdGhlIGBrbml0YCBidXR0b24gaW4gdGhlIHRvcCBsZWZ0IG9mIHRoZSAic291cmNlIiBwYW5lbC4gVGhlIGtleWJvYXJkIHNob3J0Y3V0IGlzIDxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+U2hpZnQ8L2tiZD4gKyA8a2JkPks8L2tiZD4gb24gUEMgb3IgPGtiZD5BcHBsZTwva2JkPiArIDxrYmQ+U2hpZnQ8L2tiZD4gKyA8a2JkPks8L2tiZD4gb24gTWFjT1MuCgpgYGB7ciwgb3V0LndpZHRoID0gIjEwMCUiLCBlY2hvID0gRkFMU0V9CmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy8wMS1tYXJrZG93bl9rbml0X2J1dHRvbi5wbmciKQpgYGAKCllvdSB3aWxsIHRoZW4gYmUgcHJvbXB0ZWQgdG8gc2F2ZSB0aGlzIHNjcmlwdCwgY2FsbCBpdCAicl9tYXJrZG93bl9leGFtcGxlLlJtZCIgYXMgc2F2ZSBpdCBpbiB5b3VyIGBzY3JpcHRzL2AgZGlyZWN0b3J5IHdpdGhpbiB5b3VyIHByb2plY3QgZGlyZWN0b3J5LiBPbmNlIHlvdSBoYXZlIGtuaXR0ZWQgYSB3aW5kb3cgc2hvdWxkIHBvcC11cCBjb250YWluaW5nIHlvdXIgYnJhbmQgbmV3IGFuYWx5c2lzIGRvY3VtZW50IQoKPiBSTWFya2Rvd24gc2NyaXB0cyBnZW5lcmFsbHkgaGF2ZSB0aGUgZmlsZSBleHRlbnNpb24gYC5SbWRgLgoKVGFrZSBhIGZldyBtaW51dGVzIHRvIHJlYWQgZnJvbSB0b3AgdG8gYm90dG9tIHRocm91Z2ggeW91ciBzY3JpcHQgYW5kIGlkZW50aWZ5aW5nIHRoZSBzYW1lIGZlYXR1cmVzIGluIHlvdXIgb3V0cHV0dGVkIEhUTUwgZG9jdW1lbnQuCgpcCgojIyBNYXJrZG93biBzeW50YXgKCk1hcmtkb3duIGlzIGEgc2ltcGxpZmllZCBsYW5ndWFnZSB0aGF0IHVzZXMgc3ltYm9scyB0byBlbmNvZGUgZm9ybWF0dGluZyBvZiB0ZXh0IGluIGEgY29tcGlsZWQgZG9jdW1lbnQuIE1hcmtkb3duIGRvY3VtZW50cyBjYW4gYmUgY29udmVydGVkIHRvIEhUTUwgb3IgTGFUZVggKHVzZWQgZm9yIFBERikgdGhyb3VnaCBQYW5kb2MgKHdoaWNoIGNvbWVzIGJ1bmRsZWQgd2l0aCBSU3R1ZGlvKS4KCiMjIyBIZWFkaW5ncwoKSGVhZGVycyAtIHRoZXNlIHVzZSB0aGUgXCMgZm9yIHRoZSBsYXJnZXN0IGhlYWRpbmcgKGhlYWRlciAxKSB0aHJvdWdoIHRvIFwjIyMjIyMgdGhlIHNtYWxsZXN0IGhlYWRpbmcgKGxldmVsIDYpIGFuZCBjb3JyZXNwb25kIHRvIHRoZSBoMSB0byBoNiBoZWFkaW5nIHRhZ3MgaW4gSFRNTC4KCmBgYAojIExldmVsIDEgaGVhZGluZwoKIyMgbGV2ZWwgMiBoZWFkaW5nCgojIyMgbGV2ZWwgMyBoZWFkaW5nCgojIyMjIGxldmVsIDQgaGVhZGluZwoKIyMjIyMgbGV2ZWwgNSBoZWFkaW5nCgojIyMjIyMgbGV2ZWwgNiBoZWFkaW5nCmBgYAoKXAoKV2UnbGwgY292ZXIgc29tZSBtb3JlIG9mIHRoZSBjb21tb24gdGV4dCBmb3JtYXR0aW5nIG5vdywgd2hlcmUgeW91J2xsIHNlZSB0aGUgcmVuZGVyZWQgcGFyYWdyYXBoIGZvbGxvd2VkIGJ5IHRoZSBtYXJrZG93biBzeW50YXggdGhhdCB3YXMgdXNlZCB0byBnZW5lcmF0ZSBpdDoKCiMjIyBCb2xkL0l0YWxpY3MKCgoqSXRhbGljcyogaXMgZW5jb2RlZCBieSBzdXJyb3VuZGluZyB3b3JkKHMpIHdpdGggd2l0aCBhIHNpbmdsZSBhc3RlcmlzayAoXCopIG9yIHVuZGVyc2NvcmUgKFxfKSwgKipib2xkKiogdXNlcyBkb3VibGUgYXN0ZXJpc2tzIFwqXCogb3IgdW5kZXJzY29yZXMgXF9cXy4gVG8gXnN1cGVyXnNjcmlwdCBzb21ldGhpbmcsIHN1cnJvdW5kIGl0IHdpdGggY2FyZXRzIChcXiksIGFuZCB0byB+c3VifnNjcmlwdCBzdXJyb3VuZCBpdCB3aXRoIHRpbGRlIChcfikuIFN1cnJvdW5kaW5nIHdpdGggZG91YmxlIHRpbGRlcyB3aWxsIH5+c3RyaWtldGhyb3VnaH5+LgoKYGBgCipJdGFsaWNzKiBpcyBlbmNvZGVkIGJ5IHN1cnJvdW5kaW5nIHdvcmQocykgd2l0aCB3aXRoIGEgc2luZ2xlIGFzdGVyaXNrIChcKikgb3IgdW5kZXJzY29yZSAoXyksICoqYm9sZCoqIHVzZXMgZG91YmxlIGFzdGVyaXNrcyAqKiBvciB1bmRlcnNjb3JlcyBfXy4gVG8gXnN1cGVyXnNjcmlwdCBzb21ldGhpbmcsIHN1cnJvdW5kIGl0IHdpdGggY2FyZXRzICheKSwgYW5kIHRvIH5zdWJ+c2NyaXB0IHN1cnJvdW5kIGl0IHdpdGggdGlsZGUgKH4pLiBTdXJyb3VuZGluZyB3aXRoIGRvdWJsZSB0aWxkZXMgd2lsbCB+fnN0cmlrZXRocm91Z2h+fi4KYGBgCgpcCgojIyMgTGlzdHMKClVub3JkZXJlZCBsaXN0cyBjYW4gYmUgbWFkZSBieSBzdGFydGluZyBhIGxpbmUgd2l0aCBlaXRoZXIgYSBkYXNoICgtKSBvciBhbiBhc3RlcmlzayAoXCopIGFuZCBpZiB5b3Ugd2FudCB0byBuZXN0IGl0ZW1zIHVzZSBhIHRhYiBvciB0d28gc3BhY2VzIHRvIGluZGVudCBwZXIgbGF5ZXIuCgotIGl0ZW0gMQotIGl0ZW0gMgotIGl0ZW0gMwogICAgLSBzdWJpdGVtIDEKICAgIC0gc3ViaXRlbSAyCiAgICAgICAgLSBzdWIgc3ViIGl0ZW0gMQotIGl0ZW0gNAoKCmBgYAotIGl0ZW0gMQotIGl0ZW0gMgotIGl0ZW0gMwogIC0gc3ViaXRlbSAxCiAgLSBzdWJpdGVtIDIKICAgIC0gc3ViIHN1YiBpdGVtIDEKLSBpdGVtIDQKYGBgCk9yZGVyZWQgbGlzdHMgc3RhcnQgdGhlIGxpbmUgd2l0aCBhIG51bWJlciBmb2xsb3dlZCBieSBhIGZ1bGxzdG9wLiBJdCBpcyBwb3NzaWJsZSB0byBuZXN0IHVub3JkZXJlZCBhbmQgb3JkZXJlZCBsaXN0cyB3aXRoaW4gdGhlIHNhbWUgbGlzdAoKMS4gIGl0ZW0gMQoyLiAgaXRlbSAyCjMuICBpdGVtIDMKCgpgYGAKMS4gaXRlbSAxCjIuIGl0ZW0gMgozLiBpdGVtIDMKYGBgCgpcCgojIyMgQmxvY2sgcXVvdGVzCgo+IGJsb2NrIHF1b3RlcyBhcmUgYSB3YXkgb2YgaW5jbHVkaW5nIGJsb2NrcyBvZiB0ZXh0IGZyb20gc29tZW9uZSBlbHNlLiBUbyB1c2UgdGhlc2UgdGhhdCB0aGUgbGluZSB3aXRoIGEgXD4gYW5nbGUgYnJhY2tldAoKYGBgCj4gYmxvY2sgcXVvdGVzIGFyZSBhIHdheSBvZiBpbmNsdWRpbmcgYmxvY2tzIG9mIHRleHQgZnJvbSBzb21lb25lIGVsc2UuIFRvIHVzZSB0aGVzZSBiZWdpbiB0aGUgbGluZSB3aXRoIGEgPiBhbmdsZSBicmFja2V0CmBgYAoKXAoKIyMjIExpbmtzCgpMaW5rcyBjYW4gYmUgZG9uZSBhcyBlaXRoZXIgdGhlIGZ1bGwgdXJsIGUuZy4gPGh0dHBzOi8vd3d3Lmdvb2dsZS5jb20+LCBvciB5b3UgY2FuIFtsaW5rIHdvcmRzXShodHRwczovL3d3dy5nb29nbGUuY29tKSBieSBzdXJyb3VuZGluZyB0aGVtIHdpdGggW10gZm9sbG93ZWQgaW1tZWRpYXRlbHkgYnkgdGhlIHVybCBpbiBwYXJlbnRoZXNlcy4KCmBgYApMaW5rcyBjYW4gYmUgZG9uZSBhcyBlaXRoZXIgdGhlIGZ1bGwgdXJsIGUuZy4gaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbSwgb3IgeW91IGNhbiBbbGluayB3b3Jkc10oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbSkgYnkgc3Vycm91bmRpbmcgdGhlbSB3aXRoIFtdIGZvbGxvd2VkIGltbWVkaWF0ZWx5IGJ5IHRoZSB1cmwgaW4gcGFyZW50aGVzZXMuCmBgYApcCgojIyMgVmVyYmF0aW0gY29kZQoKYGBgYApJZiB5b3Ugd2FudCB0byBpbmNsdWRlIGNvZGUgaW4geW91ciBkb2N1bWVudCwgdGhlIHVzZSBvZiB2ZXJiYXRpbSBibG9ja3Mgd2lsbCBzdG9wIHRoZSBzeW1ib2xzIGJlaW5nIGludGVycHJldGVkIGZvciBtYXJrZG93biBhbmQgd2lsbCBiZSByZXByb2R1Y2VkIGFzaXMgaW4gdGhlIGRvY3VtZW50LgpUaGVzZSBibG9ja3MgYXJlIHN0YXJ0ZWQgYW5kIGVuZGVkIHdpdGggdGhyZWUgYmFja3RpY2tzIGBgYApgYGBgCgpgYGBgCgpgYGAKSWYgeW91IHdhbnQgdG8gaW5jbHVkZSBjb2RlIGluIHlvdXIgZG9jdW1lbnQgYXMgaGFzIGJlZW4gZG9uZSB0byBkZW1vbnN0cmF0ZSB0aGUgbWFya2Rvd24gY29kZSB0aGF0IGdlbmVyYXRlZCBlYWNoIG9mIHRoZSBleGFtcGxlIHBhcmFncmFwaHMsIHRoZSB1c2Ugb2YgdmVyYmF0aW0gYmxvY2tzIHdpbGwgc3RvcCB0aGUgc3ltYm9scyBiZWluZyBpbnRlcnByZXRlZCBmb3IgbWFya2Rvd24gYW5kIHdpbGwgYmUgcmVwcm9kdWNlZCBhcyBpcyBpbiB0aGUgZG9jdW1lbnQuClRoZXNlcyBibG9ja3MgYXJlIHN0YXJ0ZWQgYW5kIGVuZGVkIHdpdGggdGhyZWUgYmFja3RpY2tzIGBgYApgYGAKYGBgYAoKWW91IGNhbiBhbHNvIGRvIGBpbmxpbmUgdmVyYmF0aW1gIGJ5IHN1cnJvdW5kaW5nIHRoZSB0ZXh0IHdpdGggYSBzaW5nbGUgYmFja3RpY2sKCmBgYApZb3UgY2FuIGFsc28gZG8gYGlubGluZSB2ZXJiYXRpbWAgYnkgc3Vycm91bmRpbmcgdGhlIHRleHQgd2l0aCBhIHNpbmdsZSBiYWNrdGljawpgYGAKCiMjIENvZGUgQ2h1bmtzCgpNYXJrZG93biBwcm92aWRlcyB2ZXJiYXRpbSBjb2RlIGNodW5rcywgaG93ZXZlciB3aGVyZSBSTWFya2Rvd24gcmVhbGx5IGNvbWVzIGludG8gaXRzIG93biBpcyB0aGUgYWJpbGl0eSB0byBoYXZlIHRoZSBjb2RlIHRoYXQgaXMgaW5jbHVkZWQgZXZhbHVhdGVkIGFuZCB0aGUgcmVzdWx0cyBhbHNvIGVtYmVkZGVkIGRpcmVjdGx5IGJlbG93IHRoZSBjb2RlIHRoYXQgd2FzIGNyZWF0ZWQgdGhlbS4gV2hpbGUgaXQncyBjYWxsZWQgUk1hcmtkb3duIHlvdSdyZSBhbHNvIG5vdCBqdXN0IGxpbWl0ZWQgdG8gUiBidXQgb3RoZXIgbGFuZ3VhZ2VzIGNhbiBiZSBpbmNsdWRlZCBhbmQgcnVuIChzbyBsb25nIGFzIHRoZSB1bmRlcmx5aW5nIGVuZ2luZXMgYXJlIHNldCB1cCkKCkEgY29kZSBjaHVuayB0YWtlcyB0aGlzIGZvcm1hdCwgc2ltaWxhciB0byB0byB0aGUgdmVyYmF0aW0gY29kZSBjaHVuayBidXQgZm9sbG93aW5nIHRoZSBmaXJzdCB0aHJlZSBiYWNrdGlja3MgYXJlIGN1cmx5IGJyYWNlcywgYW5kIGluc2lkZSB0aGUgbmFtZSBvZiB0aGUgbGFuZ3VhZ2UgaW4gbG93ZXIgY2FzZSAtIGluIHRoaXMgY2FzZSAiciIKCmBgYHtyIGVjaG8gPSBGQUxTRSwgY29tbWVudCA9ICIifQpjYXQoaHRtbHRvb2xzOjppbmNsdWRlVGV4dCgic2NyaXB0cy9jb2RlX2NodW5rLlJtZCIpKQpgYGAKCldvdWxkIHByb2R1Y2UKCmBgYHtyfQoxICsgMgpgYGAKClwKCiMjIyBXb3JraW5nIGRpcmVjdG9yeQoKVGhlIHdvcmtpbmcgZGlyZWN0b3J5IG9yIGxvY2F0aW9uIHRoYXQgUiBpcyBnb2luZyB0byBzdGFydCBsb29raW5nIGZvciBzcGVjaWZpZWQgZmlsZXMgKGUuZy4gYSBjc3YgdG8gcmVhZCBpbikgZm9yIGFuIFJNYXJrZG93biB3aWxsIGRlZmF1bHQgdG8gdGhlIGxvY2F0aW9uIHRoZSBSTWFya2Rvd24gZmlsZSBpcyBzYXZlZC4gVGhpcyBjYW4gYmUgYSBjb21tb24gc291cmNlIG9mIGVycm9ycyBpbiBjb21waWxpbmcgYW4gUk1hcmtkb3duIGRvY3VtZW50IGlmIHlvdXIgUk1hcmtkb3duIGlzIHNhdmVkIGluIGEgc3ViZGlyZWN0b3J5IGFuZCB5b3UgZG9uJ3QgaGF2ZSB5b3VyIGZpbGUgcGF0aHMgY29ycmVjdC4KCj4gRG9uJ3QgdXNlIGBzZXR3ZCgpYCBpbiBhbiBSTWFya2Rvd24uIEl0IHdpbGwgY2F1c2UgaXNzdWVzLgoKSWYgeW91IGFyZSB1c2luZyBhbiBSU3R1ZGlvIHByb2plY3QgYW5kIHN0cnVjdHVyZSBhcyBpbnRyb2R1Y2VkIGluIFtJbnRyb2R1Y2luZyBSIGFuZCBSc3R1ZGlvXSgwMS1pbnRyby5odG1sKSB5b3UgY2FuIG1ha2UgdXNlIG9mIHRoZSBbYGhlcmVgXShodHRwczovL2hlcmUuci1saWIub3JnL2FydGljbGVzL2hlcmUuaHRtbCkgcGFja2FnZSB3aGljaCBwcm92aWRlcyBhIG5pY2Ugd2F5IG9mIGRlYWxpbmcgd2l0aCByZWxhdGl2ZSBmaWxlIHBhdGhzIGFzIGlmIHlvdSB3ZXJlIG5hdmlnYXRpbmcgZnJvbSB0aGUgdG9wIG9mIHlvdXIgcHJvamVjdCBkaXJlY3RvcnkuCgpGb3IgaW5zdGFuY2UgZ2l2ZW4gdGhlIGZvbGxvd2luZyBwcm9qZWN0IHNldHVwOgoKYGBgCm15X3Byb2plY3QvCiAgfC0gZGF0YS8KICAgICAgXC0gbXlfY3N2LmNzdgogIHwtIGRvY3MvCiAgfC0gb3V0cHV0cy8KICB8LSBzY3JpcHRzLwogICAgICBcLSBteV9ybWQuUm1kCiAgXCAtIG15X3Byb2plY3QuUnByb2oKICAKYGBgCgpJZiB3ZSB3ZXJlIHdvcmtpbmcgb24gdGhlIGZpbGUgYG15X3JtZC5SbWRgIHdpdGhvdXQgdGhlIHVzZSBvZiBgaGVyZWAgd2Ugd291bGQgbmVlZCB0byB1c2UgcmVsYXRpdmUgcGF0aHMgZnJvbSBgc2NyaXB0cy9gICh3ZSB3YW50IHRvIHVzZSByZWxhdGl2ZSBwYXRocyB3aXRoaW4gb3VyIHByb2plY3QgYmVjYXVzZSB0aGV5IGFyZW4ndCBkZXBlbmRhbnQgb24gYW55IHBhcnRpY3VsYXIgY29tcHV0ZXIgbWFraW5nIG91ciBwcm9qZWN0IHRyYW5zZmVyYWJsZSkgYW5kIHRoZSBjb21tYW5kIHRvIHJlYWQgZGF0YSBpbiB3b3VsZCBsb29rIGxpa2UgdGhpczoKCmBgYHtyICwgZXZhbCA9IEZBTFNFfQpteV9kYXRhIDwtIHJlYWRfY3N2KCIuLi9kYXRhL215X2Nzdi5jc3YiKQpgYGAKClVzaW5nIGBoZXJlYCBldmVyeXRoaW5nIGlzIHJlbGF0aXZlIGZyb20gdGhlIGAuUnByb2pgIGZpbGUgd2hpY2ggY2FuIGJlIGVhc2llciB0byB0aGluayBvZiBzaW5jZSBpdCBmb2xsb3dzIGEgcmVsYXRpdmUgcGF0aCB0aGUgc2FtZSBzdHJ1Y3R1cmUgYXMgdGhlIHByb2plY3QsIG5vdCByZWxhdGl2ZSB0byB3aGVyZSB0aGUgZmlsZSB5b3UncmUgY3VycmVudGx5IHdvcmtpbmcgb24gbGl2ZXMgLSBgaGVyZWAgd29ya3MgYWxsIHRoYXQgb3V0IGZvciB5b3U6CgpgYGB7ciwgZXZhbD1GQUxTRX0KbGlicmFyeShoZXJlKQpteV9kYXRhIDwtIHJlYWRfY3N2KGhlcmUoImRhdGEvbXlfY3N2LmNzdiIpKQpgYGAKClwKCiMjIyBDb2RlIENodW5rIE9wdGlvbnMKClRoZSBiZWhhdmlvdXIgb2YgdGhlIGNvZGUgY2h1bmtzIGNhbiBiZSBtb2RpZmllZCB3aXRoIG9wdGlvbnMuIFRoZXNlIG9wdGlvbnMgYXJlIHByb3ZpZGVkIGluc2lkZSB0aGUge30ncyBvZiB0aGUgY29kZSBjaHVuayBhbmQgYXJlIGNvbW1hIHNlcGFyYXRlZC4KClRoZSBkZWZhdWx0cyBmb3IgYSBjaHVuayBhcmU6CgpgYGB7ciBlY2hvID0gRkFMU0UsIGNvbW1lbnQgPSAiIn0KY2F0KGh0bWx0b29sczo6aW5jbHVkZVRleHQoInNjcmlwdHMvY29kZV9jaHVua19kZWZhdWx0cy5SbWQiKSkKYGBgCgotICAgYGVjaG89VFJVRWAgd2lsbCAiZWNobyIgdGhlIGNvZGUgdGhhdCBpcyBydW4gYWJvdmUgdGhlIHJlc3VsdHMKLSAgIGBldmFsPVRSVUVgIG1lYW5zIHRoZSBjb2RlIGluc2lkZSB0aGUgY2h1bmsgd2lsbCBiZSBldmFsdWF0ZWQgKHJ1bikKLSAgIGBpbmNsdWRlPVRSVUVgIG1lYW5zIHRoZSBjb2RlIGFuZCB0aGUgcmVzdWx0cyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBkb2N1bWVudAotICAgYHdhcm5pbmc9VFJVRWAgd2lsbCBpbmNsdWRlIGFueSB3YXJuaW5ncyBhcyBvdXRwdXQgaW4gdGhlIGRvY3VtZW50Ci0gICBgbWVzc2FnZT1UUlVFYCB3aWxsIGluY2x1ZGUgbWVzc2FnZXMgYXMgb3V0cHV0IGluIHRoZSBkb2N1bWVudAoKVGhlc2UgY2FuIGluZGl2aWR1YWxseSBiZSBzcGVjaWZpZWQgYW5kIHNldCB0byBgRkFMU0VgIHRvIGRpc2FibGUgdGhlIHNwZWNpZmljIGJlaGF2aW91ci4KCiMjIEltYWdlcywgRmlndXJlcyBhbmQgVGFibGVzCgojIyMgSW1hZ2VzCgpJbnNlcnRpbmcgaW1hZ2VzIGludG8gUk1hcmtkb3duIGRvY3VtZW50cyBjYW4gYmUgZG9uZSBpbiB0d28gbWFpbiB3YXlzCgoxLiAgVGhyb3VnaCBtYXJrZG93biB3aXRoIGAhW2FsdCB0ZXh0XShwYXRoL3RvL2ltYWdlKWAKMi4gIFVzaW5nIGEgY29kZSBjaHVuayBhbmQgdGhlIGBpbmNsdWRlX2dyYXBoaWNzKClgIGZ1bmN0aW9uIGZyb20gYGtuaXRyYAoKVGhlIHNlY29uZCBtZXRob2QgZ2l2ZSB5b3UgbW9yZSBjb250cm9sIG92ZXIgdGhlIGRpc3BsYXkgb2YgdGhlIGltYWdlIGluIHRoZSBvdXRwdXQgYmVjYXVzZSB5b3UgY2FuIHVzZSB0aGUgY29kZSBjaHVuayBvcHRpb25zIHRvIHN1Y2ggYXMKCi0gICBgZmlnLmFsaWduYCB0byBjb250cm9sIHRoZSBhbGlnbm1lbnQgb24gdGhlIHBhZ2Ugb2YgdGhlIGltYWdlCi0gICBgZmlnLmNhcGAgdG8gcHJvdmlkZSBhIGZpZ3VyZSBjYXB0aW9uCi0gICBgb3V0LndpZHRoYCBjb250cm9scyB0aGUgb3V0cHV0IHdpZHRoCi0gICBgb3V0LmhlaWdodGAgY29udHJvbHMgdGhlIG91dHB1dCBoZWlnaHQKCiMjIyBGaWd1cmVzCgpJbWFnZXMgZ2VuZXJhdGVkIHRocm91Z2ggY29kZSBzdWNoIGFzIHBsb3RzIHdpbGwgYXV0b21hdGljYWxseSBiZSBpbmNsdWRlZCBhcyB0aGUgb3V0cHV0IHVuZGVybmVhdGggdGhlIGNvZGUgdGhhdCBjcmVhdGVkIHRoZW0uCgpUaGUgZmlndXJlIHBsYWNlbWVudCBhbmQgc2l6ZSBjYW4gYmUgY29udHJvbGxlZCB0aHJvdWdoIHRoZSBjb2RlIGNodW5rIG9wdGlvbnMKCi0gICBgZmlnLmFsaWduYCB0byBjb250cm9sIHRoZSBhbGlnbm1lbnQgb24gdGhlIHBhZ2Ugb2YgdGhlIGltYWdlCi0gICBgZmlnLmNhcGAgdG8gcHJvdmlkZSBhIGZpZ3VyZSBjYXB0aW9uCi0gICBgZmlnLndpZHRoYCBjb250cm9scyB0aGUgb3V0cHV0IHdpZHRoCi0gICBgZmlnLmhlaWdodGAgY29udHJvbHMgdGhlIG91dHB1dCBoZWlnaHQKLSAgIGBmaWcuYXNwYCBjYW4gYmUgdXNlZCB0byBzY2FsZSBhIGZpZ3VyZQoKIyMjIFRhYmxlcwoKVGFibGVzIGNhbiBiZSBjcmVhdGVkIG1hbnVhbGx5IHRocm91Z2ggbWFya2Rvd24gdXNpbmcgdGhlIGZvbGxvd2luZyBzeW50YXgKCiAgICBjb2wgMSB8IGNvbCAyIHwgY29sIDMKICAgIC0tLXwtLS18LS0tCiAgICByb3cgMSB8IGEgfCAxCiAgICByb3cgMiB8IGIgfCAyCgp3aGljaCBjcmVhdGVzIHRoZSBmb2xsb3dpbmcgdGFibGU6Cgp8IGNvbCAxIHwgY29sIDIgfCBjb2wgMyB8CnwtLS0tLS0tfC0tLS0tLS18LS0tLS0tLXwKfCByb3cgMSB8IGEgICAgIHwgMSAgICAgfAp8IHJvdyAyIHwgYiAgICAgfCAyICAgICB8CgpCdXQgdGhlc2UgdGFibGUgY2FuIGJlIHF1aXRlIGxhYm9yaW91cyB0byBjcmVhdGUgYW5kIGN1c3RvbWlzZS4gVGhleSBhbHNvIHdpbGwgbmVlZCB0byBiZSBtYW51YWxseSB1cGRhdGVkIGlmIHlvdXIgZGF0YSBjaGFuZ2VzLiBBIGJldHRlciBvcHRpb24gaXMgdG8gY3JlYXRlIHRhYmxlcyBkaXJlY3RseSBmcm9tIHlvdXIgZGF0YSB1c2luZyB0aGUgYGthYmxlKClgIGZ1bmN0aW9uIGZyb20gYGtuaXRyYCB3aGljaCB3aWxsIHRha2UgYSBkYXRhZnJhbWUgYW5kIGF1dG9tYXRpY2FsbHkgY3JlYXRlIHRoZSBtYXJrZG93biBmb3IgaXQuCgpgYGB7cn0KbGlicmFyeShwYWxtZXJwZW5ndWlucykKbGlicmFyeShrbml0cikKCnBlbmd1aW5zX3NtYWxsIDwtIGhlYWQocGVuZ3VpbnMsIG4gPSAxMCkKCmthYmxlKHBlbmd1aW5zX3NtYWxsKQpgYGAKClRoZXNlIGthYmxlIHRhYmxlcyBjYW4gYmUgZnVydGhlciBjdXN0b21pc2VkIGZyb20gdGhlIGZ1bmN0aW9uIHBhcmFtZXRlcnMgc3VjaCBhcyBgY29sLm5hbWVzYCB0byBwcm92aWRlIGEgdmVjdG9yIG9mIGNvbHVtbiBuYW1lcyBmb3IgdGhlIHRhYmxlLCBgZGlnaXRzYCB0byByb3VuZCBudW1iZXJzLCBhbmQgYGFsaWduYCB0byBjb250cm9sIHRoZSBhbGlnbm1lbnQgb2YgdGhlIGNvbHVtbnMuCgpUaGUgYWRkaXRpb25hbCBjdXN0b21pc2F0aW9uIGNhbiBiZSBhY2hpZXZlZCB0aHJvdWdoIHRoZSB1c2Ugb2YgdGhlIFtga2FibGVFeHRyYWAgcGFja2FnZV0oaHR0cHM6Ly9naXRodWIuY29tL2hhb3podTIzMy9rYWJsZUV4dHJhKSB3aGljaCBwcm92aWRlcyBudW1lcm91cyBleHRyYSBmdW5jdGlvbiBmb3IgdGhlIHRoZSBjdXN0b21pc2F0aW9uIG9mIHRhYmxlcyBpbiBib3RoIFtIVE1MXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMva2FibGVFeHRyYS92aWduZXR0ZXMvYXdlc29tZV90YWJsZV9pbl9odG1sLmh0bWwpIGFuZCBbTGFUZVhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9rYWJsZUV4dHJhL3ZpZ25ldHRlcy9hd2Vzb21lX3RhYmxlX2luX3BkZi5wZGYpIHdoaWNoIGRpZmZlciBzbGlnaHRseSBpbiB3aGF0IGlzIHBvc3NpYmxlIGluIGVhY2ggZm9ybWF0LiBCdXQgdGhleSBib3RoIGluY2x1ZGUgZmVhdHVyZXMgc3VjaCBhcyByb3cvY29sdW1uL2NlbGwgY29sb3VyaW5nLCB0ZXh0IGZvcm1hdHRpbmcsIGdyb3VwaW5ncywgYW5kIGZvb3Rub3Rlcy4KClwKCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiBzb21lIGV4dHJhIGN1c3RvbWlzYXRpb25zIHRoYXQgY291bGQgYmUgZG9uZSB0byB0aGUgb3JpZ2luYWwgdGFibGUgdGhhdCB3YXMgZGVtb25zdHJhdGVkIGFib3ZlIHdpdGggYGthYmxlYC4gSWYgeW91ciBjdXN0b21pc2F0aW9ucyBvbiB5b3VyIHRhYmxlIHJlbHkgb24gdGhlIGRhdGEgc3RheWluZyB0aGUgc2FtZSB0aGV5IG1pZ2h0IG5lZWQgdG8gYmUgcmVkb25lIGlmIHlvdSB1cGRhdGUgdGhlIGRhdGEgaW4gdGhlIHRhYmxlLiAKCmBgYHtyfQpsaWJyYXJ5KHBhbG1lcnBlbmd1aW5zKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgpwZW5ndWluc19zbWFsbCA8LSBoZWFkKHBlbmd1aW5zLCBuID0gMTApCgojIGtibCBjb21lcyBmcm9tIGthYmxlRXh0cmEgYW5kIGlzIGEgdmVyc2lvbiBvZiBrYWJsZSgpCmthYmxlRXh0cmE6OmtibChwZW5ndWluc19zbWFsbCwgCiAgICBjb2wubmFtZXMgPSBjKCJTcGVjaWVzIiwgCiAgICAgICAgICAgICAgICAgICJJc2xhbmQiLCAKICAgICAgICAgICAgICAgICAgIkJpbGwgTGVuZ3RoIiwgCiAgICAgICAgICAgICAgICAgICJCaWxsIERlcHRoIiwgCiAgICAgICAgICAgICAgICAgICJGbGlwcGVyIExlbmd0aCIsIAogICAgICAgICAgICAgICAgICAiQm9keSBNYXNzIChnKSIsIAogICAgICAgICAgICAgICAgICAiU2V4IiwgCiAgICAgICAgICAgICAgICAgICJZZWFyIiksIAogICAgYWxpZ24gPSAibGxycnJyY3IiLAogICAgY2FwdGlvbiA9ICJBIHRhYmxlIHNob3dpbmcgdGhlIG1lYXN1cmVtZW50cyBvZiB0aGUgZmlyc3QgMTAgcGVuZ3VpbnMgZnJvbSB0aGUgUGFsbWVycyBQZW5ndWlucyBkYXRhc2V0LiIpICU+JSAKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAnY2VudGVyJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IDE2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSAnc3RyaXBlZCcpICU+JSAKICAjIGFkZCBpbiBhIGdyb3VwaW5nIGhlYWRlciBmb3IgdGhlIGNvbHVtbnMgdXNpbmcgbW0KICBrYWJsZUV4dHJhOjphZGRfaGVhZGVyX2Fib3ZlKGhlYWRlciA9IGMoIiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lYXN1cmVtZW50cyAobW0pIiA9IDMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIpKQogIApgYGAKClwKCgoKIyMgQ2l0YXRpb25zCgpDaXRhdGlvbnMgY2FuIGJlIGluc2VydGVkIGludG8gYW4gUk1hcmtkb3duIGRvY3VtZW50LiBbVGhpcyBkb2N1bWVudCBmcm9tIFJTdHVkaW9dKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vdmlzdWFsLW1hcmtkb3duLWVkaXRpbmcvY2l0YXRpb25zLmh0bWwpIGdvZXMgdGhyb3VnaCBob3cgdG8gZG8gaXQgdXNpbmcgZXRoZXIgTWFya2Rvd24gb3Igd2l0aCB0aGUgdmlzdWFsIGVkaXRvciB3aGljaCBjYW4gYmUgbGlua2VkIHdpdGggYSBjaXRhdGlvbiBtYW5hZ2VyIHN1Y2ggYXMgWm90ZXJvLCBvciBieSBzZWFyY2hpbmcgRE9JcyBhbmQgbW9yZS4KClwKCiMjIENvbmNsdXNpb24KClRoaXMgbW9kdWxlIGhhcyBvbmx5IHNjcmF0Y2hlZCB0aGUgc3VyZmFjZSBvZiB3aGF0IGlzIHBvc3NpYmxlIHdpdGggdGhlIGhpZ2hseSB2ZXJzYXRpbGUgZm9ybWF0IHRoYXQgaXMgUk1hcmtkb3duLiBUaGUgbWFpbiBiZW5lZml0IHRoYXQgUk1hcmtkb3duIGlzIHRoYXQgaXQgcHJvdmlkZXMgYSBtZWNoYW5pc20gdG8gY3JlYXRlIHJlcHJvZHVjaWJsZSBhbmFseXNpcyBkb2N1bWVudHMgdGhhdCBpbmNsdWRlIHByb3NlLCBjb2RlLCBhbmQgZ2VuZXJhdGVkIG91dHB1dHMuCgpNYWtlIHN1cmUgdG8gY2hlY2sgb3V0IFtSTWFya2Rvd24gLSB0aGUgZGVmaW5pdGl2ZSBndWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykgZm9yIGEgY29tcHJlaGVuc2l2ZSBpbnRyb2R1Y3Rpb24gYW5kIGd1aWRlIHRvIHRoZSBwb3NzaWJpbGl0aWVzIG9mIFJNYXJrZG93bi4gVGhlcmUgYXJlIGFsc28gcGFja2FnZXMgZm9yIGNyZWF0aW5nIG11bHRpLWRvY3VtZW50IFJNYXJrZG93biBvdXRwdXRzIHN1Y2ggYXMgZW50aXJlIHdlYnNpdGVzIChgcGFja2FnZWRvd25gLCBgZGlzdGlsbGApLCBibG9ncyAoYGJsb2dkb3duYCksIGFuZCBib29rcyAoYGJvb2tkb3duYCkuCg==