1 Welcome

During this session you’ll get a brief introduction to R Markdown. You’ll learn about the basic building blocks of an R Markdown file and learn how to knit an HTML notebook using RStudio1.

1.1 Learning Objectives

The only pre-requisite is having R and RStudio installed on your computer since the needed packages are installed by default. You don’t need much R programming knowledge to produce professionally marked up documents.

After completing this lesson you should be able to:

  1. Create and edit an R Notebook from scratch.

  2. Knit an R Notebook containing commonly used R Markdown commands into an HTML document.

  3. Know where to get further information on more advanced R Markdown usage.

1.2 Source materials

The materials for this lesson are derived heavily from the following places which are excellent resources in their own right:

Some examples use the penguins dataset found in the palmerpenguins package (Horst, Hill, and Gorman 2020)

1.3 Why use R Markdown?

As an analyst you’ll regularly prepare reports to document your methods and communicate your findings. And these reports will likely contain a mixture of worded explanations, tables of data, and graphical figures. An R Markdown file, via the knitr2 package, allows you to embed code for generating graphs and figures amongst other explanatory text – all within the one source file. Should you wish to change some text or fix an error you can at the click of a button recompile a new .HTML, .PDF, or .DOCX report immediately.

Aside from the convenience of avoiding copy-pasting between different source documents, an R Notebook fully encapsulates your work and is easily shareable as reproducible research (see Peng 2014 for the distinction between reproducible and replicable). By sharing your R Notebook with collaborators or colleagues (sceptics?) they can take your data, code, and text, and reproduce the exact same analysis as you conducted.

source: “Piled Higher and Deeper” by Jorge Cham

According to Grolemund and Wickham (2017), R Markdown files are designed for use in three ways:

  1. Communicating to decision makers who focus on conclusions rather than the code behind your analysis.

  2. Collaborating with other analysts who are interested in both your conclusions and how you reached them.

  3. As an environment in which to conduct analysis; a modern day lab notebook where you can capture both what you did and what you were thinking at the time.

2 R Notebook Usage

2.1 Creating an R Notebook

RStudio includes all that you need to get started with creating an R Notebook. The rmarkdown3 package comes already installed. The steps below create a new (HTML) notebook with file extension .Rmd that’s pre-filled with some basic R Markdown content.

  1. Launch RStudio

  2. (Recommended) Create a new project (File, New Project…, New Directory )

  3. Click File menu

  4. Click New File \(\blacktriangleright\) R Markdown…

  5. Choose Document from the list and enter “My Notebook” and your name into the Title and Author fields respectively.

  6. Leave the Default Output Format as HTML and click OK.

From the steps above you might notice that R Markdown can be processed into various output types and formats, e.g., PDF Document, HTML slide presentation.

Exercise 1

  1. Create a new RStudio project called “my-project.”

  2. Create a new R Notebook entitled “My Notebook” with a Default Output Format of HTML.

  3. Save the notebook as my-notebook.Rmd.

  4. Identify the YAML header, formatted text, and any ‘code chunks.’

2.2 Structure of .Rmd files

From the exercise above you’ll have observed the three typical components of an R Markdown .Rmd file, briefly:

  • Formatted text

    Prose related to the presented analysis and results.

  • Code chunks

    Executable R code producing outputs for embedding into the final document.

  • YAML header

    Settings related to the generation of the final output document.

2.3 Running R code chunks

Run a code chunk by clicking the Run Current Chunk button (green arrow) within the chunk or (preferably) by placing the cursor inside the chunk and pressing Ctrl + Shift + Enter.

The output of the code chunk is displayed within the notebook inside the Source editor pane.

You can clear this output by clicking the Clear Output icon (small cross) found in the top right corner of the chunk output. You can also pop-out a separate output window or hide it altogether.

2.4 Knitting an R Notebook

‘Knitting’ an R Notebook means to compile it into an output document.

When you knit an R Notebook the .Rmd file is sent to knitr which executes any code chunks and creates an intermediate Markdown .md document. This .md file contains both the code and its output and is processed by pandoc4 into the finished file.

source: Grolemund and Wickham (2017)

The advantage of this two-step workflow is being able to create a wide range of output formats from the same .Rmd file. For example, slide presentations, dashboards, websites, and web apps.

To knit a notebook in RStudio, click the Knit button found in the toolbar of the Source editor pane, or use the keyboard shortcut Ctrl + Shift + K.

A preview of the knitted document will appear in its own window (or depending on your RStudio settings, in the Viewer pane).

Set your preferred preview location by clicking the white cog button and choosing Preview in Window or Preview in Viewer Pane.


Previewing an HTML Notebook

If the output type specified in the YAML header is html_notebook (rather than html_document as above) a Preview Notebook button appears instead of a Knit button. Preview Notebook shows you a rendered HTML copy of the contents of the Source editor pane without first executing any R code, i.e., it only renders whatever results are already shown in the pane.

Exercise 2

  1. Knit to HTML the notebook my-notebook.Rmd that you created in Exercise 1.

  2. Observe the correspondence between the R Markdown and the resultant document, particularly the R code embedded in the code chunks.

  3. Make some changes to the .Rmd file and re-knit the document. Perhaps delete some text or add head(cars) or str(cars) to an existing code chunk.

  4. Confirm that you can see the changes reflected in the re-knitted document.

TIP: Use the keyboard shortcut Ctrl + Shift + K to save and knit a notebook in a single action.

3 R Markdown Syntax

3.1 Formatted Text

Text in .Rmd files is written in pandoc R Markdown whose syntax is designed to be human-readable and suggestive of its final HTML rendering. In the examples below you’ll see that styled text is usually enclosed by special characters.

3.1.1 Headings

Headings are defined using hash # characters. The more hashes, the less prominent the heading.

# Level 1 heading
## Level 2 heading
### Level 3 heading

3.1.2 Inline text styles

Italic styling is applied using single asterisks or underscores: *italic* or _italic_

Bold styling is applied using double asterisks or underscores: **bold** or __bold__

Bold & italic styling is applied using triple asterisks or underscores: ***bold & italic*** or ___bold & italic___

Inline code styling is applied using backticks: `plot(penguins)`

Superscripting is applied using carets: S^uperscripting^

Subscripting is applied using tildes: S~ubscripting~

Strikethrough is applied using double tildes: ~~Strikethrough~~

3.1.3 Inline R code

R code can be embedded inline by surrounding it in backticks ` and inserting a single r character prefix. This code is executed and replaced with its output when the notebook is knitted.

The `cars` dataset has `r nrow(cars)` rows.

Output:

The cars dataset has 50 rows.

3.1.4 \(\LaTeX\) equations

Surrounding an expression with dollar symbols $ will have knitr interpret it as in-line \(\LaTeX\) formatting.

Sum of integer powers of a half is $\sum_{n=1}^{\infty} 2^{-n} = 1$

Output:

Sum of integer powers of a half is \(\sum_{n=1}^{\infty} 2^{-n} = 1\)

Using double dollar symbols $$ will centre the equation on its own line.

Sum of integer powers of a half is $$\sum_{n=1}^{\infty} 2^{-n} = 1$$

Output:

Sum of integer powers of a half is \[\sum_{n=1}^{\infty} 2^{-n} = 1\]

3.1.6 Footnotes

You can insert hyperlinked footnotes using square bracket and caret syntax [^footnoteID]. The footnote ID can be any string of characters without spaces.

The numbering of footnotes is done automatically upon knitting.

AIC[^aic] is used to evaluate the relative quality of models.

Output:

AIC5 is used to evaluate the relative quality of models.

The definition of the footnote must appear in the R Notebook somewhere after it is first mentioned in the text. Notice the colon : in the syntax.

[^aic]: AIC stands for Akaike Information Criterion.

The footnote itself appears at the end of the HTML document with a convenient hyperlink back to where it appears in the document.

3.1.7 Images

Images are inserted by providing a file path to the image, either a link to a locally stored file or a URL to an image hosted online. Notice the leading exclamation mark ! and caption in square parentheses []. Leave the square parentheses empty for no caption.

![source: [xkcd.com](https://xkcd.com/license.html)](https://imgs.xkcd.com/comics/purity.png)

Output:

source: xkcd.com

3.1.8 Unordered Lists

Items of an unordered list are prefixed with an asterisk *, hyphen -, or plus +. Increase the line spacing between bullet points by adding extra carriage returns and nest bullet points by prepending four blank spaces.

* An item

* Another item
    * Nested item
    * Another nested item

Output:

  • An item

  • Another item

    • Nested item
    • Another nested item

3.1.9 Ordered Lists

Ordered lists are prefixed with numbers or letters.

Notice that the numbering is incremented automatically in the output even if typed out of order.

1. First item
2. Second item
    a. First nested item
    
    a. Second nested item
    
1. Third item

Output:

  1. First item
  2. Second item
    1. First nested item

    2. Second nested item

  3. Third item

3.1.10 Block quotations

Block quotations are created by prefixing each line with the greater-than symbol >.

> First level of quoting
>
> > Nested block quotation
>
> Back to the first level

Output:

First level of quoting

Nested block quotation

Back to the first level

3.1.11 Tables

Manually create a static table using hyphens - and pipes | to indicate the header row and columns respectively. Rows are terminated by a carriage return.

First Header  | Second Header | Third Header
------------- | ------------- | ------------
Cell content  | Cell content  | Cell content
Cell content  | Cell content  | Cell content

Output:

First Header Second Header Third Header
Cell content Cell content Cell content
Cell content Cell content Cell content

Tabular code output

If the output of a code chunk is a table of values, R Markdown will render it accordingly.

```{r}
head(penguins)
```

Output:

head(penguins)
## # A tibble: 6 x 8
##   species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex  
##   <fct>   <fct>           <dbl>         <dbl>            <int>       <int> <fct>
## 1 Adelie  Torge~           39.1          18.7              181        3750 male 
## 2 Adelie  Torge~           39.5          17.4              186        3800 fema~
## 3 Adelie  Torge~           40.3          18                195        3250 fema~
## 4 Adelie  Torge~           NA            NA                 NA          NA <NA> 
## 5 Adelie  Torge~           36.7          19.3              193        3450 fema~
## 6 Adelie  Torge~           39.3          20.6              190        3650 male 
## # ... with 1 more variable: year <int>

To get nicer looking tables we can use the kable() function from the knitr package.

```{r}
kable(head(penguins))
```

Output:

kable(head(penguins))
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex year
Adelie Torgersen 39.1 18.7 181 3750 male 2007
Adelie Torgersen 39.5 17.4 186 3800 female 2007
Adelie Torgersen 40.3 18.0 195 3250 female 2007
Adelie Torgersen NA NA NA NA NA 2007
Adelie Torgersen 36.7 19.3 193 3450 female 2007
Adelie Torgersen 39.3 20.6 190 3650 male 2007

3.1.12 Horizontal rules

Horizontal rules are inserted using three or more consecutive asterisks * or hyphens -.

---

Output:


Exercise 3

Remember to re-knit the notebook to see your changes.

  1. Put a horizontal rule underneath the content in your R notebook from Exercise 2 (my-notebook.Rmd).

  2. Below the horizontal rule insert some text with inline R code, e.g., Mean bill length is `r mean(penguins$bill_length_mm)`

  3. Insert a heading called “Table of Contents”

  4. Under the heading, use an ordered list with nesting to create the outline of a typical scientific report, e.g., Introduction, Data Description, Methodology, etc.

    You’ll see how to insert a nicer, autogenerated Table of Contents later.

  5. Format some of the list items using the text styles mentioned above.

  6. Insert a footnote into your notebook and include in its body a link to RStudio’s RMarkdown tutorial.

Exercise 4 (Optional)

  1. Use \(\LaTeX\) syntax to insert Pythagoras’ theorem or Euler’s identity into your notebook.

3.2 Code Chunks

Code is inserted into R Notebooks in ‘code chunks.’ Upon knitting, these chunks are executed and their results inserted directly into the finished document. Embedding code alongside prose annotations of your methods and results speaks to the ethos of reproducible research.

Code chunks are enclosed by three backticks ``` with a prefix of curly parentheses {} containing parameters for that chunk (if any).

```{r Structure of penguins dataset}
install.packages("palmerpenguins")
library(palmerpenguins)
str(penguins)
```

In the above example the first parameter r indicates that the chunk contains R code. knitr provides support for many other languages such as Bash, Perl, SQL, Python, and Julia.

After the r is an optional name for this chunk. This helps with finding the chunk in the code navigator found in the bottom left of the Source editor pane.

The knitted notebook will therefore include both the code and its output one after the other.

Output:

str(penguins)
## tibble [344 x 8] (S3: tbl_df/tbl/data.frame)
##  $ species          : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ island           : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ bill_length_mm   : num [1:344] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
##  $ bill_depth_mm    : num [1:344] 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
##  $ flipper_length_mm: int [1:344] 181 186 195 NA 193 190 181 195 193 190 ...
##  $ body_mass_g      : int [1:344] 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
##  $ sex              : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
##  $ year             : int [1:344] 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...

Exercise 5

  1. Add a new R chunk by clicking in your notebook where you want to insert the chunk and clicking the Insert button on the toolbar.

    Alternatively use the Ctrl + Shift + I keyboard shortcut.

  2. Name this chunk “summary penguins” and confirm that name appears in the code chunk navigation menu.

  3. Add this R code into the chunk: summary(penguins).

  4. Run the chunk by clicking the Run Current Chunk button or by pressing Ctrl + Shift + Enter.

  5. Insert and run a couple more code chunks containing R code of your choosing.

  6. Knit your notebook to HTML and check that the output is as you’d expect.

3.2.1 Chunk options

You can list in the curly parentheses {} various options for changing how a chunk is knitted into the final document.

