.Rmd documents

With RMarkdown it is easy to create documents or webpages that include text, code and plots. During the practical sessions we will work with RMarkdown, and not with R scripts. RMarkdown allows you to combine the code required to produce an analysis, its results, visualizations and descriptive text all in one document.

For a detailed guide on RMarkdown see R Markdown: The Definitive Guide. Most of the contents discussed here come from that source.

Metadata

The markdown notebook will start with a YAML header, which includes the title, names of the authors and type of RMarkdown file. We typically work with html_document (the default).

---
title: "Title"
author: "Author names"
date: "Date"
output:  html_document
---

The html_document output specifies that your document will be converted to HTML when you “knit” or compile it.

Compiling an R Markdown file

Essentially, an .Rmd file is just a plain text file used to store all your text and code needed to produce your final report. Although RStudio allows you to preview the output of your code, the output is not itself part of the .Rmd file. When you save and close your Rmd file and open it again later or send it to someone, the output will have disappeared (although also here, RStudio has some tricks to keep the output). The way to properly generate the output version of your Rmd file is by compiling it. This can be done in RStudio by pressing the Knit button in the toolbar, or by pressing Shift + Ctrl + K (Mac: Shift + Cmd + K). This will produce an HTML file with the same name as your Rmd and located in the same folder. You can open this file in any internet browser (you don’t need an internet connection since it’s a local file) and marvel at the nicely formatted output of your hard work. Another advantage of working with RStudio is that it will open this file automatically, either in a new window or in the “Viewer” pane (you can change this in the RStudio settings).

Important: saving your Rmd file does not update the corresponding HTML file automatically. In contrast, when you compile (“Knit”), your Rmd file will be saved first.

While editing you generally want to save often (you don’t want to lose stuff if something goes wrong) but you don’t need to compile every time you make a minor change, unless you want to see what the output will look like.

Formatting text

Bold and italic text

Text in an R Markdown document (i.e. everything that is not considered code) is written in Markdown syntax. This enables you to format text by surrounding it with special characters.

Italic text is generated by surrounding the text with a pair of either underscores (_text_) or asterisks (*text*). Bold text uses a pair of double underscores (__text__) or asterisks (**text**). Bold italic text can be achieved by using a combination of the two (__*text*__).

Lists

Unordered list items start with *, -, or +, and you can nest one list within another list by indenting the sub-list, for example:

- one item
- one item
- one item
    * one more item
    * one more item
    * one more item

The output of the above syntax would be:

  • one item
  • one item
  • one item
    • one more item
    • one more item
    • one more item

A numbered list can be created by starting each item with a number:

1. the first item
2. the second item
3. the third item

Output:

  1. the first item
  2. the second item
  3. the third item

Note: make sure to leave an empty line between text and a list for correct formatting.

Section headers

Section headers can be written using a number of # signs, where the amount of #’s specifies the level:

# Main section title: first level

## Subsection: second level

### Sub-subsection: third level

#### Sub-sub-subsection: fourth level

The output:

Main section title: first level

Subsection: second level

Sub-subsection: third level

Sub-sub-subsection: fourth level

In general it’s not recommended to go further than 4 sub-levels of sections.

Note that you can also include a table of contents at the top of your file by specifying toc: true in the YAML header.

Integrating text and R code

You can insert chunks of R code in your RMarkdown file by wrapping a code block inside ```{r} and ```.

In RStudio this is easily done by using the Insert button in the toolbar or the keyboard shorcut Ctrl + Alt + I (Cmd + Option + I on macOS).

For more information, see section 2.6 of The Definitive Guide

We will demonstrete the use of R-code with various examples in the sections below so that you can familiarise yourself with the syntax.

Basic R stuff

Simple calculations

R can be used as a simple calculator. Executing code can be done in various ways. To execute the entire chunk of code:

  • In RStudio: click the green arrow in the upper right corner of the code chunk
  • Place your cursor inside the chunk and press Shift + Ctrl + Enter (Mac: Shift + Cmd + Enter)

Code can also be run line by line by selecting a line with your cursor and pressing Ctrl + Enter (Mac: Cmd + Enter).

Try executing the code below using both ways: line-by-line and the entire chunk.

1+1
## [1] 2
(5-3)+7*10/2
## [1] 37

The output should be displayed either right below the code chunk or in the R console. You can change this behaviour by selecting the settings gear in the RStudio toolbar and selecting Chunk Output Inline or Chunk Output in Console.

You can also run all chunks in you Rmd file by pressing the Run button in the toolbar (upper right) and then select Run All (or using the keyboard shortcut Shift + Ctrl + R on Windows or Shift + Cmd + R on Mac). Note that this menu also provides additional ways of running R chunks, the most useful ones being:

  • Run All Chunks Above: this executes all code chunks preceding your cursor location, starting at the top and tehn running down.
  • Restart R and Run All Chunks: this will restart R and re-run your entire document. Note that this will remove all current objects and data from memory and re-starting R in a blank state. This means that any code that was run in the console and not saved in a code chunk will be lost. This might seem scary at first, but there are very good reasons to do this often. You can read more about this workflow here.

Commenting R code

You can add comments to your R code by starting a line with #. This is useful to describe what your code is doing (or should be doing). Annotating your code this way is very useful to communicate both with others and your future self. Try to keep these comments clear but short. Longer descriptions should go in the main text of your RMarkdown file. Commenting also provides a way of “disabling” code without having to remove it. Note that each new line of a comment should be preceded by a #. You can easily “comment out” multiple lines by selecting them and pressing Shift + Ctrl + C (Mac: Shift + Cmd + C).

Try running the chunk below and verify that it does not produce any output. What happens if you remove one of the # signs?

# This is a comment

# This is a very long comment split over
# multiple lines

# Code inside a comment is not executed
# 1+1

Assigning objects to save results and perform calculations

You can save results of function calls or calculations by assigning the value to a variable using the assign operator <-.

Run the code below and verify the value of c. You can also check the value of a variable by entering it in the Console and pressing Enter.

a <- 2
b <- 3
c <- a + b
c
## [1] 5

Note that in principle, you can also use = for assignment, but this is considered to be bad practice because the equal sign is reserved for function arguments (see next section). So you should always use <- for assignment.

Hint: a quick and easy way to type <- in RStudio is by using the shortcut Alt + - (Mac: Option + -).

Functions

Functions are commands in R that perform certain tasks. They take inputs in the form of arguments and return their results as output. They are called using their name, followed by parentheses () in which the arguments are specified. There are many built-in functions in R. In addition, you can write your own functions or load other functins through the use of packages (more on that later).

As an example, we can use the function rnorm to sample 100 draws from a Normal distribution. We assign the result (a vector of 100 random numbers) to a new variable draws and display the first 6 values by caling the function head on this new variable.

# sample 100 numbers from a standard normal distribution 
# (mean = 0, standard deviation = 1)
draws <- rnorm(100)
head(draws)
## [1]  0.3295078 -0.8204684  0.4874291  0.7383247  0.5757814 -0.3053884

Getting help in R: ?

What if instead of drawing from the standard normal distribution we want to sample from a normal with a mean of 5 and a standard deviation of 2? Knowing that rnorm is the function to generate normally distributed numbers, we can get more information on it by executing ?rnorm (usually you would do this in the Console, but for demonstration, we run it inside a code chunk here). This will open up the help page for the “The Normal Distribution” and all its related functions inside R, one of which is rnorm.

?rnorm

Read through the documentation, can you figure out how to change the mean and standard deviation?

The solution is to specify the mean and sd arguments.

draws2 <- rnorm(100, mean = 5, sd = 2)
head(draws2)
## [1] 3.690831 8.534575 6.433415 6.820348 5.768371 8.364352

Each built-in R function or functions loaded through a package has a help page. In addition, there is a wealth of information through the wonderful magic of Google. Another great place to look for answers or ask questions yourself is StackOverflow.

Tidyverse

The tidyverse is a set of packages designed to make data science in R more user-friendly. It shares a common philosophy and grammar of doing data science, which can change somewhat from how base R works (though it shouldn’t be an excuse to learn how to use base R!!!).

Instead of installing each tidyverse package individually, you can install all of them simultaneously by simply calling

install.packages("tidyverse")

Note that this code won’t be executed when compiling this report, because I specified eval=FALSE in the chunk options. Instead it should be called manually, for example in an R console.

For more information see

Visualizations

Base R

A picture often says more than words (or lines of code output) and R has a rich visualization toolbox that allows us to make powerful visualizations of our data.

For example, to visually verify that the random numbers we generated earlier (which are still stored in memory under the variables draws and draws2) are indeed normally distributed, we could make a histogram of them, using the hist function.

# draws comes from a standard normal (mean = 0, sd = 1)
hist(draws)

# draws 2 comes from a normal with mean = 5, sd = 2
hist(draws2)

Note that you can customize these plots in a lot of ways. Looking at the help page of hist or doing a quick internet search will take you a long way!

ggplot2

Although powerful, the base R visualization framework can be somewhat challenging to work with. A good alternative is the ggplot2 package, part of the larger tidyverse which includes more useful packages for data manipulation and analysis. ggplot2 uses a visualization framework based on the grammar of graphics philosophy, which we won’t get further into here but which can be quite an intuitive way to think about data visualizations.

ggplot2 works best with a data.frame as input. As an example, we’ll use the mtcars data, which is available by default in every R installation (for more info on this data set, see ?mtcars). With just a few lines, we can create already quite elegant visualizations:

library(ggplot2)

ggplot(mpg, aes(displ, hwy, colour = class)) + 
  geom_point()

You could perfectly recreate this plot with base R, but it’s going to take more lines of code and potential headaches. Still, both frameworks have their strengths and weaknesses and they are complementary in many ways, so it pays to learn both of them rather than stubbornly sticking to one.

There are tons of documentation and tutorials on ggplot2 to be found online. A good place to start is https://ggplot2.tidyverse.org/.

Importing data

See https://r4ds.had.co.nz/data-import.html.

Note that both the base read.csv and the tidyverse equivalent readr::read_csv() can both use URLs to read in data. That way you don’t have to download the data locally on your machine or worry about different versions.

## Example from HDA2020 course (https://statomics.github.io/HDA2020/)
uk_foods <- readr::read_csv(
  file = "https://raw.githubusercontent.com/statOmics/HDA2020/data/ukFoods.csv",
  col_names = TRUE,
  col_types = cols()
)
## Warning: Missing column names filled in: 'X1' [1]
uk_foods

Summary of data

To get a quick summary of the data, you can use the summary function. This will return some summary statistics for the columns present in the data.

## iris is a default data set available in R
## To get more info, use `?iris`
summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 
class(iris)
## [1] "data.frame"

Subsetting data

