How to use an R
Markdown file
This is an R Markdown
Notebook. When you execute code within the notebook, the results appear
beneath the code.
Try executing this chunk by clicking the Run button within
the chunk or by placing your cursor inside it and pressing
Ctrl+Shift+Enter.
plot(cars)
Add a new chunk by clicking
- CLicking Code -> Insert on toolbar.
2. Add chunk via the
command palette
- Press Ctrl+Alt+I
- Just type out the formatting, e.g. three back ticks, curly brackets
containing
r
, and three more back ticks to finish the
block
When you save the notebook, an HTML file containing the code and
output will be saved alongside it (click the Preview button or
press Ctrl+Shift+K to
preview the HTML file).
one <- 1
one
R basics
Setting the working
directory
R needs to know which folder on your computer you are working in.
There are various ways to do this.
The easy way, using
the GUI
Within
RStudio go to Session >> Set Working Directory > Choose Directory...
You also have an option to set the working directory to the most
recently-loaded .R or .Rmd file.
The difficult way,
using Code.
To do this type
setwd("path/to/directory")
Unfortunately, if you are on a windows machine you will need to
change all backslashes \
to forward slashes /
.
This is because R follows UNIX conventions which are native to Linux and
Mac computers.
If you are not sure what your working directory is type
getwd()
Getting the right path is a vital first step in R, and you really
need to know how to do this. Here are some instructional videos if you
get stuck…
For Windows computers refer to this YouTube
video. For Macs refer to this YouTube
video. If you’re on Linux then refer to this YouTube
video
However this is a big problem with this approach. If you send your
file to someone else who is working on a different machine, it is most
likely that your path will be pointing to the wrong location
The difficult way
(2) (but by far the best way!)
By far the best way to set the working directory is create an “R
Project” in RStudio. When you do this, the RProject keeps track of the
directory where the files are stored, so there is no need to set the
working directory.
In addition, if you set up a project you can use it to store all the
datasets and other data objects which were opened in the last session.
This is quite convenient but it can take up a lot of memory, and you
also run the risk that you will lose track of how the variables were
created, which is a threat to reproducibility.
Using R as a
calculator
We can use the console for general arithmetic
1 + 3 + 5
(2 + 9) / 7
1 + 2+ 3
We can also create variables, e.g.
x <- 10 # This is a comment
x = 10 # Does the same thing!!
y <- 21
x*y
Functions
Most work in R is done using Functions. These take the
following form: function(argument(s)). Here are some
functions
sqrt(10)
seq(1, 10, 2)
rep(5, 10)
EX 1 & 2: Working
with Functions
EX1: What do the arguments of seq
and rep
do? To find out more search for the relevant help file in the console by
typing ?seq
or by using Google.
EX2: Have a look at the following arguments called gsub
and grepl
. What do they do? Clue: if you’re stuck, search
the help file using ?
gsub("R-studio", "Rstudio", "R-studio is a great piece of software")
grepl("chocolate", "Mary likes chocolate cookies")
DIY functions
It’s possible to create your own functions. This
makes R extremely powerful and extendible. We’re not going to cover
making your own functions in this course, but it’s important to be aware
of this capability. There are plenty of good resources online for
learning how to do this, including this
one
Getting help
As we have seen above, to find out about a particular function just
type ?
and the name of the function into the console,
e.g. ?grepl
. This accesses the help files on your computer.
If you’d like to search more broadly type ??grepl
and your
computer will look online for relevant materials on CRAN (the main R
website)
Help files in R are quite densely written and not particularly aimed
at beginners. Fortunately there are loads of excellent resources on the
internet. Here are some really good sites:
- https://www.tidyverse.org/
- A brilliant set of of resources on all things related to the
tidyverse, Hadley Wickham’s brilliant suite of packages
- https://www.statmethods.net/index.html
- a quick way of looking up basic R techniques
- https://stats.idre.ucla.edu/r/modules/
- https://rseek.org/ - a search
engine for all things related to R (because the word ‘R’ brings up a
whole load of irrelevant stuff in Google)
- http://www.cookbook-r.com/
- this has lots of tips on how to do graphics.
And there are plenty more! If you find a good one share it with your
colleagues via email, Twitter, or whatever social media you prefer!
Packages
Installation
To enhance the basic capabilities of R, we need to load
packages/libraries. Most of the time, we download these from ‘CRAN’
Tools > Install packages
or
install.packages()
. Once the package/library is installed
(i.e. it is sitting somewhere on your computer), we then need to
load it to the current R session using the
library()
function.
Remember using a package/library is a two-stage process. We
Install
the package/library onto your computer (from
the internet)
Load
the package/library into your current session
using the library command.
One of the most useful packages is called ‘tidyverse’.
If your first code block is called “settings” then the code for that
block will be automatically run when you open the file. So it is useful
to load all of your packages in this first block.
One package I always load at the start is the
tidyverse
It contains a number of useful commands for plots, and data
manipulation.
Note that
Install the ‘tidyverse’ package, and then load it with the following
function:
library(tidyverse)
I find that a particularly easy way to load packages is via the
p_load
function from the pacman
library. This
will check if the package has been loaded into the current session. If
not it will search to find out if the package has been stored in your
computer. If the package is not in your computer it will automatically
find it. It basically does everything you need! However, we are not
going to practise using it, but just to let you know that it exists!
Obtaining help
To find out more about a package type ?package_name
in
the console. Alternatively you can look for the package documentation on
CRAN.
Using functions from
packages
Most of the functions loaded in a package should work ‘out of the
box’. However occasionally you need to refer to the package first, and
then the function using the format
package_name::function_from_that_package
. This is useful
for a variety of reasons:
- It allows you to use a function from a package without having to
load that package
- It helps in cases where you load two packages which contain two
different functions which happen to have the same name.
- Sometimes, even when a package is loaded, you need to precede a
function by the package name. (I am not sure why this happens…).
However, most of the time this is not necessary.
EX 3 - Using
packages
- Install and load the package
ggplot2
- Look up the function
geom_point
from this package. What
does it do?
Objects, data frames
and indices
Objects
A variable is a type of ‘object’ which R stores in memory. R is
capable of creating and storing a wide range of objects. To see what
type of object we have created, we use the function
class()
, e.g.
x <- 1
class(x)
z <- "hello"
class(z)
class is one of the most useful functions in R as errors are
often due to misassignment of class, e.g.
x + z
Here we have tried to add a number to a string which is clearly
impossible. It’s possible to change the class of an object using
commands such as as.character
, as.integer
,
as.numeric
, as.factor
, e.g.
one <- "1"
x + one
one <- as.numeric(one)
x + one
Here is a list of the main object classes in R:
- Numeric - a number with decimal places
- Integer - a number without decimal places
- Character - a string of letters/numbers
- Vector - an ordered list of numbers or characters, or
multi-character strings. NB each number, character, or character string
is also an object. So you can have objects within objects!
- Dataframe - a 2 x 2 array in which each column has a name
- List - this is like a vector, except it is capable of storing
multiple object classes, e.g. it can contain both numbers and
strings.
In order to create a vector we need to use the c
function. (c = ‘combine’), e.g.
list.of.numbers <- c(1,4,54,22,43,9,0,0,21)
mean(list.of.numbers)
sd(list.of.numbers)
a.character.vector <- c("Mary", "Jane", "Ali", "Chen")
a.list <- as.list(c(1, 2, "Mary", "Jane"))
Creating a data frame
from scratch
A data frame is a two-dimensional object containing variables and row
numbers. It’s basically a spreadsheet.
The following code creates a data frame programmatically. It creates
two variables, and combines them together to make a data frame. Note
that to do this we need to use the functions as.data.frame
and cbind
.
list.of.movies <- c("Independence Day", "Pretty Woman", "The Godfather Part
Two", "Planet of the Apes (original)")
rotten.tomatoes.variable <- c(62, 61, 97, 89)
df <- as.data.frame(cbind(list.of.movies, rotten.tomatoes.variable)) # 'cbind' binds columns together
Viewing the contents
of a data frame
To glimpse the top few rows type
head(name_of_data_frame)
in the console, e.g.
head(df)
To view the data frame in the ‘source’ window, type
View(name_of_data_frame)
in the console, .e.g.
View(df) #NB first letter is a capital letter.
Referring to
variables
To refer to variables, use the following syntax
data_frame_name$variable_name
, e.g.
df$list.of.movies
When naming variables we can use dots and underscores,
e.g. df$list.of.movies
and df$list_of_movies
.
We can use numbers as long as they don’t come at the beginning,
e.g. df$list_of_movies.v3
.
If you use this convention, then the names for variables can get very
long. However, it’s generally useful, as in R you often have multiple
data frames loaded into memory. By specifiying both the name of the data
frame and the variable, this avoids confusion.
Try to be consistent with your naming conventions. I tend to use
underscores to name variables,
e.g. data.frame.x$variable_y
. This is also what Hadley
Wickham recommends (Have a look at the Tidyverse Style Guide)
If you’d like to see all the variable names in a data frame type
names(data_frame)
, e.g.
names(df)
Indices
Whenever you wish to access the contents of an object with multiple
values (e.g. a data frame) you use indexes. These are placed inside
square brackets, e.g. [1]
. Have a look at the following
example:
vector = c(1, 4, 2, 99, 0.5, 10)
vector[1]
vector[2]
vector[5]
vector[2:5]
mean(vector[2:5])
Here is how we would use vectors with a datafrome
df[1,2]
df[1,] # here the second number is blank
df[,2] # here the first number is blank
EX 3 - understanding
indices
What does each number refer to? What happens when we leave a blank
cell?
Reading data frames
from files using code
However, rather than use the menu, it’s much better to use actual
code, as this will automate the process. Let’s import a dataset on World
Happiness Report (2017), by country. The files are WHR_2017.xlsx, WHR_2017.sav, and WHR_2017.csv. Alternatively you can actually
download the data set straight from the URL (below)
# This code depends on using the `tidyverse` and `haven` packages
# If you have not imported / loaded them, you need to so
# library(tidyverse)
# library(haven)
df <- readxl::read_excel("WHR_2017.xlsx") # Read an excel file
df <- haven::read_spss("WHR_2017.sav") # Read from an SPSS file
df <- read_csv("WHR_2017.csv") # Read from a .csv file
#Or to download straight from the URL!!
df <- read_csv("https://verbingnouns.github.io/AdventuresInR/docs/WHR_2017.csv")
Possibly the best data format to work in is the .csv
data format (Comma-Separated Value). This is good because it is readable
in Excel, small, simple, and not easily-corrupted. It’s only
disadvantage is that it does not support Excel formulas or formatting
(NB some would say this is an advantage as Excel formulae are not that
reliability and not very consistent with scientific reproducibility)
To read .csv files we use the read.csv()
function from
base R, or read_csv()
from the tidyverse (I would go with
the latter as it also shows you a list of the variable types)
Subsetting a data set
using (a) base R and (d) dplyr
Subsetting with base
R
We’re going to subset the WHR dataset (i.e. choose only
those cases/observations which fulfil a specific criterion). To do this
we’re going to use the which()
function. When you apply
which
to a variable in a dataset, it will produce indices
(indexes) of the rows which fulfil a certain criterion,
e.g. which(df$var_name == 2)
will give you the indices of
all rows where the value of the variable is 2.
EX4: Subsetting using
base R
Armed with this knowledge, your task is to subset the data frame so
that it only contains information from African countries.
If you’re stuck have a look at the answer below.
df.Africa <- df[which(df$region == "Africa"), ]
Piping
Okay, the above code is pretty horrible, so we’re going to explore an
alternative using the package dplyr
which is from the
tidyverse
. But before we can use dplyr
we have
to learn how to ‘pipe’.
Pipes are written in R as %>%
(note you must use a
percentage sign before and after the pipe). To demonstrate what pipes
do, I have a look at the following pseudocode.
All pipes do is enable us to ‘pass’ a data frame (or another object)
to a new function without having to keep on specifying the data frame.
In addition, we can chain pipes together indefinitely.
Here’s how we would subset the data frame using piping:
df.Africa <- filter(df, region == "Africa") # This is the version without piping
df %>% filter(region == "Africa") -> df.Africa # This is the version with piping. It looks longer, but we can chain multiple functions together!
Note that to create a new data frame, we need a solid arrow at the
end. If we don’t include that solid arrow, the results are shown in the
console, but no new data frame is created. This is an incredibly useful
feature of pipes. You can try before you buy
!
And here is an example where we chain a series of pipes
together:
df %>%
group_by(region) %>%
summarise(mean.happiness = mean(happiness_score)) ->
df.mean.happiness.by.region
NB When piping the code becomes more readable when the line ends with
the pipe.
There are a couple of important points to note.
- We can refer to variables without specifying the data frame
- If we wish to store the results we must output them using and arrow
->
. If we don’t store the results they will merely be
displayed in the console.
Piping is a key technique in R and once you’ve learnt it you will
write much more powerful and readable code.
As well as using pipes to create data frame, you can also insert
pipes into both analyses and figures! Here is an example of a pipe
inserted within an ANOVA.
# An ANOVA without a pipe. NB we are using the base function "aov". If you would like to conduct SPSS-style ANOVAs, the best package is called "afex".
mod <- aov(happiness_rank ~ region, data = df)
pacman::p_load(broom) # To load the "tidy" function.
tidy(mod)
# Here we use a pipe inside the analysis
mod <- aov(happiness_rank ~ region, # NB note we can break the line after a comma
data = df %>% filter(region == "Africa" | region == "South America"))
tidy(mod)
Note how I have broken some of the lines after a comma. This makes
the code more readable. Generally we can break a line when it ends in
some kind of symbol, e.g. a pipe, an arrow, or a comma.
Loops and if-then
statements
Loops and if-then statements are useful programming tools which have
the same structure: FUNCTION (STATEMENT) {.....}
.
Loops
for(i in 1:10){
print(as.character(i))
}
EX5: Loops
The code below creates a sequence ranging from 0 to 30 going up in
steps of 0.25. Try to achieve the same result using a loop
seq(0,30,2.5)
If-then
statements
To demonstrate if-then statements, we are going to create a new
variable which shows if the happiness index is above the mean
df$happiness_above_mean <- 0 # Set variable to 0
mean_happiness <- mean(df$happiness_score) # Calculate mean mpg
for (i in 1:nrow(df)){
if(df$happiness_score[i] > mean_happiness){
df$happiness_above_mean[i] <- 1
}
}
And here is the same process using dplyr
, which avoids
the loop and the if-then statement.
df %>%
mutate(happiness_above_mean = as.numeric(happiness_score > mean(happiness_score))) ->
df
Note loops and if-then statements are quite verbose, and there is
almost always a neater and much shorter alternatives. However, I think
they are useful procedures for the relative beginner.
Here is the way to create the variable without using the
tidyverse
df <- read_csv("WHR_2017.csv")
df$happiness_above_mean <- as.numeric(df$happiness_score > mean(df$happiness_score))
So how does this work? The statement in brackets evaluates to TRUE /
FALSE. We then turn this into a number using as.numeric
.
TRUE evaluates to 1, while FALSE evaluates to 0.
It can be quite useful to chain statements. For example, if we wish
to identify countries where both the happiness score and life expectancy
are above the mean, we could do this….
df$happiness_and_LE_above_mean <- as.numeric((df$happiness_score > mean(df$happiness_score)) & (df$life_expectancy > mean(df$life_expectancy)))
## EX6: Creating variables
Try to identify countries where both the GDP per capita and trust in
the government are above the mean.
Stored results
Whenever you run an analysis in R and save that to an object, the
object has an internal structure. To demonstrate this, let’s do a simple
regression using the mtcars dataset:
df <- read.csv("WHR_2017.csv")
head(df)
Let’s draw a plot looking at the relationship between GDP per capita
and Happiness Score. We’re not going to focus on the code, which will be
covered in the next session.
g <- ggplot(aes(x = df$gdp_per_capita, y = df$happiness_score), data = df)
g <- g + geom_point()
g <- g + geom_smooth()
g
Now let’s run a regression. Again, we’re not going going to focus on
the code, which will be covered in the final session.
mod <- lm(happiness_score ~ gdp_per_capita, data = df) # mod = "model"
pacman::p_load(broom) # Broom is a package which produces neat tables of results
tidy(mod) # This is a broom function which tidies up the statistical results for reporting
Now, let’s have a look at the structure
of this model.
There are two ways to do this:
- Use the
str
function, e.g. str(mod)
- Type
mod$
, and then use autocomplete.
We can see that the $
symbol has a dual function in R:
firstly, to specify variables within dataframes, and secondly to specify
subcomponents of an object.
It is useful to be able to refer to subcomponents of an object so
that we can integrate into our report, e.g. the regression yielded a
value of
EX 6: Let’s put it
all together!!!
- Download the data for life
expectancy by country
- The data covers many years. Select the most recent year.
- Merge the data with the “WHR” data (you will need to merge using the
“country” variable)
- Draw plots of (a) life expectancy against GDP per capita, (b) life
expectancy against family values
Once you get stuck have a look at the first code chunk below. This
contains the solution but with pesky errors added! See if you can sort
out the errors.
whr <- read_csv("WHR_2017.csv")
le <- read_csv("WHO_life_expectancy.csv")
whr %>% # NB we need to ensure that the "country" variable has exactly the same name in both datasets
rename(country = Country) ->
whr
le %>%
filter(Year == 2015) %>%
merge(whr) %>% doc
df
plot(df$`Life expectancy`, df$GDP)
plot(df$`Life expectancy`, df$family)
The code in this chunk shows the solution!
whr <- read_csv("WHR_2017.csv")
le <- read_csv("WHO_life_expectancy.csv")
whr %>%
rename(Country = country) ->
whr
le %>%
filter(Year == 2015) %>%
merge(whr) ->
df
plot(df$`Life expectancy`, df$GDP)
plot(df$`Life expectancy`, df$family)
LS0tCnRpdGxlOiAiU2Vzc2lvbiAxIC0gSW50cm9kdWN0aW9uLlJtZCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnMicKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6CiAgICBkZl9wcmludDogcGFnZWQKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAyCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogbm8KLS0tCgpgYGB7ciBzZXR0aW5nc30KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGFjbWFuKQpgYGAKCgoKIyBUaGUgcHVycG9zZSBvZiB0aGlzIGNvdXJzZQoKLSBBbiBpbnRyb2R1Y3Rpb24gdG8gYmFzaWMgdGVjaG5pcXVlcyBpbiBSCiFbXShpbWFnZXMvY3Jhd2wtd2Fsay1ydW4tZmx5LnBuZykKLSBBbiBpbnRlcmRpc2NpcGxpbmFyeSBhcHByb2FjaCB0byBSLCBlLmcuIHJlZ3Jlc3Npb24gbW9kZWxsaW5nIGZvciBwc3ljaG9sb2dpc3RzLCBhbmQgdGV4dCBhbmFseXNpcyBmb3IgZGlnaXRhbCBodW1hbml0aWVzCgojIFdoeSBSPwoKLSAqT3BlbiBTb3VyY2UqCiAgLSBtZWFucyB0aGF0IGFuYWx5c2VzIGFyZSAoYSkgY3V0dGluZyBlZGdlIGFuZCAoYikgYWNjdXJhdGUKLSAqU3Ryb25nIGVtcGhhc2lzIG9uIHJlcHJvZHVjaWJsZSByZXNlYXJjaCoKICAtIGRhdGEgYXJlIChhKSBhY2N1cmF0ZWx5IHJlcG9ydGVkIChiKSBzaGFyZWFibGUKCiMgSG93IHRvIHVzZSBhbiBSIE1hcmtkb3duIGZpbGUKClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5CnBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouCgoKCmBgYHtyIHBsb3QgY2Fyc30KcGxvdChjYXJzKQpgYGAKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZwoKMS4gQ0xpY2tpbmcgQ29kZSAtPiBJbnNlcnQgb24gdG9vbGJhci4KCiFbXShpbWFnZXMvYWRkX2NvZGVfYmxvY2tfdmlhX21lbnUucG5nKQoyLiBBZGQgY2h1bmsgdmlhIHRoZSBjb21tYW5kIHBhbGV0dGUKCiFbXShpbWFnZXMvaW5zZXJ0X2NodW5rX3ZpYV9jb21tYW5kX3BhbGV0dGUucG5nKQoKMy4gUHJlc3MgKkN0cmwrQWx0K0kqCjQuIEp1c3QgdHlwZSBvdXQgdGhlIGZvcm1hdHRpbmcsIGUuZy4gdGhyZWUgYmFjayB0aWNrcywgY3VybHkgYnJhY2tldHMgY29udGFpbmluZyBgcmAsIGFuZCB0aHJlZSBtb3JlIGJhY2sgdGlja3MgdG8gZmluaXNoIHRoZSBibG9jawoKCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byAgICAKcHJldmlldyB0aGUgSFRNTCBmaWxlKS4KCmBgYHtyIGFzc2lnbiB2YWx1ZXMgdG8gYSB2YXJpYWJsZX0Kb25lIDwtIDEKb25lCmBgYAoKCiMgUlN0dWRpbyBicmVha2Rvd24KCiMjIFBhbmVzCgpSU3R1ZGlvIHNob3dzIHlvdSBmb3VyIHBhbmVzOgoKMS4gVGhlICdTb3VyY2UnIHBhbmU6IHRoZSBmaWxlIHdoZXJlIHlvdSB3cml0ZSB5b3VyIGNvZGUuIFRoaXMgaXMgdGhlIGNvZGUgdGhhdCB5b3Ugd2lsbCBiZSBzYXZpbmcgdG8geW91ciBjb21wdXRlciBvbiBhIHJlZ3VsYXIgYmFzaXMuCjIuIFRoZSAnQ29uc29sZScgd2hlcmUgYWN0dWFsIGNvZGUgaXMgcnVuLiBUaGUgb3V0cHV0IGlzIHRlbXBvcmFyeSBhbmQgeW91IGRvIG5vdCB0ZW5kIHRvIHNhdmUgdGhpcy4KMy4gVGhlICdFbnZpcm9ubWVudCcgcGFuZSwgd2hpY2ggc2hvd3MgeW91IHZhcmlhYmxlcyAvIGRhdGFzZXRzCjMuIFRoZSAnVmlld2VyJyBwYW5lLCB3aGljaCBzaG93cyB5b3UgcGxvdHMsIGhlbHAgZmlsZXMgYW5kIG90aGVyIHVzZWZ1bCB0aGluZ3MuCgohW10oaW1hZ2VzL2NvbnNvbGVfZXRjLnBuZykKCgpZb3UgY2FuIGFycmFuZ2UgdGhlc2UgaW4gYW55IG9yZGVyIHVzaW5nIFRvb2xzID4gR2xvYmFsIE9wdGlvbnMuCgohW10oaW1hZ2VzL3BhbmVzLnBuZykKCgojIyBBdXRvY29tcGxldGUKClJTdHVkaW8gaGFzIGZhbnRhc3RpYyBhdXRvY29tcGxldGUgY2FwYWJpbGl0ZXMuIFRvIGF1dG9jb21wbGV0ZSBqdXN0IHByZXNzIFRBQi4gVGhpcyBpcyBlc3BlY2lhbGx5IHVzZWZ1bCB3aGVuIGxvYWRpbmcgZmlsZXMgYXMgdXNpbmcgYXV0b2NvbXBsZXRlIHdpbGwgaGVscCB5b3UgdG8gaWRlbnRpZnkgcmVsZXZhbnQgb25lcy4KCiMgUiBiYXNpY3MKCiMjIFNldHRpbmcgdGhlIHdvcmtpbmcgZGlyZWN0b3J5CgpSIG5lZWRzIHRvIGtub3cgd2hpY2ggZm9sZGVyIG9uIHlvdXIgY29tcHV0ZXIgeW91IGFyZSB3b3JraW5nIGluLiBUaGVyZSBhcmUgdmFyaW91cyB3YXlzIHRvIGRvIHRoaXMuCgojIyMgVGhlIGVhc3kgd2F5LCB1c2luZyB0aGUgR1VJCgpXaXRoaW4gYFJTdHVkaW8gZ28gdG8gU2Vzc2lvbiA+PiBTZXQgV29ya2luZyBEaXJlY3RvcnkgPiBDaG9vc2UgRGlyZWN0b3J5Li4uYAoKIVtdKHNldHdkLnBuZykKCllvdSBhbHNvIGhhdmUgYW4gb3B0aW9uIHRvIHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnkgdG8gdGhlIG1vc3QgcmVjZW50bHktbG9hZGVkIC5SIG9yIC5SbWQgZmlsZS4KCiMjIyBUaGUgZGlmZmljdWx0IHdheSwgdXNpbmcgQ29kZS4KClRvIGRvIHRoaXMgdHlwZQoKYHNldHdkKCJwYXRoL3RvL2RpcmVjdG9yeSIpYAoKVW5mb3J0dW5hdGVseSwgaWYgeW91IGFyZSBvbiBhIHdpbmRvd3MgbWFjaGluZSB5b3Ugd2lsbCBuZWVkIHRvIGNoYW5nZSBhbGwKYmFja3NsYXNoZXMgYFxgIHRvIGZvcndhcmQgc2xhc2hlcyBgL2AuIFRoaXMgaXMgYmVjYXVzZSBSIGZvbGxvd3MgVU5JWCBjb252ZW50aW9ucyB3aGljaCBhcmUgbmF0aXZlIHRvIExpbnV4IGFuZCBNYWMgY29tcHV0ZXJzLgoKSWYgeW91IGFyZSBub3Qgc3VyZSB3aGF0IHlvdXIgd29ya2luZyBkaXJlY3RvcnkgaXMgdHlwZQoKYGdldHdkKClgCgpHZXR0aW5nIHRoZSByaWdodCBwYXRoIGlzIGEgdml0YWwgZmlyc3Qgc3RlcCBpbiBSLCBhbmQgeW91IHJlYWxseSBuZWVkIHRvIGtub3cgaG93IHRvIGRvIHRoaXMuIEhlcmUgYXJlIHNvbWUgaW5zdHJ1Y3Rpb25hbCB2aWRlb3MgaWYgeW91IGdldCBzdHVjay4uLgoKRm9yIFdpbmRvd3MgY29tcHV0ZXJzIHJlZmVyIHRvIFt0aGlzIFlvdVR1YmUgdmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9UXpTVjh3dkExRG8pLiBGb3IgTWFjcyByZWZlciB0byBbdGhpcyBZb3VUdWJlIHZpZGVvXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PTQzVzlUdVB3cWFjKS4gSWYgeW91J3JlIG9uIExpbnV4IHRoZW4gcmVmZXIgdG8gW3RoaXMgWW91VHViZSB2aWRlb10oaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUSkKCkhvd2V2ZXIgdGhpcyBpcyBhIGJpZyBwcm9ibGVtIHdpdGggdGhpcyBhcHByb2FjaC4gSWYgeW91IHNlbmQgeW91ciBmaWxlIHRvIHNvbWVvbmUgZWxzZSB3aG8gaXMgd29ya2luZyBvbiBhIGRpZmZlcmVudCBtYWNoaW5lLCBpdCBpcyBtb3N0IGxpa2VseSB0aGF0IHlvdXIgcGF0aCB3aWxsIGJlIHBvaW50aW5nIHRvIHRoZSB3cm9uZyBsb2NhdGlvbgoKIyMjIFRoZSBkaWZmaWN1bHQgd2F5ICgyKSAoYnV0IGJ5IGZhciB0aGUgYmVzdCB3YXkhKQoKQnkgZmFyIHRoZSBiZXN0IHdheSB0byBzZXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5IGlzIGNyZWF0ZSBhbiAiUiBQcm9qZWN0IiBpbiBSU3R1ZGlvLiBXaGVuIHlvdSBkbyB0aGlzLCB0aGUgUlByb2plY3Qga2VlcHMgdHJhY2sgb2YgdGhlIGRpcmVjdG9yeSB3aGVyZSB0aGUgZmlsZXMgYXJlIHN0b3JlZCwgc28gdGhlcmUgaXMgbm8gbmVlZCB0byBzZXQgdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKSW4gYWRkaXRpb24sIGlmIHlvdSBzZXQgdXAgYSBwcm9qZWN0IHlvdSBjYW4gdXNlIGl0IHRvIHN0b3JlIGFsbCB0aGUgZGF0YXNldHMgYW5kIG90aGVyIGRhdGEgb2JqZWN0cyB3aGljaCB3ZXJlIG9wZW5lZCBpbiB0aGUgbGFzdCBzZXNzaW9uLiBUaGlzIGlzIHF1aXRlIGNvbnZlbmllbnQgYnV0IGl0IGNhbiB0YWtlIHVwIGEgbG90IG9mIG1lbW9yeSwgYW5kIHlvdSBhbHNvIHJ1biB0aGUgcmlzayB0aGF0IHlvdSB3aWxsIGxvc2UgdHJhY2sgb2YgaG93IHRoZSB2YXJpYWJsZXMgd2VyZSBjcmVhdGVkLCB3aGljaCBpcyBhIHRocmVhdCB0byByZXByb2R1Y2liaWxpdHkuCgojIyBVc2luZyBSIGFzIGEgY2FsY3VsYXRvcgoKV2UgY2FuIHVzZSB0aGUgY29uc29sZSBmb3IgZ2VuZXJhbCBhcml0aG1ldGljCgpgYGB7ciBzaW1wbGUgbWF0aHN9CgoxICsgMyArIDUKKDIgKyA5KSAvIDcKCjEgKyAyKyAzCgpgYGAKCldlIGNhbiBhbHNvIGNyZWF0ZSB2YXJpYWJsZXMsIGUuZy4KCmBgYHtyIGNyZWF0aW5nIHZhcmlhYmxlc30KCnggPC0gMTAgIyBUaGlzIGlzIGEgY29tbWVudAp4ID0gMTAgIyBEb2VzIHRoZSBzYW1lIHRoaW5nISEKeSA8LSAyMQp4KnkKCmBgYAoKCgojIyBDb21tZW50cwoKSWYgeW91J2QgbGlrZSB0byBjb21tZW50IG9uIGFueSBjb2RlIHlvdSB3cml0ZSAoaS5lLiB5b3UgZG8gbm90IHdpc2ggUiB0byB0cnkgdG8gJ3J1bicgdGhpcyBjb2RlKSBqdXN0IGFkZCBhIGhhc2ggKGAjYCkgb3Igc2VyaWVzIG9mIGhhc2hlcyBpbiBmcm9udCBvZiBpdCwgZS5nLgoKYGRmIDwtIHJlYWQuY3N2KCJjc3ZfZmlsZS5jc3YiKSAjIFRoaXMgcmVhZHMgaW4gdGhlIG1haW4gZmlsZSBmb3IgdGhlIGV4cGVyaW1lbnRgCgpJdCBpcyBnb29kIHByYWN0aWNlIHRvIG1ha2UgYSBsb3Qgb2YgY29tbWVudHMsIGVzcGVjaWFsbHkgd2hlbiB5b3UgYXJlIGp1c3Qgc3RhcnRpbmcgb3V0IGluIFIuIFRoZXkgd2lsbCBoZWxwIHRvIHlvdSByZW1pbmQgeW91IG9mIHdoYXQgdGhlIGNvZGUgZG9lcywgYW5kIHlvdSBjb3VsZCBhbHNvIHVzZSB0aGVtIHRvIGhpZ2hsaWdodCBhbnkgZGlmZmljdWx0aWVzIHlvdSBoYXZlIGhhZCwgdGhpbmdzIHlvdSBuZWVkIHRvIGJlIGNhcmVmdWwgYWJvdXQsIHVzZWZ1bCBvbmxpbmUgcmVzb3VyY2VzIGV0Yy4KCiFbXShpbWFnZXMvY29tbWVudHNfY2FydG9vbi5wbmcpCgojIyBGdW5jdGlvbnMKCk1vc3Qgd29yayBpbiBSIGlzIGRvbmUgdXNpbmcgX0Z1bmN0aW9uc18uIFRoZXNlIHRha2UgdGhlIGZvbGxvd2luZyBmb3JtOgpfZnVuY3Rpb24oYXJndW1lbnQocykpXy4gSGVyZSBhcmUgc29tZSBmdW5jdGlvbnMKCmBgYHtyIGV4YW1wbGVzIG9mIGZ1bmN0aW9uc30KCnNxcnQoMTApCgpzZXEoMSwgMTAsIDIpCgpyZXAoNSwgMTApCgpgYGAKCiMjIEVYIDEgJiAyOiBXb3JraW5nIHdpdGggRnVuY3Rpb25zCgpFWDE6IFdoYXQgZG8gdGhlIGFyZ3VtZW50cyBvZiBgc2VxYCBhbmQgYHJlcGAgZG8/IFRvIGZpbmQgb3V0IG1vcmUgc2VhcmNoIGZvciB0aGUgcmVsZXZhbnQgaGVscCBmaWxlIGluIHRoZSBjb25zb2xlIGJ5IHR5cGluZyBgP3NlcWAgb3IgYnkgdXNpbmcgR29vZ2xlLgoKRVgyOiBIYXZlIGEgbG9vayBhdCB0aGUgZm9sbG93aW5nIGFyZ3VtZW50cyBjYWxsZWQgYGdzdWJgIGFuZCBgZ3JlcGxgLiBXaGF0IGRvIHRoZXkgZG8/IENsdWU6IGlmIHlvdSdyZSBzdHVjaywgc2VhcmNoIHRoZSBoZWxwIGZpbGUgdXNpbmcgYD9gCmBgYHtyfQoKZ3N1YigiUi1zdHVkaW8iLCAiUnN0dWRpbyIsICJSLXN0dWRpbyBpcyBhIGdyZWF0IHBpZWNlIG9mIHNvZnR3YXJlIikKCmdyZXBsKCJjaG9jb2xhdGUiLCAiTWFyeSBsaWtlcyBjaG9jb2xhdGUgY29va2llcyIpCgpgYGAKCgojIyBESVkgZnVuY3Rpb25zCgpJdCdzIHBvc3NpYmxlIHRvICoqY3JlYXRlIHlvdXIgb3duIGZ1bmN0aW9ucyoqLiBUaGlzIG1ha2VzIFIgZXh0cmVtZWx5IHBvd2VyZnVsIGFuZCBleHRlbmRpYmxlLiBXZSdyZSBub3QgZ29pbmcgdG8gY292ZXIgbWFraW5nIHlvdXIgb3duIGZ1bmN0aW9ucyBpbiB0aGlzIGNvdXJzZSwgYnV0IGl0J3MgaW1wb3J0YW50IHRvIGJlIGF3YXJlIG9mIHRoaXMgY2FwYWJpbGl0eS4gVGhlcmUgYXJlIHBsZW50eSBvZiBnb29kIHJlc291cmNlcyBvbmxpbmUgZm9yIGxlYXJuaW5nIGhvdyB0byBkbyB0aGlzLCBpbmNsdWRpbmcgW3RoaXMgb25lXShodHRwczovL3d3dy5zdGF0bWV0aG9kcy5uZXQvbWFuYWdlbWVudC91c2VyZnVuY3Rpb25zLmh0bWwpCgojIyBHZXR0aW5nIGhlbHAKCkFzIHdlIGhhdmUgc2VlbiBhYm92ZSwgdG8gZmluZCBvdXQgYWJvdXQgYSBwYXJ0aWN1bGFyIGZ1bmN0aW9uIGp1c3QgdHlwZSBgP2AgYW5kIHRoZSBuYW1lIG9mIHRoZSBmdW5jdGlvbiBpbnRvIHRoZSBjb25zb2xlLCBlLmcuIGA/Z3JlcGxgLiBUaGlzIGFjY2Vzc2VzIHRoZSBoZWxwIGZpbGVzIG9uIHlvdXIgY29tcHV0ZXIuIElmIHlvdSdkIGxpa2UgdG8gc2VhcmNoIG1vcmUgYnJvYWRseSB0eXBlIGA/P2dyZXBsYCBhbmQgeW91ciBjb21wdXRlciB3aWxsIGxvb2sgb25saW5lIGZvciByZWxldmFudCBtYXRlcmlhbHMgb24gQ1JBTiAodGhlIG1haW4gUiB3ZWJzaXRlKQoKSGVscCBmaWxlcyBpbiBSIGFyZSBxdWl0ZSBkZW5zZWx5IHdyaXR0ZW4gYW5kIG5vdCBwYXJ0aWN1bGFybHkgYWltZWQgYXQgYmVnaW5uZXJzLiBGb3J0dW5hdGVseSB0aGVyZSBhcmUgbG9hZHMgb2YgZXhjZWxsZW50IHJlc291cmNlcyBvbiB0aGUgaW50ZXJuZXQuIEhlcmUgYXJlIHNvbWUgcmVhbGx5IGdvb2Qgc2l0ZXM6CgooYSkgW2h0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLykgLSBBIGJyaWxsaWFudCBzZXQgb2Ygb2YgcmVzb3VyY2VzIG9uIGFsbCB0aGluZ3MgcmVsYXRlZCB0byB0aGUgdGlkeXZlcnNlLCBIYWRsZXkgV2lja2hhbSdzIGJyaWxsaWFudCBzdWl0ZSBvZiBwYWNrYWdlcwooYikgW2h0dHBzOi8vd3d3LnN0YXRtZXRob2RzLm5ldC9pbmRleC5odG1sXShodHRwczovL3d3dy5zdGF0bWV0aG9kcy5uZXQvaW5kZXguaHRtbCkgLSBhIHF1aWNrIHdheSBvZiBsb29raW5nIHVwIGJhc2ljIFIgdGVjaG5pcXVlcwooYykgW2h0dHBzOi8vc3RhdHMuaWRyZS51Y2xhLmVkdS9yL21vZHVsZXMvXShodHRwczovL3N0YXRzLmlkcmUudWNsYS5lZHUvci9tb2R1bGVzLykKKGQpIFtodHRwczovL3JzZWVrLm9yZy9dKGh0dHBzOi8vcnNlZWsub3JnLykgLSBhIHNlYXJjaCBlbmdpbmUgZm9yIGFsbCB0aGluZ3MgcmVsYXRlZCB0byBSIChiZWNhdXNlIHRoZSB3b3JkICdSJyBicmluZ3MgdXAgYSB3aG9sZSBsb2FkIG9mIGlycmVsZXZhbnQgc3R1ZmYgaW4gR29vZ2xlKQooZSkgW2h0dHA6Ly93d3cuY29va2Jvb2stci5jb20vXShodHRwOi8vd3d3LmNvb2tib29rLXIuY29tLykgLSB0aGlzIGhhcyBsb3RzIG9mIHRpcHMgb24gaG93IHRvIGRvIGdyYXBoaWNzLgoKQW5kIHRoZXJlIGFyZSBwbGVudHkgbW9yZSEgSWYgeW91IGZpbmQgYSBnb29kIG9uZSBzaGFyZSBpdCB3aXRoIHlvdXIgY29sbGVhZ3VlcyB2aWEgZW1haWwsIFR3aXR0ZXIsIG9yIHdoYXRldmVyIHNvY2lhbCBtZWRpYSB5b3UgcHJlZmVyIQoKIyBQYWNrYWdlcwoKIyMgSW5zdGFsbGF0aW9uCgpUbyBlbmhhbmNlIHRoZSBiYXNpYyBjYXBhYmlsaXRpZXMgb2YgUiwgd2UgbmVlZCB0byBsb2FkIHBhY2thZ2VzL2xpYnJhcmllcy4gTW9zdCBvZiB0aGUKdGltZSwgd2UgZG93bmxvYWQgdGhlc2UgZnJvbSAnQ1JBTicgYFRvb2xzID4gSW5zdGFsbCBwYWNrYWdlc2Agb3IgYGluc3RhbGwucGFja2FnZXMoKWAuIE9uY2UgdGhlIHBhY2thZ2UvbGlicmFyeSBpcyBpbnN0YWxsZWQgKGkuZS4gaXQgaXMgc2l0dGluZyBzb21ld2hlcmUgb24geW91ciBjb21wdXRlciksIHdlIHRoZW4gbmVlZCB0byBfbG9hZF8gaXQgdG8gdGhlIGN1cnJlbnQgUiBzZXNzaW9uIHVzaW5nIHRoZSBgbGlicmFyeSgpYCBmdW5jdGlvbi4KClJlbWVtYmVyIHVzaW5nIGEgcGFja2FnZS9saWJyYXJ5IGlzIGEgdHdvLXN0YWdlIHByb2Nlc3MuIFdlCgoxLiBgSW5zdGFsbGAgdGhlIHBhY2thZ2UvbGlicmFyeSBvbnRvIHlvdXIgY29tcHV0ZXIgKGZyb20gdGhlIGludGVybmV0KQoyLiBgTG9hZGAgdGhlIHBhY2thZ2UvbGlicmFyeSBpbnRvIHlvdXIgY3VycmVudCBzZXNzaW9uIHVzaW5nIHRoZSBsaWJyYXJ5IGNvbW1hbmQuCgpPbmUgb2YgdGhlIG1vc3QgdXNlZnVsIHBhY2thZ2VzIGlzIGNhbGxlZCAndGlkeXZlcnNlJy4KCklmIHlvdXIgZmlyc3QgY29kZSBibG9jayBpcyBjYWxsZWQgInNldHRpbmdzIiB0aGVuIHRoZSBjb2RlIGZvciB0aGF0IGJsb2NrIHdpbGwgYmUgYXV0b21hdGljYWxseSBydW4gd2hlbiB5b3Ugb3BlbiB0aGUgZmlsZS4gU28gaXQgaXMgdXNlZnVsIHRvIGxvYWQgYWxsIG9mIHlvdXIgcGFja2FnZXMgaW4gdGhpcyBmaXJzdCBibG9jay4KCk9uZSBwYWNrYWdlIEkgYWx3YXlzIGxvYWQgYXQgdGhlIHN0YXJ0IGlzIHRoZSBgdGlkeXZlcnNlYAoKIVtdKGltYWdlcy90aWR5dmVyc2UucG5nKQoKSXQgY29udGFpbnMgYSBudW1iZXIgb2YgdXNlZnVsIGNvbW1hbmRzIGZvciBwbG90cywgYW5kIGRhdGEgbWFuaXB1bGF0aW9uLgoKTm90ZSB0aGF0CgpJbnN0YWxsIHRoZSAndGlkeXZlcnNlJyBwYWNrYWdlLCBhbmQgdGhlbiBsb2FkIGl0IHdpdGggdGhlIGZvbGxvd2luZyBmdW5jdGlvbjoKCmBgYHtyIGxvYWRpbmcgdGhlIHRpZHl2ZXJzZX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKSSBmaW5kIHRoYXQgYSBwYXJ0aWN1bGFybHkgZWFzeSB3YXkgdG8gbG9hZCBwYWNrYWdlcyBpcyB2aWEgdGhlIGBwX2xvYWRgIGZ1bmN0aW9uIGZyb20gdGhlIGBwYWNtYW5gIGxpYnJhcnkuIFRoaXMgd2lsbCBjaGVjayBpZiB0aGUgcGFja2FnZSBoYXMgYmVlbiBsb2FkZWQgaW50byB0aGUgY3VycmVudCBzZXNzaW9uLiBJZiBub3QgaXQgd2lsbCBzZWFyY2ggdG8gZmluZCBvdXQgaWYgdGhlIHBhY2thZ2UgaGFzIGJlZW4gc3RvcmVkIGluIHlvdXIgY29tcHV0ZXIuIElmIHRoZSBwYWNrYWdlIGlzIG5vdCBpbiB5b3VyIGNvbXB1dGVyIGl0IHdpbGwgYXV0b21hdGljYWxseSBmaW5kIGl0LiBJdCBiYXNpY2FsbHkgZG9lcyBldmVyeXRoaW5nIHlvdSBuZWVkISBIb3dldmVyLCB3ZSBhcmUgbm90IGdvaW5nIHRvIHByYWN0aXNlIHVzaW5nIGl0LCBidXQganVzdCB0byBsZXQgeW91IGtub3cgdGhhdCBpdCBleGlzdHMhCgojIyBPYnRhaW5pbmcgaGVscAoKVG8gZmluZCBvdXQgbW9yZSBhYm91dCBhIHBhY2thZ2UgdHlwZSBgP3BhY2thZ2VfbmFtZWAgaW4gdGhlIGNvbnNvbGUuIEFsdGVybmF0aXZlbHkgeW91IGNhbiBsb29rIGZvciB0aGUgcGFja2FnZSBkb2N1bWVudGF0aW9uIG9uIFtDUkFOXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy8pLgoKIyMgVXNpbmcgZnVuY3Rpb25zIGZyb20gcGFja2FnZXMKCk1vc3Qgb2YgdGhlIGZ1bmN0aW9ucyBsb2FkZWQgaW4gYSBwYWNrYWdlIHNob3VsZCB3b3JrICdvdXQgb2YgdGhlIGJveCcuIEhvd2V2ZXIgb2NjYXNpb25hbGx5IHlvdSBuZWVkIHRvIHJlZmVyIHRvIHRoZSBwYWNrYWdlIGZpcnN0LCBhbmQgdGhlbiB0aGUgZnVuY3Rpb24gdXNpbmcgdGhlIGZvcm1hdCBgcGFja2FnZV9uYW1lOjpmdW5jdGlvbl9mcm9tX3RoYXRfcGFja2FnZWAuIFRoaXMgaXMgdXNlZnVsIGZvciBhIHZhcmlldHkgb2YgcmVhc29uczoKCjEuIEl0IGFsbG93cyB5b3UgdG8gdXNlIGEgZnVuY3Rpb24gZnJvbSBhIHBhY2thZ2Ugd2l0aG91dCBoYXZpbmcgdG8gbG9hZCB0aGF0IHBhY2thZ2UKMi4gSXQgaGVscHMgaW4gY2FzZXMgd2hlcmUgeW91IGxvYWQgdHdvIHBhY2thZ2VzIHdoaWNoIGNvbnRhaW4gdHdvIGRpZmZlcmVudCBmdW5jdGlvbnMgd2hpY2ggaGFwcGVuIHRvIGhhdmUgdGhlIHNhbWUgbmFtZS4KMy4gU29tZXRpbWVzLCBldmVuIHdoZW4gYSBwYWNrYWdlIGlzIGxvYWRlZCwgeW91IG5lZWQgdG8gcHJlY2VkZSBhIGZ1bmN0aW9uIGJ5IHRoZSBwYWNrYWdlIG5hbWUuIChJIGFtIG5vdCBzdXJlIHdoeSB0aGlzIGhhcHBlbnMuLi4pLiBIb3dldmVyLCBtb3N0IG9mIHRoZSB0aW1lIHRoaXMgaXMgbm90IG5lY2Vzc2FyeS4KCiMjIEVYIDMgLSBVc2luZyBwYWNrYWdlcwoKMS4gSW5zdGFsbCBhbmQgbG9hZCB0aGUgcGFja2FnZSBgZ2dwbG90MmAKMi4gTG9vayB1cCB0aGUgZnVuY3Rpb24gYGdlb21fcG9pbnRgIGZyb20gdGhpcyBwYWNrYWdlLiBXaGF0IGRvZXMgaXQgZG8/CgojIE9iamVjdHMsIGRhdGEgZnJhbWVzIGFuZCBpbmRpY2VzCgojIyBPYmplY3RzCgpBIHZhcmlhYmxlIGlzIGEgdHlwZSBvZiAnb2JqZWN0JyB3aGljaCBSIHN0b3JlcyBpbiBtZW1vcnkuIFIgaXMgY2FwYWJsZSBvZiBjcmVhdGluZyBhbmQgc3RvcmluZyBhIHdpZGUgcmFuZ2Ugb2Ygb2JqZWN0cy4gVG8gc2VlIHdoYXQgdHlwZSBvZiBvYmplY3Qgd2UgaGF2ZSBjcmVhdGVkLCB3ZSB1c2UgdGhlIGZ1bmN0aW9uIGBjbGFzcygpYCwgZS5nLgoKYGBge3IgdmFyaWFibGUgY2xhc3NlcyAvIHR5cGVzfQoKeCA8LSAxCgpjbGFzcyh4KQoKeiA8LSAiaGVsbG8iCgpjbGFzcyh6KQoKYGBgCgoqY2xhc3MqIGlzIG9uZSBvZiB0aGUgbW9zdCB1c2VmdWwgZnVuY3Rpb25zIGluIFIgYXMgZXJyb3JzIGFyZSBvZnRlbiBkdWUgdG8gbWlzYXNzaWdubWVudCBvZiBjbGFzcywgZS5nLgoKYGBge3IgZm9yY2luZyBhbiBlcnJvciBkdWUgdG8gYSB0eXBlIGNsYXNoLCBlcnJvciA9IFRSVUV9Cgp4ICsgegoKYGBgCgpIZXJlIHdlIGhhdmUgdHJpZWQgdG8gYWRkIGEgbnVtYmVyIHRvIGEgc3RyaW5nIHdoaWNoIGlzIGNsZWFybHkgaW1wb3NzaWJsZS4gSXQncyBwb3NzaWJsZSB0byBjaGFuZ2UgdGhlIGNsYXNzIG9mIGFuIG9iamVjdCB1c2luZyBjb21tYW5kcyBzdWNoIGFzCmBhcy5jaGFyYWN0ZXJgLCBgYXMuaW50ZWdlcmAsIGBhcy5udW1lcmljYCwgYGFzLmZhY3RvcmAsIGUuZy4KCmBgYHtyIGNoYW5naW5nIHRoZSB0eXBlIG9mIGEgdmFyaWFibGUsIGVycm9yID0gVFJVRX0Kb25lIDwtICIxIgp4ICsgb25lCm9uZSA8LSBhcy5udW1lcmljKG9uZSkKeCArIG9uZSAKYGBgCgpIZXJlIGlzIGEgbGlzdCBvZiB0aGUgbWFpbiBvYmplY3QgY2xhc3NlcyBpbiBSOgoKMS4gTnVtZXJpYyAtIGEgbnVtYmVyIHdpdGggZGVjaW1hbCBwbGFjZXMKMi4gSW50ZWdlciAtIGEgbnVtYmVyIHdpdGhvdXQgZGVjaW1hbCBwbGFjZXMKMy4gQ2hhcmFjdGVyIC0gYSBzdHJpbmcgb2YgbGV0dGVycy9udW1iZXJzCjQuIFZlY3RvciAtIGFuIG9yZGVyZWQgbGlzdCBvZiBudW1iZXJzIG9yIGNoYXJhY3RlcnMsIG9yIG11bHRpLWNoYXJhY3RlciBzdHJpbmdzLiBOQiBlYWNoIG51bWJlciwgY2hhcmFjdGVyLCBvciBjaGFyYWN0ZXIgc3RyaW5nIGlzIGFsc28gYW4gb2JqZWN0LiBTbyB5b3UgY2FuIGhhdmUgb2JqZWN0cyB3aXRoaW4gb2JqZWN0cyEKNS4gRGF0YWZyYW1lIC0gYSAyIHggMiBhcnJheSBpbiB3aGljaCBlYWNoIGNvbHVtbiBoYXMgYSBuYW1lCjYuIExpc3QgLSB0aGlzIGlzIGxpa2UgYSB2ZWN0b3IsIGV4Y2VwdCBpdCBpcyBjYXBhYmxlIG9mIHN0b3JpbmcgbXVsdGlwbGUgb2JqZWN0IGNsYXNzZXMsIGUuZy4gaXQgY2FuIGNvbnRhaW4gYm90aCBudW1iZXJzIGFuZCBzdHJpbmdzLgoKSW4gb3JkZXIgdG8gY3JlYXRlIGEgdmVjdG9yIHdlIG5lZWQgdG8gdXNlIHRoZSBgY2AgZnVuY3Rpb24uIChjID0gJ2NvbWJpbmUnKSwgZS5nLgoKYGBge3IgbWFraW5nIGEgdmVjdG9yIHVzaW5nIHRoZSBjIGZ1bmN0aW9ufQpsaXN0Lm9mLm51bWJlcnMgPC0gYygxLDQsNTQsMjIsNDMsOSwwLDAsMjEpCgptZWFuKGxpc3Qub2YubnVtYmVycykKCnNkKGxpc3Qub2YubnVtYmVycykKYGBgCgpgYGB7ciB0dXJuaW5nIGEgdmVjdG9yIGludG8gYSBsaXN0fQoKYS5jaGFyYWN0ZXIudmVjdG9yIDwtIGMoIk1hcnkiLCAiSmFuZSIsICJBbGkiLCAiQ2hlbiIpCgphLmxpc3QgPC0gYXMubGlzdChjKDEsIDIsICJNYXJ5IiwgIkphbmUiKSkKCmBgYAoKCiMjIENyZWF0aW5nIGEgZGF0YSBmcmFtZSBmcm9tIHNjcmF0Y2gKCkEgZGF0YSBmcmFtZSBpcyBhIHR3by1kaW1lbnNpb25hbCBvYmplY3QgY29udGFpbmluZyB2YXJpYWJsZXMgYW5kIHJvdyBudW1iZXJzLiBJdCdzIGJhc2ljYWxseSBhIHNwcmVhZHNoZWV0LgoKVGhlIGZvbGxvd2luZyBjb2RlIGNyZWF0ZXMgYSBkYXRhIGZyYW1lIHByb2dyYW1tYXRpY2FsbHkuIEl0IGNyZWF0ZXMgdHdvIHZhcmlhYmxlcywgYW5kIGNvbWJpbmVzIHRoZW0gdG9nZXRoZXIgdG8gbWFrZSBhIGRhdGEgZnJhbWUuIE5vdGUgdGhhdCB0byBkbyB0aGlzIHdlIG5lZWQgdG8gdXNlIHRoZSBmdW5jdGlvbnMgYGFzLmRhdGEuZnJhbWVgIGFuZCBgY2JpbmRgLgoKYGBge3IgbWFraW5nIGEgZGF0YSBmcmFtZSBwcm9ncmFtbWF0aWNhbGx5fQoKbGlzdC5vZi5tb3ZpZXMgPC0gYygiSW5kZXBlbmRlbmNlIERheSIsICJQcmV0dHkgV29tYW4iLCAiVGhlIEdvZGZhdGhlciBQYXJ0ClR3byIsICJQbGFuZXQgb2YgdGhlIEFwZXMgKG9yaWdpbmFsKSIpCgpyb3R0ZW4udG9tYXRvZXMudmFyaWFibGUgPC0gYyg2MiwgNjEsIDk3LCA4OSkKCmRmIDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQobGlzdC5vZi5tb3ZpZXMsIHJvdHRlbi50b21hdG9lcy52YXJpYWJsZSkpICMgJ2NiaW5kJyBiaW5kcyBjb2x1bW5zIHRvZ2V0aGVyCmBgYAoKIyMgVmlld2luZyB0aGUgY29udGVudHMgb2YgYSBkYXRhIGZyYW1lCgpUbyBnbGltcHNlIHRoZSB0b3AgZmV3IHJvd3MgdHlwZSBgaGVhZChuYW1lX29mX2RhdGFfZnJhbWUpYCBpbiB0aGUgY29uc29sZSwgZS5nLgoKYGBge3IgaGVhZCBmdW5jdGlvbn0KaGVhZChkZikKYGBgCgpUbyB2aWV3IHRoZSBkYXRhIGZyYW1lIGluIHRoZSAnc291cmNlJyB3aW5kb3csIHR5cGUgYFZpZXcobmFtZV9vZl9kYXRhX2ZyYW1lKWAgaW4gdGhlIGNvbnNvbGUsIC5lLmcuCgpgYGB7ciB2aWV3aW5nIGRhdGEgYXMgYSBzcHJlYWRzaGVldH0KVmlldyhkZikgI05CIGZpcnN0IGxldHRlciBpcyBhIGNhcGl0YWwgbGV0dGVyLgpgYGAKCiMjIFJlZmVycmluZyB0byB2YXJpYWJsZXMKClRvIHJlZmVyIHRvIHZhcmlhYmxlcywgdXNlIHRoZSBmb2xsb3dpbmcgc3ludGF4IGBkYXRhX2ZyYW1lX25hbWUkdmFyaWFibGVfbmFtZWAsIGUuZy4KYGBge3IgcmVmZXJyaW5nIHRvIHZhcmlhYmxlc30KZGYkbGlzdC5vZi5tb3ZpZXMKYGBgCldoZW4gbmFtaW5nIHZhcmlhYmxlcyB3ZSBjYW4gdXNlIGRvdHMgYW5kIHVuZGVyc2NvcmVzLCBlLmcuIGBkZiRsaXN0Lm9mLm1vdmllc2AgYW5kIGBkZiRsaXN0X29mX21vdmllc2AuIFdlIGNhbiB1c2UgbnVtYmVycyBhcyBsb25nIGFzIHRoZXkgZG9uJ3QgY29tZSBhdCB0aGUgYmVnaW5uaW5nLCBlLmcuIGBkZiRsaXN0X29mX21vdmllcy52M2AuCgpJZiB5b3UgdXNlIHRoaXMgY29udmVudGlvbiwgdGhlbiB0aGUgbmFtZXMgZm9yIHZhcmlhYmxlcyBjYW4gZ2V0IHZlcnkgbG9uZy4gSG93ZXZlciwgaXQncyBnZW5lcmFsbHkgdXNlZnVsLCBhcyBpbiBSIHlvdSBvZnRlbiBoYXZlIG11bHRpcGxlIGRhdGEgZnJhbWVzIGxvYWRlZCBpbnRvIG1lbW9yeS4gQnkgc3BlY2lmaXlpbmcgYm90aCB0aGUgbmFtZSBvZiB0aGUgZGF0YSBmcmFtZSBhbmQgdGhlIHZhcmlhYmxlLCB0aGlzIGF2b2lkcyBjb25mdXNpb24uCgpUcnkgdG8gYmUgY29uc2lzdGVudCB3aXRoIHlvdXIgbmFtaW5nIGNvbnZlbnRpb25zLiBJIHRlbmQgdG8gdXNlIHVuZGVyc2NvcmVzIHRvIG5hbWUgdmFyaWFibGVzLCBlLmcuIGBkYXRhLmZyYW1lLngkdmFyaWFibGVfeWAuIFRoaXMgaXMgYWxzbyB3aGF0IEhhZGxleSBXaWNraGFtIHJlY29tbWVuZHMgKEhhdmUgYSBsb29rIGF0IHRoZSBbVGlkeXZlcnNlIFN0eWxlIEd1aWRlXShodHRwczovL3N0eWxlLnRpZHl2ZXJzZS5vcmcvKSkKCklmIHlvdSdkIGxpa2UgdG8gc2VlIGFsbCB0aGUgdmFyaWFibGUgbmFtZXMgaW4gYSBkYXRhIGZyYW1lIHR5cGUgYG5hbWVzKGRhdGFfZnJhbWUpYCwgZS5nLiAKCmBgYHtyIHZpZXdpbmcgdmFyaWFibGUgbmFtZXN9Cm5hbWVzKGRmKQpgYGAKCiMjIEluZGljZXMKCldoZW5ldmVyIHlvdSB3aXNoIHRvIGFjY2VzcyB0aGUgY29udGVudHMgb2YgYW4gb2JqZWN0IHdpdGggbXVsdGlwbGUgdmFsdWVzIChlLmcuIGEgZGF0YSBmcmFtZSkgeW91IHVzZSBpbmRleGVzLiBUaGVzZSBhcmUgcGxhY2VkIGluc2lkZSBzcXVhcmUgYnJhY2tldHMsIGUuZy4gYFsxXWAuIEhhdmUgYSBsb29rIGF0IHRoZSBmb2xsb3dpbmcgZXhhbXBsZToKCmBgYHtyIGluZGljZXN9Cgp2ZWN0b3IgPSBjKDEsIDQsIDIsIDk5LCAwLjUsIDEwKQoKdmVjdG9yWzFdCgp2ZWN0b3JbMl0KCnZlY3Rvcls1XQoKdmVjdG9yWzI6NV0KCm1lYW4odmVjdG9yWzI6NV0pCgpgYGAKCkhlcmUgaXMgaG93IHdlIHdvdWxkIHVzZSB2ZWN0b3JzIHdpdGggYSBkYXRhZnJvbWUKCmBgYHtyIGdhcHMgaW4gaW5kaWNlc30KZGZbMSwyXQoKZGZbMSxdICMgaGVyZSB0aGUgc2Vjb25kIG51bWJlciBpcyBibGFuawoKZGZbLDJdICMgaGVyZSB0aGUgZmlyc3QgbnVtYmVyIGlzIGJsYW5rCmBgYAoKIyMgRVggMyAtIHVuZGVyc3RhbmRpbmcgaW5kaWNlcwoKV2hhdCBkb2VzIGVhY2ggbnVtYmVyIHJlZmVyIHRvPyBXaGF0IGhhcHBlbnMgd2hlbiB3ZSBsZWF2ZSBhIGJsYW5rIGNlbGw/CgojIyBSZWFkaW5nIGRhdGEgZnJhbWVzIGZyb20gZmlsZXMgdXNpbmcgbWVudXMKCldlIGNhbiB1c2UgdGhlIG1lbnUgaW4gUnN0dWRpbzogYEZpbGUgPiBJbXBvcnQgZGF0YXNldGAuIFlvdSBjYW4gZG8gdGhpcyB0byBpbXBvcnQgRXhjZWwsIFNQU1MsIFNBUyBhbmQgU1RBVEEgZmlsZXMuCgojIyBSZWFkaW5nIGRhdGEgZnJhbWVzIGZyb20gZmlsZXMgdXNpbmcgY29kZQoKSG93ZXZlciwgcmF0aGVyIHRoYW4gdXNlIHRoZSBtZW51LCBpdCdzIG11Y2ggYmV0dGVyIHRvIHVzZSBhY3R1YWwgY29kZSwgYXMgdGhpcyB3aWxsIGF1dG9tYXRlIHRoZSBwcm9jZXNzLiBMZXQncyBpbXBvcnQgYSBkYXRhc2V0IG9uIFdvcmxkIEhhcHBpbmVzcyBSZXBvcnQgKDIwMTcpLCBieSBjb3VudHJ5LiBUaGUgZmlsZXMgYXJlIFtXSFJfMjAxNy54bHN4XShXSFJfMjAxNy54bHN4KSwgW1dIUl8yMDE3LnNhdl0oV0hSXzIwMTcuc2F2KSwgYW5kIFtXSFJfMjAxNy5jc3ZdKFdIUl8yMDE3LmNzdikuIEFsdGVybmF0aXZlbHkgeW91IGNhbiBhY3R1YWxseSBkb3dubG9hZCB0aGUgZGF0YSBzZXQgc3RyYWlnaHQgZnJvbSB0aGUgVVJMIChiZWxvdykKCgpgYGB7ciBpbXBvcnRpbmcgZGF0YSwgbWVzc2FnZSA9IEZBTFNFfQoKIyBUaGlzIGNvZGUgZGVwZW5kcyBvbiB1c2luZyB0aGUgYHRpZHl2ZXJzZWAgYW5kIGBoYXZlbmAgcGFja2FnZXMKIyBJZiB5b3UgaGF2ZSBub3QgaW1wb3J0ZWQgLyBsb2FkZWQgdGhlbSwgeW91IG5lZWQgdG8gc28KIyBsaWJyYXJ5KHRpZHl2ZXJzZSkKIyBsaWJyYXJ5KGhhdmVuKQoKZGYgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCJXSFJfMjAxNy54bHN4IikgIyBSZWFkIGFuIGV4Y2VsIGZpbGUKCmRmIDwtIGhhdmVuOjpyZWFkX3Nwc3MoIldIUl8yMDE3LnNhdiIpICMgUmVhZCBmcm9tIGFuIFNQU1MgZmlsZQoKZGYgPC0gcmVhZF9jc3YoIldIUl8yMDE3LmNzdiIpICMgUmVhZCBmcm9tIGEgLmNzdiBmaWxlCgojT3IgdG8gZG93bmxvYWQgc3RyYWlnaHQgZnJvbSB0aGUgVVJMISEKCmRmIDwtIHJlYWRfY3N2KCJodHRwczovL3ZlcmJpbmdub3Vucy5naXRodWIuaW8vQWR2ZW50dXJlc0luUi9kb2NzL1dIUl8yMDE3LmNzdiIpCgpgYGAKCgoKUG9zc2libHkgdGhlIGJlc3QgZGF0YSBmb3JtYXQgdG8gd29yayBpbiBpcyB0aGUgYC5jc3ZgIGRhdGEgZm9ybWF0IChDb21tYS1TZXBhcmF0ZWQgVmFsdWUpLiBUaGlzIGlzIGdvb2QgYmVjYXVzZSBpdCBpcyByZWFkYWJsZSBpbiBFeGNlbCwgc21hbGwsIHNpbXBsZSwgYW5kIG5vdCBlYXNpbHktY29ycnVwdGVkLiBJdCdzIG9ubHkgZGlzYWR2YW50YWdlIGlzIHRoYXQgaXQgZG9lcyBub3Qgc3VwcG9ydCBFeGNlbCBmb3JtdWxhcyBvciBmb3JtYXR0aW5nIChOQiBzb21lIHdvdWxkIHNheSB0aGlzIGlzIGFuIGFkdmFudGFnZSBhcyBFeGNlbCBmb3JtdWxhZSBhcmUgbm90IHRoYXQgcmVsaWFiaWxpdHkgYW5kIG5vdCB2ZXJ5IGNvbnNpc3RlbnQgd2l0aCBzY2llbnRpZmljIHJlcHJvZHVjaWJpbGl0eSkKClRvIHJlYWQgLmNzdiBmaWxlcyB3ZSB1c2UgdGhlIGByZWFkLmNzdigpYCBmdW5jdGlvbiBmcm9tIGJhc2UgUiwgb3IgYHJlYWRfY3N2KClgIGZyb20gdGhlIHRpZHl2ZXJzZSAoSSB3b3VsZCBnbyB3aXRoIHRoZSBsYXR0ZXIgYXMgaXQgYWxzbyBzaG93cyB5b3UgYSBsaXN0IG9mIHRoZSB2YXJpYWJsZSB0eXBlcykKCiMgU3Vic2V0dGluZyBhIGRhdGEgc2V0IHVzaW5nIChhKSBiYXNlIFIgYW5kIChkKSBkcGx5cgoKIyMgU3Vic2V0dGluZyB3aXRoIGJhc2UgUgoKV2UncmUgZ29pbmcgdG8gKnN1YnNldCogdGhlIFdIUiBkYXRhc2V0IChpLmUuIGNob29zZSBvbmx5IHRob3NlIGNhc2VzL29ic2VydmF0aW9ucyB3aGljaCBmdWxmaWwgYSBzcGVjaWZpYyBjcml0ZXJpb24pLiBUbyBkbyB0aGlzIHdlJ3JlIGdvaW5nIHRvIHVzZSB0aGUgYHdoaWNoKClgIGZ1bmN0aW9uLiBXaGVuIHlvdSBhcHBseSBgd2hpY2hgIHRvIGEgdmFyaWFibGUgaW4gYSBkYXRhc2V0LCBpdCB3aWxsIHByb2R1Y2UgaW5kaWNlcyAoaW5kZXhlcykgb2YgdGhlIHJvd3Mgd2hpY2ggZnVsZmlsIGEgY2VydGFpbiBjcml0ZXJpb24sIGUuZy4gYHdoaWNoKGRmJHZhcl9uYW1lID09IDIpYCB3aWxsIGdpdmUgeW91IHRoZSBpbmRpY2VzIG9mIGFsbCByb3dzIHdoZXJlIHRoZSB2YWx1ZSBvZiB0aGUgdmFyaWFibGUgaXMgMi4KCiMjIEVYNDogU3Vic2V0dGluZyB1c2luZyBiYXNlIFIKCkFybWVkIHdpdGggdGhpcyBrbm93bGVkZ2UsIHlvdXIgdGFzayBpcyB0byBzdWJzZXQgdGhlIGRhdGEgZnJhbWUgc28gdGhhdCBpdCBvbmx5IGNvbnRhaW5zIGluZm9ybWF0aW9uIGZyb20gQWZyaWNhbiBjb3VudHJpZXMuCgpJZiB5b3UncmUgc3R1Y2sgaGF2ZSBhIGxvb2sgYXQgdGhlIGFuc3dlciBiZWxvdy4gCgpgYGB7ciBTdWJzZXR0aW5nIHVzaW5nIGJhc2UgUn0KZGYuQWZyaWNhIDwtIGRmW3doaWNoKGRmJHJlZ2lvbiA9PSAiQWZyaWNhIiksIF0KYGBgCgojIyBQaXBpbmcKCk9rYXksIHRoZSBhYm92ZSBjb2RlIGlzIHByZXR0eSBob3JyaWJsZSwgc28gd2UncmUgZ29pbmcgdG8gZXhwbG9yZSBhbiBhbHRlcm5hdGl2ZSB1c2luZyB0aGUgcGFja2FnZSBgZHBseXJgIHdoaWNoIGlzIGZyb20gdGhlIGB0aWR5dmVyc2VgLiBCdXQgYmVmb3JlIHdlIGNhbiB1c2UgYGRwbHlyYCB3ZSBoYXZlIHRvIGxlYXJuIGhvdyB0byAncGlwZScuCgohW10oaW1hZ2VzL01hZ3JpdHRlUGlwZS5qcGcpCgpQaXBlcyBhcmUgd3JpdHRlbiBpbiBSIGFzIGAlPiVgIChub3RlIHlvdSBtdXN0IHVzZSBhIHBlcmNlbnRhZ2Ugc2lnbiBiZWZvcmUgYW5kIGFmdGVyIHRoZSBwaXBlKS4gVG8gZGVtb25zdHJhdGUgd2hhdCBwaXBlcyBkbywgSSBoYXZlIGEgbG9vayBhdCB0aGUgZm9sbG93aW5nIHBzZXVkb2NvZGUuCgohW10oaW1hZ2VzL3BpcGluZy5wbmcpCgpBbGwgcGlwZXMgZG8gaXMgZW5hYmxlIHVzIHRvICdwYXNzJyBhIGRhdGEgZnJhbWUgKG9yIGFub3RoZXIgb2JqZWN0KSB0byBhIG5ldyBmdW5jdGlvbiB3aXRob3V0IGhhdmluZyB0byBrZWVwIG9uIHNwZWNpZnlpbmcgdGhlIGRhdGEgZnJhbWUuIEluIGFkZGl0aW9uLCB3ZSBjYW4gKmNoYWluKiBwaXBlcyB0b2dldGhlciBpbmRlZmluaXRlbHkuCgpIZXJlJ3MgaG93IHdlIHdvdWxkIHN1YnNldCB0aGUgZGF0YSBmcmFtZSB1c2luZyBwaXBpbmc6CgpgYGB7ciBzdWJzZXR0aW5nIHVzaW5nIHBpcGluZ30KCmRmLkFmcmljYSA8LSBmaWx0ZXIoZGYsIHJlZ2lvbiA9PSAiQWZyaWNhIikgIyBUaGlzIGlzIHRoZSB2ZXJzaW9uIHdpdGhvdXQgcGlwaW5nCgpkZiAlPiUgZmlsdGVyKHJlZ2lvbiA9PSAiQWZyaWNhIikgLT4gZGYuQWZyaWNhICMgVGhpcyBpcyB0aGUgdmVyc2lvbiB3aXRoIHBpcGluZy4gSXQgbG9va3MgbG9uZ2VyLCBidXQgd2UgY2FuIGNoYWluIG11bHRpcGxlIGZ1bmN0aW9ucyB0b2dldGhlciEKYGBgCgpOb3RlIHRoYXQgdG8gY3JlYXRlIGEgbmV3IGRhdGEgZnJhbWUsIHdlIG5lZWQgYSBzb2xpZCBhcnJvdyBhdCB0aGUgZW5kLiBJZiB3ZSBkb24ndCBpbmNsdWRlIHRoYXQgc29saWQgYXJyb3csIHRoZSByZXN1bHRzIGFyZSBzaG93biBpbiB0aGUgY29uc29sZSwgYnV0IG5vIG5ldyBkYXRhIGZyYW1lIGlzIGNyZWF0ZWQuIFRoaXMgaXMgYW4gaW5jcmVkaWJseSB1c2VmdWwgZmVhdHVyZSBvZiBwaXBlcy4gWW91IGNhbiBgdHJ5IGJlZm9yZSB5b3UgYnV5YCEKCkFuZCBoZXJlIGlzIGFuIGV4YW1wbGUgd2hlcmUgd2UgKmNoYWluKiBhIHNlcmllcyBvZiBwaXBlcyB0b2dldGhlcjoKCmBgYHtyIGNoYWluaW5nIHBpcGVzIHRvZ2V0aGVyfQoKZGYgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW4uaGFwcGluZXNzID0gbWVhbihoYXBwaW5lc3Nfc2NvcmUpKSAtPgogIGRmLm1lYW4uaGFwcGluZXNzLmJ5LnJlZ2lvbgoKYGBgCgpOQiBXaGVuIHBpcGluZyB0aGUgY29kZSBiZWNvbWVzIG1vcmUgcmVhZGFibGUgd2hlbiB0aGUgbGluZSBlbmRzIHdpdGggdGhlIHBpcGUuCgpUaGVyZSBhcmUgYSBjb3VwbGUgb2YgaW1wb3J0YW50IHBvaW50cyB0byBub3RlLgoKKDEpIFdlIGNhbiByZWZlciB0byB2YXJpYWJsZXMgd2l0aG91dCBzcGVjaWZ5aW5nIHRoZSBkYXRhIGZyYW1lCigyKSBJZiB3ZSB3aXNoIHRvIHN0b3JlIHRoZSByZXN1bHRzIHdlIG11c3Qgb3V0cHV0IHRoZW0gdXNpbmcgYW5kIGFycm93IGAtPmAuIElmIHdlIGRvbid0IHN0b3JlIHRoZSByZXN1bHRzIHRoZXkgd2lsbCBtZXJlbHkgYmUgZGlzcGxheWVkIGluIHRoZSBjb25zb2xlLgoKUGlwaW5nIGlzIGEga2V5IHRlY2huaXF1ZSBpbiBSIGFuZCBvbmNlIHlvdSd2ZSBsZWFybnQgaXQgeW91IHdpbGwgd3JpdGUgbXVjaCBtb3JlIHBvd2VyZnVsIGFuZCByZWFkYWJsZSBjb2RlLgoKQXMgd2VsbCBhcyB1c2luZyBwaXBlcyB0byBjcmVhdGUgZGF0YSBmcmFtZSwgeW91IGNhbiBhbHNvIGluc2VydCBwaXBlcyBpbnRvIGJvdGggYW5hbHlzZXMgYW5kIGZpZ3VyZXMhIEhlcmUgaXMgYW4gZXhhbXBsZSBvZiBhIHBpcGUgaW5zZXJ0ZWQgd2l0aGluIGFuIEFOT1ZBLgoKYGBge3IgZW1iZWRkaW5nIHBpcGVzIHdpdGhpbiBhbiBhbmFseXNpc30KCiMgQW4gQU5PVkEgd2l0aG91dCBhIHBpcGUuIE5CIHdlIGFyZSB1c2luZyB0aGUgYmFzZSBmdW5jdGlvbiAiYW92Ii4gSWYgeW91IHdvdWxkIGxpa2UgdG8gY29uZHVjdCBTUFNTLXN0eWxlIEFOT1ZBcywgdGhlIGJlc3QgcGFja2FnZSBpcyBjYWxsZWQgImFmZXgiLgoKbW9kIDwtIGFvdihoYXBwaW5lc3NfcmFuayB+IHJlZ2lvbiwgZGF0YSA9IGRmKQoKcGFjbWFuOjpwX2xvYWQoYnJvb20pICMgVG8gbG9hZCB0aGUgInRpZHkiIGZ1bmN0aW9uLgoKdGlkeShtb2QpCgojIEhlcmUgd2UgdXNlIGEgcGlwZSBpbnNpZGUgdGhlIGFuYWx5c2lzCm1vZCA8LSBhb3YoaGFwcGluZXNzX3JhbmsgfiByZWdpb24sICMgTkIgbm90ZSB3ZSBjYW4gYnJlYWsgdGhlIGxpbmUgYWZ0ZXIgYSBjb21tYQogICAgICAgICAgIGRhdGEgPSBkZiAlPiUgZmlsdGVyKHJlZ2lvbiA9PSAiQWZyaWNhIiB8IHJlZ2lvbiA9PSAiU291dGggQW1lcmljYSIpKQoKdGlkeShtb2QpCgoKYGBgCgpOb3RlIGhvdyBJIGhhdmUgYnJva2VuIHNvbWUgb2YgdGhlIGxpbmVzIGFmdGVyIGEgY29tbWEuIFRoaXMgbWFrZXMgdGhlIGNvZGUgbW9yZSByZWFkYWJsZS4gR2VuZXJhbGx5IHdlIGNhbiBicmVhayBhIGxpbmUgd2hlbiBpdCBlbmRzIGluIHNvbWUga2luZCBvZiBzeW1ib2wsIGUuZy4gYSBwaXBlLCBhbiBhcnJvdywgb3IgYSBjb21tYS4KCgojIExvb3BzIGFuZCBpZi10aGVuIHN0YXRlbWVudHMKCkxvb3BzIGFuZCBpZi10aGVuIHN0YXRlbWVudHMgYXJlIHVzZWZ1bCBwcm9ncmFtbWluZyB0b29scyB3aGljaCBoYXZlIHRoZSBzYW1lIHN0cnVjdHVyZTogYEZVTkNUSU9OIChTVEFURU1FTlQpIHsuLi4uLn1gLgoKIyMgTG9vcHMKCiFbXShodHRwczovL21lZGlhLmdpcGh5LmNvbS9tZWRpYS9NRFhvbXJjR3NoR3NvL2dpcGh5LmdpZikKCmBgYHtyIGV4YW1wbGUgb2YgYSBsb29wfQpmb3IoaSBpbiAxOjEwKXsKICBwcmludChhcy5jaGFyYWN0ZXIoaSkpCn0KYGBgCgoKIyMgRVg1OiBMb29wcwoKVGhlIGNvZGUgYmVsb3cgY3JlYXRlcyBhIHNlcXVlbmNlIHJhbmdpbmcgZnJvbSAwIHRvIDMwIGdvaW5nIHVwIGluIHN0ZXBzIG9mIDAuMjUuIFRyeSB0byBhY2hpZXZlIHRoZSBzYW1lIHJlc3VsdCB1c2luZyBhIGxvb3AKCmBgYHtyfQpzZXEoMCwzMCwyLjUpCmBgYAoKCiMjIElmLXRoZW4gc3RhdGVtZW50cwoKVG8gZGVtb25zdHJhdGUgaWYtdGhlbiBzdGF0ZW1lbnRzLCB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHdoaWNoIHNob3dzIGlmIHRoZSBoYXBwaW5lc3MgaW5kZXggaXMgYWJvdmUgdGhlIG1lYW4KCmBgYHtyIGV4YW1wbGUgb2YgYW4gaWYtdGhlbiBzdGF0ZW1lbnR9CmRmJGhhcHBpbmVzc19hYm92ZV9tZWFuIDwtIDAgIyBTZXQgdmFyaWFibGUgdG8gMAptZWFuX2hhcHBpbmVzcyA8LSBtZWFuKGRmJGhhcHBpbmVzc19zY29yZSkgIyBDYWxjdWxhdGUgbWVhbiBtcGcKZm9yIChpIGluIDE6bnJvdyhkZikpewogIGlmKGRmJGhhcHBpbmVzc19zY29yZVtpXSA+IG1lYW5faGFwcGluZXNzKXsKICAgIGRmJGhhcHBpbmVzc19hYm92ZV9tZWFuW2ldIDwtIDEKICAgIH0KfQpgYGAKCkFuZCBoZXJlIGlzIHRoZSBzYW1lIHByb2Nlc3MgdXNpbmcgYGRwbHlyYCwgd2hpY2ggYXZvaWRzIHRoZSBsb29wIGFuZCB0aGUgaWYtdGhlbiBzdGF0ZW1lbnQuCgpgYGB7ciBjcmVhdGluZyBhIHZhcmlhYmxlIHVzaW5nIHRpZHl2ZXJzZSBhbmQgYXZvaWRpbmcgaWYtdGhlbiBzdGF0ZW1lbnR9CgpkZiAlPiUKICBtdXRhdGUoaGFwcGluZXNzX2Fib3ZlX21lYW4gPSBhcy5udW1lcmljKGhhcHBpbmVzc19zY29yZSA+IG1lYW4oaGFwcGluZXNzX3Njb3JlKSkpIC0+CiAgZGYKYGBgCgpOb3RlIGxvb3BzIGFuZCBpZi10aGVuIHN0YXRlbWVudHMgYXJlIHF1aXRlIHZlcmJvc2UsIGFuZCB0aGVyZSBpcyBhbG1vc3QgYWx3YXlzIGEgbmVhdGVyIGFuZCBtdWNoIHNob3J0ZXIgYWx0ZXJuYXRpdmVzLiBIb3dldmVyLCBJIHRoaW5rIHRoZXkgYXJlIHVzZWZ1bCBwcm9jZWR1cmVzIGZvciB0aGUgcmVsYXRpdmUgYmVnaW5uZXIuCgpIZXJlIGlzIHRoZSB3YXkgdG8gY3JlYXRlIHRoZSB2YXJpYWJsZSB3aXRob3V0IHVzaW5nIHRoZSB0aWR5dmVyc2UKCmBgYHtyIGNyZWF0aW5nIGEgdmFyaWFibGUgd2l0aG91dCB0aWR5dmVyc2UsIG1lc3NhZ2UgPSBGQUxTRX0KCmRmIDwtIHJlYWRfY3N2KCJXSFJfMjAxNy5jc3YiKQoKZGYkaGFwcGluZXNzX2Fib3ZlX21lYW4gPC0gYXMubnVtZXJpYyhkZiRoYXBwaW5lc3Nfc2NvcmUgPiBtZWFuKGRmJGhhcHBpbmVzc19zY29yZSkpCmBgYAoKU28gaG93IGRvZXMgdGhpcyB3b3JrPyBUaGUgc3RhdGVtZW50IGluIGJyYWNrZXRzIGV2YWx1YXRlcyB0byBUUlVFIC8gRkFMU0UuIFdlIHRoZW4gdHVybiB0aGlzIGludG8gYSBudW1iZXIgdXNpbmcgYGFzLm51bWVyaWNgLiBUUlVFIGV2YWx1YXRlcyB0byAxLCB3aGlsZSBGQUxTRSBldmFsdWF0ZXMgdG8gMC4KCkl0IGNhbiBiZSBxdWl0ZSB1c2VmdWwgdG8gY2hhaW4gc3RhdGVtZW50cy4gRm9yIGV4YW1wbGUsIGlmIHdlIHdpc2ggdG8gaWRlbnRpZnkgY291bnRyaWVzIHdoZXJlIGJvdGggdGhlIGhhcHBpbmVzcyBzY29yZSBhbmQgbGlmZSBleHBlY3RhbmN5IGFyZSBhYm92ZSB0aGUgbWVhbiwgd2UgY291bGQgZG8gdGhpcy4uLi4KCmBgYHtyIGZ1cnRoZXIgZXhhbXBsZX0KZGYkaGFwcGluZXNzX2FuZF9MRV9hYm92ZV9tZWFuIDwtIGFzLm51bWVyaWMoKGRmJGhhcHBpbmVzc19zY29yZSA+IG1lYW4oZGYkaGFwcGluZXNzX3Njb3JlKSkgJiAoZGYkbGlmZV9leHBlY3RhbmN5ID4gbWVhbihkZiRsaWZlX2V4cGVjdGFuY3kpKSkKYGBgCgojI8KgRVg2OiBDcmVhdGluZyB2YXJpYWJsZXMKClRyeSB0byBpZGVudGlmeSBjb3VudHJpZXMgd2hlcmUgYm90aCB0aGUgR0RQIHBlciBjYXBpdGEgYW5kIHRydXN0IGluIHRoZSBnb3Zlcm5tZW50IGFyZSBhYm92ZSB0aGUgbWVhbi4KCiMgU3RvcmVkIHJlc3VsdHMKCldoZW5ldmVyIHlvdSBydW4gYW4gYW5hbHlzaXMgaW4gUiBhbmQgc2F2ZSB0aGF0IHRvIGFuIG9iamVjdCwgdGhlIG9iamVjdCBoYXMgYW4gaW50ZXJuYWwgc3RydWN0dXJlLiBUbyBkZW1vbnN0cmF0ZSB0aGlzLCBsZXQncyBkbyBhIHNpbXBsZSByZWdyZXNzaW9uIHVzaW5nIHRoZSBtdGNhcnMgZGF0YXNldDoKCmBgYHtyIHJlYWQgaW4gZGF0YSwgbWVzc2FnZSA9IEZBTFNFfQoKZGYgPC0gcmVhZC5jc3YoIldIUl8yMDE3LmNzdiIpCgpoZWFkKGRmKQoKYGBgCgpMZXQncyBkcmF3IGEgcGxvdCBsb29raW5nIGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBHRFAgcGVyIGNhcGl0YSBhbmQgSGFwcGluZXNzIFNjb3JlLiBXZSdyZSBub3QgZ29pbmcgdG8gZm9jdXMgb24gdGhlIGNvZGUsIHdoaWNoIHdpbGwgYmUgY292ZXJlZCBpbiB0aGUgbmV4dCBzZXNzaW9uLgoKYGBge3IgcnVuIGEgcGxvdH0KZyA8LSBnZ3Bsb3QoYWVzKHggPSBkZiRnZHBfcGVyX2NhcGl0YSwgeSA9IGRmJGhhcHBpbmVzc19zY29yZSksIGRhdGEgPSBkZikKZyA8LSBnICsgZ2VvbV9wb2ludCgpCmcgPC0gZyArIGdlb21fc21vb3RoKCkKZwpgYGAKCk5vdyBsZXQncyBydW4gYSByZWdyZXNzaW9uLiBBZ2Fpbiwgd2UncmUgbm90IGdvaW5nIGdvaW5nIHRvIGZvY3VzIG9uIHRoZSBjb2RlLCB3aGljaCB3aWxsIGJlIGNvdmVyZWQgaW4gdGhlIGZpbmFsIHNlc3Npb24uCgpgYGB7ciByZWdyZXNzaW9uIG1vZGVsc30KCm1vZCA8LSBsbShoYXBwaW5lc3Nfc2NvcmUgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IGRmKSAjIG1vZCA9ICJtb2RlbCIKCnBhY21hbjo6cF9sb2FkKGJyb29tKSAjIEJyb29tIGlzIGEgcGFja2FnZSB3aGljaCBwcm9kdWNlcyBuZWF0IHRhYmxlcyBvZiByZXN1bHRzCgp0aWR5KG1vZCkgIyBUaGlzIGlzIGEgYnJvb20gZnVuY3Rpb24gd2hpY2ggdGlkaWVzIHVwIHRoZSBzdGF0aXN0aWNhbCByZXN1bHRzIGZvciByZXBvcnRpbmcKCmBgYAoKCk5vdywgbGV0J3MgaGF2ZSBhIGxvb2sgYXQgdGhlIGBzdHJ1Y3R1cmVgIG9mIHRoaXMgbW9kZWwuIFRoZXJlIGFyZSB0d28gd2F5cyB0byBkbyB0aGlzOgoKMS4gVXNlIHRoZSBgc3RyYCBmdW5jdGlvbiwgZS5nLiBgc3RyKG1vZClgCjIuIFR5cGUgYG1vZCRgLCBhbmQgdGhlbiB1c2UgYXV0b2NvbXBsZXRlLgoKV2UgY2FuIHNlZSB0aGF0IHRoZSBgJGAgc3ltYm9sIGhhcyBhIGR1YWwgZnVuY3Rpb24gaW4gUjogZmlyc3RseSwgdG8gc3BlY2lmeSB2YXJpYWJsZXMgd2l0aGluIGRhdGFmcmFtZXMsIGFuZCBzZWNvbmRseSB0byBzcGVjaWZ5IHN1YmNvbXBvbmVudHMgb2YgYW4gb2JqZWN0LgoKSXQgaXMgdXNlZnVsIHRvIGJlIGFibGUgdG8gcmVmZXIgdG8gc3ViY29tcG9uZW50cyBvZiBhbiBvYmplY3Qgc28gdGhhdCB3ZSBjYW4gaW50ZWdyYXRlIGludG8gb3VyIHJlcG9ydCwgZS5nLiB0aGUgcmVncmVzc2lvbiB5aWVsZGVkIGEgdmFsdWUgb2YgYHIgc3VtbWFyeShtb2QpJHIuc3F1YXJlZGAKCiMjIEVYIDY6IExldCdzIHB1dCBpdCBhbGwgdG9nZXRoZXIhISEKCigxKSBEb3dubG9hZCB0aGUgZGF0YSBmb3IgW2xpZmUgZXhwZWN0YW5jeSBieSBjb3VudHJ5XShXSE9fbGlmZV9leHBlY3RhbmN5LmNzdikKKDIpIFRoZSBkYXRhIGNvdmVycyBtYW55IHllYXJzLiBTZWxlY3QgdGhlIG1vc3QgcmVjZW50IHllYXIuCigzKSBNZXJnZSB0aGUgZGF0YSB3aXRoIHRoZSAiV0hSIiBkYXRhICh5b3Ugd2lsbCBuZWVkIHRvIG1lcmdlIHVzaW5nIHRoZSAiY291bnRyeSIgdmFyaWFibGUpCig0KSBEcmF3IHBsb3RzIG9mIChhKSBsaWZlIGV4cGVjdGFuY3kgYWdhaW5zdCBHRFAgcGVyIGNhcGl0YSwgKGIpIGxpZmUgZXhwZWN0YW5jeSBhZ2FpbnN0IGZhbWlseSB2YWx1ZXMKCk9uY2UgeW91IGdldCBzdHVjayBoYXZlIGEgbG9vayBhdCB0aGUgZmlyc3QgY29kZSBjaHVuayBiZWxvdy4gVGhpcyBjb250YWlucyB0aGUgc29sdXRpb24gYnV0IHdpdGggcGVza3kgZXJyb3JzIGFkZGVkISBTZWUgaWYgeW91IGNhbiBzb3J0IG91dCB0aGUgZXJyb3JzLgoKYGBge3IgZXhlcmNpc2Ugd2l0aCBlcnJvcnMsIGV2YWwgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBlcnJvcj1UUlVFfQoKd2hyIDwtIHJlYWRfY3N2KCJXSFJfMjAxNy5jc3YiKQoKbGUgPC0gcmVhZF9jc3YoIldIT19saWZlX2V4cGVjdGFuY3kuY3N2IikKCndociAlPiUgIyBOQiB3ZSBuZWVkIHRvIGVuc3VyZSB0aGF0IHRoZSAiY291bnRyeSIgdmFyaWFibGUgaGFzIGV4YWN0bHkgdGhlIHNhbWUgbmFtZSBpbiBib3RoIGRhdGFzZXRzCiAgcmVuYW1lKGNvdW50cnkgPSBDb3VudHJ5KSAtPgogIHdocgoKbGUgJT4lIAogIGZpbHRlcihZZWFyID09IDIwMTUpICU+JSAKICBtZXJnZSh3aHIpICU+JSBkb2MKICBkZgoKcGxvdChkZiRgTGlmZSBleHBlY3RhbmN5YCwgZGYkR0RQKQpwbG90KGRmJGBMaWZlIGV4cGVjdGFuY3lgLCBkZiRmYW1pbHkpCgpgYGAKClRoZSBjb2RlIGluIHRoaXMgY2h1bmsgc2hvd3MgdGhlIHNvbHV0aW9uIQoKYGBge3IgQ29ycmVjdCEsIG1lc3NhZ2UgPSBGQUxTRX0KCndociA8LSByZWFkX2NzdigiV0hSXzIwMTcuY3N2IikKCmxlIDwtIHJlYWRfY3N2KCJXSE9fbGlmZV9leHBlY3RhbmN5LmNzdiIpCgp3aHIgJT4lIAogIHJlbmFtZShDb3VudHJ5ID0gY291bnRyeSkgLT4KICB3aHIKCmxlICU+JSAKICBmaWx0ZXIoWWVhciA9PSAyMDE1KSAlPiUgCiAgbWVyZ2Uod2hyKSAtPgogIGRmCgpwbG90KGRmJGBMaWZlIGV4cGVjdGFuY3lgLCBkZiRHRFApCnBsb3QoZGYkYExpZmUgZXhwZWN0YW5jeWAsIGRmJGZhbWlseSkKCmBgYAoKCgoK
5.3 Comments
If you’d like to comment on any code you write (i.e. you do not wish R to try to ‘run’ this code) just add a hash (
#
) or series of hashes in front of it, e.g.df <- read.csv("csv_file.csv") # This reads in the main file for the experiment
It is good practice to make a lot of comments, especially when you are just starting out in R. They will help to you remind you of what the code does, and you could also use them to highlight any difficulties you have had, things you need to be careful about, useful online resources etc.