Welcome to your first R workshop! 😁🥳
The aim of todays session is to give you an introduction to R, talk
you through some of its uses, and how it might be useful to you as
bioinformaticians.
The learning objectives for todays session are as follows:
- To learn what R is, and how we interact with it
- Focus on RStudio as an interface and project management system
- To understand data structures and basic functions in R
- To begin to use R’s plotting and visualisation tools
- To practice reading in datasets
- To learn how to install and load packages
We’ve got lots to cover, but no introduction can ever give you
everything you need to know. The general idea here is to give you some
level of familiarity with R, to remove the barrier to entry. Hopefully,
you’ll be able to go away from these sessions with some confidence to
practice, play, and gain some experience using everybodies (well, my)
favourite coding language! We’ll have a quick introduction before we get
into the coding proper, so bare with that and then we can play with some
code! Right, let’s get cracking.
An introduction to R:
R is the coding language that I primarily use, and have used
throughout my career thus far. I have dabbled in both Python and unix,
but R is my favourite, and the one I return to most frequently. I never
had a formal introduction to R, such as the one you guys are getting now
- I taught myself out of necessity, as you can imagine, this took quite
some time. Over the last decade, however, R has become increasingly wide
spread and accessible - there are more courses than you can shake a
stick at online.
Before we start proper, I also think it’s important to know that even
people who have been using R for years still make mistakes. There’s a
fair amount that I can do in R off of the top of my head (for example, I
am currently making this document in RStudio!), but I regularly still
have to google things. It’s really easy to feel a bit overwhelmed and
unsure where to start with any coding language, but remember that nobody
is expecting you to suddenly become fluent or memorise everything (as
another example, I’ve just had to google how to code sub-bullet points
to the above list!). We just want you to get some familiarity and
experience.
Now then, I’ve said all of this, but haven’t answered one key
question - what is R?!
R is a freely available programming language, developed in the early
1990s, made open source in 1995. R was developed on top of another
language, S. S was a propriatory language, which ultimately, R became
the open source version of.
R’s ethos was to develop something specifically for statistical
computation and visualisataion - it was developed by
researchers, for researchers.
So, in 2023, when you may have already begun to learn, for example,
Python, why bother with R?
- The statistics and data-vis packages in Python are very recent, they
did not exist 10 years ago!
- The “default” language varies from field to field, but certainly in
ecology and evolution, you’re likely to be working with colleagues who
use R (interestingly, ecologists were actually one of the first user
bases of R)
- R is designed to be an efficient, interpreted language in a way that
is fundementally different to the initial design of Python, which is
typically interacted with via a script. R is designed to be a sort of
“statistical conversation” where you interactively program.
- R was designed to have efficient data handling and storage
mechanisms. There aer lots of types of data structures in R - these
might seem unnecessary at first, but as we delve deeper into R and how
it works, you’ll see why they’re important. R is written in a way that
makes accessing reasonably sized datasets super efficient. Typically,
this is not true of Python for a plethora of reasons that we don’t have
the time to talk about (although admittedly this is getting better with
the advent of modules such as Pandas)
- R contains a large collection of tools specifically developed for
data analysis, as well as some really good built in data visualisation
features!
- There is a huge multiverse that has been built around R with loads
of different flavours associated with it. We’ll discuss this in more
detail next week.
- Finally, R is fundementally designed to be simple. This is why it’s
taught to non-programmers. You don’t have to do complicated things like
for loops if you don’t want to (although we’re going to!). These can be
avoided and R can be used for it’s base functionality of data analysis
and plotting with no fancy extras if you don’t want them.
More specifically:
- R is a major part of the bioinformatic and biostatistics toolkits,
and it isn’t going away any time soon.
- It was explicitly designed to handle data, particularly in a format
known as data.frames - this is extremely important to the way that R
functions
- It is free, and widely supported. In Evolution and Ecology papers in
the last decade, 66% mention R. If you want to have a career in
research, R is a vital skill.
- R is used by loads of major tech companies for their analytics -
including facebook, google, and twitter!
So, how do we interact with R?
How do we use R to have those statistical conversations that I
referenced earlier? There are 2 main ways. The first way is to use R
directly through an interface known as “base R” or “native R”. This is
using R in it’s purest form, and is actually quite tricky. If we load
base R, we see a window like this:

This console window contains a load of gobbledegook abut version
numbers etc., which will vary between individual machines and R
installs. The OS that you’re running will also dramatically impact how
your R window looks - this is the MacOS R version. Essentially, R is
waiting for you to enter commands and tell it what to do next. As you
can see, it’s not overly user friendly. That being said, the MacOS
version is much nicer. The Windows version is clunky, and even less
friendly. MacOS R has features not available on Windows too, which means
using R across multiple machines can be a bit of pain.
Here, we will use an R IDE, known as RStudio (although you might also
hear it referred to as posit). An IDE, or an interactive developer
environment, is a built-on interface that helps you to run a
programming language more easily and effectively. Other examples of IDEs
can be found in Python - you might have come across Spyder or Jupyter
for example. RStudio is completely free, and the best R IDE I’ve found.
It’s also the most well supported, which is useful. There are others,
but RStudio is particularly good. It will help to make your R journey
much smoother, and actually helps you to spot errors in your code, which
is always a bonus!
It looks a bit like this:

You’ll notice that my version of RStudio is differently coloured to
yours - this is just due to personal preference. I spend lots of time
staring at my R window rather intently, so having it darker really
helps!!!
RStudio standardises the R interface across all platforms - it looks
the same whatever OS you might be running. It also has a lot of powerful
features that makes running R more straightforward, we’ll talk about
these in more detail in the coming sessions. It also has great project
management tools, which are endlessly useful when you’re working on
multiple projects all at the same time!
Now, let’s talk through what all the bits are about.