See https://yihui.name/knitr/options for all the available options; only a few commonly used options are shown here.

a) Show the code and the output (default)

```{r}
colMeans(penguins[,3:6], na.rm = TRUE)
```

Output:

colMeans(penguins[,3:6], na.rm = TRUE)
##    bill_length_mm     bill_depth_mm flipper_length_mm       body_mass_g 
##          43.92193          17.15117         200.91520        4201.75439

b) eval=FALSE shows the code but does not execute it

```{r, eval=FALSE}
colMeans(penguins[,3:6], na.rm = TRUE)
```

Output:

colMeans(penguins[,3:6], na.rm = TRUE)

c) echo=FALSE shows the output but does not show the code

```{r, echo=FALSE}
colMeans(penguins[,3:6], na.rm = TRUE)
```

Output:

##    bill_length_mm     bill_depth_mm flipper_length_mm       body_mass_g 
##          43.92193          17.15117         200.91520        4201.75439

d) include=FALSE executes the code but does not show anything

```{r, include=FALSE}
colMeans(penguins[,3:6], na.rm = TRUE)
```

Output:

The setup chunk

A special code chunk (if it exists) is the one named setup. The setup chunk is automatically run just before any other code chunk is executed. It is useful for loading R librarys and data used subsequent analyses.

```{r setup, include=FALSE} 
library(knitr)
library(palmerpenguins)
```

Recall that include=FALSE prevents the setup chunk from inserting any output into the knitted document.

Exercise 6

  1. Duplicate (copy-paste) the code chunk from Exercise 5 but specify a different output option from amongst those mentioned above. Observe the different output in the knitted document.

    HINT: instead of manually typing the output options, RStudio provides a shortcut by clicking the Modify Chunk Options icon (grey cog) found in the top right corner of the chunk next to the Run Current Chunk button.

    The popup also has a Chunk options link to documentation on available chunk options.

  2. Repeat for some other output options, observing their effect on the knitted output.

3.2.2 Figure options

Below is an example of a chunk that produces a figure rather than numerical output, namely a boxplot of bill lengths (millimetres) from the penguins dataset.

```{r bill length boxplot, echo=FALSE} 
boxplot(bill_length_mm ~ species, data = penguins, col = hcl.colors(3), main = "Penguin Bill Lengths")
```

Output:

We can resize the plot using the fig.height and fig.width chunk options.

```{r bill length boxplot echo=FALSE, fig.height=3, fig.width=3} 
boxplot(bill_length_mm ~ species, data = penguins, col = hcl.colors(3), main = "Penguin Bill Lengths")
```

Output:

Other useful options include:

  • fig.asp for setting the figure aspect ratio

  • fig.dim for specifying the figure width and height as a (width, height) tuple

  • fig.align for aligning the figure to the left, right, or centre of the page

See https://yihui.name/knitr/options/#plots for an extensive list.

Exercise 7

Check these exercises by re-running the edited code chunk and re-knitting the whole notebook. Sometimes the preview and document are different!

HINT: You may need to check the online documentation mentioned above.

  1. Duplicate (copy-paste) the code chunk of one of the figures in your notebook (renaming it if necessary) and use the fig.asp figure option to set its aspect ratio to be square, i.e., 1:1.

  2. Now apply the fig.align option to centre it on the page.

  3. On a fresh duplicate of the code chunk, use fig.dim to resize the figure to a width of 4 inches and height of 6 inches.

3.3 YAML Header

At the top of a .Rmd file, enclosed by triple hyphens ---, is the YAML6 header. It defines settings that affect the entire document, in particular specifying the output type.

Below is the default YAML header created by RStudio for new R Notebooks. It sets the R Markdown file to knit to an HTML notebook html_notebook.

---
title: "R Notebook"
output: html_notebook
---

Other document output types include PDF, Word, and HTML documents (distinct from HTML notebook). Note that PDF output requires \(\LaTeX\) (see the tinytex R package) and you obviously need Microsoft Word or an equivalent to preview Word outputs.

---
title: "R Document"
output:
  pdf_document: default
  word_document: default
  html_document: default
---

Alternatively, you can produce a slide deck by setting the output parameter to be beamer_presentation, ioslides_presentation, or slidy_presentation.

---
title: "R Slideshow"
output:
  beamer_presentation: default
  ioslides_presentation: default
  slidy_presentation: default
---

See Chapter 4 of Xie, Allaire, and Grolemund (2018) for a full breakdown of these types.

HTML document settings

The focus of this lesson is knitting HTML documents (the html_document output type). There are many settings available as illustrated by the YAML header used in the .Rmd file for this lesson:

---
title: "Introduction to R Markdown"
author: "[Shih Ching Fu](https://shihchingfu.com)"
date: "July 2021"
bibliography: ref.bib
output:
  #slidy_presentation: default
  html_document:
    toc: true
    toc_depth: 3
    toc_float: 
      collapsed: true
      smooth_scroll: true
    number_sections: true
    theme: readable
    highlight: haddock
    code_download: true
knit: 
  (function(input_file, encoding) {
    rmarkdown::render(input_file,
                      encoding=encoding,
                      output_file=file.path(dirname(input_file), 'docs', 'index.html'))})
---

Many of these options also accessible via the “Output options…” item under the R Markdown format options menu (gear icon) in the source pane.

See Part II of Xie, Allaire, and Grolemund (2018) for full details of options for various output types.

3.4 Bibliographies

R Markdown supports common bibliography formats such as BibTeX, BibLaTeX, and EndNote.

The path to the bibliography file must be specified in the YAML header under the bibliography field.

---
title: "Introduction to R Markdown"
author: "[Shih Ching Fu](https://shihchingfu.com)"
date: "April 2021"
bibliography: ref.bib
---

Here’s a sample BibTeX record from the abovementioned ref.bib file:

@book{xie2018RGuide, 
      author = "Yihui Xie and J.J. Allaire and Garrett Grolemund",
      title = "R Markdown: The Definitive Guide",
      year = "2018",
      publisher = "CRC Press",
      url = "https://bookdown.org/yihui/rmarkdown/"}

In-text citations are inserted using the at sign @ followed by the citation key.

Part II of @xie2018RGuide describes the various output formats available with R Markdown.

Output:

Part II of Xie, Allaire, and Grolemund (2018) describes the various output formats available with R Markdown.

4 RStudio Visual Editor

Since version 1.4, RStudio has a “Visual Editor” mode for the Source pane. It is akin to the what you see is what you get (WYSIWIG) experience that comes with a word processor like Microsoft Word.

You can enable it from the format options menu (gear icon) in the source pane.

With this mode turned on the Source pane now shows a toolbar that has pretty much all the formatting options that are described above.

You might ask why bother with learning R markdown syntax now that there is a visual editor? Well, the choice is entirely up to you and indeed you can swap between them as you feel inclined. I’ve even it used it as a learning tool by composing a notebook in the Visual Editor and then inspecting the R Markdown syntax that is generated underneath!

Full documentation is available here: https://rstudio.github.io/visual-markdown-editing/.

5 End of the beginning

There is much more to R Markdown than what’s covered here!

The sources mentioned in the bibliography below are good starting points for further developing your R Markdown expertise. Galleries such as https://yihui.name/knitr/demo/showcase/ are also a great place to start.

RStudio also provides ‘cheatsheets’ that are accessible from the Help menu. These are a convenient printable reference of commonly used syntax and commands.

May the knitr be with you.

6 R Session Info

## - Session info ---------------------------------------------------------------
##  setting  value                       
##  version  R version 4.1.0 (2021-05-18)
##  os       Windows 10 x64              
##  system   x86_64, mingw32             
##  ui       RTerm                       
##  language (EN)                        
##  collate  English_Australia.1252      
##  ctype    English_Australia.1252      
##  tz       Australia/Perth             
##  date     2021-07-01                  
## 
## - Packages -------------------------------------------------------------------
##  package        * version date       lib source        
##  bslib            0.2.5.1 2021-05-18 [1] CRAN (R 4.1.0)
##  cachem           1.0.5   2021-05-15 [1] CRAN (R 4.1.0)
##  callr            3.7.0   2021-04-20 [1] CRAN (R 4.1.0)
##  cli              2.5.0   2021-04-26 [1] CRAN (R 4.1.0)
##  crayon           1.4.1   2021-02-08 [1] CRAN (R 4.1.0)
##  desc             1.3.0   2021-03-05 [1] CRAN (R 4.1.0)
##  devtools         2.4.1   2021-05-05 [1] CRAN (R 4.1.0)
##  digest           0.6.27  2020-10-24 [1] CRAN (R 4.1.0)
##  ellipsis         0.3.2   2021-04-29 [1] CRAN (R 4.1.0)
##  evaluate         0.14    2019-05-28 [1] CRAN (R 4.1.0)
##  fansi            0.5.0   2021-05-25 [1] CRAN (R 4.1.0)
##  fastmap          1.1.0   2021-01-25 [1] CRAN (R 4.1.0)
##  fs               1.5.0   2020-07-31 [1] CRAN (R 4.1.0)
##  glue             1.4.2   2020-08-27 [1] CRAN (R 4.1.0)
##  highr            0.9     2021-04-16 [1] CRAN (R 4.1.0)
##  htmltools        0.5.1.1 2021-01-22 [1] CRAN (R 4.1.0)
##  jquerylib        0.1.4   2021-04-26 [1] CRAN (R 4.1.0)
##  jsonlite         1.7.2   2020-12-09 [1] CRAN (R 4.1.0)
##  knitr          * 1.33    2021-04-24 [1] CRAN (R 4.1.0)
##  lifecycle        1.0.0   2021-02-15 [1] CRAN (R 4.1.0)
##  magrittr         2.0.1   2020-11-17 [1] CRAN (R 4.1.0)
##  memoise          2.0.0   2021-01-26 [1] CRAN (R 4.1.0)
##  palmerpenguins * 0.1.0   2020-07-23 [1] CRAN (R 4.1.0)
##  pillar           1.6.1   2021-05-16 [1] CRAN (R 4.1.0)
##  pkgbuild         1.2.0   2020-12-15 [1] CRAN (R 4.1.0)
##  pkgconfig        2.0.3   2019-09-22 [1] CRAN (R 4.1.0)
##  pkgload          1.2.1   2021-04-06 [1] CRAN (R 4.1.0)
##  prettyunits      1.1.1   2020-01-24 [1] CRAN (R 4.1.0)
##  processx         3.5.2   2021-04-30 [1] CRAN (R 4.1.0)
##  ps               1.6.0   2021-02-28 [1] CRAN (R 4.1.0)
##  purrr            0.3.4   2020-04-17 [1] CRAN (R 4.1.0)
##  R6               2.5.0   2020-10-28 [1] CRAN (R 4.1.0)
##  remotes          2.4.0   2021-06-02 [1] CRAN (R 4.1.0)
##  rlang            0.4.11  2021-04-30 [1] CRAN (R 4.1.0)
##  rmarkdown        2.8     2021-05-07 [1] CRAN (R 4.1.0)
##  rprojroot        2.0.2   2020-11-15 [1] CRAN (R 4.1.0)
##  rstudioapi       0.13    2020-11-12 [1] CRAN (R 4.1.0)
##  sass             0.4.0   2021-05-12 [1] CRAN (R 4.1.0)
##  sessioninfo      1.1.1   2018-11-05 [1] CRAN (R 4.1.0)
##  stringi          1.6.2   2021-05-17 [1] CRAN (R 4.1.0)
##  stringr          1.4.0   2019-02-10 [1] CRAN (R 4.1.0)
##  testthat         3.0.2   2021-02-14 [1] CRAN (R 4.1.0)
##  tibble           3.1.2   2021-05-16 [1] CRAN (R 4.1.0)
##  usethis          2.0.1   2021-02-10 [1] CRAN (R 4.1.0)
##  utf8             1.2.1   2021-03-12 [1] CRAN (R 4.1.0)
##  vctrs            0.3.8   2021-04-29 [1] CRAN (R 4.1.0)
##  withr            2.4.2   2021-04-18 [1] CRAN (R 4.1.0)
##  xfun             0.23    2021-05-15 [1] CRAN (R 4.1.0)
##  yaml             2.2.1   2020-02-01 [1] CRAN (R 4.1.0)
## 
## [1] C:/Users/shihc/OneDrive/Documents/R/win-library/4.1
## [2] C:/Program Files/R/R-4.1.0/library

References

Grolemund, Garrett, and Hadley Wickham. 2017. R for Data Science. O’Reilly Media. https://r4ds.had.co.nz/.
Horst, Allison Marie, Alison Presmanes Hill, and Kristen B Gorman. 2020. Palmerpenguins: Palmer Archipelago (Antarctica) Penguin Data. https://doi.org/10.5281/zenodo.3960218.
Peng, Roger. 2014. “The Real Reason Reproducible Research Is Important.” https://simplystatistics.org/2014/06/06/the-real-reason-reproducible-research-is-important/.
Wright, Thomas, and Naupaka Zimmerman, eds. 2016. “Software Carpentry: R for Reproducible Scientific Analysis.” https://doi.org/10.5281/zenodo.57520.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown.

  1. RStudio, https://www.rstudio.com/↩︎

  2. knitr, http://yihui.name/knitr/↩︎

  3. rmarkdown, https://pkgs.rstudio.com/rmarkdown/index.html↩︎

  4. pandoc, http://pandoc.org/↩︎

  5. AIC stands for Akaike Information Criterion.↩︎

  6. YAML stands for YAML Ain’t Markup Language. It’s a recursive name!↩︎

