Objectives
This notebook will demonstrate how to:
- Navigate the RStudio environment
- Use R for simple calculations, both mathematical and logical
- Define and use variables in base R
- Understand and apply base R functions
- Understand, define, and use R data types, including vector
manipulation and indexing
- Understand the anatomy of a data frame
More resources for learning R
What is R?
R is a statistical computing language that is
open source, meaning the underlying code for the language is
freely available to anyone. You do not need a special license or set of
permissions to use and develop code in R.
R itself is an interpreted computer language and comes with
functionality that comes bundled with the language itself, known as
“base R”. But there is also rich additional
functionality provided by external packages, or
libraries of code that assist in accomplishing certain tasks and can be
freely downloaded and loaded for use.
In the next notebook and subsequent modules, we will be using a suite
of packages collectively known as The Tidyverse. The
tidyverse
is geared towards intuitive data science
applications that follow a shared data philosophy. But there are still
many core features of base R which are important to be aware of, and we
will be using concepts from both base R and the tidyverse in our
analyses, as well as task specific packages for analyses such as gene
expression.
What is RStudio?
RStudio is a graphical environment (“integrated development
environment” or IDE) for writing and developing R code. RStudio is NOT a
separate programming language - it is an interface we use to facilitate
R programming. In other words, you can program in R without RStudio, but
you can’t use the RStudio environment without R.
For more information about RStudio than you ever wanted to know, see
this RStudio
IDE Cheatsheet (pdf).
The RStudio Environment
The RStudio environment has four main panes, each of
which may have a number of tabs that display different information or
functionality. (their specific location can be changed under Tools ->
Global Options -> Pane Layout).
The Editor pane is where you can write R scripts
and other documents. Each tab here is its own document. This is your
text editor, which will allow you to save your R code for
future use. Note that change code here will not run automatically until
you run it.
The Console pane is where you can
interactively run R code.
- There is also a Terminal tab here which can be used
for running programs outside R on your computer
The Environment pane primarily displays the
variables, sometimes known as objects that are defined during a
given R session, and what data or values they might hold.
The final pane, Files, Plots, Help, …, has
several pretty important tabs:
- The Files tab shows the structure and contents of
files and folders (also known as directories) on your computer.
- The Plots tab will reveal plots when you make
them
- The Packages tab shows which installed packages
have been loaded into your R session
- The Help tab will show the help page when you look
up a function
- The Viewer tab will reveal compiled R Markdown
documents
Basic Calculations
Mathematical operators
The most basic use of R is as a regular calculator:
Add |
+ |
Subtract |
- |
Multiply |
* |
Divide |
/ |
Exponentiate |
^ or ** |
For example, we can do some simple multiplication like this. 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
Cmd+Shift+Enter on a Mac, or Ctrl+Shift+Enter on a
PC.
5 * 6
[1] 30
Use the console to calculate other expressions. Standard order of
operations applies (mostly), and you can use parentheses ()
as you might expect (but not brackets []
or
braces{}
, which have special meanings). Note however, that
you must always specify multiplication with
*
; implicit multiplication such as 10(3 + 4)
or 10x
will not work and will generate an error, or
worse.
10 * (3 + 4)^2
[1] 490
Defining and using variables
To define a variable, we use the assignment operator which
looks like an arrow: <-
, for example
x <- 7
takes the value on the right-hand side of the
operator and assigns it to the variable name on the left-hand side.
# Define a variable x to equal 7, and print out the value of x
x <- 7
# We can have R repeat back to us what `x` is by just using `x`
x
[1] 7
Some features of variables, considering the example
x <- 7
: Every variable has a name, a
value, and a type. This variable’s
name is x
, its value is 7
, and its type is
numeric
(7 is a number!). Re-defining a variable will
overwrite the value.
x <- 5.5
x
[1] 5.5
We can modify an existing variable by reassigning it to its same
name. Here we’ll add 2
to x
and reassign the
result back to x
.
x <- x + 2
x
[1] 7.5
Variable naming note:
As best you can, it is a good idea to make your variable names
informative (e.g. x
doesn’t mean anything, but
sandwich_price
is meaningful… if we’re talking about the
cost of sandwiches, that is..).
Functions
We can use pre-built computation methods called “functions” for other
operations. Functions have the following format, where the
argument is the information we are providing to the function
for it to run. An example of this was the atan()
function
used above.
function_name(argument)
To learn about functions, we’ll examine one called log()
first.
To know what a function does and how to use it, use the question mark
which will reveal documentation in the help pane:
?log
The documentation tells us that log()
is derived from
{base}
, meaning it is a function that is part of base R. It
provides a brief description of what the function does and shows several
examples of to how use it.
In particular, the documentation tells us about what argument(s) to
provide:
- The first required argument is the value we’d like to take
the log of, by default its natural log
- The second optional argument can specify a different base
rather than the default
e
.
Functions also return values for us to use. In the case of
log()
, the returned value is the log’d value the function
computed.
log(73)
[1] 4.290459
Here we can specify an argument of base
to
calculate log base 3.
log(81, base = 3)
[1] 4
If we don’t specify the argument names, it assumes they are
in the order that log
defines them. See ?log
to see more about its arguments.
log(8, 2)
[1] 3
We can switch the order if we specify the argument names.
log(base = 10, x = 4342)
[1] 3.63769
We can also provide variables as arguments in the same way as the raw
values.
meaning <- 42
log(meaning)
[1] 3.73767
Working with variables
Variable Types
Variable types in R can sometimes be coerced (converted)
from one type to another.
# Define a variable with a number
x <- 15
The function class()
will tell us the variable’s
type.
class(x)
[1] "numeric"
numeric
Let’s coerce it to a character.
x <- as.character(x)
class(x)
[1] "character"
character
See it now has quotes around it? It’s now a character and will behave
as such.
x
[1] "15"
15
Use this chunk to try to perform calculations with x
,
now that it is a character, what happens?
# Try to perform calculations on `x`
But we can’t coerce everything:
# Let's create a character variable
x <- "look at my character variable"
Let’s try making this a numeric variable:
x <- as.numeric(x)
Warning: NAs introduced by coercion
Print out x
.
x
[1] NA
R is telling us it doesn’t know how to convert this to a numeric
variable, so it has returned NA
instead.
For reference, here’s a summary of some of the most important
variable types.
numeric |
Any number value |
5
7.5
-1 |
as.numeric() |
integer |
Any whole number value (no decimals) |
5 -100 |
as.integer() |
character |
Any collection of characters defined within quotation
marks. Also known as a “string”. |
"a" (a single letter)
"stringofletters" (a whole bunch of characters put
together as one) "string of letters and spaces"
"5" 'single quotes are also good' |
as.character() |
logical |
A value of TRUE , FALSE , or
NA |
TRUE FALSE NA (not
defined) |
as.logical() |
factor |
A special type of variable that denotes specific categories of a
categorical variable |
(stay tuned..) |
as.factor() |
Vectors
You will have noticed that all your computations tend to pop up with
a [1]
preceding them in R’s output. This is because, in
fact, all (ok mostly all) variables are by default vectors, and
our answers are the first (in these cases only) value in the vector. As
vectors get longer, new index indicators will appear at the start of new
lines.
# This is actually an vector that has one item in it.
x <- 7
# The length() functions tells us how long an vector is:
length(x)
[1] 1
We can define vectors with the function c()
, which
stands for “combine”. This function takes a comma-separated set of
values to place in the vector, and returns the vector itself:
my_numeric_vector <- c(1, 1, 2, 3, 5, 8, 13, 21)
my_numeric_vector
[1] 1 1 2 3 5 8 13 21
We can build on vectors in place by redefining them:
# add the next two Fibonacci numbers to the series.
my_numeric_vector <- c(my_numeric_vector, 34, 55)
my_numeric_vector
[1] 1 1 2 3 5 8 13 21 34 55
We can pull out specific items from an vector using a process called
indexing, which uses brackets []
to specify the
position of an item.
# Grab the fourth value from my_numeric_vector
# This gives us an vector of length 1
my_numeric_vector[4]
[1] 3
Colons are also a nice way to quickly make ordered numeric vectors
Use a colon to specify an inclusive range of indices This will return an
vector with 2, 3, 4, and 5.
my_numeric_vector[2:5]
[1] 1 2 3 5
One major benefit of vectors is the concept of
vectorization, where R by default performs operations
on the entire vector at once. For example, we can get the log
of all numbers 1-20 with a single, simple call, and more!
values_1_to_20 <- 1:20
# calculate the log of values_1_to_20
log(values_1_to_20)
[1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101
[8] 2.0794415 2.1972246 2.3025851 2.3978953 2.4849066 2.5649494 2.6390573
[15] 2.7080502 2.7725887 2.8332133 2.8903718 2.9444390 2.9957323
Finally, we can apply logical expressions to vectors, just as we can
do for single values. The output here is a logical vector telling us
whether each value in example_vector is TRUE or FALSE
# Which values are <= 3?
values_1_to_20 <= 3
[1] TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
There are several key functions which can be used on vectors
containing numeric values, some of which are below.
mean()
: The average value in the vector
min()
: The minimum value in the vector
max()
: The maximum value in the vector
sum()
: The sum of all values in the vector
We can try out these functions on the vector
values_1_to_20
we’ve created.
mean(values_1_to_20)
[1] 10.5
# Try out some of the other functions we've listed above
A note on variable naming
We have learned functions such as c
,
length
, sum
, and etc. Imagine defining a
variable called c
: This will work, but it will lead to a
lot of unintended bugs, so it’s best to avoid this.
The %in%
logical operator
%in%
is useful for determining whether a given item(s)
are in an vector.
# is `7` in our vector?
7 %in% values_1_to_20
[1] TRUE
# is `50` in our vector?
50 %in% values_1_to_20
[1] FALSE
We can test a vector of values being within another vector of
values.
question_values <- c(1:3, 7, 50)
# Are these values in our vector?
question_values %in% values_1_to_20
[1] TRUE TRUE TRUE TRUE FALSE
Data frames
Data frames are one of the most useful tools for data analysis in
R. They are tables which consist of rows and columns, much like a
spreadsheet. Each column is a variable which behaves as a
vector, and each row is an observation. We will begin our
exploration with dataset of measurements from three penguin species
measured, which we can find in the palmerpenguins
package. We’ll talk more about packages soon! To use this dataset,
we will load it from the palmerpenguins
package using a
::
(more on this later) and assign it to a variable named
penguins
in our current environment.
penguins <- palmerpenguins::penguins
Artwork by @allison_horst
Exploring data frames
The first step to using any data is to look at it!!! RStudio contains
a special function View()
which allows you to literally
view a variable. You can also click on the object in the environment
pane to see its overall properties, or click the table icon on the
object’s row to automatically view the variable.
Some useful functions for exploring our data frame include:
head()
to see the first 6 rows of a data frame.
Additional arguments supplied can change the number of rows.
tail()
to see the last 6 rows of a data frame.
Additional arguments supplied can change the number of rows.
names()
to see the column names of the data frame.
nrow()
to see how many rows are in the data frame
ncol()
to see how many columns are in the data
frame.
We can additionally explore overall properties of the data
frame with two different functions: summary()
and
str()
.
This provides summary statistics for each column:
summary(penguins)
species island bill_length_mm bill_depth_mm
Adelie :152 Biscoe :168 Min. :32.10 Min. :13.10
Chinstrap: 68 Dream :124 1st Qu.:39.23 1st Qu.:15.60
Gentoo :124 Torgersen: 52 Median :44.45 Median :17.30
Mean :43.92 Mean :17.15
3rd Qu.:48.50 3rd Qu.:18.70
Max. :59.60 Max. :21.50
NA's :2 NA's :2
flipper_length_mm body_mass_g sex year
Min. :172.0 Min. :2700 female:165 Min. :2007
1st Qu.:190.0 1st Qu.:3550 male :168 1st Qu.:2007
Median :197.0 Median :4050 NA's : 11 Median :2008
Mean :200.9 Mean :4202 Mean :2008
3rd Qu.:213.0 3rd Qu.:4750 3rd Qu.:2009
Max. :231.0 Max. :6300 Max. :2009
NA's :2 NA's :2
This provides a short view of the structure and
contents of the data frame.
str(penguins)
tibble [344 × 8] (S3: tbl_df/tbl/data.frame)
$ species : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
$ island : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
$ bill_length_mm : num [1:344] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
$ bill_depth_mm : num [1:344] 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
$ flipper_length_mm: int [1:344] 181 186 195 NA 193 190 181 195 193 190 ...
$ body_mass_g : int [1:344] 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
$ sex : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
$ year : int [1:344] 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
You’ll notice that the column species
is a
factor: This is a special type of character variable that
represents distinct categories known as “levels”. We have learned here
that there are three levels in the species
column: Adelie,
Chinstrap, and Gentoo. We might want to explore individual columns of
the data frame more in-depth. We can examine individual columns using
the dollar sign $
to select one by name:
# Extract bill_length_mm as a vector
penguins$bill_length_mm
[1] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42.0 37.8 37.8 41.1 38.6 34.6
[16] 36.6 38.7 42.5 34.4 46.0 37.8 37.7 35.9 38.2 38.8 35.3 40.6 40.5 37.9 40.5
[31] 39.5 37.2 39.5 40.9 36.4 39.2 38.8 42.2 37.6 39.8 36.5 40.8 36.0 44.1 37.0
[46] 39.6 41.1 37.5 36.0 42.3 39.6 40.1 35.0 42.0 34.5 41.4 39.0 40.6 36.5 37.6
[61] 35.7 41.3 37.6 41.1 36.4 41.6 35.5 41.1 35.9 41.8 33.5 39.7 39.6 45.8 35.5
[76] 42.8 40.9 37.2 36.2 42.1 34.6 42.9 36.7 35.1 37.3 41.3 36.3 36.9 38.3 38.9
[91] 35.7 41.1 34.0 39.6 36.2 40.8 38.1 40.3 33.1 43.2
[ reached getOption("max.print") -- omitted 244 entries ]
# indexing operators can be used on these vectors too
penguins$bill_length_mm[1:10]
[1] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42.0
We can perform our regular vector operations on columns directly.
# calculate the mean of the bill_length_mm column
mean(penguins$bill_length_mm,
na.rm = TRUE) # remove missing values before calculating the mean
[1] 43.92193
We can also calculate the full summary statistics for a single column
directly.
# show a summary of the bill_length_mm column
summary(penguins$bill_length_mm)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
32.10 39.23 44.45 43.92 48.50 59.60 2
Extract species
as a vector and subset it to see a
preview.
# get the first 10 values of the species column
penguins$species[1:10]
[1] Adelie Adelie Adelie Adelie Adelie Adelie Adelie Adelie Adelie Adelie
Levels: Adelie Chinstrap Gentoo
And view its levels with the levels()
function.
levels(penguins$species)
[1] "Adelie" "Chinstrap" "Gentoo"
Adelie
Chinstrap
Gentoo
Files and directories
In many situations, we will be reading in tabular data from a file
and using it as a data frame. To practice, we will read in a file we
will be using in the next notebook as well,
gene_results_GSE44971.tsv
, in the data
folder.
File paths are relative to the location where this notebook file (.Rmd)
is saved.
Here we will use a function, read_tsv()
from the
readr
package. Before we are able to use the function, we
have to load the package using library()
.
library(readr)
file.path()
creates a properly formatted file path by
adding a path separator (/
on Mac and Linux operating
systems, the latter of which is the operating system that our RStudio
Server runs on) between separate folders or directories. Because file
path separators can differ between your computer and the computer of
someone who wants to use your code, we use file.path()
instead of typing out "data/gene_results_GSE44971.tsv"
.
Each argument to file.path()
is a directory or
file name. You’ll notice each argument is in quotes, we specify
data
first because the file,
gene_results_GSE44971.tsv
is in the data
folder.
file.path("data", "gene_results_GSE44971.tsv")
[1] "data/gene_results_GSE44971.tsv"
data/gene_results_GSE44971.tsv
As you can see above, the result of running file.path()
is that it creates a string with an accurately-formatted path
for your file system. This string can be used moving forward when you
need to refer to the path to your file. Let’s go ahead and store this
file path as a variable in our environment.
gene_file_path <- file.path("data", "gene_results_GSE44971.tsv")
Now we are ready to use read_tsv()
to read the file into
R. The resulting data frame will be stored in a variable named
stats_df
. Note the <-
(assignment
operator!) is responsible for saving this to our global environment.
# read in the file `gene_results_GSE44971.tsv` from the data directory
stats_df <- read_tsv(gene_file_path)
Rows: 6804 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: "\t"
chr (3): ensembl_id, gene_symbol, contrast
dbl (5): log_fold_change, avg_expression, t_statistic, p_value, adj_p_value
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Take a look at your environment panel to see what
stats_df
looks like. We can also print out a preview of the
stats_df
data frame here.
# display stats_df
stats_df
Session Info
At the end of every notebook, you will see us print out
sessionInfo
. This aids in the reproducibility of your code
by showing exactly what packages and versions were being used the last
time the notebook was run.
sessionInfo()
R version 4.4.1 (2024-06-14)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 22.04.4 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
time zone: Etc/UTC
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] readr_2.1.5 optparse_1.7.5
loaded via a namespace (and not attached):
[1] crayon_1.5.2 vctrs_0.6.5 cli_3.6.2
[4] knitr_1.46 rlang_1.1.3 xfun_0.43
[7] stringi_1.8.3 jsonlite_1.8.8 bit_4.0.5
[10] glue_1.7.0 htmltools_0.5.8.1 sass_0.4.9
[13] hms_1.1.3 fansi_1.0.6 rmarkdown_2.26
[16] evaluate_0.23 jquerylib_0.1.4 tibble_3.2.1
[19] tzdb_0.4.0 fastmap_1.1.1 yaml_2.3.8
[22] lifecycle_1.0.4 palmerpenguins_0.1.1 stringr_1.5.1
[25] compiler_4.4.1 getopt_1.20.4 pkgconfig_2.0.3
[28] digest_0.6.35 R6_2.5.1 tidyselect_1.2.1
[31] utf8_1.2.4 parallel_4.4.1 vroom_1.6.5
[34] pillar_1.9.0 magrittr_2.0.3 bslib_0.7.0
[37] bit64_4.0.5 tools_4.4.1 cachem_1.0.8
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgYW5kIFJTdHVkaW8iCmF1dGhvcjogT3JpZ2luYWxseSBhdXRob3JlZCBieSBTdGVwaGFuaWUgSi4gU3BpZWxtYW4sPGJyPmFkYXB0ZWQgYnkgQ0NETCBmb3IgQUxTRgpkYXRlOiAyMDIxCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgojIyBPYmplY3RpdmVzCgpUaGlzIG5vdGVib29rIHdpbGwgZGVtb25zdHJhdGUgaG93IHRvOiAgCgotIE5hdmlnYXRlIHRoZSBSU3R1ZGlvIGVudmlyb25tZW50ICAKLSBVc2UgUiBmb3Igc2ltcGxlIGNhbGN1bGF0aW9ucywgYm90aCBtYXRoZW1hdGljYWwgYW5kIGxvZ2ljYWwgIAotIERlZmluZSBhbmQgdXNlIHZhcmlhYmxlcyBpbiBiYXNlIFIgIAotIFVuZGVyc3RhbmQgYW5kIGFwcGx5IGJhc2UgUiBmdW5jdGlvbnMgICAKLSBVbmRlcnN0YW5kLCBkZWZpbmUsIGFuZCB1c2UgUiBkYXRhIHR5cGVzLCBpbmNsdWRpbmcgdmVjdG9yIG1hbmlwdWxhdGlvbiBhbmQgaW5kZXhpbmcgIAotIFVuZGVyc3RhbmQgdGhlIGFuYXRvbXkgb2YgYSBkYXRhIGZyYW1lICAKCi0tLQoKIyMjIyAqTW9yZSByZXNvdXJjZXMgZm9yIGxlYXJuaW5nIFIqIAoKLSBbU3dpcmwsIGFuIGludGVyYWN0aXZlIHR1dG9yaWFsXShodHRwczovL3N3aXJsc3RhdHMuY29tLykgIAotIFtfUiBmb3IgRGF0YSBTY2llbmNlXyBib29rXShodHRwczovL3I0ZHMuaGFkbGV5Lm56LykgIAotIFtUdXRvcmlhbCBvbiBSLCBSU3R1ZGlvIGFuZCBSIE1hcmtkb3duXShodHRwczovL2lzbWF5Yy5naXRodWIuaW8vcmJhc2ljcy1ib29rLykgIAotIFtIYW5keSBSIGNoZWF0c2hlZXRzXShodHRwczovL3d3dy5wb3NpdC5jby9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKSAgCi0gW1IgTWFya2Rvd24gd2Vic2l0ZV0oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pICAKLSBbX1IgTWFya2Rvd246IFRoZSBEZWZpbml0aXZlIEd1aWRlX10oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykgIAoKIyMgV2hhdCBpcyBSPwoKKipSKiogaXMgYSBzdGF0aXN0aWNhbCBjb21wdXRpbmcgbGFuZ3VhZ2UgdGhhdCBpcyBfb3BlbiBzb3VyY2VfLCBtZWFuaW5nIHRoZSB1bmRlcmx5aW5nIGNvZGUgZm9yIHRoZSBsYW5ndWFnZSBpcyBmcmVlbHkgYXZhaWxhYmxlIHRvIGFueW9uZS4gCllvdSBkbyBub3QgbmVlZCBhIHNwZWNpYWwgbGljZW5zZSBvciBzZXQgb2YgcGVybWlzc2lvbnMgdG8gdXNlIGFuZCBkZXZlbG9wIGNvZGUgaW4gUi4gCgpSIGl0c2VsZiBpcyBhbiBfaW50ZXJwcmV0ZWQgY29tcHV0ZXIgbGFuZ3VhZ2VfIGFuZCBjb21lcyB3aXRoIGZ1bmN0aW9uYWxpdHkgdGhhdCBjb21lcyBidW5kbGVkIHdpdGggdGhlIGxhbmd1YWdlIGl0c2VsZiwga25vd24gYXMgKioiYmFzZSBSIioqLgpCdXQgdGhlcmUgaXMgYWxzbyByaWNoIGFkZGl0aW9uYWwgZnVuY3Rpb25hbGl0eSBwcm92aWRlZCBieSAqKmV4dGVybmFsIHBhY2thZ2VzKiosIG9yIGxpYnJhcmllcyBvZiBjb2RlIHRoYXQgYXNzaXN0IGluIGFjY29tcGxpc2hpbmcgY2VydGFpbiB0YXNrcyBhbmQgY2FuIGJlIGZyZWVseSBkb3dubG9hZGVkIGFuZCBsb2FkZWQgZm9yIHVzZS4gCgpJbiB0aGUgbmV4dCBub3RlYm9vayBhbmQgc3Vic2VxdWVudCBtb2R1bGVzLCB3ZSB3aWxsIGJlIHVzaW5nIGEgc3VpdGUgb2YgcGFja2FnZXMgY29sbGVjdGl2ZWx5IGtub3duIGFzIFsqKlRoZSBUaWR5dmVyc2UqKl0oaHR0cHM6Ly90aWR5dmVyc2Uub3JnKS4gClRoZSBgdGlkeXZlcnNlYCBpcyBnZWFyZWQgdG93YXJkcyBpbnR1aXRpdmUgZGF0YSBzY2llbmNlIGFwcGxpY2F0aW9ucyB0aGF0IGZvbGxvdyBhIHNoYXJlZCBkYXRhIHBoaWxvc29waHkuCkJ1dCB0aGVyZSBhcmUgc3RpbGwgbWFueSBjb3JlIGZlYXR1cmVzIG9mIGJhc2UgUiB3aGljaCBhcmUgaW1wb3J0YW50IHRvIGJlIGF3YXJlIG9mLCBhbmQgd2Ugd2lsbCBiZSB1c2luZyBjb25jZXB0cyBmcm9tIGJvdGggYmFzZSBSIGFuZCB0aGUgdGlkeXZlcnNlIGluIG91ciBhbmFseXNlcywgYXMgd2VsbCBhcyB0YXNrIHNwZWNpZmljIHBhY2thZ2VzIGZvciBhbmFseXNlcyBzdWNoIGFzIGdlbmUgZXhwcmVzc2lvbi4gCgojIyMgV2hhdCBpcyBSU3R1ZGlvPwoKUlN0dWRpbyBpcyBhIF9ncmFwaGljYWwgZW52aXJvbm1lbnRfICgiaW50ZWdyYXRlZCBkZXZlbG9wbWVudCBlbnZpcm9ubWVudCIgb3IgSURFKSBmb3Igd3JpdGluZyBhbmQgZGV2ZWxvcGluZyBSIGNvZGUuIFJTdHVkaW8gaXMgTk9UIGEgc2VwYXJhdGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgLSBpdCBpcyBhbiBpbnRlcmZhY2Ugd2UgdXNlIHRvIGZhY2lsaXRhdGUgUiBwcm9ncmFtbWluZy4gCkluIG90aGVyIHdvcmRzLCB5b3UgY2FuIHByb2dyYW0gaW4gUiB3aXRob3V0IFJTdHVkaW8sIGJ1dCB5b3UgY2FuJ3QgdXNlIHRoZSBSU3R1ZGlvIGVudmlyb25tZW50IHdpdGhvdXQgUi4KCkZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IFJTdHVkaW8gdGhhbiB5b3UgZXZlciB3YW50ZWQgdG8ga25vdywgc2VlIHRoaXMgW1JTdHVkaW8gSURFIENoZWF0c2hlZXQgKHBkZildKGh0dHBzOi8vZ2l0aHViLmNvbS9yc3R1ZGlvL2NoZWF0c2hlZXRzL3Jhdy9tYWluL3JzdHVkaW8taWRlLnBkZikuCgojIyBUaGUgUlN0dWRpbyBFbnZpcm9ubWVudAoKVGhlIFJTdHVkaW8gZW52aXJvbm1lbnQgaGFzIGZvdXIgbWFpbiAqKnBhbmVzKiosIGVhY2ggb2Ygd2hpY2ggbWF5IGhhdmUgYSBudW1iZXIgb2YgdGFicyB0aGF0IGRpc3BsYXkgZGlmZmVyZW50IGluZm9ybWF0aW9uIG9yIGZ1bmN0aW9uYWxpdHkuICh0aGVpciBzcGVjaWZpYyBsb2NhdGlvbiBjYW4gYmUgY2hhbmdlZCB1bmRlciBUb29scyAtPiBHbG9iYWwgT3B0aW9ucyAtPiBQYW5lIExheW91dCkuCiFbUlN0dWRpbyBBcHBlYXJhbmNlXShzY3JlZW5zaG90cy9yc3R1ZGlvLXBhbmVzLnBuZykgCgoxLiBUaGUgKipFZGl0b3IqKiBwYW5lIGlzIHdoZXJlIHlvdSBjYW4gd3JpdGUgUiBzY3JpcHRzIGFuZCBvdGhlciBkb2N1bWVudHMuIEVhY2ggdGFiIGhlcmUgaXMgaXRzIG93biBkb2N1bWVudC4KVGhpcyBpcyB5b3VyIF90ZXh0IGVkaXRvcl8sIHdoaWNoIHdpbGwgYWxsb3cgeW91IHRvIHNhdmUgeW91ciBSIGNvZGUgZm9yIGZ1dHVyZSB1c2UuIApOb3RlIHRoYXQgY2hhbmdlIGNvZGUgaGVyZSB3aWxsIG5vdCBydW4gYXV0b21hdGljYWxseSB1bnRpbCB5b3UgcnVuIGl0LiAKCjIuIFRoZSAqKkNvbnNvbGUqKiBwYW5lIGlzIHdoZXJlIHlvdSBjYW4gX2ludGVyYWN0aXZlbHlfIHJ1biBSIGNvZGUuIAogICsgVGhlcmUgaXMgYWxzbyBhICoqVGVybWluYWwqKiB0YWIgaGVyZSB3aGljaCBjYW4gYmUgdXNlZCBmb3IgcnVubmluZyBwcm9ncmFtcyBvdXRzaWRlIFIgb24geW91ciBjb21wdXRlcgogIAozLiBUaGUgKipFbnZpcm9ubWVudCoqIHBhbmUgcHJpbWFyaWx5IGRpc3BsYXlzIHRoZSB2YXJpYWJsZXMsIHNvbWV0aW1lcyBrbm93biBhcyBfb2JqZWN0c18gdGhhdCBhcmUgZGVmaW5lZCBkdXJpbmcgYSBnaXZlbiBSIHNlc3Npb24sIGFuZCB3aGF0IGRhdGEgb3IgdmFsdWVzIHRoZXkgbWlnaHQgaG9sZC4KCjQuIFRoZSBmaW5hbCBwYW5lLCAqKkZpbGVzLCBQbG90cywgSGVscCwgLi4uKiosIGhhcyBzZXZlcmFsIHByZXR0eSBpbXBvcnRhbnQgdGFiczoKICAgICsgVGhlICoqRmlsZXMqKiB0YWIgc2hvd3MgdGhlIHN0cnVjdHVyZSBhbmQgY29udGVudHMgb2YgZmlsZXMgYW5kIGZvbGRlcnMgKGFsc28ga25vd24gYXMgZGlyZWN0b3JpZXMpIG9uIHlvdXIgY29tcHV0ZXIuCiAgICArIFRoZSAqKlBsb3RzKiogdGFiIHdpbGwgcmV2ZWFsIHBsb3RzIHdoZW4geW91IG1ha2UgdGhlbQogICAgKyBUaGUgKipQYWNrYWdlcyoqIHRhYiBzaG93cyB3aGljaCBpbnN0YWxsZWQgcGFja2FnZXMgaGF2ZSBiZWVuIGxvYWRlZCBpbnRvIHlvdXIgUiBzZXNzaW9uCiAgICArIFRoZSAqKkhlbHAqKiB0YWIgd2lsbCBzaG93IHRoZSBoZWxwIHBhZ2Ugd2hlbiB5b3UgbG9vayB1cCBhIGZ1bmN0aW9uCiAgICArIFRoZSAqKlZpZXdlcioqIHRhYiB3aWxsIHJldmVhbCBjb21waWxlZCBSIE1hcmtkb3duIGRvY3VtZW50cwoKIyMgQmFzaWMgQ2FsY3VsYXRpb25zCgojIyMgTWF0aGVtYXRpY2FsIG9wZXJhdG9ycwoKVGhlIG1vc3QgYmFzaWMgdXNlIG9mIFIgaXMgYXMgYSByZWd1bGFyIGNhbGN1bGF0b3I6Cgp8IE9wZXJhdGlvbiB8IFN5bWJvbCB8CnwtLS0tLS0tLS0tLXwtLS0tLS0tLXwKfCBBZGQgIHwgYCtgIHwgCnwgU3VidHJhY3QgIHwgYC1gIHwgCnwgTXVsdGlwbHkgIHwgYCpgIHwgCnwgRGl2aWRlICB8IGAvYCB8IAp8IEV4cG9uZW50aWF0ZSB8IGBeYCBvciBgKipgIHwgCgpGb3IgZXhhbXBsZSwgd2UgY2FuIGRvIHNvbWUgc2ltcGxlIG11bHRpcGxpY2F0aW9uIGxpa2UgdGhpcy4gCldoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgCnBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ21kK1NoaWZ0K0VudGVyKiBvbiBhIE1hYywgb3IgKkN0cmwrU2hpZnQrRW50ZXIqIG9uIGEgUEMuCgpgYGB7ciBjYWxjdWxhdG9yfQo1ICogNgpgYGAKClVzZSB0aGUgY29uc29sZSB0byBjYWxjdWxhdGUgb3RoZXIgZXhwcmVzc2lvbnMuIFN0YW5kYXJkIG9yZGVyIG9mIG9wZXJhdGlvbnMgYXBwbGllcyAobW9zdGx5KSwgYW5kICB5b3UgY2FuIHVzZSBwYXJlbnRoZXNlcyBgKClgIGFzIHlvdSBtaWdodCBleHBlY3QgKGJ1dCBub3QgYnJhY2tldHMgYFtdYCBvciBicmFjZXNge31gLCB3aGljaCBoYXZlIHNwZWNpYWwgbWVhbmluZ3MpLiBOb3RlIGhvd2V2ZXIsIHRoYXQgeW91IG11c3QgKiphbHdheXMqKiBzcGVjaWZ5IG11bHRpcGxpY2F0aW9uIHdpdGggYCpgOyBpbXBsaWNpdCBtdWx0aXBsaWNhdGlvbiBzdWNoIGFzIGAxMCgzICsgNClgIG9yIGAxMHhgIHdpbGwgbm90IHdvcmsgYW5kIHdpbGwgZ2VuZXJhdGUgYW4gZXJyb3IsIG9yIHdvcnNlLgoKYGBge3IgZXhwcmVzc2lvbnMsIGxpdmUgPSBUUlVFfQoxMCAqICgzICsgNCleMgpgYGAKCgojIyMgRGVmaW5pbmcgYW5kIHVzaW5nIHZhcmlhYmxlcyAKClRvIGRlZmluZSBhIHZhcmlhYmxlLCB3ZSB1c2UgdGhlIF9hc3NpZ25tZW50IG9wZXJhdG9yXyB3aGljaCBsb29rcyBsaWtlIGFuIGFycm93OiBgPC1gLCBmb3IgZXhhbXBsZSBgeCA8LSA3YCB0YWtlcyB0aGUgdmFsdWUgb24gdGhlIHJpZ2h0LWhhbmQgc2lkZSBvZiB0aGUgb3BlcmF0b3IgYW5kIGFzc2lnbnMgaXQgdG8gdGhlIHZhcmlhYmxlIG5hbWUgb24gdGhlIGxlZnQtaGFuZCBzaWRlLiAKCmBgYHtyIHZhci1kZWZpbmUsIGxpdmUgPSBUUlVFfQojIERlZmluZSBhIHZhcmlhYmxlIHggdG8gZXF1YWwgNywgYW5kIHByaW50IG91dCB0aGUgdmFsdWUgb2YgeAp4IDwtIDcKCiMgV2UgY2FuIGhhdmUgUiByZXBlYXQgYmFjayB0byB1cyB3aGF0IGB4YCBpcyBieSBqdXN0IHVzaW5nIGB4YAp4CmBgYAoKU29tZSBmZWF0dXJlcyBvZiB2YXJpYWJsZXMsIGNvbnNpZGVyaW5nIHRoZSBleGFtcGxlIGB4IDwtIDdgOgpFdmVyeSB2YXJpYWJsZSBoYXMgYSAqKm5hbWUqKiwgYSAqKnZhbHVlKiosIGFuZCBhICoqdHlwZSoqLiAKVGhpcyB2YXJpYWJsZSdzIG5hbWUgaXMgYHhgLCBpdHMgdmFsdWUgaXMgYDdgLCBhbmQgaXRzIHR5cGUgaXMgYG51bWVyaWNgICg3IGlzIGEgbnVtYmVyISkuClJlLWRlZmluaW5nIGEgdmFyaWFibGUgd2lsbCBvdmVyd3JpdGUgdGhlIHZhbHVlLgoKYGBge3IgdmFyLXJlZGVmaW5lfQp4IDwtIDUuNQoKeApgYGAKCldlIGNhbiBtb2RpZnkgYW4gZXhpc3RpbmcgdmFyaWFibGUgYnkgcmVhc3NpZ25pbmcgaXQgdG8gaXRzIHNhbWUgbmFtZS4gCkhlcmUgd2UnbGwgYWRkIGAyYCB0byBgeGAgYW5kIHJlYXNzaWduIHRoZSByZXN1bHQgYmFjayB0byBgeGAuIAoKYGBge3IgdmFyLW1vZGlmeSwgbGl2ZSA9IFRSVUV9CnggPC0geCArIDIKCngKYGBgCgojIyMgVmFyaWFibGUgbmFtaW5nIG5vdGU6CkFzIGJlc3QgeW91IGNhbiwgaXQgaXMgYSBnb29kIGlkZWEgdG8gbWFrZSB5b3VyIHZhcmlhYmxlIG5hbWVzIGluZm9ybWF0aXZlIChlLmcuIGB4YCBkb2Vzbid0IG1lYW4gYW55dGhpbmcsIGJ1dCBgc2FuZHdpY2hfcHJpY2VgIGlzIG1lYW5pbmdmdWwuLi4gaWYgd2UncmUgdGFsa2luZyBhYm91dCB0aGUgY29zdCBvZiBzYW5kd2ljaGVzLCB0aGF0IGlzLi4pLiAKCiMjIyBDb21tZW50cwoKQXJndWFibHkgdGhlIF9fbW9zdCBpbXBvcnRhbnRfXyBhc3BlY3Qgb2YgeW91ciBjb2RpbmcgaXMgY29tbWVudHM6IFNtYWxsIHBpZWNlcyBvZiBleHBsYW5hdG9yeSB0ZXh0IHlvdSBsZWF2ZSBpbiB5b3VyIGNvZGUgdG8gZXhwbGFpbiB3aGF0IHRoZSBjb2RlIGlzIGRvaW5nIGFuZC9vciBsZWF2ZSBub3RlcyB0byB5b3Vyc2VsZiBvciBvdGhlcnMuIApDb21tZW50cyBhcmUgaW52YWx1YWJsZSBmb3IgY29tbXVuaWNhdGluZyB5b3VyIGNvZGUgdG8gb3RoZXJzLCBidXQgdGhleSBhcmUgbW9zdCBpbXBvcnRhbnQgZm9yICoqRnV0dXJlIFlvdSoqLiAKRnV0dXJlIFlvdSBjb21lcyBpbnRvIGV4aXN0ZW5jZSBhYm91dCBvbmUgc2Vjb25kIGFmdGVyIHlvdSB3cml0ZSBjb2RlLCBhbmQgaGFzIG5vIGlkZWEgd2hhdCBvbiBlYXJ0aCBQYXN0IFlvdSB3YXMgdGhpbmtpbmcuIAoKQ29tbWVudHMgaW4gUiBjb2RlIGFyZSBpbmRpY2F0ZWQgd2l0aCBwb3VuZCBzaWducyAoKmFrYSogaGFzaHRhZ3MsIG9jdG90aG9ycHMpLiBSIHdpbGwgX2lnbm9yZV8gYW55IHRleHQgaW4gYSBsaW5lIGFmdGVyIHRoZSBwb3VuZCBzaWduLCBzbyB5b3UgY2FuIHB1dCB3aGF0ZXZlciB0ZXh0IHlvdSBsaWtlIHRoZXJlLgoKYGBge3IgY29tbWVudHN9CjIyLzcgIyBub3QgcXVpdGUgcGkKCiMgSWYgd2UgbmVlZCBhIGJldHRlciBhcHByb3hpbWF0aW9uIG9mIHBpLCB3ZSBjYW4gdXNlIEV1bGVyJ3MgZm9ybXVsYQojIFRoaXMgdXNlcyBhdGFuKCksIHdoaWNoIGNhbGN1bGF0ZXMgYXJjdGFuZ2VudC4KMjAgKiBhdGFuKDEvNykgKyA4ICogYXRhbigzLzc5KSAKYGBgCgpIZWxwIG91dCBGdXR1cmUgWW91IGJ5IGFkZGluZyBsb3RzIG9mIGNvbW1lbnRzISAKRnV0dXJlIFlvdSBuZXh0IHdlZWsgdGhpbmtzIFRvZGF5IFlvdSBpcyBhbiBpZGlvdCwgYW5kIHRoZSBvbmx5IHdheSB5b3UgY2FuIGNvbnZpbmNlIEZ1dHVyZSBZb3UgdGhhdCBUb2RheSBZb3UgaXMgcmVhc29uYWJseSBjb21wZXRlbnQgaXMgYnkgYWRkaW5nIGNvbW1lbnRzIGluIHlvdXIgY29kZSBleHBsYWluaW5nIHdoeSBUb2RheSBZb3UgaXMgYWN0dWFsbHkgbm90IHNvIGJhZC4KCiMjIEZ1bmN0aW9ucwpXZSBjYW4gdXNlIHByZS1idWlsdCBjb21wdXRhdGlvbiBtZXRob2RzIGNhbGxlZCAiZnVuY3Rpb25zIiBmb3Igb3RoZXIgb3BlcmF0aW9ucy4gCkZ1bmN0aW9ucyBoYXZlIHRoZSBmb2xsb3dpbmcgZm9ybWF0LCB3aGVyZSB0aGUgX2FyZ3VtZW50XyBpcyB0aGUgaW5mb3JtYXRpb24gd2UgYXJlIHByb3ZpZGluZyB0byB0aGUgZnVuY3Rpb24gZm9yIGl0IHRvIHJ1bi4gCkFuIGV4YW1wbGUgb2YgdGhpcyB3YXMgdGhlIGBhdGFuKClgIGZ1bmN0aW9uIHVzZWQgYWJvdmUuCgpgYGByCmZ1bmN0aW9uX25hbWUoYXJndW1lbnQpCmBgYAoKVG8gbGVhcm4gYWJvdXQgZnVuY3Rpb25zLCB3ZSdsbCBleGFtaW5lIG9uZSBjYWxsZWQgYGxvZygpYCBmaXJzdC4gCgpUbyBrbm93IHdoYXQgYSBmdW5jdGlvbiBkb2VzIGFuZCBob3cgdG8gdXNlIGl0LCB1c2UgdGhlIHF1ZXN0aW9uIG1hcmsgd2hpY2ggd2lsbCByZXZlYWwgZG9jdW1lbnRhdGlvbiBpbiB0aGUgKipoZWxwIHBhbmUqKjogYD9sb2dgCiFbcmhlbHBdKHNjcmVlbnNob3RzL3JoZWxwLWxvZy5wbmcpIAoKVGhlIGRvY3VtZW50YXRpb24gdGVsbHMgdXMgdGhhdCBgbG9nKClgIGlzIGRlcml2ZWQgZnJvbSBge2Jhc2V9YCwgbWVhbmluZyBpdCBpcyBhIGZ1bmN0aW9uIHRoYXQgaXMgcGFydCBvZiBiYXNlIFIuIApJdCBwcm92aWRlcyBhIGJyaWVmIGRlc2NyaXB0aW9uIG9mIHdoYXQgdGhlIGZ1bmN0aW9uIGRvZXMgYW5kIHNob3dzIHNldmVyYWwgZXhhbXBsZXMgb2YgdG8gaG93IHVzZSBpdC4KCkluIHBhcnRpY3VsYXIsIHRoZSBkb2N1bWVudGF0aW9uIHRlbGxzIHVzIGFib3V0IHdoYXQgYXJndW1lbnQocykgdG8gcHJvdmlkZToKCisgVGhlIGZpcnN0IF9yZXF1aXJlZF8gYXJndW1lbnQgaXMgdGhlIHZhbHVlIHdlJ2QgbGlrZSB0byB0YWtlIHRoZSBsb2cgb2YsIGJ5IGRlZmF1bHQgaXRzIF9uYXR1cmFsIGxvZ18KKyBUaGUgc2Vjb25kIF9vcHRpb25hbF8gYXJndW1lbnQgY2FuIHNwZWNpZnkgYSBkaWZmZXJlbnQgYmFzZSByYXRoZXIgdGhhbiB0aGUgZGVmYXVsdCBgZWAuCgpGdW5jdGlvbnMgYWxzbyBfcmV0dXJuXyB2YWx1ZXMgZm9yIHVzIHRvIHVzZS4gCkluIHRoZSBjYXNlIG9mIGBsb2coKWAsIHRoZSByZXR1cm5lZCB2YWx1ZSBpcyB0aGUgbG9nJ2QgdmFsdWUgdGhlIGZ1bmN0aW9uIGNvbXB1dGVkLgoKYGBge3IgbG9nfQpsb2coNzMpCmBgYAoKSGVyZSB3ZSBjYW4gc3BlY2lmeSBhbiBfYXJndW1lbnRfIG9mIGBiYXNlYCB0byBjYWxjdWxhdGUgbG9nIGJhc2UgMy4gCgpgYGB7ciBsb2czfQpsb2coODEsIGJhc2UgPSAzKQpgYGAKCklmIHdlIGRvbid0IHNwZWNpZnkgdGhlIF9hcmd1bWVudF8gbmFtZXMsIGl0IGFzc3VtZXMgdGhleSBhcmUgaW4gdGhlIG9yZGVyIHRoYXQgYGxvZ2AgZGVmaW5lcyB0aGVtLiAKU2VlIGA/bG9nYCB0byBzZWUgbW9yZSBhYm91dCBpdHMgYXJndW1lbnRzLiAKCmBgYHtyIGxvZzIsIGxpdmUgPSBUUlVFfQpsb2coOCwgMikKYGBgCgpXZSBjYW4gc3dpdGNoIHRoZSBvcmRlciBpZiB3ZSBzcGVjaWZ5IHRoZSBhcmd1bWVudCBuYW1lcy4gCgpgYGB7ciBsb2ctb3JkZXJ9CmxvZyhiYXNlID0gMTAsIHggPSA0MzQyKQpgYGAKCldlIGNhbiBhbHNvIHByb3ZpZGUgdmFyaWFibGVzIGFzIGFyZ3VtZW50cyBpbiB0aGUgc2FtZSB3YXkgYXMgdGhlIHJhdyB2YWx1ZXMuIAoKYGBge3IgbG9nLXZhcmlhYmxlfQptZWFuaW5nIDwtIDQyCmxvZyhtZWFuaW5nKQpgYGAKCiMjIFdvcmtpbmcgd2l0aCB2YXJpYWJsZXMKCiMjIyBWYXJpYWJsZSBUeXBlcwoKVmFyaWFibGUgdHlwZXMgaW4gUiBjYW4gc29tZXRpbWVzIGJlIF9jb2VyY2VkXyAoY29udmVydGVkKSBmcm9tIG9uZSB0eXBlIHRvIGFub3RoZXIuCgpgYGB7cn0KIyBEZWZpbmUgYSB2YXJpYWJsZSB3aXRoIGEgbnVtYmVyCnggPC0gMTUKYGBgCgpUaGUgZnVuY3Rpb24gYGNsYXNzKClgIHdpbGwgdGVsbCB1cyB0aGUgdmFyaWFibGUncyB0eXBlLgoKYGBge3J9CmNsYXNzKHgpCmBgYAoKTGV0J3MgY29lcmNlIGl0IHRvIGEgY2hhcmFjdGVyLiAKCmBgYHtyfQp4IDwtIGFzLmNoYXJhY3Rlcih4KQpjbGFzcyh4KQpgYGAKClNlZSBpdCBub3cgaGFzIHF1b3RlcyBhcm91bmQgaXQ/IEl0J3Mgbm93IGEgY2hhcmFjdGVyIGFuZCB3aWxsIGJlaGF2ZSBhcyBzdWNoLgoKYGBge3J9CngKYGBgCgpVc2UgdGhpcyBjaHVuayB0byB0cnkgdG8gcGVyZm9ybSBjYWxjdWxhdGlvbnMgd2l0aCBgeGAsIG5vdyB0aGF0IGl0IGlzIGEgY2hhcmFjdGVyLCB3aGF0IGhhcHBlbnM/IAoKYGBge3IgbGl2ZSA9IFRSVUV9CiMgVHJ5IHRvIHBlcmZvcm0gY2FsY3VsYXRpb25zIG9uIGB4YApgYGAKCkJ1dCB3ZSBjYW4ndCBjb2VyY2UgZXZlcnl0aGluZzoKCmBgYHtyfQojIExldCdzIGNyZWF0ZSBhIGNoYXJhY3RlciB2YXJpYWJsZQp4IDwtICJsb29rIGF0IG15IGNoYXJhY3RlciB2YXJpYWJsZSIKYGBgCgpMZXQncyB0cnkgbWFraW5nIHRoaXMgYSBudW1lcmljIHZhcmlhYmxlOgoKYGBge3IgY29lcmNlLWNoYXIsIGVycm9yPVRSVUV9CnggPC0gYXMubnVtZXJpYyh4KQpgYGAKClByaW50IG91dCBgeGAuCgpgYGB7cn0KeApgYGAKClIgaXMgdGVsbGluZyB1cyBpdCBkb2Vzbid0IGtub3cgaG93IHRvIGNvbnZlcnQgdGhpcyB0byBhIG51bWVyaWMgdmFyaWFibGUsIHNvIGl0IGhhcyByZXR1cm5lZCBgTkFgIGluc3RlYWQuCgpGb3IgcmVmZXJlbmNlLCBoZXJlJ3MgYSBzdW1tYXJ5IG9mIHNvbWUgb2YgdGhlIG1vc3QgaW1wb3J0YW50IHZhcmlhYmxlIHR5cGVzLiAKCnwgVmFyaWFibGUgVHlwZSB8IERlZmluaXRpb24gfCBFeGFtcGxlcyB8IENvZXJjaW9uIHwKfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS18LS0tLS0tLS0tLXwgLS0tLS0tLS18CnwgYG51bWVyaWNgICAgICAgIHwgQW55IG51bWJlciB2YWx1ZSB8IGA1YDxicj5gNy41YCA8YnI+YC0xYHwgYGFzLm51bWVyaWMoKWAKfCBgaW50ZWdlcmAgICAgICAgfCBBbnkgX3dob2xlXyBudW1iZXIgdmFsdWUgKG5vIGRlY2ltYWxzKSB8IGA1YCA8YnI+IGAtMTAwYCB8IGBhcy5pbnRlZ2VyKClgCnxgY2hhcmFjdGVyYCAgICAgIHwgQW55IGNvbGxlY3Rpb24gb2YgY2hhcmFjdGVycyBkZWZpbmVkIHdpdGhpbiBfcXVvdGF0aW9uIG1hcmtzXy4gQWxzbyBrbm93biBhcyBhICJzdHJpbmciLiB8IGAiYSJgIChhIHNpbmdsZSBsZXR0ZXIpIDxicj5gInN0cmluZ29mbGV0dGVycyJgIChhIHdob2xlIGJ1bmNoIG9mIGNoYXJhY3RlcnMgcHV0IHRvZ2V0aGVyIGFzIG9uZSkgPGJyPiBgInN0cmluZyBvZiBsZXR0ZXJzIGFuZCBzcGFjZXMiYCA8YnI+IGAiNSJgIDxicj4gYCdzaW5nbGUgcXVvdGVzIGFyZSBhbHNvIGdvb2QnYCB8IGBhcy5jaGFyYWN0ZXIoKWAKfGBsb2dpY2FsYCAgICAgIHwgQSB2YWx1ZSBvZiBgVFJVRWAsIGBGQUxTRWAsIG9yIGBOQWAgfCBgVFJVRWAgPGJyPiBgRkFMU0VgIDxicj4gYE5BYCAobm90IGRlZmluZWQpIHwgYGFzLmxvZ2ljYWwoKWAgCnxgZmFjdG9yYCAgICAgICB8IEEgc3BlY2lhbCB0eXBlIG9mIHZhcmlhYmxlIHRoYXQgZGVub3RlcyBzcGVjaWZpYyBjYXRlZ29yaWVzIG9mIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgfCAoc3RheSB0dW5lZC4uKSB8IGBhcy5mYWN0b3IoKWAKCiMjIyBWZWN0b3JzCgpZb3Ugd2lsbCBoYXZlIG5vdGljZWQgdGhhdCBhbGwgeW91ciBjb21wdXRhdGlvbnMgdGVuZCB0byBwb3AgdXAgd2l0aCBhIGBbMV1gIHByZWNlZGluZyB0aGVtIGluIFIncyBvdXRwdXQuIApUaGlzIGlzIGJlY2F1c2UsIGluIGZhY3QsIGFsbCAob2sgbW9zdGx5IGFsbCkgdmFyaWFibGVzIGFyZSBfYnkgZGVmYXVsdF8gIHZlY3RvcnMsIGFuZCBvdXIgYW5zd2VycyBhcmUgdGhlIGZpcnN0IChpbiB0aGVzZSBjYXNlcyBvbmx5KSB2YWx1ZSBpbiB0aGUgdmVjdG9yLiAKQXMgdmVjdG9ycyBnZXQgbG9uZ2VyLCBuZXcgaW5kZXggaW5kaWNhdG9ycyB3aWxsIGFwcGVhciBhdCB0aGUgc3RhcnQgb2YgbmV3IGxpbmVzLiAKCmBgYHtyfQojIFRoaXMgaXMgYWN0dWFsbHkgYW4gdmVjdG9yIHRoYXQgaGFzIG9uZSBpdGVtIGluIGl0Lgp4IDwtIDcKYGBgCgpgYGB7ciB2ZWN0b3ItbGVuZ3RofQojIFRoZSBsZW5ndGgoKSBmdW5jdGlvbnMgdGVsbHMgdXMgaG93IGxvbmcgYW4gdmVjdG9yIGlzOgpsZW5ndGgoeCkKYGBgCgpXZSBjYW4gZGVmaW5lIHZlY3RvcnMgd2l0aCB0aGUgZnVuY3Rpb24gYGMoKWAsIHdoaWNoIHN0YW5kcyBmb3IgImNvbWJpbmUiLiAKVGhpcyBmdW5jdGlvbiB0YWtlcyBhIGNvbW1hLXNlcGFyYXRlZCBzZXQgb2YgdmFsdWVzIHRvIHBsYWNlIGluIHRoZSB2ZWN0b3IsIGFuZCByZXR1cm5zIHRoZSB2ZWN0b3IgaXRzZWxmOgoKYGBge3IgbWFrZS12ZWN0b3J9Cm15X251bWVyaWNfdmVjdG9yIDwtIGMoMSwgMSwgMiwgMywgNSwgOCwgMTMsIDIxKQpteV9udW1lcmljX3ZlY3RvcgpgYGAKCldlIGNhbiBidWlsZCBvbiB2ZWN0b3JzIGluIHBsYWNlIGJ5IHJlZGVmaW5pbmcgdGhlbToKCmBgYHtyIGZpYmJvbmFjY2ksIGxpdmUgPSBUUlVFfQojIGFkZCB0aGUgbmV4dCB0d28gRmlib25hY2NpIG51bWJlcnMgdG8gdGhlIHNlcmllcy4KbXlfbnVtZXJpY192ZWN0b3IgPC0gYyhteV9udW1lcmljX3ZlY3RvciwgMzQsIDU1KQpteV9udW1lcmljX3ZlY3RvcgpgYGAKCldlIGNhbiBwdWxsIG91dCBzcGVjaWZpYyBpdGVtcyBmcm9tIGFuIHZlY3RvciB1c2luZyBhIHByb2Nlc3MgY2FsbGVkIF9pbmRleGluZ18sIHdoaWNoIHVzZXMgYnJhY2tldHMgYFtdYCB0byBzcGVjaWZ5IHRoZSBwb3NpdGlvbiBvZiBhbiBpdGVtLiAKCmBgYHtyIHN1YnNldDF9CiMgR3JhYiB0aGUgZm91cnRoIHZhbHVlIGZyb20gbXlfbnVtZXJpY192ZWN0b3IKIyBUaGlzIGdpdmVzIHVzIGFuIHZlY3RvciBvZiBsZW5ndGggMSAKbXlfbnVtZXJpY192ZWN0b3JbNF0KYGBgCgpDb2xvbnMgYXJlIGFsc28gYSBuaWNlIHdheSB0byBxdWlja2x5IG1ha2Ugb3JkZXJlZCBudW1lcmljIHZlY3RvcnMKVXNlIGEgY29sb24gdG8gc3BlY2lmeSBhbiBpbmNsdXNpdmUgcmFuZ2Ugb2YgaW5kaWNlcwpUaGlzIHdpbGwgcmV0dXJuIGFuIHZlY3RvciB3aXRoIDIsIDMsIDQsIGFuZCA1LgoKYGBge3Igc3Vic2V0LW1hbnl9Cm15X251bWVyaWNfdmVjdG9yWzI6NV0KYGBgCgpPbmUgbWFqb3IgYmVuZWZpdCBvZiB2ZWN0b3JzIGlzIHRoZSBjb25jZXB0IG9mICoqdmVjdG9yaXphdGlvbioqLCB3aGVyZSBSIGJ5IGRlZmF1bHQgcGVyZm9ybXMgb3BlcmF0aW9ucyBvbiB0aGUgX2VudGlyZSB2ZWN0b3IgYXQgb25jZV8uIApGb3IgZXhhbXBsZSwgd2UgY2FuIGdldCB0aGUgbG9nIG9mIGFsbCBudW1iZXJzIDEtMjAgd2l0aCBhIHNpbmdsZSwgc2ltcGxlIGNhbGwsIGFuZCBtb3JlIQoKYGBge3IgdmVjdG9yaXplfQp2YWx1ZXNfMV90b18yMCA8LSAxOjIwCmBgYAoKCmBgYHtyIHZlY3Rvcml6ZS1sb2csIGxpdmUgPSBUUlVFfQojIGNhbGN1bGF0ZSB0aGUgbG9nIG9mIHZhbHVlc18xX3RvXzIwCmxvZyh2YWx1ZXNfMV90b18yMCkKYGBgCgpGaW5hbGx5LCB3ZSBjYW4gYXBwbHkgbG9naWNhbCBleHByZXNzaW9ucyB0byB2ZWN0b3JzLCBqdXN0IGFzIHdlIGNhbiBkbyBmb3Igc2luZ2xlIHZhbHVlcy4KVGhlIG91dHB1dCBoZXJlIGlzIGEgbG9naWNhbCB2ZWN0b3IgdGVsbGluZyB1cyB3aGV0aGVyIGVhY2ggdmFsdWUgaW4gZXhhbXBsZV92ZWN0b3IgaXMgVFJVRSBvciBGQUxTRQoKYGBge3IgdmVjdG9yLWNvbXBhcmV9CiMgV2hpY2ggdmFsdWVzIGFyZSA8PSAzPwp2YWx1ZXNfMV90b18yMCA8PSAzCmBgYAoKVGhlcmUgYXJlIHNldmVyYWwga2V5IGZ1bmN0aW9ucyB3aGljaCBjYW4gYmUgdXNlZCBvbiB2ZWN0b3JzIGNvbnRhaW5pbmcgbnVtZXJpYyB2YWx1ZXMsIHNvbWUgb2Ygd2hpY2ggYXJlIGJlbG93LgoKKyBgbWVhbigpYDogVGhlIGF2ZXJhZ2UgdmFsdWUgaW4gdGhlIHZlY3RvcgorIGBtaW4oKWA6IFRoZSBtaW5pbXVtIHZhbHVlIGluIHRoZSB2ZWN0b3IKKyBgbWF4KClgOiBUaGUgbWF4aW11bSB2YWx1ZSBpbiB0aGUgdmVjdG9yCisgYHN1bSgpYDogVGhlIHN1bSBvZiBhbGwgdmFsdWVzIGluIHRoZSB2ZWN0b3IKCldlIGNhbiB0cnkgb3V0IHRoZXNlIGZ1bmN0aW9ucyBvbiB0aGUgdmVjdG9yIGB2YWx1ZXNfMV90b18yMGAgd2UndmUgY3JlYXRlZC4gCgpgYGB7ciB2ZWN0b3ItZnVuY3N9Cm1lYW4odmFsdWVzXzFfdG9fMjApCgojIFRyeSBvdXQgc29tZSBvZiB0aGUgb3RoZXIgZnVuY3Rpb25zIHdlJ3ZlIGxpc3RlZCBhYm92ZSAKCmBgYAoKIyMjIEEgbm90ZSBvbiB2YXJpYWJsZSBuYW1pbmcKCldlIGhhdmUgbGVhcm5lZCBmdW5jdGlvbnMgc3VjaCBhcyBgY2AsIGBsZW5ndGhgLCBgc3VtYCwgYW5kIGV0Yy4gCkltYWdpbmUgZGVmaW5pbmcgYSB2YXJpYWJsZSBjYWxsZWQgYGNgOiBUaGlzIHdpbGwgd29yaywgYnV0IGl0IHdpbGwgbGVhZCB0byBhIApsb3Qgb2YgdW5pbnRlbmRlZCBidWdzLCBzbyBpdCdzIGJlc3QgdG8gYXZvaWQgdGhpcy4gCgojIyMgVGhlIGAlaW4lYCBsb2dpY2FsIG9wZXJhdG9yIAoKYCVpbiVgIGlzIHVzZWZ1bCBmb3IgZGV0ZXJtaW5pbmcgd2hldGhlciBhIGdpdmVuIGl0ZW0ocykgYXJlIGluIGFuIHZlY3Rvci4KCmBgYHtyIGluLW9wZXJhdG9yfQojIGlzIGA3YCBpbiBvdXIgdmVjdG9yPyAKNyAlaW4lIHZhbHVlc18xX3RvXzIwCmBgYAoKYGBge3IgaW4yLCBsaXZlID0gVFJVRX0KIyBpcyBgNTBgIGluIG91ciB2ZWN0b3I/IAo1MCAlaW4lIHZhbHVlc18xX3RvXzIwCmBgYAoKV2UgY2FuIHRlc3QgYSB2ZWN0b3Igb2YgdmFsdWVzIGJlaW5nIHdpdGhpbiBhbm90aGVyIHZlY3RvciBvZiB2YWx1ZXMuIAoKYGBge3IgdmVjdG9yLWluLCBsaXZlID0gVFJVRX0KcXVlc3Rpb25fdmFsdWVzIDwtIGMoMTozLCA3LCA1MCkKIyBBcmUgdGhlc2UgdmFsdWVzIGluIG91ciB2ZWN0b3I/CnF1ZXN0aW9uX3ZhbHVlcyAlaW4lIHZhbHVlc18xX3RvXzIwCmBgYAoKIyMgRGF0YSBmcmFtZXMKCl9EYXRhIGZyYW1lcyBhcmUgb25lIG9mIHRoZSBtb3N0IHVzZWZ1bCB0b29scyBmb3IgZGF0YSBhbmFseXNpcyBpbiBSLl8gClRoZXkgYXJlIHRhYmxlcyB3aGljaCBjb25zaXN0IG9mIHJvd3MgYW5kIGNvbHVtbnMsIG11Y2ggbGlrZSBhIF9zcHJlYWRzaGVldF8uIApFYWNoIGNvbHVtbiBpcyBhIHZhcmlhYmxlIHdoaWNoIGJlaGF2ZXMgYXMgYSBfdmVjdG9yXywgYW5kIGVhY2ggcm93IGlzIGFuIG9ic2VydmF0aW9uLiAKV2Ugd2lsbCBiZWdpbiBvdXIgZXhwbG9yYXRpb24gd2l0aCBkYXRhc2V0IG9mIG1lYXN1cmVtZW50cyBmcm9tIHRocmVlIHBlbmd1aW4gc3BlY2llcyBtZWFzdXJlZCwgd2hpY2ggd2UgY2FuIGZpbmQgaW4gdGhlIFtgcGFsbWVycGVuZ3VpbnNgIHBhY2thZ2VdKGh0dHBzOi8vYWxsaXNvbmhvcnN0LmdpdGh1Yi5pby9wYWxtZXJwZW5ndWlucy8pLiAKV2UnbGwgdGFsayBtb3JlIGFib3V0IHBhY2thZ2VzIHNvb24hClRvIHVzZSB0aGlzIGRhdGFzZXQsIHdlIHdpbGwgbG9hZCBpdCBmcm9tIHRoZSBgcGFsbWVycGVuZ3VpbnNgIHBhY2thZ2UgdXNpbmcgYSBgOjpgIChtb3JlIG9uIHRoaXMgbGF0ZXIpIGFuZCBhc3NpZ24gaXQgdG8gYSB2YXJpYWJsZSBuYW1lZCBgcGVuZ3VpbnNgIGluIG91ciBjdXJyZW50IGVudmlyb25tZW50LgoKYGBge3IgcGVuZ3Vpbi1saWJyYXJ5fQpwZW5ndWlucyA8LSBwYWxtZXJwZW5ndWluczo6cGVuZ3VpbnMKYGBgCgohW2RyYXdpbmdzIG9mIHBlbmd1aW4gc3BlY2llc10oZGlhZ3JhbXMvbHRlcl9wZW5ndWlucy5wbmcpIEFydHdvcmsgYnkgW0BhbGxpc29uX2hvcnN0XShodHRwczovL3R3aXR0ZXIuY29tL2FsbGlzb25faG9yc3QpCgojIyMgRXhwbG9yaW5nIGRhdGEgZnJhbWVzCgpUaGUgZmlyc3Qgc3RlcCB0byB1c2luZyBhbnkgZGF0YSBpcyB0byBsb29rIGF0IGl0ISEhIApSU3R1ZGlvIGNvbnRhaW5zIGEgc3BlY2lhbCBmdW5jdGlvbiBgVmlldygpYCB3aGljaCBhbGxvd3MgeW91IHRvIGxpdGVyYWxseSB2aWV3IGEgdmFyaWFibGUuCllvdSBjYW4gYWxzbyBjbGljayBvbiB0aGUgb2JqZWN0IGluIHRoZSBlbnZpcm9ubWVudCBwYW5lIHRvIHNlZSBpdHMgb3ZlcmFsbCBwcm9wZXJ0aWVzLCBvciBjbGljayB0aGUgdGFibGUgaWNvbiBvbiB0aGUgb2JqZWN0J3Mgcm93IHRvIGF1dG9tYXRpY2FsbHkgdmlldyB0aGUgdmFyaWFibGUuIAoKU29tZSB1c2VmdWwgZnVuY3Rpb25zIGZvciBleHBsb3Jpbmcgb3VyIGRhdGEgZnJhbWUgaW5jbHVkZToKCisgYGhlYWQoKWAgdG8gc2VlIHRoZSBmaXJzdCA2IHJvd3Mgb2YgYSBkYXRhIGZyYW1lLiBBZGRpdGlvbmFsIGFyZ3VtZW50cyBzdXBwbGllZCBjYW4gY2hhbmdlIHRoZSBudW1iZXIgb2Ygcm93cy4KKyBgdGFpbCgpYCB0byBzZWUgdGhlIGxhc3QgNiByb3dzIG9mIGEgZGF0YSBmcmFtZS4gQWRkaXRpb25hbCBhcmd1bWVudHMgc3VwcGxpZWQgY2FuIGNoYW5nZSB0aGUgbnVtYmVyIG9mIHJvd3MuCisgYG5hbWVzKClgIHRvIHNlZSB0aGUgY29sdW1uIG5hbWVzIG9mIHRoZSBkYXRhIGZyYW1lLgorIGBucm93KClgIHRvIHNlZSBob3cgbWFueSByb3dzIGFyZSBpbiB0aGUgZGF0YSBmcmFtZQorIGBuY29sKClgIHRvIHNlZSBob3cgbWFueSBjb2x1bW5zIGFyZSBpbiB0aGUgZGF0YSBmcmFtZS4KCldlIGNhbiBhZGRpdGlvbmFsbHkgZXhwbG9yZSBfb3ZlcmFsbCBwcm9wZXJ0aWVzXyBvZiB0aGUgZGF0YSBmcmFtZSB3aXRoIHR3byBkaWZmZXJlbnQgZnVuY3Rpb25zOiBgc3VtbWFyeSgpYCBhbmQgYHN0cigpYC4KClRoaXMgcHJvdmlkZXMgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciBlYWNoIGNvbHVtbjoKCmBgYHtyIHBlbmd1aW5zLXN1bW1hcnl9CnN1bW1hcnkocGVuZ3VpbnMpCmBgYAoKVGhpcyBwcm92aWRlcyBhIHNob3J0IHZpZXcgb2YgdGhlICoqc3RyKip1Y3R1cmUgYW5kIGNvbnRlbnRzIG9mIHRoZSBkYXRhIGZyYW1lLgoKYGBge3IgcGVuZ3VpbnMtc3RyfQpzdHIocGVuZ3VpbnMpCmBgYAoKWW91J2xsIG5vdGljZSB0aGF0IHRoZSBjb2x1bW4gYHNwZWNpZXNgIGlzIGEgX2ZhY3Rvcl86IFRoaXMgaXMgYSBzcGVjaWFsIHR5cGUgb2YgY2hhcmFjdGVyIHZhcmlhYmxlIHRoYXQgcmVwcmVzZW50cyBkaXN0aW5jdCBjYXRlZ29yaWVzIGtub3duIGFzICJsZXZlbHMiLiAKV2UgaGF2ZSBsZWFybmVkIGhlcmUgdGhhdCB0aGVyZSBhcmUgdGhyZWUgbGV2ZWxzIGluIHRoZSBgc3BlY2llc2AgY29sdW1uOiBBZGVsaWUsIENoaW5zdHJhcCwgYW5kIEdlbnRvby4KV2UgbWlnaHQgd2FudCB0byBleHBsb3JlIGluZGl2aWR1YWwgY29sdW1ucyBvZiB0aGUgZGF0YSBmcmFtZSBtb3JlIGluLWRlcHRoLiAKV2UgY2FuIGV4YW1pbmUgaW5kaXZpZHVhbCBjb2x1bW5zIHVzaW5nIHRoZSBkb2xsYXIgc2lnbiBgJGAgdG8gc2VsZWN0IG9uZSBieSBuYW1lOgoKYGBge3IgcGVuZ3VpbnMtc3Vic2V0fQojIEV4dHJhY3QgYmlsbF9sZW5ndGhfbW0gYXMgYSB2ZWN0b3IKcGVuZ3VpbnMkYmlsbF9sZW5ndGhfbW0KCiMgaW5kZXhpbmcgb3BlcmF0b3JzIGNhbiBiZSB1c2VkIG9uIHRoZXNlIHZlY3RvcnMgdG9vCnBlbmd1aW5zJGJpbGxfbGVuZ3RoX21tWzE6MTBdCmBgYAoKV2UgY2FuIHBlcmZvcm0gb3VyIHJlZ3VsYXIgdmVjdG9yIG9wZXJhdGlvbnMgb24gY29sdW1ucyBkaXJlY3RseS4KCmBgYHtyIHBlbmd1aW5zLWNvbC1tZWFuLCBsaXZlID0gVFJVRX0KIyBjYWxjdWxhdGUgdGhlIG1lYW4gb2YgdGhlIGJpbGxfbGVuZ3RoX21tIGNvbHVtbgptZWFuKHBlbmd1aW5zJGJpbGxfbGVuZ3RoX21tLAogICAgIG5hLnJtID0gVFJVRSkgIyByZW1vdmUgbWlzc2luZyB2YWx1ZXMgYmVmb3JlIGNhbGN1bGF0aW5nIHRoZSBtZWFuCmBgYAoKV2UgY2FuIGFsc28gY2FsY3VsYXRlIHRoZSBmdWxsIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgYSBzaW5nbGUgY29sdW1uIGRpcmVjdGx5LiAKCmBgYHtyIHBlbmd1aW5zLWNvbC1zdW1tYXJ5LCBsaXZlID0gVFJVRX0KIyBzaG93IGEgc3VtbWFyeSBvZiB0aGUgYmlsbF9sZW5ndGhfbW0gY29sdW1uCnN1bW1hcnkocGVuZ3VpbnMkYmlsbF9sZW5ndGhfbW0pCmBgYAoKRXh0cmFjdCBgc3BlY2llc2AgYXMgYSB2ZWN0b3IgYW5kIHN1YnNldCBpdCB0byBzZWUgYSBwcmV2aWV3LgoKYGBge3IgcGVuZ3VpbnMtY29sLXN1YnNldCwgbGl2ZSA9IFRSVUV9CiMgZ2V0IHRoZSBmaXJzdCAxMCB2YWx1ZXMgb2YgdGhlIHNwZWNpZXMgY29sdW1uCnBlbmd1aW5zJHNwZWNpZXNbMToxMF0KYGBgCgpBbmQgdmlldyBpdHMgX2xldmVsc18gd2l0aCB0aGUgYGxldmVscygpYCBmdW5jdGlvbi4KCmBgYHtyIHBlbmd1aW4tbGV2ZWxzfQpsZXZlbHMocGVuZ3VpbnMkc3BlY2llcykKYGBgCgojIyBGaWxlcyBhbmQgZGlyZWN0b3JpZXMKCkluIG1hbnkgc2l0dWF0aW9ucywgd2Ugd2lsbCBiZSByZWFkaW5nIGluIHRhYnVsYXIgZGF0YSBmcm9tIGEgZmlsZSBhbmQgdXNpbmcgaXQgYXMgYSBkYXRhIGZyYW1lLiAKVG8gcHJhY3RpY2UsIHdlIHdpbGwgcmVhZCBpbiBhIGZpbGUgd2Ugd2lsbCBiZSB1c2luZyBpbiB0aGUgbmV4dCBub3RlYm9vayBhcyB3ZWxsLCBgZ2VuZV9yZXN1bHRzX0dTRTQ0OTcxLnRzdmAsIGluIHRoZSBgZGF0YWAgZm9sZGVyLiAKRmlsZSBwYXRocyBhcmUgcmVsYXRpdmUgdG8gdGhlIGxvY2F0aW9uIHdoZXJlIHRoaXMgbm90ZWJvb2sgZmlsZSAoLlJtZCkgaXMgc2F2ZWQuCgpIZXJlIHdlIHdpbGwgdXNlIGEgZnVuY3Rpb24sIGByZWFkX3RzdigpYCBmcm9tIHRoZSBgcmVhZHJgIHBhY2thZ2UuCkJlZm9yZSB3ZSBhcmUgYWJsZSB0byB1c2UgdGhlIGZ1bmN0aW9uLCB3ZSBoYXZlIHRvIGxvYWQgdGhlIHBhY2thZ2UgdXNpbmcgYGxpYnJhcnkoKWAuIAoKYGBge3IgcmVhZHJ9CmxpYnJhcnkocmVhZHIpCmBgYAoKYGZpbGUucGF0aCgpYCBjcmVhdGVzIGEgcHJvcGVybHkgZm9ybWF0dGVkIGZpbGUgcGF0aCBieSBhZGRpbmcgYSBwYXRoIHNlcGFyYXRvciAoYC9gIG9uIE1hYyBhbmQgTGludXggb3BlcmF0aW5nIHN5c3RlbXMsIHRoZSBsYXR0ZXIgb2Ygd2hpY2ggaXMgdGhlIG9wZXJhdGluZyBzeXN0ZW0gdGhhdCBvdXIgUlN0dWRpbyBTZXJ2ZXIgcnVucyBvbikgYmV0d2VlbiBzZXBhcmF0ZSBmb2xkZXJzIG9yIGRpcmVjdG9yaWVzLgpCZWNhdXNlIGZpbGUgcGF0aCBzZXBhcmF0b3JzIGNhbiBkaWZmZXIgYmV0d2VlbiB5b3VyIGNvbXB1dGVyIGFuZCB0aGUgY29tcHV0ZXIgb2Ygc29tZW9uZSB3aG8gd2FudHMgdG8gdXNlIHlvdXIgY29kZSwgd2UgdXNlIGBmaWxlLnBhdGgoKWAgaW5zdGVhZCBvZiB0eXBpbmcgb3V0IGAiZGF0YS9nZW5lX3Jlc3VsdHNfR1NFNDQ5NzEudHN2ImAuCkVhY2ggX2FyZ3VtZW50XyB0byBgZmlsZS5wYXRoKClgIGlzIGEgZGlyZWN0b3J5IG9yIGZpbGUgbmFtZS4KWW91J2xsIG5vdGljZSBlYWNoIGFyZ3VtZW50IGlzIGluIHF1b3Rlcywgd2Ugc3BlY2lmeSBgZGF0YWAgZmlyc3QgYmVjYXVzZSB0aGUgZmlsZSwgYGdlbmVfcmVzdWx0c19HU0U0NDk3MS50c3ZgIGlzIGluIHRoZSBgZGF0YWAgZm9sZGVyLiAKCmBgYHtyIGZpbGUucGF0aH0KZmlsZS5wYXRoKCJkYXRhIiwgImdlbmVfcmVzdWx0c19HU0U0NDk3MS50c3YiKQpgYGAKCkFzIHlvdSBjYW4gc2VlIGFib3ZlLCB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcgYGZpbGUucGF0aCgpYCBpcyB0aGF0IGl0IF9jcmVhdGVzIGEgc3RyaW5nXyB3aXRoIGFuIGFjY3VyYXRlbHktZm9ybWF0dGVkIHBhdGggZm9yIHlvdXIgZmlsZSBzeXN0ZW0uClRoaXMgc3RyaW5nIGNhbiBiZSB1c2VkIG1vdmluZyBmb3J3YXJkIHdoZW4geW91IG5lZWQgdG8gcmVmZXIgdG8gdGhlIHBhdGggdG8geW91ciBmaWxlLgpMZXQncyBnbyBhaGVhZCBhbmQgc3RvcmUgdGhpcyBmaWxlIHBhdGggYXMgYSB2YXJpYWJsZSBpbiBvdXIgZW52aXJvbm1lbnQuIAoKYGBge3IgZmlsZS5wYXRoLXZhcmlhYmxlfQpnZW5lX2ZpbGVfcGF0aCA8LSBmaWxlLnBhdGgoImRhdGEiLCAiZ2VuZV9yZXN1bHRzX0dTRTQ0OTcxLnRzdiIpCmBgYAoKTm93IHdlIGFyZSByZWFkeSB0byB1c2UgYHJlYWRfdHN2KClgIHRvIHJlYWQgdGhlIGZpbGUgaW50byBSLgpUaGUgcmVzdWx0aW5nIGRhdGEgZnJhbWUgd2lsbCBiZSBzdG9yZWQgaW4gYSB2YXJpYWJsZSBuYW1lZCBgc3RhdHNfZGZgLgpOb3RlIHRoZSBgPC1gIChhc3NpZ25tZW50IG9wZXJhdG9yISkgaXMgcmVzcG9uc2libGUgZm9yIHNhdmluZyB0aGlzIHRvIG91ciBnbG9iYWwgZW52aXJvbm1lbnQuIAoKYGBge3IgcmVhZC1zdGF0c30KIyByZWFkIGluIHRoZSBmaWxlIGBnZW5lX3Jlc3VsdHNfR1NFNDQ5NzEudHN2YCBmcm9tIHRoZSBkYXRhIGRpcmVjdG9yeQpzdGF0c19kZiA8LSByZWFkX3RzdihnZW5lX2ZpbGVfcGF0aCkKYGBgCgpUYWtlIGEgbG9vayBhdCB5b3VyIGVudmlyb25tZW50IHBhbmVsIHRvIHNlZSB3aGF0IGBzdGF0c19kZmAgbG9va3MgbGlrZS4gCldlIGNhbiBhbHNvIHByaW50IG91dCBhIHByZXZpZXcgb2YgdGhlIGBzdGF0c19kZmAgZGF0YSBmcmFtZSBoZXJlLiAKCmBgYHtyIHNob3ctc3RhdHMsIGxpdmUgPSBUUlVFfQojIGRpc3BsYXkgc3RhdHNfZGYKc3RhdHNfZGYKYGBgCgojIyMgU2Vzc2lvbiBJbmZvCgpBdCB0aGUgZW5kIG9mIGV2ZXJ5IG5vdGVib29rLCB5b3Ugd2lsbCBzZWUgdXMgcHJpbnQgb3V0IGBzZXNzaW9uSW5mb2AuIApUaGlzIGFpZHMgaW4gdGhlIHJlcHJvZHVjaWJpbGl0eSBvZiB5b3VyIGNvZGUgYnkgc2hvd2luZyBleGFjdGx5IHdoYXQgcGFja2FnZXMgCmFuZCB2ZXJzaW9ucyB3ZXJlIGJlaW5nIHVzZWQgdGhlIGxhc3QgdGltZSB0aGUgbm90ZWJvb2sgd2FzIHJ1bi4KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAo=
Comments
Arguably the most important aspect of your coding is comments: Small pieces of explanatory text you leave in your code to explain what the code is doing and/or leave notes to yourself or others. Comments are invaluable for communicating your code to others, but they are most important for Future You. Future You comes into existence about one second after you write code, and has no idea what on earth Past You was thinking.
Comments in R code are indicated with pound signs (aka hashtags, octothorps). R will ignore any text in a line after the pound sign, so you can put whatever text you like there.
Help out Future You by adding lots of comments! Future You next week thinks Today You is an idiot, and the only way you can convince Future You that Today You is reasonably competent is by adding comments in your code explaining why Today You is actually not so bad.