Preface
This tutorial presumes that you have R and R Studio installed, or that you have an account on rstudio.cloud. If you do not already have R and/or R Studio you will need to download and install them. You must first install R from R Project and then the R Studio IDE from R Studio.
R Notebooks vs R Scripts
There are several distinct ways to write R code and to program in R: R Notebooks, Quatro Documents, and R Scripts. An R Markdown Notebook (.Rmd file) and an R Script (.R file) are both tools used in the R programming environment, but they serve different purposes and have distinct features:
R Markdown Notebook
- Integrated Documentation and Code:
- R Markdown allows you to combine narrative text, code, and output in a single document. It supports Markdown syntax for text formatting, making it easy to create well-documented reports, presentations, and interactive notebooks. The code blocks can be a mix of R, Python, SQL, among many other programming languages. R Notebooks are similar to Jupyter Notebooks often used in Python.
- Dynamic Report Generation:
- You can execute code chunks within the document and immediately see the results, including plots, tables, and other outputs. This makes R Markdown ideal for creating dynamic and reproducible research documents.
- Interactive Features:
- Notebooks in R Markdown can include interactive features, such as HTML widgets and Shiny apps, which can be embedded directly into the document.
- Output Formats:
- R Markdown documents can be rendered into various formats, including HTML, PDF, Word, and slideshows. This flexibility allows for easy sharing and presentation of the results.
- Ease of Collaboration:
- The combination of code and its output with narrative text makes it easier to share complete analyses with collaborators, who can see both the methods and the results in context.
R Script (.R file)
- Code Only:
- An R Script is a plain text file containing only R code. It does not support Markdown or other types of text formatting.
- Execution:
- R Scripts are typically run line-by-line or as a whole in an R console or RStudio environment. They are straightforward for writing and executing R code but do not provide integrated documentation or immediate visual feedback within the script itself.
- Simplicity:
- The simplicity of R Scripts makes them ideal for writing and testing R code quickly. They are less cumbersome than R Markdown files when you only need to write and execute code without the need for extensive documentation or presentation of results.
- Use Cases:
- R Scripts are commonly used for scripting tasks, data manipulation, analysis pipelines, and batch processing where the primary focus is on code execution rather than presentation.
R Markdown Notebook (.Rmd file) are best for creating comprehensive, reproducible documents that integrate code, results, and narrative text. They can contain a mix of code chunks (blocks) in R, Python, SQL, C++, Java, D3, and many other languages. Ideal for reports, interactive documents, and presentations. On the other hand, R Script (.R file) are preferable for straightforward coding tasks, scripting, and batch processing where the focus is solely on the code without the need for integrated documentation or presentation. They are “programs” similar to Python programs. Both types of “programs” are essential in the R ecosystem, and their use depends on the specific needs of your project. This tutorial will focus on R Markdown Notebooks.
R Notebooks
R Notebooks are documents that combine code and text, allowing for reproducible research and data analysis. They are created in Posit (formerly R Studio), an integrated development environment (IDE) for the R and Python programming languages.
R Notebooks use a text-based document writing system called R Markdown for literate programming, which allows you to embed executable R (as well as Python, C++, SQL, and bash) code within Markdown text. This means you can write narrative text, add headings, insert figures, embed images, link to URLs, and include mathematical LaTeX-formatted equations in your document, while also executing R code chunks and displaying the results inline.
The R Markdown syntax is based on the Markdown syntax, which is a lightweight markup language used for formatting text documents. R Notebooks allow you to write documents that are both human-readable and executable. They make it easy to share your code, data, and analysis with others, while also providing a clear and organized record of your analysis process.
Workflow
All of your work must be done within an R Project, so create a project first, or, if you already have one, open the project before doing any work.
New R Notebook
To build a new R Notebook, you should follow these steps:
- Open RStudio
- Click on “File” in the top left-hand corner, and then click on “New File” and select “R Notebook”.
- This will create a new R Notebook with some pre-populated text and code. You can modify this as needed.
- You can add new code chunks by clicking on the “+” icon in the top left-hand corner of the notebook or by using the keyboard shortcut “Ctrl + Alt + I”.
- Write your R code within the code chunks.
- Write narrative text using Markdown syntax in between the code chunks.
- Test each code chunk by clicking the “Run” button within the chunk or using the keyboard shortcut “Ctrl + Enter”.
- To save your R Notebook, click on “File” and then click on “Save As…”. You can then save your notebook in your desired location.
- Knit the R Notebook to the desired document format (HTML or PDF).
With an R Notebook, you can mix R code with narrative text, which makes it easy to document your analysis and share it with others. Additionally, you can include visualizations and other outputs directly in the notebook, which makes it easy to present your results.
Knitting
Once your R Notebook is written, it must be knitted. Knitting generates a markdown document which is then converted to a document, commonly PDF or HTML. This process is often called knitting or rendering; it is a form of compilation. During the knitting process, code chunks are executed and any output is embedded in the result document, unless chunks are marked to not be evaluated or not being included.
While writing the R Notebook, code chunks can be executed individually which can be helpful for development. During knitting, the chunks are run in sequence starting with the first code chunk.
Tutorial
Before proceeding with the remainder of this lesson and the specific R Notebook writing elements, watch this short narrated tutorial that demonstrates how to build R Notebooks and knit them to HTML and PDF documents.
Knitting to PDF requires installation of TeX tools which may prove to be difficult on some operating systems, notably MacOS. A work-around is to upload your R Notebook and supporting files to posit.cloud and knit there and then download the resulting PDF to your local project folder. The tutorial below demonstrates this workflow.
R Studio Projects
Projects are a better way to manage code rather than creating individual R Notebooks, R Scripts, and other code files. Projects allows all files, including data files, to be managed as a single unit, shared, and version controlled using services such as git and GitHub. Consult Lesson 6.202 – Working with R Projects for more details on how to create R Projects.
Literate Programming
Literate Programming is a document-centric programming paradigm introduced by Donald Knuth around 1984. A literate computer program is a “document” written in a natural language such as English, interspersed with chunks of source code in various programming languages, from which compilable source code can be generated. This programming approach is commonly used in scientific computing, data programming, and data science with the goal of producing reproducible data pipelines and data analyses. Jupyter Notebooks and R Notebooks are two common implementations of this paradigm.
A literate program must be “compiled” into code suitable for execution and a representation that can be viewed. The latter is commonly an HTML or PDF document. The former is commonly R or Python code interspersed with C++, Java, and SQL code and embedded formatting directives in a markup language such HTML, Markdown, and LaTeX.
The knitr package implements the programming paradigm within R Notebooks, which are, in turn, a variant of R Markdown. R Markdown is a superset of Markdown.
From the perspective of information science, a document is an aggregation of information objects, some of which are created programmatically.
R Markdown in a Nutshell
The key markdown directives are illustrated below with their result right afterwards:
This is _markdown_. Markdown contains embedded formatting
such as _italics_, **boldfacing**, and ~~strikes~~.
Of course we can also do superscripts
like x^2^ or subscripts like x~i~.
Headers are marked with hash marks ###
#### LaTeX Equations
More complex formatting of math expressions can be done
with embedded [LaTeX](https://latex-tutorial.com/)
like this $x_i$ or on a separate line:
$\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)$
or centered like this:
$$
\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)
$$
Did you see how I created an embedded link to a URL?
Numbered lists are produced with:
1. item 1
2. item 2
a. sub item a
b. sub item b
3. item 3
Bulleted lists can be produced with:
- bullet item
- bullet item
Task lists can be produced with:
- [ ] task 1
- [ ] task 2
- [x] task 3 is done
> Lastly, you can use > to make blockquotes for calling out important
information.
Did you notice how the second line in the block quote was intented?
The markdown above is knitted to the following format:
This is markdown. Markdown contains embedded formatting such as italics, boldfacing, and strikes. Of course we can also do superscripts like x2 or subscripts like xi.
Headers are marked with hash marks ###
LaTeX Equations
More complex formatting of math expressions can be done with embedded LaTeX like this \(x_i\) or on a separate line:
\(\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)\)
or centered like this:
\[
\bar{x}=\frac{1}{n}\sum_{i=0}^{n}(x_i)
\]
Did you see how I created an embedded link to a URL?
Numbered lists are produced with:
- item 1
- item 2
- sub item a
- sub item b
- item 3
Bulleted lists can be produced with:
Task lists can be produced with:
Lastly, you can use > to make blockquotes for calling out important information.
Did you notice how the second line in the block quote was intented?
See the R Markdown Reference Guide for a complete list of markdown elements.
R Notebook Elements
Embedded Code
One of the most useful elements of an R Notebook is the ability to embed code fragments within text. Code within a code block (or code chunk or code fence) is generally in R but can also be in Python, Java, C++, bash, or SQL.
Embedding R Code
A code chunk is created with three backticks in a row followed by a set of braces with the programming language.
```{r echo=F}
```
Code can also be embedded inline within text like so: `r a+b`
The result of the code in then added in the output document.
Named Code Chunks
Code chunks should be named so they can be more easily found. Adding a name after the language creates a label for the code chunk:
```{r chunk-name-without-spaces}
# code goes here
```
Hiding Code Chunks in Output
Often, we want the code to run but we do not want the code to be part of the output document. To do that, add “echo=F” after the code chunk name, like so:
```{r chunk-name-no-spaces, echo=F}
# code goes here
```
Suppress Evaluation
The code in a code chunk can be included (or not) in the document even though the code is not run. That is affected with the “eval=F” parameter.
```{r chunk-name-no-spaces, eval=F}
# code goes here
```
Code Chunks with Line Numbers
To add line numbers to the code, add “attr.source=‘.numberLines’” to the parameters.
```{r codeNoLines, attr.source='.numberLines'}
if (TRUE) {
x <- 1:10
x + 1
}
```
The above will produce:
if (TRUE) {
x <- 1:10
x + 1
}
Navigating Code Chunks
In general, a code chunk starts with the language followed by an optional name for the chunk. The name (or chunk label) is useful for quick navigation and for referencing within the document. In R Studio, it can be used for quickly jumping to a section of code.
Jumping to A Chunk by Name
Embedding C++ Code
To embed C++ code, use either {Rcpp} or {r engine=‘Rcpp’} for the fence header.
```{Rcpp fibCode, eval=T}
#include <Rcpp.h>
// [[Rcpp::export]]
int Fibonacci(const int x) {
if (x == 0 || x == 1)
return(x);
return (Fibonacci(x - 1)) + Fibonacci(x - 2);
}
```
Because the function Fibonacci()
was defined with the Rcpp::export attribute it is accessible to R code chunks as a normal R function:
```{r eval=F, echo=T}
print(paste0("10! = ", Fibonacci(10L)))
fact20 <- Fibonacci(20L)
print(paste0("20! = ", fact20))
```
Note that caching should not be used with Rcpp code chunks (since the compiled C++ function will not survive past the lifetime of the current R session).
Headings
Heading levels are specified with hashmarks (#). One hashmark is a first-level header (the title for the document), a second-level header is a section headings, and so forth.
---
title: "Predicting Car Sales"
date: "August 23, 2022"
author: "<small>Martin Schedlbauer</small>"
## Introduction
## Analysis
### Data Cleaning
### Factor Analysis
## Conclusion
---
Embedding LaTeX
LaTeX equations can be embedded in three different ways:
- inline by enclosing the equation in a text blow like so $z = (x - ) / $
- in a separate block by enclosing within $ but the equation is on its own line
- in double $$ which puts the equation in its own block and is centered
The fragment below illustrates how to embed LaTeX.
In mathematical terms, two relations $R_1$ and $R_2$ are union compatible if and only if
$degree(R_1)=degree(R_2)$, and $\mathfrak{D}(R^{A_i}_{1}) = \mathfrak{D}(R^{A_i}_{2})$, where $A_i$ is the *ith* attribute and $\mathfrak{D}(R^{A_i}_{k})$ is the domain of the *ith* attribute of relation $R_k$.
For example, the two relations $A$ and $B$ below are union compatible:
$A(a_1(char),a_2(char),a_3(date))$
$B(b_1(char),b_2(char),b_3(date))$
Embedding Images
Images can be embedded in several ways, the most common being the markdown shown below:
![image caption](URL or filename){style-parameters}
You can optionally add style parameters such as {width=50%} which are only meaningful when knitting to HTML.
Here’s an example:
![CRISP-DM Process](images/crisp-dm.png){width=30%}
The above would render as:
CRISP-DM Process
Embedding HTML
If the target document format is HTML, then it is permitted to insert HTML code fragments directly into the markdown document. This is useful when embedding external objects in HTML documents as illustrated below:
<iframe src="https://player.vimeo.com/video/821398"
width="480" height="270" frameborder="0"
title="Journaling with Markdown"
data-external="1"></iframe>
To ensure that embedded videos are playable, you must add the attribute data-external=“1” to any <iframe>.
Code Style
To render text as “code” using a monospaced front, enclose the text in single backticks. The fragment below illustrates this:
The correlation coefficient can be calculating using the
`cor()` function in R.
The above markdown would render as:
The correlation coefficient can be calculating using the cor() function in R. |
Chunk Options
Chunk output can be customized with knitr options, arguments set in the {} of a chunk header. Above, we use five arguments:
include = FALSE
prevents code and results from appearing in the finished file. R Markdown still runs the code in the chunk, and the results can be used by other chunks.
echo = FALSE
prevents code, but not the results from appearing in the finished file. This is a useful way to embed figures.
message = FALSE
prevents messages that are generated by code from appearing in the finished file.
warning = FALSE
prevents warnings that are generated by code from appearing in the finished.
fig.cap = “…”
adds a caption to graphical results.
comment = “…”
???
attr.source = “.numberLines”
adds line numbers to a code chunk
See the R Markdown Reference Guide for a complete list of knitr chunk options.
Global Options
To set global options that apply to every chunk in your file, call knitr::opts_chunk$set
in a code chunk. Knitr will treat each option that you pass to knitr::opts_chunk$set as a global default that can be overwritten in individual chunk headers.
Markdown Tables
While tables can be generated through R code using various R functions such as kable()
, they can also be created in markdown. Naturally, tables that contain calculated data or data from files should be included using R code chunks.
In Markdown, a table is a structured presentation of data, organized into rows and columns. To create a table in Markdown, you can use the vertical line “|” to separate each column and three or more dashes “—” to create the header for each column. Additionally, you should include a vertical line at both ends of the row to separate it from other content.
The markdown below produces this table:
| Month | Budget |
| -------- | -------|
| January | $2500 |
| February | $3000 |
| March | $4200 |
January |
$2500 |
February |
$3000 |
March |
$4200 |
The cell width do not have to align.
Align text in the columns to the left, right, or center by adding a colon “:” to the left, right, or on both side of the dashes — within the header row. The example is rendered below:
| Course | Credits | Term |
| :---------------- | :------:| ----: |
| Intro to Python | 2 | Fall |
| SQL for Beginners | 3 | Fall |
| Statistics with R | 4 | Spring |
| OOD with C++ | 4 | Summer |
Intro to Python |
2 |
Fall |
SQL for Beginners |
3 |
Fall |
Statistics with R |
4 |
Spring |
OOD with C++ |
4 |
Summer |
- :– means the column is left aligned
- –: means the column is right aligned
- :-: means the column is center aligned
Text can be formatted within tables using general markdown. However, some formatting options are not available within tables, including:
- Embedded R
- Headings
- Blockquotes
- Horizontal Lines
- Images
- Lists
- Embedded HTML
Summary
R Markdown is a tool that allows you to combine text and code to create documents that are both human-readable and executable. R Notebooks are a specific type of R Markdown document that are designed for interactive data analysis and reproducible research. By using R Markdown and R Notebooks, you can write documents that include code, text, equations, figures, and interactive visualizations, making it easy to document your analysis process and share your results with others. In this tutorial, you’ll learn how to create R Markdown documents and R Notebooks, and how to use Markdown syntax to format your text and embed code chunks in your documents.
Combining code and text in a Markdown document offers several benefits:
Reproducibility: By embedding code in a Markdown document, you can ensure that others can easily reproduce your work. They can see exactly what code you used to generate your results, and they can run that code themselves to verify your findings.
Transparency: By providing a clear and detailed record of your analysis process, you can increase transparency and build trust with your audience. This is especially important in fields like data science, where reproducibility and transparency are essential.
Documentation: Embedding code in a Markdown document can also make it easier to document your work. By including narrative text alongside your code, you can provide context and explanations for your analysis, making it easier for others to understand and replicate your work.
Presentation: Markdown documents can be easily converted into a variety of formats, such as HTML, PDF, and Word documents. This makes it easy to present your analysis in a polished and professional manner, without having to manually copy and paste your code and results into a separate document.
Overall, embedding code in a Markdown document can make your analysis more transparent, reproducible, and well-documented, which can improve the quality and credibility of your analysis.
This lesson provided an introduction. There are many more advanced markdown and R Notebook techniques, including writing books and building full websites. In fact, the :artificium lesson repository was full built in R Notebooks and the source for this lesson is an R Notebook.
Errata
None collected yet. Let us know.
LS0tCnRpdGxlOiAiTGl0ZXJhdGUgUHJvZ3JhbW1pbmcgd2l0aCBSIE5vdGVib29rcyIKcGFyYW1zOgogIGNhdGVnb3J5OiA2CiAgbnVtYmVyOiAyMDQKICB0aW1lOiA0NQogIGxldmVsOiBiZWdpbm5lcgogIHRhZ3M6ICJyLHIgc3R1ZGlvLHIgbWFya2Rvd24sbGl0ZXJhdGUgcHJvZ3JhbW1pbmciCiAgZGVzY3JpcHRpb246ICJFeHBsYWlucyB0aGUgYmVuZWZpdHMgb2Ygd29ya2luZyB3aXRoIFIgTm90ZWJvb2tzIGFuZCBob3cgdG8KICAgICAgICAgICAgICAgIGxldmVyYWdlIGNvZGUgY2h1bmtzIGFuZCBmb2xsb3cgdGhlIHByaW5jaXBsZXMgb2YgTGl0ZXJhdGUKICAgICAgICAgICAgICAgIFByb2dyYW1taW5nLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgUHJlZmFjZQoKVGhpcyB0dXRvcmlhbCBwcmVzdW1lcyB0aGF0IHlvdSBoYXZlIFIgYW5kIFIgU3R1ZGlvIGluc3RhbGxlZCwgb3IgdGhhdCB5b3UgaGF2ZSBhbiBhY2NvdW50IG9uIFtyc3R1ZGlvLmNsb3VkXShodHRwOi8vcnN0dWRpby5jbG91ZCkuIElmIHlvdSBkbyBub3QgYWxyZWFkeSBoYXZlIFIgYW5kL29yIFIgU3R1ZGlvIHlvdSB3aWxsIG5lZWQgdG8gZG93bmxvYWQgYW5kIGluc3RhbGwgdGhlbS4gWW91IG11c3QgZmlyc3QgaW5zdGFsbCBSIGZyb20gW1IgUHJvamVjdF0oaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnLykgYW5kIHRoZW4gdGhlIFIgU3R1ZGlvIElERSBmcm9tIFtSIFN0dWRpb10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLykuCgojIyBSIE5vdGVib29rcyB2cyBSIFNjcmlwdHMKClRoZXJlIGFyZSBzZXZlcmFsIGRpc3RpbmN0IHdheXMgdG8gd3JpdGUgUiBjb2RlIGFuZCB0byBwcm9ncmFtIGluIFI6IFIgTm90ZWJvb2tzLCBRdWF0cm8gRG9jdW1lbnRzLCBhbmQgUiBTY3JpcHRzLiBBbiBSIE1hcmtkb3duIE5vdGVib29rICgqLlJtZCogZmlsZSkgYW5kIGFuIFIgU2NyaXB0ICgqLlIqIGZpbGUpIGFyZSBib3RoIHRvb2xzIHVzZWQgaW4gdGhlIFIgcHJvZ3JhbW1pbmcgZW52aXJvbm1lbnQsIGJ1dCB0aGV5IHNlcnZlIGRpZmZlcmVudCBwdXJwb3NlcyBhbmQgaGF2ZSBkaXN0aW5jdCBmZWF0dXJlczoKCiMjIyBSIE1hcmtkb3duIE5vdGVib29rCgoxLiAgKipJbnRlZ3JhdGVkIERvY3VtZW50YXRpb24gYW5kIENvZGUqKjoKICAgIC0gICBSIE1hcmtkb3duIGFsbG93cyB5b3UgdG8gY29tYmluZSBuYXJyYXRpdmUgdGV4dCwgY29kZSwgYW5kIG91dHB1dCBpbiBhIHNpbmdsZSBkb2N1bWVudC4gSXQgc3VwcG9ydHMgTWFya2Rvd24gc3ludGF4IGZvciB0ZXh0IGZvcm1hdHRpbmcsIG1ha2luZyBpdCBlYXN5IHRvIGNyZWF0ZSB3ZWxsLWRvY3VtZW50ZWQgcmVwb3J0cywgcHJlc2VudGF0aW9ucywgYW5kIGludGVyYWN0aXZlIG5vdGVib29rcy4gVGhlIGNvZGUgYmxvY2tzIGNhbiBiZSBhIG1peCBvZiBSLCBQeXRob24sIFNRTCwgYW1vbmcgbWFueSBvdGhlciBwcm9ncmFtbWluZyBsYW5ndWFnZXMuIFIgTm90ZWJvb2tzIGFyZSBzaW1pbGFyIHRvIEp1cHl0ZXIgTm90ZWJvb2tzIG9mdGVuIHVzZWQgaW4gUHl0aG9uLgoyLiAgKipEeW5hbWljIFJlcG9ydCBHZW5lcmF0aW9uKio6CiAgICAtICAgWW91IGNhbiBleGVjdXRlIGNvZGUgY2h1bmtzIHdpdGhpbiB0aGUgZG9jdW1lbnQgYW5kIGltbWVkaWF0ZWx5IHNlZSB0aGUgcmVzdWx0cywgaW5jbHVkaW5nIHBsb3RzLCB0YWJsZXMsIGFuZCBvdGhlciBvdXRwdXRzLiBUaGlzIG1ha2VzIFIgTWFya2Rvd24gaWRlYWwgZm9yIGNyZWF0aW5nIGR5bmFtaWMgYW5kIHJlcHJvZHVjaWJsZSByZXNlYXJjaCBkb2N1bWVudHMuCjMuICAqKkludGVyYWN0aXZlIEZlYXR1cmVzKio6CiAgICAtICAgTm90ZWJvb2tzIGluIFIgTWFya2Rvd24gY2FuIGluY2x1ZGUgaW50ZXJhY3RpdmUgZmVhdHVyZXMsIHN1Y2ggYXMgSFRNTCB3aWRnZXRzIGFuZCBTaGlueSBhcHBzLCB3aGljaCBjYW4gYmUgZW1iZWRkZWQgZGlyZWN0bHkgaW50byB0aGUgZG9jdW1lbnQuCjQuICAqKk91dHB1dCBGb3JtYXRzKio6CiAgICAtICAgUiBNYXJrZG93biBkb2N1bWVudHMgY2FuIGJlIHJlbmRlcmVkIGludG8gdmFyaW91cyBmb3JtYXRzLCBpbmNsdWRpbmcgSFRNTCwgUERGLCBXb3JkLCBhbmQgc2xpZGVzaG93cy4gVGhpcyBmbGV4aWJpbGl0eSBhbGxvd3MgZm9yIGVhc3kgc2hhcmluZyBhbmQgcHJlc2VudGF0aW9uIG9mIHRoZSByZXN1bHRzLgo1LiAgKipFYXNlIG9mIENvbGxhYm9yYXRpb24qKjoKICAgIC0gICBUaGUgY29tYmluYXRpb24gb2YgY29kZSBhbmQgaXRzIG91dHB1dCB3aXRoIG5hcnJhdGl2ZSB0ZXh0IG1ha2VzIGl0IGVhc2llciB0byBzaGFyZSBjb21wbGV0ZSBhbmFseXNlcyB3aXRoIGNvbGxhYm9yYXRvcnMsIHdobyBjYW4gc2VlIGJvdGggdGhlIG1ldGhvZHMgYW5kIHRoZSByZXN1bHRzIGluIGNvbnRleHQuCgojIyMgUiBTY3JpcHQgKC5SIGZpbGUpCgoxLiAgKipDb2RlIE9ubHkqKjoKICAgIC0gICBBbiBSIFNjcmlwdCBpcyBhIHBsYWluIHRleHQgZmlsZSBjb250YWluaW5nIG9ubHkgUiBjb2RlLiBJdCBkb2VzIG5vdCBzdXBwb3J0IE1hcmtkb3duIG9yIG90aGVyIHR5cGVzIG9mIHRleHQgZm9ybWF0dGluZy4KMi4gICoqRXhlY3V0aW9uKio6CiAgICAtICAgUiBTY3JpcHRzIGFyZSB0eXBpY2FsbHkgcnVuIGxpbmUtYnktbGluZSBvciBhcyBhIHdob2xlIGluIGFuIFIgY29uc29sZSBvciBSU3R1ZGlvIGVudmlyb25tZW50LiBUaGV5IGFyZSBzdHJhaWdodGZvcndhcmQgZm9yIHdyaXRpbmcgYW5kIGV4ZWN1dGluZyBSIGNvZGUgYnV0IGRvIG5vdCBwcm92aWRlIGludGVncmF0ZWQgZG9jdW1lbnRhdGlvbiBvciBpbW1lZGlhdGUgdmlzdWFsIGZlZWRiYWNrIHdpdGhpbiB0aGUgc2NyaXB0IGl0c2VsZi4KMy4gICoqU2ltcGxpY2l0eSoqOgogICAgLSAgIFRoZSBzaW1wbGljaXR5IG9mIFIgU2NyaXB0cyBtYWtlcyB0aGVtIGlkZWFsIGZvciB3cml0aW5nIGFuZCB0ZXN0aW5nIFIgY29kZSBxdWlja2x5LiBUaGV5IGFyZSBsZXNzIGN1bWJlcnNvbWUgdGhhbiBSIE1hcmtkb3duIGZpbGVzIHdoZW4geW91IG9ubHkgbmVlZCB0byB3cml0ZSBhbmQgZXhlY3V0ZSBjb2RlIHdpdGhvdXQgdGhlIG5lZWQgZm9yIGV4dGVuc2l2ZSBkb2N1bWVudGF0aW9uIG9yIHByZXNlbnRhdGlvbiBvZiByZXN1bHRzLgo0LiAgKipVc2UgQ2FzZXMqKjoKICAgIC0gICBSIFNjcmlwdHMgYXJlIGNvbW1vbmx5IHVzZWQgZm9yIHNjcmlwdGluZyB0YXNrcywgZGF0YSBtYW5pcHVsYXRpb24sIGFuYWx5c2lzIHBpcGVsaW5lcywgYW5kIGJhdGNoIHByb2Nlc3Npbmcgd2hlcmUgdGhlIHByaW1hcnkgZm9jdXMgaXMgb24gY29kZSBleGVjdXRpb24gcmF0aGVyIHRoYW4gcHJlc2VudGF0aW9uLgoKKipSIE1hcmtkb3duIE5vdGVib29rICguUm1kIGZpbGUpKiogYXJlIGJlc3QgZm9yIGNyZWF0aW5nIGNvbXByZWhlbnNpdmUsIHJlcHJvZHVjaWJsZSBkb2N1bWVudHMgdGhhdCBpbnRlZ3JhdGUgY29kZSwgcmVzdWx0cywgYW5kIG5hcnJhdGl2ZSB0ZXh0LiBUaGV5IGNhbiBjb250YWluIGEgbWl4IG9mIGNvZGUgY2h1bmtzIChibG9ja3MpIGluIFIsIFB5dGhvbiwgU1FMLCBDKyssIEphdmEsIEQzLCBhbmQgbWFueSBvdGhlciBsYW5ndWFnZXMuIElkZWFsIGZvciByZXBvcnRzLCBpbnRlcmFjdGl2ZSBkb2N1bWVudHMsIGFuZCBwcmVzZW50YXRpb25zLiBPbiB0aGUgb3RoZXIgaGFuZCwgKipSIFNjcmlwdCAoLlIgZmlsZSkqKiBhcmUgcHJlZmVyYWJsZSBmb3Igc3RyYWlnaHRmb3J3YXJkIGNvZGluZyB0YXNrcywgc2NyaXB0aW5nLCBhbmQgYmF0Y2ggcHJvY2Vzc2luZyB3aGVyZSB0aGUgZm9jdXMgaXMgc29sZWx5IG9uIHRoZSBjb2RlIHdpdGhvdXQgdGhlIG5lZWQgZm9yIGludGVncmF0ZWQgZG9jdW1lbnRhdGlvbiBvciBwcmVzZW50YXRpb24uIFRoZXkgYXJlICJwcm9ncmFtcyIgc2ltaWxhciB0byBQeXRob24gcHJvZ3JhbXMuIEJvdGggdHlwZXMgb2YgInByb2dyYW1zIiBhcmUgZXNzZW50aWFsIGluIHRoZSBSIGVjb3N5c3RlbSwgYW5kIHRoZWlyIHVzZSBkZXBlbmRzIG9uIHRoZSBzcGVjaWZpYyBuZWVkcyBvZiB5b3VyIHByb2plY3QuIFRoaXMgdHV0b3JpYWwgd2lsbCBmb2N1cyBvbiBSIE1hcmtkb3duIE5vdGVib29rcy4KCiMjIFIgTm90ZWJvb2tzCgpSIE5vdGVib29rcyBhcmUgZG9jdW1lbnRzIHRoYXQgY29tYmluZSBjb2RlIGFuZCB0ZXh0LCBhbGxvd2luZyBmb3IgcmVwcm9kdWNpYmxlIHJlc2VhcmNoIGFuZCBkYXRhIGFuYWx5c2lzLiBUaGV5IGFyZSBjcmVhdGVkIGluIFtQb3NpdCAoZm9ybWVybHkgUiBTdHVkaW8pXShodHRwczovL3Bvc2l0LmNvLyksIGFuIGludGVncmF0ZWQgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgKElERSkgZm9yIHRoZSBSIGFuZCBQeXRob24gcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLgoKUiBOb3RlYm9va3MgdXNlIGEgdGV4dC1iYXNlZCBkb2N1bWVudCB3cml0aW5nIHN5c3RlbSBjYWxsZWQgUiBNYXJrZG93biBmb3IgbGl0ZXJhdGUgcHJvZ3JhbW1pbmcsIHdoaWNoIGFsbG93cyB5b3UgdG8gZW1iZWQgZXhlY3V0YWJsZSBSIChhcyB3ZWxsIGFzIFB5dGhvbiwgQysrLCBTUUwsIGFuZCBiYXNoKSBjb2RlIHdpdGhpbiBNYXJrZG93biB0ZXh0LiBUaGlzIG1lYW5zIHlvdSBjYW4gd3JpdGUgbmFycmF0aXZlIHRleHQsIGFkZCBoZWFkaW5ncywgaW5zZXJ0IGZpZ3VyZXMsIGVtYmVkIGltYWdlcywgbGluayB0byBVUkxzLCBhbmQgaW5jbHVkZSBtYXRoZW1hdGljYWwgTGFUZVgtZm9ybWF0dGVkIGVxdWF0aW9ucyBpbiB5b3VyIGRvY3VtZW50LCB3aGlsZSBhbHNvIGV4ZWN1dGluZyBSIGNvZGUgY2h1bmtzIGFuZCBkaXNwbGF5aW5nIHRoZSByZXN1bHRzIGlubGluZS4KClRoZSBSIE1hcmtkb3duIHN5bnRheCBpcyBiYXNlZCBvbiB0aGUgTWFya2Rvd24gc3ludGF4LCB3aGljaCBpcyBhIGxpZ2h0d2VpZ2h0IG1hcmt1cCBsYW5ndWFnZSB1c2VkIGZvciBmb3JtYXR0aW5nIHRleHQgZG9jdW1lbnRzLiBSIE5vdGVib29rcyBhbGxvdyB5b3UgdG8gd3JpdGUgZG9jdW1lbnRzIHRoYXQgYXJlIGJvdGggaHVtYW4tcmVhZGFibGUgYW5kIGV4ZWN1dGFibGUuIFRoZXkgbWFrZSBpdCBlYXN5IHRvIHNoYXJlIHlvdXIgY29kZSwgZGF0YSwgYW5kIGFuYWx5c2lzIHdpdGggb3RoZXJzLCB3aGlsZSBhbHNvIHByb3ZpZGluZyBhIGNsZWFyIGFuZCBvcmdhbml6ZWQgcmVjb3JkIG9mIHlvdXIgYW5hbHlzaXMgcHJvY2Vzcy4KCiMjIFdvcmtmbG93CgpBbGwgb2YgeW91ciB3b3JrIG11c3QgYmUgZG9uZSB3aXRoaW4gYW4gUiBQcm9qZWN0LCBzbyBjcmVhdGUgYSBwcm9qZWN0IGZpcnN0LCBvciwgaWYgeW91IGFscmVhZHkgaGF2ZSBvbmUsIG9wZW4gdGhlIHByb2plY3QgYmVmb3JlIGRvaW5nIGFueSB3b3JrLgoKIyMjIE5ldyBSIE5vdGVib29rCgpUbyBidWlsZCBhIG5ldyBSIE5vdGVib29rLCB5b3Ugc2hvdWxkIGZvbGxvdyB0aGVzZSBzdGVwczoKCjEuICBPcGVuIFJTdHVkaW8KMi4gIENsaWNrIG9uICJGaWxlIiBpbiB0aGUgdG9wIGxlZnQtaGFuZCBjb3JuZXIsIGFuZCB0aGVuIGNsaWNrIG9uICJOZXcgRmlsZSIgYW5kIHNlbGVjdCAiUiBOb3RlYm9vayIuCjMuICBUaGlzIHdpbGwgY3JlYXRlIGEgbmV3IFIgTm90ZWJvb2sgd2l0aCBzb21lIHByZS1wb3B1bGF0ZWQgdGV4dCBhbmQgY29kZS4gWW91IGNhbiBtb2RpZnkgdGhpcyBhcyBuZWVkZWQuCjQuICBZb3UgY2FuIGFkZCBuZXcgY29kZSBjaHVua3MgYnkgY2xpY2tpbmcgb24gdGhlICIrIiBpY29uIGluIHRoZSB0b3AgbGVmdC1oYW5kIGNvcm5lciBvZiB0aGUgbm90ZWJvb2sgb3IgYnkgdXNpbmcgdGhlIGtleWJvYXJkIHNob3J0Y3V0ICJDdHJsICsgQWx0ICsgSSIuCjUuICBXcml0ZSB5b3VyIFIgY29kZSB3aXRoaW4gdGhlIGNvZGUgY2h1bmtzLgo2LiAgV3JpdGUgbmFycmF0aXZlIHRleHQgdXNpbmcgTWFya2Rvd24gc3ludGF4IGluIGJldHdlZW4gdGhlIGNvZGUgY2h1bmtzLgo3LiAgVGVzdCBlYWNoIGNvZGUgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICJSdW4iIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIHVzaW5nIHRoZSBrZXlib2FyZCBzaG9ydGN1dCAiQ3RybCArIEVudGVyIi4KOC4gIFRvIHNhdmUgeW91ciBSIE5vdGVib29rLCBjbGljayBvbiAiRmlsZSIgYW5kIHRoZW4gY2xpY2sgb24gIlNhdmUgQXMuLi4iLiBZb3UgY2FuIHRoZW4gc2F2ZSB5b3VyIG5vdGVib29rIGluIHlvdXIgZGVzaXJlZCBsb2NhdGlvbi4KOS4gIEtuaXQgdGhlIFIgTm90ZWJvb2sgdG8gdGhlIGRlc2lyZWQgZG9jdW1lbnQgZm9ybWF0IChIVE1MIG9yIFBERikuCgpXaXRoIGFuIFIgTm90ZWJvb2ssIHlvdSBjYW4gbWl4IFIgY29kZSB3aXRoIG5hcnJhdGl2ZSB0ZXh0LCB3aGljaCBtYWtlcyBpdCBlYXN5IHRvIGRvY3VtZW50IHlvdXIgYW5hbHlzaXMgYW5kIHNoYXJlIGl0IHdpdGggb3RoZXJzLiBBZGRpdGlvbmFsbHksIHlvdSBjYW4gaW5jbHVkZSB2aXN1YWxpemF0aW9ucyBhbmQgb3RoZXIgb3V0cHV0cyBkaXJlY3RseSBpbiB0aGUgbm90ZWJvb2ssIHdoaWNoIG1ha2VzIGl0IGVhc3kgdG8gcHJlc2VudCB5b3VyIHJlc3VsdHMuCgojIyMgS25pdHRpbmcKCk9uY2UgeW91ciBSIE5vdGVib29rIGlzIHdyaXR0ZW4sIGl0IG11c3QgYmUgKmtuaXR0ZWQqLiBLbml0dGluZyBnZW5lcmF0ZXMgYSBtYXJrZG93biBkb2N1bWVudCB3aGljaCBpcyB0aGVuIGNvbnZlcnRlZCB0byBhIGRvY3VtZW50LCBjb21tb25seSBQREYgb3IgSFRNTC4gVGhpcyBwcm9jZXNzIGlzIG9mdGVuIGNhbGxlZCBrbml0dGluZyBvciByZW5kZXJpbmc7IGl0IGlzIGEgZm9ybSBvZiBjb21waWxhdGlvbi4gRHVyaW5nIHRoZSBrbml0dGluZyBwcm9jZXNzLCBjb2RlIGNodW5rcyBhcmUgZXhlY3V0ZWQgYW5kIGFueSBvdXRwdXQgaXMgZW1iZWRkZWQgaW4gdGhlIHJlc3VsdCBkb2N1bWVudCwgdW5sZXNzIGNodW5rcyBhcmUgbWFya2VkIHRvIG5vdCBiZSBldmFsdWF0ZWQgb3Igbm90IGJlaW5nIGluY2x1ZGVkLgoKV2hpbGUgd3JpdGluZyB0aGUgUiBOb3RlYm9vaywgY29kZSBjaHVua3MgY2FuIGJlIGV4ZWN1dGVkIGluZGl2aWR1YWxseSB3aGljaCBjYW4gYmUgaGVscGZ1bCBmb3IgZGV2ZWxvcG1lbnQuIER1cmluZyBrbml0dGluZywgdGhlIGNodW5rcyBhcmUgcnVuIGluIHNlcXVlbmNlIHN0YXJ0aW5nIHdpdGggdGhlIGZpcnN0IGNvZGUgY2h1bmsuCgojIyBUdXRvcmlhbAoKQmVmb3JlIHByb2NlZWRpbmcgd2l0aCB0aGUgcmVtYWluZGVyIG9mIHRoaXMgbGVzc29uIGFuZCB0aGUgc3BlY2lmaWMgUiBOb3RlYm9vayB3cml0aW5nIGVsZW1lbnRzLCB3YXRjaCB0aGlzIHNob3J0IG5hcnJhdGVkIHR1dG9yaWFsIHRoYXQgZGVtb25zdHJhdGVzIGhvdyB0byBidWlsZCBSIE5vdGVib29rcyBhbmQga25pdCB0aGVtIHRvIEhUTUwgYW5kIFBERiBkb2N1bWVudHMuCgo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9wbGF5ZXIudmltZW8uY29tL3ZpZGVvLzgyMTM5ODk2OT9oPTM3MTNkMzc2NDEmYW1wO3RpdGxlPTAmYW1wO2J5bGluZT0wJmFtcDtwb3J0cmFpdD0wJmFtcDtzcGVlZD0wJmFtcDtiYWRnZT0wJmFtcDthdXRvcGF1c2U9MCZhbXA7cGxheWVyX2lkPTAmYW1wO2FwcF9pZD01ODQ3OSIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSIzMDkiIGZyYW1lYm9yZGVyPSIxIiBhbGxvdz0iYXV0b3BsYXk7IGZ1bGxzY3JlZW47IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuIHRpdGxlPSJSIE5vdGVib29rcyBmb3IgSm91cm5hbGluZyBhbmQgTWFya2Rvd24iIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgpLbml0dGluZyB0byBQREYgcmVxdWlyZXMgaW5zdGFsbGF0aW9uIG9mIFRlWCB0b29scyB3aGljaCBtYXkgcHJvdmUgdG8gYmUgZGlmZmljdWx0IG9uIHNvbWUgb3BlcmF0aW5nIHN5c3RlbXMsIG5vdGFibHkgTWFjT1MuIEEgd29yay1hcm91bmQgaXMgdG8gdXBsb2FkIHlvdXIgUiBOb3RlYm9vayBhbmQgc3VwcG9ydGluZyBmaWxlcyB0byBbcG9zaXQuY2xvdWRdKGh0dHA6Ly9wb3NpdC5jbG91ZCkgYW5kIGtuaXQgdGhlcmUgYW5kIHRoZW4gZG93bmxvYWQgdGhlIHJlc3VsdGluZyBQREYgdG8geW91ciBsb2NhbCBwcm9qZWN0IGZvbGRlci4gVGhlIHR1dG9yaWFsIGJlbG93IGRlbW9uc3RyYXRlcyB0aGlzIHdvcmtmbG93LgoKPGlmcmFtZSBzcmM9Imh0dHBzOi8vcGxheWVyLnZpbWVvLmNvbS92aWRlby84ODExNTYzMzM/dGl0bGU9MCZhbXA7YnlsaW5lPTAmYW1wO3BvcnRyYWl0PTAmYW1wO3NwZWVkPTAmYW1wO2JhZGdlPTAmYW1wO2F1dG9wYXVzZT0wJmFtcDthaXJwbGF5PTAmYW1wO2F1ZGlvX3RyYWNrcz0wJmFtcDtjaGFwdGVycz0wJmFtcDtjaHJvbWVjYXN0PTAmYW1wO2Nsb3NlZF9jYXB0aW9ucz0wJmFtcDt0cmFuc2NyaXB0PTAmYW1wO3BsYXllcl9pZD0wJmFtcDthcHBfaWQ9NTg0NzkiIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBmcmFtZWJvcmRlcj0iMSIgYWxsb3c9ImF1dG9wbGF5OyBmdWxsc2NyZWVuOyBwaWN0dXJlLWluLXBpY3R1cmUiIHRpdGxlPSJLbml0IFIgTm90ZWJvb2sgdG8gUERGIHVzaW5nIFIgU3R1ZGlvIChQb3NpdCkgQ2xvdWQiIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgojIyBSIFN0dWRpbyBQcm9qZWN0cwoKUHJvamVjdHMgYXJlIGEgYmV0dGVyIHdheSB0byBtYW5hZ2UgY29kZSByYXRoZXIgdGhhbiBjcmVhdGluZyBpbmRpdmlkdWFsIFIgTm90ZWJvb2tzLCBSIFNjcmlwdHMsIGFuZCBvdGhlciBjb2RlIGZpbGVzLiBQcm9qZWN0cyBhbGxvd3MgYWxsIGZpbGVzLCBpbmNsdWRpbmcgZGF0YSBmaWxlcywgdG8gYmUgbWFuYWdlZCBhcyBhIHNpbmdsZSB1bml0LCBzaGFyZWQsIGFuZCB2ZXJzaW9uIGNvbnRyb2xsZWQgdXNpbmcgc2VydmljZXMgc3VjaCBhcyAqZ2l0KiBhbmQgKkdpdEh1YiouIENvbnN1bHQgW0xlc3NvbiA2LjIwMiAtLSBXb3JraW5nIHdpdGggUiBQcm9qZWN0c10oaHR0cDovL2FydGlmaWNpdW0udXMvbGVzc29ucy8wNi5yL2wtNi0yMDItci1wcm9qZWN0cy9sLTYtMjAyLmh0bWwpIGZvciBtb3JlIGRldGFpbHMgb24gaG93IHRvIGNyZWF0ZSBSIFByb2plY3RzLgoKIyMgTGl0ZXJhdGUgUHJvZ3JhbW1pbmcKCipMaXRlcmF0ZSBQcm9ncmFtbWluZyogaXMgYSBkb2N1bWVudC1jZW50cmljIHByb2dyYW1taW5nIHBhcmFkaWdtIGludHJvZHVjZWQgYnkgRG9uYWxkIEtudXRoIGFyb3VuZCAxOTg0LiBBIGxpdGVyYXRlIGNvbXB1dGVyIHByb2dyYW0gaXMgYSAiZG9jdW1lbnQiIHdyaXR0ZW4gaW4gYSBuYXR1cmFsIGxhbmd1YWdlIHN1Y2ggYXMgRW5nbGlzaCwgaW50ZXJzcGVyc2VkIHdpdGggY2h1bmtzIG9mIHNvdXJjZSBjb2RlIGluIHZhcmlvdXMgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLCBmcm9tIHdoaWNoIGNvbXBpbGFibGUgc291cmNlIGNvZGUgY2FuIGJlIGdlbmVyYXRlZC4gVGhpcyBwcm9ncmFtbWluZyBhcHByb2FjaCBpcyBjb21tb25seSB1c2VkIGluIHNjaWVudGlmaWMgY29tcHV0aW5nLCBkYXRhIHByb2dyYW1taW5nLCBhbmQgZGF0YSBzY2llbmNlIHdpdGggdGhlIGdvYWwgb2YgcHJvZHVjaW5nIHJlcHJvZHVjaWJsZSBkYXRhIHBpcGVsaW5lcyBhbmQgZGF0YSBhbmFseXNlcy4gSnVweXRlciBOb3RlYm9va3MgYW5kIFIgTm90ZWJvb2tzIGFyZSB0d28gY29tbW9uIGltcGxlbWVudGF0aW9ucyBvZiB0aGlzIHBhcmFkaWdtLgoKQSBsaXRlcmF0ZSBwcm9ncmFtIG11c3QgYmUgImNvbXBpbGVkIiBpbnRvIGNvZGUgc3VpdGFibGUgZm9yIGV4ZWN1dGlvbiBhbmQgYSByZXByZXNlbnRhdGlvbiB0aGF0IGNhbiBiZSB2aWV3ZWQuIFRoZSBsYXR0ZXIgaXMgY29tbW9ubHkgYW4gSFRNTCBvciBQREYgZG9jdW1lbnQuIFRoZSBmb3JtZXIgaXMgY29tbW9ubHkgUiBvciBQeXRob24gY29kZSBpbnRlcnNwZXJzZWQgd2l0aCBDKyssIEphdmEsIGFuZCBTUUwgY29kZSBhbmQgZW1iZWRkZWQgZm9ybWF0dGluZyBkaXJlY3RpdmVzIGluIGEgbWFya3VwIGxhbmd1YWdlIHN1Y2ggSFRNTCwgTWFya2Rvd24sIGFuZCBMYVRlWC4KClRoZSAqKmtuaXRyKiogcGFja2FnZSBpbXBsZW1lbnRzIHRoZSBwcm9ncmFtbWluZyBwYXJhZGlnbSB3aXRoaW4gUiBOb3RlYm9va3MsIHdoaWNoIGFyZSwgaW4gdHVybiwgYSB2YXJpYW50IG9mIFIgTWFya2Rvd24uIFIgTWFya2Rvd24gaXMgYSBzdXBlcnNldCBvZiBNYXJrZG93bi4KCkZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIGluZm9ybWF0aW9uIHNjaWVuY2UsIGEgZG9jdW1lbnQgaXMgYW4gYWdncmVnYXRpb24gb2YgaW5mb3JtYXRpb24gb2JqZWN0cywgc29tZSBvZiB3aGljaCBhcmUgY3JlYXRlZCBwcm9ncmFtbWF0aWNhbGx5LgoKIyMgUiBNYXJrZG93biBpbiBhIE51dHNoZWxsCgpUaGUga2V5IG1hcmtkb3duIGRpcmVjdGl2ZXMgYXJlIGlsbHVzdHJhdGVkIGJlbG93IHdpdGggdGhlaXIgcmVzdWx0IHJpZ2h0IGFmdGVyd2FyZHM6CgpgYGAgICAgICAgICAKVGhpcyBpcyBfbWFya2Rvd25fLiBNYXJrZG93biBjb250YWlucyBlbWJlZGRlZCBmb3JtYXR0aW5nIApzdWNoIGFzIF9pdGFsaWNzXywgKipib2xkZmFjaW5nKiosIGFuZCB+fnN0cmlrZXN+fi4gCk9mIGNvdXJzZSB3ZSBjYW4gYWxzbyBkbyBzdXBlcnNjcmlwdHMKbGlrZSB4XjJeIG9yIHN1YnNjcmlwdHMgbGlrZSB4fml+LiAKCkhlYWRlcnMgYXJlIG1hcmtlZCB3aXRoIGhhc2ggbWFya3MgIyMjCgojIyMjIExhVGVYIEVxdWF0aW9ucwoKTW9yZSBjb21wbGV4IGZvcm1hdHRpbmcgb2YgbWF0aCBleHByZXNzaW9ucyBjYW4gYmUgZG9uZSAKd2l0aCBlbWJlZGRlZCBbTGFUZVhdKGh0dHBzOi8vbGF0ZXgtdHV0b3JpYWwuY29tLykgCmxpa2UgdGhpcyAkeF9pJCBvciBvbiBhIHNlcGFyYXRlIGxpbmU6CgokXGJhcnt4fT1cZnJhY3sxfXtufVxzdW1fe2k9MH1ee259KHhfaSkkCgpvciBjZW50ZXJlZCBsaWtlIHRoaXM6CgokJApcYmFye3h9PVxmcmFjezF9e259XHN1bV97aT0wfV57bn0oeF9pKQokJAoKRGlkIHlvdSBzZWUgaG93IEkgY3JlYXRlZCBhbiBlbWJlZGRlZCBsaW5rIHRvIGEgVVJMPwoKTnVtYmVyZWQgbGlzdHMgYXJlIHByb2R1Y2VkIHdpdGg6CgoxLiBpdGVtIDEKMi4gaXRlbSAyCiAgYS4gc3ViIGl0ZW0gYQogIGIuIHN1YiBpdGVtIGIKMy4gaXRlbSAzCgpCdWxsZXRlZCBsaXN0cyBjYW4gYmUgcHJvZHVjZWQgd2l0aDoKCi0gYnVsbGV0IGl0ZW0KLSBidWxsZXQgaXRlbQoKVGFzayBsaXN0cyBjYW4gYmUgcHJvZHVjZWQgd2l0aDoKCi0gWyBdIHRhc2sgMQotIFsgXSB0YXNrIDIKLSBbeF0gdGFzayAzIGlzIGRvbmUKCj4gTGFzdGx5LCB5b3UgY2FuIHVzZSA+IHRvIG1ha2UgYmxvY2txdW90ZXMgZm9yIGNhbGxpbmcgb3V0IGltcG9ydGFudAogIGluZm9ybWF0aW9uLgogIApEaWQgeW91IG5vdGljZSBob3cgdGhlIHNlY29uZCBsaW5lIGluIHRoZSBibG9jayBxdW90ZSB3YXMgaW50ZW50ZWQ/CmBgYAoKVGhlIG1hcmtkb3duIGFib3ZlIGlzIGtuaXR0ZWQgdG8gdGhlIGZvbGxvd2luZyBmb3JtYXQ6CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClRoaXMgaXMgKm1hcmtkb3duKi4gTWFya2Rvd24gY29udGFpbnMgZW1iZWRkZWQgZm9ybWF0dGluZyBzdWNoIGFzICppdGFsaWNzKiwgKipib2xkZmFjaW5nKiosIGFuZCB+fnN0cmlrZXN+fi4gT2YgY291cnNlIHdlIGNhbiBhbHNvIGRvIHN1cGVyc2NyaXB0cyBsaWtlIHheMl4gb3Igc3Vic2NyaXB0cyBsaWtlIHh+aX4uCgpIZWFkZXJzIGFyZSBtYXJrZWQgd2l0aCBoYXNoIG1hcmtzIFwjIyMKCiMjIyMgTGFUZVggRXF1YXRpb25zCgpNb3JlIGNvbXBsZXggZm9ybWF0dGluZyBvZiBtYXRoIGV4cHJlc3Npb25zIGNhbiBiZSBkb25lIHdpdGggZW1iZWRkZWQgW0xhVGVYXShodHRwczovL2xhdGV4LXR1dG9yaWFsLmNvbS8pIGxpa2UgdGhpcyAkeF9pJCBvciBvbiBhIHNlcGFyYXRlIGxpbmU6CgokXGJhcnt4fT1cZnJhY3sxfXtufVxzdW1fe2k9MH1ee259KHhfaSkkCgpvciBjZW50ZXJlZCBsaWtlIHRoaXM6CgokJApcYmFye3h9PVxmcmFjezF9e259XHN1bV97aT0wfV57bn0oeF9pKQokJAoKRGlkIHlvdSBzZWUgaG93IEkgY3JlYXRlZCBhbiBlbWJlZGRlZCBsaW5rIHRvIGEgVVJMPwoKTnVtYmVyZWQgbGlzdHMgYXJlIHByb2R1Y2VkIHdpdGg6CgoxLiAgaXRlbSAxCjIuICBpdGVtIDIKCjwhLS0gLS0+CgphLiAgc3ViIGl0ZW0gYQpiLiAgc3ViIGl0ZW0gYgoKPCEtLSAtLT4KCjMuICBpdGVtIDMKCkJ1bGxldGVkIGxpc3RzIGNhbiBiZSBwcm9kdWNlZCB3aXRoOgoKLSAgIGJ1bGxldCBpdGVtCi0gICBidWxsZXQgaXRlbQoKVGFzayBsaXN0cyBjYW4gYmUgcHJvZHVjZWQgd2l0aDoKCi0gICBbIF0gdGFzayAxCi0gICBbIF0gdGFzayAyCi0gICBbeF0gdGFzayAzIGlzIGRvbmUKCj4gTGFzdGx5LCB5b3UgY2FuIHVzZSBcPiB0byBtYWtlIGJsb2NrcXVvdGVzIGZvciBjYWxsaW5nIG91dCBpbXBvcnRhbnQgaW5mb3JtYXRpb24uCgpEaWQgeW91IG5vdGljZSBob3cgdGhlIHNlY29uZCBsaW5lIGluIHRoZSBibG9jayBxdW90ZSB3YXMgaW50ZW50ZWQ/CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClNlZSB0aGUgW1IgTWFya2Rvd24gUmVmZXJlbmNlIEd1aWRlXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS93cC1jb250ZW50L3VwbG9hZHMvMjAxNS8wMy9ybWFya2Rvd24tcmVmZXJlbmNlLnBkZj9fZ2E9Mi41OTE4NDE3My4xMjE0MjUyOTI4LjE2MzU5ODA0NzQtMTk0OTk1NTE3LjE2MzU0MzM3NTcpIGZvciBhIGNvbXBsZXRlIGxpc3Qgb2YgbWFya2Rvd24gZWxlbWVudHMuCgojIyBSIE5vdGVib29rIEVsZW1lbnRzCgojIyMgRG9jdW1lbnQgTWV0YSBUYWdzCgpUaGUga2V5IG1ldGEgdGFncyB0aGF0IHlvdSBtdXN0IHByb3ZpZGUgYXJlICp0aXRsZSosICphdXRob3IqLCBhbmQgKmRhdGUqLiBZb3UgbWF5IGFsc28gd2lzaCB0byBwcm92aWRlICplbWFpbCouIFRoZXkgYXJlIGluIHRoZSBtZXRhIHNlY3Rpb24gb2YgeW91ciBub3RlYm9vazoKCmBgYCAgICAgICAgIAotLS0KdGl0bGU6ICJMaXRlcmF0ZSBQcm9ncmFtbWluZyB3aXRoIFIgTm90ZWJvb2tzIgpkYXRlOiAiPHNtYWxsPmByIFN5cy5EYXRlKClgPC9zbWFsbD4iCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKZW1haWw6ICJtLnNjaGVkbGJhdWVyQG5ldS5lZHUiCi4uLgotLS0KYGBgCgojIyMgRW1iZWRkZWQgQ29kZQoKT25lIG9mIHRoZSBtb3N0IHVzZWZ1bCBlbGVtZW50cyBvZiBhbiBSIE5vdGVib29rIGlzIHRoZSBhYmlsaXR5IHRvIGVtYmVkIGNvZGUgZnJhZ21lbnRzIHdpdGhpbiB0ZXh0LiBDb2RlIHdpdGhpbiBhIGNvZGUgYmxvY2sgKG9yIGNvZGUgY2h1bmsgb3IgY29kZSBmZW5jZSkgaXMgZ2VuZXJhbGx5IGluIFIgYnV0IGNhbiBhbHNvIGJlIGluIFB5dGhvbiwgSmF2YSwgQysrLCBiYXNoLCBvciBTUUwuCgojIyMjIEVtYmVkZGluZyBSIENvZGUgeyNlbWJSfQoKQSBjb2RlIGNodW5rIGlzIGNyZWF0ZWQgd2l0aCB0aHJlZSBiYWNrdGlja3MgaW4gYSByb3cgZm9sbG93ZWQgYnkgYSBzZXQgb2YgYnJhY2VzIHdpdGggdGhlIHByb2dyYW1taW5nIGxhbmd1YWdlLgoKYGBge3IgZWNobz1GfQprbml0cjo6cmF3X2h0bWwoIjxwcmU+IikKa25pdHI6OnJhd19odG1sKHBhc3RlKAogICImIzk2OyYjOTY7JiM5Njt7ciBlY2hvPUZ9IiwKICAiJiM5NjsmIzk2OyYjOTY7IiwKICBzZXA9Ijxici8+IikpCmtuaXRyOjpyYXdfaHRtbCgiPC9wcmU+IikKYGBgCgpDb2RlIGNhbiBhbHNvIGJlIGVtYmVkZGVkIGlubGluZSB3aXRoaW4gdGV4dCBsaWtlIHNvOiBgYCBgciBrbml0cjo6aW5saW5lX2V4cHIoImErYiIpYCBgYCBUaGUgcmVzdWx0IG9mIHRoZSBjb2RlIGluIHRoZW4gYWRkZWQgaW4gdGhlIG91dHB1dCBkb2N1bWVudC4KCiMjIyMjIE5hbWVkIENvZGUgQ2h1bmtzCgpDb2RlIGNodW5rcyBzaG91bGQgYmUgbmFtZWQgc28gdGhleSBjYW4gYmUgbW9yZSBlYXNpbHkgZm91bmQuIEFkZGluZyBhIG5hbWUgYWZ0ZXIgdGhlIGxhbmd1YWdlIGNyZWF0ZXMgYSBsYWJlbCBmb3IgdGhlIGNvZGUgY2h1bms6CgpgYGBge3ZlcmJhdGltfQpgYGB7ciBjaHVuay1uYW1lLXdpdGhvdXQtc3BhY2VzfQojIGNvZGUgZ29lcyBoZXJlCmBgYApgYGBgCgojIyMjIyBIaWRpbmcgQ29kZSBDaHVua3MgaW4gT3V0cHV0CgpPZnRlbiwgd2Ugd2FudCB0aGUgY29kZSB0byBydW4gYnV0IHdlIGRvIG5vdCB3YW50IHRoZSBjb2RlIHRvIGJlIHBhcnQgb2YgdGhlIG91dHB1dCBkb2N1bWVudC4gVG8gZG8gdGhhdCwgYWRkICJlY2hvPUYiIGFmdGVyIHRoZSBjb2RlIGNodW5rIG5hbWUsIGxpa2Ugc286CgpgYGBge3ZlcmJhdGltfQpgYGB7ciBjaHVuay1uYW1lLW5vLXNwYWNlcywgZWNobz1GfQojIGNvZGUgZ29lcyBoZXJlCmBgYApgYGBgCgojIyMjIyBTdXBwcmVzcyBFdmFsdWF0aW9uCgpUaGUgY29kZSBpbiBhIGNvZGUgY2h1bmsgY2FuIGJlIGluY2x1ZGVkIChvciBub3QpIGluIHRoZSBkb2N1bWVudCBldmVuIHRob3VnaCB0aGUgY29kZSBpcyBub3QgcnVuLiBUaGF0IGlzIGFmZmVjdGVkIHdpdGggdGhlICJldmFsPUYiIHBhcmFtZXRlci4KCmBgYGB7dmVyYmF0aW19CmBgYHtyIGNodW5rLW5hbWUtbm8tc3BhY2VzLCBldmFsPUZ9CiMgY29kZSBnb2VzIGhlcmUKYGBgCmBgYGAKCiMjIyMjIENvZGUgQ2h1bmtzIHdpdGggTGluZSBOdW1iZXJzCgpUbyBhZGQgbGluZSBudW1iZXJzIHRvIHRoZSBjb2RlLCBhZGQgImF0dHIuc291cmNlPScubnVtYmVyTGluZXMnIiB0byB0aGUgcGFyYW1ldGVycy4KCmBgYGB7dmVyYmF0aW19CmBgYHtyIGNvZGVOb0xpbmVzLCBhdHRyLnNvdXJjZT0nLm51bWJlckxpbmVzJ30KaWYgKFRSVUUpIHsKICB4IDwtIDE6MTAKICB4ICsgMQp9CmBgYApgYGBgCgpUaGUgYWJvdmUgd2lsbCBwcm9kdWNlOgoKYGBge3IgYXR0ci5zb3VyY2U9Jy5udW1iZXJMaW5lcycsIGV2YWw9Rn0KaWYgKFRSVUUpIHsKICB4IDwtIDE6MTAKICB4ICsgMQp9CmBgYAoKIyMjIyMgTmF2aWdhdGluZyBDb2RlIENodW5rcwoKSW4gZ2VuZXJhbCwgYSBjb2RlIGNodW5rIHN0YXJ0cyB3aXRoIHRoZSBsYW5ndWFnZSBmb2xsb3dlZCBieSBhbiBvcHRpb25hbCBuYW1lIGZvciB0aGUgY2h1bmsuIFRoZSBuYW1lIChvciBjaHVuayBsYWJlbCkgaXMgdXNlZnVsIGZvciBxdWljayBuYXZpZ2F0aW9uIGFuZCBmb3IgcmVmZXJlbmNpbmcgd2l0aGluIHRoZSBkb2N1bWVudC4gSW4gUiBTdHVkaW8sIGl0IGNhbiBiZSB1c2VkIGZvciBxdWlja2x5IGp1bXBpbmcgdG8gYSBzZWN0aW9uIG9mIGNvZGUuCgohW0p1bXBpbmcgdG8gQSBDaHVuayBieSBOYW1lXShpbWFnZXMvY2h1bmstbGFiZWxzLmpwZyl7d2lkdGg9IjI1JSJ9CgojIyMjIEVtYmVkZGluZyBDKysgQ29kZQoKVG8gZW1iZWQgQysrIGNvZGUsIHVzZSBlaXRoZXIge1JjcHB9IG9yIHtyIGVuZ2luZT0nUmNwcCd9IGZvciB0aGUgZmVuY2UgaGVhZGVyLgoKYGBgYHt2ZXJiYXRpbX0KYGBge1JjcHAgZmliQ29kZSwgZXZhbD1UfQojaW5jbHVkZSA8UmNwcC5oPgoKLy8gW1tSY3BwOjpleHBvcnRdXQppbnQgRmlib25hY2NpKGNvbnN0IGludCB4KSB7CiAgaWYgKHggPT0gMCB8fCB4ID09IDEpIAogICAgcmV0dXJuKHgpOwogICAgCiAgcmV0dXJuIChGaWJvbmFjY2koeCAtIDEpKSArIEZpYm9uYWNjaSh4IC0gMik7Cn0KYGBgCmBgYGAKCkJlY2F1c2UgdGhlIGZ1bmN0aW9uIGBGaWJvbmFjY2koKWAgd2FzIGRlZmluZWQgd2l0aCB0aGUgKlJjcHA6OmV4cG9ydCogYXR0cmlidXRlIGl0IGlzIGFjY2Vzc2libGUgdG8gUiBjb2RlIGNodW5rcyBhcyBhIG5vcm1hbCBSIGZ1bmN0aW9uOgoKYGBgYHt2ZXJiYXRpbX0KYGBge3IgZXZhbD1GLCBlY2hvPVR9CnByaW50KHBhc3RlMCgiMTAhID0gIiwgRmlib25hY2NpKDEwTCkpKQpmYWN0MjAgPC0gRmlib25hY2NpKDIwTCkKCnByaW50KHBhc3RlMCgiMjAhID0gIiwgZmFjdDIwKSkKYGBgCmBgYGAKCk5vdGUgdGhhdCBjYWNoaW5nIHNob3VsZCBub3QgYmUgdXNlZCB3aXRoIFJjcHAgY29kZSBjaHVua3MgKHNpbmNlIHRoZSBjb21waWxlZCBDKysgZnVuY3Rpb24gd2lsbCBub3Qgc3Vydml2ZSBwYXN0IHRoZSBsaWZldGltZSBvZiB0aGUgY3VycmVudCBSIHNlc3Npb24pLgoKIyMjIEhlYWRpbmdzCgpIZWFkaW5nIGxldmVscyBhcmUgc3BlY2lmaWVkIHdpdGggaGFzaG1hcmtzIChcIykuIE9uZSBoYXNobWFyayBpcyBhIGZpcnN0LWxldmVsIGhlYWRlciAodGhlIHRpdGxlIGZvciB0aGUgZG9jdW1lbnQpLCBhIHNlY29uZC1sZXZlbCBoZWFkZXIgaXMgYSBzZWN0aW9uIGhlYWRpbmdzLCBhbmQgc28gZm9ydGguCgpgYGAgICAgICAgICAKLS0tCnRpdGxlOiAiUHJlZGljdGluZyBDYXIgU2FsZXMiCmRhdGU6ICJBdWd1c3QgMjMsIDIwMjIiCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKCiMjIEludHJvZHVjdGlvbgoKIyMgQW5hbHlzaXMKCiMjIyBEYXRhIENsZWFuaW5nCgojIyMgRmFjdG9yIEFuYWx5c2lzCgojIyBDb25jbHVzaW9uCi0tLQpgYGAKCiMjIyBFbWJlZGRpbmcgTGFUZVgKCkxhVGVYIGVxdWF0aW9ucyBjYW4gYmUgZW1iZWRkZWQgaW4gdGhyZWUgZGlmZmVyZW50IHdheXM6CgoxLiAgaW5saW5lIGJ5IGVuY2xvc2luZyB0aGUgZXF1YXRpb24gaW4gYSB0ZXh0IGJsb3cgbGlrZSBzbyBcJHogPSAoeCAtIFxtdSkgLyBcc2lnbWFcJAoyLiAgaW4gYSBzZXBhcmF0ZSBibG9jayBieSBlbmNsb3Npbmcgd2l0aGluIFwkIGJ1dCB0aGUgZXF1YXRpb24gaXMgb24gaXRzIG93biBsaW5lCjMuICBpbiBkb3VibGUgXCRcJCB3aGljaCBwdXRzIHRoZSBlcXVhdGlvbiBpbiBpdHMgb3duIGJsb2NrIGFuZCBpcyBjZW50ZXJlZAoKVGhlIGZyYWdtZW50IGJlbG93IGlsbHVzdHJhdGVzIGhvdyB0byBlbWJlZCBMYVRlWC4KCmBgYCAgICAgICAgIApJbiBtYXRoZW1hdGljYWwgdGVybXMsIHR3byByZWxhdGlvbnMgJFJfMSQgYW5kICRSXzIkIGFyZSB1bmlvbiBjb21wYXRpYmxlIGlmIGFuZCBvbmx5IGlmCgokZGVncmVlKFJfMSk9ZGVncmVlKFJfMikkLCBhbmQgJFxtYXRoZnJha3tEfShSXntBX2l9X3sxfSkgPSBcbWF0aGZyYWt7RH0oUl57QV9pfV97Mn0pJCwgd2hlcmUgJEFfaSQgaXMgdGhlICppdGgqIGF0dHJpYnV0ZSBhbmQgJFxtYXRoZnJha3tEfShSXntBX2l9X3trfSkkIGlzIHRoZSBkb21haW4gb2YgdGhlICppdGgqIGF0dHJpYnV0ZSBvZiByZWxhdGlvbiAkUl9rJC4KCkZvciBleGFtcGxlLCB0aGUgdHdvIHJlbGF0aW9ucyAkQSQgYW5kICRCJCBiZWxvdyBhcmUgdW5pb24gY29tcGF0aWJsZToKCiRBKGFfMShjaGFyKSxhXzIoY2hhciksYV8zKGRhdGUpKSQKCiRCKGJfMShjaGFyKSxiXzIoY2hhciksYl8zKGRhdGUpKSQKYGBgCgojIyMgRW1iZWRkaW5nIEltYWdlcwoKSW1hZ2VzIGNhbiBiZSBlbWJlZGRlZCBpbiBzZXZlcmFsIHdheXMsIHRoZSBtb3N0IGNvbW1vbiBiZWluZyB0aGUgbWFya2Rvd24gc2hvd24gYmVsb3c6CgpgYGAgICAgICAgICAKIVtpbWFnZSBjYXB0aW9uXShVUkwgb3IgZmlsZW5hbWUpe3N0eWxlLXBhcmFtZXRlcnN9CmBgYAoKWW91IGNhbiBvcHRpb25hbGx5IGFkZCBzdHlsZSBwYXJhbWV0ZXJzIHN1Y2ggYXMge3dpZHRoPTUwJX0gd2hpY2ggYXJlIG9ubHkgbWVhbmluZ2Z1bCB3aGVuIGtuaXR0aW5nIHRvIEhUTUwuCgpIZXJlJ3MgYW4gZXhhbXBsZToKCmBgYCAgICAgICAgIAohW0NSSVNQLURNIFByb2Nlc3NdKGltYWdlcy9jcmlzcC1kbS5wbmcpe3dpZHRoPTMwJX0KYGBgCgpUaGUgYWJvdmUgd291bGQgcmVuZGVyIGFzOgoKIVtDUklTUC1ETSBQcm9jZXNzXShpbWFnZXMvY3Jpc3AtZG0ucG5nKXt3aWR0aD0iMzAlIn0KCiMjIyBFbWJlZGRpbmcgSFRNTAoKSWYgdGhlIHRhcmdldCBkb2N1bWVudCBmb3JtYXQgaXMgSFRNTCwgdGhlbiBpdCBpcyBwZXJtaXR0ZWQgdG8gaW5zZXJ0IEhUTUwgY29kZSBmcmFnbWVudHMgZGlyZWN0bHkgaW50byB0aGUgbWFya2Rvd24gZG9jdW1lbnQuIFRoaXMgaXMgdXNlZnVsIHdoZW4gZW1iZWRkaW5nIGV4dGVybmFsIG9iamVjdHMgaW4gSFRNTCBkb2N1bWVudHMgYXMgaWxsdXN0cmF0ZWQgYmVsb3c6CgpgYGB7dmVyYmF0aW19CjxpZnJhbWUgc3JjPSJodHRwczovL3BsYXllci52aW1lby5jb20vdmlkZW8vODIxMzk4IgogICAgICAgIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBmcmFtZWJvcmRlcj0iMCIgCiAgICAgICAgdGl0bGU9IkpvdXJuYWxpbmcgd2l0aCBNYXJrZG93biIgCiAgICAgICAgZGF0YS1leHRlcm5hbD0iMSI+PC9pZnJhbWU+CmBgYAoKPiBUbyBlbnN1cmUgdGhhdCBlbWJlZGRlZCB2aWRlb3MgYXJlIHBsYXlhYmxlLCB5b3UgbXVzdCBhZGQgdGhlIGF0dHJpYnV0ZSAqZGF0YS1leHRlcm5hbD0iMSIqIHRvIGFueSBcPGlmcmFtZVw+LgoKIyMjIENvZGUgU3R5bGUKClRvIHJlbmRlciB0ZXh0IGFzICJjb2RlIiB1c2luZyBhIG1vbm9zcGFjZWQgZnJvbnQsIGVuY2xvc2UgdGhlIHRleHQgaW4gc2luZ2xlIGJhY2t0aWNrcy4gVGhlIGZyYWdtZW50IGJlbG93IGlsbHVzdHJhdGVzIHRoaXM6CgpgYGAgICAgICAgICAKVGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGNhbiBiZSBjYWxjdWxhdGluZyB1c2luZyB0aGUgCmBjb3IoKWAgZnVuY3Rpb24gaW4gUi4KYGBgCgpUaGUgYWJvdmUgbWFya2Rvd24gd291bGQgcmVuZGVyIGFzOgoKfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCBUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgY2FuIGJlIGNhbGN1bGF0aW5nIHVzaW5nIHRoZSBgY29yKClgIGZ1bmN0aW9uIGluIFIuIHwKCiMjIyBDaHVuayBPcHRpb25zCgpDaHVuayBvdXRwdXQgY2FuIGJlIGN1c3RvbWl6ZWQgd2l0aCBba25pdHIgb3B0aW9uc10oaHR0cHM6Ly95aWh1aS5vcmcva25pdHIvb3B0aW9ucy8pLCBhcmd1bWVudHMgc2V0IGluIHRoZSB7fSBvZiBhIGNodW5rIGhlYWRlci4gQWJvdmUsIHdlIHVzZSBmaXZlIGFyZ3VtZW50czoKCi0gICA8Y29kZT5pbmNsdWRlID0gRkFMU0U8L2NvZGU+IHByZXZlbnRzIGNvZGUgYW5kIHJlc3VsdHMgZnJvbSBhcHBlYXJpbmcgaW4gdGhlIGZpbmlzaGVkIGZpbGUuIFIgTWFya2Rvd24gc3RpbGwgcnVucyB0aGUgY29kZSBpbiB0aGUgY2h1bmssIGFuZCB0aGUgcmVzdWx0cyBjYW4gYmUgdXNlZCBieSBvdGhlciBjaHVua3MuCi0gICA8Y29kZT5lY2hvID0gRkFMU0U8L2NvZGU+IHByZXZlbnRzIGNvZGUsIGJ1dCBub3QgdGhlIHJlc3VsdHMgZnJvbSBhcHBlYXJpbmcgaW4gdGhlIGZpbmlzaGVkIGZpbGUuIFRoaXMgaXMgYSB1c2VmdWwgd2F5IHRvIGVtYmVkIGZpZ3VyZXMuCi0gICA8Y29kZT5tZXNzYWdlID0gRkFMU0U8L2NvZGU+IHByZXZlbnRzIG1lc3NhZ2VzIHRoYXQgYXJlIGdlbmVyYXRlZCBieSBjb2RlIGZyb20gYXBwZWFyaW5nIGluIHRoZSBmaW5pc2hlZCBmaWxlLgotICAgPGNvZGU+d2FybmluZyA9IEZBTFNFPC9jb2RlPiBwcmV2ZW50cyB3YXJuaW5ncyB0aGF0IGFyZSBnZW5lcmF0ZWQgYnkgY29kZSBmcm9tIGFwcGVhcmluZyBpbiB0aGUgZmluaXNoZWQuCi0gICA8Y29kZT5maWcuY2FwID0gIi4uLiI8L2NvZGU+IGFkZHMgYSBjYXB0aW9uIHRvIGdyYXBoaWNhbCByZXN1bHRzLgotICAgPGNvZGU+Y29tbWVudCA9ICIuLi4iPC9jb2RlPiA/Pz8KLSAgIDxjb2RlPmF0dHIuc291cmNlID0gIi5udW1iZXJMaW5lcyI8L2NvZGU+IGFkZHMgbGluZSBudW1iZXJzIHRvIGEgY29kZSBjaHVuawoKU2VlIHRoZSBbUiBNYXJrZG93biBSZWZlcmVuY2UgR3VpZGVdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE1LzAzL3JtYXJrZG93bi1yZWZlcmVuY2UucGRmP19nYT0yLjU5MTg0MTczLjEyMTQyNTI5MjguMTYzNTk4MDQ3NC0xOTQ5OTU1MTcuMTYzNTQzMzc1NykgZm9yIGEgY29tcGxldGUgbGlzdCBvZiBrbml0ciBjaHVuayBvcHRpb25zLgoKIyMjIEdsb2JhbCBPcHRpb25zCgpUbyBzZXQgZ2xvYmFsIG9wdGlvbnMgdGhhdCBhcHBseSB0byBldmVyeSBjaHVuayBpbiB5b3VyIGZpbGUsIGNhbGwgPGNvZGU+a25pdHI6Om9wdHNfY2h1bmtcJHNldDwvY29kZT4gaW4gYSBjb2RlIGNodW5rLiBLbml0ciB3aWxsIHRyZWF0IGVhY2ggb3B0aW9uIHRoYXQgeW91IHBhc3MgdG8ga25pdHI6Om9wdHNfY2h1bmtcJHNldCBhcyBhIGdsb2JhbCBkZWZhdWx0IHRoYXQgY2FuIGJlIG92ZXJ3cml0dGVuIGluIGluZGl2aWR1YWwgY2h1bmsgaGVhZGVycy4KCiMjIE1hcmtkb3duIFRhYmxlcwoKV2hpbGUgdGFibGVzIGNhbiBiZSBnZW5lcmF0ZWQgdGhyb3VnaCBSIGNvZGUgdXNpbmcgdmFyaW91cyBSIGZ1bmN0aW9ucyBzdWNoIGFzIGBrYWJsZSgpYCwgdGhleSBjYW4gYWxzbyBiZSBjcmVhdGVkIGluIG1hcmtkb3duLiBOYXR1cmFsbHksIHRhYmxlcyB0aGF0IGNvbnRhaW4gY2FsY3VsYXRlZCBkYXRhIG9yIGRhdGEgZnJvbSBmaWxlcyBzaG91bGQgYmUgaW5jbHVkZWQgdXNpbmcgUiBjb2RlIGNodW5rcy4KCkluIE1hcmtkb3duLCBhIHRhYmxlIGlzIGEgc3RydWN0dXJlZCBwcmVzZW50YXRpb24gb2YgZGF0YSwgb3JnYW5pemVkIGludG8gcm93cyBhbmQgY29sdW1ucy4gVG8gY3JlYXRlIGEgdGFibGUgaW4gTWFya2Rvd24sIHlvdSBjYW4gdXNlIHRoZSB2ZXJ0aWNhbCBsaW5lICJcfCIgdG8gc2VwYXJhdGUgZWFjaCBjb2x1bW4gYW5kIHRocmVlIG9yIG1vcmUgZGFzaGVzICItLS0iIHRvIGNyZWF0ZSB0aGUgaGVhZGVyIGZvciBlYWNoIGNvbHVtbi4gQWRkaXRpb25hbGx5LCB5b3Ugc2hvdWxkIGluY2x1ZGUgYSB2ZXJ0aWNhbCBsaW5lIGF0IGJvdGggZW5kcyBvZiB0aGUgcm93IHRvIHNlcGFyYXRlIGl0IGZyb20gb3RoZXIgY29udGVudC4KClRoZSBtYXJrZG93biBiZWxvdyBwcm9kdWNlcyB0aGlzIHRhYmxlOgoKYGBgICAgICAgICAgCnwgTW9udGggICAgfCBCdWRnZXQgfAp8IC0tLS0tLS0tIHwgLS0tLS0tLXwKfCBKYW51YXJ5ICB8ICQyNTAwICB8CnwgRmVicnVhcnkgfCAkMzAwMCAgfAp8IE1hcmNoICAgIHwgJDQyMDAgIHwKYGBgCgp8IE1vbnRoICAgIHwgQnVkZ2V0IHwKfC0tLS0tLS0tLS18LS0tLS0tLS18CnwgSmFudWFyeSAgfCBcJDI1MDAgfAp8IEZlYnJ1YXJ5IHwgXCQzMDAwIHwKfCBNYXJjaCAgICB8IFwkNDIwMCB8CgpUaGUgY2VsbCB3aWR0aCBkbyBub3QgaGF2ZSB0byBhbGlnbi4KCkFsaWduIHRleHQgaW4gdGhlIGNvbHVtbnMgdG8gdGhlIGxlZnQsIHJpZ2h0LCBvciBjZW50ZXIgYnkgYWRkaW5nIGEgY29sb24gIjoiIHRvIHRoZSBsZWZ0LCByaWdodCwgb3Igb24gYm90aCBzaWRlIG9mIHRoZSBkYXNoZXMgLS0tIHdpdGhpbiB0aGUgaGVhZGVyIHJvdy4gVGhlIGV4YW1wbGUgaXMgcmVuZGVyZWQgYmVsb3c6CgpgYGAgICAgICAgICAKfCBDb3Vyc2UgICAgICAgICAgICB8IENyZWRpdHMgfCBUZXJtICAgfAp8IDotLS0tLS0tLS0tLS0tLS0tIHwgOi0tLS0tLTp8IC0tLS06ICB8CnwgSW50cm8gdG8gUHl0aG9uICAgfCAgIDIgICAgIHwgRmFsbCAgIHwKfCBTUUwgZm9yIEJlZ2lubmVycyB8ICAgMyAgICAgfCBGYWxsICAgfAp8IFN0YXRpc3RpY3Mgd2l0aCBSIHwgICA0ICAgICB8IFNwcmluZyB8CnwgT09EIHdpdGggQysrICAgICAgfCAgIDQgICAgIHwgU3VtbWVyIHwKYGBgCgp8IENvdXJzZSAgICAgICAgICAgIHwgQ3JlZGl0cyB8ICAgVGVybSB8Cnw6LS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tOnwtLS0tLS0tOnwKfCBJbnRybyB0byBQeXRob24gICB8ICAgIDIgICAgfCAgIEZhbGwgfAp8IFNRTCBmb3IgQmVnaW5uZXJzIHwgICAgMyAgICB8ICAgRmFsbCB8CnwgU3RhdGlzdGljcyB3aXRoIFIgfCAgICA0ICAgIHwgU3ByaW5nIHwKfCBPT0Qgd2l0aCBDKysgICAgICB8ICAgIDQgICAgfCBTdW1tZXIgfAoKLSAgIDotLSBtZWFucyB0aGUgY29sdW1uIGlzIGxlZnQgYWxpZ25lZAotICAgLS06IG1lYW5zIHRoZSBjb2x1bW4gaXMgcmlnaHQgYWxpZ25lZAotICAgOi06IG1lYW5zIHRoZSBjb2x1bW4gaXMgY2VudGVyIGFsaWduZWQKClRleHQgY2FuIGJlIGZvcm1hdHRlZCB3aXRoaW4gdGFibGVzIHVzaW5nIGdlbmVyYWwgbWFya2Rvd24uIEhvd2V2ZXIsIHNvbWUgZm9ybWF0dGluZyBvcHRpb25zIGFyZSBub3QgYXZhaWxhYmxlIHdpdGhpbiB0YWJsZXMsIGluY2x1ZGluZzoKCi0gICBFbWJlZGRlZCBSCi0gICBIZWFkaW5ncwotICAgQmxvY2txdW90ZXMKLSAgIEhvcml6b250YWwgTGluZXMKLSAgIEltYWdlcwotICAgTGlzdHMKLSAgIEVtYmVkZGVkIEhUTUwKCiMjIFN1bW1hcnkKClIgTWFya2Rvd24gaXMgYSB0b29sIHRoYXQgYWxsb3dzIHlvdSB0byBjb21iaW5lIHRleHQgYW5kIGNvZGUgdG8gY3JlYXRlIGRvY3VtZW50cyB0aGF0IGFyZSBib3RoIGh1bWFuLXJlYWRhYmxlIGFuZCBleGVjdXRhYmxlLiBSIE5vdGVib29rcyBhcmUgYSBzcGVjaWZpYyB0eXBlIG9mIFIgTWFya2Rvd24gZG9jdW1lbnQgdGhhdCBhcmUgZGVzaWduZWQgZm9yIGludGVyYWN0aXZlIGRhdGEgYW5hbHlzaXMgYW5kIHJlcHJvZHVjaWJsZSByZXNlYXJjaC4gQnkgdXNpbmcgUiBNYXJrZG93biBhbmQgUiBOb3RlYm9va3MsIHlvdSBjYW4gd3JpdGUgZG9jdW1lbnRzIHRoYXQgaW5jbHVkZSBjb2RlLCB0ZXh0LCBlcXVhdGlvbnMsIGZpZ3VyZXMsIGFuZCBpbnRlcmFjdGl2ZSB2aXN1YWxpemF0aW9ucywgbWFraW5nIGl0IGVhc3kgdG8gZG9jdW1lbnQgeW91ciBhbmFseXNpcyBwcm9jZXNzIGFuZCBzaGFyZSB5b3VyIHJlc3VsdHMgd2l0aCBvdGhlcnMuIEluIHRoaXMgdHV0b3JpYWwsIHlvdSdsbCBsZWFybiBob3cgdG8gY3JlYXRlIFIgTWFya2Rvd24gZG9jdW1lbnRzIGFuZCBSIE5vdGVib29rcywgYW5kIGhvdyB0byB1c2UgTWFya2Rvd24gc3ludGF4IHRvIGZvcm1hdCB5b3VyIHRleHQgYW5kIGVtYmVkIGNvZGUgY2h1bmtzIGluIHlvdXIgZG9jdW1lbnRzLgoKQ29tYmluaW5nIGNvZGUgYW5kIHRleHQgaW4gYSBNYXJrZG93biBkb2N1bWVudCBvZmZlcnMgc2V2ZXJhbCBiZW5lZml0czoKCi0gICAqKlJlcHJvZHVjaWJpbGl0eSoqOiBCeSBlbWJlZGRpbmcgY29kZSBpbiBhIE1hcmtkb3duIGRvY3VtZW50LCB5b3UgY2FuIGVuc3VyZSB0aGF0IG90aGVycyBjYW4gZWFzaWx5IHJlcHJvZHVjZSB5b3VyIHdvcmsuIFRoZXkgY2FuIHNlZSBleGFjdGx5IHdoYXQgY29kZSB5b3UgdXNlZCB0byBnZW5lcmF0ZSB5b3VyIHJlc3VsdHMsIGFuZCB0aGV5IGNhbiBydW4gdGhhdCBjb2RlIHRoZW1zZWx2ZXMgdG8gdmVyaWZ5IHlvdXIgZmluZGluZ3MuCgotICAgKipUcmFuc3BhcmVuY3kqKjogQnkgcHJvdmlkaW5nIGEgY2xlYXIgYW5kIGRldGFpbGVkIHJlY29yZCBvZiB5b3VyIGFuYWx5c2lzIHByb2Nlc3MsIHlvdSBjYW4gaW5jcmVhc2UgdHJhbnNwYXJlbmN5IGFuZCBidWlsZCB0cnVzdCB3aXRoIHlvdXIgYXVkaWVuY2UuIFRoaXMgaXMgZXNwZWNpYWxseSBpbXBvcnRhbnQgaW4gZmllbGRzIGxpa2UgZGF0YSBzY2llbmNlLCB3aGVyZSByZXByb2R1Y2liaWxpdHkgYW5kIHRyYW5zcGFyZW5jeSBhcmUgZXNzZW50aWFsLgoKLSAgICoqRG9jdW1lbnRhdGlvbioqOiBFbWJlZGRpbmcgY29kZSBpbiBhIE1hcmtkb3duIGRvY3VtZW50IGNhbiBhbHNvIG1ha2UgaXQgZWFzaWVyIHRvIGRvY3VtZW50IHlvdXIgd29yay4gQnkgaW5jbHVkaW5nIG5hcnJhdGl2ZSB0ZXh0IGFsb25nc2lkZSB5b3VyIGNvZGUsIHlvdSBjYW4gcHJvdmlkZSBjb250ZXh0IGFuZCBleHBsYW5hdGlvbnMgZm9yIHlvdXIgYW5hbHlzaXMsIG1ha2luZyBpdCBlYXNpZXIgZm9yIG90aGVycyB0byB1bmRlcnN0YW5kIGFuZCByZXBsaWNhdGUgeW91ciB3b3JrLgoKLSAgICoqUHJlc2VudGF0aW9uKio6IE1hcmtkb3duIGRvY3VtZW50cyBjYW4gYmUgZWFzaWx5IGNvbnZlcnRlZCBpbnRvIGEgdmFyaWV0eSBvZiBmb3JtYXRzLCBzdWNoIGFzIEhUTUwsIFBERiwgYW5kIFdvcmQgZG9jdW1lbnRzLiBUaGlzIG1ha2VzIGl0IGVhc3kgdG8gcHJlc2VudCB5b3VyIGFuYWx5c2lzIGluIGEgcG9saXNoZWQgYW5kIHByb2Zlc3Npb25hbCBtYW5uZXIsIHdpdGhvdXQgaGF2aW5nIHRvIG1hbnVhbGx5IGNvcHkgYW5kIHBhc3RlIHlvdXIgY29kZSBhbmQgcmVzdWx0cyBpbnRvIGEgc2VwYXJhdGUgZG9jdW1lbnQuCgpPdmVyYWxsLCBlbWJlZGRpbmcgY29kZSBpbiBhIE1hcmtkb3duIGRvY3VtZW50IGNhbiBtYWtlIHlvdXIgYW5hbHlzaXMgbW9yZSB0cmFuc3BhcmVudCwgcmVwcm9kdWNpYmxlLCBhbmQgd2VsbC1kb2N1bWVudGVkLCB3aGljaCBjYW4gaW1wcm92ZSB0aGUgcXVhbGl0eSBhbmQgY3JlZGliaWxpdHkgb2YgeW91ciBhbmFseXNpcy4KClRoaXMgbGVzc29uIHByb3ZpZGVkIGFuIGludHJvZHVjdGlvbi4gVGhlcmUgYXJlIG1hbnkgbW9yZSBhZHZhbmNlZCBtYXJrZG93biBhbmQgUiBOb3RlYm9vayB0ZWNobmlxdWVzLCBpbmNsdWRpbmcgd3JpdGluZyBib29rcyBhbmQgYnVpbGRpbmcgZnVsbCB3ZWJzaXRlcy4gSW4gZmFjdCwgdGhlIFs6YXJ0aWZpY2l1bV0oaHR0cDovL2FydGlmaWNpdW0udXMpIGxlc3NvbiByZXBvc2l0b3J5IHdhcyBmdWxsIGJ1aWx0IGluIFIgTm90ZWJvb2tzIGFuZCB0aGUgc291cmNlIGZvciB0aGlzIGxlc3NvbiBpcyBhbiBbUiBOb3RlYm9va10obC02LTIwNC5SbWQpLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKWGllLCBYLiwgRGVydmlldXgsIEMuLCBSaWVkZXJlciwgRS4gKG4uZC4pLiBSIE1hcmtkb3duIENvb2tib29rLiBBdmFpbGFibGUgYXQgW2Jvb2tkb3duLm9yZ10oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLWNvb2tib29rLykKCltPdmVydmlldyBvZiBSIE1hcmtkb3duXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS8pCgpbUiBNYXJrZG93biBDaGVhdCBTaGVldF0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDMvcm1hcmtkb3duLXJlZmVyZW5jZS5wZGY/X2dhPTIuNTkxODQxNzMuMTIxNDI1MjkyOC4xNjM1OTgwNDc0LTE5NDk5NTUxNy4xNjM1NDMzNzU3KQoKW1dpa2lwZWRpYTogTGl0ZXJhdGUgUHJvZ3JhbW1pbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xpdGVyYXRlX3Byb2dyYW1taW5nKQoKW0VtYmVkZGluZyBWZXJiYXRpbSBDb2RlIENodW5rcyBpbiBNYXJrZG93bl0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLWNvb2tib29rL3ZlcmJhdGltLWNvZGUtY2h1bmtzLmh0bWwpCgojIyBFcnJhdGEKCk5vbmUgY29sbGVjdGVkIHlldC4gTGV0IHVzIGtub3cuCgpgYGB7PWh0bWx9CjxzY3JpcHQgc3JjPSJodHRwczovL2Zvcm0uam90Zm9ybS5jb20vc3RhdGljL2ZlZWRiYWNrMi5qcyIgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KICBuZXcgSm90Zm9ybUZlZWRiYWNrKHsKICAgIGZvcm1JZDogIjIxMjE4NzA3Mjc4NDE1NyIsCiAgICBidXR0b25UZXh0OiAiRmVlZGJhY2siLAogICAgYmFzZTogImh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS8iLAogICAgYmFja2dyb3VuZDogIiNGNTkyMDIiLAogICAgZm9udENvbG9yOiAiI0ZGRkZGRiIsCiAgICBidXR0b25TaWRlOiAibGVmdCIsCiAgICBidXR0b25BbGlnbjogImNlbnRlciIsCiAgICB0eXBlOiBmYWxzZSwKICAgIHdpZHRoOiA3MDAsCiAgICBoZWlnaHQ6IDUwMCwKICAgIGlzQ2FyZEZvcm06IGZhbHNlCiAgfSk7Cjwvc2NyaXB0PgpgYGAKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2RlcGxveUtuaXQuUicpKSwgaW5jbHVkZSA9IEZBTFNFfQpgYGAK