You can select subsets of a data.frame by using square brackets [] and specifying the number(s) of the row(s) or column(s) you want to select. Alternatively, you can use the dollar sign $ to select a column using its name.

To reduce the output printed out, we will first make a subset of the iris data containing just the first 10 rows.

# make subset of data to prevent long outputs
iris_sub <- iris[1:10, ]
iris_sub
# Select first column, single brackets returns data.frame
iris_sub[1]
iris_sub["Sepal.Length"]
# double brackets returns vector
iris_sub[[1]]
##  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9
iris_sub[["Sepal.Length"]]
##  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9
# using the dollar sign, also returns vector
iris_sub$Sepal.Length
##  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9
# Select all columns except the first one
iris_sub[-1]
# Selecting rows
iris_sub[1, ] # Select the first row
iris_sub[1:5,] # Select the first five rows
iris_sub[c(2, 4), ] # select the second and fourth rows
# columns and rows
iris_sub[1:5, "Sepal.Length"] # first 5 rows of "Sepal.Length" column
## [1] 5.1 4.9 4.7 4.6 5.0
iris_sub[3, 2]  # third row, second column
## [1] 3.2

Including R object values or results in the text

You can add inline R code results by wrapping them inside `r `. This is useful for discussing the value of a result in your text. Instead of having to copy the value of a result (which is prone to error and not robust to changes), you can just call it inside the text. For example, we could calculate the mean sepal length of the iris flowers as follow:

mean(iris$Sepal.Length)
## [1] 5.843333

We could copy the value inside our text, but a better way is by just running the code inline as mean(iris$Sepal.Length) surrounded by `r and `. So we could say that the iris flowers in our data have a mean length of 5.8433333.

Note: to actually see the value of the inline code, place your cursor inside the backticks ` `r and press Ctrl + Enter or Cmd + Enter. When you knit your Rmd file and build the HTML output, the inline R code will be replaced by its output value.

Including equations

Finally, you can include equations in your text using LaTeX syntax and surrounding it by a pair of double dollar signs $$. This is useful to specify models. For example, we can write the equation of a linear model as

$$
y_i = \beta_0 + \beta_1 x_i + \epsilon_i
$$

Which will be converted to the following output:

\[ y_i = \beta_0 + \beta_1 x_i + \epsilon_i \]

Note that RStudio will give you a preview of what your equation will look like in the final document.

You can also include inline \(\LaTeX\) equations by using a pair of single $ signs. For example, the following sentence:

The sample mean of $y$ is given by $\bar{y}=\sum\limits_{i=1}^{n}\frac{y_i}{n}$

Will be converted to:

The sample mean of \(y\) is given by \(\bar{y}=\sum\limits_{i=1}^{n}\frac{y_i}{n}\)

Useful resources

Session Info

Finally, it’s always good practice to include the Session Info for your R session in your document. That way, other persons (including your future self) looking at your document can see what versions of R and loaded packages were used, which can be quite essential for reproducibility. There are 2 options, either using the base R command sessionInfo() or using the version from the devtools package: devtools::session_info(). Their outputs have slightly different formatting but the contents are essentially the same. Personally, I prefer the devtools version, but this is really a personal choice.

You can also include the date with Sys.time() so you have a time stamp of when the report was compiled. If you happen to be working inside a git repository, git2r::repository() is a useful function that displays information about the current git state and the last commit.