LS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byBSIE1hcmtkb3duIg0KYXV0aG9yOiAiW1NoaWggQ2hpbmcgRnVdKGh0dHBzOi8vc2hpaGNoaW5nZnUuY29tKSINCmRhdGU6ICJKdWx5IDIwMjEiDQpiaWJsaW9ncmFwaHk6IHJlZi5iaWINCm91dHB1dDoNCiAgI3NsaWR5X3ByZXNlbnRhdGlvbjogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICB0aGVtZTogcmVhZGFibGUNCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQprbml0OiANCiAgKGZ1bmN0aW9uKGlucHV0X2ZpbGUsIGVuY29kaW5nKSB7DQogICAgcm1hcmtkb3duOjpyZW5kZXIoaW5wdXRfZmlsZSwNCiAgICAgICAgICAgICAgICAgICAgICBlbmNvZGluZz1lbmNvZGluZywNCiAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRfZmlsZT1maWxlLnBhdGgoZGlybmFtZShpbnB1dF9maWxlKSwgJ2RvY3MnLCAnaW5kZXguaHRtbCcpKX0pDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShwYWxtZXJwZW5ndWlucykNCmBgYA0KDQojIFdlbGNvbWUNCg0KRHVyaW5nIHRoaXMgc2Vzc2lvbiB5b3UnbGwgZ2V0IGEgYnJpZWYgaW50cm9kdWN0aW9uIHRvIFIgTWFya2Rvd24uIFlvdSdsbCBsZWFybiBhYm91dCB0aGUgYmFzaWMgYnVpbGRpbmcgYmxvY2tzIG9mIGFuIFIgTWFya2Rvd24gZmlsZSBhbmQgbGVhcm4gaG93IHRvIGtuaXQgYW4gSFRNTCBub3RlYm9vayB1c2luZyBSU3R1ZGlvW15yc3R1ZGlvXS4NCg0KW15yc3R1ZGlvXTogUlN0dWRpbywgaHR0cHM6Ly93d3cucnN0dWRpby5jb20vDQoNCjxjZW50ZXI+DQohW10oLi9pbWcvcnN0dWRpby5wbmcpICFbXSguL2ltZy9ybWFya2Rvd24ucG5nKSAhW10oLi9pbWcva25pdHIucG5nKQ0KPC9jZW50ZXI+DQoNCg0KIyMgTGVhcm5pbmcgT2JqZWN0aXZlcw0KDQpUaGUgb25seSBwcmUtcmVxdWlzaXRlIGlzIGhhdmluZyBSIGFuZCBSU3R1ZGlvIGluc3RhbGxlZCBvbiB5b3VyIGNvbXB1dGVyIHNpbmNlIHRoZSBuZWVkZWQgcGFja2FnZXMgYXJlIGluc3RhbGxlZCBieSBkZWZhdWx0LiBZb3UgZG9u4oCZdCBuZWVkIG11Y2ggUiBwcm9ncmFtbWluZyBrbm93bGVkZ2UgdG8gcHJvZHVjZSBwcm9mZXNzaW9uYWxseSBtYXJrZWQgdXAgZG9jdW1lbnRzLg0KDQpBZnRlciBjb21wbGV0aW5nIHRoaXMgbGVzc29uIHlvdSBzaG91bGQgYmUgYWJsZSB0bzoNCg0KMS4gQ3JlYXRlIGFuZCBlZGl0IGFuIFIgTm90ZWJvb2sgZnJvbSBzY3JhdGNoLg0KDQoyLiBLbml0IGFuIFIgTm90ZWJvb2sgY29udGFpbmluZyBjb21tb25seSB1c2VkIFIgTWFya2Rvd24gY29tbWFuZHMgaW50byBhbiBIVE1MIGRvY3VtZW50Lg0KDQozLiBLbm93IHdoZXJlIHRvIGdldCBmdXJ0aGVyIGluZm9ybWF0aW9uIG9uIG1vcmUgYWR2YW5jZWQgUiBNYXJrZG93biB1c2FnZS4NCg0KDQojIyBTb3VyY2UgbWF0ZXJpYWxzDQoNClRoZSBtYXRlcmlhbHMgZm9yIHRoaXMgbGVzc29uIGFyZSBkZXJpdmVkIGhlYXZpbHkgZnJvbSB0aGUgZm9sbG93aW5nIHBsYWNlcyB3aGljaCBhcmUgZXhjZWxsZW50IHJlc291cmNlcyBpbiB0aGVpciBvd24gcmlnaHQ6DQoNCiogW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei8pIFtAZ3JvbGVtdW5kMjAxN1JTY2llbmNlXSANCg0KKiBbUiBmb3IgUmVwcm9kdWNpYmxlIFNjaWVudGlmaWMgQW5hbHlzaXNdKGh0dHA6Ly9zd2NhcnBlbnRyeS5naXRodWIuaW8vci1ub3ZpY2UtZ2FwbWluZGVyLykgW0B3cmlnaHQyMDE2UkFuYWx5c2lzXQ0KDQoqIFtSIE1hcmtkb3duOiBUaGUgRGVmaW5pdGl2ZSBHdWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykgW0B4aWUyMDE4Ukd1aWRlXQ0KDQoqIFtybWFya2Rvd246IER5bmFtaWMgRG9jdW1lbnRzIGZvciBSXShodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9ybWFya2Rvd24pIChHaXRIdWIgcGFnZSkNCg0KU29tZSBleGFtcGxlcyB1c2UgdGhlIGBwZW5ndWluc2AgZGF0YXNldCBmb3VuZCBpbiB0aGUgYHBhbG1lcnBlbmd1aW5zYCBwYWNrYWdlIFtAcGFsbWVycGVuZ3VpbnNdDQoNCiMjIFdoeSB1c2UgUiBNYXJrZG93bj8NCg0KQXMgYW4gYW5hbHlzdCB5b3UnbGwgcmVndWxhcmx5IHByZXBhcmUgcmVwb3J0cyB0byBkb2N1bWVudCB5b3VyIG1ldGhvZHMgYW5kIGNvbW11bmljYXRlIHlvdXIgZmluZGluZ3MuIEFuZCB0aGVzZSByZXBvcnRzIHdpbGwgbGlrZWx5IGNvbnRhaW4gYSBtaXh0dXJlIG9mIHdvcmRlZCBleHBsYW5hdGlvbnMsIHRhYmxlcyBvZiBkYXRhLCBhbmQgZ3JhcGhpY2FsIGZpZ3VyZXMuIEFuIFIgTWFya2Rvd24gZmlsZSwgdmlhIHRoZSBga25pdHJgW15rbml0cl0gcGFja2FnZSwgYWxsb3dzIHlvdSB0byBlbWJlZCBjb2RlIGZvciBnZW5lcmF0aW5nIGdyYXBocyBhbmQgZmlndXJlcyBhbW9uZ3N0IG90aGVyIGV4cGxhbmF0b3J5IHRleHQgLS0gYWxsIHdpdGhpbiB0aGUgb25lIHNvdXJjZSBmaWxlLiBTaG91bGQgeW91IHdpc2ggdG8gY2hhbmdlIHNvbWUgdGV4dCBvciBmaXggYW4gZXJyb3IgeW91IGNhbiBhdCB0aGUgY2xpY2sgb2YgYSBidXR0b24gcmVjb21waWxlIGEgbmV3IGAuSFRNTGAsIGAuUERGYCwgb3IgYC5ET0NYYCByZXBvcnQgaW1tZWRpYXRlbHkuDQoNCkFzaWRlIGZyb20gdGhlIGNvbnZlbmllbmNlIG9mIGF2b2lkaW5nIGNvcHktcGFzdGluZyBiZXR3ZWVuIGRpZmZlcmVudCBzb3VyY2UgZG9jdW1lbnRzLCBhbiBSIE5vdGVib29rIGZ1bGx5IGVuY2Fwc3VsYXRlcyB5b3VyIHdvcmsgYW5kIGlzIGVhc2lseSBzaGFyZWFibGUgYXMgcmVwcm9kdWNpYmxlIHJlc2VhcmNoIFtzZWUgQHBlbmcyMDE0VGhlSW1wb3J0YW50IGZvciB0aGUgZGlzdGluY3Rpb24gYmV0d2VlbiByZXByb2R1Y2libGUgYW5kIHJlcGxpY2FibGVdLiBCeSBbc2hhcmluZ10oaHR0cHM6Ly9naXRodWIuY29tL3NoaWhjaGluZ2Z1L2ludHJvLXRvLXJtZC9ibG9iL21hc3Rlci9pbnRyby10by1ybWQuUm1kKSB5b3VyIFIgTm90ZWJvb2sgd2l0aCBjb2xsYWJvcmF0b3JzIG9yIGNvbGxlYWd1ZXMgKHNjZXB0aWNzPykgdGhleSBjYW4gdGFrZSB5b3VyIGRhdGEsIGNvZGUsIGFuZCB0ZXh0LCBhbmQgcmVwcm9kdWNlIHRoZSBleGFjdCBzYW1lIGFuYWx5c2lzIGFzIHlvdSBjb25kdWN0ZWQuDQoNCltea25pdHJdOiBrbml0ciwgaHR0cDovL3lpaHVpLm5hbWUva25pdHIvDQoNCjxjZW50ZXI+DQpbIVtzb3VyY2U6ICJQaWxlZCBIaWdoZXIgYW5kIERlZXBlciIgYnkgSm9yZ2UgQ2hhbV0oLi9pbWcvcGhkMDMxMjE0cy5wbmcpXShodHRwczovL3BoZGNvbWljcy5jb20vY29taWNzL2FyY2hpdmUucGhwP2NvbWljaWQ9MTY4OSkNCjwvY2VudGVyPg0KDQpBY2NvcmRpbmcgdG8gQGdyb2xlbXVuZDIwMTdSU2NpZW5jZSwgUiBNYXJrZG93biBmaWxlcyBhcmUgZGVzaWduZWQgZm9yIHVzZSBpbiB0aHJlZSB3YXlzOg0KDQoxLiBDb21tdW5pY2F0aW5nIHRvIGRlY2lzaW9uIG1ha2VycyB3aG8gZm9jdXMgb24gY29uY2x1c2lvbnMgcmF0aGVyIHRoYW4gdGhlIGNvZGUgYmVoaW5kIHlvdXIgYW5hbHlzaXMuDQoNCjIuIENvbGxhYm9yYXRpbmcgd2l0aCBvdGhlciBhbmFseXN0cyB3aG8gYXJlIGludGVyZXN0ZWQgaW4gKmJvdGgqIHlvdXIgY29uY2x1c2lvbnMgYW5kIGhvdyB5b3UgcmVhY2hlZCB0aGVtLg0KDQozLiBBcyBhbiBlbnZpcm9ubWVudCBpbiB3aGljaCB0byBjb25kdWN0IGFuYWx5c2lzOyBhIG1vZGVybiBkYXkgbGFiIG5vdGVib29rIHdoZXJlIHlvdSBjYW4gY2FwdHVyZSBib3RoIHdoYXQgeW91IGRpZCBhbmQgd2hhdCB5b3Ugd2VyZSB0aGlua2luZyBhdCB0aGUgdGltZS4NCg0KDQojIFIgTm90ZWJvb2sgVXNhZ2UNCg0KDQojIyBDcmVhdGluZyBhbiBSIE5vdGVib29rDQoNClJTdHVkaW8gaW5jbHVkZXMgYWxsIHRoYXQgeW91IG5lZWQgdG8gZ2V0IHN0YXJ0ZWQgd2l0aCBjcmVhdGluZyBhbiBSIE5vdGVib29rLiBUaGUgYHJtYXJrZG93bmBbXnJtZHBrZ10gcGFja2FnZSBjb21lcyBhbHJlYWR5IGluc3RhbGxlZC4gVGhlIHN0ZXBzIGJlbG93IGNyZWF0ZSBhIG5ldyAoSFRNTCkgbm90ZWJvb2sgd2l0aCBmaWxlIGV4dGVuc2lvbiBgLlJtZGAgdGhhdCdzIHByZS1maWxsZWQgd2l0aCBzb21lIGJhc2ljIFIgTWFya2Rvd24gY29udGVudC4NCg0KW15ybWRwa2ddOiBybWFya2Rvd24sIGh0dHBzOi8vcGtncy5yc3R1ZGlvLmNvbS9ybWFya2Rvd24vaW5kZXguaHRtbA0KDQoxLiBMYXVuY2ggUlN0dWRpbw0KDQoyLiAoUmVjb21tZW5kZWQpIENyZWF0ZSBhIG5ldyBwcm9qZWN0ICgqRmlsZSosICpOZXcgUHJvamVjdC4uLiosICpOZXcgRGlyZWN0b3J5KiApDQoNCjIuIENsaWNrICpGaWxlKiBtZW51DQoNCjMuIENsaWNrICpOZXcgRmlsZSogJFxibGFja3RyaWFuZ2xlcmlnaHQkICpSIE1hcmtkb3duLi4uKg0KDQogICAhW10oLi9pbWcvY3JlYXRlbmV3cm1hcmtkb3duLnBuZykNCg0KNC4gQ2hvb3NlICpEb2N1bWVudCogZnJvbSB0aGUgbGlzdCBhbmQgZW50ZXIgIk15IE5vdGVib29rIiBhbmQgeW91ciBuYW1lIGludG8gdGhlICpUaXRsZSogYW5kICpBdXRob3IqIGZpZWxkcyByZXNwZWN0aXZlbHkuDQoNCiAgICFbXSguL2ltZy9uZXdtYXJrZG93bmRpYWxvZy5wbmcpDQoNCjUuIExlYXZlIHRoZSAqRGVmYXVsdCBPdXRwdXQgRm9ybWF0KiBhcyAqSFRNTCogYW5kIGNsaWNrICpPSyouDQoNCkZyb20gdGhlIHN0ZXBzIGFib3ZlIHlvdSBtaWdodCBub3RpY2UgdGhhdCBSIE1hcmtkb3duIGNhbiBiZSBwcm9jZXNzZWQgaW50byB2YXJpb3VzIG91dHB1dCB0eXBlcyBhbmQgZm9ybWF0cywgZS5nLiwgUERGIERvY3VtZW50LCBIVE1MIHNsaWRlIHByZXNlbnRhdGlvbi4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjZWVjMjc1MTA7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkICNlZWMyNzUiPg0KKipFeGVyY2lzZSAxKioNCg0KMS4gQ3JlYXRlIGEgbmV3IFJTdHVkaW8gcHJvamVjdCBjYWxsZWQgIm15LXByb2plY3QiLg0KDQoyLiBDcmVhdGUgYSBuZXcgUiBOb3RlYm9vayBlbnRpdGxlZCAiTXkgTm90ZWJvb2siIHdpdGggYSAqRGVmYXVsdCBPdXRwdXQgRm9ybWF0KiBvZiAqSFRNTCouDQoNCjMuIFNhdmUgdGhlIG5vdGVib29rIGFzIGBteS1ub3RlYm9vay5SbWRgLg0KDQogICAhW10oLi9pbWcvbXlub3RlYm9vay5wbmcpDQoNCjQuIElkZW50aWZ5IHRoZSBZQU1MIGhlYWRlciwgZm9ybWF0dGVkIHRleHQsIGFuZCBhbnkgJ2NvZGUgY2h1bmtzJy4NCg0KPC9kaXY+PC9wPg0KDQoNCiMjIFN0cnVjdHVyZSBvZiBgLlJtZGAgZmlsZXMNCg0KRnJvbSB0aGUgZXhlcmNpc2UgYWJvdmUgeW91J2xsIGhhdmUgb2JzZXJ2ZWQgdGhlIHRocmVlIHR5cGljYWwgY29tcG9uZW50cyBvZiBhbiBSIE1hcmtkb3duIGAuUm1kYCBmaWxlLCBicmllZmx5Og0KDQorICoqRm9ybWF0dGVkIHRleHQqKg0KDQogIFByb3NlIHJlbGF0ZWQgdG8gdGhlIHByZXNlbnRlZCBhbmFseXNpcyBhbmQgcmVzdWx0cy4NCg0KKyAqKkNvZGUgY2h1bmtzKioNCg0KICBFeGVjdXRhYmxlIFIgY29kZSBwcm9kdWNpbmcgb3V0cHV0cyBmb3IgZW1iZWRkaW5nIGludG8gdGhlIGZpbmFsIGRvY3VtZW50Lg0KDQorICoqWUFNTCBoZWFkZXIqKg0KDQogIFNldHRpbmdzIHJlbGF0ZWQgdG8gdGhlIGdlbmVyYXRpb24gb2YgdGhlIGZpbmFsIG91dHB1dCBkb2N1bWVudC4NCg0KDQojIyBSdW5uaW5nIFIgY29kZSBjaHVua3MNCg0KUnVuIGEgY29kZSBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biBDdXJyZW50IENodW5rKiBidXR0b24gKGdyZWVuIGFycm93KSB3aXRoaW4gdGhlIGNodW5rIG9yIChwcmVmZXJhYmx5KSBieSBwbGFjaW5nIHRoZSBjdXJzb3IgaW5zaWRlIHRoZSBjaHVuayBhbmQgcHJlc3NpbmcgPGtiZD5DdHJsPC9rYmQ+ICsgPGtiZD5TaGlmdDwva2JkPiArIDxrYmQ+RW50ZXI8L2tiZD4uDQoNCjxjZW50ZXI+DQohW10oLi9pbWcvcnVuY2h1bmsucG5nKQ0KPC9jZW50ZXI+DQoNClRoZSBvdXRwdXQgb2YgdGhlIGNvZGUgY2h1bmsgaXMgZGlzcGxheWVkIHdpdGhpbiB0aGUgbm90ZWJvb2sgaW5zaWRlIHRoZSAqU291cmNlKiBlZGl0b3IgcGFuZS4NCg0KWW91IGNhbiBjbGVhciB0aGlzIG91dHB1dCBieSBjbGlja2luZyB0aGUgKkNsZWFyIE91dHB1dCogaWNvbiAoc21hbGwgY3Jvc3MpIGZvdW5kIGluIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIHRoZSBjaHVuayBvdXRwdXQuIFlvdSBjYW4gYWxzbyBwb3Atb3V0IGEgc2VwYXJhdGUgb3V0cHV0IHdpbmRvdyBvciBoaWRlIGl0IGFsdG9nZXRoZXIuDQoNCjxjZW50ZXI+DQohW10oLi9pbWcvY2xlYXJjaHVua291dHB1dC5wbmcpDQo8L2NlbnRlcj4NCg0KDQojIyBLbml0dGluZyBhbiBSIE5vdGVib29rDQoNCidLbml0dGluZycgYW4gUiBOb3RlYm9vayBtZWFucyB0byBjb21waWxlIGl0IGludG8gYW4gb3V0cHV0IGRvY3VtZW50Lg0KDQpXaGVuIHlvdSBrbml0IGFuIFIgTm90ZWJvb2sgdGhlIGAuUm1kYCBmaWxlIGlzIHNlbnQgdG8gYGtuaXRyYCB3aGljaCBleGVjdXRlcyBhbnkgY29kZSBjaHVua3MgYW5kIGNyZWF0ZXMgYW4gaW50ZXJtZWRpYXRlIE1hcmtkb3duIGAubWRgIGRvY3VtZW50LiBUaGlzIGAubWRgIGZpbGUgY29udGFpbnMgYm90aCB0aGUgY29kZSBhbmQgaXRzIG91dHB1dCBhbmQgaXMgcHJvY2Vzc2VkIGJ5IGBwYW5kb2NgW15wYW5kb2NdIGludG8gdGhlIGZpbmlzaGVkIGZpbGUuIA0KDQpbXnBhbmRvY106IHBhbmRvYywgaHR0cDovL3BhbmRvYy5vcmcvDQoNCjxjZW50ZXI+DQohW3NvdXJjZTogQGdyb2xlbXVuZDIwMTdSU2NpZW5jZV0oLi9pbWcvcm1hcmtkb3duZmxvdy5wbmcpDQoNCjwvY2VudGVyPg0KDQpUaGUgYWR2YW50YWdlIG9mIHRoaXMgdHdvLXN0ZXAgd29ya2Zsb3cgaXMgYmVpbmcgYWJsZSB0byBjcmVhdGUgYSB3aWRlIHJhbmdlIG9mIG91dHB1dCBmb3JtYXRzIGZyb20gdGhlIHNhbWUgYC5SbWRgIGZpbGUuIEZvciBleGFtcGxlLCBzbGlkZSBwcmVzZW50YXRpb25zLCBkYXNoYm9hcmRzLCB3ZWJzaXRlcywgYW5kIHdlYiBhcHBzLg0KDQpUbyBrbml0IGEgbm90ZWJvb2sgaW4gUlN0dWRpbywgY2xpY2sgdGhlICpLbml0KiBidXR0b24gZm91bmQgaW4gdGhlIHRvb2xiYXIgb2YgdGhlICpTb3VyY2UqIGVkaXRvciBwYW5lLCBvciB1c2UgdGhlIGtleWJvYXJkIHNob3J0Y3V0IDxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+U2hpZnQ8L2tiZD4gKyA8a2JkPks8L2tiZD4uDQoNCjxjZW50ZXI+DQohW10oLi9pbWcva25pdG5vdGVib29rLnBuZykNCjwvY2VudGVyPg0KDQpBIHByZXZpZXcgb2YgdGhlIGtuaXR0ZWQgZG9jdW1lbnQgd2lsbCBhcHBlYXIgaW4gaXRzIG93biB3aW5kb3cgKG9yIGRlcGVuZGluZyBvbiB5b3VyIFJTdHVkaW8gc2V0dGluZ3MsIGluIHRoZSAqVmlld2VyKiBwYW5lKS4gDQoNClNldCB5b3VyIHByZWZlcnJlZCBwcmV2aWV3IGxvY2F0aW9uIGJ5IGNsaWNraW5nIHRoZSB3aGl0ZSBjb2cgYnV0dG9uIGFuZCBjaG9vc2luZyAqUHJldmlldyBpbiBXaW5kb3cqIG9yICpQcmV2aWV3IGluIFZpZXdlciBQYW5lKi4NCg0KPGNlbnRlcj4NCiFbXSguL2ltZy9wcmV2aWV3aW52aWV3ZXIucG5nKQ0KPC9jZW50ZXI+DQo8YnI+DQoNCiMjIyMgUHJldmlld2luZyBhbiBIVE1MICpOb3RlYm9vayogey19DQoNCklmIHRoZSBvdXRwdXQgdHlwZSBzcGVjaWZpZWQgaW4gdGhlIFlBTUwgaGVhZGVyIGlzIGBodG1sX25vdGVib29rYCAocmF0aGVyIHRoYW4gYGh0bWxfZG9jdW1lbnRgIGFzIGFib3ZlKSBhICpQcmV2aWV3IE5vdGVib29rKiBidXR0b24gYXBwZWFycyBpbnN0ZWFkIG9mIGEgKktuaXQqIGJ1dHRvbi4gKlByZXZpZXcgTm90ZWJvb2sqIHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlICpTb3VyY2UqIGVkaXRvciBwYW5lIHdpdGhvdXQgZmlyc3QgZXhlY3V0aW5nIGFueSBSIGNvZGUsIGkuZS4sICBpdCBvbmx5IHJlbmRlcnMgd2hhdGV2ZXIgcmVzdWx0cyBhcmUgYWxyZWFkeSBzaG93biBpbiB0aGUgcGFuZS4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjZWVjMjc1MTA7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkICNlZWMyNzUiPg0KKipFeGVyY2lzZSAyKioNCg0KMS4gS25pdCB0byBIVE1MIHRoZSBub3RlYm9vayBgbXktbm90ZWJvb2suUm1kYCB0aGF0IHlvdSBjcmVhdGVkIGluIEV4ZXJjaXNlIDEuDQoNCjIuIE9ic2VydmUgdGhlIGNvcnJlc3BvbmRlbmNlIGJldHdlZW4gdGhlIFIgTWFya2Rvd24gYW5kIHRoZSByZXN1bHRhbnQgZG9jdW1lbnQsIHBhcnRpY3VsYXJseSB0aGUgUiBjb2RlIGVtYmVkZGVkIGluIHRoZSBjb2RlIGNodW5rcy4NCg0KMy4gTWFrZSBzb21lIGNoYW5nZXMgdG8gdGhlIGAuUm1kYCBmaWxlIGFuZCByZS1rbml0IHRoZSBkb2N1bWVudC4gUGVyaGFwcyBkZWxldGUgc29tZSB0ZXh0IG9yIGFkZCBgaGVhZChjYXJzKWAgb3IgYHN0cihjYXJzKWAgdG8gYW4gZXhpc3RpbmcgY29kZSBjaHVuay4NCg0KNC4gQ29uZmlybSB0aGF0IHlvdSBjYW4gc2VlIHRoZSBjaGFuZ2VzIHJlZmxlY3RlZCBpbiB0aGUgcmUta25pdHRlZCBkb2N1bWVudC4NCg0KVElQOiBVc2UgdGhlIGtleWJvYXJkIHNob3J0Y3V0IDxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+U2hpZnQ8L2tiZD4gKyA8a2JkPks8L2tiZD4gdG8gc2F2ZSBhbmQga25pdCBhIG5vdGVib29rIGluIGEgc2luZ2xlIGFjdGlvbi4NCg0KPC9kaXY+PC9wPg0KDQoNCiMgUiBNYXJrZG93biBTeW50YXgNCg0KDQojIyBGb3JtYXR0ZWQgVGV4dA0KDQpUZXh0IGluIGAuUm1kYCBmaWxlcyBpcyB3cml0dGVuIGluIGBwYW5kb2NgIFIgTWFya2Rvd24gd2hvc2Ugc3ludGF4IGlzIGRlc2lnbmVkIHRvIGJlIGh1bWFuLXJlYWRhYmxlIGFuZCBzdWdnZXN0aXZlIG9mIGl0cyBmaW5hbCBIVE1MIHJlbmRlcmluZy4gSW4gdGhlIGV4YW1wbGVzIGJlbG93IHlvdSdsbCBzZWUgdGhhdCBzdHlsZWQgdGV4dCBpcyB1c3VhbGx5IGVuY2xvc2VkIGJ5IHNwZWNpYWwgY2hhcmFjdGVycy4gDQoNCg0KIyMjIEhlYWRpbmdzDQoNCkhlYWRpbmdzIGFyZSBkZWZpbmVkIHVzaW5nIGhhc2ggYCNgIGNoYXJhY3RlcnMuIFRoZSBtb3JlIGhhc2hlcywgdGhlIGxlc3MgcHJvbWluZW50IHRoZSBoZWFkaW5nLg0KDQp+fn4NCiMgTGV2ZWwgMSBoZWFkaW5nDQp+fn4NCg0Kfn5+DQojIyBMZXZlbCAyIGhlYWRpbmcNCn5+fg0KDQp+fn4NCiMjIyBMZXZlbCAzIGhlYWRpbmcNCn5+fg0KDQoNCiMjIyBJbmxpbmUgdGV4dCBzdHlsZXMNCg0KKkl0YWxpYyogc3R5bGluZyBpcyBhcHBsaWVkIHVzaW5nIHNpbmdsZSBhc3Rlcmlza3Mgb3IgdW5kZXJzY29yZXM6IGAqaXRhbGljKmAgb3IgYF9pdGFsaWNfYA0KDQoqKkJvbGQqKiBzdHlsaW5nIGlzIGFwcGxpZWQgdXNpbmcgZG91YmxlIGFzdGVyaXNrcyBvciB1bmRlcnNjb3JlczogYCoqYm9sZCoqYCBvciAgYF9fYm9sZF9fYA0KDQoqKipCb2xkICYgaXRhbGljKioqIHN0eWxpbmcgaXMgYXBwbGllZCB1c2luZyB0cmlwbGUgYXN0ZXJpc2tzIG9yIHVuZGVyc2NvcmVzOiBgKioqYm9sZCAmIGl0YWxpYyoqKmAgb3IgIGBfX19ib2xkICYgaXRhbGljX19fYA0KDQpgSW5saW5lIGNvZGVgIHN0eWxpbmcgaXMgYXBwbGllZCB1c2luZyBiYWNrdGlja3M6IGBgIGBwbG90KHBlbmd1aW5zKWAgYGANCg0KU151cGVyc2NyaXB0aW5nXiBpcyBhcHBsaWVkIHVzaW5nIGNhcmV0czogYFNedXBlcnNjcmlwdGluZ15gDQoNClN+dWJzY3JpcHRpbmd+IGlzIGFwcGxpZWQgdXNpbmcgdGlsZGVzOiBgU351YnNjcmlwdGluZ35gDQoNCn5+U3RyaWtldGhyb3VnaH5+IGlzIGFwcGxpZWQgdXNpbmcgZG91YmxlIHRpbGRlczogYH5+U3RyaWtldGhyb3VnaH5+YA0KDQoNCiMjIyBJbmxpbmUgUiBjb2RlDQoNClIgY29kZSBjYW4gYmUgZW1iZWRkZWQgaW5saW5lIGJ5IHN1cnJvdW5kaW5nIGl0IGluIGJhY2t0aWNrcyBgYCBgIGBgIGFuZCBpbnNlcnRpbmcgYSBzaW5nbGUgYHJgIGNoYXJhY3RlciBwcmVmaXguIFRoaXMgY29kZSBpcyBleGVjdXRlZCBhbmQgcmVwbGFjZWQgd2l0aCBpdHMgb3V0cHV0IHdoZW4gdGhlIG5vdGVib29rIGlzIGtuaXR0ZWQuDQoNCn5+fg0KVGhlIGBjYXJzYCBkYXRhc2V0IGhhcyBgYHIgJ3IgbnJvdyhjYXJzKSdgYCByb3dzLg0Kfn5+DQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KVGhlIGBjYXJzYCBkYXRhc2V0IGhhcyBgciBucm93KGNhcnMpYCByb3dzLg0KDQo8L2Rpdj48L3A+DQoNCg0KIyMjICRcTGFUZVgkIGVxdWF0aW9ucw0KDQpTdXJyb3VuZGluZyBhbiBleHByZXNzaW9uIHdpdGggZG9sbGFyIHN5bWJvbHMgYCRgIHdpbGwgaGF2ZSBga25pdHJgIGludGVycHJldCBpdCBhcyBpbi1saW5lICRcTGFUZVgkIGZvcm1hdHRpbmcuIA0KDQp+fn4NClN1bSBvZiBpbnRlZ2VyIHBvd2VycyBvZiBhIGhhbGYgaXMgJFxzdW1fe249MX1ee1xpbmZ0eX0gMl57LW59ID0gMSQNCn5+fg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNClN1bSBvZiBpbnRlZ2VyIHBvd2VycyBvZiBhIGhhbGYgaXMgJFxzdW1fe249MX1ee1xpbmZ0eX0gMl57LW59ID0gMSQNCjwvZGl2PjwvcD4NCg0KVXNpbmcgZG91YmxlIGRvbGxhciBzeW1ib2xzIGAkJGAgd2lsbCBjZW50cmUgdGhlIGVxdWF0aW9uIG9uIGl0cyBvd24gbGluZS4gDQoNCn5+fg0KU3VtIG9mIGludGVnZXIgcG93ZXJzIG9mIGEgaGFsZiBpcyAkJFxzdW1fe249MX1ee1xpbmZ0eX0gMl57LW59ID0gMSQkDQp+fn4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMEVFMDU7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkIGJsdWUiPg0KT3V0cHV0Og0KDQpTdW0gb2YgaW50ZWdlciBwb3dlcnMgb2YgYSBoYWxmIGlzICQkXHN1bV97bj0xfV57XGluZnR5fSAyXnstbn0gPSAxJCQNCjwvZGl2PjwvcD4NCg0KDQojIyMgTGlua3MNCg0KQ2xpY2thYmxlIFVSTHMgYXJlIGluc2VydGVkIGJ5IGVuY2xvc2luZyB0aGUgVVJMIGluIGdyZWF0ZXItdGhhbiBgPGAgYW5kIGxlc3MtdGhhbiBgPmAgc3ltYm9scy4gDQoNCn5+fg0KPGh0dHA6Ly9leGFtcGxlLmNvbT4NCn5+fg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCjxodHRwOi8vZXhhbXBsZS5jb20+DQoNCjwvZGl2PjwvcD4NCg0KTGlua2VkIHRleHQgaXMgZW5jbG9zZWQgaW4gc3F1YXJlIHBhcmVudGhlc2VzIGBbXWAgZm9sbG93ZWQgYnkgdGhlIFVSTCBpbiByb3VuZCBwYXJlbnRoZXNlcyBgKClgLg0KDQp+fn4NCltoeXBlcnRleHQgbGlua10oaHR0cDovL2V4YW1wbGUuY29tKQ0Kfn5+DQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KW2h5cGVydGV4dCBsaW5rXShodHRwOi8vZXhhbXBsZS5jb20pDQo8L2Rpdj48L3A+DQoNCg0KIyMjIEZvb3Rub3Rlcw0KDQpZb3UgY2FuIGluc2VydCBoeXBlcmxpbmtlZCBmb290bm90ZXMgdXNpbmcgc3F1YXJlIGJyYWNrZXQgYW5kIGNhcmV0IHN5bnRheCBgW15mb290bm90ZUlEXWAuIFRoZSBmb290bm90ZSBJRCBjYW4gYmUgYW55IHN0cmluZyBvZiBjaGFyYWN0ZXJzIHdpdGhvdXQgc3BhY2VzLiANCg0KVGhlIG51bWJlcmluZyBvZiBmb290bm90ZXMgaXMgZG9uZSBhdXRvbWF0aWNhbGx5IHVwb24ga25pdHRpbmcuDQoNCn5+fg0KQUlDW15haWNdIGlzIHVzZWQgdG8gZXZhbHVhdGUgdGhlIHJlbGF0aXZlIHF1YWxpdHkgb2YgbW9kZWxzLg0Kfn5+DQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KQUlDW15haWNdIGlzIHVzZWQgdG8gZXZhbHVhdGUgdGhlIHJlbGF0aXZlIHF1YWxpdHkgb2YgbW9kZWxzLg0KDQo8L2Rpdj48L3A+DQoNClRoZSBkZWZpbml0aW9uIG9mIHRoZSBmb290bm90ZSBtdXN0IGFwcGVhciBpbiB0aGUgUiBOb3RlYm9vayBzb21ld2hlcmUgX2FmdGVyXyBpdCBpcyBmaXJzdCBtZW50aW9uZWQgaW4gdGhlIHRleHQuIE5vdGljZSB0aGUgY29sb24gYDpgIGluIHRoZSBzeW50YXguDQoNCn5+fg0KW15haWNdOiBBSUMgc3RhbmRzIGZvciBBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uLg0Kfn5+DQoNClteYWljXTogQUlDIHN0YW5kcyBmb3IgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbi4NCg0KVGhlIGZvb3Rub3RlIGl0c2VsZiBhcHBlYXJzIGF0IHRoZSBlbmQgb2YgdGhlIEhUTUwgZG9jdW1lbnQgd2l0aCBhIGNvbnZlbmllbnQgaHlwZXJsaW5rIGJhY2sgdG8gd2hlcmUgaXQgYXBwZWFycyBpbiB0aGUgZG9jdW1lbnQuDQoNCg0KIyMjIEltYWdlcw0KIA0KSW1hZ2VzIGFyZSBpbnNlcnRlZCBieSBwcm92aWRpbmcgYSBmaWxlIHBhdGggdG8gdGhlIGltYWdlLCBlaXRoZXIgYSBsaW5rIHRvIGEgbG9jYWxseSBzdG9yZWQgZmlsZSBvciBhIFVSTCB0byBhbiBpbWFnZSBob3N0ZWQgb25saW5lLiBOb3RpY2UgdGhlIGxlYWRpbmcgZXhjbGFtYXRpb24gbWFyayBgIWAgYW5kIGNhcHRpb24gaW4gc3F1YXJlIHBhcmVudGhlc2VzIGBbXWAuIExlYXZlIHRoZSBzcXVhcmUgcGFyZW50aGVzZXMgZW1wdHkgZm9yIG5vIGNhcHRpb24uDQoNCn5+fg0KIVtzb3VyY2U6IFt4a2NkLmNvbV0oaHR0cHM6Ly94a2NkLmNvbS9saWNlbnNlLmh0bWwpXShodHRwczovL2ltZ3MueGtjZC5jb20vY29taWNzL3B1cml0eS5wbmcpDQp+fn4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMEVFMDU7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkIGJsdWUiPg0KT3V0cHV0Og0KDQohW3NvdXJjZTogW3hrY2QuY29tXShodHRwczovL3hrY2QuY29tL2xpY2Vuc2UuaHRtbCldKC4vaW1nL3B1cml0eS5wbmcpDQoNCjwvZGl2PjwvcD4NCg0KDQojIyMgVW5vcmRlcmVkIExpc3RzDQoNCkl0ZW1zIG9mIGFuIHVub3JkZXJlZCBsaXN0IGFyZSBwcmVmaXhlZCB3aXRoIGFuIGFzdGVyaXNrIGAqYCwgaHlwaGVuIGAtYCwgb3IgcGx1cyBgK2AuIEluY3JlYXNlIHRoZSBsaW5lIHNwYWNpbmcgYmV0d2VlbiBidWxsZXQgcG9pbnRzIGJ5IGFkZGluZyBleHRyYSBjYXJyaWFnZSByZXR1cm5zIGFuZCBuZXN0IGJ1bGxldCBwb2ludHMgYnkgcHJlcGVuZGluZyBmb3VyIGJsYW5rIHNwYWNlcy4NCg0Kfn5+DQoqIEFuIGl0ZW0NCg0KKiBBbm90aGVyIGl0ZW0NCiAgICAqIE5lc3RlZCBpdGVtDQogICAgKiBBbm90aGVyIG5lc3RlZCBpdGVtDQp+fn4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMEVFMDU7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkIGJsdWUiPg0KT3V0cHV0Og0KDQoqIEFuIGl0ZW0NCg0KKiBBbm90aGVyIGl0ZW0NCiAgICAqIE5lc3RlZCBpdGVtDQogICAgKiBBbm90aGVyIG5lc3RlZCBpdGVtDQoNCjwvZGl2PjwvcD4NCg0KDQojIyMgT3JkZXJlZCBMaXN0cw0KDQpPcmRlcmVkIGxpc3RzIGFyZSBwcmVmaXhlZCB3aXRoIG51bWJlcnMgb3IgbGV0dGVycy4gDQoNCk5vdGljZSB0aGF0IHRoZSBudW1iZXJpbmcgaXMgaW5jcmVtZW50ZWQgYXV0b21hdGljYWxseSBpbiB0aGUgb3V0cHV0IGV2ZW4gaWYgdHlwZWQgb3V0IG9mIG9yZGVyLg0KDQp+fn4NCjEuIEZpcnN0IGl0ZW0NCjIuIFNlY29uZCBpdGVtDQogICAgYS4gRmlyc3QgbmVzdGVkIGl0ZW0NCiAgICANCiAgICBhLiBTZWNvbmQgbmVzdGVkIGl0ZW0NCiAgICANCjEuIFRoaXJkIGl0ZW0NCn5+fg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCjEuIEZpcnN0IGl0ZW0NCjIuIFNlY29uZCBpdGVtDQogICAgYS4gRmlyc3QgbmVzdGVkIGl0ZW0NCiAgICANCiAgICBhLiBTZWNvbmQgbmVzdGVkIGl0ZW0NCiAgICANCjEuIFRoaXJkIGl0ZW0NCg0KPC9kaXY+PC9wPg0KDQoNCiMjIyBCbG9jayBxdW90YXRpb25zDQoNCkJsb2NrIHF1b3RhdGlvbnMgYXJlIGNyZWF0ZWQgYnkgcHJlZml4aW5nIGVhY2ggbGluZSB3aXRoIHRoZSBncmVhdGVyLXRoYW4gc3ltYm9sIGA+YC4NCg0Kfn5+DQo+IEZpcnN0IGxldmVsIG9mIHF1b3RpbmcNCj4NCj4gPiBOZXN0ZWQgYmxvY2sgcXVvdGF0aW9uDQo+DQo+IEJhY2sgdG8gdGhlIGZpcnN0IGxldmVsDQp+fn4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMEVFMDU7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkIGJsdWUiPg0KT3V0cHV0Og0KDQo+IEZpcnN0IGxldmVsIG9mIHF1b3RpbmcNCj4NCj4gPiBOZXN0ZWQgYmxvY2sgcXVvdGF0aW9uDQo+DQo+IEJhY2sgdG8gdGhlIGZpcnN0IGxldmVsDQoNCjwvZGl2PjwvcD4NCg0KDQojIyMgVGFibGVzDQoNCk1hbnVhbGx5IGNyZWF0ZSBhIHN0YXRpYyB0YWJsZSB1c2luZyBoeXBoZW5zIGAtYCBhbmQgcGlwZXMgYHxgIHRvIGluZGljYXRlIHRoZSBoZWFkZXIgcm93IGFuZCBjb2x1bW5zIHJlc3BlY3RpdmVseS4gUm93cyBhcmUgdGVybWluYXRlZCBieSBhIGNhcnJpYWdlIHJldHVybi4NCg0Kfn5+DQpGaXJzdCBIZWFkZXIgIHwgU2Vjb25kIEhlYWRlciB8IFRoaXJkIEhlYWRlcg0KLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0NCkNlbGwgY29udGVudCAgfCBDZWxsIGNvbnRlbnQgIHwgQ2VsbCBjb250ZW50DQpDZWxsIGNvbnRlbnQgIHwgQ2VsbCBjb250ZW50ICB8IENlbGwgY29udGVudA0Kfn5+DQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KRmlyc3QgSGVhZGVyICB8IFNlY29uZCBIZWFkZXIgfCBUaGlyZCBIZWFkZXINCi0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tDQpDZWxsIGNvbnRlbnQgIHwgQ2VsbCBjb250ZW50ICB8IENlbGwgY29udGVudA0KQ2VsbCBjb250ZW50ICB8IENlbGwgY29udGVudCAgfCBDZWxsIGNvbnRlbnQNCg0KPC9kaXY+PC9wPg0KDQoNCiMjIyMgVGFidWxhciBjb2RlIG91dHB1dCB7LX0NCg0KSWYgdGhlIG91dHB1dCBvZiBhIGNvZGUgY2h1bmsgaXMgYSB0YWJsZSBvZiB2YWx1ZXMsIFIgTWFya2Rvd24gd2lsbCByZW5kZXIgaXQgYWNjb3JkaW5nbHkuDQoNCmBgYGANCmBgYHtyfWByICcnYA0KaGVhZChwZW5ndWlucykNCmBgYA0KYGBgYA0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMEVFMDU7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkIGJsdWUiPg0KT3V0cHV0Og0KDQpgYGB7cn0NCmhlYWQocGVuZ3VpbnMpDQpgYGANCg0KPC9kaXY+PC9wPg0KDQpUbyBnZXQgbmljZXIgbG9va2luZyB0YWJsZXMgd2UgY2FuIHVzZSB0aGUgYGthYmxlKClgIGZ1bmN0aW9uIGZyb20gdGhlIGBrbml0cmAgcGFja2FnZS4NCg0KYGBgYA0KYGBge3J9YHIgJydgDQprYWJsZShoZWFkKHBlbmd1aW5zKSkNCmBgYA0KYGBgYA0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCmBgYHtyfQ0Ka2FibGUoaGVhZChwZW5ndWlucykpDQpgYGANCg0KPC9kaXY+PC9wPg0KDQoNCiMjIyBIb3Jpem9udGFsIHJ1bGVzDQoNCkhvcml6b250YWwgcnVsZXMgYXJlIGluc2VydGVkIHVzaW5nIHRocmVlIG9yIG1vcmUgY29uc2VjdXRpdmUgYXN0ZXJpc2tzIGAqYCBvciBoeXBoZW5zIGAtYC4NCg0Kfn5+DQotLS0NCn5+fg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCi0tLQ0KDQo8L2Rpdj48L3A+DQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogI2VlYzI3NTEwOyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCAjZWVjMjc1Ij4NCioqRXhlcmNpc2UgMyoqDQoNClJlbWVtYmVyIHRvIF9fcmUta25pdF9fIHRoZSBub3RlYm9vayB0byBzZWUgeW91ciBjaGFuZ2VzLg0KDQoxLiBQdXQgYSBob3Jpem9udGFsIHJ1bGUgdW5kZXJuZWF0aCB0aGUgY29udGVudCBpbiB5b3VyIFIgbm90ZWJvb2sgZnJvbSBFeGVyY2lzZSAyIChgbXktbm90ZWJvb2suUm1kYCkuDQoNCjIuIEJlbG93IHRoZSBob3Jpem9udGFsIHJ1bGUgaW5zZXJ0IHNvbWUgdGV4dCB3aXRoIGlubGluZSBSIGNvZGUsIGUuZy4sIGBgIE1lYW4gYmlsbCBsZW5ndGggaXMgYHINCm1lYW4ocGVuZ3VpbnMkYmlsbF9sZW5ndGhfbW0pYCBgYA0KDQoyLiBJbnNlcnQgYSBoZWFkaW5nIGNhbGxlZCAiVGFibGUgb2YgQ29udGVudHMiDQoNCjMuIFVuZGVyIHRoZSBoZWFkaW5nLCB1c2UgYW4gb3JkZXJlZCBsaXN0IHdpdGggbmVzdGluZyB0byBjcmVhdGUgdGhlIG91dGxpbmUgb2YgYSB0eXBpY2FsIHNjaWVudGlmaWMgcmVwb3J0LCBlLmcuLCBJbnRyb2R1Y3Rpb24sIERhdGEgRGVzY3JpcHRpb24sIE1ldGhvZG9sb2d5LCBldGMuDQoNCiAgIFlvdSdsbCBzZWUgaG93IHRvIGluc2VydCBhIG5pY2VyLCBhdXRvZ2VuZXJhdGVkIFRhYmxlIG9mIENvbnRlbnRzIGxhdGVyLg0KDQo0LiBGb3JtYXQgc29tZSBvZiB0aGUgbGlzdCBpdGVtcyB1c2luZyB0aGUgdGV4dCBzdHlsZXMgbWVudGlvbmVkIGFib3ZlLg0KDQo1LiBJbnNlcnQgYSBmb290bm90ZSBpbnRvIHlvdXIgbm90ZWJvb2sgYW5kIGluY2x1ZGUgaW4gaXRzIGJvZHkgYSBsaW5rIHRvIFJTdHVkaW8ncyBbUk1hcmtkb3duIHR1dG9yaWFsXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tMS5odG1sKS4NCg0KPC9kaXY+PC9wPg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNlZWMyNzUxMDsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgI2VlYzI3NSI+DQoqKkV4ZXJjaXNlIDQgKE9wdGlvbmFsKSoqDQoNCjEuIFVzZSAkXExhVGVYJCBzeW50YXggdG8gaW5zZXJ0IFB5dGhhZ29yYXMnIHRoZW9yZW0gb3IgRXVsZXIncyBpZGVudGl0eSBpbnRvIHlvdXIgbm90ZWJvb2suDQoNCjwvZGl2PjwvcD4NCg0KDQojIyBDb2RlIENodW5rcw0KDQpDb2RlIGlzIGluc2VydGVkIGludG8gUiBOb3RlYm9va3MgaW4gJ2NvZGUgY2h1bmtzJy4gVXBvbiBrbml0dGluZywgdGhlc2UgY2h1bmtzIGFyZSBleGVjdXRlZCBhbmQgdGhlaXIgcmVzdWx0cyBpbnNlcnRlZCBkaXJlY3RseSBpbnRvIHRoZSBmaW5pc2hlZCBkb2N1bWVudC4gRW1iZWRkaW5nIGNvZGUgYWxvbmdzaWRlIHByb3NlIGFubm90YXRpb25zIG9mIHlvdXIgbWV0aG9kcyBhbmQgcmVzdWx0cyBzcGVha3MgdG8gdGhlIGV0aG9zIG9mIHJlcHJvZHVjaWJsZSByZXNlYXJjaC4NCg0KQ29kZSBjaHVua3MgYXJlIGVuY2xvc2VkIGJ5IHRocmVlIGJhY2t0aWNrcyBgYCBgYGAgYGAgd2l0aCBhIHByZWZpeCBvZiBjdXJseSBwYXJlbnRoZXNlcyBge31gIGNvbnRhaW5pbmcgcGFyYW1ldGVycyBmb3IgdGhhdCBjaHVuayAoaWYgYW55KS4gDQoNCmBgYGANCmBgYHtyIFN0cnVjdHVyZSBvZiBwZW5ndWlucyBkYXRhc2V0fWByICcnYA0KaW5zdGFsbC5wYWNrYWdlcygicGFsbWVycGVuZ3VpbnMiKQ0KbGlicmFyeShwYWxtZXJwZW5ndWlucykNCnN0cihwZW5ndWlucykNCmBgYA0KYGBgYA0KDQpJbiB0aGUgYWJvdmUgZXhhbXBsZSB0aGUgZmlyc3QgcGFyYW1ldGVyIGByYCBpbmRpY2F0ZXMgdGhhdCB0aGUgY2h1bmsgY29udGFpbnMgUiBjb2RlLiBga25pdHJgIHByb3ZpZGVzIHN1cHBvcnQgZm9yIG1hbnkgb3RoZXIgbGFuZ3VhZ2VzIHN1Y2ggYXMgQmFzaCwgUGVybCwgU1FMLCBQeXRob24sIGFuZCBKdWxpYS4NCg0KQWZ0ZXIgdGhlIGByYCBpcyBhbiBvcHRpb25hbCBuYW1lIGZvciB0aGlzIGNodW5rLiBUaGlzIGhlbHBzIHdpdGggZmluZGluZyB0aGUgY2h1bmsgaW4gdGhlIGNvZGUgbmF2aWdhdG9yIGZvdW5kIGluIHRoZSBib3R0b20gbGVmdCBvZiB0aGUgKlNvdXJjZSogZWRpdG9yIHBhbmUuDQoNCjxjZW50ZXI+DQohW10oLi9pbWcvbmFtZWRjaHVuay5wbmcpDQo8L2NlbnRlcj4NCg0KVGhlIGtuaXR0ZWQgbm90ZWJvb2sgd2lsbCB0aGVyZWZvcmUgaW5jbHVkZSBib3RoIHRoZSBjb2RlIGFuZCBpdHMgb3V0cHV0IG9uZSBhZnRlciB0aGUgb3RoZXIuDQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KYGBge3IgU3RydWN0dXJlIG9mIHBlbmd1aW5zIGRhdGFzZXR9DQpzdHIocGVuZ3VpbnMpDQpgYGANCg0KPC9kaXY+PC9wPg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNlZWMyNzUxMDsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgI2VlYzI3NSI+DQoqKkV4ZXJjaXNlIDUqKg0KDQoxLiBBZGQgYSBuZXcgUiBjaHVuayBieSBjbGlja2luZyBpbiB5b3VyIG5vdGVib29rIHdoZXJlIHlvdSB3YW50IHRvIGluc2VydCB0aGUgY2h1bmsgYW5kIGNsaWNraW5nIHRoZSAqSW5zZXJ0KiBidXR0b24gb24gdGhlIHRvb2xiYXIuIA0KDQogICBBbHRlcm5hdGl2ZWx5IHVzZSB0aGUgPGtiZD5DdHJsPC9rYmQ+ICsgPGtiZD5TaGlmdDwva2JkPiArIDxrYmQ+STwva2JkPiBrZXlib2FyZCBzaG9ydGN1dC4NCiAgIA0KICAgIVtdKC4vaW1nL2luc2VydHJjaHVuay5wbmcpDQoNCjIuIE5hbWUgdGhpcyBjaHVuayAic3VtbWFyeSBwZW5ndWlucyIgYW5kIGNvbmZpcm0gdGhhdCBuYW1lIGFwcGVhcnMgaW4gdGhlIGNvZGUgY2h1bmsgbmF2aWdhdGlvbiBtZW51Lg0KDQozLiBBZGQgdGhpcyBSIGNvZGUgaW50byB0aGUgY2h1bms6IGBzdW1tYXJ5KHBlbmd1aW5zKWAuDQoNCjQuIFJ1biB0aGUgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4gQ3VycmVudCBDaHVuayogYnV0dG9uIG9yIGJ5IHByZXNzaW5nIDxrYmQ+Q3RybDwva2JkPiArIDxrYmQ+U2hpZnQ8L2tiZD4gKyA8a2JkPkVudGVyPC9rYmQ+LiANCiAgIA0KICAgIVtdKC4vaW1nL3J1bmNodW5rLnBuZykNCg0KNC4gSW5zZXJ0IGFuZCBydW4gYSBjb3VwbGUgbW9yZSBjb2RlIGNodW5rcyBjb250YWluaW5nIFIgY29kZSBvZiB5b3VyIGNob29zaW5nLiANCg0KNS4gS25pdCB5b3VyIG5vdGVib29rIHRvIEhUTUwgYW5kIGNoZWNrIHRoYXQgdGhlIG91dHB1dCBpcyBhcyB5b3UnZCBleHBlY3QuDQoNCjwvZGl2PjwvcD4NCg0KDQojIyMgQ2h1bmsgb3B0aW9ucw0KDQpZb3UgY2FuIGxpc3QgaW4gdGhlIGN1cmx5IHBhcmVudGhlc2VzIGB7fWAgdmFyaW91cyBvcHRpb25zIGZvciBjaGFuZ2luZyBob3cgYSBjaHVuayBpcyBrbml0dGVkIGludG8gdGhlIGZpbmFsIGRvY3VtZW50LiANCg0KU2VlIDxodHRwczovL3lpaHVpLm5hbWUva25pdHIvb3B0aW9ucz4gZm9yIGFsbCB0aGUgYXZhaWxhYmxlIG9wdGlvbnM7IG9ubHkgYSBmZXcgY29tbW9ubHkgdXNlZCBvcHRpb25zIGFyZSBzaG93biBoZXJlLg0KDQoqYSkgU2hvdyB0aGUgY29kZSBhbmQgdGhlIG91dHB1dCAoZGVmYXVsdCkqDQoNCmBgYGANCmBgYHtyfWByICcnYA0KY29sTWVhbnMocGVuZ3VpbnNbLDM6Nl0sIG5hLnJtID0gVFJVRSkNCmBgYA0KYGBgYA0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCmBgYHtyfQ0KY29sTWVhbnMocGVuZ3VpbnNbLDM6Nl0sIG5hLnJtID0gVFJVRSkNCmBgYA0KDQo8L2Rpdj48L3A+DQoNCipiKSBgZXZhbD1GQUxTRWAgc2hvd3MgdGhlIGNvZGUgYnV0IGRvZXMgbm90IGV4ZWN1dGUgaXQqDQoNCmBgYGANCmBgYHtyLCBldmFsPUZBTFNFfWByICcnYA0KY29sTWVhbnMocGVuZ3VpbnNbLDM6Nl0sIG5hLnJtID0gVFJVRSkNCmBgYA0KYGBgYA0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KY29sTWVhbnMocGVuZ3VpbnNbLDM6Nl0sIG5hLnJtID0gVFJVRSkNCmBgYA0KDQo8L2Rpdj48L3A+DQoNCipjKSBgZWNobz1GQUxTRWAgc2hvd3MgdGhlIG91dHB1dCBidXQgZG9lcyBub3Qgc2hvdyB0aGUgY29kZSoNCg0KYGBgYA0KYGBge3IsIGVjaG89RkFMU0V9YHIgJydgDQpjb2xNZWFucyhwZW5ndWluc1ssMzo2XSwgbmEucm0gPSBUUlVFKQ0KYGBgDQpgYGBgDQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpjb2xNZWFucyhwZW5ndWluc1ssMzo2XSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCjwvZGl2PjwvcD4NCg0KKmQpIGBpbmNsdWRlPUZBTFNFYCBleGVjdXRlcyB0aGUgY29kZSBidXQgZG9lcyBub3Qgc2hvdyBhbnl0aGluZyoNCg0KYGBgYA0KYGBge3IsIGluY2x1ZGU9RkFMU0V9YHIgJydgDQpjb2xNZWFucyhwZW5ndWluc1ssMzo2XSwgbmEucm0gPSBUUlVFKQ0KYGBgDQpgYGBgDQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogIzAwMDBFRTA1OyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCBibHVlIj4NCk91dHB1dDoNCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQpjb2xNZWFucyhwZW5ndWluc1ssMzo2XSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCjwvZGl2PjwvcD4NCg0KDQojIyMjIFRoZSBzZXR1cCBjaHVuayB7LX0NCg0KQSBzcGVjaWFsIGNvZGUgY2h1bmsgKGlmIGl0IGV4aXN0cykgaXMgdGhlIG9uZSBuYW1lZCAqc2V0dXAqLiBUaGUgc2V0dXAgY2h1bmsgaXMgYXV0b21hdGljYWxseSBydW4ganVzdCBiZWZvcmUgYW55IG90aGVyIGNvZGUgY2h1bmsgaXMgZXhlY3V0ZWQuIEl0IGlzIHVzZWZ1bCBmb3IgbG9hZGluZyBSIGBsaWJyYXJ5YHMgYW5kIGRhdGEgdXNlZCBzdWJzZXF1ZW50IGFuYWx5c2VzLiANCg0KYGBgYA0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9IGByICcnYA0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocGFsbWVycGVuZ3VpbnMpDQpgYGANCmBgYGANCg0KUmVjYWxsIHRoYXQgYGluY2x1ZGU9RkFMU0VgIHByZXZlbnRzIHRoZSBzZXR1cCBjaHVuayBmcm9tIGluc2VydGluZyBhbnkgb3V0cHV0IGludG8gdGhlIGtuaXR0ZWQgZG9jdW1lbnQuDQoNCjxwPjxkaXYgY2xhc3M9ImJveGVkIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjogI2VlYzI3NTEwOyBwYWRkaW5nOiAxMHB4OyBib3JkZXI6IDFweCBzb2xpZCAjZWVjMjc1Ij4NCioqRXhlcmNpc2UgNioqDQoNCjEuIER1cGxpY2F0ZSAoY29weS1wYXN0ZSkgdGhlIGNvZGUgY2h1bmsgZnJvbSBFeGVyY2lzZSA1IGJ1dCBzcGVjaWZ5IGEgZGlmZmVyZW50IG91dHB1dCBvcHRpb24gZnJvbSBhbW9uZ3N0IHRob3NlIG1lbnRpb25lZCBhYm92ZS4gT2JzZXJ2ZSB0aGUgZGlmZmVyZW50IG91dHB1dCBpbiB0aGUga25pdHRlZCBkb2N1bWVudC4NCg0KICAgSElOVDogaW5zdGVhZCBvZiBtYW51YWxseSB0eXBpbmcgdGhlIG91dHB1dCBvcHRpb25zLCBSU3R1ZGlvIHByb3ZpZGVzIGEgc2hvcnRjdXQgYnkgY2xpY2tpbmcgdGhlICpNb2RpZnkgQ2h1bmsgT3B0aW9ucyogaWNvbiAoZ3JleSBjb2cpIGZvdW5kIGluIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIHRoZSBjaHVuayBuZXh0IHRvIHRoZSAqUnVuIEN1cnJlbnQgQ2h1bmsqIGJ1dHRvbi4gDQoNCiAgICFbXSguL2ltZy9jaHVua29wdGlvbnMucG5nKQ0KDQogICBUaGUgcG9wdXAgYWxzbyBoYXMgYSBbKkNodW5rIG9wdGlvbnMqXShodHRwczovL3lpaHVpLm5hbWUva25pdHIvb3B0aW9ucy8pIGxpbmsgdG8gZG9jdW1lbnRhdGlvbiBvbiAgYXZhaWxhYmxlIGNodW5rIG9wdGlvbnMuDQoNCjIuIFJlcGVhdCBmb3Igc29tZSBvdGhlciBvdXRwdXQgb3B0aW9ucywgb2JzZXJ2aW5nIHRoZWlyIGVmZmVjdCBvbiB0aGUga25pdHRlZCBvdXRwdXQuDQoNCjwvZGl2PjwvcD4NCg0KDQojIyMgRmlndXJlIG9wdGlvbnMNCg0KQmVsb3cgaXMgYW4gZXhhbXBsZSBvZiBhIGNodW5rIHRoYXQgcHJvZHVjZXMgYSBmaWd1cmUgcmF0aGVyIHRoYW4gbnVtZXJpY2FsIG91dHB1dCwgbmFtZWx5IGEgYm94cGxvdCBvZiBiaWxsIGxlbmd0aHMgKG1pbGxpbWV0cmVzKSBmcm9tIHRoZSBgcGVuZ3VpbnNgIGRhdGFzZXQuDQoNCmBgYGANCmBgYHtyIGJpbGwgbGVuZ3RoIGJveHBsb3QsIGVjaG89RkFMU0V9IGByICcnYA0KYm94cGxvdChiaWxsX2xlbmd0aF9tbSB+IHNwZWNpZXMsIGRhdGEgPSBwZW5ndWlucywgY29sID0gaGNsLmNvbG9ycygzKSwgbWFpbiA9ICJQZW5ndWluIEJpbGwgTGVuZ3RocyIpDQpgYGANCmBgYGANCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMEVFMDU7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkIGJsdWUiPg0KT3V0cHV0Og0KDQpgYGB7ciBiaWxsIGxlbmd0aCBib3hwbG90LCBlY2hvPUZBTFNFfQ0KYm94cGxvdChiaWxsX2xlbmd0aF9tbSB+IHNwZWNpZXMsIGRhdGEgPSBwZW5ndWlucywgY29sID0gaGNsLmNvbG9ycygzKSwgbWFpbiA9ICJQZW5ndWluIEJpbGwgTGVuZ3RocyIpDQpgYGANCg0KPC9kaXY+PC9wPg0KDQpXZSBjYW4gcmVzaXplIHRoZSBwbG90IHVzaW5nIHRoZSBgZmlnLmhlaWdodGAgYW5kIGBmaWcud2lkdGhgIGNodW5rIG9wdGlvbnMuDQoNCmBgYGANCmBgYHtyIGJpbGwgbGVuZ3RoIGJveHBsb3QgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9M30gYHIgJydgDQpib3hwbG90KGJpbGxfbGVuZ3RoX21tIH4gc3BlY2llcywgZGF0YSA9IHBlbmd1aW5zLCBjb2wgPSBoY2wuY29sb3JzKDMpLCBtYWluID0gIlBlbmd1aW4gQmlsbCBMZW5ndGhzIikNCmBgYA0KYGBgYA0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTN9DQpib3hwbG90KGJpbGxfbGVuZ3RoX21tIH4gc3BlY2llcywgZGF0YSA9IHBlbmd1aW5zLCBjb2wgPSBoY2wuY29sb3JzKDMpLCBtYWluID0gIlBlbmd1aW4gQmlsbCBMZW5ndGhzIikNCmBgYA0KDQo8L2Rpdj48L3A+DQoNCk90aGVyIHVzZWZ1bCBvcHRpb25zIGluY2x1ZGU6DQoNCiogYGZpZy5hc3BgIGZvciBzZXR0aW5nIHRoZSBmaWd1cmUgYXNwZWN0IHJhdGlvDQoNCiogYGZpZy5kaW1gIGZvciBzcGVjaWZ5aW5nIHRoZSBmaWd1cmUgd2lkdGggYW5kIGhlaWdodCBhcyBhIGAod2lkdGgsIGhlaWdodClgIHR1cGxlDQoNCiogYGZpZy5hbGlnbmAgZm9yIGFsaWduaW5nIHRoZSBmaWd1cmUgdG8gdGhlIGxlZnQsIHJpZ2h0LCBvciBjZW50cmUgb2YgdGhlIHBhZ2UNCg0KU2VlIDxodHRwczovL3lpaHVpLm5hbWUva25pdHIvb3B0aW9ucy8jcGxvdHM+IGZvciBhbiBleHRlbnNpdmUgbGlzdC4NCg0KPHA+PGRpdiBjbGFzcz0iYm94ZWQiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiAjZWVjMjc1MTA7IHBhZGRpbmc6IDEwcHg7IGJvcmRlcjogMXB4IHNvbGlkICNlZWMyNzUiPg0KKipFeGVyY2lzZSA3KioNCg0KQ2hlY2sgdGhlc2UgZXhlcmNpc2VzIGJ5IHJlLXJ1bm5pbmcgdGhlIGVkaXRlZCBjb2RlIGNodW5rIGFuZCByZS1rbml0dGluZyB0aGUgd2hvbGUgbm90ZWJvb2suIFNvbWV0aW1lcyB0aGUgcHJldmlldyBhbmQgZG9jdW1lbnQgYXJlIGRpZmZlcmVudCEgDQoNCkhJTlQ6IFlvdSBtYXkgbmVlZCB0byBjaGVjayB0aGUgb25saW5lIGRvY3VtZW50YXRpb24gbWVudGlvbmVkIGFib3ZlLg0KDQoxLiBEdXBsaWNhdGUgKGNvcHktcGFzdGUpIHRoZSBjb2RlIGNodW5rIG9mIG9uZSBvZiB0aGUgZmlndXJlcyBpbiB5b3VyIG5vdGVib29rIChyZW5hbWluZyBpdCBpZiBuZWNlc3NhcnkpIGFuZCB1c2UgdGhlIGBmaWcuYXNwYCBmaWd1cmUgb3B0aW9uIHRvIHNldCBpdHMgYXNwZWN0IHJhdGlvIHRvIGJlIHNxdWFyZSwgaS5lLiwgMToxLg0KDQoyLiBOb3cgYXBwbHkgdGhlIGBmaWcuYWxpZ25gIG9wdGlvbiB0byBjZW50cmUgaXQgb24gdGhlIHBhZ2UuDQoNCjMuIE9uIGEgZnJlc2ggZHVwbGljYXRlIG9mIHRoZSBjb2RlIGNodW5rLCB1c2UgYGZpZy5kaW1gIHRvIHJlc2l6ZSB0aGUgZmlndXJlIHRvIGEgd2lkdGggb2YgNCBpbmNoZXMgYW5kIGhlaWdodCBvZiA2IGluY2hlcy4NCg0KPC9kaXY+PC9wPg0KDQoNCiMjIFlBTUwgSGVhZGVyDQoNCkF0IHRoZSB0b3Agb2YgYSBgLlJtZGAgZmlsZSwgZW5jbG9zZWQgYnkgdHJpcGxlIGh5cGhlbnMgYC0tLWAsIGlzIHRoZSBZQU1MW155YW1sXSBoZWFkZXIuIEl0IGRlZmluZXMgc2V0dGluZ3MgdGhhdCBhZmZlY3QgdGhlIGVudGlyZSBkb2N1bWVudCwgaW4gcGFydGljdWxhciBzcGVjaWZ5aW5nIHRoZSBvdXRwdXQgdHlwZS4NCg0KW155YW1sXTogWUFNTCBzdGFuZHMgZm9yIFlBTUwgQWluJ3QgTWFya3VwIExhbmd1YWdlLiBJdCdzIGEgcmVjdXJzaXZlIG5hbWUhDQoNCkJlbG93IGlzIHRoZSBkZWZhdWx0IFlBTUwgaGVhZGVyIGNyZWF0ZWQgYnkgUlN0dWRpbyBmb3IgbmV3IFIgTm90ZWJvb2tzLiBJdCBzZXRzIHRoZSBSIE1hcmtkb3duIGZpbGUgdG8ga25pdCB0byBhbiBIVE1MIG5vdGVib29rIGBodG1sX25vdGVib29rYC4NCg0Kfn5+DQotLS0NCnRpdGxlOiAiUiBOb3RlYm9vayINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQp+fn4NCg0KT3RoZXIgZG9jdW1lbnQgb3V0cHV0IHR5cGVzIGluY2x1ZGUgUERGLCBXb3JkLCBhbmQgSFRNTCBkb2N1bWVudHMgKGRpc3RpbmN0IGZyb20gSFRNTCAqbm90ZWJvb2sqKS4gTm90ZSB0aGF0IFBERiBvdXRwdXQgcmVxdWlyZXMgJFxMYVRlWCQgKHNlZSB0aGUgYHRpbnl0ZXhgIFIgcGFja2FnZSkgYW5kIHlvdSBvYnZpb3VzbHkgbmVlZCBNaWNyb3NvZnQgV29yZCBvciBhbiBlcXVpdmFsZW50IHRvIHByZXZpZXcgV29yZCBvdXRwdXRzLg0KDQp+fn4NCi0tLQ0KdGl0bGU6ICJSIERvY3VtZW50Ig0Kb3V0cHV0Og0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgd29yZF9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCn5+fg0KDQpBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHByb2R1Y2UgYSBzbGlkZSBkZWNrIGJ5IHNldHRpbmcgdGhlIG91dHB1dCBwYXJhbWV0ZXIgdG8gYmUgYGJlYW1lcl9wcmVzZW50YXRpb25gLCBgaW9zbGlkZXNfcHJlc2VudGF0aW9uYCwgb3IgYHNsaWR5X3ByZXNlbnRhdGlvbmAuDQoNCn5+fg0KLS0tDQp0aXRsZTogIlIgU2xpZGVzaG93Ig0Kb3V0cHV0Og0KICBiZWFtZXJfcHJlc2VudGF0aW9uOiBkZWZhdWx0DQogIGlvc2xpZGVzX3ByZXNlbnRhdGlvbjogZGVmYXVsdA0KICBzbGlkeV9wcmVzZW50YXRpb246IGRlZmF1bHQNCi0tLQ0Kfn5+DQoNClNlZSBbQ2hhcHRlciA0XShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vcHJlc2VudGF0aW9ucy5odG1sKSBvZiBAeGllMjAxOFJHdWlkZSBmb3IgYSBmdWxsIGJyZWFrZG93biBvZiB0aGVzZSB0eXBlcy4gDQoNCg0KIyMjIyBIVE1MIGRvY3VtZW50IHNldHRpbmdzIHstfQ0KDQpUaGUgZm9jdXMgb2YgdGhpcyBsZXNzb24gaXMga25pdHRpbmcgSFRNTCBkb2N1bWVudHMgKHRoZSBgaHRtbF9kb2N1bWVudGAgb3V0cHV0IHR5cGUpLiBUaGVyZSBhcmUgbWFueSBzZXR0aW5ncyBhdmFpbGFibGUgYXMgaWxsdXN0cmF0ZWQgYnkgdGhlIFlBTUwgaGVhZGVyIHVzZWQgaW4gdGhlIGAuUm1kYCBmaWxlIGZvciB0aGlzIGxlc3NvbjoNCg0Kfn5+DQotLS0NCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgTWFya2Rvd24iDQphdXRob3I6ICJbU2hpaCBDaGluZyBGdV0oaHR0cHM6Ly9zaGloY2hpbmdmdS5jb20pIg0KZGF0ZTogIkp1bHkgMjAyMSINCmJpYmxpb2dyYXBoeTogcmVmLmJpYg0Kb3V0cHV0Og0KICAjc2xpZHlfcHJlc2VudGF0aW9uOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiANCiAgICAgIGNvbGxhcHNlZDogdHJ1ZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGhpZ2hsaWdodDogaGFkZG9jaw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCmtuaXQ6IA0KICAoZnVuY3Rpb24oaW5wdXRfZmlsZSwgZW5jb2RpbmcpIHsNCiAgICBybWFya2Rvd246OnJlbmRlcihpbnB1dF9maWxlLA0KICAgICAgICAgICAgICAgICAgICAgIGVuY29kaW5nPWVuY29kaW5nLA0KICAgICAgICAgICAgICAgICAgICAgIG91dHB1dF9maWxlPWZpbGUucGF0aChkaXJuYW1lKGlucHV0X2ZpbGUpLCAnZG9jcycsICdpbmRleC5odG1sJykpfSkNCi0tLQ0Kfn5+DQoNCk1hbnkgb2YgdGhlc2Ugb3B0aW9ucyBhbHNvIGFjY2Vzc2libGUgdmlhIHRoZSAiT3V0cHV0IG9wdGlvbnMuLi4iIGl0ZW0gdW5kZXIgdGhlIFIgTWFya2Rvd24gZm9ybWF0IG9wdGlvbnMgbWVudSAoZ2VhciBpY29uKSBpbiB0aGUgc291cmNlIHBhbmUuDQoNCjxjZW50ZXI+DQohW10oaW1nL291dHB1dG9wdGlvbnMucG5nKQ0KPC9jZW50ZXI+DQoNClNlZSBbUGFydCBJSV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duL2RvY3VtZW50cy5odG1sKSBvZiBAeGllMjAxOFJHdWlkZSBmb3IgZnVsbCBkZXRhaWxzIG9mIG9wdGlvbnMgZm9yIHZhcmlvdXMgb3V0cHV0IHR5cGVzLg0KDQoNCg0KIyMgQmlibGlvZ3JhcGhpZXMNCg0KUiBNYXJrZG93biBzdXBwb3J0cyBjb21tb24gYmlibGlvZ3JhcGh5IGZvcm1hdHMgc3VjaCBhcyBCaWJUZVgsIEJpYkxhVGVYLCBhbmQgRW5kTm90ZS4NCg0KVGhlIHBhdGggdG8gdGhlIGJpYmxpb2dyYXBoeSBmaWxlIG11c3QgYmUgc3BlY2lmaWVkIGluIHRoZSBZQU1MIGhlYWRlciB1bmRlciB0aGUgYGJpYmxpb2dyYXBoeWAgZmllbGQuDQoNCn5+fg0KLS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byBSIE1hcmtkb3duIg0KYXV0aG9yOiAiW1NoaWggQ2hpbmcgRnVdKGh0dHBzOi8vc2hpaGNoaW5nZnUuY29tKSINCmRhdGU6ICJBcHJpbCAyMDIxIg0KYmlibGlvZ3JhcGh5OiByZWYuYmliDQotLS0NCn5+fg0KDQpIZXJlJ3MgYSBzYW1wbGUgQmliVGVYIHJlY29yZCBmcm9tIHRoZSBhYm92ZW1lbnRpb25lZCBgcmVmLmJpYmAgZmlsZToNCg0Kfn5+DQpAYm9va3t4aWUyMDE4Ukd1aWRlLCANCiAgICAgIGF1dGhvciA9ICJZaWh1aSBYaWUgYW5kIEouSi4gQWxsYWlyZSBhbmQgR2FycmV0dCBHcm9sZW11bmQiLA0KICAgICAgdGl0bGUgPSAiUiBNYXJrZG93bjogVGhlIERlZmluaXRpdmUgR3VpZGUiLA0KICAgICAgeWVhciA9ICIyMDE4IiwNCiAgICAgIHB1Ymxpc2hlciA9ICJDUkMgUHJlc3MiLA0KICAgICAgdXJsID0gImh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi8ifQ0Kfn5+DQoNCkluLXRleHQgY2l0YXRpb25zIGFyZSBpbnNlcnRlZCB1c2luZyB0aGUgYXQgc2lnbiBgQGAgZm9sbG93ZWQgYnkgdGhlIGNpdGF0aW9uIGtleS4gDQoNCn5+fg0KUGFydCBJSSBvZiBAeGllMjAxOFJHdWlkZSBkZXNjcmliZXMgdGhlIHZhcmlvdXMgb3V0cHV0IGZvcm1hdHMgYXZhaWxhYmxlIHdpdGggUiBNYXJrZG93bi4NCn5+fg0KDQo8cD48ZGl2IGNsYXNzPSJib3hlZCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICMwMDAwRUUwNTsgcGFkZGluZzogMTBweDsgYm9yZGVyOiAxcHggc29saWQgYmx1ZSI+DQpPdXRwdXQ6DQoNClBhcnQgSUkgb2YgQHhpZTIwMThSR3VpZGUgZGVzY3JpYmVzIHRoZSB2YXJpb3VzIG91dHB1dCBmb3JtYXRzIGF2YWlsYWJsZSB3aXRoIFIgTWFya2Rvd24uDQoNCjwvZGl2PjwvcD4NCg0KDQojIFJTdHVkaW8gVmlzdWFsIEVkaXRvcg0KDQpTaW5jZSB2ZXJzaW9uIDEuNCwgUlN0dWRpbyBoYXMgYSAiVmlzdWFsIEVkaXRvciIgbW9kZSBmb3IgdGhlIFNvdXJjZSBwYW5lLiBJdCBpcyBha2luIHRvIHRoZSB3aGF0IHlvdSBzZWUgaXMgd2hhdCB5b3UgZ2V0IChXWVNJV0lHKSBleHBlcmllbmNlIHRoYXQgY29tZXMgd2l0aCBhIHdvcmQgcHJvY2Vzc29yIGxpa2UgTWljcm9zb2Z0IFdvcmQuDQoNCllvdSBjYW4gZW5hYmxlIGl0IGZyb20gdGhlIGZvcm1hdCBvcHRpb25zIG1lbnUgKGdlYXIgaWNvbikgaW4gdGhlIHNvdXJjZSBwYW5lLg0KDQo8Y2VudGVyPg0KIVtdKGltZy9lbmFibGV2aXN1YWxlZGl0b3IucG5nKQ0KPC9jZW50ZXI+DQoNCldpdGggdGhpcyBtb2RlIHR1cm5lZCBvbiB0aGUgU291cmNlIHBhbmUgbm93IHNob3dzIGEgdG9vbGJhciB0aGF0IGhhcyBwcmV0dHkgbXVjaCBhbGwgdGhlIGZvcm1hdHRpbmcgb3B0aW9ucyB0aGF0IGFyZSBkZXNjcmliZWQgYWJvdmUuDQoNCjxjZW50ZXI+DQohW10oaW1nL3Zpc3VhbGVkaXRvcnRvb2xiYXIucG5nKQ0KPC9jZW50ZXI+DQoNCllvdSBtaWdodCBhc2sgd2h5IGJvdGhlciB3aXRoIGxlYXJuaW5nIFIgbWFya2Rvd24gc3ludGF4IG5vdyB0aGF0IHRoZXJlIGlzIGEgdmlzdWFsIGVkaXRvcj8gV2VsbCwgdGhlIGNob2ljZSBpcyBlbnRpcmVseSB1cCB0byB5b3UgYW5kIGluZGVlZCB5b3UgY2FuIHN3YXAgYmV0d2VlbiB0aGVtIGFzIHlvdSBmZWVsIGluY2xpbmVkLiBJJ3ZlIGV2ZW4gaXQgdXNlZCBpdCBhcyBhIGxlYXJuaW5nIHRvb2wgYnkgY29tcG9zaW5nIGEgbm90ZWJvb2sgaW4gdGhlIFZpc3VhbCBFZGl0b3IgYW5kIHRoZW4gaW5zcGVjdGluZyB0aGUgUiBNYXJrZG93biBzeW50YXggdGhhdCBpcyBnZW5lcmF0ZWQgdW5kZXJuZWF0aCENCg0KRnVsbCBkb2N1bWVudGF0aW9uIGlzIGF2YWlsYWJsZSBoZXJlOiA8aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby92aXN1YWwtbWFya2Rvd24tZWRpdGluZy8+Lg0KDQojIEVuZCBvZiB0aGUgYmVnaW5uaW5nDQoNClRoZXJlIGlzICoqKm11Y2gqKiogbW9yZSB0byBSIE1hcmtkb3duIHRoYW4gd2hhdCdzIGNvdmVyZWQgaGVyZSENCg0KVGhlIHNvdXJjZXMgbWVudGlvbmVkIGluIHRoZSBiaWJsaW9ncmFwaHkgYmVsb3cgYXJlIGdvb2Qgc3RhcnRpbmcgcG9pbnRzIGZvciBmdXJ0aGVyIGRldmVsb3BpbmcgeW91ciBSIE1hcmtkb3duIGV4cGVydGlzZS4gR2FsbGVyaWVzIHN1Y2ggYXMgPGh0dHBzOi8veWlodWkubmFtZS9rbml0ci9kZW1vL3Nob3djYXNlLz4gYXJlIGFsc28gYSBncmVhdCBwbGFjZSB0byBzdGFydC4NCg0KUlN0dWRpbyBhbHNvIHByb3ZpZGVzICdjaGVhdHNoZWV0cycgdGhhdCBhcmUgYWNjZXNzaWJsZSBmcm9tIHRoZSAqSGVscCogbWVudS4gVGhlc2UgYXJlIGEgY29udmVuaWVudCBwcmludGFibGUgcmVmZXJlbmNlIG9mIGNvbW1vbmx5IHVzZWQgc3ludGF4IGFuZCBjb21tYW5kcy4NCg0KPGNlbnRlcj4NCiFbXSguL2ltZy9jaGVhdHNoZWV0cy5wbmcpDQo8L2NlbnRlcj4NCg0KTWF5IHRoZSBga25pdHJgIGJlIHdpdGggeW91Lg0KDQoNCiMgUiBTZXNzaW9uIEluZm8NCg0KYGBge3IgZWNobz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkNCmBgYA0KDQojIFJlZmVyZW5jZXMNCg0K