As you can see above, the RStudio interface is made up of various
parts. The first of which is the console. This, like native R, is
waiting for your input in the “statistical conversations” that you’ll be
having with R. It gives you a bit of an odd blurb about versioning etc.
Each of the versions has a slightly odd name, I’m not sure why. Some of
them are named after various albums but that’s as far as I’ve got with
figuring out the naming system!
Anyway, theres loads of other stuff over on the right hand side, most
of which is not imortant or useful to you right now. The “Environment”
section keeps track of what you’ve got loaded in terms of datasets and
variables etc., which can prove incredibly useful. Underneath, you can
find file trees, plots that you have created, help files, and loads of
other stuff that we can talk more about later on.
Project Management in R
Starting with project management tools feels a bit bizarre, but as
someone who used R for many many years without this functionality, trust
me, it’s easiest to get to grips with it early doors. Something that
people struggle with, and something you might have come across with
other coding languages, is where files are stored on a computer. RStudio
has a great feature that will make this much easier to deal with. So, to
demonstrate what I mean, type the following code into your console
window, and press enter.
getwd()
This is the get working directory command, and is similar to commands
in unix and python - in unix, you’d use pwd(). This command
prints the working directory. (A quick note on functions in R which
we will come back to - anything followed by () is a function
i.e. something that takes an input and does something with it) If
you run the getwd() command, you will get an output with a
filepath, this is your current working directory, or, where R is looking
for files! You can use R by putting stuff places and then using loads of
really long and difficult path names to navigate through your computers
file system and then sticking to the same directory. This quickly
becomes a nightmare if you’re working on multiple projects at once
though, because you end up trying to read files from and write files to
the wrong directories, which you have to keep changing!
A better idea is to set up R using projects. These contain everything
you need which is associated with a single bit of analysis or a single
project (see what I did?) that you’re using R to work on. We
will create a project for this session, which will create a
self-contained directory, which R will always open when looking for
files associated with what we’re doing, so you don’t have to try and
navigate through complicated file structures within R itself. This is
relatively straight forward, and we’ll do it now.
Up in the right hand corner of your RStudio window, there should be a
bit of text that reads project or similar. Click on this, and
you’ll get a drop down menu appear. From this menu, select “new
project”, which will give you some more options. Chose “new directory”
and call it something sensible, like “LIFE4138-R”.
Note: Don’t ever use spaces in file or directory names. It’s
a really easy way to make sure that R will kick off at you! Use an
underscore instead!
Finally, click “create project” and R will do the rest for you. Now,
if you try the getwd() function again, it should print of
the location of the new directory! It will also have changed the
information displayed in the “files” section, having created a new
folder wherever you asked it to. The easiest way to access files now is
to pop them directly into this folder. You could now send someone this
.Rproj file, and they’d have all the stuff they needed to recreate your
work!
Anyway, that was an odd place to start, but it is important to get
this part right.
Interacting with the R environment
When we interact with R, generally we are typing in the console. You
can also write scripts (if you don’t have a script already open, you can
open a new one by clicking the new script option from the menu at the
top left of the screen - the white rectangle with a green + in the top
corner!). A script is effectively a record of what you have done using
R, allowing you to keep track. When you’ve written commands in a script,
you can run them with your cursor on the line of code you wish to run,
and pressing ctrl+enter (cmd+enter on MacOS). You may have come across
scripts in python and unix, but generally we run them a little
differently in R. We tend to run scripts interactively, either a single
line or a few lines at a time, assess an output, and then run some
more.
Let’s get started using R!
R as a calculator
First things first, R can be used as a basic calculator. Try typing
the following commands into your script window and running them with
ctrl/cmd+enter.
4
4 + 3
50 - 5
50 * 2000
9 / 3
10 ^ 2
You can see by doing this that R is able to perform basic
mathematical functions. You’ll have noticed when you gave it a single
number input, it echoed this number back to you. Play around with this,
and see what R is capable of! Whilst you’re unlikely to often use R
explicitly as a calculator, it is important to understand that it can
handle numerics.
Note: the “>” prompt in the console is waiting for you to ask
it something - try running the examples directly in the console as well
as in script form!
R and text input
R can also interpret text! You can give it a character string, and it
will print it back to you - try running the following:
"Hello world!"
'Hello world!'
Hello world
Note that the last example of this does not work, because R is
looking for an object called Hello world which it
cannot find. Without the quotation marks (either type is fine, but be
consistent), it does not recognise the text as a string.
You’ll have got a funky error in the last example, something about an
unepexted symbol - it likely wont have made much sense to you. This is
fairly typical of R error messages unfortunately, they are famed for
being tricky to interpret. They take some getting used to, but
eventually you will be able to translate these bizarre messages into
something that actually makes sense. For example, here, the “unexpected
symbol” is referring to the space between the words “Hello” and “world”.
Without the quotation marks, R expects these things to be functions or
objects rather than a character string, and cannot process the
space.
R as a logical interpreter
R can tell you whether a statement is true or false. This seems
basic, but it will build up to create a useful tool alongside the other
parts of it’s functionality that we’re discussing. The logical
interpreter within R is a key part of how R functions as a peice of
software, and is commonly in-built into many sophisticated functions and
analyses. R will tell you if something is logical, or if it makes sense,
by returning either TRUE or FALSE to an input.
This is possible with numerical input and character
strings - try the following for example:
2 == 2
5 > 10
9 <= 10
"Mario" == "Mario"
"Mario" == "Luigi"
Note: you’ll notice that when we are asking R if things are
equivelant to one another, we use a double == sign. This is because a
single = sign is used in R to asign something to a variable name. I’ll
explain more about that in a minute!
Right, time to start building up to using R practically.
Assigning objects
So, it’s useful to know how to make a variable in your R environment.
You may already know this from your adventures with Python. In Python,
you use an = to assign a variable. Whilst you can do this in R, it’s
best practice to use the <- operator instead. Note this
creates an object in R, not a
variable. This is because of the statistical nature of R - in
statistics, a variable means something entirely different. I use <-
because it is how I was taught to use R, but it’s okay to use = if you’d
prefer. It does get complicated because of the == function, so I like to
use <- instead. Some programmers get a bit picky and judgy if you use
a different way to them, but my philosophy with R is if it works, it
works.
So, why asign? It saves time and makes your scripting easier! There
are some rules, however. Assignment is case sensitive, so don’t type
something with loads of varying cases. Your object name also can’t start
with a number, and some words that are associated with common functions
like if or else are not allowed and will bring
up an error message. Try the following and take note of the error
messages you see:
my_number <- 150302
my_number2 = 204211
my_text <- “Hello world”
1my_text <- "Hello world"
for <- "Hello world"
Also, it is important to make sure you don’t name an object the same
as a variable in your data structure, or you’ll run into some
trouble!!
A note on scripting:
Scripts are essentially a record of what you’ve done - like a live
document you can edit and add to as you go. When I script, it’s almost
literally a stream of consciousness, which includes bits of code that
don’t work so I don’t make the same error again. You should leave
comments to remind yourself of what you’re doing, because even if you
think you’ll remember, I promise if you come back to it in six months,
you’ll be lost! You denote a comment by starting a line with a
#. R will ignore these lines (they will be greyed out in
RStudio), so add as many as you like!
When you’re thinking about not using comments, remember the Voyrich
manuscript. It was written in gibberish, and nobody knows what it means
because there is no way of translating it, and no way to work out what
the author was thinking. I go super over-board with comments to myself,
particularly when I’m sharing scripts with others.
Data structures
Right, lets get to the real meat. Data structures. There are 4 main
data structures that we’ll cover here (well, 3.5 because we’ll cover
lists properly another time) - Vectors, Matricies, and Dataframes.
Vetors
We’ll start with vectors. We’ve already considered all three main
classes of data above, numeric, character, and logical. We use these and
others to build up our data structures in R.
A vector is just a 1-dimensional series of values - the length of the
vector is its only dimension. This is the most basic data structure
you’ll find in R, and the fundementals of accessing its contents are
different to Python. So, we’ll start by creating a series of vectors,
starting with a numeric vector: Note: c() is a useful function here,
it’s short for concat or combine, we’ll talk more about functions
later!
x <- c(1, 2, 3, 4, 5)
y <- 1:5
z <- seq(from = 1, to = 5, by = 1)
All of these examples will give you a number vector that ranges from
1-5. The first combines all listed numbers, the second creates a series
of numbers from 1:5 (the : essentially means from 1 to 5),
and the third creates a sequence from 1 to 5, going up in 1s.
We can also create character vectors. Later, we will discuss how you
access an individual component of each of these vectors, but for now,
let’s build some character vectors (using my favourite nintendo
examples!). Note that you can only create a character vector with the
c() function. Without this, R is only expecting a single
value in your assignment and will throw an error up. Let’s try:
a <- c(“Mario”, “Luigi”, “Peach”)
b <- c(“Link”, “Zelda”, “Gannon”
We can also create a vector of logical values. Remember that
TRUE and FALSE have to be in caps for R to interpret them as
logicals. Here, we’ll create a logical vector using logcal
values, and then one from character vectors with ==:
e <- c(TRUE, FALSE, TRUE)
f <- a == b
Vector properties
It’s time to have a look at the properties of a vector - later we’ll
move on to sticking vectors together to make new data structures, but
for now, we’ll have a look at vectors as stand alone objects. We can do
mathematical operations on entire numeric vectors - we can apply a
single operation to all values in a vector, or we can perform operations
on two different vectors:
x <- 1:10
x + 5
x – 5
y <- 11:20
x + y
x * y
Vector operations such as those above are a very important and
powerful tool in R for rapid calculations across large sets of
numbers.
Data structures in R have properties - the main property of a vector
is its length. Once you know something about the length of a vector, you
can more easily access the stuff inside of it. You find the length of a
vector using length(x).
You will get warnings to do with the length of a vector in various
circumstances, for e.g. if two vector lengths are not multiples of one
another in some mathematical calculations. Try the following:
x <- 1:10
length(x)
y <- 1:5
x + y
x * y
z <- 1:3
y * z
Here, you’ll notice that the operation causes the shorter vector (z)
to be looped across until it fits the longer. So, your result from
y * z is actually:
- 1 * 1,
- 2 * 2,
- 3 * 3,
- 4 * 1, and
- 5 * 2
R will still perform these operations, but it will warn you that
vector lengths are not multiples of one another.
So, how do we interact with vectors and start to pull items from
them? Vectors are great, but they’re not overly useful unless we can get
at the stuff inside of them. We’ll create another character vector,
x.
x <- c("dog", "cat", "mouse")
x[] # This will print all vector values
x[1] # This will print the first value - note that R is indexed from 1 unlike Python!!
x[c(1, 3)] # This gives you the first and third values - note the use of c()
x[2:3] # this gives you values 2 through to 3.
So, now we can pull out whatever values we want, we can use this to
manipulate the contents of our vector! If we wanted to, for example,
replace the mouse with an elephant, we’d use the following:
x[3] # This prints "mouse"
x[3] <- "elephant" # This assigns the string "elephant" to the third index of the vector, replacing "mouse".
x
Now, what if we want to remove number 3 all together? We can do this
by assignin it an NA value, which indicates to R that there
is no value present at this location:
x[3] <- NA
A note on NA:
NA is a placeholder in R, for when data is “Not
Available”, and it usually denotes missing data. For example, you might
be collecting blood samples from patients in a longitudinal trial, and a
patient is unable to provide a sample at point 3 of 5, so here, your
value for whatever you’re measuring in the blood would be
NA. Other commonly encountered missing value placeholders
in R are NaN (Not A Number) and Inf
(Infinity).
Functions
We’ll take a brief interlude from data structures for a brief word
about functions now. Functions are the bread and butter of R. They are
code that takes an input, processes it, and returns a result in the form
of an output. We have already used some functions above, such as
length() and seq(). There are thousands of
functions available to you in R, from the very basic to the extremely
complicated and involved. You can (and you will!) write your own
functions, much like you can in Python, although the syntax is
different. Pre-built functions often come with help files, try the
following:
y <- 1:10
length(y)
?length
Use ?function or help("function") to access
help. The help files generally contain a description of the function and
details of all the arguments which may be supplied to it. These help
files do take some getting used to, as true to R’s style, they can be
quite tricky to interpret!
The anatomy of a function
Try running the following code:
y <- 1:10
sum(y)
y[5] <- NA # Replace the 5th index with NA
sum(y)
You’ll notice that if a vector contains NA, functions
such as sum() will return NA. Something hasn’t
quite worked here, so we need to add an additional argument to our
function to deal with those pesky NAs…
sum(y, na.rm = TRUE)
Here, the na.rm argument is set to TRUE, so
that NA is ignored (or, more accurately, removed). Note
that the assignment of things inside of a function is always
done with = and not <-.
Plotting and visualisation
Now is a good time to start thinking about what we can actually get
out of what we’ve learned so far, so we’ll use Rs integrated plotting
software to create some nice plots! You can have a look at what R has to
offer using the now slightly outdated demo(graphics)
command. Try taking a tour through the graph types.
Let’s use the skills we’ve learned so far to make a plot!
x <- 1:100
y <- x^2
plot(x, y)
Nice! You should have produced a scatter plot. What if we want to
turn that into a line plot?
plot(x, y, type = "l")
Fabulous. The ways to customise graphics in R are almost endless -
we’ll have a closer look later on! For now though, we’ll get back to our
data structures.
Returning to data structures
Matricies
The second type of data structure we’ll look at is the humble matrix.
These data structures store data in rows and columns (i.e. like a
table!). They are very similar to vectors, only they are
two-dimensional. In fact, we can build our first matrix from some
vectors using the cbind() and rbind()
functions:
x <- 1:4
y <- 21:24
z <- cbind(x, y)
z
cbind() binds vectors togther by column, whereas
rbind() does it by row, effectively flipping our table. Try
running z1 <- rbind(x, y) and looking at the output.
There is a simple way to determine whether your data structure is a
matrix, which is by running the is.matrix(z) command. Try
it! It should give a logical output of TRUE or FALSE. You can also
access the dimensions of a matrix in a similar way to a vector (although
slightly different). dim(z) tells you the dimensions
overall, nrow() tells you the number of rows, and
unsurprisingly, ncol() gives you information about the
number of columns in the matrix. Try it with our matrix
z.
An important consideration with matricies is that we refer to
them by the row index, and then the column. This is something
that is very easy to forget, and I often have to look it up, so don’t
worry if you can’t remember. Matricies are also only capable of storing
1 type of data, either logical, character, or numeric. If your data is
mixed in type, you’ll need a dataframe rather than a matrix, but we’ll
get to that soon. Let’s see what happens if we try and store multiple
data types:
x <- c(“Mario”, “Luigi”, “Peach”)
y <- c(“Toad”, “Bowser”, “Wario”)
z <- c(1, 2, 3)
m <- cbind(x, y, z)
Here you can see that the numbers in z are transformed
into characters!
Anyway, how do we extract and access information stored in a matrix?!
Like with vectors, we use square brackets. Let’s make a bigger matrix
and have a go. Note that we are using the matrix() function
here rather than cind().
m <- matrix(1:10, ncol = 2) # ncol = 2 tells R that we want the numbers 1-10 split into 2 columns
m[1, ] # return first row
m[, 2] # return second column
m[1,2] # return the information in the first row of the second column, in this example, 6.
Data frames
Right, on to our third (and probably final) data structure - data
frames. Most “real” data that you come across in your travels will be in
a dataframe. It’s a bit like a matrix, but capable of storing multuple
data classes in the same object. Let’s make one from 3 vectors and have
a look:
name <- c(“Mario”, “Luigi”, “Link”, “Zelda”)
height <- c(155, 160, 180.3, 180.3)
age <- c(26, 24, 17, 19)
df <- data.frame(name, height, age)
Note that the dataframe must have named columns! You can look at the
first few rows of your data with head(df), and take note of
the structure of it with str(df). Now, everything you’ve
just learned about accessing data inside of a matrix stands true for
dataframes also - they work in a very similar fashion with the rows and
columns format. There is, however, another way to access data from your
dataframe that I find more intuitive than using column indicies, which
is referring to the column by its name (hence the need for named
columns!). Try this:
# Accessing data as if it were a matrix
df[, 1]
df[3, ]
df[4, 3]
# Using column names as references
df[“name”]
df[, “name”]
df$name
When you extract a column in this way, it becomes a vector! Note that
in df$name, the $ essentially just means “look
inside” - so you’re telling R to look inside df to find the
names column.
Accessing example data
Using the toy datasets as we just have is all well and good when
you’re learning, and is a fun way to experiment and figure out how
things work! But, what if we want to get hold of some actual data? There
are loads of pre-loaded real life datasets that come with R, so let’s
have a look at arguably the most famous of these, the iris dataset.
If we type data() into our R console/script and run it,
R will load these datasets for us. We can then use the
head() function to look at the iris
dataset…
data()
head(iris)
?iris
Note that we can get more information about the dataset by running
the help ? function. We will revisit these dataset in a
minute, but first, what if you want to import your own data?!
The easy way: you can use RStudio to import data via the GUI, which
is a good way to learn at first, but isn’t as flexible as learning
functions to read data…

The (arguably) better way is to use the read.csv()
function. I will use it here to upload a .csv file I have in my project
directory which contains data from Netflix titles over the years. Try
with your own data!
netflix <- read.csv("./netflix_titles.csv")
head(netflix)
You may also need to write data out of R, which can be good for
saving your progress or saving filtered datasets. Here, we will write
out a file of comma-separated variables (a .csv file).
df <- data.frame(name = c(“Mario”, “Luigi”, “Link”, “Zelda”),
height = c(155, 160, 180.3, 180.3),
age = c(26, 24, 17, 19))
write.csv(df, “./nintendo.csv”)
Note: this is the nintendo dataframe we made earlier, so you may
not need to remake it!
Extending beyond base R:
Packages, which are analagous to modules in Python, are a great way
of extending your R universe. They can be installed in a multitude of
ways, but perhaps the most common is installing them directly through
the Comprehensive R Network - CRAN. There are currently over 18500
packages listed on CRAN, so it’s likely that if you’re trying to do
something specific in R, there is already a package! Other repositories
include GitHub and BioConductor.
Installing and loading R packages:
Installnig packages is usually straight forward… You also only need
to do it once on each computer you use! We will install
ggplot2 now, a package we will use lots in other sessions.
Once installed, you must load your package into R with the
library() function.
install.packages("ggplot2")
library(ggplot2)
Back to plots!
Visualising data is a fundementally important tool in R - think of it
as a way to understand and properly explore your data. We wont use
ggplot2 for this for now, although this is a fabulous plotting tool. We
can use R to make a simple scatter plot, as we did before:
x <- seq(from = 1, to = 100, by = 5)
y <- x^2
plot(x, y)

We can customise almost anything on this plot, and we add to it
iteratively as we go. You’ll see what I mean in the following examples.
First, we’ll change the orientation of the y axis labels with the
las = 1 argument in the plot() function:
plot(x, y, las = 1)

We can change the colour of the points, and then add a line:
plot(x, y, las = 1, col = “red”)
lines(x,y)

We can add a title:
plot(x, y, las = 1, col = “red”,
main = “relationship between x & y”)
lines(x,y)

The possibilities are endless!
Right, lets make a basic histogram and a box and whisker, then we’ll
call it a day.
Plotting the distribution of data with a histogram can be useful to
identify outliers or have a look at the shape of your data. We can plot
the normal distribution as an example - the following code will generate
a series of numbers that follow a normal distribution and then plot
it:
x <- rnorm(n = 1000, mean = 25.5, sd = 3)
hist(x)

Boxplots are useful to have a look at potential differences between
groups of data - let’s plot the iris data and see how petal width might
differ among species:
head(iris)
boxplot(iris$Petal.Width ~ iris$Species,
las = 1, ylab = “Petal width”,
xlab = “Species”)

A quick note about tilde (~)
In R, a tilde denotes the relatinship between two variables, and is
commonly used in statistical functions. It’s slightly confusing, as it
appears to be the wrong way around - you code the dependent variable and
then the independent. So, Petal width ~ Species means how
does petal width vary among species?!
Top tips for learning R:
- Experiment! Not much can go horribly wrong…
- Practice, practice, practice!
- There is no single right way - if it works, it works.
- Use resources available online - StackOverflow, Twitter, R forums
(with caution!)
- Take a break. A walk and a brew does wonders.
LS0tCnRpdGxlOiAiTElGRSA0MTM4OiBSIFdvcmtzaG9wIDEgLSBIYW5uYWggSmFja3NvbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCgpXZWxjb21lIHRvIHlvdXIgZmlyc3QgUiB3b3Jrc2hvcCEg8J+YgfCfpbMKClRoZSBhaW0gb2YgdG9kYXlzIHNlc3Npb24gaXMgdG8gZ2l2ZSB5b3UgYW4gaW50cm9kdWN0aW9uIHRvIFIsIHRhbGsgeW91IHRocm91Z2ggc29tZSBvZiBpdHMgdXNlcywgYW5kIGhvdyBpdCBtaWdodCBiZSB1c2VmdWwgdG8geW91IGFzIGJpb2luZm9ybWF0aWNpYW5zLgoKVGhlIGxlYXJuaW5nIG9iamVjdGl2ZXMgZm9yIHRvZGF5cyBzZXNzaW9uIGFyZSBhcyBmb2xsb3dzOgoKKiBUbyBsZWFybiB3aGF0IFIgaXMsIGFuZCBob3cgd2UgaW50ZXJhY3Qgd2l0aCBpdAogICsgRm9jdXMgb24gUlN0dWRpbyBhcyBhbiBpbnRlcmZhY2UgYW5kIHByb2plY3QgbWFuYWdlbWVudCBzeXN0ZW0KKiBUbyB1bmRlcnN0YW5kIGRhdGEgc3RydWN0dXJlcyBhbmQgYmFzaWMgZnVuY3Rpb25zIGluIFIKKiBUbyBiZWdpbiB0byB1c2UgUidzIHBsb3R0aW5nIGFuZCB2aXN1YWxpc2F0aW9uIHRvb2xzCiogVG8gcHJhY3RpY2UgcmVhZGluZyBpbiBkYXRhc2V0cwoqIFRvIGxlYXJuIGhvdyB0byBpbnN0YWxsIGFuZCBsb2FkIHBhY2thZ2VzCgpXZSd2ZSBnb3QgbG90cyB0byBjb3ZlciwgYnV0IG5vIGludHJvZHVjdGlvbiBjYW4gZXZlciBnaXZlIHlvdSBldmVyeXRoaW5nIHlvdSBuZWVkIHRvIGtub3cuIFRoZSBnZW5lcmFsIGlkZWEgaGVyZSBpcyB0byBnaXZlIHlvdSBzb21lIGxldmVsIG9mIGZhbWlsaWFyaXR5IHdpdGggUiwgdG8gcmVtb3ZlIHRoZSBiYXJyaWVyIHRvIGVudHJ5LiBIb3BlZnVsbHksIHlvdSdsbCBiZSBhYmxlIHRvIGdvIGF3YXkgZnJvbSB0aGVzZSBzZXNzaW9ucyB3aXRoIHNvbWUgY29uZmlkZW5jZSB0byBwcmFjdGljZSwgcGxheSwgYW5kIGdhaW4gc29tZSBleHBlcmllbmNlIHVzaW5nIGV2ZXJ5Ym9kaWVzICh3ZWxsLCBteSkgZmF2b3VyaXRlIGNvZGluZyBsYW5ndWFnZSEgIFdlJ2xsIGhhdmUgYSBxdWljayBpbnRyb2R1Y3Rpb24gYmVmb3JlIHdlIGdldCBpbnRvIHRoZSBjb2RpbmcgcHJvcGVyLCBzbyBiYXJlIHdpdGggdGhhdCBhbmQgdGhlbiB3ZSBjYW4gcGxheSB3aXRoIHNvbWUgY29kZSEgUmlnaHQsIGxldCdzIGdldCBjcmFja2luZy4KCiMgQW4gaW50cm9kdWN0aW9uIHRvIFI6CgpSIGlzIHRoZSBjb2RpbmcgbGFuZ3VhZ2UgdGhhdCBJIHByaW1hcmlseSB1c2UsIGFuZCBoYXZlIHVzZWQgdGhyb3VnaG91dCBteSBjYXJlZXIgdGh1cyBmYXIuIEkgaGF2ZSBkYWJibGVkIGluIGJvdGggUHl0aG9uIGFuZCB1bml4LCBidXQgUiBpcyBteSBmYXZvdXJpdGUsIGFuZCB0aGUgb25lIEkgcmV0dXJuIHRvIG1vc3QgZnJlcXVlbnRseS4gSSBuZXZlciBoYWQgYSBmb3JtYWwgaW50cm9kdWN0aW9uIHRvIFIsIHN1Y2ggYXMgdGhlIG9uZSB5b3UgZ3V5cyBhcmUgZ2V0dGluZyBub3cgLSBJIHRhdWdodCBteXNlbGYgb3V0IG9mIG5lY2Vzc2l0eSwgYXMgeW91IGNhbiBpbWFnaW5lLCB0aGlzIHRvb2sgcXVpdGUgc29tZSB0aW1lLiBPdmVyIHRoZSBsYXN0IGRlY2FkZSwgaG93ZXZlciwgUiBoYXMgYmVjb21lIGluY3JlYXNpbmdseSB3aWRlIHNwcmVhZCBhbmQgYWNjZXNzaWJsZSAtIHRoZXJlIGFyZSBtb3JlIGNvdXJzZXMgdGhhbiB5b3UgY2FuIHNoYWtlIGEgc3RpY2sgYXQgb25saW5lLgoKQmVmb3JlIHdlIHN0YXJ0IHByb3BlciwgSSBhbHNvIHRoaW5rIGl0J3MgaW1wb3J0YW50IHRvIGtub3cgdGhhdCBldmVuIHBlb3BsZSB3aG8gaGF2ZSBiZWVuIHVzaW5nIFIgZm9yIHllYXJzIHN0aWxsIG1ha2UgbWlzdGFrZXMuIFRoZXJlJ3MgYSBmYWlyIGFtb3VudCB0aGF0IEkgY2FuIGRvIGluIFIgb2ZmIG9mIHRoZSB0b3Agb2YgbXkgaGVhZCAoZm9yIGV4YW1wbGUsIEkgYW0gY3VycmVudGx5IG1ha2luZyB0aGlzIGRvY3VtZW50IGluIFJTdHVkaW8hKSwgYnV0IEkgcmVndWxhcmx5IHN0aWxsIGhhdmUgdG8gZ29vZ2xlIHRoaW5ncy4gSXQncyByZWFsbHkgZWFzeSB0byBmZWVsIGEgYml0IG92ZXJ3aGVsbWVkIGFuZCB1bnN1cmUgd2hlcmUgdG8gc3RhcnQgd2l0aCBhbnkgY29kaW5nIGxhbmd1YWdlLCBidXQgcmVtZW1iZXIgdGhhdCBub2JvZHkgaXMgZXhwZWN0aW5nIHlvdSB0byBzdWRkZW5seSBiZWNvbWUgZmx1ZW50IG9yIG1lbW9yaXNlIGV2ZXJ5dGhpbmcgKGFzIGFub3RoZXIgZXhhbXBsZSwgSSd2ZSBqdXN0IGhhZCB0byBnb29nbGUgaG93IHRvIGNvZGUgc3ViLWJ1bGxldCBwb2ludHMgdG8gdGhlIGFib3ZlIGxpc3QhKS4gV2UganVzdCB3YW50IHlvdSB0byBnZXQgc29tZSBmYW1pbGlhcml0eSBhbmQgZXhwZXJpZW5jZS4gCgojIyMgTm93IHRoZW4sIEkndmUgc2FpZCBhbGwgb2YgdGhpcywgYnV0IGhhdmVuJ3QgYW5zd2VyZWQgb25lIGtleSBxdWVzdGlvbiAtIHdoYXQgaXMgUj8hCgpSIGlzIGEgZnJlZWx5IGF2YWlsYWJsZSBwcm9ncmFtbWluZyBsYW5ndWFnZSwgZGV2ZWxvcGVkIGluIHRoZSBlYXJseSAxOTkwcywgbWFkZSBvcGVuIHNvdXJjZSBpbiAxOTk1LiBSIHdhcyBkZXZlbG9wZWQgb24gdG9wIG9mIGFub3RoZXIgbGFuZ3VhZ2UsIFMuIFMgd2FzIGEgcHJvcHJpYXRvcnkgbGFuZ3VhZ2UsIHdoaWNoIHVsdGltYXRlbHksIFIgYmVjYW1lIHRoZSBvcGVuIHNvdXJjZSB2ZXJzaW9uIG9mLgoKUidzIGV0aG9zIHdhcyB0byBkZXZlbG9wIHNvbWV0aGluZyBzcGVjaWZpY2FsbHkgZm9yIHN0YXRpc3RpY2FsIGNvbXB1dGF0aW9uIGFuZCB2aXN1YWxpc2F0YWlvbiAtIGl0IHdhcyBkZXZlbG9wZWQgKipieSoqIHJlc2VhcmNoZXJzLCAqKmZvcioqIHJlc2VhcmNoZXJzLgoKU28sIGluIDIwMjMsIHdoZW4geW91IG1heSBoYXZlIGFscmVhZHkgYmVndW4gdG8gbGVhcm4sIGZvciBleGFtcGxlLCBQeXRob24sIHdoeSBib3RoZXIgd2l0aCBSPwoKKiBUaGUgc3RhdGlzdGljcyBhbmQgZGF0YS12aXMgcGFja2FnZXMgaW4gUHl0aG9uIGFyZSB2ZXJ5IHJlY2VudCwgdGhleSBkaWQgbm90IGV4aXN0IDEwIHllYXJzIGFnbyEKKiBUaGUgImRlZmF1bHQiIGxhbmd1YWdlIHZhcmllcyBmcm9tIGZpZWxkIHRvIGZpZWxkLCBidXQgY2VydGFpbmx5IGluIGVjb2xvZ3kgYW5kIGV2b2x1dGlvbiwgeW91J3JlIGxpa2VseSB0byBiZSB3b3JraW5nIHdpdGggY29sbGVhZ3VlcyB3aG8gdXNlIFIgKGludGVyZXN0aW5nbHksIGVjb2xvZ2lzdHMgd2VyZSBhY3R1YWxseSBvbmUgb2YgdGhlIGZpcnN0IHVzZXIgYmFzZXMgb2YgUikKKiBSIGlzIGRlc2lnbmVkIHRvIGJlIGFuIGVmZmljaWVudCwgaW50ZXJwcmV0ZWQgbGFuZ3VhZ2UgaW4gYSB3YXkgdGhhdCBpcyBmdW5kZW1lbnRhbGx5IGRpZmZlcmVudCB0byB0aGUgaW5pdGlhbCBkZXNpZ24gb2YgUHl0aG9uLCB3aGljaCBpcyB0eXBpY2FsbHkgaW50ZXJhY3RlZCB3aXRoIHZpYSBhIHNjcmlwdC4gUiBpcyBkZXNpZ25lZCB0byBiZSBhIHNvcnQgb2YgInN0YXRpc3RpY2FsIGNvbnZlcnNhdGlvbiIgd2hlcmUgeW91IGludGVyYWN0aXZlbHkgcHJvZ3JhbS4KKiBSIHdhcyBkZXNpZ25lZCB0byBoYXZlIGVmZmljaWVudCBkYXRhIGhhbmRsaW5nIGFuZCBzdG9yYWdlIG1lY2hhbmlzbXMuIFRoZXJlIGFlciBsb3RzIG9mIHR5cGVzIG9mIGRhdGEgc3RydWN0dXJlcyBpbiBSIC0gdGhlc2UgbWlnaHQgc2VlbSB1bm5lY2Vzc2FyeSBhdCBmaXJzdCwgYnV0IGFzIHdlIGRlbHZlIGRlZXBlciBpbnRvIFIgYW5kIGhvdyBpdCB3b3JrcywgeW91J2xsIHNlZSB3aHkgdGhleSdyZSBpbXBvcnRhbnQuIFIgaXMgd3JpdHRlbiBpbiBhIHdheSB0aGF0IG1ha2VzIGFjY2Vzc2luZyByZWFzb25hYmx5IHNpemVkIGRhdGFzZXRzIHN1cGVyIGVmZmljaWVudC4gVHlwaWNhbGx5LCB0aGlzIGlzIG5vdCB0cnVlIG9mIFB5dGhvbiBmb3IgYSBwbGV0aG9yYSBvZiByZWFzb25zIHRoYXQgd2UgZG9uJ3QgaGF2ZSB0aGUgdGltZSB0byB0YWxrIGFib3V0IChhbHRob3VnaCBhZG1pdHRlZGx5IHRoaXMgaXMgZ2V0dGluZyBiZXR0ZXIgd2l0aCB0aGUgYWR2ZW50IG9mIG1vZHVsZXMgc3VjaCBhcyBQYW5kYXMpCiogUiBjb250YWlucyBhIGxhcmdlIGNvbGxlY3Rpb24gb2YgdG9vbHMgc3BlY2lmaWNhbGx5IGRldmVsb3BlZCBmb3IgZGF0YSBhbmFseXNpcywgYXMgd2VsbCBhcyBzb21lIHJlYWxseSBnb29kIGJ1aWx0IGluIGRhdGEgdmlzdWFsaXNhdGlvbiBmZWF0dXJlcyEKKiBUaGVyZSBpcyBhIGh1Z2UgbXVsdGl2ZXJzZSB0aGF0IGhhcyBiZWVuIGJ1aWx0IGFyb3VuZCBSIHdpdGggbG9hZHMgb2YgZGlmZmVyZW50IGZsYXZvdXJzIGFzc29jaWF0ZWQgd2l0aCBpdC4gV2UnbGwgZGlzY3VzcyB0aGlzIGluIG1vcmUgZGV0YWlsIG5leHQgd2Vlay4KKiBGaW5hbGx5LCBSIGlzIGZ1bmRlbWVudGFsbHkgZGVzaWduZWQgdG8gYmUgc2ltcGxlLiBUaGlzIGlzIHdoeSBpdCdzIHRhdWdodCB0byBub24tcHJvZ3JhbW1lcnMuIFlvdSBkb24ndCBoYXZlIHRvIGRvIGNvbXBsaWNhdGVkIHRoaW5ncyBsaWtlIGZvciBsb29wcyBpZiB5b3UgZG9uJ3Qgd2FudCB0byAoYWx0aG91Z2ggd2UncmUgZ29pbmcgdG8hKS4gVGhlc2UgY2FuIGJlIGF2b2lkZWQgYW5kIFIgY2FuIGJlIHVzZWQgZm9yIGl0J3MgYmFzZSBmdW5jdGlvbmFsaXR5IG9mIGRhdGEgYW5hbHlzaXMgYW5kIHBsb3R0aW5nIHdpdGggbm8gZmFuY3kgZXh0cmFzIGlmIHlvdSBkb24ndCB3YW50IHRoZW0uCgpNb3JlIHNwZWNpZmljYWxseToKCiogUiBpcyBhIG1ham9yIHBhcnQgb2YgdGhlIGJpb2luZm9ybWF0aWMgYW5kIGJpb3N0YXRpc3RpY3MgdG9vbGtpdHMsIGFuZCBpdCBpc24ndCBnb2luZyBhd2F5IGFueSB0aW1lIHNvb24uCiogSXQgd2FzIGV4cGxpY2l0bHkgZGVzaWduZWQgdG8gaGFuZGxlIGRhdGEsIHBhcnRpY3VsYXJseSBpbiBhIGZvcm1hdCBrbm93biBhcyBkYXRhLmZyYW1lcyAtIHRoaXMgaXMgZXh0cmVtZWx5IGltcG9ydGFudCB0byB0aGUgd2F5IHRoYXQgUiBmdW5jdGlvbnMKKiBJdCBpcyBmcmVlLCBhbmQgd2lkZWx5IHN1cHBvcnRlZC4gSW4gRXZvbHV0aW9uIGFuZCBFY29sb2d5IHBhcGVycyBpbiB0aGUgbGFzdCBkZWNhZGUsIDY2JSBtZW50aW9uIFIuIElmIHlvdSB3YW50IHRvIGhhdmUgYSBjYXJlZXIgaW4gcmVzZWFyY2gsIFIgaXMgYSB2aXRhbCBza2lsbC4KKiBSIGlzIHVzZWQgYnkgbG9hZHMgb2YgbWFqb3IgdGVjaCBjb21wYW5pZXMgZm9yIHRoZWlyIGFuYWx5dGljcyAtIGluY2x1ZGluZyBmYWNlYm9vaywgZ29vZ2xlLCBhbmQgdHdpdHRlciEKCgojIyMgU28sIGhvdyBkbyB3ZSBpbnRlcmFjdCB3aXRoIFI/CgpIb3cgZG8gd2UgdXNlIFIgdG8gaGF2ZSB0aG9zZSBzdGF0aXN0aWNhbCBjb252ZXJzYXRpb25zIHRoYXQgSSByZWZlcmVuY2VkIGVhcmxpZXI/IFRoZXJlIGFyZSAyIG1haW4gd2F5cy4gVGhlIGZpcnN0IHdheSBpcyB0byB1c2UgUiBkaXJlY3RseSB0aHJvdWdoIGFuIGludGVyZmFjZSBrbm93biBhcyAiYmFzZSBSIiBvciAibmF0aXZlIFIiLiBUaGlzIGlzIHVzaW5nIFIgaW4gaXQncyBwdXJlc3QgZm9ybSwgYW5kIGlzIGFjdHVhbGx5IHF1aXRlIHRyaWNreS4gSWYgd2UgbG9hZCBiYXNlIFIsIHdlIHNlZSBhIHdpbmRvdyBsaWtlIHRoaXM6CgohW10oYmFzZVIucG5nKQoKVGhpcyBjb25zb2xlIHdpbmRvdyBjb250YWlucyBhIGxvYWQgb2YgZ29iYmxlZGVnb29rIGFidXQgdmVyc2lvbiBudW1iZXJzIGV0Yy4sIHdoaWNoIHdpbGwgdmFyeSBiZXR3ZWVuIGluZGl2aWR1YWwgbWFjaGluZXMgYW5kIFIgaW5zdGFsbHMuIFRoZSBPUyB0aGF0IHlvdSdyZSBydW5uaW5nIHdpbGwgYWxzbyBkcmFtYXRpY2FsbHkgaW1wYWN0IGhvdyB5b3VyIFIgd2luZG93IGxvb2tzIC0gdGhpcyBpcyB0aGUgTWFjT1MgUiB2ZXJzaW9uLiBFc3NlbnRpYWxseSwgUiBpcyB3YWl0aW5nIGZvciB5b3UgdG8gZW50ZXIgY29tbWFuZHMgYW5kIHRlbGwgaXQgd2hhdCB0byBkbyBuZXh0LiBBcyB5b3UgY2FuIHNlZSwgaXQncyBub3Qgb3Zlcmx5IHVzZXIgZnJpZW5kbHkuIFRoYXQgYmVpbmcgc2FpZCwgdGhlIE1hY09TIHZlcnNpb24gaXMgbXVjaCBuaWNlci4gVGhlIFdpbmRvd3MgdmVyc2lvbiBpcyBjbHVua3ksIGFuZCBldmVuIGxlc3MgZnJpZW5kbHkuIE1hY09TIFIgaGFzIGZlYXR1cmVzIG5vdCBhdmFpbGFibGUgb24gV2luZG93cyB0b28sIHdoaWNoIG1lYW5zIHVzaW5nIFIgYWNyb3NzIG11bHRpcGxlIG1hY2hpbmVzIGNhbiBiZSBhIGJpdCBvZiBwYWluLiAKCkhlcmUsIHdlIHdpbGwgdXNlIGFuIFIgSURFLCBrbm93biBhcyBSU3R1ZGlvIChhbHRob3VnaCB5b3UgbWlnaHQgYWxzbyBoZWFyIGl0IHJlZmVycmVkIHRvIGFzIHBvc2l0KS4gQW4gSURFLCBvciBhbiAqaW50ZXJhY3RpdmUgZGV2ZWxvcGVyIGVudmlyb25tZW50KiwgaXMgYSBidWlsdC1vbiBpbnRlcmZhY2UgdGhhdCBoZWxwcyB5b3UgdG8gcnVuIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgbW9yZSBlYXNpbHkgYW5kIGVmZmVjdGl2ZWx5LiBPdGhlciBleGFtcGxlcyBvZiBJREVzIGNhbiBiZSBmb3VuZCBpbiBQeXRob24gLSB5b3UgbWlnaHQgaGF2ZSBjb21lIGFjcm9zcyBTcHlkZXIgb3IgSnVweXRlciBmb3IgZXhhbXBsZS4gUlN0dWRpbyBpcyBjb21wbGV0ZWx5IGZyZWUsIGFuZCB0aGUgYmVzdCBSIElERSBJJ3ZlIGZvdW5kLiBJdCdzIGFsc28gdGhlIG1vc3Qgd2VsbCBzdXBwb3J0ZWQsIHdoaWNoIGlzIHVzZWZ1bC4gVGhlcmUgYXJlIG90aGVycywgYnV0IFJTdHVkaW8gaXMgcGFydGljdWxhcmx5IGdvb2QuIEl0IHdpbGwgaGVscCB0byBtYWtlIHlvdXIgUiBqb3VybmV5IG11Y2ggc21vb3RoZXIsIGFuZCBhY3R1YWxseSBoZWxwcyB5b3UgdG8gc3BvdCBlcnJvcnMgaW4geW91ciBjb2RlLCB3aGljaCBpcyBhbHdheXMgYSBib251cyEgIAoKSXQgbG9va3MgYSBiaXQgbGlrZSB0aGlzOgoKIVtdKFJTdHVkaW8ucG5nKQoKWW91J2xsIG5vdGljZSB0aGF0IG15IHZlcnNpb24gb2YgUlN0dWRpbyBpcyBkaWZmZXJlbnRseSBjb2xvdXJlZCB0byB5b3VycyAtIHRoaXMgaXMganVzdCBkdWUgdG8gcGVyc29uYWwgcHJlZmVyZW5jZS4gSSBzcGVuZCBsb3RzIG9mIHRpbWUgc3RhcmluZyBhdCBteSBSIHdpbmRvdyByYXRoZXIgaW50ZW50bHksIHNvIGhhdmluZyBpdCBkYXJrZXIgcmVhbGx5IGhlbHBzISEhCgpSU3R1ZGlvIHN0YW5kYXJkaXNlcyB0aGUgUiBpbnRlcmZhY2UgYWNyb3NzIGFsbCBwbGF0Zm9ybXMgLSBpdCBsb29rcyB0aGUgc2FtZSB3aGF0ZXZlciBPUyB5b3UgbWlnaHQgYmUgcnVubmluZy4gSXQgYWxzbyBoYXMgYSBsb3Qgb2YgcG93ZXJmdWwgZmVhdHVyZXMgdGhhdCBtYWtlcyBydW5uaW5nIFIgbW9yZSBzdHJhaWdodGZvcndhcmQsIHdlJ2xsIHRhbGsgYWJvdXQgdGhlc2UgaW4gbW9yZSBkZXRhaWwgaW4gdGhlIGNvbWluZyBzZXNzaW9ucy4gSXQgYWxzbyBoYXMgZ3JlYXQgcHJvamVjdCBtYW5hZ2VtZW50IHRvb2xzLCB3aGljaCBhcmUgZW5kbGVzc2x5IHVzZWZ1bCB3aGVuIHlvdSdyZSB3b3JraW5nIG9uIG11bHRpcGxlIHByb2plY3RzIGFsbCBhdCB0aGUgc2FtZSB0aW1lIQoKTm93LCBsZXQncyB0YWxrIHRocm91Z2ggd2hhdCBhbGwgdGhlIGJpdHMgYXJlIGFib3V0LgoKIVtdKFJTdHVkaW8yLnBuZykKCkFzIHlvdSBjYW4gc2VlIGFib3ZlLCB0aGUgUlN0dWRpbyBpbnRlcmZhY2UgaXMgbWFkZSB1cCBvZiB2YXJpb3VzIHBhcnRzLiBUaGUgZmlyc3Qgb2Ygd2hpY2ggaXMgdGhlIGNvbnNvbGUuIFRoaXMsIGxpa2UgbmF0aXZlIFIsIGlzIHdhaXRpbmcgZm9yIHlvdXIgaW5wdXQgaW4gdGhlICJzdGF0aXN0aWNhbCBjb252ZXJzYXRpb25zIiB0aGF0IHlvdSdsbCBiZSBoYXZpbmcgd2l0aCBSLiBJdCBnaXZlcyB5b3UgYSBiaXQgb2YgYW4gb2RkIGJsdXJiIGFib3V0IHZlcnNpb25pbmcgZXRjLiBFYWNoIG9mIHRoZSB2ZXJzaW9ucyBoYXMgYSBzbGlnaHRseSBvZGQgbmFtZSwgSSdtIG5vdCBzdXJlIHdoeS4gU29tZSBvZiB0aGVtIGFyZSBuYW1lZCBhZnRlciB2YXJpb3VzIGFsYnVtcyBidXQgdGhhdCdzIGFzIGZhciBhcyBJJ3ZlIGdvdCB3aXRoIGZpZ3VyaW5nIG91dCB0aGUgbmFtaW5nIHN5c3RlbSEKCkFueXdheSwgdGhlcmVzIGxvYWRzIG9mIG90aGVyIHN0dWZmIG92ZXIgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSwgbW9zdCBvZiB3aGljaCBpcyBub3QgaW1vcnRhbnQgb3IgdXNlZnVsIHRvIHlvdSByaWdodCBub3cuIFRoZSAiRW52aXJvbm1lbnQiIHNlY3Rpb24ga2VlcHMgdHJhY2sgb2Ygd2hhdCB5b3UndmUgZ290IGxvYWRlZCBpbiB0ZXJtcyBvZiBkYXRhc2V0cyBhbmQgdmFyaWFibGVzIGV0Yy4sIHdoaWNoIGNhbiBwcm92ZSBpbmNyZWRpYmx5IHVzZWZ1bC4gVW5kZXJuZWF0aCwgeW91IGNhbiBmaW5kIGZpbGUgdHJlZXMsIHBsb3RzIHRoYXQgeW91IGhhdmUgY3JlYXRlZCwgaGVscCBmaWxlcywgYW5kIGxvYWRzIG9mIG90aGVyIHN0dWZmIHRoYXQgd2UgY2FuIHRhbGsgbW9yZSBhYm91dCBsYXRlciBvbi4KCiMjIFByb2plY3QgTWFuYWdlbWVudCBpbiBSCgpTdGFydGluZyB3aXRoIHByb2plY3QgbWFuYWdlbWVudCB0b29scyBmZWVscyBhIGJpdCBiaXphcnJlLCBidXQgYXMgc29tZW9uZSB3aG8gdXNlZCBSIGZvciBtYW55IG1hbnkgeWVhcnMgd2l0aG91dCB0aGlzIGZ1bmN0aW9uYWxpdHksIHRydXN0IG1lLCBpdCdzIGVhc2llc3QgdG8gZ2V0IHRvIGdyaXBzIHdpdGggaXQgZWFybHkgZG9vcnMuIFNvbWV0aGluZyB0aGF0IHBlb3BsZSBzdHJ1Z2dsZSB3aXRoLCBhbmQgc29tZXRoaW5nIHlvdSBtaWdodCBoYXZlIGNvbWUgYWNyb3NzIHdpdGggb3RoZXIgY29kaW5nIGxhbmd1YWdlcywgaXMgd2hlcmUgZmlsZXMgYXJlIHN0b3JlZCBvbiBhIGNvbXB1dGVyLiBSU3R1ZGlvIGhhcyBhIGdyZWF0IGZlYXR1cmUgdGhhdCB3aWxsIG1ha2UgdGhpcyBtdWNoIGVhc2llciB0byBkZWFsIHdpdGguIFNvLCB0byBkZW1vbnN0cmF0ZSB3aGF0IEkgbWVhbiwgdHlwZSB0aGUgZm9sbG93aW5nIGNvZGUgaW50byB5b3VyIGNvbnNvbGUgd2luZG93LCBhbmQgcHJlc3MgZW50ZXIuCgpgYGB7cn0KZ2V0d2QoKQpgYGAKClRoaXMgaXMgdGhlIGdldCB3b3JraW5nIGRpcmVjdG9yeSBjb21tYW5kLCBhbmQgaXMgc2ltaWxhciB0byBjb21tYW5kcyBpbiB1bml4IGFuZCBweXRob24gLSBpbiB1bml4LCB5b3UnZCB1c2UgYGBgcHdkKClgYGAuIFRoaXMgY29tbWFuZCBwcmludHMgdGhlIHdvcmtpbmcgZGlyZWN0b3J5LiAoKkEgcXVpY2sgbm90ZSBvbiBmdW5jdGlvbnMgaW4gUiB3aGljaCB3ZSB3aWxsIGNvbWUgYmFjayB0byAtIGFueXRoaW5nIGZvbGxvd2VkIGJ5ICgpIGlzIGEgZnVuY3Rpb24gaS5lLiBzb21ldGhpbmcgdGhhdCB0YWtlcyBhbiBpbnB1dCBhbmQgZG9lcyBzb21ldGhpbmcgd2l0aCBpdCopIElmIHlvdSBydW4gdGhlIGBgYGdldHdkKClgYGAgY29tbWFuZCwgeW91IHdpbGwgZ2V0IGFuIG91dHB1dCB3aXRoIGEgZmlsZXBhdGgsIHRoaXMgaXMgeW91ciBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LCBvciwgd2hlcmUgUiBpcyBsb29raW5nIGZvciBmaWxlcyEgWW91IGNhbiB1c2UgUiBieSBwdXR0aW5nIHN0dWZmIHBsYWNlcyBhbmQgdGhlbiB1c2luZyBsb2FkcyBvZiByZWFsbHkgbG9uZyBhbmQgZGlmZmljdWx0IHBhdGggbmFtZXMgdG8gbmF2aWdhdGUgdGhyb3VnaCB5b3VyIGNvbXB1dGVycyBmaWxlIHN5c3RlbSBhbmQgdGhlbiBzdGlja2luZyB0byB0aGUgc2FtZSBkaXJlY3RvcnkuIFRoaXMgcXVpY2tseSBiZWNvbWVzIGEgbmlnaHRtYXJlIGlmIHlvdSdyZSB3b3JraW5nIG9uIG11bHRpcGxlIHByb2plY3RzIGF0IG9uY2UgdGhvdWdoLCBiZWNhdXNlIHlvdSBlbmQgdXAgdHJ5aW5nIHRvIHJlYWQgZmlsZXMgZnJvbSBhbmQgd3JpdGUgZmlsZXMgdG8gdGhlIHdyb25nIGRpcmVjdG9yaWVzLCB3aGljaCB5b3UgaGF2ZSB0byBrZWVwIGNoYW5naW5nIQoKQSBiZXR0ZXIgaWRlYSBpcyB0byBzZXQgdXAgUiB1c2luZyBwcm9qZWN0cy4gVGhlc2UgY29udGFpbiBldmVyeXRoaW5nIHlvdSBuZWVkIHdoaWNoIGlzIGFzc29jaWF0ZWQgd2l0aCBhIHNpbmdsZSBiaXQgb2YgYW5hbHlzaXMgb3IgYSBzaW5nbGUgKnByb2plY3QqIChzZWUgd2hhdCBJIGRpZD8pIHRoYXQgeW91J3JlIHVzaW5nIFIgdG8gd29yayBvbi4gV2Ugd2lsbCBjcmVhdGUgYSBwcm9qZWN0IGZvciB0aGlzIHNlc3Npb24sIHdoaWNoIHdpbGwgY3JlYXRlIGEgc2VsZi1jb250YWluZWQgZGlyZWN0b3J5LCB3aGljaCBSIHdpbGwgYWx3YXlzIG9wZW4gd2hlbiBsb29raW5nIGZvciBmaWxlcyBhc3NvY2lhdGVkIHdpdGggd2hhdCB3ZSdyZSBkb2luZywgc28geW91IGRvbid0IGhhdmUgdG8gdHJ5IGFuZCBuYXZpZ2F0ZSB0aHJvdWdoIGNvbXBsaWNhdGVkIGZpbGUgc3RydWN0dXJlcyB3aXRoaW4gUiBpdHNlbGYuIFRoaXMgaXMgcmVsYXRpdmVseSBzdHJhaWdodCBmb3J3YXJkLCBhbmQgd2UnbGwgZG8gaXQgbm93LgoKVXAgaW4gdGhlIHJpZ2h0IGhhbmQgY29ybmVyIG9mIHlvdXIgUlN0dWRpbyB3aW5kb3csIHRoZXJlIHNob3VsZCBiZSBhIGJpdCBvZiB0ZXh0IHRoYXQgcmVhZHMgcHJvamVjdDxub25lPiBvciBzaW1pbGFyLiBDbGljayBvbiB0aGlzLCBhbmQgeW91J2xsIGdldCBhIGRyb3AgZG93biBtZW51IGFwcGVhci4gRnJvbSB0aGlzIG1lbnUsIHNlbGVjdCAibmV3IHByb2plY3QiLCB3aGljaCB3aWxsIGdpdmUgeW91IHNvbWUgbW9yZSBvcHRpb25zLiBDaG9zZSAibmV3IGRpcmVjdG9yeSIgYW5kIGNhbGwgaXQgc29tZXRoaW5nIHNlbnNpYmxlLCBsaWtlICJMSUZFNDEzOC1SIi4KCioqTm90ZTogRG9uJ3QgZXZlciB1c2Ugc3BhY2VzIGluIGZpbGUgb3IgZGlyZWN0b3J5IG5hbWVzLiBJdCdzIGEgcmVhbGx5IGVhc3kgd2F5IHRvIG1ha2Ugc3VyZSB0aGF0IFIgd2lsbCBraWNrIG9mZiBhdCB5b3UhIFVzZSBhbiB1bmRlcnNjb3JlIGluc3RlYWQhKioKCgpGaW5hbGx5LCBjbGljayAiY3JlYXRlIHByb2plY3QiIGFuZCBSIHdpbGwgZG8gdGhlIHJlc3QgZm9yIHlvdS4gTm93LCBpZiB5b3UgdHJ5IHRoZSBgYGBnZXR3ZCgpYGBgIGZ1bmN0aW9uIGFnYWluLCBpdCBzaG91bGQgcHJpbnQgb2YgdGhlIGxvY2F0aW9uIG9mIHRoZSBuZXcgZGlyZWN0b3J5ISBJdCB3aWxsIGFsc28gaGF2ZSBjaGFuZ2VkIHRoZSBpbmZvcm1hdGlvbiBkaXNwbGF5ZWQgaW4gdGhlICJmaWxlcyIgc2VjdGlvbiwgaGF2aW5nIGNyZWF0ZWQgYSBuZXcgZm9sZGVyIHdoZXJldmVyIHlvdSBhc2tlZCBpdCB0by4gVGhlIGVhc2llc3Qgd2F5IHRvIGFjY2VzcyBmaWxlcyBub3cgaXMgdG8gcG9wIHRoZW0gZGlyZWN0bHkgaW50byB0aGlzIGZvbGRlci4gWW91IGNvdWxkIG5vdyBzZW5kIHNvbWVvbmUgdGhpcyAuUnByb2ogZmlsZSwgYW5kIHRoZXknZCBoYXZlIGFsbCB0aGUgc3R1ZmYgdGhleSBuZWVkZWQgdG8gcmVjcmVhdGUgeW91ciB3b3JrIQoKQW55d2F5LCB0aGF0IHdhcyBhbiBvZGQgcGxhY2UgdG8gc3RhcnQsIGJ1dCBpdCBpcyBpbXBvcnRhbnQgdG8gZ2V0IHRoaXMgcGFydCByaWdodC4KCiMjIEludGVyYWN0aW5nIHdpdGggdGhlIFIgZW52aXJvbm1lbnQKCldoZW4gd2UgaW50ZXJhY3Qgd2l0aCBSLCBnZW5lcmFsbHkgd2UgYXJlIHR5cGluZyBpbiB0aGUgY29uc29sZS4gWW91IGNhbiBhbHNvIHdyaXRlIHNjcmlwdHMgKGlmIHlvdSBkb24ndCBoYXZlIGEgc2NyaXB0IGFscmVhZHkgb3BlbiwgeW91IGNhbiBvcGVuIGEgbmV3IG9uZSBieSBjbGlja2luZyB0aGUgbmV3IHNjcmlwdCBvcHRpb24gZnJvbSB0aGUgbWVudSBhdCB0aGUgdG9wIGxlZnQgb2YgdGhlIHNjcmVlbiAtIHRoZSB3aGl0ZSByZWN0YW5nbGUgd2l0aCBhIGdyZWVuICsgaW4gdGhlIHRvcCBjb3JuZXIhKS4gQSBzY3JpcHQgaXMgZWZmZWN0aXZlbHkgYSByZWNvcmQgb2Ygd2hhdCB5b3UgaGF2ZSBkb25lIHVzaW5nIFIsIGFsbG93aW5nIHlvdSB0byBrZWVwIHRyYWNrLiBXaGVuIHlvdSd2ZSB3cml0dGVuIGNvbW1hbmRzIGluIGEgc2NyaXB0LCB5b3UgY2FuIHJ1biB0aGVtIHdpdGggeW91ciBjdXJzb3Igb24gdGhlIGxpbmUgb2YgY29kZSB5b3Ugd2lzaCB0byBydW4sIGFuZCBwcmVzc2luZyBjdHJsK2VudGVyIChjbWQrZW50ZXIgb24gTWFjT1MpLiBZb3UgbWF5IGhhdmUgY29tZSBhY3Jvc3Mgc2NyaXB0cyBpbiBweXRob24gYW5kIHVuaXgsIGJ1dCBnZW5lcmFsbHkgd2UgcnVuIHRoZW0gYSBsaXR0bGUgZGlmZmVyZW50bHkgaW4gUi4gV2UgdGVuZCB0byBydW4gc2NyaXB0cyBpbnRlcmFjdGl2ZWx5LCBlaXRoZXIgYSBzaW5nbGUgbGluZSBvciBhIGZldyBsaW5lcyBhdCBhIHRpbWUsIGFzc2VzcyBhbiBvdXRwdXQsIGFuZCB0aGVuIHJ1biBzb21lIG1vcmUuCgojIExldCdzIGdldCBzdGFydGVkIHVzaW5nIFIhCgojIyMgUiBhcyBhIGNhbGN1bGF0b3IKCkZpcnN0IHRoaW5ncyBmaXJzdCwgUiBjYW4gYmUgdXNlZCBhcyBhIGJhc2ljIGNhbGN1bGF0b3IuIFRyeSB0eXBpbmcgdGhlIGZvbGxvd2luZyBjb21tYW5kcyBpbnRvIHlvdXIgc2NyaXB0IHdpbmRvdyBhbmQgcnVubmluZyB0aGVtIHdpdGggY3RybC9jbWQrZW50ZXIuCgpgYGB7cn0KNAo0ICsgMwo1MCAtIDUKNTAgKiAyMDAwCjkgLyAzCjEwIF4gMgpgYGAKCllvdSBjYW4gc2VlIGJ5IGRvaW5nIHRoaXMgdGhhdCBSIGlzIGFibGUgdG8gcGVyZm9ybSBiYXNpYyBtYXRoZW1hdGljYWwgZnVuY3Rpb25zLiBZb3UnbGwgaGF2ZSBub3RpY2VkIHdoZW4geW91IGdhdmUgaXQgYSBzaW5nbGUgbnVtYmVyIGlucHV0LCBpdCBlY2hvZWQgdGhpcyBudW1iZXIgYmFjayB0byB5b3UuIFBsYXkgYXJvdW5kIHdpdGggdGhpcywgYW5kIHNlZSB3aGF0IFIgaXMgY2FwYWJsZSBvZiEgV2hpbHN0IHlvdSdyZSB1bmxpa2VseSB0byBvZnRlbiB1c2UgUiBleHBsaWNpdGx5IGFzIGEgY2FsY3VsYXRvciwgaXQgaXMgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgdGhhdCBpdCBjYW4gaGFuZGxlIG51bWVyaWNzLgoKKk5vdGU6IHRoZSAiPiIgcHJvbXB0IGluIHRoZSBjb25zb2xlIGlzIHdhaXRpbmcgZm9yIHlvdSB0byBhc2sgaXQgc29tZXRoaW5nIC0gdHJ5IHJ1bm5pbmcgdGhlIGV4YW1wbGVzIGRpcmVjdGx5IGluIHRoZSBjb25zb2xlIGFzIHdlbGwgYXMgaW4gc2NyaXB0IGZvcm0hKgoKIyMjIFIgYW5kIHRleHQgaW5wdXQKClIgY2FuIGFsc28gaW50ZXJwcmV0IHRleHQhIFlvdSBjYW4gZ2l2ZSBpdCBhIGNoYXJhY3RlciBzdHJpbmcsIGFuZCBpdCB3aWxsIHByaW50IGl0IGJhY2sgdG8geW91IC0gdHJ5IHJ1bm5pbmcgdGhlIGZvbGxvd2luZzoKCmBgYHtyfQoiSGVsbG8gd29ybGQhIgonSGVsbG8gd29ybGQhJwpIZWxsbyB3b3JsZApgYGAKTm90ZSB0aGF0IHRoZSBsYXN0IGV4YW1wbGUgb2YgdGhpcyBkb2VzIG5vdCB3b3JrLCBiZWNhdXNlIFIgaXMgbG9va2luZyBmb3IgYW4gKipvYmplY3QqKiBjYWxsZWQgSGVsbG8gd29ybGQgd2hpY2ggaXQgY2Fubm90IGZpbmQuIFdpdGhvdXQgdGhlIHF1b3RhdGlvbiBtYXJrcyAoZWl0aGVyIHR5cGUgaXMgZmluZSwgYnV0IGJlIGNvbnNpc3RlbnQpLCBpdCBkb2VzIG5vdCByZWNvZ25pc2UgdGhlIHRleHQgYXMgYSBzdHJpbmcuCgpZb3UnbGwgaGF2ZSBnb3QgYSBmdW5reSBlcnJvciBpbiB0aGUgbGFzdCBleGFtcGxlLCBzb21ldGhpbmcgYWJvdXQgYW4gdW5lcGV4dGVkIHN5bWJvbCAtIGl0IGxpa2VseSB3b250IGhhdmUgbWFkZSBtdWNoIHNlbnNlIHRvIHlvdS4gVGhpcyBpcyBmYWlybHkgdHlwaWNhbCBvZiBSIGVycm9yIG1lc3NhZ2VzIHVuZm9ydHVuYXRlbHksIHRoZXkgYXJlIGZhbWVkIGZvciBiZWluZyB0cmlja3kgdG8gaW50ZXJwcmV0LiBUaGV5IHRha2Ugc29tZSBnZXR0aW5nIHVzZWQgdG8sIGJ1dCBldmVudHVhbGx5IHlvdSB3aWxsIGJlIGFibGUgdG8gdHJhbnNsYXRlIHRoZXNlIGJpemFycmUgbWVzc2FnZXMgaW50byBzb21ldGhpbmcgdGhhdCBhY3R1YWxseSBtYWtlcyBzZW5zZS4gRm9yIGV4YW1wbGUsIGhlcmUsIHRoZSAidW5leHBlY3RlZCBzeW1ib2wiIGlzIHJlZmVycmluZyB0byB0aGUgc3BhY2UgYmV0d2VlbiB0aGUgd29yZHMgIkhlbGxvIiBhbmQgIndvcmxkIi4gV2l0aG91dCB0aGUgcXVvdGF0aW9uIG1hcmtzLCBSIGV4cGVjdHMgdGhlc2UgdGhpbmdzIHRvIGJlIGZ1bmN0aW9ucyBvciBvYmplY3RzIHJhdGhlciB0aGFuIGEgY2hhcmFjdGVyIHN0cmluZywgYW5kIGNhbm5vdCBwcm9jZXNzIHRoZSBzcGFjZS4KCgojIyMgUiBhcyBhIGxvZ2ljYWwgaW50ZXJwcmV0ZXIKClIgY2FuIHRlbGwgeW91IHdoZXRoZXIgYSBzdGF0ZW1lbnQgaXMgdHJ1ZSBvciBmYWxzZS4gVGhpcyBzZWVtcyBiYXNpYywgYnV0IGl0IHdpbGwgYnVpbGQgdXAgdG8gY3JlYXRlIGEgdXNlZnVsIHRvb2wgYWxvbmdzaWRlIHRoZSBvdGhlciBwYXJ0cyBvZiBpdCdzIGZ1bmN0aW9uYWxpdHkgdGhhdCB3ZSdyZSBkaXNjdXNzaW5nLiBUaGUgbG9naWNhbCBpbnRlcnByZXRlciB3aXRoaW4gUiBpcyBhIGtleSBwYXJ0IG9mIGhvdyBSIGZ1bmN0aW9ucyBhcyBhIHBlaWNlIG9mIHNvZnR3YXJlLCBhbmQgaXMgY29tbW9ubHkgaW4tYnVpbHQgaW50byBtYW55IHNvcGhpc3RpY2F0ZWQgZnVuY3Rpb25zIGFuZCBhbmFseXNlcy4gUiB3aWxsIHRlbGwgeW91IGlmIHNvbWV0aGluZyBpcyBsb2dpY2FsLCBvciBpZiBpdCBtYWtlcyBzZW5zZSwgYnkgcmV0dXJuaW5nIGVpdGhlciBgYGBUUlVFYGBgIG9yIGBgYEZBTFNFYGBgIHRvIGFuIGlucHV0LiBUaGlzIGlzIHBvc3NpYmxlIHdpdGggbnVtZXJpY2FsIGlucHV0ICoqYW5kKiogY2hhcmFjdGVyIHN0cmluZ3MgLSB0cnkgdGhlIGZvbGxvd2luZyBmb3IgZXhhbXBsZToKYGBge3J9CjIgPT0gMgo1ID4gMTAKOSA8PSAxMAoiTWFyaW8iID09ICJNYXJpbyIKIk1hcmlvIiA9PSAiTHVpZ2kiCmBgYAoKKk5vdGU6IHlvdSdsbCBub3RpY2UgdGhhdCB3aGVuIHdlIGFyZSBhc2tpbmcgUiBpZiB0aGluZ3MgYXJlIGVxdWl2ZWxhbnQgdG8gb25lIGFub3RoZXIsIHdlIHVzZSBhIGRvdWJsZSA9PSBzaWduLiBUaGlzIGlzIGJlY2F1c2UgYSBzaW5nbGUgPSBzaWduIGlzIHVzZWQgaW4gUiB0byBhc2lnbiBzb21ldGhpbmcgdG8gYSB2YXJpYWJsZSBuYW1lLiBJJ2xsIGV4cGxhaW4gbW9yZSBhYm91dCB0aGF0IGluIGEgbWludXRlISoKClJpZ2h0LCB0aW1lIHRvIHN0YXJ0IGJ1aWxkaW5nIHVwIHRvIHVzaW5nIFIgcHJhY3RpY2FsbHkuCgojIyMgQXNzaWduaW5nIG9iamVjdHMKClNvLCBpdCdzIHVzZWZ1bCB0byBrbm93IGhvdyB0byBtYWtlIGEgdmFyaWFibGUgaW4geW91ciBSIGVudmlyb25tZW50LiBZb3UgbWF5IGFscmVhZHkga25vdyB0aGlzIGZyb20geW91ciBhZHZlbnR1cmVzIHdpdGggUHl0aG9uLiBJbiBQeXRob24sIHlvdSB1c2UgYW4gPSB0byBhc3NpZ24gYSB2YXJpYWJsZS4gV2hpbHN0IHlvdSBjYW4gZG8gdGhpcyBpbiBSLCBpdCdzIGJlc3QgcHJhY3RpY2UgdG8gdXNlIHRoZSBgYGA8LWBgYCBvcGVyYXRvciBpbnN0ZWFkLiBOb3RlIHRoaXMgY3JlYXRlcyBhbiAqb2JqZWN0KiBpbiBSLCAqKm5vdCoqIGEgKnZhcmlhYmxlKi4gVGhpcyBpcyBiZWNhdXNlIG9mIHRoZSBzdGF0aXN0aWNhbCBuYXR1cmUgb2YgUiAtIGluIHN0YXRpc3RpY3MsIGEgdmFyaWFibGUgbWVhbnMgc29tZXRoaW5nIGVudGlyZWx5IGRpZmZlcmVudC4gSSB1c2UgPC0gYmVjYXVzZSBpdCBpcyBob3cgSSB3YXMgdGF1Z2h0IHRvIHVzZSBSLCBidXQgaXQncyBva2F5IHRvIHVzZSA9IGlmIHlvdSdkIHByZWZlci4gSXQgZG9lcyBnZXQgY29tcGxpY2F0ZWQgYmVjYXVzZSBvZiB0aGUgPT0gZnVuY3Rpb24sIHNvIEkgbGlrZSB0byB1c2UgPC0gaW5zdGVhZC4gU29tZSBwcm9ncmFtbWVycyBnZXQgYSBiaXQgcGlja3kgYW5kIGp1ZGd5IGlmIHlvdSB1c2UgYSBkaWZmZXJlbnQgd2F5IHRvIHRoZW0sIGJ1dCBteSBwaGlsb3NvcGh5IHdpdGggUiBpcyBpZiBpdCB3b3JrcywgaXQgd29ya3MuCgpTbywgd2h5IGFzaWduPyBJdCBzYXZlcyB0aW1lIGFuZCBtYWtlcyB5b3VyIHNjcmlwdGluZyBlYXNpZXIhIFRoZXJlIGFyZSBzb21lIHJ1bGVzLCBob3dldmVyLiBBc3NpZ25tZW50IGlzIGNhc2Ugc2Vuc2l0aXZlLCBzbyBkb24ndCB0eXBlIHNvbWV0aGluZyB3aXRoIGxvYWRzIG9mIHZhcnlpbmcgY2FzZXMuIFlvdXIgb2JqZWN0IG5hbWUgYWxzbyBjYW4ndCBzdGFydCB3aXRoIGEgbnVtYmVyLCBhbmQgc29tZSB3b3JkcyB0aGF0IGFyZSBhc3NvY2lhdGVkIHdpdGggY29tbW9uIGZ1bmN0aW9ucyBsaWtlIGBgYGlmYGBgIG9yIGBgYGVsc2VgYGAgYXJlIG5vdCBhbGxvd2VkIGFuZCB3aWxsIGJyaW5nIHVwIGFuIGVycm9yIG1lc3NhZ2UuIFRyeSB0aGUgZm9sbG93aW5nIGFuZCB0YWtlIG5vdGUgb2YgdGhlIGVycm9yIG1lc3NhZ2VzIHlvdSBzZWU6CmBgYHtyfQpteV9udW1iZXIgPC0gMTUwMzAyCgpteV9udW1iZXIyID0gMjA0MjExCgpteV90ZXh0IDwtIOKAnEhlbGxvIHdvcmxk4oCdCgoxbXlfdGV4dCA8LSAiSGVsbG8gd29ybGQiCgpmb3IgPC0gIkhlbGxvIHdvcmxkIgpgYGAKCkFsc28sIGl0IGlzIGltcG9ydGFudCB0byBtYWtlIHN1cmUgeW91IGRvbid0IG5hbWUgYW4gb2JqZWN0IHRoZSBzYW1lIGFzIGEgdmFyaWFibGUgaW4geW91ciBkYXRhIHN0cnVjdHVyZSwgb3IgeW91J2xsIHJ1biBpbnRvIHNvbWUgdHJvdWJsZSEhCgojIEEgbm90ZSBvbiBzY3JpcHRpbmc6CgpTY3JpcHRzIGFyZSBlc3NlbnRpYWxseSBhIHJlY29yZCBvZiB3aGF0IHlvdSd2ZSBkb25lIC0gbGlrZSBhIGxpdmUgZG9jdW1lbnQgeW91IGNhbiBlZGl0IGFuZCBhZGQgdG8gYXMgeW91IGdvLiBXaGVuIEkgc2NyaXB0LCBpdCdzIGFsbW9zdCBsaXRlcmFsbHkgYSBzdHJlYW0gb2YgY29uc2Npb3VzbmVzcywgd2hpY2ggaW5jbHVkZXMgYml0cyBvZiBjb2RlIHRoYXQgZG9uJ3Qgd29yayBzbyBJIGRvbid0IG1ha2UgdGhlIHNhbWUgZXJyb3IgYWdhaW4uIFlvdSBzaG91bGQgbGVhdmUgY29tbWVudHMgdG8gcmVtaW5kIHlvdXJzZWxmIG9mIHdoYXQgeW91J3JlIGRvaW5nLCBiZWNhdXNlIGV2ZW4gaWYgeW91IHRoaW5rIHlvdSdsbCByZW1lbWJlciwgSSBwcm9taXNlIGlmIHlvdSBjb21lIGJhY2sgdG8gaXQgaW4gc2l4IG1vbnRocywgeW91J2xsIGJlIGxvc3QhIFlvdSBkZW5vdGUgYSBjb21tZW50IGJ5IHN0YXJ0aW5nIGEgbGluZSB3aXRoIGEgYGBgI2BgYC4gUiB3aWxsIGlnbm9yZSB0aGVzZSBsaW5lcyAodGhleSB3aWxsIGJlIGdyZXllZCBvdXQgaW4gUlN0dWRpbyksIHNvIGFkZCBhcyBtYW55IGFzIHlvdSBsaWtlIQoKV2hlbiB5b3UncmUgdGhpbmtpbmcgYWJvdXQgbm90IHVzaW5nIGNvbW1lbnRzLCByZW1lbWJlciB0aGUgVm95cmljaCBtYW51c2NyaXB0LiBJdCB3YXMgd3JpdHRlbiBpbiBnaWJiZXJpc2gsIGFuZCBub2JvZHkga25vd3Mgd2hhdCBpdCBtZWFucyBiZWNhdXNlIHRoZXJlIGlzIG5vIHdheSBvZiB0cmFuc2xhdGluZyBpdCwgYW5kIG5vIHdheSB0byB3b3JrIG91dCB3aGF0IHRoZSBhdXRob3Igd2FzIHRoaW5raW5nLiBJIGdvIHN1cGVyIG92ZXItYm9hcmQgd2l0aCBjb21tZW50cyB0byBteXNlbGYsIHBhcnRpY3VsYXJseSB3aGVuIEknbSBzaGFyaW5nIHNjcmlwdHMgd2l0aCBvdGhlcnMuCgojIERhdGEgc3RydWN0dXJlcwoKUmlnaHQsIGxldHMgZ2V0IHRvIHRoZSByZWFsIG1lYXQuIERhdGEgc3RydWN0dXJlcy4gVGhlcmUgYXJlIDQgbWFpbiBkYXRhIHN0cnVjdHVyZXMgdGhhdCB3ZSdsbCBjb3ZlciBoZXJlICh3ZWxsLCAzLjUgYmVjYXVzZSB3ZSdsbCBjb3ZlciBsaXN0cyBwcm9wZXJseSBhbm90aGVyIHRpbWUpIC0gVmVjdG9ycywgTWF0cmljaWVzLCBhbmQgRGF0YWZyYW1lcy4KCiMjIFZldG9ycwoKV2UnbGwgc3RhcnQgd2l0aCB2ZWN0b3JzLiBXZSd2ZSBhbHJlYWR5IGNvbnNpZGVyZWQgYWxsIHRocmVlIG1haW4gY2xhc3NlcyBvZiBkYXRhIGFib3ZlLCBudW1lcmljLCBjaGFyYWN0ZXIsIGFuZCBsb2dpY2FsLiBXZSB1c2UgdGhlc2UgYW5kIG90aGVycyB0byBidWlsZCB1cCBvdXIgZGF0YSBzdHJ1Y3R1cmVzIGluIFIuCgpBIHZlY3RvciBpcyBqdXN0IGEgMS1kaW1lbnNpb25hbCBzZXJpZXMgb2YgdmFsdWVzIC0gdGhlIGxlbmd0aCBvZiB0aGUgdmVjdG9yIGlzIGl0cyBvbmx5IGRpbWVuc2lvbi4gVGhpcyBpcyB0aGUgbW9zdCBiYXNpYyBkYXRhIHN0cnVjdHVyZSB5b3UnbGwgZmluZCBpbiBSLCBhbmQgdGhlIGZ1bmRlbWVudGFscyBvZiBhY2Nlc3NpbmcgaXRzIGNvbnRlbnRzIGFyZSBkaWZmZXJlbnQgdG8gUHl0aG9uLiBTbywgd2UnbGwgc3RhcnQgYnkgY3JlYXRpbmcgYSBzZXJpZXMgb2YgdmVjdG9ycywgc3RhcnRpbmcgd2l0aCBhIG51bWVyaWMgdmVjdG9yOgoqTm90ZTogYygpIGlzIGEgdXNlZnVsIGZ1bmN0aW9uIGhlcmUsIGl0J3Mgc2hvcnQgZm9yIGNvbmNhdCBvciBjb21iaW5lLCB3ZSdsbCB0YWxrIG1vcmUgYWJvdXQgZnVuY3Rpb25zIGxhdGVyISoKCmBgYHtyfQp4IDwtIGMoMSwgMiwgMywgNCwgNSkKCnkgPC0gMTo1Cgp6IDwtIHNlcShmcm9tID0gMSwgdG8gPSA1LCBieSA9IDEpIAoKYGBgCkFsbCBvZiB0aGVzZSBleGFtcGxlcyB3aWxsIGdpdmUgeW91IGEgbnVtYmVyIHZlY3RvciB0aGF0IHJhbmdlcyBmcm9tIDEtNS4gVGhlIGZpcnN0IGNvbWJpbmVzIGFsbCBsaXN0ZWQgbnVtYmVycywgdGhlIHNlY29uZCBjcmVhdGVzIGEgc2VyaWVzIG9mIG51bWJlcnMgZnJvbSAxOjUgKHRoZSBgYGA6YGBgIGVzc2VudGlhbGx5IG1lYW5zIGZyb20gMSB0byA1KSwgYW5kIHRoZSB0aGlyZCBjcmVhdGVzIGEgc2VxdWVuY2UgZnJvbSAxIHRvIDUsIGdvaW5nIHVwIGluIDFzLgoKV2UgY2FuIGFsc28gY3JlYXRlIGNoYXJhY3RlciB2ZWN0b3JzLiBMYXRlciwgd2Ugd2lsbCBkaXNjdXNzIGhvdyB5b3UgYWNjZXNzIGFuIGluZGl2aWR1YWwgY29tcG9uZW50IG9mIGVhY2ggb2YgdGhlc2UgdmVjdG9ycywgYnV0IGZvciBub3csIGxldCdzIGJ1aWxkIHNvbWUgY2hhcmFjdGVyIHZlY3RvcnMgKHVzaW5nIG15IGZhdm91cml0ZSBuaW50ZW5kbyBleGFtcGxlcyEpLiBOb3RlIHRoYXQgeW91IGNhbiBvbmx5IGNyZWF0ZSBhIGNoYXJhY3RlciB2ZWN0b3Igd2l0aCB0aGUgYGBgYygpYGBgIGZ1bmN0aW9uLiBXaXRob3V0IHRoaXMsIFIgaXMgb25seSBleHBlY3RpbmcgYSBzaW5nbGUgdmFsdWUgaW4geW91ciBhc3NpZ25tZW50IGFuZCB3aWxsIHRocm93IGFuIGVycm9yIHVwLiBMZXQncyB0cnk6CgpgYGB7cn0KYSA8LSBjKOKAnE1hcmlv4oCdLCDigJxMdWlnaeKAnSwg4oCcUGVhY2jigJ0pCgpiIDwtIGMo4oCcTGlua+KAnSwg4oCcWmVsZGHigJ0sIOKAnEdhbm5vbuKAnQoKYGBgCgpXZSBjYW4gYWxzbyBjcmVhdGUgYSB2ZWN0b3Igb2YgbG9naWNhbCB2YWx1ZXMuICoqUmVtZW1iZXIgdGhhdCBUUlVFIGFuZCBGQUxTRSBoYXZlIHRvIGJlIGluIGNhcHMgZm9yIFIgdG8gaW50ZXJwcmV0IHRoZW0gYXMgbG9naWNhbHMqKi4gSGVyZSwgd2UnbGwgY3JlYXRlIGEgbG9naWNhbCB2ZWN0b3IgdXNpbmcgbG9nY2FsIHZhbHVlcywgYW5kIHRoZW4gb25lIGZyb20gY2hhcmFjdGVyIHZlY3RvcnMgd2l0aCBgYGA9PWBgYDoKCmBgYHtyfQplIDwtIGMoVFJVRSwgRkFMU0UsIFRSVUUpCgpmIDwtIGEgPT0gYgpgYGAKCiMjIyBWZWN0b3IgcHJvcGVydGllcwoKSXQncyB0aW1lIHRvIGhhdmUgYSBsb29rIGF0IHRoZSBwcm9wZXJ0aWVzIG9mIGEgdmVjdG9yIC0gbGF0ZXIgd2UnbGwgbW92ZSBvbiB0byBzdGlja2luZyB2ZWN0b3JzIHRvZ2V0aGVyIHRvIG1ha2UgbmV3IGRhdGEgc3RydWN0dXJlcywgYnV0IGZvciBub3csIHdlJ2xsIGhhdmUgYSBsb29rIGF0IHZlY3RvcnMgYXMgc3RhbmQgYWxvbmUgb2JqZWN0cy4gV2UgY2FuIGRvIG1hdGhlbWF0aWNhbCBvcGVyYXRpb25zIG9uIGVudGlyZSBudW1lcmljIHZlY3RvcnMgLSB3ZSBjYW4gYXBwbHkgYSBzaW5nbGUgb3BlcmF0aW9uIHRvIGFsbCB2YWx1ZXMgaW4gYSB2ZWN0b3IsIG9yIHdlIGNhbiBwZXJmb3JtIG9wZXJhdGlvbnMgb24gdHdvIGRpZmZlcmVudCB2ZWN0b3JzOgoKYGBge3J9CnggPC0gMToxMAp4ICsgNQp4IOKAkyA1Cgp5IDwtIDExOjIwCnggKyB5CnggKiB5CgpgYGAKClZlY3RvciBvcGVyYXRpb25zIHN1Y2ggYXMgdGhvc2UgYWJvdmUgYXJlIGEgdmVyeSBpbXBvcnRhbnQgYW5kIHBvd2VyZnVsIHRvb2wgaW4gUiBmb3IgcmFwaWQgY2FsY3VsYXRpb25zIGFjcm9zcyBsYXJnZSBzZXRzIG9mIG51bWJlcnMuCgpEYXRhIHN0cnVjdHVyZXMgaW4gUiBoYXZlIHByb3BlcnRpZXMgLSB0aGUgbWFpbiBwcm9wZXJ0eSBvZiBhIHZlY3RvciBpcyBpdHMgbGVuZ3RoLiBPbmNlIHlvdSBrbm93IHNvbWV0aGluZyBhYm91dCB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yLCB5b3UgY2FuIG1vcmUgZWFzaWx5IGFjY2VzcyB0aGUgc3R1ZmYgaW5zaWRlIG9mIGl0LiBZb3UgZmluZCB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yIHVzaW5nIGBgYGxlbmd0aCh4KWBgYC4gCgpZb3Ugd2lsbCBnZXQgd2FybmluZ3MgdG8gZG8gd2l0aCB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yIGluIHZhcmlvdXMgY2lyY3Vtc3RhbmNlcywgZm9yIGUuZy4gaWYgdHdvIHZlY3RvciBsZW5ndGhzIGFyZSBub3QgbXVsdGlwbGVzIG9mIG9uZSBhbm90aGVyIGluIHNvbWUgbWF0aGVtYXRpY2FsIGNhbGN1bGF0aW9ucy4gVHJ5IHRoZSBmb2xsb3dpbmc6CgpgYGB7cn0KeCA8LSAxOjEwCmxlbmd0aCh4KQoKeSA8LSAxOjUKeCArIHkKeCAqIHkKCnogPC0gMTozCnkgKiB6IAoKYGBgCkhlcmUsIHlvdSdsbCBub3RpY2UgdGhhdCB0aGUgb3BlcmF0aW9uIGNhdXNlcyB0aGUgc2hvcnRlciB2ZWN0b3IgKHopIHRvIGJlIGxvb3BlZCBhY3Jvc3MgdW50aWwgaXQgZml0cyB0aGUgbG9uZ2VyLiBTbywgeW91ciByZXN1bHQgZnJvbSBgYGB5ICogemBgYCBpcyBhY3R1YWxseToKCi0gMSAqIDEsIAotIDIgKiAyLAotIDMgKiAzLCAKLSA0ICogMSwgYW5kIAotIDUgKiAyCgpSIHdpbGwgc3RpbGwgcGVyZm9ybSB0aGVzZSBvcGVyYXRpb25zLCBidXQgaXQgd2lsbCB3YXJuIHlvdSB0aGF0IHZlY3RvciBsZW5ndGhzIGFyZSBub3QgbXVsdGlwbGVzIG9mIG9uZSBhbm90aGVyLgoKU28sIGhvdyBkbyB3ZSBpbnRlcmFjdCB3aXRoIHZlY3RvcnMgYW5kIHN0YXJ0IHRvIHB1bGwgaXRlbXMgZnJvbSB0aGVtPyBWZWN0b3JzIGFyZSBncmVhdCwgYnV0IHRoZXkncmUgbm90IG92ZXJseSB1c2VmdWwgdW5sZXNzIHdlIGNhbiBnZXQgYXQgdGhlIHN0dWZmIGluc2lkZSBvZiB0aGVtLiBXZSdsbCBjcmVhdGUgYW5vdGhlciBjaGFyYWN0ZXIgdmVjdG9yLCBgYGB4YGBgLgoKYGBge3J9CnggPC0gYygiZG9nIiwgImNhdCIsICJtb3VzZSIpCnhbXSAjIFRoaXMgd2lsbCBwcmludCBhbGwgdmVjdG9yIHZhbHVlcwp4WzFdICMgVGhpcyB3aWxsIHByaW50IHRoZSBmaXJzdCB2YWx1ZSAtIG5vdGUgdGhhdCBSIGlzIGluZGV4ZWQgZnJvbSAxIHVubGlrZSBQeXRob24hIQp4W2MoMSwgMyldICMgVGhpcyBnaXZlcyB5b3UgdGhlIGZpcnN0IGFuZCB0aGlyZCB2YWx1ZXMgLSBub3RlIHRoZSB1c2Ugb2YgYygpCnhbMjozXSAjIHRoaXMgZ2l2ZXMgeW91IHZhbHVlcyAyIHRocm91Z2ggdG8gMy4KCmBgYAoKU28sIG5vdyB3ZSBjYW4gcHVsbCBvdXQgd2hhdGV2ZXIgdmFsdWVzIHdlIHdhbnQsIHdlIGNhbiB1c2UgdGhpcyB0byBtYW5pcHVsYXRlIHRoZSBjb250ZW50cyBvZiBvdXIgdmVjdG9yISBJZiB3ZSB3YW50ZWQgdG8sIGZvciBleGFtcGxlLCByZXBsYWNlIHRoZSBtb3VzZSB3aXRoIGFuIGVsZXBoYW50LCB3ZSdkIHVzZSB0aGUgZm9sbG93aW5nOgoKYGBge3J9CnhbM10gIyBUaGlzIHByaW50cyAibW91c2UiCnhbM10gPC0gImVsZXBoYW50IiAjIFRoaXMgYXNzaWducyB0aGUgc3RyaW5nICJlbGVwaGFudCIgdG8gdGhlIHRoaXJkIGluZGV4IG9mIHRoZSB2ZWN0b3IsIHJlcGxhY2luZyAibW91c2UiLgp4CmBgYApOb3csIHdoYXQgaWYgd2Ugd2FudCB0byByZW1vdmUgbnVtYmVyIDMgYWxsIHRvZ2V0aGVyPyBXZSBjYW4gZG8gdGhpcyBieSBhc3NpZ25pbiBpdCBhbiBgYGBOQWBgYCB2YWx1ZSwgd2hpY2ggaW5kaWNhdGVzIHRvIFIgdGhhdCB0aGVyZSBpcyBubyB2YWx1ZSBwcmVzZW50IGF0IHRoaXMgbG9jYXRpb246CgpgYGB7cn0KeFszXSA8LSBOQQpgYGAKIyMjIEEgbm90ZSBvbiBOQToKCmBgYE5BYGBgIGlzIGEgcGxhY2Vob2xkZXIgaW4gUiwgZm9yIHdoZW4gZGF0YSBpcyAiTm90IEF2YWlsYWJsZSIsIGFuZCBpdCB1c3VhbGx5IGRlbm90ZXMgbWlzc2luZyBkYXRhLiBGb3IgZXhhbXBsZSwgeW91IG1pZ2h0IGJlIGNvbGxlY3RpbmcgYmxvb2Qgc2FtcGxlcyBmcm9tIHBhdGllbnRzIGluIGEgbG9uZ2l0dWRpbmFsIHRyaWFsLCBhbmQgYSBwYXRpZW50IGlzIHVuYWJsZSB0byBwcm92aWRlIGEgc2FtcGxlIGF0IHBvaW50IDMgb2YgNSwgc28gaGVyZSwgeW91ciB2YWx1ZSBmb3Igd2hhdGV2ZXIgeW91J3JlIG1lYXN1cmluZyBpbiB0aGUgYmxvb2Qgd291bGQgYmUgYGBgTkFgYGAuIE90aGVyIGNvbW1vbmx5IGVuY291bnRlcmVkIG1pc3NpbmcgdmFsdWUgcGxhY2Vob2xkZXJzIGluIFIgYXJlIGBgYE5hTmBgYCAoTm90IEEgTnVtYmVyKSBhbmQgYGBgSW5mYGBgIChJbmZpbml0eSkuCgoKIyBGdW5jdGlvbnMKCldlJ2xsIHRha2UgYSBicmllZiBpbnRlcmx1ZGUgZnJvbSBkYXRhIHN0cnVjdHVyZXMgZm9yIGEgYnJpZWYgd29yZCBhYm91dCBmdW5jdGlvbnMgbm93LiBGdW5jdGlvbnMgYXJlIHRoZSBicmVhZCBhbmQgYnV0dGVyIG9mIFIuIFRoZXkgYXJlIGNvZGUgdGhhdCB0YWtlcyBhbiBpbnB1dCwgcHJvY2Vzc2VzIGl0LCBhbmQgcmV0dXJucyBhIHJlc3VsdCBpbiB0aGUgZm9ybSBvZiBhbiBvdXRwdXQuIFdlIGhhdmUgYWxyZWFkeSB1c2VkIHNvbWUgZnVuY3Rpb25zIGFib3ZlLCBzdWNoIGFzIGBgYGxlbmd0aCgpYGBgIGFuZCBgYGBzZXEoKWBgYC4gVGhlcmUgYXJlIHRob3VzYW5kcyBvZiBmdW5jdGlvbnMgYXZhaWxhYmxlIHRvIHlvdSBpbiBSLCBmcm9tIHRoZSB2ZXJ5IGJhc2ljIHRvIHRoZSBleHRyZW1lbHkgY29tcGxpY2F0ZWQgYW5kIGludm9sdmVkLiBZb3UgY2FuIChhbmQgeW91IHdpbGwhKSB3cml0ZSB5b3VyIG93biBmdW5jdGlvbnMsIG11Y2ggbGlrZSB5b3UgY2FuIGluIFB5dGhvbiwgYWx0aG91Z2ggdGhlIHN5bnRheCBpcyBkaWZmZXJlbnQuIFByZS1idWlsdCBmdW5jdGlvbnMgb2Z0ZW4gY29tZSB3aXRoIGhlbHAgZmlsZXMsIHRyeSB0aGUgZm9sbG93aW5nOgoKYGBge3J9CnkgPC0gMToxMApsZW5ndGgoeSkKP2xlbmd0aApgYGAKVXNlIGBgYD9mdW5jdGlvbmBgYCBvciBgYGBoZWxwKCJmdW5jdGlvbiIpYGBgIHRvIGFjY2VzcyBoZWxwLiBUaGUgaGVscCBmaWxlcyBnZW5lcmFsbHkgY29udGFpbiBhIGRlc2NyaXB0aW9uIG9mIHRoZSBmdW5jdGlvbiBhbmQgZGV0YWlscyBvZiBhbGwgdGhlIGFyZ3VtZW50cyB3aGljaCBtYXkgYmUgc3VwcGxpZWQgdG8gaXQuIFRoZXNlIGhlbHAgZmlsZXMgZG8gdGFrZSBzb21lIGdldHRpbmcgdXNlZCB0bywgYXMgdHJ1ZSB0byBSJ3Mgc3R5bGUsIHRoZXkgY2FuIGJlIHF1aXRlIHRyaWNreSB0byBpbnRlcnByZXQhCgojIyBUaGUgYW5hdG9teSBvZiBhIGZ1bmN0aW9uCgpUcnkgcnVubmluZyB0aGUgZm9sbG93aW5nIGNvZGU6CgpgYGB7cn0KeSA8LSAxOjEwCnN1bSh5KQp5WzVdIDwtIE5BICMgUmVwbGFjZSB0aGUgNXRoIGluZGV4IHdpdGggTkEKc3VtKHkpCmBgYAoKCllvdSdsbCBub3RpY2UgdGhhdCBpZiBhIHZlY3RvciBjb250YWlucyBgYGBOQWBgYCwgZnVuY3Rpb25zIHN1Y2ggYXMgYGBgc3VtKClgYGAgd2lsbCByZXR1cm4gYGBgTkFgYGAuIFNvbWV0aGluZyBoYXNuJ3QgcXVpdGUgd29ya2VkIGhlcmUsIHNvIHdlIG5lZWQgdG8gYWRkIGFuIGFkZGl0aW9uYWwgYXJndW1lbnQgdG8gb3VyIGZ1bmN0aW9uIHRvIGRlYWwgd2l0aCB0aG9zZSBwZXNreSBgYGBOQWBgYHMuLi4KCmBgYHtyfQpzdW0oeSwgbmEucm0gPSBUUlVFKQpgYGAKCkhlcmUsIHRoZSBgYGBuYS5ybWBgYCBhcmd1bWVudCBpcyBzZXQgdG8gYGBgVFJVRWBgYCwgc28gdGhhdCBgYGBOQWBgYCBpcyBpZ25vcmVkIChvciwgbW9yZSBhY2N1cmF0ZWx5LCByZW1vdmVkKS4gTm90ZSB0aGF0IHRoZSBhc3NpZ25tZW50IG9mIHRoaW5ncyAqaW5zaWRlKiBvZiBhIGZ1bmN0aW9uIGlzIGFsd2F5cyBkb25lIHdpdGggYGBgPWBgYCBhbmQgbm90IGBgYDwtYGBgLiAKCiMgUGxvdHRpbmcgYW5kIHZpc3VhbGlzYXRpb24KCk5vdyBpcyBhIGdvb2QgdGltZSB0byBzdGFydCB0aGlua2luZyBhYm91dCB3aGF0IHdlIGNhbiBhY3R1YWxseSBnZXQgb3V0IG9mIHdoYXQgd2UndmUgbGVhcm5lZCBzbyBmYXIsIHNvIHdlJ2xsIHVzZSBScyBpbnRlZ3JhdGVkIHBsb3R0aW5nIHNvZnR3YXJlIHRvIGNyZWF0ZSBzb21lIG5pY2UgcGxvdHMhIFlvdSBjYW4gaGF2ZSBhIGxvb2sgYXQgd2hhdCBSIGhhcyB0byBvZmZlciB1c2luZyB0aGUgbm93IHNsaWdodGx5IG91dGRhdGVkIGBgYGRlbW8oZ3JhcGhpY3MpYGBgIGNvbW1hbmQuIFRyeSB0YWtpbmcgYSB0b3VyIHRocm91Z2ggdGhlIGdyYXBoIHR5cGVzLgoKTGV0J3MgdXNlIHRoZSBza2lsbHMgd2UndmUgbGVhcm5lZCBzbyBmYXIgdG8gbWFrZSBhIHBsb3QhCmBgYHtyfQp4IDwtIDE6MTAwCnkgPC0geF4yCnBsb3QoeCwgeSkKYGBgCgpOaWNlISBZb3Ugc2hvdWxkIGhhdmUgcHJvZHVjZWQgYSBzY2F0dGVyIHBsb3QuIFdoYXQgaWYgd2Ugd2FudCB0byB0dXJuIHRoYXQgaW50byBhIGxpbmUgcGxvdD8KCmBgYHtyfQpwbG90KHgsIHksIHR5cGUgPSAibCIpCmBgYAoKRmFidWxvdXMuIFRoZSB3YXlzIHRvIGN1c3RvbWlzZSBncmFwaGljcyBpbiBSIGFyZSBhbG1vc3QgZW5kbGVzcyAtIHdlJ2xsIGhhdmUgYSBjbG9zZXIgbG9vayBsYXRlciBvbiEgRm9yIG5vdyB0aG91Z2gsIHdlJ2xsIGdldCBiYWNrIHRvIG91ciBkYXRhIHN0cnVjdHVyZXMuCgojIFJldHVybmluZyB0byBkYXRhIHN0cnVjdHVyZXMKCiMjIE1hdHJpY2llcwoKVGhlIHNlY29uZCB0eXBlIG9mIGRhdGEgc3RydWN0dXJlIHdlJ2xsIGxvb2sgYXQgaXMgdGhlIGh1bWJsZSBtYXRyaXguIFRoZXNlIGRhdGEgc3RydWN0dXJlcyBzdG9yZSBkYXRhIGluIHJvd3MgYW5kIGNvbHVtbnMgKGkuZS4gbGlrZSBhIHRhYmxlISkuIFRoZXkgYXJlIHZlcnkgc2ltaWxhciB0byB2ZWN0b3JzLCBvbmx5IHRoZXkgYXJlIHR3by1kaW1lbnNpb25hbC4gSW4gZmFjdCwgd2UgY2FuIGJ1aWxkIG91ciBmaXJzdCBtYXRyaXggZnJvbSBzb21lIHZlY3RvcnMgdXNpbmcgdGhlIGBgYGNiaW5kKClgYGAgYW5kIGBgYHJiaW5kKClgYGAgZnVuY3Rpb25zOgoKYGBge3J9CnggPC0gMTo0CnkgPC0gMjE6MjQKeiA8LSBjYmluZCh4LCB5KQp6CmBgYAoKYGBgY2JpbmQoKWBgYCBiaW5kcyB2ZWN0b3JzIHRvZ3RoZXIgYnkgY29sdW1uLCB3aGVyZWFzIGBgYHJiaW5kKClgYGAgZG9lcyBpdCBieSByb3csIGVmZmVjdGl2ZWx5IGZsaXBwaW5nIG91ciB0YWJsZS4gVHJ5IHJ1bm5pbmcgYGBgejEgPC0gcmJpbmQoeCwgeSlgYGAgYW5kIGxvb2tpbmcgYXQgdGhlIG91dHB1dC4KClRoZXJlIGlzIGEgc2ltcGxlIHdheSB0byBkZXRlcm1pbmUgd2hldGhlciB5b3VyIGRhdGEgc3RydWN0dXJlIGlzIGEgbWF0cml4LCB3aGljaCBpcyBieSBydW5uaW5nIHRoZSBgYGBpcy5tYXRyaXgoeilgYGAgY29tbWFuZC4gVHJ5IGl0ISBJdCBzaG91bGQgZ2l2ZSBhIGxvZ2ljYWwgb3V0cHV0IG9mIFRSVUUgb3IgRkFMU0UuIFlvdSBjYW4gYWxzbyBhY2Nlc3MgdGhlIGRpbWVuc2lvbnMgb2YgYSBtYXRyaXggaW4gYSBzaW1pbGFyIHdheSB0byBhIHZlY3RvciAoYWx0aG91Z2ggc2xpZ2h0bHkgZGlmZmVyZW50KS4gYGBgZGltKHopYGBgIHRlbGxzIHlvdSB0aGUgZGltZW5zaW9ucyBvdmVyYWxsLCBgYGBucm93KClgYGAgdGVsbHMgeW91IHRoZSBudW1iZXIgb2Ygcm93cywgYW5kIHVuc3VycHJpc2luZ2x5LCBgYGBuY29sKClgYGAgZ2l2ZXMgeW91IGluZm9ybWF0aW9uIGFib3V0IHRoZSBudW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgbWF0cml4LiBUcnkgaXQgd2l0aCBvdXIgbWF0cml4IGBgYHpgYGAuCgoqKkFuIGltcG9ydGFudCBjb25zaWRlcmF0aW9uIHdpdGggbWF0cmljaWVzIGlzIHRoYXQgd2UgcmVmZXIgdG8gdGhlbSBieSB0aGUgcm93IGluZGV4LCBhbmQgdGhlbiB0aGUgY29sdW1uKiouIFRoaXMgaXMgc29tZXRoaW5nIHRoYXQgaXMgdmVyeSBlYXN5IHRvIGZvcmdldCwgYW5kIEkgb2Z0ZW4gaGF2ZSB0byBsb29rIGl0IHVwLCBzbyBkb24ndCB3b3JyeSBpZiB5b3UgY2FuJ3QgcmVtZW1iZXIuIE1hdHJpY2llcyBhcmUgYWxzbyBvbmx5IGNhcGFibGUgb2Ygc3RvcmluZyAxIHR5cGUgb2YgZGF0YSwgZWl0aGVyIGxvZ2ljYWwsIGNoYXJhY3Rlciwgb3IgbnVtZXJpYy4gSWYgeW91ciBkYXRhIGlzIG1peGVkIGluIHR5cGUsIHlvdSdsbCBuZWVkIGEgZGF0YWZyYW1lIHJhdGhlciB0aGFuIGEgbWF0cml4LCBidXQgd2UnbGwgZ2V0IHRvIHRoYXQgc29vbi4gTGV0J3Mgc2VlIHdoYXQgaGFwcGVucyBpZiB3ZSB0cnkgYW5kIHN0b3JlIG11bHRpcGxlIGRhdGEgdHlwZXM6CgpgYGB7cn0KeCA8LSBjKOKAnE1hcmlv4oCdLCDigJxMdWlnaeKAnSwg4oCcUGVhY2jigJ0pCnkgPC0gYyjigJxUb2Fk4oCdLCDigJxCb3dzZXLigJ0sIOKAnFdhcmlv4oCdKQp6IDwtIGMoMSwgMiwgMykKbSA8LSBjYmluZCh4LCB5LCB6KQoKYGBgCkhlcmUgeW91IGNhbiBzZWUgdGhhdCB0aGUgbnVtYmVycyBpbiBgYGB6YGBgIGFyZSB0cmFuc2Zvcm1lZCBpbnRvIGNoYXJhY3RlcnMhCgpBbnl3YXksIGhvdyBkbyB3ZSBleHRyYWN0IGFuZCBhY2Nlc3MgaW5mb3JtYXRpb24gc3RvcmVkIGluIGEgbWF0cml4PyEgTGlrZSB3aXRoIHZlY3RvcnMsIHdlIHVzZSBzcXVhcmUgYnJhY2tldHMuIExldCdzIG1ha2UgYSBiaWdnZXIgbWF0cml4IGFuZCBoYXZlIGEgZ28uIE5vdGUgdGhhdCB3ZSBhcmUgdXNpbmcgdGhlIGBgYG1hdHJpeCgpYGBgIGZ1bmN0aW9uIGhlcmUgcmF0aGVyIHRoYW4gYGBgY2luZCgpYGBgLiAKCmBgYHtyfQptIDwtIG1hdHJpeCgxOjEwLCBuY29sID0gMikgIyBuY29sID0gMiB0ZWxscyBSIHRoYXQgd2Ugd2FudCB0aGUgbnVtYmVycyAxLTEwIHNwbGl0IGludG8gMiBjb2x1bW5zCm1bMSwgXSAjIHJldHVybiBmaXJzdCByb3cKbVssIDJdICMgcmV0dXJuIHNlY29uZCBjb2x1bW4KbVsxLDJdICMgcmV0dXJuIHRoZSBpbmZvcm1hdGlvbiBpbiB0aGUgZmlyc3Qgcm93IG9mIHRoZSBzZWNvbmQgY29sdW1uLCBpbiB0aGlzIGV4YW1wbGUsIDYuCmBgYAojIyBEYXRhIGZyYW1lcwoKUmlnaHQsIG9uIHRvIG91ciB0aGlyZCAoYW5kIHByb2JhYmx5IGZpbmFsKSBkYXRhIHN0cnVjdHVyZSAtIGRhdGEgZnJhbWVzLiBNb3N0ICJyZWFsIiBkYXRhIHRoYXQgeW91IGNvbWUgYWNyb3NzIGluIHlvdXIgdHJhdmVscyB3aWxsIGJlIGluIGEgZGF0YWZyYW1lLiBJdCdzIGEgYml0IGxpa2UgYSBtYXRyaXgsIGJ1dCBjYXBhYmxlIG9mIHN0b3JpbmcgbXVsdHVwbGUgZGF0YSBjbGFzc2VzIGluIHRoZSBzYW1lIG9iamVjdC4gTGV0J3MgbWFrZSBvbmUgZnJvbSAzIHZlY3RvcnMgYW5kIGhhdmUgYSBsb29rOgoKYGBge3J9Cm5hbWUgPC0gYyjigJxNYXJpb+KAnSwg4oCcTHVpZ2nigJ0sIOKAnExpbmvigJ0sIOKAnFplbGRh4oCdKQpoZWlnaHQgPC0gYygxNTUsIDE2MCwgMTgwLjMsIDE4MC4zKQphZ2UgPC0gYygyNiwgMjQsIDE3LCAxOSkKCmRmIDwtIGRhdGEuZnJhbWUobmFtZSwgaGVpZ2h0LCBhZ2UpCgpgYGAKTm90ZSB0aGF0IHRoZSBkYXRhZnJhbWUgbXVzdCBoYXZlIG5hbWVkIGNvbHVtbnMhIFlvdSBjYW4gbG9vayBhdCB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgeW91ciBkYXRhIHdpdGggYGBgaGVhZChkZilgYGAsIGFuZCB0YWtlIG5vdGUgb2YgdGhlIHN0cnVjdHVyZSBvZiBpdCB3aXRoIGBgYHN0cihkZilgYGAuIE5vdywgZXZlcnl0aGluZyB5b3UndmUganVzdCBsZWFybmVkIGFib3V0IGFjY2Vzc2luZyBkYXRhIGluc2lkZSBvZiBhIG1hdHJpeCBzdGFuZHMgdHJ1ZSBmb3IgZGF0YWZyYW1lcyBhbHNvIC0gdGhleSB3b3JrIGluIGEgdmVyeSBzaW1pbGFyIGZhc2hpb24gd2l0aCB0aGUgcm93cyBhbmQgY29sdW1ucyBmb3JtYXQuIFRoZXJlIGlzLCBob3dldmVyLCBhbm90aGVyIHdheSB0byBhY2Nlc3MgZGF0YSBmcm9tIHlvdXIgZGF0YWZyYW1lIHRoYXQgSSBmaW5kIG1vcmUgaW50dWl0aXZlIHRoYW4gdXNpbmcgY29sdW1uIGluZGljaWVzLCB3aGljaCBpcyByZWZlcnJpbmcgdG8gdGhlIGNvbHVtbiBieSBpdHMgbmFtZSAoaGVuY2UgdGhlIG5lZWQgZm9yIG5hbWVkIGNvbHVtbnMhKS4gVHJ5IHRoaXM6CgpgYGB7cn0KIyBBY2Nlc3NpbmcgZGF0YSBhcyBpZiBpdCB3ZXJlIGEgbWF0cml4CmRmWywgMV0KZGZbMywgXQpkZls0LCAzXQoKIyBVc2luZyBjb2x1bW4gbmFtZXMgYXMgcmVmZXJlbmNlcwoKZGZb4oCcbmFtZeKAnV0KZGZbLCDigJxuYW1l4oCdXQpkZiRuYW1lCgpgYGAKV2hlbiB5b3UgZXh0cmFjdCBhIGNvbHVtbiBpbiB0aGlzIHdheSwgaXQgYmVjb21lcyBhIHZlY3RvciEgTm90ZSB0aGF0IGluIGBgYGRmJG5hbWVgYGAsIHRoZSBgYGAkYGBgIGVzc2VudGlhbGx5IGp1c3QgbWVhbnMgImxvb2sgaW5zaWRlIiAtIHNvIHlvdSdyZSB0ZWxsaW5nIFIgdG8gbG9vayBpbnNpZGUgYGBgZGZgYGAgdG8gZmluZCB0aGUgYGBgbmFtZXNgYGAgY29sdW1uLiAKCgojIEFjY2Vzc2luZyBleGFtcGxlIGRhdGEKClVzaW5nIHRoZSB0b3kgZGF0YXNldHMgYXMgd2UganVzdCBoYXZlIGlzIGFsbCB3ZWxsIGFuZCBnb29kIHdoZW4geW91J3JlIGxlYXJuaW5nLCBhbmQgaXMgYSBmdW4gd2F5IHRvIGV4cGVyaW1lbnQgYW5kIGZpZ3VyZSBvdXQgaG93IHRoaW5ncyB3b3JrISBCdXQsIHdoYXQgaWYgd2Ugd2FudCB0byBnZXQgaG9sZCBvZiBzb21lIGFjdHVhbCBkYXRhPyBUaGVyZSBhcmUgbG9hZHMgb2YgcHJlLWxvYWRlZCByZWFsIGxpZmUgZGF0YXNldHMgdGhhdCBjb21lIHdpdGggUiwgc28gbGV0J3MgaGF2ZSBhIGxvb2sgYXQgYXJndWFibHkgdGhlIG1vc3QgZmFtb3VzIG9mIHRoZXNlLCB0aGUgaXJpcyBkYXRhc2V0LgoKSWYgd2UgdHlwZSBgYGBkYXRhKClgYGAgaW50byBvdXIgUiBjb25zb2xlL3NjcmlwdCBhbmQgcnVuIGl0LCBSIHdpbGwgbG9hZCB0aGVzZSBkYXRhc2V0cyBmb3IgdXMuIFdlIGNhbiB0aGVuIHVzZSB0aGUgYGBgaGVhZCgpYGBgIGZ1bmN0aW9uIHRvIGxvb2sgYXQgdGhlIGBgYGlyaXNgYGAgZGF0YXNldC4uLgoKYGBge3J9CmRhdGEoKQoKaGVhZChpcmlzKQoKP2lyaXMKYGBgCgpOb3RlIHRoYXQgd2UgY2FuIGdldCBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkYXRhc2V0IGJ5IHJ1bm5pbmcgdGhlIGhlbHAgYGBgP2BgYCBmdW5jdGlvbi4gV2Ugd2lsbCByZXZpc2l0IHRoZXNlIGRhdGFzZXQgaW4gYSBtaW51dGUsIGJ1dCBmaXJzdCwgd2hhdCBpZiB5b3Ugd2FudCB0byBpbXBvcnQgeW91ciBvd24gZGF0YT8hCgpUaGUgZWFzeSB3YXk6IHlvdSBjYW4gdXNlIFJTdHVkaW8gdG8gaW1wb3J0IGRhdGEgdmlhIHRoZSBHVUksIHdoaWNoIGlzIGEgZ29vZCB3YXkgdG8gbGVhcm4gYXQgZmlyc3QsIGJ1dCBpc24ndCBhcyBmbGV4aWJsZSBhcyBsZWFybmluZyBmdW5jdGlvbnMgdG8gcmVhZCBkYXRhLi4uCgohW10oaW1wb3J0LnBuZykKClRoZSAoYXJndWFibHkpIGJldHRlciB3YXkgaXMgdG8gdXNlIHRoZSBgYGByZWFkLmNzdigpYGBgIGZ1bmN0aW9uLiBJIHdpbGwgdXNlIGl0IGhlcmUgdG8gdXBsb2FkIGEgLmNzdiBmaWxlIEkgaGF2ZSBpbiBteSBwcm9qZWN0IGRpcmVjdG9yeSB3aGljaCBjb250YWlucyBkYXRhIGZyb20gTmV0ZmxpeCB0aXRsZXMgb3ZlciB0aGUgeWVhcnMuIFRyeSB3aXRoIHlvdXIgb3duIGRhdGEhCgpgYGB7cn0KbmV0ZmxpeCA8LSByZWFkLmNzdigiLi9uZXRmbGl4X3RpdGxlcy5jc3YiKQpoZWFkKG5ldGZsaXgpCmBgYAoKWW91IG1heSBhbHNvIG5lZWQgdG8gd3JpdGUgZGF0YSBvdXQgb2YgUiwgd2hpY2ggY2FuIGJlIGdvb2QgZm9yIHNhdmluZyB5b3VyIHByb2dyZXNzIG9yIHNhdmluZyBmaWx0ZXJlZCBkYXRhc2V0cy4gSGVyZSwgd2Ugd2lsbCB3cml0ZSBvdXQgYSBmaWxlIG9mIGNvbW1hLXNlcGFyYXRlZCB2YXJpYWJsZXMgKGEgLmNzdiBmaWxlKS4KCmBgYHtyfQpkZiA8LSBkYXRhLmZyYW1lKG5hbWUgPSBjKOKAnE1hcmlv4oCdLCDigJxMdWlnaeKAnSwg4oCcTGlua+KAnSwg4oCcWmVsZGHigJ0pLAoJCSAgICBoZWlnaHQgPSBjKDE1NSwgMTYwLCAxODAuMywgMTgwLjMpLAoJCSAgICBhZ2UgPSBjKDI2LCAyNCwgMTcsIDE5KSkKCndyaXRlLmNzdihkZiwg4oCcLi9uaW50ZW5kby5jc3bigJ0pIAoKYGBgCipOb3RlOiB0aGlzIGlzIHRoZSBuaW50ZW5kbyBkYXRhZnJhbWUgd2UgbWFkZSBlYXJsaWVyLCBzbyB5b3UgbWF5IG5vdCBuZWVkIHRvIHJlbWFrZSBpdCEqCgojIEV4dGVuZGluZyBiZXlvbmQgYmFzZSBSOgoKUGFja2FnZXMsIHdoaWNoIGFyZSBhbmFsYWdvdXMgdG8gbW9kdWxlcyBpbiBQeXRob24sIGFyZSBhIGdyZWF0IHdheSBvZiBleHRlbmRpbmcgeW91ciBSIHVuaXZlcnNlLiBUaGV5IGNhbiBiZSBpbnN0YWxsZWQgaW4gYSBtdWx0aXR1ZGUgb2Ygd2F5cywgYnV0IHBlcmhhcHMgdGhlIG1vc3QgY29tbW9uIGlzIGluc3RhbGxpbmcgdGhlbSBkaXJlY3RseSB0aHJvdWdoIHRoZSBDb21wcmVoZW5zaXZlIFIgTmV0d29yayAtIENSQU4uIFRoZXJlIGFyZSBjdXJyZW50bHkgb3ZlciAxODUwMCBwYWNrYWdlcyBsaXN0ZWQgb24gQ1JBTiwgc28gaXQncyBsaWtlbHkgdGhhdCBpZiB5b3UncmUgdHJ5aW5nIHRvIGRvIHNvbWV0aGluZyBzcGVjaWZpYyBpbiBSLCB0aGVyZSBpcyBhbHJlYWR5IGEgcGFja2FnZSEgT3RoZXIgcmVwb3NpdG9yaWVzIGluY2x1ZGUgR2l0SHViIGFuZCBCaW9Db25kdWN0b3IuCgojIyBJbnN0YWxsaW5nIGFuZCBsb2FkaW5nIFIgcGFja2FnZXM6CgpJbnN0YWxsbmlnIHBhY2thZ2VzIGlzIHVzdWFsbHkgc3RyYWlnaHQgZm9yd2FyZC4uLiBZb3UgYWxzbyBvbmx5IG5lZWQgdG8gZG8gaXQgb25jZSBvbiBlYWNoIGNvbXB1dGVyIHlvdSB1c2UhIFdlIHdpbGwgaW5zdGFsbCBgYGBnZ3Bsb3QyYGBgIG5vdywgYSBwYWNrYWdlIHdlIHdpbGwgdXNlIGxvdHMgaW4gb3RoZXIgc2Vzc2lvbnMuIE9uY2UgaW5zdGFsbGVkLCB5b3UgbXVzdCBsb2FkIHlvdXIgcGFja2FnZSBpbnRvIFIgd2l0aCB0aGUgYGBgbGlicmFyeSgpYGBgIGZ1bmN0aW9uLgoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKIyBCYWNrIHRvIHBsb3RzIQoKVmlzdWFsaXNpbmcgZGF0YSBpcyBhIGZ1bmRlbWVudGFsbHkgaW1wb3J0YW50IHRvb2wgaW4gUiAtIHRoaW5rIG9mIGl0IGFzIGEgd2F5IHRvIHVuZGVyc3RhbmQgYW5kIHByb3Blcmx5IGV4cGxvcmUgeW91ciBkYXRhLiBXZSB3b250IHVzZSBnZ3Bsb3QyIGZvciB0aGlzIGZvciBub3csIGFsdGhvdWdoIHRoaXMgaXMgYSBmYWJ1bG91cyBwbG90dGluZyB0b29sLiBXZSBjYW4gdXNlIFIgdG8gbWFrZSBhIHNpbXBsZSBzY2F0dGVyIHBsb3QsIGFzIHdlIGRpZCBiZWZvcmU6CgpgYGB7cn0KeCA8LSBzZXEoZnJvbSA9IDEsIHRvID0gMTAwLCBieSA9IDUpCnkgPC0geF4yCgpwbG90KHgsIHkpCgpgYGAKIVtdKHBsb3QxLnBuZykKCldlIGNhbiBjdXN0b21pc2UgYWxtb3N0IGFueXRoaW5nIG9uIHRoaXMgcGxvdCwgYW5kIHdlIGFkZCB0byBpdCBpdGVyYXRpdmVseSBhcyB3ZSBnby4gWW91J2xsIHNlZSB3aGF0IEkgbWVhbiBpbiB0aGUgZm9sbG93aW5nIGV4YW1wbGVzLiBGaXJzdCwgd2UnbGwgY2hhbmdlIHRoZSBvcmllbnRhdGlvbiBvZiB0aGUgeSBheGlzIGxhYmVscyB3aXRoIHRoZSBgYGBsYXMgPSAxYGBgIGFyZ3VtZW50IGluIHRoZSBgYGBwbG90KClgYGAgZnVuY3Rpb246CgpgYGB7cn0KcGxvdCh4LCB5LCBsYXMgPSAxKQpgYGAKCiFbXShwbG90Mi5wbmcpCgpXZSBjYW4gY2hhbmdlIHRoZSBjb2xvdXIgb2YgdGhlIHBvaW50cywgYW5kIHRoZW4gYWRkIGEgbGluZToKCmBgYHtyfQpwbG90KHgsIHksIGxhcyA9IDEsIGNvbCA9IOKAnHJlZOKAnSkKbGluZXMoeCx5KQoKYGBgCgohW10ocGxvdDMucG5nKQoKV2UgY2FuIGFkZCBhIHRpdGxlOgoKYGBge3J9CnBsb3QoeCwgeSwgbGFzID0gMSwgY29sID0g4oCccmVk4oCdLAogICAgIG1haW4gPSDigJxyZWxhdGlvbnNoaXAgYmV0d2VlbiB4ICYgeeKAnSkKbGluZXMoeCx5KQoKYGBgCiFbXShwbG90NC5wbmcpCgpUaGUgcG9zc2liaWxpdGllcyBhcmUgZW5kbGVzcyEKClJpZ2h0LCBsZXRzIG1ha2UgYSBiYXNpYyBoaXN0b2dyYW0gYW5kIGEgYm94IGFuZCB3aGlza2VyLCB0aGVuIHdlJ2xsIGNhbGwgaXQgYSBkYXkuCgpQbG90dGluZyB0aGUgZGlzdHJpYnV0aW9uIG9mIGRhdGEgd2l0aCBhIGhpc3RvZ3JhbSBjYW4gYmUgdXNlZnVsIHRvIGlkZW50aWZ5IG91dGxpZXJzIG9yIGhhdmUgYSBsb29rIGF0IHRoZSBzaGFwZSBvZiB5b3VyIGRhdGEuIFdlIGNhbiBwbG90IHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uIGFzIGFuIGV4YW1wbGUgLSB0aGUgZm9sbG93aW5nIGNvZGUgd2lsbCBnZW5lcmF0ZSBhIHNlcmllcyBvZiBudW1iZXJzIHRoYXQgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhbmQgdGhlbiBwbG90IGl0OgoKYGBge3J9CnggPC0gcm5vcm0obiA9IDEwMDAsIG1lYW4gPSAyNS41LCBzZCA9IDMpCgpoaXN0KHgpCgpgYGAKCiFbXShoaXN0MS5wbmcpCgpCb3hwbG90cyBhcmUgdXNlZnVsIHRvIGhhdmUgYSBsb29rIGF0IHBvdGVudGlhbCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGdyb3VwcyBvZiBkYXRhIC0gbGV0J3MgcGxvdCB0aGUgaXJpcyBkYXRhIGFuZCBzZWUgaG93IHBldGFsIHdpZHRoIG1pZ2h0IGRpZmZlciBhbW9uZyBzcGVjaWVzOgoKYGBge3J9CmhlYWQoaXJpcykKCmJveHBsb3QoaXJpcyRQZXRhbC5XaWR0aCB+IGlyaXMkU3BlY2llcywKCSAgbGFzID0gMSwgeWxhYiA9IOKAnFBldGFsIHdpZHRo4oCdLAoJICB4bGFiID0g4oCcU3BlY2llc+KAnSkKCmBgYAoKIVtdKGJveDEucG5nKQoKIyMgQSBxdWljayBub3RlIGFib3V0IHRpbGRlICh+KQoKSW4gUiwgYSB0aWxkZSBkZW5vdGVzIHRoZSByZWxhdGluc2hpcCBiZXR3ZWVuIHR3byB2YXJpYWJsZXMsIGFuZCBpcyBjb21tb25seSB1c2VkIGluIHN0YXRpc3RpY2FsIGZ1bmN0aW9ucy4gSXQncyBzbGlnaHRseSBjb25mdXNpbmcsIGFzIGl0IGFwcGVhcnMgdG8gYmUgdGhlIHdyb25nIHdheSBhcm91bmQgLSB5b3UgY29kZSB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCB0aGVuIHRoZSBpbmRlcGVuZGVudC4gU28sIGBgYFBldGFsIHdpZHRoIH4gU3BlY2llc2BgYCBtZWFucyBob3cgZG9lcyBwZXRhbCB3aWR0aCB2YXJ5IGFtb25nIHNwZWNpZXM/IQoKIyBUb3AgdGlwcyBmb3IgbGVhcm5pbmcgUjoKCiogRXhwZXJpbWVudCEgTm90IG11Y2ggY2FuIGdvIGhvcnJpYmx5IHdyb25nLi4uCiogUHJhY3RpY2UsIHByYWN0aWNlLCBwcmFjdGljZSEKKiBUaGVyZSBpcyBubyBzaW5nbGUgcmlnaHQgd2F5IC0gaWYgaXQgd29ya3MsIGl0IHdvcmtzLgoqIFVzZSByZXNvdXJjZXMgYXZhaWxhYmxlIG9ubGluZSAtIFN0YWNrT3ZlcmZsb3csIFR3aXR0ZXIsIFIgZm9ydW1zICh3aXRoIGNhdXRpb24hKQoqIFRha2UgYSBicmVhay4gQSB3YWxrIGFuZCBhIGJyZXcgZG9lcyB3b25kZXJzLgoKCgoKCgo=