Sys.time()
## [1] "2021-05-11 14:32:02 UTC"
devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value                       
##  version  R version 4.0.5 (2021-03-31)
##  os       macOS Catalina 10.15.7      
##  system   x86_64, darwin17.0          
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  ctype    en_US.UTF-8                 
##  tz       UTC                         
##  date     2021-05-11                  
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package                * version  date       lib source        
##  AnnotationDbi            1.52.0   2020-10-27 [1] Bioconductor  
##  AnnotationHub          * 2.22.1   2021-04-16 [1] Bioconductor  
##  assertthat               0.2.1    2019-03-21 [1] CRAN (R 4.0.2)
##  backports                1.2.1    2020-12-09 [1] CRAN (R 4.0.2)
##  beachmat                 2.6.4    2020-12-20 [1] Bioconductor  
##  beeswarm                 0.3.1    2021-03-07 [1] CRAN (R 4.0.2)
##  Biobase                * 2.50.0   2020-10-27 [1] Bioconductor  
##  BiocFileCache          * 1.14.0   2020-10-27 [1] Bioconductor  
##  BiocGenerics           * 0.36.1   2021-04-16 [1] Bioconductor  
##  BiocManager              1.30.15  2021-05-11 [1] CRAN (R 4.0.5)
##  BiocNeighbors            1.8.2    2020-12-07 [1] Bioconductor  
##  BiocParallel             1.24.1   2020-11-06 [1] Bioconductor  
##  BiocSingular             1.6.0    2020-10-27 [1] Bioconductor  
##  BiocVersion              3.12.0   2020-05-14 [1] Bioconductor  
##  bit                      4.0.4    2020-08-04 [1] CRAN (R 4.0.2)
##  bit64                    4.0.5    2020-08-30 [1] CRAN (R 4.0.2)
##  bitops                   1.0-7    2021-04-24 [1] CRAN (R 4.0.2)
##  blob                     1.2.1    2020-01-20 [1] CRAN (R 4.0.2)
##  broom                    0.7.6    2021-04-05 [1] CRAN (R 4.0.2)
##  bslib                    0.2.4    2021-01-25 [1] CRAN (R 4.0.2)
##  cachem                   1.0.4    2021-02-13 [1] CRAN (R 4.0.2)
##  callr                    3.7.0    2021-04-20 [1] CRAN (R 4.0.2)
##  CCA                    * 1.2.1    2021-03-01 [1] CRAN (R 4.0.2)
##  cellranger               1.1.0    2016-07-27 [1] CRAN (R 4.0.2)
##  cli                      2.5.0    2021-04-26 [1] CRAN (R 4.0.2)
##  cluster                * 2.1.2    2021-04-17 [1] CRAN (R 4.0.2)
##  colorspace               2.0-1    2021-05-04 [1] CRAN (R 4.0.2)
##  crayon                   1.4.1    2021-02-08 [1] CRAN (R 4.0.2)
##  curl                     4.3.1    2021-04-30 [1] CRAN (R 4.0.2)
##  DBI                      1.1.1    2021-01-15 [1] CRAN (R 4.0.2)
##  dbplyr                 * 2.1.1    2021-04-06 [1] CRAN (R 4.0.2)
##  DelayedArray             0.16.3   2021-03-24 [1] Bioconductor  
##  DelayedMatrixStats       1.12.3   2021-02-03 [1] Bioconductor  
##  desc                     1.3.0    2021-03-05 [1] CRAN (R 4.0.2)
##  devtools                 2.4.1    2021-05-05 [1] CRAN (R 4.0.2)
##  digest                   0.6.27   2020-10-24 [1] CRAN (R 4.0.2)
##  dotCall64              * 1.0-1    2021-02-11 [1] CRAN (R 4.0.2)
##  dplyr                  * 1.0.6    2021-05-05 [1] CRAN (R 4.0.2)
##  ellipsis                 0.3.2    2021-04-29 [1] CRAN (R 4.0.2)
##  evaluate                 0.14     2019-05-28 [1] CRAN (R 4.0.1)
##  ExperimentHub          * 1.16.1   2021-04-16 [1] Bioconductor  
##  fansi                    0.4.2    2021-01-15 [1] CRAN (R 4.0.2)
##  farver                   2.1.0    2021-02-28 [1] CRAN (R 4.0.2)
##  fastmap                  1.1.0    2021-01-25 [1] CRAN (R 4.0.2)
##  fda                    * 5.1.9    2020-12-16 [1] CRAN (R 4.0.2)
##  fds                    * 1.8      2018-10-31 [1] CRAN (R 4.0.2)
##  fields                 * 11.6     2020-10-09 [1] CRAN (R 4.0.2)
##  forcats                * 0.5.1    2021-01-27 [1] CRAN (R 4.0.2)
##  fs                       1.5.0    2020-07-31 [1] CRAN (R 4.0.2)
##  generics                 0.1.0    2020-10-31 [1] CRAN (R 4.0.2)
##  GenomeInfoDb           * 1.26.7   2021-04-08 [1] Bioconductor  
##  GenomeInfoDbData         1.2.4    2021-05-11 [1] Bioconductor  
##  GenomicRanges          * 1.42.0   2020-10-27 [1] Bioconductor  
##  ggbeeswarm               0.6.0    2017-08-07 [1] CRAN (R 4.0.2)
##  ggplot2                * 3.3.3    2020-12-30 [1] CRAN (R 4.0.2)
##  glue                     1.4.2    2020-08-27 [1] CRAN (R 4.0.2)
##  gridExtra                2.3      2017-09-09 [1] CRAN (R 4.0.2)
##  gtable                   0.3.0    2019-03-25 [1] CRAN (R 4.0.2)
##  haven                    2.4.1    2021-04-23 [1] CRAN (R 4.0.2)
##  hdrcde                   3.4      2021-01-18 [1] CRAN (R 4.0.2)
##  highr                    0.9      2021-04-16 [1] CRAN (R 4.0.2)
##  hms                      1.0.0    2021-01-13 [1] CRAN (R 4.0.2)
##  htmltools                0.5.1.1  2021-01-22 [1] CRAN (R 4.0.2)
##  httpuv                   1.6.1    2021-05-07 [1] CRAN (R 4.0.2)
##  httr                     1.4.2    2020-07-20 [1] CRAN (R 4.0.2)
##  interactiveDisplayBase   1.28.0   2020-10-27 [1] Bioconductor  
##  IRanges                * 2.24.1   2020-12-12 [1] Bioconductor  
##  irlba                    2.3.3    2019-02-05 [1] CRAN (R 4.0.2)
##  jpeg                     0.1-8.1  2019-10-24 [1] CRAN (R 4.0.2)
##  jquerylib                0.1.4    2021-04-26 [1] CRAN (R 4.0.2)
##  jsonlite                 1.7.2    2020-12-09 [1] CRAN (R 4.0.2)
##  KernSmooth               2.23-18  2020-10-29 [2] CRAN (R 4.0.5)
##  knitr                    1.33     2021-04-24 [1] CRAN (R 4.0.2)
##  ks                       1.12.0   2021-02-07 [1] CRAN (R 4.0.2)
##  labeling                 0.4.2    2020-10-20 [1] CRAN (R 4.0.2)
##  later                    1.2.0    2021-04-23 [1] CRAN (R 4.0.2)
##  lattice                  0.20-41  2020-04-02 [2] CRAN (R 4.0.5)
##  lifecycle                1.0.0    2021-02-15 [1] CRAN (R 4.0.2)
##  lubridate                1.7.10   2021-02-26 [1] CRAN (R 4.0.2)
##  magrittr                 2.0.1    2020-11-17 [1] CRAN (R 4.0.2)
##  maps                     3.3.0    2018-04-03 [1] CRAN (R 4.0.2)
##  MASS                   * 7.3-53.1 2021-02-12 [2] CRAN (R 4.0.5)
##  Matrix                 * 1.3-2    2021-01-06 [2] CRAN (R 4.0.5)
##  MatrixGenerics         * 1.2.1    2021-01-30 [1] Bioconductor  
##  matrixStats            * 0.58.0   2021-01-29 [1] CRAN (R 4.0.2)
##  mclust                   5.4.7    2020-11-20 [1] CRAN (R 4.0.2)
##  memoise                  2.0.0    2021-01-26 [1] CRAN (R 4.0.2)
##  mime                     0.10     2021-02-13 [1] CRAN (R 4.0.2)
##  misc3d                   0.9-0    2020-09-06 [1] CRAN (R 4.0.2)
##  modelr                   0.1.8    2020-05-19 [1] CRAN (R 4.0.2)
##  munsell                  0.5.0    2018-06-12 [1] CRAN (R 4.0.2)
##  muscData               * 1.4.0    2020-10-29 [1] Bioconductor  
##  mvtnorm                  1.1-1    2020-06-09 [1] CRAN (R 4.0.2)
##  pcaPP                  * 1.9-74   2021-04-23 [1] CRAN (R 4.0.2)
##  pillar                   1.6.0    2021-04-13 [1] CRAN (R 4.0.2)
##  pkgbuild                 1.2.0    2020-12-15 [1] CRAN (R 4.0.2)
##  pkgconfig                2.0.3    2019-09-22 [1] CRAN (R 4.0.2)
##  pkgload                  1.2.1    2021-04-06 [1] CRAN (R 4.0.2)
##  plot3D                 * 1.3      2019-12-18 [1] CRAN (R 4.0.2)
##  prettyunits              1.1.1    2020-01-24 [1] CRAN (R 4.0.2)
##  processx                 3.5.2    2021-04-30 [1] CRAN (R 4.0.2)
##  promises                 1.2.0.1  2021-02-11 [1] CRAN (R 4.0.2)
##  ps                       1.6.0    2021-02-28 [1] CRAN (R 4.0.2)
##  purrr                  * 0.3.4    2020-04-17 [1] CRAN (R 4.0.2)
##  R6                       2.5.0    2020-10-28 [1] CRAN (R 4.0.2)
##  rainbow                * 3.6      2019-01-29 [1] CRAN (R 4.0.2)
##  rappdirs                 0.3.3    2021-01-31 [1] CRAN (R 4.0.2)
##  Rcpp                     1.0.6    2021-01-15 [1] CRAN (R 4.0.2)
##  RCurl                  * 1.98-1.3 2021-03-16 [1] CRAN (R 4.0.2)
##  readr                  * 1.4.0    2020-10-05 [1] CRAN (R 4.0.2)
##  readxl                   1.3.1    2019-03-13 [1] CRAN (R 4.0.2)
##  remotes                  2.3.0    2021-04-01 [1] CRAN (R 4.0.2)
##  reprex                   2.0.0    2021-04-02 [1] CRAN (R 4.0.2)
##  rlang                    0.4.11   2021-04-30 [1] CRAN (R 4.0.2)
##  rmarkdown                2.8      2021-05-07 [1] CRAN (R 4.0.2)
##  rprojroot                2.0.2    2020-11-15 [1] CRAN (R 4.0.2)
##  RSQLite                  2.2.7    2021-04-22 [1] CRAN (R 4.0.2)
##  rstudioapi               0.13     2020-11-12 [1] CRAN (R 4.0.2)
##  rsvd                     1.0.5    2021-04-16 [1] CRAN (R 4.0.2)
##  rvest                    1.0.0    2021-03-09 [1] CRAN (R 4.0.2)
##  S4Vectors              * 0.28.1   2020-12-09 [1] Bioconductor  
##  sass                     0.3.1    2021-01-24 [1] CRAN (R 4.0.2)
##  scales                   1.1.1    2020-05-11 [1] CRAN (R 4.0.2)
##  scater                 * 1.18.6   2021-02-26 [1] Bioconductor  
##  scuttle                  1.0.4    2020-12-17 [1] Bioconductor  
##  sessioninfo              1.1.1    2018-11-05 [1] CRAN (R 4.0.2)
##  shiny                    1.6.0    2021-01-25 [1] CRAN (R 4.0.2)
##  SingleCellExperiment   * 1.12.0   2020-10-27 [1] Bioconductor  
##  spam                   * 2.6-0    2020-12-14 [1] CRAN (R 4.0.2)
##  sparseMatrixStats        1.2.1    2021-02-02 [1] Bioconductor  
##  stringi                  1.6.1    2021-05-10 [1] CRAN (R 4.0.5)
##  stringr                * 1.4.0    2019-02-10 [1] CRAN (R 4.0.2)
##  SummarizedExperiment   * 1.20.0   2020-10-27 [1] Bioconductor  
##  testthat                 3.0.2    2021-02-14 [1] CRAN (R 4.0.2)
##  tibble                 * 3.1.1    2021-04-18 [1] CRAN (R 4.0.2)
##  tidyr                  * 1.1.3    2021-03-03 [1] CRAN (R 4.0.2)
##  tidyselect               1.1.1    2021-04-30 [1] CRAN (R 4.0.2)
##  tidyverse              * 1.3.1    2021-04-15 [1] CRAN (R 4.0.2)
##  tinytex                  0.31     2021-03-30 [1] CRAN (R 4.0.2)
##  usethis                  2.0.1    2021-02-10 [1] CRAN (R 4.0.2)
##  utf8                     1.2.1    2021-03-12 [1] CRAN (R 4.0.2)
##  vctrs                    0.3.8    2021-04-29 [1] CRAN (R 4.0.2)
##  vipor                    0.4.5    2017-03-22 [1] CRAN (R 4.0.2)
##  viridis                  0.6.1    2021-05-11 [1] CRAN (R 4.0.5)
##  viridisLite              0.4.0    2021-04-13 [1] CRAN (R 4.0.2)
##  withr                    2.4.2    2021-04-18 [1] CRAN (R 4.0.2)
##  xfun                     0.22     2021-03-11 [1] CRAN (R 4.0.2)
##  xml2                     1.3.2    2020-04-23 [1] CRAN (R 4.0.2)
##  xtable                   1.8-4    2019-04-21 [1] CRAN (R 4.0.2)
##  XVector                  0.30.0   2020-10-28 [1] Bioconductor  
##  yaml                     2.2.1    2020-02-01 [1] CRAN (R 4.0.2)
##  zlibbioc                 1.36.0   2020-10-28 [1] Bioconductor  
## 
## [1] /Users/runner/work/_temp/Library
## [2] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
## only use this when working inside a git repository, don't worry if you don't know what this means
git2r::repository()
## Local:    master /Users/runner/work/HDA2020/HDA2020
## Remote:   master @ origin (https://github.com/statOmics/HDA2020)
## Head:     [d9699b7] 2021-05-11: Fix URL
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFJNYXJrZG93biIKYXV0aG9yOiAiTWlsYW4gTWFsZmFpdCIKZGF0ZTogJ2ByIGZvcm1hdChTeXMuRGF0ZSgpLCAiJUIgJWQsICVZIilgJwpvdXRwdXQ6CiAgICBodG1sX2RvY3VtZW50OgogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQotLS0KCiMgYC5SbWRgIGRvY3VtZW50cwoKV2l0aCBSTWFya2Rvd24gaXQgaXMgZWFzeSB0byBjcmVhdGUgZG9jdW1lbnRzIG9yIHdlYnBhZ2VzIHRoYXQgaW5jbHVkZSB0ZXh0LCBjb2RlIGFuZCBwbG90cy4gRHVyaW5nIHRoZSBwcmFjdGljYWwgc2Vzc2lvbnMgd2Ugd2lsbCB3b3JrIHdpdGggUk1hcmtkb3duLCBhbmQgbm90IHdpdGggYFJgIHNjcmlwdHMuIFJNYXJrZG93biBhbGxvd3MgeW91IHRvIGNvbWJpbmUgdGhlIGNvZGUgcmVxdWlyZWQgdG8gcHJvZHVjZSBhbiBhbmFseXNpcywgaXRzIHJlc3VsdHMsIHZpc3VhbGl6YXRpb25zIGFuZCBkZXNjcmlwdGl2ZSB0ZXh0IGFsbCBpbiBvbmUgZG9jdW1lbnQuCgpGb3IgYSBkZXRhaWxlZCBndWlkZSBvbiBSTWFya2Rvd24gc2VlIFtSIE1hcmtkb3duOiBUaGUgRGVmaW5pdGl2ZSBHdWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykuIE1vc3Qgb2YgdGhlIGNvbnRlbnRzIGRpc2N1c3NlZCBoZXJlIGNvbWUgZnJvbSB0aGF0IHNvdXJjZS4KCiMjIE1ldGFkYXRhCgpUaGUgbWFya2Rvd24gbm90ZWJvb2sgd2lsbCBzdGFydCB3aXRoIGEgW1lBTUxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1lBTUwpIGhlYWRlciwgd2hpY2ggaW5jbHVkZXMgdGhlIHRpdGxlLCBuYW1lcyBvZiB0aGUgYXV0aG9ycyBhbmQgdHlwZSBvZiBSTWFya2Rvd24gZmlsZS4gV2UgdHlwaWNhbGx5IHdvcmsgd2l0aCBgaHRtbF9kb2N1bWVudGAgKHRoZSBkZWZhdWx0KS4KCmBgYCB5YW1sCi0tLQp0aXRsZTogIlRpdGxlIgphdXRob3I6ICJBdXRob3IgbmFtZXMiCmRhdGU6ICJEYXRlIgpvdXRwdXQ6ICBodG1sX2RvY3VtZW50Ci0tLQpgYGAKClRoZSBgaHRtbF9kb2N1bWVudGAgb3V0cHV0IHNwZWNpZmllcyB0aGF0IHlvdXIgZG9jdW1lbnQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gSFRNTCB3aGVuIHlvdSAia25pdCIgb3IgY29tcGlsZSBpdC4gCgoKIyMgQ29tcGlsaW5nIGFuIFIgTWFya2Rvd24gZmlsZQoKRXNzZW50aWFsbHksIGFuIC5SbWQgZmlsZSBpcyBqdXN0IGEgcGxhaW4gdGV4dCBmaWxlIHVzZWQgdG8gc3RvcmUgYWxsIHlvdXIgdGV4dCBhbmQgY29kZSBuZWVkZWQgdG8gcHJvZHVjZSB5b3VyIGZpbmFsIHJlcG9ydC4gQWx0aG91Z2ggUlN0dWRpbyBhbGxvd3MgeW91IHRvIHByZXZpZXcgdGhlIG91dHB1dCBvZiB5b3VyIGNvZGUsIHRoZSBvdXRwdXQgaXMgbm90IGl0c2VsZiBwYXJ0IG9mIHRoZSAuUm1kIGZpbGUuIFdoZW4geW91IHNhdmUgYW5kIGNsb3NlIHlvdXIgUm1kIGZpbGUgYW5kIG9wZW4gaXQgYWdhaW4gbGF0ZXIgb3Igc2VuZCBpdCB0byBzb21lb25lLCB0aGUgb3V0cHV0IHdpbGwgaGF2ZSBkaXNhcHBlYXJlZCAoYWx0aG91Z2ggYWxzbyBoZXJlLCBSU3R1ZGlvIGhhcyBzb21lIHRyaWNrcyB0byBrZWVwIHRoZSBvdXRwdXQpLiBUaGUgd2F5IHRvIHByb3Blcmx5IGdlbmVyYXRlIHRoZSBvdXRwdXQgdmVyc2lvbiBvZiB5b3VyIFJtZCBmaWxlIGlzIGJ5IF9fY29tcGlsaW5nX18gaXQuIFRoaXMgY2FuIGJlIGRvbmUgaW4gUlN0dWRpbyBieSBwcmVzc2luZyB0aGUgYEtuaXRgIGJ1dHRvbiBpbiB0aGUgdG9vbGJhciwgb3IgYnkgcHJlc3NpbmcgYFNoaWZ0ICsgQ3RybCArIEtgIChNYWM6IGBTaGlmdCArIENtZCArIEtgKS4gVGhpcyB3aWxsIHByb2R1Y2UgYW4gSFRNTCBmaWxlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyB5b3VyIFJtZCBhbmQgbG9jYXRlZCBpbiB0aGUgc2FtZSBmb2xkZXIuIFlvdSBjYW4gb3BlbiB0aGlzIGZpbGUgaW4gYW55IGludGVybmV0IGJyb3dzZXIgKHlvdSBkb24ndCBuZWVkIGFuIGludGVybmV0IGNvbm5lY3Rpb24gc2luY2UgaXQncyBhIGxvY2FsIGZpbGUpIGFuZCBtYXJ2ZWwgYXQgdGhlIG5pY2VseSBmb3JtYXR0ZWQgb3V0cHV0IG9mIHlvdXIgaGFyZCB3b3JrLiBBbm90aGVyIGFkdmFudGFnZSBvZiB3b3JraW5nIHdpdGggUlN0dWRpbyBpcyB0aGF0IGl0IHdpbGwgb3BlbiB0aGlzIGZpbGUgYXV0b21hdGljYWxseSwgZWl0aGVyIGluIGEgbmV3IHdpbmRvdyBvciBpbiB0aGUgIlZpZXdlciIgcGFuZSAoeW91IGNhbiBjaGFuZ2UgdGhpcyBpbiB0aGUgUlN0dWRpbyBzZXR0aW5ncykuCgpfX0ltcG9ydGFudF9fOiBzYXZpbmcgeW91ciBSbWQgZmlsZSBkb2VzIF9fbm90X18gdXBkYXRlIHRoZSBjb3JyZXNwb25kaW5nIEhUTUwgZmlsZSBhdXRvbWF0aWNhbGx5LiBJbiBjb250cmFzdCwgd2hlbiB5b3UgY29tcGlsZSAoIktuaXQiKSwgeW91ciBSbWQgZmlsZSB3aWxsIGJlIHNhdmVkIGZpcnN0LiAKCldoaWxlIGVkaXRpbmcgeW91IGdlbmVyYWxseSB3YW50IHRvIHNhdmUgb2Z0ZW4gKHlvdSBkb24ndCB3YW50IHRvIGxvc2Ugc3R1ZmYgaWYgc29tZXRoaW5nIGdvZXMgd3JvbmcpIGJ1dCB5b3UgZG9uJ3QgbmVlZCB0byBjb21waWxlIGV2ZXJ5IHRpbWUgeW91IG1ha2UgYSBtaW5vciBjaGFuZ2UsIHVubGVzcyB5b3UgIHdhbnQgdG8gc2VlIHdoYXQgdGhlIG91dHB1dCB3aWxsIGxvb2sgbGlrZS4KCgojIyBGb3JtYXR0aW5nIHRleHQKCiMjIyBCb2xkIGFuZCBpdGFsaWMgdGV4dAoKVGV4dCBpbiBhbiBSIE1hcmtkb3duIGRvY3VtZW50IChpLmUuIGV2ZXJ5dGhpbmcgdGhhdCBpcyBub3QgY29uc2lkZXJlZCBjb2RlKSBpcyB3cml0dGVuIGluIFtNYXJrZG93biBzeW50YXhdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9tYXJrZG93bi1zeW50YXguaHRtbCkuIFRoaXMgZW5hYmxlcyB5b3UgdG8gZm9ybWF0IHRleHQgYnkgc3Vycm91bmRpbmcgaXQgd2l0aCBzcGVjaWFsIGNoYXJhY3RlcnMuCgoqSXRhbGljIHRleHQqIGlzIGdlbmVyYXRlZCBieSBzdXJyb3VuZGluZyB0aGUgdGV4dCB3aXRoIGEgcGFpciBvZiBlaXRoZXIgdW5kZXJzY29yZXMgKGBfdGV4dF9gKSBvciBhc3Rlcmlza3MgKGAqdGV4dCpgKS4gKipCb2xkIHRleHQqKiB1c2VzIGEgcGFpciBvZiBkb3VibGUgdW5kZXJzY29yZXMgKGBfX3RleHRfX2ApIG9yIGFzdGVyaXNrcyAoYCoqdGV4dCoqYCkuIF9fKkJvbGQgaXRhbGljIHRleHQqX18gY2FuIGJlIGFjaGlldmVkIGJ5IHVzaW5nIGEgY29tYmluYXRpb24gb2YgdGhlIHR3byAoYF9fKnRleHQqX19gKS4KCiMjIyBMaXN0cwoKVW5vcmRlcmVkIGxpc3QgaXRlbXMgc3RhcnQgd2l0aCBgKmAsIGAtYCwgb3IgYCtgLCBhbmQgeW91IGNhbiBuZXN0IG9uZSBsaXN0IHdpdGhpbiBhbm90aGVyIGxpc3QgYnkgaW5kZW50aW5nIHRoZSBzdWItbGlzdCwgZm9yIGV4YW1wbGU6CgpgYGBtYXJrZG93bgotIG9uZSBpdGVtCi0gb25lIGl0ZW0KLSBvbmUgaXRlbQogICAgKiBvbmUgbW9yZSBpdGVtCiAgICAqIG9uZSBtb3JlIGl0ZW0KICAgICogb25lIG1vcmUgaXRlbQpgYGAKClRoZSBvdXRwdXQgb2YgdGhlIGFib3ZlIHN5bnRheCB3b3VsZCBiZToKCi0gb25lIGl0ZW0KLSBvbmUgaXRlbQotIG9uZSBpdGVtCiAgICAqIG9uZSBtb3JlIGl0ZW0KICAgICogb25lIG1vcmUgaXRlbQogICAgKiBvbmUgbW9yZSBpdGVtCgoKQSBudW1iZXJlZCBsaXN0IGNhbiBiZSBjcmVhdGVkIGJ5IHN0YXJ0aW5nIGVhY2ggaXRlbSB3aXRoIGEgbnVtYmVyOgoKYGBgbWFya2Rvd24KMS4gdGhlIGZpcnN0IGl0ZW0KMi4gdGhlIHNlY29uZCBpdGVtCjMuIHRoZSB0aGlyZCBpdGVtCmBgYAoKT3V0cHV0OgoKMS4gdGhlIGZpcnN0IGl0ZW0KMi4gdGhlIHNlY29uZCBpdGVtCjMuIHRoZSB0aGlyZCBpdGVtCgpfX05vdGU6X18gbWFrZSBzdXJlIHRvIGxlYXZlIGFuIGVtcHR5IGxpbmUgYmV0d2VlbiB0ZXh0IGFuZCBhIGxpc3QgZm9yIGNvcnJlY3QgZm9ybWF0dGluZy4KCgojIyMgU2VjdGlvbiBoZWFkZXJzCgpTZWN0aW9uIGhlYWRlcnMgY2FuIGJlIHdyaXR0ZW4gdXNpbmcgYSBudW1iZXIgb2YgXCMgc2lnbnMsIHdoZXJlIHRoZSBhbW91bnQgb2YgXCMncyBzcGVjaWZpZXMgdGhlIGxldmVsOiAKCmBgYG1hcmtkb3duCiMgTWFpbiBzZWN0aW9uIHRpdGxlOiBmaXJzdCBsZXZlbAoKIyMgU3Vic2VjdGlvbjogc2Vjb25kIGxldmVsCgojIyMgU3ViLXN1YnNlY3Rpb246IHRoaXJkIGxldmVsCgojIyMjIFN1Yi1zdWItc3Vic2VjdGlvbjogZm91cnRoIGxldmVsCmBgYAoKVGhlIG91dHB1dDoKCiMgTWFpbiBzZWN0aW9uIHRpdGxlOiBmaXJzdCBsZXZlbAoKIyMgU3Vic2VjdGlvbjogc2Vjb25kIGxldmVsCgojIyMgU3ViLXN1YnNlY3Rpb246IHRoaXJkIGxldmVsCgojIyMjIFN1Yi1zdWItc3Vic2VjdGlvbjogZm91cnRoIGxldmVsCgpJbiBnZW5lcmFsIGl0J3Mgbm90IHJlY29tbWVuZGVkIHRvIGdvIGZ1cnRoZXIgdGhhbiA0IHN1Yi1sZXZlbHMgb2Ygc2VjdGlvbnMuCgpOb3RlIHRoYXQgeW91IGNhbiBhbHNvIGluY2x1ZGUgYSBbdGFibGUgb2YgY29udGVudHNdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9odG1sLWRvY3VtZW50Lmh0bWwjdGFibGUtb2YtY29udGVudHMpIGF0IHRoZSB0b3Agb2YgeW91ciBmaWxlIGJ5IHNwZWNpZnlpbmcgYHRvYzogdHJ1ZWAgaW4gdGhlIFlBTUwgaGVhZGVyLgoKCiMjIEludGVncmF0aW5nIHRleHQgYW5kIFIgY29kZQoKWW91IGNhbiBpbnNlcnQgY2h1bmtzIG9mIFIgY29kZSBpbiB5b3VyIFJNYXJrZG93biBmaWxlIGJ5IHdyYXBwaW5nIGEgY29kZSBibG9jayBpbnNpZGUgYGBgYCBgYGB7cn0gYGBgYCBhbmQgYGBgYCBgYGAgYGBgYC4KCkluIFJTdHVkaW8gdGhpcyBpcyBlYXNpbHkgZG9uZSBieSB1c2luZyB0aGUgYEluc2VydGAgYnV0dG9uIGluIHRoZSB0b29sYmFyIG9yIHRoZSBrZXlib2FyZCBzaG9yY3V0IGBDdHJsICsgQWx0ICsgSWAgKGBDbWQgKyBPcHRpb24gKyBJYCBvbiBtYWNPUykuCgpGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIFtzZWN0aW9uIDIuNl0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duL3ItY29kZS5odG1sKSBvZiAqVGhlIERlZmluaXRpdmUgR3VpZGUqCgpXZSB3aWxsIGRlbW9uc3RyZXRlIHRoZSB1c2Ugb2YgUi1jb2RlIHdpdGggdmFyaW91cyBleGFtcGxlcyBpbiB0aGUgc2VjdGlvbnMgYmVsb3cgc28gdGhhdCB5b3UgY2FuIGZhbWlsaWFyaXNlIHlvdXJzZWxmIHdpdGggdGhlIHN5bnRheC4KCgojIEJhc2ljIFIgc3R1ZmYKCiMjIFNpbXBsZSBjYWxjdWxhdGlvbnMKClIgY2FuIGJlIHVzZWQgYXMgYSBzaW1wbGUgY2FsY3VsYXRvci4gRXhlY3V0aW5nIGNvZGUgY2FuIGJlIGRvbmUgaW4gdmFyaW91cyB3YXlzLiBUbyBleGVjdXRlIHRoZSBlbnRpcmUgY2h1bmsgb2YgY29kZToKCiAtIEluIFJTdHVkaW86IGNsaWNrIHRoZSBncmVlbiBhcnJvdyBpbiB0aGUgdXBwZXIgcmlnaHQgY29ybmVyIG9mIHRoZSBjb2RlIGNodW5rCiAtIFBsYWNlIHlvdXIgY3Vyc29yIGluc2lkZSB0aGUgY2h1bmsgYW5kIHByZXNzIGBTaGlmdCArIEN0cmwgKyBFbnRlcmAgKE1hYzogYFNoaWZ0ICsgQ21kICsgRW50ZXJgKQogCkNvZGUgY2FuIGFsc28gYmUgcnVuIGxpbmUgYnkgbGluZSBieSBzZWxlY3RpbmcgYSBsaW5lIHdpdGggeW91ciBjdXJzb3IgYW5kIHByZXNzaW5nIGBDdHJsICsgRW50ZXJgIChNYWM6IGBDbWQgKyBFbnRlcmApLgoKVHJ5IGV4ZWN1dGluZyB0aGUgY29kZSBiZWxvdyB1c2luZyBib3RoIHdheXM6IGxpbmUtYnktbGluZSBhbmQgdGhlIGVudGlyZSBjaHVuay4KCmBgYHtyfQoxKzEKKDUtMykrNyoxMC8yCmBgYAoKVGhlIG91dHB1dCBzaG91bGQgYmUgZGlzcGxheWVkIGVpdGhlciByaWdodCBiZWxvdyB0aGUgY29kZSBjaHVuayBvciBpbiB0aGUgUiBjb25zb2xlLiBZb3UgY2FuIGNoYW5nZSB0aGlzIGJlaGF2aW91ciBieSBzZWxlY3RpbmcgdGhlIHNldHRpbmdzIGdlYXIgaW4gdGhlIFJTdHVkaW8gdG9vbGJhciBhbmQgc2VsZWN0aW5nIGBDaHVuayBPdXRwdXQgSW5saW5lYCBvciBgQ2h1bmsgT3V0cHV0IGluIENvbnNvbGVgLgoKWW91IGNhbiBhbHNvIHJ1biBhbGwgY2h1bmtzIGluIHlvdSBSbWQgZmlsZSBieSBwcmVzc2luZyB0aGUgYFJ1bmAgYnV0dG9uIGluIHRoZSB0b29sYmFyICh1cHBlciByaWdodCkgYW5kIHRoZW4gc2VsZWN0IGBSdW4gQWxsYCAob3IgdXNpbmcgdGhlIGtleWJvYXJkIHNob3J0Y3V0IGBTaGlmdCArIEN0cmwgKyBSYCBvbiBXaW5kb3dzIG9yIGBTaGlmdCArIENtZCArIFJgIG9uIE1hYykuIE5vdGUgdGhhdCB0aGlzIG1lbnUgYWxzbyBwcm92aWRlcyBhZGRpdGlvbmFsIHdheXMgb2YgcnVubmluZyBSIGNodW5rcywgdGhlIG1vc3QgdXNlZnVsIG9uZXMgYmVpbmc6CgogICogYFJ1biBBbGwgQ2h1bmtzIEFib3ZlYDogdGhpcyBleGVjdXRlcyBhbGwgY29kZSBjaHVua3MgcHJlY2VkaW5nIHlvdXIgY3Vyc29yIGxvY2F0aW9uLCBzdGFydGluZyBhdCB0aGUgdG9wIGFuZCB0ZWhuIHJ1bm5pbmcgZG93bi4KICAqIGBSZXN0YXJ0IFIgYW5kIFJ1biBBbGwgQ2h1bmtzYDogdGhpcyB3aWxsIHJlc3RhcnQgUiBhbmQgcmUtcnVuIHlvdXIgZW50aXJlIGRvY3VtZW50LiBOb3RlIHRoYXQgdGhpcyB3aWxsIF9fcmVtb3ZlIGFsbCBjdXJyZW50IG9iamVjdHMgYW5kIGRhdGEgZnJvbSBtZW1vcnlfXyBhbmQgcmUtc3RhcnRpbmcgUiBpbiBhIGJsYW5rIHN0YXRlLiBUaGlzIG1lYW5zIHRoYXQgYW55IGNvZGUgdGhhdCB3YXMgcnVuIGluIHRoZSBjb25zb2xlIGFuZCBub3Qgc2F2ZWQgaW4gYSBjb2RlIGNodW5rIHdpbGwgYmUgbG9zdC4gVGhpcyBtaWdodCBzZWVtIHNjYXJ5IGF0IGZpcnN0LCBidXQgdGhlcmUgYXJlIHZlcnkgZ29vZCByZWFzb25zIHRvIGRvIHRoaXMgb2Z0ZW4uIFlvdSBjYW4gcmVhZCBtb3JlIGFib3V0IHRoaXMgd29ya2Zsb3cgW2hlcmVdKGh0dHBzOi8vcnN0YXRzLnd0Zi9zYXZlLXNvdXJjZS5odG1sI3Jlc3RhcnQtci1vZnRlbi1kdXJpbmctZGV2ZWxvcG1lbnQpLgoKIyMgQ29tbWVudGluZyBSIGNvZGUKCllvdSBjYW4gYWRkIGNvbW1lbnRzIHRvIHlvdXIgUiBjb2RlIGJ5IHN0YXJ0aW5nIGEgbGluZSB3aXRoIFwjLiBUaGlzIGlzIHVzZWZ1bCB0byBkZXNjcmliZSB3aGF0IHlvdXIgY29kZSBpcyBkb2luZyAob3Igc2hvdWxkIGJlIGRvaW5nKS4gQW5ub3RhdGluZyB5b3VyIGNvZGUgdGhpcyB3YXkgaXMgdmVyeSB1c2VmdWwgdG8gY29tbXVuaWNhdGUgYm90aCB3aXRoIG90aGVycyBhbmQgeW91ciBmdXR1cmUgc2VsZi4gVHJ5IHRvIGtlZXAgdGhlc2UgY29tbWVudHMgY2xlYXIgYnV0IHNob3J0LiBMb25nZXIgZGVzY3JpcHRpb25zIHNob3VsZCBnbyBpbiB0aGUgbWFpbiB0ZXh0IG9mIHlvdXIgUk1hcmtkb3duIGZpbGUuIENvbW1lbnRpbmcgYWxzbyBwcm92aWRlcyBhIHdheSBvZiAiZGlzYWJsaW5nIiBjb2RlIHdpdGhvdXQgaGF2aW5nIHRvIHJlbW92ZSBpdC4gTm90ZSB0aGF0IGVhY2ggbmV3IGxpbmUgb2YgYSBjb21tZW50IHNob3VsZCBiZSBwcmVjZWRlZCBieSBhIFwjLiBZb3UgY2FuIGVhc2lseSAiY29tbWVudCBvdXQiIG11bHRpcGxlIGxpbmVzIGJ5IHNlbGVjdGluZyB0aGVtIGFuZCBwcmVzc2luZyBgU2hpZnQgKyBDdHJsICsgQ2AgKE1hYzogYFNoaWZ0ICsgQ21kICsgQ2ApLgoKVHJ5IHJ1bm5pbmcgdGhlIGNodW5rIGJlbG93IGFuZCB2ZXJpZnkgdGhhdCBpdCBkb2VzIG5vdCBwcm9kdWNlIGFueSBvdXRwdXQuIFdoYXQgaGFwcGVucyBpZiB5b3UgcmVtb3ZlIG9uZSBvZiB0aGUgXCMgc2lnbnM/CgpgYGB7cn0KIyBUaGlzIGlzIGEgY29tbWVudAoKIyBUaGlzIGlzIGEgdmVyeSBsb25nIGNvbW1lbnQgc3BsaXQgb3ZlcgojIG11bHRpcGxlIGxpbmVzCgojIENvZGUgaW5zaWRlIGEgY29tbWVudCBpcyBub3QgZXhlY3V0ZWQKIyAxKzEKYGBgCgoKIyMgQXNzaWduaW5nIG9iamVjdHMgdG8gc2F2ZSByZXN1bHRzIGFuZCBwZXJmb3JtIGNhbGN1bGF0aW9ucwoKWW91IGNhbiBzYXZlIHJlc3VsdHMgb2YgZnVuY3Rpb24gY2FsbHMgb3IgY2FsY3VsYXRpb25zIGJ5IGFzc2lnbmluZyB0aGUgdmFsdWUgdG8gYSAqdmFyaWFibGUqIHVzaW5nIHRoZSBhc3NpZ24gb3BlcmF0b3IgYDwtYC4KClJ1biB0aGUgY29kZSBiZWxvdyBhbmQgdmVyaWZ5IHRoZSB2YWx1ZSBvZiBgY2AuIFlvdSBjYW4gYWxzbyBjaGVjayB0aGUgdmFsdWUgb2YgYSB2YXJpYWJsZSBieSBlbnRlcmluZyBpdCBpbiB0aGUgQ29uc29sZSBhbmQgcHJlc3NpbmcgYEVudGVyYC4gCgpgYGB7cn0KYSA8LSAyCmIgPC0gMwpjIDwtIGEgKyBiCmMKYGBgCgpOb3RlIHRoYXQgaW4gcHJpbmNpcGxlLCB5b3UgY2FuIGFsc28gdXNlIGA9YCBmb3IgYXNzaWdubWVudCwgYnV0IHRoaXMgaXMgY29uc2lkZXJlZCB0byBiZSBiYWQgcHJhY3RpY2UgYmVjYXVzZSB0aGUgZXF1YWwgc2lnbiBpcyByZXNlcnZlZCBmb3IgZnVuY3Rpb24gYXJndW1lbnRzIChzZWUgbmV4dCBzZWN0aW9uKS4gU28geW91IHNob3VsZCBhbHdheXMgdXNlIGA8LWAgZm9yIGFzc2lnbm1lbnQuCgoqKkhpbnQ6KiogYSBxdWljayBhbmQgZWFzeSB3YXkgdG8gdHlwZSBgPC1gIGluIFJTdHVkaW8gaXMgYnkgdXNpbmcgdGhlIHNob3J0Y3V0IGBBbHQgKyAtYCAoTWFjOiBgT3B0aW9uICsgLWApLgoKCiMjIEZ1bmN0aW9ucwoKRnVuY3Rpb25zIGFyZSBjb21tYW5kcyBpbiBSIHRoYXQgcGVyZm9ybSBjZXJ0YWluIHRhc2tzLiBUaGV5IHRha2UgaW5wdXRzIGluIHRoZSBmb3JtIG9mICphcmd1bWVudHMqIGFuZCByZXR1cm4gdGhlaXIgcmVzdWx0cyBhcyAqb3V0cHV0Ki4gVGhleSBhcmUgY2FsbGVkIHVzaW5nIHRoZWlyIG5hbWUsIGZvbGxvd2VkIGJ5IHBhcmVudGhlc2VzIGAoKWAgaW4gd2hpY2ggdGhlIGFyZ3VtZW50cyBhcmUgc3BlY2lmaWVkLiBUaGVyZSBhcmUgbWFueSBidWlsdC1pbiBmdW5jdGlvbnMgaW4gUi4gSW4gYWRkaXRpb24sIHlvdSBjYW4gd3JpdGUgeW91ciBvd24gZnVuY3Rpb25zIG9yIGxvYWQgb3RoZXIgZnVuY3RpbnMgdGhyb3VnaCB0aGUgdXNlIG9mICpwYWNrYWdlcyogKG1vcmUgb24gdGhhdCBsYXRlcikuCgpBcyBhbiBleGFtcGxlLCB3ZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcm5vcm1gIHRvIHNhbXBsZSAxMDAgZHJhd3MgZnJvbSBhIE5vcm1hbCBkaXN0cmlidXRpb24uIFdlIGFzc2lnbiB0aGUgcmVzdWx0IChhIHZlY3RvciBvZiAxMDAgcmFuZG9tIG51bWJlcnMpIHRvIGEgbmV3IHZhcmlhYmxlIGBkcmF3c2AgYW5kIGRpc3BsYXkgdGhlIGZpcnN0IDYgdmFsdWVzIGJ5IGNhbGluZyB0aGUgZnVuY3Rpb24gYGhlYWRgIG9uIHRoaXMgbmV3IHZhcmlhYmxlLgoKYGBge3J9CiMgc2FtcGxlIDEwMCBudW1iZXJzIGZyb20gYSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uIAojIChtZWFuID0gMCwgc3RhbmRhcmQgZGV2aWF0aW9uID0gMSkKZHJhd3MgPC0gcm5vcm0oMTAwKQpoZWFkKGRyYXdzKQpgYGAKCgojIyBHZXR0aW5nIGhlbHAgaW4gUjogYD9gCgpXaGF0IGlmIGluc3RlYWQgb2YgZHJhd2luZyBmcm9tIHRoZSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uIHdlIHdhbnQgdG8gc2FtcGxlIGZyb20gYSBub3JtYWwgd2l0aCBhIG1lYW4gb2YgNSBhbmQgYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMj8gS25vd2luZyB0aGF0IGBybm9ybWAgaXMgdGhlIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIG51bWJlcnMsIHdlIGNhbiBnZXQgbW9yZSBpbmZvcm1hdGlvbiBvbiBpdCBieSBleGVjdXRpbmcgYD9ybm9ybWAgKHVzdWFsbHkgeW91IHdvdWxkIGRvIHRoaXMgaW4gdGhlIENvbnNvbGUsIGJ1dCBmb3IgZGVtb25zdHJhdGlvbiwgd2UgcnVuIGl0IGluc2lkZSBhIGNvZGUgY2h1bmsgaGVyZSkuIFRoaXMgd2lsbCBvcGVuIHVwIHRoZSAqaGVscCogcGFnZSBmb3IgdGhlICJUaGUgTm9ybWFsIERpc3RyaWJ1dGlvbiIgYW5kIGFsbCBpdHMgcmVsYXRlZCBmdW5jdGlvbnMgaW5zaWRlIFIsIG9uZSBvZiB3aGljaCBpcyBgcm5vcm1gLiAKCmBgYHtyLCBldmFsID0gRkFMU0V9Cj9ybm9ybQpgYGAKClJlYWQgdGhyb3VnaCB0aGUgZG9jdW1lbnRhdGlvbiwgY2FuIHlvdSBmaWd1cmUgb3V0IGhvdyB0byBjaGFuZ2UgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbj8KClRoZSBzb2x1dGlvbiBpcyB0byBzcGVjaWZ5IHRoZSBgbWVhbmAgYW5kIGBzZGAgYXJndW1lbnRzLgoKYGBge3J9CmRyYXdzMiA8LSBybm9ybSgxMDAsIG1lYW4gPSA1LCBzZCA9IDIpCmhlYWQoZHJhd3MyKQpgYGAKCkVhY2ggYnVpbHQtaW4gUiBmdW5jdGlvbiBvciBmdW5jdGlvbnMgbG9hZGVkIHRocm91Z2ggYSBwYWNrYWdlIGhhcyBhIGhlbHAgcGFnZS4gSW4gYWRkaXRpb24sIHRoZXJlIGlzIGEgd2VhbHRoIG9mIGluZm9ybWF0aW9uIHRocm91Z2ggdGhlIHdvbmRlcmZ1bCBtYWdpYyBvZiBbR29vZ2xlXShodHRwczovL3d3dy5nb29nbGUuY29tLykuIEFub3RoZXIgZ3JlYXQgcGxhY2UgdG8gbG9vayBmb3IgYW5zd2VycyBvciBhc2sgcXVlc3Rpb25zIHlvdXJzZWxmIGlzIFtTdGFja092ZXJmbG93XShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tLykuCgoKIyMgVGlkeXZlcnNlCgpUaGUgKnRpZHl2ZXJzZSogaXMgYSBzZXQgb2YgcGFja2FnZXMgZGVzaWduZWQgdG8gbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBtb3JlIHVzZXItZnJpZW5kbHkuCkl0IHNoYXJlcyBhIGNvbW1vbiBwaGlsb3NvcGh5IGFuZCBncmFtbWFyIG9mIGRvaW5nIGRhdGEgc2NpZW5jZSwgd2hpY2ggY2FuIGNoYW5nZSBzb21ld2hhdCBmcm9tIGhvdyBiYXNlIFIgd29ya3MgKHRob3VnaCBpdCBzaG91bGRuJ3QgYmUgYW4gZXhjdXNlIHRvIGxlYXJuIGhvdyB0byB1c2UgYmFzZSBSISEhKS4KCkluc3RlYWQgb2YgaW5zdGFsbGluZyBlYWNoICp0aWR5dmVyc2UqIHBhY2thZ2UgaW5kaXZpZHVhbGx5LCB5b3UgY2FuIGluc3RhbGwgYWxsIG9mIHRoZW0gc2ltdWx0YW5lb3VzbHkgYnkgc2ltcGx5IGNhbGxpbmcKCmBgYHtyLCBldmFsPUZBTFNFfSAKaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKYGBgCgpOb3RlIHRoYXQgdGhpcyBjb2RlIHdvbid0IGJlIGV4ZWN1dGVkIHdoZW4gY29tcGlsaW5nIHRoaXMgcmVwb3J0LCBiZWNhdXNlIEkgc3BlY2lmaWVkIGBldmFsPUZBTFNFYCBpbiB0aGUgW2NodW5rIG9wdGlvbnNdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi9yLWNvZGUuaHRtbCkuCkluc3RlYWQgaXQgc2hvdWxkIGJlIGNhbGxlZCBtYW51YWxseSwgZm9yIGV4YW1wbGUgaW4gYW4gUiBjb25zb2xlLgoKCkZvciBtb3JlIGluZm9ybWF0aW9uIHNlZSAKCi0gPGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvPgotIDxodHRwczovL3JhZmFsYWIuZ2l0aHViLmlvL2RzYm9vay90aWR5dmVyc2UuaHRtbD4KLSA8aHR0cHM6Ly9yNGRzLmhhZC5jby5uei8+CgoKCiMjIFZpc3VhbGl6YXRpb25zCgojIyMgQmFzZSBSCgpBIHBpY3R1cmUgb2Z0ZW4gc2F5cyBtb3JlIHRoYW4gd29yZHMgKG9yIGxpbmVzIG9mIGNvZGUgb3V0cHV0KSBhbmQgUiBoYXMgYSByaWNoIFt2aXN1YWxpemF0aW9uIHRvb2xib3hdKGh0dHBzOi8vcnN0dWRpby1wdWJzLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tLzc5NTNfNGUzZWZkNWI5NDE1NDQ0Y2EwNjViMTE2Nzg2MmMzNDkuaHRtbCkgdGhhdCBhbGxvd3MgdXMgdG8gbWFrZSBwb3dlcmZ1bCB2aXN1YWxpemF0aW9ucyBvZiBvdXIgZGF0YS4gCgpGb3IgZXhhbXBsZSwgdG8gdmlzdWFsbHkgdmVyaWZ5IHRoYXQgdGhlIHJhbmRvbSBudW1iZXJzIHdlIGdlbmVyYXRlZCBlYXJsaWVyICh3aGljaCBhcmUgc3RpbGwgc3RvcmVkIGluIG1lbW9yeSB1bmRlciB0aGUgdmFyaWFibGVzIGBkcmF3c2AgYW5kIGBkcmF3czJgKSBhcmUgaW5kZWVkIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB3ZSBjb3VsZCBtYWtlIGEgaGlzdG9ncmFtIG9mIHRoZW0sIHVzaW5nIHRoZSBgaGlzdGAgZnVuY3Rpb24uCgpgYGB7cn0KIyBkcmF3cyBjb21lcyBmcm9tIGEgc3RhbmRhcmQgbm9ybWFsIChtZWFuID0gMCwgc2QgPSAxKQpoaXN0KGRyYXdzKQoKIyBkcmF3cyAyIGNvbWVzIGZyb20gYSBub3JtYWwgd2l0aCBtZWFuID0gNSwgc2QgPSAyCmhpc3QoZHJhd3MyKQpgYGAKCk5vdGUgdGhhdCB5b3UgY2FuIGN1c3RvbWl6ZSB0aGVzZSBwbG90cyBpbiBhIGxvdCBvZiB3YXlzLiBMb29raW5nIGF0IHRoZSBoZWxwIHBhZ2Ugb2YgYGhpc3RgIG9yIGRvaW5nIGEgcXVpY2sgaW50ZXJuZXQgc2VhcmNoIHdpbGwgdGFrZSB5b3UgYSBsb25nIHdheSEKCgojIyMgZ2dwbG90MgoKQWx0aG91Z2ggcG93ZXJmdWwsIHRoZSBiYXNlIFIgdmlzdWFsaXphdGlvbiBmcmFtZXdvcmsgY2FuIGJlIHNvbWV3aGF0IGNoYWxsZW5naW5nIHRvIHdvcmsgd2l0aC4KQSBnb29kIGFsdGVybmF0aXZlIGlzIHRoZSBbYGdncGxvdDJgIHBhY2thZ2VdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyksIHBhcnQgb2YgdGhlIGxhcmdlciBgdGlkeXZlcnNlYCB3aGljaCBpbmNsdWRlcyBtb3JlIHVzZWZ1bCBwYWNrYWdlcyBmb3IgZGF0YSBtYW5pcHVsYXRpb24gYW5kIGFuYWx5c2lzLgpgZ2dwbG90MmAgdXNlcyBhIHZpc3VhbGl6YXRpb24gZnJhbWV3b3JrIGJhc2VkIG9uIHRoZSBbKmdyYW1tYXIgb2YgZ3JhcGhpY3MqIHBoaWxvc29waHldKGh0dHBzOi8vZ2dwbG90Mi1ib29rLm9yZy9pbnRyb2R1Y3Rpb24uaHRtbCN3aGF0LWlzLXRoZS1ncmFtbWFyLW9mLWdyYXBoaWNzKSwgd2hpY2ggd2Ugd29uJ3QgZ2V0IGZ1cnRoZXIgaW50byBoZXJlIGJ1dCB3aGljaCBjYW4gYmUgcXVpdGUgYW4gaW50dWl0aXZlIHdheSB0byB0aGluayBhYm91dCBkYXRhIHZpc3VhbGl6YXRpb25zLgoKYGdncGxvdDJgIHdvcmtzIGJlc3Qgd2l0aCBhIGBkYXRhLmZyYW1lYCBhcyBpbnB1dC4KQXMgYW4gZXhhbXBsZSwgd2UnbGwgdXNlIHRoZSBgbXRjYXJzYCBkYXRhLCB3aGljaCBpcyBhdmFpbGFibGUgYnkgZGVmYXVsdCBpbiBldmVyeSBSIGluc3RhbGxhdGlvbiAoZm9yIG1vcmUgaW5mbyBvbiB0aGlzIGRhdGEgc2V0LCBzZWUgYD9tdGNhcnNgKS4KV2l0aCBqdXN0IGEgZmV3IGxpbmVzLCB3ZSBjYW4gY3JlYXRlIGFscmVhZHkgcXVpdGUgZWxlZ2FudCB2aXN1YWxpemF0aW9uczoKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgpnZ3Bsb3QobXBnLCBhZXMoZGlzcGwsIGh3eSwgY29sb3VyID0gY2xhc3MpKSArIAogIGdlb21fcG9pbnQoKQpgYGAKCllvdSBjb3VsZCBwZXJmZWN0bHkgcmVjcmVhdGUgdGhpcyBwbG90IHdpdGggYmFzZSBSLCBidXQgaXQncyBnb2luZyB0byB0YWtlIG1vcmUgbGluZXMgb2YgY29kZSBhbmQgcG90ZW50aWFsIGhlYWRhY2hlcy4KU3RpbGwsIGJvdGggZnJhbWV3b3JrcyBoYXZlIHRoZWlyIHN0cmVuZ3RocyBhbmQgd2Vha25lc3NlcyBhbmQgdGhleSBhcmUgY29tcGxlbWVudGFyeSBpbiBtYW55IHdheXMsIHNvIGl0IHBheXMgdG8gbGVhcm4gYm90aCBvZiB0aGVtIHJhdGhlciB0aGFuIHN0dWJib3JubHkgc3RpY2tpbmcgdG8gb25lLgoKVGhlcmUgYXJlIHRvbnMgb2YgZG9jdW1lbnRhdGlvbiBhbmQgdHV0b3JpYWxzIG9uIGBnZ3Bsb3QyYCB0byBiZSBmb3VuZCBvbmxpbmUuCkEgZ29vZCBwbGFjZSB0byBzdGFydCBpcyA8aHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvPi4KCgojIyBJbXBvcnRpbmcgZGF0YQoKU2VlIDxodHRwczovL3I0ZHMuaGFkLmNvLm56L2RhdGEtaW1wb3J0Lmh0bWw+LgoKTm90ZSB0aGF0IGJvdGggdGhlIGJhc2UgYHJlYWQuY3N2YCBhbmQgdGhlICp0aWR5dmVyc2UqIGVxdWl2YWxlbnQgYHJlYWRyOjpyZWFkX2NzdigpYCBjYW4gYm90aCB1c2UgVVJMcyB0byByZWFkIGluIGRhdGEuClRoYXQgd2F5IHlvdSBkb24ndCBoYXZlIHRvIGRvd25sb2FkIHRoZSBkYXRhIGxvY2FsbHkgb24geW91ciBtYWNoaW5lIG9yIHdvcnJ5IGFib3V0IGRpZmZlcmVudCB2ZXJzaW9ucy4KCmBgYHtyfQojIyBFeGFtcGxlIGZyb20gSERBMjAyMCBjb3Vyc2UgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pby9IREEyMDIwLykKdWtfZm9vZHMgPC0gcmVhZHI6OnJlYWRfY3N2KAogIGZpbGUgPSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3N0YXRPbWljcy9IREEyMDIwL2RhdGEvdWtGb29kcy5jc3YiLAogIGNvbF9uYW1lcyA9IFRSVUUsCiAgY29sX3R5cGVzID0gY29scygpCikKdWtfZm9vZHMKYGBgCgoKCiMjIFN1bW1hcnkgb2YgZGF0YQoKVG8gZ2V0IGEgcXVpY2sgc3VtbWFyeSBvZiB0aGUgZGF0YSwgeW91IGNhbiB1c2UgdGhlIGBzdW1tYXJ5YCBmdW5jdGlvbi4gVGhpcyB3aWxsIHJldHVybiBzb21lIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIGNvbHVtbnMgcHJlc2VudCBpbiB0aGUgZGF0YS4KCmBgYHtyfQojIyBpcmlzIGlzIGEgZGVmYXVsdCBkYXRhIHNldCBhdmFpbGFibGUgaW4gUgojIyBUbyBnZXQgbW9yZSBpbmZvLCB1c2UgYD9pcmlzYApzdW1tYXJ5KGlyaXMpCmNsYXNzKGlyaXMpCmBgYAoKCiMjIFN1YnNldHRpbmcgZGF0YQoKWW91IGNhbiBzZWxlY3Qgc3Vic2V0cyBvZiBhIGBkYXRhLmZyYW1lYCBieSB1c2luZyBzcXVhcmUgYnJhY2tldHMgYFtdYCBhbmQgc3BlY2lmeWluZyB0aGUgbnVtYmVyKHMpIG9mIHRoZSByb3cocykgb3IgY29sdW1uKHMpIHlvdSB3YW50IHRvIHNlbGVjdC4gQWx0ZXJuYXRpdmVseSwgeW91IGNhbiB1c2UgdGhlIGRvbGxhciBzaWduIGAkYCB0byBzZWxlY3QgYSBjb2x1bW4gdXNpbmcgaXRzIG5hbWUuCgpUbyByZWR1Y2UgdGhlIG91dHB1dCBwcmludGVkIG91dCwgd2Ugd2lsbCBmaXJzdCBtYWtlIGEgc3Vic2V0IG9mIHRoZSBgaXJpc2AgZGF0YSBjb250YWluaW5nIGp1c3QgdGhlIGZpcnN0IDEwIHJvd3MuCgpgYGB7cn0KIyBtYWtlIHN1YnNldCBvZiBkYXRhIHRvIHByZXZlbnQgbG9uZyBvdXRwdXRzCmlyaXNfc3ViIDwtIGlyaXNbMToxMCwgXQppcmlzX3N1YgoKIyBTZWxlY3QgZmlyc3QgY29sdW1uLCBzaW5nbGUgYnJhY2tldHMgcmV0dXJucyBkYXRhLmZyYW1lCmlyaXNfc3ViWzFdCmlyaXNfc3ViWyJTZXBhbC5MZW5ndGgiXQojIGRvdWJsZSBicmFja2V0cyByZXR1cm5zIHZlY3RvcgppcmlzX3N1YltbMV1dCmlyaXNfc3ViW1siU2VwYWwuTGVuZ3RoIl1dCiMgdXNpbmcgdGhlIGRvbGxhciBzaWduLCBhbHNvIHJldHVybnMgdmVjdG9yCmlyaXNfc3ViJFNlcGFsLkxlbmd0aAoKIyBTZWxlY3QgYWxsIGNvbHVtbnMgZXhjZXB0IHRoZSBmaXJzdCBvbmUKaXJpc19zdWJbLTFdCgojIFNlbGVjdGluZyByb3dzCmlyaXNfc3ViWzEsIF0gIyBTZWxlY3QgdGhlIGZpcnN0IHJvdwppcmlzX3N1YlsxOjUsXSAjIFNlbGVjdCB0aGUgZmlyc3QgZml2ZSByb3dzCmlyaXNfc3ViW2MoMiwgNCksIF0gIyBzZWxlY3QgdGhlIHNlY29uZCBhbmQgZm91cnRoIHJvd3MKCiMgY29sdW1ucyBhbmQgcm93cwppcmlzX3N1YlsxOjUsICJTZXBhbC5MZW5ndGgiXSAjIGZpcnN0IDUgcm93cyBvZiAiU2VwYWwuTGVuZ3RoIiBjb2x1bW4KaXJpc19zdWJbMywgMl0gICMgdGhpcmQgcm93LCBzZWNvbmQgY29sdW1uCmBgYAoKCiMjIEluY2x1ZGluZyBSIG9iamVjdCB2YWx1ZXMgb3IgcmVzdWx0cyBpbiB0aGUgdGV4dAoKWW91IGNhbiBhZGQgaW5saW5lIFIgY29kZSByZXN1bHRzIGJ5IHdyYXBwaW5nIHRoZW0gaW5zaWRlIGBgIGByIGAgYGAuIFRoaXMgaXMgdXNlZnVsIGZvciBkaXNjdXNzaW5nIHRoZSB2YWx1ZSBvZiBhIHJlc3VsdCBpbiB5b3VyIHRleHQuIEluc3RlYWQgb2YgaGF2aW5nIHRvIGNvcHkgdGhlIHZhbHVlIG9mIGEgcmVzdWx0ICh3aGljaCBpcyBwcm9uZSB0byBlcnJvciBhbmQgbm90IHJvYnVzdCB0byBjaGFuZ2VzKSwgeW91IGNhbiBqdXN0IGNhbGwgaXQgaW5zaWRlIHRoZSB0ZXh0LiBGb3IgZXhhbXBsZSwgd2UgY291bGQgY2FsY3VsYXRlIHRoZSBtZWFuIHNlcGFsIGxlbmd0aCBvZiB0aGUgaXJpcyBmbG93ZXJzIGFzIGZvbGxvdzoKCmBgYHtyfQptZWFuKGlyaXMkU2VwYWwuTGVuZ3RoKQpgYGAKCldlIGNvdWxkIGNvcHkgdGhlIHZhbHVlIGluc2lkZSBvdXIgdGV4dCwgYnV0IGEgYmV0dGVyIHdheSBpcyBieSBqdXN0IHJ1bm5pbmcgdGhlIGNvZGUgaW5saW5lIGFzIGBtZWFuKGlyaXMkU2VwYWwuTGVuZ3RoKWAgc3Vycm91bmRlZCBieSBgYCBgciBgYCBhbmQgYGAgYCBgYC4gU28gd2UgY291bGQgc2F5IHRoYXQgdGhlIGlyaXMgZmxvd2VycyBpbiBvdXIgZGF0YSBoYXZlIGEgbWVhbiBsZW5ndGggb2YgYHIgbWVhbihpcmlzJFNlcGFsLkxlbmd0aClgLgoKTm90ZTogdG8gYWN0dWFsbHkgc2VlIHRoZSB2YWx1ZSBvZiB0aGUgaW5saW5lIGNvZGUsIHBsYWNlIHlvdXIgY3Vyc29yIGluc2lkZSB0aGUgYmFja3RpY2tzIGBgIGAgYHIgYGAgYW5kIHByZXNzIGBDdHJsICsgRW50ZXJgIG9yIGBDbWQgKyBFbnRlcmAuIFdoZW4geW91IGtuaXQgeW91ciBSbWQgZmlsZSBhbmQgYnVpbGQgdGhlIEhUTUwgb3V0cHV0LCB0aGUgaW5saW5lIFIgY29kZSB3aWxsIGJlIHJlcGxhY2VkIGJ5IGl0cyBvdXRwdXQgdmFsdWUuCgoKIyMgSW5jbHVkaW5nIGVxdWF0aW9ucwoKRmluYWxseSwgeW91IGNhbiBpbmNsdWRlIGVxdWF0aW9ucyBpbiB5b3VyIHRleHQgdXNpbmcgW0xhVGVYXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MYVRlWCkgc3ludGF4IGFuZCBzdXJyb3VuZGluZyBpdCBieSAgYSBwYWlyIG9mIGRvdWJsZSBkb2xsYXIgc2lnbnMgYCQkYC4gVGhpcyBpcyB1c2VmdWwgdG8gc3BlY2lmeSBtb2RlbHMuIEZvciBleGFtcGxlLCB3ZSBjYW4gd3JpdGUgdGhlIGVxdWF0aW9uIG9mIGEgbGluZWFyIG1vZGVsIGFzCgpgYGAKJCQKeV9pID0gXGJldGFfMCArIFxiZXRhXzEgeF9pICsgXGVwc2lsb25faQokJApgYGAKCldoaWNoIHdpbGwgYmUgY29udmVydGVkIHRvIHRoZSBmb2xsb3dpbmcgb3V0cHV0OgoKJCQKeV9pID0gXGJldGFfMCArIFxiZXRhXzEgeF9pICsgXGVwc2lsb25faQokJAoKTm90ZSB0aGF0IFJTdHVkaW8gd2lsbCBnaXZlIHlvdSBhIHByZXZpZXcgb2Ygd2hhdCB5b3VyIGVxdWF0aW9uIHdpbGwgbG9vayBsaWtlIGluIHRoZSBmaW5hbCBkb2N1bWVudC4KCllvdSBjYW4gYWxzbyBpbmNsdWRlIGlubGluZSAkXExhVGVYJCBlcXVhdGlvbnMgYnkgdXNpbmcgYSBwYWlyIG9mIHNpbmdsZSBgJGAgc2lnbnMuIEZvciBleGFtcGxlLCB0aGUgZm9sbG93aW5nIHNlbnRlbmNlOgoKYFRoZSBzYW1wbGUgbWVhbiBvZiAkeSQgaXMgZ2l2ZW4gYnkgJFxiYXJ7eX09XHN1bVxsaW1pdHNfe2k9MX1ee259XGZyYWN7eV9pfXtufSRgCgpXaWxsIGJlIGNvbnZlcnRlZCB0bzoKClRoZSBzYW1wbGUgbWVhbiBvZiAkeSQgaXMgZ2l2ZW4gYnkgJFxiYXJ7eX09XHN1bVxsaW1pdHNfe2k9MX1ee259XGZyYWN7eV9pfXtufSQKCgoKIyBVc2VmdWwgcmVzb3VyY2VzCgotIFtSIE1hcmtkb3duOiBUaGUgRGVmaW5pdGl2ZSBHdWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykKLSBbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56LykgYnkgSGFkbGV5IFdpY2toYW0gKG1haW4gYXV0aG9yIG9mIHRoZSBgdGlkeXZlcnNlYCBwYWNrYWdlcykKLSBbSW50cm9kdWN0aW9uIHRvIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yYWZhbGFiLmdpdGh1Yi5pby9kc2Jvb2svKSBieSBSYWZhZWwgSXJpemFycnkKLSBbV2hhdCBUaGV5IEZvcmdvdCB0byBUZWFjaCBZb3UgQWJvdXQgUl0oaHR0cHM6Ly9yc3RhdHMud3RmLyksIGZvciBzb21lIHVzZWZ1bCAiZ29vZCBwcmFjdGljZXMiIHRpcHMgd2hlbiB3b3JraW5nIHdpdGggUgoKCgojIFNlc3Npb24gSW5mbwoKRmluYWxseSwgaXQncyBhbHdheXMgZ29vZCBwcmFjdGljZSB0byBpbmNsdWRlIHRoZSBbU2Vzc2lvbiBJbmZvXSgpIGZvciB5b3VyIFIgc2Vzc2lvbiBpbiB5b3VyIGRvY3VtZW50LgpUaGF0IHdheSwgb3RoZXIgcGVyc29ucyAoaW5jbHVkaW5nIHlvdXIgZnV0dXJlIHNlbGYpIGxvb2tpbmcgYXQgeW91ciBkb2N1bWVudCBjYW4gc2VlIHdoYXQgdmVyc2lvbnMgb2YgUiBhbmQgbG9hZGVkIHBhY2thZ2VzIHdlcmUgdXNlZCwgd2hpY2ggY2FuIGJlIHF1aXRlIGVzc2VudGlhbCBmb3IgcmVwcm9kdWNpYmlsaXR5LgpUaGVyZSBhcmUgMiBvcHRpb25zLCBlaXRoZXIgdXNpbmcgdGhlIGJhc2UgUiBjb21tYW5kIGBzZXNzaW9uSW5mbygpYCBvciB1c2luZyBbdGhlIHZlcnNpb24gZnJvbSB0aGUgYGRldnRvb2xzYCBwYWNrYWdlXShodHRwczovL2RldnRvb2xzLnItbGliLm9yZy9yZWZlcmVuY2Uvc2Vzc2lvbl9pbmZvLmh0bWwpOiBgZGV2dG9vbHM6OnNlc3Npb25faW5mbygpYC4KVGhlaXIgb3V0cHV0cyBoYXZlIHNsaWdodGx5IGRpZmZlcmVudCBmb3JtYXR0aW5nIGJ1dCB0aGUgY29udGVudHMgYXJlIGVzc2VudGlhbGx5IHRoZSBzYW1lLgpQZXJzb25hbGx5LCBJIHByZWZlciB0aGUgYGRldnRvb2xzYCB2ZXJzaW9uLCBidXQgdGhpcyBpcyByZWFsbHkgYSBwZXJzb25hbCBjaG9pY2UuCgpZb3UgY2FuIGFsc28gaW5jbHVkZSB0aGUgZGF0ZSB3aXRoIGBTeXMudGltZSgpYCBzbyB5b3UgaGF2ZSBhIHRpbWUgc3RhbXAgb2Ygd2hlbiB0aGUgcmVwb3J0IHdhcyBjb21waWxlZC4KSWYgeW91IGhhcHBlbiB0byBiZSB3b3JraW5nIGluc2lkZSBhIGdpdCByZXBvc2l0b3J5LCBgZ2l0MnI6OnJlcG9zaXRvcnkoKWAgaXMgYSB1c2VmdWwgZnVuY3Rpb24gdGhhdCBkaXNwbGF5cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY3VycmVudCBgZ2l0YCBzdGF0ZSBhbmQgdGhlIGxhc3QgY29tbWl0LiAKCmBgYHtyIHNlc3Npb25faW5mbywgY2FjaGU9RkFMU0V9ClN5cy50aW1lKCkKZGV2dG9vbHM6OnNlc3Npb25faW5mbygpCgojIyBvbmx5IHVzZSB0aGlzIHdoZW4gd29ya2luZyBpbnNpZGUgYSBnaXQgcmVwb3NpdG9yeSwgZG9uJ3Qgd29ycnkgaWYgeW91IGRvbid0IGtub3cgd2hhdCB0aGlzIG1lYW5zCmdpdDJyOjpyZXBvc2l0b3J5KCkKYGBgCgojIFtIb21lXShodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8vSERBMjAyMC8pIHstfQo=