Grace Strobbe
1. The General Structure of an R Notebook
R Notebook files (*.Rmd) allow you to combine text elements with
snippets of code and the outputs generated from said code. There are
three main parts to an R Notebook file, which are introduced in this
section. In addition, each R Notebook automatically generates an *.html
file that provides you with the formatted document including all
components, which you will ultimately submit for your homework.
1.2. Code Chunks
R code chunks are delineated with three ticks (''') at
the beginning and the end, and {r} after the first set of
ticks lets your computer know that you will be using the R programming
language. You can always add a code chunk by clicking “Insert > Code
Chunk > R” above or by clicking the “+C” icon, although we usually
already created all the chunks you will need in the template. Any text
within a code chunk, if written correctly, represents executable code,
which the computer can interpret as a command to perform certain tasks.
You can make your computer execute the code in a chunk by pressing the
small, green play arrow on the top right corner of each chunk, or you
can just highlight the code and press command+enter (control+enter on
PC). When you execute the code, the output will automatically appear
below a chunk. Sometimes you will find us using hash tags
(#) within code chunks. Hash tags “silence” the text that
follows on the same line, such that the computer jumps over that section
when executing the code. That is useful for code annotation, and you
will frequently see us using the hash tags to add further descriptions
or explanations within code chunks.
Pro tip: If you want to execute all code chunks in a document
automatically, you can click “Run > Run All” in the RStudio menu.
1.3. Text
The text in between code snippets is just that: text. We will use
these sections to provide you with background information and discussion
prompts, and you will use these sections to respond to questions and
offer your interpretations of data. Sections where you need to write
something are always highlighted in italics. You can use a
variety of prompts to format your text if you are working with basic
Markdown (see here
for a cheat sheet). Most of you, however, will prefer the text editor
that is implemented in R Studio to format text with the click of a
button.
Pro tip: You can toggle back and forth between source code (with
Markdown formatting) and the WYSIWYG editor (with text formatting
through clicking) by using the Source/Visual buttons in the RStudio
menu
1.4. HTML Preview and Output
As already mentioned, your R Notebook (including text, code chunks,
and the outputs from your code) can be automatically knitted into an
*.html file. You can click “Preview > Preview Notebook” or “Preview
> Knit to HTML” to see the live html version as you are working on
your R Notebook (just make sure to save to update), and you can find the
shareable *.html file in the same folder as your *.Rmd file (same file
name with .nb appended).
Note: Sometime R will prompt you to update some packages in the
Console before you can knit the html file. If it is not working on the
first try, make sure to check for prompts in the Console.
2. Getting Started
2.1. Setting Your Working Directory
Having a well-organized file structure is critical to avoid issues
with coding, because you will frequently read in data files, and you
need to make sure that R knows where to look for those files. To
facilitate this process, we will provide you with all the necessary
files in a zipped folder (if you are working through this, you have
already found the first file). We recommend that you move that *.zip
file to the location where you want it (e.g., your folder for this
course) before unzipping.
The folder containing the files for a particular exercise is called a
“Working Directory”, and opening an *.Rmd file automatically sets the
working directory to the directory of that R Notebook file. So after
unzipping, it is important not to move any files out of the folder we
provide you with, unless you want to manually tell R where to look for
readable files. If so, you can use the setwd() command to
point R toward the location of your files (see
textbook for details).
2.2. Loading Your Libraries
When you install R, your computer can understand and execute a number
of commands. This is what is known as “Base R”. The power of R, however,
is that you can expand the number of commands your computer understands
by installing and loading additional R packages (also called libraries).
There are R packages specialized for pretty much any area of biology,
providing the capability to analyze data from the level of genes and
genomes to ecosystem level processes. We will frequently use a package
called ggplot2, which allows for plotting data. Depending
on the module, you will need to install additional libraries. To
download and install new R packages, go to “Tools > Install
Packages…” and type in the name of the package you want to install.
Alternatively, you can use the install.packages() function.
Fore example, execute the following code chunk to install
ggplot2:
#Install ggplot2
install.packages("ggplot2")
Note that you only need to install every package once (unless you
reinstall R). I recommend deleting the code chunk above after you run it
successfully, or you can silence it by a hash tag in the beginning of
install.packages("ggplot2"). Failure to do so can cause
problems during the export (knitting) of your R Notebook as an *.html
file.
To make use of installed packages, you also need to load the packages
every time you use R (i.e., every time you restart the
program). You can do this with the library() command, and
you will find a code snippet prompting you to load all needed libraries
at the beginning of each R Notebook (in a section that is typically
called dependencies). You can try it here by executing the code chunk
below to load ggplot2:
#Note that loading a library does not lead to an output
library(ggplot2)
2.3. Importing Data
One of the reasons we’re working through the coding basics here is of
course that you will work with actual data. To do that, you will need to
import data into R. With every exercise, we will provide you with one or
more data sets. These data sets will mostly come as *.csv files (which
stands for comma-separated values). They are essentially text files
containing data tables, and you can also open these files in Excel or
other programs. To import data, we will use the read.csv()
function. In the code chunk below, you can import a simple test data set
(“test_data.csv”) that includes the variables sex, length, and mass for
a population of an animal. Note that the fileEncoding
argument simply indicates that I generated the input files on a Mac,
which will prevent some import issues for those of you that use a
PC.
#The line of code simply prompts the computer to read the "test_data.csv" file and generate a data.frame called test.data
test.data <- read.csv("test_data.csv", fileEncoding = 'UTF-8-BOM')
If this worked correctly, you should now see this data set as
test.data in your global environment (top right panel). You
can double click it to view it. There should be three columns: sex,
length, and mass.
3. Making Figures
A key learning objective of this course is that you learn to
visualize data in different ways to facilitate data interpretation in
the context of different evolutionary hypotheses. In the following
sections, I will explain step by step (that is code line by code line)
how to make a simple graph with our sample data set. Let’s aim to make a
scatter plot showing the relationship between length and mass in our
species. The process is not much different than sketching a graph by
hand and layering different parts of the graph on top of each other,
just that you use words (code) to make the computer draw.
3.1. Define the Axes and Coordinate System
The first step of making any graph is to define the axes and
establish the coordinate grid that allows for the plotting of the data.
You can do this by calling the ggplot() function within
which you first need to specify the data source (in our case the data
frame we just created, called test.data) and then the so
called aesthetics—aes()—that contain information about what
variables define the x and y axes. In practice, this is accomplished
with the following line of code:
#This line of code calls for the ggplot function (a plotting function) and make a grid based on the test.data data frame, using length as the x axis and mass as the y axis
ggplot(test.data, aes(x=length, y=mass))
3.2. Adding a Layer with Data Points
The second step is to draw the data into the established coordinate
system. To do so, you just need to tell the program what kind of graph
you want to draw. Different graph types in ggplot2 are
referred to as geoms (geometries), and a scatter plot is designated as
geom_point. You can just add that to your existing code
with a plus sign. For an overview of some of the graph types (geoms)
ggplot2 offers, check the appendix
of our textbook.
ggplot(test.data, aes(x=length, y=mass)) +
geom_point()
3.3. Adding a Trendline
Whenever we look at the relationship between two variables, we may
want to add a trendline. You can add a trendline by adding the
geom_smooth() function to your existing code, and
method="lm" designates that your trendline should be
linear. The se argument designates whether or not you want
to draw an error estimate around your trendline.
{r message=FALSE} #The code within the brackets of the geom_smooth command specified some additional options, namely that we want to draw a straight line (method="lm") and that we do not want to show the confidence interval (se=FALSE). Set the se=TRUE and see what happens. ggplot(test.data, aes(x=length, y=mass)) + geom_point() + geom_smooth(method="lm", se=FALSE)
3.4. Changing the Axes Labels
The variable names in the data set do not always provide the clearest
description of what a variable means. We can modify the x and y axis
labels using the xlab() and ylab() functions,
respectively. The actual titles need to be written within quotation
marks:
#Simply add the new label text in quotation marks
ggplot(test.data, aes(x=length, y=mass)) +
geom_point() +
geom_smooth(method="lm", se=FALSE) +
xlab("Body length in cm") +
ylab("Body mass in kg")
3.5. Change the Theme
I honestly hate the default theme of ggplot with its
gray background. But you can quickly alter the look of the graph by
switching to a number of other possible themes. I personally like the
theme_classic(), but you can customize the look of your
graph with themes listed here.
ggplot(test.data, aes(x=length, y=mass)) +
geom_point() +
geom_smooth(method="lm", se=FALSE) +
xlab("Body length in cm") +
ylab("Body mass in kg") +
theme_classic()
Et voilà! You got yourself a perfectly good graph! As you exercise
building graphs throughout the semester, make sure to check the
“Practical Skills” sections of individual chapters refer to the appendix
of the book as needed.
To get additional advice on how to work with different color schemes
in gglot(), including the use of colorblind-friendly
palettes, please check the corresponding
textbook section.
4. Your First Data Set: Darwin’s Finches
One of the most iconic study systems in evolutionary biology are
Darwin’s finches on the Galapagos Islands. Rosemary and Peter Grant
spent much of their lives devoted to the study of these bird, examining
how their traits change in response to major ecological perturbations.
To do so, they collected a massive, long-term data set on different
traits of the medium ground finch (Geospiza fortis) population
on Daphne Major Island. For this exercise, we will take a look at their
beak size data from 1972-1994.

4.1. Import data
The beak size data can be found in file called “finches.csv”. The
file includes three variables: year, the average relative beak size
(rel.beak.size), and the standard error (st.err) that describes the
variability of beak size in any given year.
finch <- read.csv("finches.csv", fileEncoding = 'UTF-8-BOM')
4.2. Plotting the Data
The following code chunk provides the base code to make a scatter
plot as above. You will only have to specify the x and y variables and
label the axes correctly.
ggplot(finch, aes(x=year, y=rel.beak.size)) +
geom_point() +
xlab("year") +
ylab("beak size") +
theme_classic()
4.3. Adding Additional Graphical Elements
There are two graphical elements that we can add to facilitate the
interpretation of the data:
- Since this is a time series, it makes sense to connect the dots
representing the means from year to year. You can do this by simply
adding another geom:
geom_line().
- We want to know how much the average beak size changes relative to
the variability in the population. If variability is high, year to year
variation in may be negligible. But if variability is low, changes
across year may actually be substantial. You can do this by adding
another geom:
geom_errorbar(). Make sure to specify the x
and y axes variables as above
ggplot(finch, aes(x=year, y=rel.beak.size)) +
geom_point() +
geom_line() +
geom_errorbar(aes(ymin=rel.beak.size-st.err, ymax=rel.beak.size+st.err)) +
xlab("year") +
ylab("beak size in cm") +
theme_classic()
4.4. Interpretation
4.4.1. General patterns
Based on the graphs you just made, what do you observe? How do you
interpret the data if I told you that 1977 was a massive drought
year?
Based on the graph the birds beak sizes vary heavily from year to
year which is most likley caused by environmental change. In the year
1977 there is a noticeable increase in the size of the beaks belonging
to the finches. This is most likely due to the need for long beaks for
digging or rooting for food during the drought period. In other words
the birds with longer beak sizes where the only ones surviving and
reproducing.
4.4.2. Evolution… or Not?
Do you think these data reflect evolutionary change through time?
What is a potential alternative explanation? What additional information
would you need to either accept or reject the hypothesis that these
patterns reflect evolutionary change?
The graph does in-fact reflect evolutionary change throughout a
period of time, as it shows major patterns of different traits presented
between the generations of the finches.Useful additional information
would be weather reports, and other respources on the types of
environments influencing the changes in beak size between the finches.
5. Resources
5.1. Data References
Data on beak size variation in Darwin’s finches came from the
following publication:
5.2 Resources You Consulted
Consulting additional resources to solve this assignment is
absolutely allowed, but failure to disclose those resources is
plagiarism. Please list any collaborators you worked with and resources
you used below or state that you have not used any.
No outside resources
LS0tCnRpdGxlOiAiQW4gSW50cm9kdWN0aW9uIHRvIFIgTm90ZWJvb2tzIGFuZCBFdmlkZW5jZSBmb3IgRXZvbHV0aW9uIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzMnCiAgaHRtbF9kb2N1bWVudDoKICAgIGtlZXBfbWQ6IFRSVUUKLS0tCgojIyAqR3JhY2UgU3Ryb2JiZSoKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyAxLiBUaGUgR2VuZXJhbCBTdHJ1Y3R1cmUgb2YgYW4gUiBOb3RlYm9vawoKUiBOb3RlYm9vayBmaWxlcyAoXCouUm1kKSBhbGxvdyB5b3UgdG8gY29tYmluZSB0ZXh0IGVsZW1lbnRzIHdpdGggc25pcHBldHMgb2YgY29kZSBhbmQgdGhlIG91dHB1dHMgZ2VuZXJhdGVkIGZyb20gc2FpZCBjb2RlLiBUaGVyZSBhcmUgdGhyZWUgbWFpbiBwYXJ0cyB0byBhbiBSIE5vdGVib29rIGZpbGUsIHdoaWNoIGFyZSBpbnRyb2R1Y2VkIGluIHRoaXMgc2VjdGlvbi4gSW4gYWRkaXRpb24sIGVhY2ggUiBOb3RlYm9vayBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlcyBhbiBcKi5odG1sIGZpbGUgdGhhdCBwcm92aWRlcyB5b3Ugd2l0aCB0aGUgZm9ybWF0dGVkIGRvY3VtZW50IGluY2x1ZGluZyBhbGwgY29tcG9uZW50cywgd2hpY2ggeW91IHdpbGwgdWx0aW1hdGVseSBzdWJtaXQgZm9yIHlvdXIgaG9tZXdvcmsuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDEuMS4gVGhlIEhlYWRlcgoKVGhlIGhlYWRlciwgd2hpY2ggeW91IGNhbiBzZWUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGlzIGRvY3VtZW50LCBpcyBkZWxpbmVhdGVkIHdpdGggdGhyZWUgZGFzaGVzIChgLS0tYCkgYXQgdGhlIGJlZ2lubmluZyBhbmQgdGhlIGVuZC4gSXQgaW5jbHVkZXMgc29tZSBjb2RlIHRoYXQgaXMgaW1wb3J0YW50IGZvciB0aGUgZm9ybWF0dGluZyBvZiBvdXRwdXQgZmlsZXMsIHNvIEkgd291bGQgcmVjb21tZW5kIG5vdCBhbHRlcmluZyB0aGF0IHNlY3Rpb24uIEluIGdlbmVyYWwsIHRoZXJlIHNob3VsZCBiZSBubyByZWFzb24gZm9yIHlvdSB0byBjaGFuZ2UgdGhlIGhlYWRlciBmb3IgYW55IGV4ZXJjaXNlcyBpbiB0aGlzIGNvdXJzZS4gSG93ZXZlciwgaWYgeW91IHdvdWxkIGxpa2UgdG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgZGlmZmVyZW50IGhlYWRlciBvcHRpb25zLCB5b3UgY2FuIGZpbmQgYSBnb29kIHR1dG9yaWFsIFtoZXJlXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vaHRtbC1kb2N1bWVudC5odG1sI3RhYmxlLW9mLWNvbnRlbnRzKS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgMS4yLiBDb2RlIENodW5rcwoKUiBjb2RlIGNodW5rcyBhcmUgZGVsaW5lYXRlZCB3aXRoIHRocmVlIHRpY2tzIChgJycnYCkgYXQgdGhlIGJlZ2lubmluZyBhbmQgdGhlIGVuZCwgYW5kIGB7cn1gIGFmdGVyIHRoZSBmaXJzdCBzZXQgb2YgdGlja3MgbGV0cyB5b3VyIGNvbXB1dGVyIGtub3cgdGhhdCB5b3Ugd2lsbCBiZSB1c2luZyB0aGUgUiBwcm9ncmFtbWluZyBsYW5ndWFnZS4gWW91IGNhbiBhbHdheXMgYWRkIGEgY29kZSBjaHVuayBieSBjbGlja2luZyAiSW5zZXJ0IFw+IENvZGUgQ2h1bmsgXD4gUiIgYWJvdmUgb3IgYnkgY2xpY2tpbmcgdGhlICIrQyIgaWNvbiwgYWx0aG91Z2ggd2UgdXN1YWxseSBhbHJlYWR5IGNyZWF0ZWQgYWxsIHRoZSBjaHVua3MgeW91IHdpbGwgbmVlZCBpbiB0aGUgdGVtcGxhdGUuIEFueSB0ZXh0IHdpdGhpbiBhIGNvZGUgY2h1bmssIGlmIHdyaXR0ZW4gY29ycmVjdGx5LCByZXByZXNlbnRzIGV4ZWN1dGFibGUgY29kZSwgd2hpY2ggdGhlIGNvbXB1dGVyIGNhbiBpbnRlcnByZXQgYXMgYSBjb21tYW5kIHRvIHBlcmZvcm0gY2VydGFpbiB0YXNrcy4gWW91IGNhbiBtYWtlIHlvdXIgY29tcHV0ZXIgZXhlY3V0ZSB0aGUgY29kZSBpbiBhIGNodW5rIGJ5IHByZXNzaW5nIHRoZSBzbWFsbCwgZ3JlZW4gcGxheSBhcnJvdyBvbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBvZiBlYWNoIGNodW5rLCBvciB5b3UgY2FuIGp1c3QgaGlnaGxpZ2h0IHRoZSBjb2RlIGFuZCBwcmVzcyBjb21tYW5kK2VudGVyIChjb250cm9sK2VudGVyIG9uIFBDKS4gV2hlbiB5b3UgZXhlY3V0ZSB0aGUgY29kZSwgdGhlIG91dHB1dCB3aWxsIGF1dG9tYXRpY2FsbHkgYXBwZWFyIGJlbG93IGEgY2h1bmsuIFNvbWV0aW1lcyB5b3Ugd2lsbCBmaW5kIHVzIHVzaW5nIGhhc2ggdGFncyAoYCNgKSB3aXRoaW4gY29kZSBjaHVua3MuIEhhc2ggdGFncyAic2lsZW5jZSIgdGhlIHRleHQgdGhhdCBmb2xsb3dzIG9uIHRoZSBzYW1lIGxpbmUsIHN1Y2ggdGhhdCB0aGUgY29tcHV0ZXIganVtcHMgb3ZlciB0aGF0IHNlY3Rpb24gd2hlbiBleGVjdXRpbmcgdGhlIGNvZGUuIFRoYXQgaXMgdXNlZnVsIGZvciBjb2RlIGFubm90YXRpb24sIGFuZCB5b3Ugd2lsbCBmcmVxdWVudGx5IHNlZSB1cyB1c2luZyB0aGUgaGFzaCB0YWdzIHRvIGFkZCBmdXJ0aGVyIGRlc2NyaXB0aW9ucyBvciBleHBsYW5hdGlvbnMgd2l0aGluIGNvZGUgY2h1bmtzLgoKUHJvIHRpcDogSWYgeW91IHdhbnQgdG8gZXhlY3V0ZSBhbGwgY29kZSBjaHVua3MgaW4gYSBkb2N1bWVudCBhdXRvbWF0aWNhbGx5LCB5b3UgY2FuIGNsaWNrICJSdW4gXD4gUnVuIEFsbCIgaW4gdGhlIFJTdHVkaW8gbWVudS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgMS4zLiBUZXh0CgpUaGUgdGV4dCBpbiBiZXR3ZWVuIGNvZGUgc25pcHBldHMgaXMganVzdCB0aGF0OiB0ZXh0LiBXZSB3aWxsIHVzZSB0aGVzZSBzZWN0aW9ucyB0byBwcm92aWRlIHlvdSB3aXRoIGJhY2tncm91bmQgaW5mb3JtYXRpb24gYW5kIGRpc2N1c3Npb24gcHJvbXB0cywgYW5kIHlvdSB3aWxsIHVzZSB0aGVzZSBzZWN0aW9ucyB0byByZXNwb25kIHRvIHF1ZXN0aW9ucyBhbmQgb2ZmZXIgeW91ciBpbnRlcnByZXRhdGlvbnMgb2YgZGF0YS4gU2VjdGlvbnMgd2hlcmUgeW91IG5lZWQgdG8gd3JpdGUgc29tZXRoaW5nIGFyZSBhbHdheXMgaGlnaGxpZ2h0ZWQgaW4gKml0YWxpY3MqLiBZb3UgY2FuIHVzZSBhIHZhcmlldHkgb2YgcHJvbXB0cyB0byBmb3JtYXQgeW91ciB0ZXh0IGlmIHlvdSBhcmUgd29ya2luZyB3aXRoIGJhc2ljIE1hcmtkb3duIChzZWUgW2hlcmVdKGh0dHBzOi8vcnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDIvcm1hcmtkb3duLWNoZWF0c2hlZXQucGRmKSBmb3IgYSBjaGVhdCBzaGVldCkuIE1vc3Qgb2YgeW91LCBob3dldmVyLCB3aWxsIHByZWZlciB0aGUgdGV4dCBlZGl0b3IgdGhhdCBpcyBpbXBsZW1lbnRlZCBpbiBSIFN0dWRpbyB0byBmb3JtYXQgdGV4dCB3aXRoIHRoZSBjbGljayBvZiBhIGJ1dHRvbi4KClBybyB0aXA6IFlvdSBjYW4gdG9nZ2xlIGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gc291cmNlIGNvZGUgKHdpdGggTWFya2Rvd24gZm9ybWF0dGluZykgYW5kIHRoZSBXWVNJV1lHIGVkaXRvciAod2l0aCB0ZXh0IGZvcm1hdHRpbmcgdGhyb3VnaCBjbGlja2luZykgYnkgdXNpbmcgdGhlIFNvdXJjZS9WaXN1YWwgYnV0dG9ucyBpbiB0aGUgUlN0dWRpbyBtZW51CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDEuNC4gSFRNTCBQcmV2aWV3IGFuZCBPdXRwdXQKCkFzIGFscmVhZHkgbWVudGlvbmVkLCB5b3VyIFIgTm90ZWJvb2sgKGluY2x1ZGluZyB0ZXh0LCBjb2RlIGNodW5rcywgYW5kIHRoZSBvdXRwdXRzIGZyb20geW91ciBjb2RlKSBjYW4gYmUgYXV0b21hdGljYWxseSBrbml0dGVkIGludG8gYW4gXCouaHRtbCBmaWxlLiBZb3UgY2FuIGNsaWNrICJQcmV2aWV3IFw+IFByZXZpZXcgTm90ZWJvb2siIG9yICJQcmV2aWV3IFw+IEtuaXQgdG8gSFRNTCIgdG8gc2VlIHRoZSBsaXZlIGh0bWwgdmVyc2lvbiBhcyB5b3UgYXJlIHdvcmtpbmcgb24geW91ciBSIE5vdGVib29rIChqdXN0IG1ha2Ugc3VyZSB0byBzYXZlIHRvIHVwZGF0ZSksIGFuZCB5b3UgY2FuIGZpbmQgdGhlIHNoYXJlYWJsZSBcKi5odG1sIGZpbGUgaW4gdGhlIHNhbWUgZm9sZGVyIGFzIHlvdXIgXCouUm1kIGZpbGUgKHNhbWUgZmlsZSBuYW1lIHdpdGggLm5iIGFwcGVuZGVkKS4KCk5vdGU6IFNvbWV0aW1lIFIgd2lsbCBwcm9tcHQgeW91IHRvIHVwZGF0ZSBzb21lIHBhY2thZ2VzIGluIHRoZSBDb25zb2xlIGJlZm9yZSB5b3UgY2FuIGtuaXQgdGhlIGh0bWwgZmlsZS4gSWYgaXQgaXMgbm90IHdvcmtpbmcgb24gdGhlIGZpcnN0IHRyeSwgbWFrZSBzdXJlIHRvIGNoZWNrIGZvciBwcm9tcHRzIGluIHRoZSBDb25zb2xlLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIDIuIEdldHRpbmcgU3RhcnRlZAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAyLjEuIFNldHRpbmcgWW91ciBXb3JraW5nIERpcmVjdG9yeQoKSGF2aW5nIGEgd2VsbC1vcmdhbml6ZWQgZmlsZSBzdHJ1Y3R1cmUgaXMgY3JpdGljYWwgdG8gYXZvaWQgaXNzdWVzIHdpdGggY29kaW5nLCBiZWNhdXNlIHlvdSB3aWxsIGZyZXF1ZW50bHkgcmVhZCBpbiBkYXRhIGZpbGVzLCBhbmQgeW91IG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgUiBrbm93cyB3aGVyZSB0byBsb29rIGZvciB0aG9zZSBmaWxlcy4gVG8gZmFjaWxpdGF0ZSB0aGlzIHByb2Nlc3MsIHdlIHdpbGwgcHJvdmlkZSB5b3Ugd2l0aCBhbGwgdGhlIG5lY2Vzc2FyeSBmaWxlcyBpbiBhIHppcHBlZCBmb2xkZXIgKGlmIHlvdSBhcmUgd29ya2luZyB0aHJvdWdoIHRoaXMsIHlvdSBoYXZlIGFscmVhZHkgZm91bmQgdGhlIGZpcnN0IGZpbGUpLiBXZSByZWNvbW1lbmQgdGhhdCB5b3UgbW92ZSB0aGF0IFwqLnppcCBmaWxlIHRvIHRoZSBsb2NhdGlvbiB3aGVyZSB5b3Ugd2FudCBpdCAoZS5nLiwgeW91ciBmb2xkZXIgZm9yIHRoaXMgY291cnNlKSBiZWZvcmUgdW56aXBwaW5nLgoKVGhlIGZvbGRlciBjb250YWluaW5nIHRoZSBmaWxlcyBmb3IgYSBwYXJ0aWN1bGFyIGV4ZXJjaXNlIGlzIGNhbGxlZCBhICJXb3JraW5nIERpcmVjdG9yeSIsIGFuZCBvcGVuaW5nIGFuIFwqLlJtZCBmaWxlIGF1dG9tYXRpY2FsbHkgc2V0cyB0aGUgd29ya2luZyBkaXJlY3RvcnkgdG8gdGhlIGRpcmVjdG9yeSBvZiB0aGF0IFIgTm90ZWJvb2sgZmlsZS4gU28gYWZ0ZXIgdW56aXBwaW5nLCBpdCBpcyBpbXBvcnRhbnQgbm90IHRvIG1vdmUgYW55IGZpbGVzIG91dCBvZiB0aGUgZm9sZGVyIHdlIHByb3ZpZGUgeW91IHdpdGgsIHVubGVzcyB5b3Ugd2FudCB0byBtYW51YWxseSB0ZWxsIFIgd2hlcmUgdG8gbG9vayBmb3IgcmVhZGFibGUgZmlsZXMuIElmIHNvLCB5b3UgY2FuIHVzZSB0aGUgYHNldHdkKClgIGNvbW1hbmQgdG8gcG9pbnQgUiB0b3dhcmQgdGhlIGxvY2F0aW9uIG9mIHlvdXIgZmlsZXMgKFtzZWUgdGV4dGJvb2sgZm9yIGRldGFpbHNdKGh0dHBzOi8vd3d3Lmstc3RhdGUuZWR1L2Jpb2xvZ3kvcDJlL2V2aWRlbmNlLWZvci1ldm9sdXRpb24uaHRtbCNpbXBvcnQtZGF0YSkpLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAyLjIuIExvYWRpbmcgWW91ciBMaWJyYXJpZXMKCldoZW4geW91IGluc3RhbGwgUiwgeW91ciBjb21wdXRlciBjYW4gdW5kZXJzdGFuZCBhbmQgZXhlY3V0ZSBhIG51bWJlciBvZiBjb21tYW5kcy4gVGhpcyBpcyB3aGF0IGlzIGtub3duIGFzICJCYXNlIFIiLiBUaGUgcG93ZXIgb2YgUiwgaG93ZXZlciwgaXMgdGhhdCB5b3UgY2FuIGV4cGFuZCB0aGUgbnVtYmVyIG9mIGNvbW1hbmRzIHlvdXIgY29tcHV0ZXIgdW5kZXJzdGFuZHMgYnkgaW5zdGFsbGluZyBhbmQgbG9hZGluZyBhZGRpdGlvbmFsIFIgcGFja2FnZXMgKGFsc28gY2FsbGVkIGxpYnJhcmllcykuIFRoZXJlIGFyZSBSIHBhY2thZ2VzIHNwZWNpYWxpemVkIGZvciBwcmV0dHkgbXVjaCBhbnkgYXJlYSBvZiBiaW9sb2d5LCBwcm92aWRpbmcgdGhlIGNhcGFiaWxpdHkgdG8gYW5hbHl6ZSBkYXRhIGZyb20gdGhlIGxldmVsIG9mIGdlbmVzIGFuZCBnZW5vbWVzIHRvIGVjb3N5c3RlbSBsZXZlbCBwcm9jZXNzZXMuIFdlIHdpbGwgZnJlcXVlbnRseSB1c2UgYSBwYWNrYWdlIGNhbGxlZCBgZ2dwbG90MmAsIHdoaWNoIGFsbG93cyBmb3IgcGxvdHRpbmcgZGF0YS4gRGVwZW5kaW5nIG9uIHRoZSBtb2R1bGUsIHlvdSB3aWxsIG5lZWQgdG8gaW5zdGFsbCBhZGRpdGlvbmFsIGxpYnJhcmllcy4gVG8gZG93bmxvYWQgYW5kIGluc3RhbGwgbmV3IFIgcGFja2FnZXMsIGdvIHRvICJUb29scyBcPiBJbnN0YWxsIFBhY2thZ2VzLi4uIiBhbmQgdHlwZSBpbiB0aGUgbmFtZSBvZiB0aGUgcGFja2FnZSB5b3Ugd2FudCB0byBpbnN0YWxsLiBBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHVzZSB0aGUgYGluc3RhbGwucGFja2FnZXMoKWAgZnVuY3Rpb24uIEZvcmUgZXhhbXBsZSwgZXhlY3V0ZSB0aGUgZm9sbG93aW5nIGNvZGUgY2h1bmsgdG8gaW5zdGFsbCBgZ2dwbG90MmA6CgpgYGB7cn0KI0luc3RhbGwgZ2dwbG90MgppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKYGBgCgpOb3RlIHRoYXQgeW91IG9ubHkgbmVlZCB0byBpbnN0YWxsIGV2ZXJ5IHBhY2thZ2Ugb25jZSAodW5sZXNzIHlvdSByZWluc3RhbGwgUikuIEkgcmVjb21tZW5kIGRlbGV0aW5nIHRoZSBjb2RlIGNodW5rIGFib3ZlIGFmdGVyIHlvdSBydW4gaXQgc3VjY2Vzc2Z1bGx5LCBvciB5b3UgY2FuIHNpbGVuY2UgaXQgYnkgYSBoYXNoIHRhZyBpbiB0aGUgYmVnaW5uaW5nIG9mIGBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIilgLiBGYWlsdXJlIHRvIGRvIHNvIGNhbiBjYXVzZSBwcm9ibGVtcyBkdXJpbmcgdGhlIGV4cG9ydCAoa25pdHRpbmcpIG9mIHlvdXIgUiBOb3RlYm9vayBhcyBhbiBcKi5odG1sIGZpbGUuCgpUbyBtYWtlIHVzZSBvZiBpbnN0YWxsZWQgcGFja2FnZXMsIHlvdSBhbHNvIG5lZWQgdG8gbG9hZCB0aGUgcGFja2FnZXMgKmV2ZXJ5IHRpbWUqIHlvdSB1c2UgUiAoKmkuZS4qLCBldmVyeSB0aW1lIHlvdSByZXN0YXJ0IHRoZSBwcm9ncmFtKS4gWW91IGNhbiBkbyB0aGlzIHdpdGggdGhlIGBsaWJyYXJ5KClgIGNvbW1hbmQsIGFuZCB5b3Ugd2lsbCBmaW5kIGEgY29kZSBzbmlwcGV0IHByb21wdGluZyB5b3UgdG8gbG9hZCBhbGwgbmVlZGVkIGxpYnJhcmllcyBhdCB0aGUgYmVnaW5uaW5nIG9mIGVhY2ggUiBOb3RlYm9vayAoaW4gYSBzZWN0aW9uIHRoYXQgaXMgdHlwaWNhbGx5IGNhbGxlZCBkZXBlbmRlbmNpZXMpLiBZb3UgY2FuIHRyeSBpdCBoZXJlIGJ5IGV4ZWN1dGluZyB0aGUgY29kZSBjaHVuayBiZWxvdyB0byBsb2FkIGBnZ3Bsb3QyYDoKCmBgYHtyfQojTm90ZSB0aGF0IGxvYWRpbmcgYSBsaWJyYXJ5IGRvZXMgbm90IGxlYWQgdG8gYW4gb3V0cHV0CmxpYnJhcnkoZ2dwbG90MikKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDIuMy4gSW1wb3J0aW5nIERhdGEKCk9uZSBvZiB0aGUgcmVhc29ucyB3ZSdyZSB3b3JraW5nIHRocm91Z2ggdGhlIGNvZGluZyBiYXNpY3MgaGVyZSBpcyBvZiBjb3Vyc2UgdGhhdCB5b3Ugd2lsbCB3b3JrIHdpdGggYWN0dWFsIGRhdGEuIFRvIGRvIHRoYXQsIHlvdSB3aWxsIG5lZWQgdG8gaW1wb3J0IGRhdGEgaW50byBSLiBXaXRoIGV2ZXJ5IGV4ZXJjaXNlLCB3ZSB3aWxsIHByb3ZpZGUgeW91IHdpdGggb25lIG9yIG1vcmUgZGF0YSBzZXRzLiBUaGVzZSBkYXRhIHNldHMgd2lsbCBtb3N0bHkgY29tZSBhcyBcKi5jc3YgZmlsZXMgKHdoaWNoIHN0YW5kcyBmb3IgY29tbWEtc2VwYXJhdGVkIHZhbHVlcykuIFRoZXkgYXJlIGVzc2VudGlhbGx5IHRleHQgZmlsZXMgY29udGFpbmluZyBkYXRhIHRhYmxlcywgYW5kIHlvdSBjYW4gYWxzbyBvcGVuIHRoZXNlIGZpbGVzIGluIEV4Y2VsIG9yIG90aGVyIHByb2dyYW1zLiBUbyBpbXBvcnQgZGF0YSwgd2Ugd2lsbCB1c2UgdGhlIGByZWFkLmNzdigpYCBmdW5jdGlvbi4gSW4gdGhlIGNvZGUgY2h1bmsgYmVsb3csIHlvdSBjYW4gaW1wb3J0IGEgc2ltcGxlIHRlc3QgZGF0YSBzZXQgKCJ0ZXN0X2RhdGEuY3N2IikgdGhhdCBpbmNsdWRlcyB0aGUgdmFyaWFibGVzIHNleCwgbGVuZ3RoLCBhbmQgbWFzcyBmb3IgYSBwb3B1bGF0aW9uIG9mIGFuIGFuaW1hbC4gTm90ZSB0aGF0IHRoZSBgZmlsZUVuY29kaW5nYCBhcmd1bWVudCBzaW1wbHkgaW5kaWNhdGVzIHRoYXQgSSBnZW5lcmF0ZWQgdGhlIGlucHV0IGZpbGVzIG9uIGEgTWFjLCB3aGljaCB3aWxsIHByZXZlbnQgc29tZSBpbXBvcnQgaXNzdWVzIGZvciB0aG9zZSBvZiB5b3UgdGhhdCB1c2UgYSBQQy4KCmBgYHtyfQojVGhlIGxpbmUgb2YgY29kZSBzaW1wbHkgcHJvbXB0cyB0aGUgY29tcHV0ZXIgdG8gcmVhZCB0aGUgInRlc3RfZGF0YS5jc3YiIGZpbGUgYW5kIGdlbmVyYXRlIGEgZGF0YS5mcmFtZSBjYWxsZWQgdGVzdC5kYXRhCnRlc3QuZGF0YSA8LSByZWFkLmNzdigidGVzdF9kYXRhLmNzdiIsIGZpbGVFbmNvZGluZyA9ICdVVEYtOC1CT00nKQpgYGAKCklmIHRoaXMgd29ya2VkIGNvcnJlY3RseSwgeW91IHNob3VsZCBub3cgc2VlIHRoaXMgZGF0YSBzZXQgYXMgYHRlc3QuZGF0YWAgaW4geW91ciBnbG9iYWwgZW52aXJvbm1lbnQgKHRvcCByaWdodCBwYW5lbCkuIFlvdSBjYW4gZG91YmxlIGNsaWNrIGl0IHRvIHZpZXcgaXQuIFRoZXJlIHNob3VsZCBiZSB0aHJlZSBjb2x1bW5zOiBzZXgsIGxlbmd0aCwgYW5kIG1hc3MuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgMy4gTWFraW5nIEZpZ3VyZXMKCkEga2V5IGxlYXJuaW5nIG9iamVjdGl2ZSBvZiB0aGlzIGNvdXJzZSBpcyB0aGF0IHlvdSBsZWFybiB0byB2aXN1YWxpemUgZGF0YSBpbiBkaWZmZXJlbnQgd2F5cyB0byBmYWNpbGl0YXRlIGRhdGEgaW50ZXJwcmV0YXRpb24gaW4gdGhlIGNvbnRleHQgb2YgZGlmZmVyZW50IGV2b2x1dGlvbmFyeSBoeXBvdGhlc2VzLiBJbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zLCBJIHdpbGwgZXhwbGFpbiBzdGVwIGJ5IHN0ZXAgKHRoYXQgaXMgY29kZSBsaW5lIGJ5IGNvZGUgbGluZSkgaG93IHRvIG1ha2UgYSBzaW1wbGUgZ3JhcGggd2l0aCBvdXIgc2FtcGxlIGRhdGEgc2V0LiBMZXQncyBhaW0gdG8gbWFrZSBhIHNjYXR0ZXIgcGxvdCBzaG93aW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBsZW5ndGggYW5kIG1hc3MgaW4gb3VyIHNwZWNpZXMuIFRoZSBwcm9jZXNzIGlzIG5vdCBtdWNoIGRpZmZlcmVudCB0aGFuIHNrZXRjaGluZyBhIGdyYXBoIGJ5IGhhbmQgYW5kIGxheWVyaW5nIGRpZmZlcmVudCBwYXJ0cyBvZiB0aGUgZ3JhcGggb24gdG9wIG9mIGVhY2ggb3RoZXIsIGp1c3QgdGhhdCB5b3UgdXNlIHdvcmRzIChjb2RlKSB0byBtYWtlIHRoZSBjb21wdXRlciBkcmF3LgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAzLjEuIERlZmluZSB0aGUgQXhlcyBhbmQgQ29vcmRpbmF0ZSBTeXN0ZW0KClRoZSBmaXJzdCBzdGVwIG9mIG1ha2luZyBhbnkgZ3JhcGggaXMgdG8gZGVmaW5lIHRoZSBheGVzIGFuZCBlc3RhYmxpc2ggdGhlIGNvb3JkaW5hdGUgZ3JpZCB0aGF0IGFsbG93cyBmb3IgdGhlIHBsb3R0aW5nIG9mIHRoZSBkYXRhLiBZb3UgY2FuIGRvIHRoaXMgYnkgY2FsbGluZyB0aGUgYGdncGxvdCgpYCBmdW5jdGlvbiB3aXRoaW4gd2hpY2ggeW91IGZpcnN0IG5lZWQgdG8gc3BlY2lmeSB0aGUgZGF0YSBzb3VyY2UgKGluIG91ciBjYXNlIHRoZSBkYXRhIGZyYW1lIHdlIGp1c3QgY3JlYXRlZCwgY2FsbGVkIGB0ZXN0LmRhdGFgKSBhbmQgdGhlbiB0aGUgc28gY2FsbGVkIGFlc3RoZXRpY3MtLS1gYWVzKClgLS0tdGhhdCBjb250YWluIGluZm9ybWF0aW9uIGFib3V0IHdoYXQgdmFyaWFibGVzIGRlZmluZSB0aGUgeCBhbmQgeSBheGVzLiBJbiBwcmFjdGljZSwgdGhpcyBpcyBhY2NvbXBsaXNoZWQgd2l0aCB0aGUgZm9sbG93aW5nIGxpbmUgb2YgY29kZToKCmBgYHtyfQojVGhpcyBsaW5lIG9mIGNvZGUgY2FsbHMgZm9yIHRoZSBnZ3Bsb3QgZnVuY3Rpb24gKGEgcGxvdHRpbmcgZnVuY3Rpb24pIGFuZCBtYWtlIGEgZ3JpZCBiYXNlZCBvbiB0aGUgdGVzdC5kYXRhIGRhdGEgZnJhbWUsIHVzaW5nIGxlbmd0aCBhcyB0aGUgeCBheGlzIGFuZCBtYXNzIGFzIHRoZSB5IGF4aXMKZ2dwbG90KHRlc3QuZGF0YSwgYWVzKHg9bGVuZ3RoLCB5PW1hc3MpKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgMy4yLiBBZGRpbmcgYSBMYXllciB3aXRoIERhdGEgUG9pbnRzCgpUaGUgc2Vjb25kIHN0ZXAgaXMgdG8gZHJhdyB0aGUgZGF0YSBpbnRvIHRoZSBlc3RhYmxpc2hlZCBjb29yZGluYXRlIHN5c3RlbS4gVG8gZG8gc28sIHlvdSBqdXN0IG5lZWQgdG8gdGVsbCB0aGUgcHJvZ3JhbSB3aGF0IGtpbmQgb2YgZ3JhcGggeW91IHdhbnQgdG8gZHJhdy4gRGlmZmVyZW50IGdyYXBoIHR5cGVzIGluIGBnZ3Bsb3QyYCBhcmUgcmVmZXJyZWQgdG8gYXMgZ2VvbXMgKGdlb21ldHJpZXMpLCBhbmQgYSBzY2F0dGVyIHBsb3QgaXMgZGVzaWduYXRlZCBhcyBgZ2VvbV9wb2ludGAuIFlvdSBjYW4ganVzdCBhZGQgdGhhdCB0byB5b3VyIGV4aXN0aW5nIGNvZGUgd2l0aCBhIHBsdXMgc2lnbi4gRm9yIGFuIG92ZXJ2aWV3IG9mIHNvbWUgb2YgdGhlIGdyYXBoIHR5cGVzIChnZW9tcykgYGdncGxvdDJgIG9mZmVycywgY2hlY2sgdGhlIFthcHBlbmRpeF0oaHR0cHM6Ly93d3cuay1zdGF0ZS5lZHUvYmlvbG9neS9wMmUvZ3JhcGgtbGlicmFyeS5odG1sKSBvZiBvdXIgdGV4dGJvb2suCgpgYGB7cn0KZ2dwbG90KHRlc3QuZGF0YSwgYWVzKHg9bGVuZ3RoLCB5PW1hc3MpKSArCiAgZ2VvbV9wb2ludCgpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAzLjMuIEFkZGluZyBhIFRyZW5kbGluZQoKV2hlbmV2ZXIgd2UgbG9vayBhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIHZhcmlhYmxlcywgd2UgbWF5IHdhbnQgdG8gYWRkIGEgdHJlbmRsaW5lLiBZb3UgY2FuIGFkZCBhIHRyZW5kbGluZSBieSBhZGRpbmcgdGhlIGBnZW9tX3Ntb290aCgpYCBmdW5jdGlvbiB0byB5b3VyIGV4aXN0aW5nIGNvZGUsIGFuZCBgbWV0aG9kPSJsbSJgIGRlc2lnbmF0ZXMgdGhhdCB5b3VyIHRyZW5kbGluZSBzaG91bGQgYmUgbGluZWFyLiBUaGUgYHNlYCBhcmd1bWVudCBkZXNpZ25hdGVzIHdoZXRoZXIgb3Igbm90IHlvdSB3YW50IHRvIGRyYXcgYW4gZXJyb3IgZXN0aW1hdGUgYXJvdW5kIHlvdXIgdHJlbmRsaW5lLgoKYGBge3IgbWVzc2FnZT1GQUxTRX0KI1RoZSBjb2RlIHdpdGhpbiB0aGUgYnJhY2tldHMgb2YgdGhlIGdlb21fc21vb3RoIGNvbW1hbmQgc3BlY2lmaWVkIHNvbWUgYWRkaXRpb25hbCBvcHRpb25zLCBuYW1lbHkgdGhhdCB3ZSB3YW50IHRvIGRyYXcgYSBzdHJhaWdodCBsaW5lIChtZXRob2Q9ImxtIikgYW5kIHRoYXQgd2UgZG8gbm90IHdhbnQgdG8gc2hvdyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCAoc2U9RkFMU0UpLiBTZXQgdGhlIHNlPVRSVUUgYW5kIHNlZSB3aGF0IGhhcHBlbnMuCmdncGxvdCh0ZXN0LmRhdGEsIGFlcyh4PWxlbmd0aCwgeT1tYXNzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUZBTFNFKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgMy40LiBDaGFuZ2luZyB0aGUgQXhlcyBMYWJlbHMKClRoZSB2YXJpYWJsZSBuYW1lcyBpbiB0aGUgZGF0YSBzZXQgZG8gbm90IGFsd2F5cyBwcm92aWRlIHRoZSBjbGVhcmVzdCBkZXNjcmlwdGlvbiBvZiB3aGF0IGEgdmFyaWFibGUgbWVhbnMuIFdlIGNhbiBtb2RpZnkgdGhlIHggYW5kIHkgYXhpcyBsYWJlbHMgdXNpbmcgdGhlIGB4bGFiKClgIGFuZCBgeWxhYigpYCBmdW5jdGlvbnMsIHJlc3BlY3RpdmVseS4gVGhlIGFjdHVhbCB0aXRsZXMgbmVlZCB0byBiZSB3cml0dGVuIHdpdGhpbiBxdW90YXRpb24gbWFya3M6CgpgYGB7cn0KI1NpbXBseSBhZGQgdGhlIG5ldyBsYWJlbCB0ZXh0IGluIHF1b3RhdGlvbiBtYXJrcwpnZ3Bsb3QodGVzdC5kYXRhLCBhZXMoeD1sZW5ndGgsIHk9bWFzcykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBzZT1GQUxTRSkgKwogIHhsYWIoIkJvZHkgbGVuZ3RoIGluIGNtIikgKwogIHlsYWIoIkJvZHkgbWFzcyBpbiBrZyIpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyAzLjUuIENoYW5nZSB0aGUgVGhlbWUKCkkgaG9uZXN0bHkgaGF0ZSB0aGUgZGVmYXVsdCB0aGVtZSBvZiBgZ2dwbG90YCB3aXRoIGl0cyBncmF5IGJhY2tncm91bmQuIEJ1dCB5b3UgY2FuIHF1aWNrbHkgYWx0ZXIgdGhlIGxvb2sgb2YgdGhlIGdyYXBoIGJ5IHN3aXRjaGluZyB0byBhIG51bWJlciBvZiBvdGhlciBwb3NzaWJsZSB0aGVtZXMuIEkgcGVyc29uYWxseSBsaWtlIHRoZSBgdGhlbWVfY2xhc3NpYygpYCwgYnV0IHlvdSBjYW4gY3VzdG9taXplIHRoZSBsb29rIG9mIHlvdXIgZ3JhcGggd2l0aCB0aGVtZXMgbGlzdGVkIFtoZXJlXShodHRwczovL3d3dy5kYXRhbm92aWEuY29tL2VuL2Jsb2cvZ2dwbG90LXRoZW1lcy1nYWxsZXJ5LyNiYXNpYy1nZ3Bsb3QpLgoKYGBge3J9CmdncGxvdCh0ZXN0LmRhdGEsIGFlcyh4PWxlbmd0aCwgeT1tYXNzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIHNlPUZBTFNFKSArCiAgeGxhYigiQm9keSBsZW5ndGggaW4gY20iKSArCiAgeWxhYigiQm9keSBtYXNzIGluIGtnIikgKwogIHRoZW1lX2NsYXNzaWMoKQpgYGAKCkV0IHZvaWzDoCEgWW91IGdvdCB5b3Vyc2VsZiBhIHBlcmZlY3RseSBnb29kIGdyYXBoISBBcyB5b3UgZXhlcmNpc2UgYnVpbGRpbmcgZ3JhcGhzIHRocm91Z2hvdXQgdGhlIHNlbWVzdGVyLCBtYWtlIHN1cmUgdG8gY2hlY2sgdGhlICJQcmFjdGljYWwgU2tpbGxzIiBzZWN0aW9ucyBvZiBpbmRpdmlkdWFsIGNoYXB0ZXJzIHJlZmVyIHRvIHRoZSBhcHBlbmRpeCBvZiB0aGUgYm9vayBhcyBuZWVkZWQuCgpUbyBnZXQgYWRkaXRpb25hbCBhZHZpY2Ugb24gaG93IHRvIHdvcmsgd2l0aCBkaWZmZXJlbnQgY29sb3Igc2NoZW1lcyBpbiBgZ2dsb3QoKWAsIGluY2x1ZGluZyB0aGUgdXNlIG9mIGNvbG9yYmxpbmQtZnJpZW5kbHkgcGFsZXR0ZXMsIHBsZWFzZSBjaGVjayB0aGUgW2NvcnJlc3BvbmRpbmcgdGV4dGJvb2sgc2VjdGlvbl0oaHR0cHM6Ly93d3cuay1zdGF0ZS5lZHUvYmlvbG9neS9wMmUvZXZpZGVuY2UtZm9yLWV2b2x1dGlvbi5odG1sI2dyYXBoaW5nLWRhdGEpLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIDQuIFlvdXIgRmlyc3QgRGF0YSBTZXQ6IERhcndpbidzIEZpbmNoZXMKCk9uZSBvZiB0aGUgbW9zdCBpY29uaWMgc3R1ZHkgc3lzdGVtcyBpbiBldm9sdXRpb25hcnkgYmlvbG9neSBhcmUgRGFyd2luJ3MgZmluY2hlcyBvbiB0aGUgR2FsYXBhZ29zIElzbGFuZHMuIFJvc2VtYXJ5IGFuZCBQZXRlciBHcmFudCBzcGVudCBtdWNoIG9mIHRoZWlyIGxpdmVzIGRldm90ZWQgdG8gdGhlIHN0dWR5IG9mIHRoZXNlIGJpcmQsIGV4YW1pbmluZyBob3cgdGhlaXIgdHJhaXRzIGNoYW5nZSBpbiByZXNwb25zZSB0byBtYWpvciBlY29sb2dpY2FsIHBlcnR1cmJhdGlvbnMuIFRvIGRvIHNvLCB0aGV5IGNvbGxlY3RlZCBhIG1hc3NpdmUsIGxvbmctdGVybSBkYXRhIHNldCBvbiBkaWZmZXJlbnQgdHJhaXRzIG9mIHRoZSBtZWRpdW0gZ3JvdW5kIGZpbmNoICgqR2Vvc3BpemEgZm9ydGlzKikgcG9wdWxhdGlvbiBvbiBEYXBobmUgTWFqb3IgSXNsYW5kLiBGb3IgdGhpcyBleGVyY2lzZSwgd2Ugd2lsbCB0YWtlIGEgbG9vayBhdCB0aGVpciBiZWFrIHNpemUgZGF0YSBmcm9tIDE5NzItMTk5NC4KCiFbXShmaW5jaC5qcGcpCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDQuMS4gSW1wb3J0IGRhdGEKClRoZSBiZWFrIHNpemUgZGF0YSBjYW4gYmUgZm91bmQgaW4gZmlsZSBjYWxsZWQgImZpbmNoZXMuY3N2Ii4gVGhlIGZpbGUgaW5jbHVkZXMgdGhyZWUgdmFyaWFibGVzOiB5ZWFyLCB0aGUgYXZlcmFnZSByZWxhdGl2ZSBiZWFrIHNpemUgKHJlbC5iZWFrLnNpemUpLCBhbmQgdGhlIHN0YW5kYXJkIGVycm9yIChzdC5lcnIpIHRoYXQgZGVzY3JpYmVzIHRoZSB2YXJpYWJpbGl0eSBvZiBiZWFrIHNpemUgaW4gYW55IGdpdmVuIHllYXIuCgpgYGB7cn0KZmluY2ggPC0gcmVhZC5jc3YoImZpbmNoZXMuY3N2IiwgZmlsZUVuY29kaW5nID0gJ1VURi04LUJPTScpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyA0LjIuIFBsb3R0aW5nIHRoZSBEYXRhCgpUaGUgZm9sbG93aW5nIGNvZGUgY2h1bmsgcHJvdmlkZXMgdGhlIGJhc2UgY29kZSB0byBtYWtlIGEgc2NhdHRlciBwbG90IGFzIGFib3ZlLiBZb3Ugd2lsbCBvbmx5IGhhdmUgdG8gc3BlY2lmeSB0aGUgeCBhbmQgeSB2YXJpYWJsZXMgYW5kIGxhYmVsIHRoZSBheGVzIGNvcnJlY3RseS4KCmBgYHtyfQpnZ3Bsb3QoZmluY2gsIGFlcyh4PXllYXIsIHk9cmVsLmJlYWsuc2l6ZSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoInllYXIiKSArCiAgeWxhYigiYmVhayBzaXplIikgKwogIHRoZW1lX2NsYXNzaWMoKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgNC4zLiBBZGRpbmcgQWRkaXRpb25hbCBHcmFwaGljYWwgRWxlbWVudHMKClRoZXJlIGFyZSB0d28gZ3JhcGhpY2FsIGVsZW1lbnRzIHRoYXQgd2UgY2FuIGFkZCB0byBmYWNpbGl0YXRlIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgZGF0YToKCjEuICBTaW5jZSB0aGlzIGlzIGEgdGltZSBzZXJpZXMsIGl0IG1ha2VzIHNlbnNlIHRvIGNvbm5lY3QgdGhlIGRvdHMgcmVwcmVzZW50aW5nIHRoZSBtZWFucyBmcm9tIHllYXIgdG8geWVhci4gWW91IGNhbiBkbyB0aGlzIGJ5IHNpbXBseSBhZGRpbmcgYW5vdGhlciBnZW9tOiBgZ2VvbV9saW5lKClgLgoyLiAgV2Ugd2FudCB0byBrbm93IGhvdyBtdWNoIHRoZSBhdmVyYWdlIGJlYWsgc2l6ZSBjaGFuZ2VzIHJlbGF0aXZlIHRvIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgcG9wdWxhdGlvbi4gSWYgdmFyaWFiaWxpdHkgaXMgaGlnaCwgeWVhciB0byB5ZWFyIHZhcmlhdGlvbiBpbiBtYXkgYmUgbmVnbGlnaWJsZS4gQnV0IGlmIHZhcmlhYmlsaXR5IGlzIGxvdywgY2hhbmdlcyBhY3Jvc3MgeWVhciBtYXkgYWN0dWFsbHkgYmUgc3Vic3RhbnRpYWwuIFlvdSBjYW4gZG8gdGhpcyBieSBhZGRpbmcgYW5vdGhlciBnZW9tOiBgZ2VvbV9lcnJvcmJhcigpYC4gTWFrZSBzdXJlIHRvIHNwZWNpZnkgdGhlIHggYW5kIHkgYXhlcyB2YXJpYWJsZXMgYXMgYWJvdmUKCmBgYHtyfQpnZ3Bsb3QoZmluY2gsIGFlcyh4PXllYXIsIHk9cmVsLmJlYWsuc2l6ZSkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPXJlbC5iZWFrLnNpemUtc3QuZXJyLCB5bWF4PXJlbC5iZWFrLnNpemUrc3QuZXJyKSkgICsKICB4bGFiKCJ5ZWFyIikgKwogIHlsYWIoImJlYWsgc2l6ZSBpbiBjbSIpICsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDQuNC4gSW50ZXJwcmV0YXRpb24KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIDQuNC4xLiBHZW5lcmFsIHBhdHRlcm5zCgpCYXNlZCBvbiB0aGUgZ3JhcGhzIHlvdSBqdXN0IG1hZGUsIHdoYXQgZG8geW91IG9ic2VydmU/IEhvdyBkbyB5b3UgaW50ZXJwcmV0IHRoZSBkYXRhIGlmIEkgdG9sZCB5b3UgdGhhdCAxOTc3IHdhcyBhIG1hc3NpdmUgZHJvdWdodCB5ZWFyPwoKKkJhc2VkIG9uIHRoZSBncmFwaCB0aGUgYmlyZHMgYmVhayBzaXplcyB2YXJ5IGhlYXZpbHkgZnJvbSB5ZWFyIHRvIHllYXIgd2hpY2ggaXMgbW9zdCBsaWtsZXkgY2F1c2VkIGJ5IGVudmlyb25tZW50YWwgY2hhbmdlLiBJbiB0aGUgeWVhciAxOTc3IHRoZXJlIGlzIGEgbm90aWNlYWJsZSBpbmNyZWFzZSBpbiB0aGUgc2l6ZSBvZiB0aGUgYmVha3MgYmVsb25naW5nIHRvIHRoZSBmaW5jaGVzLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byB0aGUgbmVlZCBmb3IgbG9uZyBiZWFrcyBmb3IgZGlnZ2luZyBvciByb290aW5nIGZvciBmb29kIGR1cmluZyB0aGUgZHJvdWdodCBwZXJpb2QuIEluIG90aGVyIHdvcmRzIHRoZSBiaXJkcyB3aXRoIGxvbmdlciBiZWFrIHNpemVzIHdoZXJlIHRoZSBvbmx5IG9uZXMgc3Vydml2aW5nIGFuZCByZXByb2R1Y2luZy4gICoKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIDQuNC4yLiBFdm9sdXRpb24uLi4gb3IgTm90PwoKRG8geW91IHRoaW5rIHRoZXNlIGRhdGEgcmVmbGVjdCBldm9sdXRpb25hcnkgY2hhbmdlIHRocm91Z2ggdGltZT8gV2hhdCBpcyBhIHBvdGVudGlhbCBhbHRlcm5hdGl2ZSBleHBsYW5hdGlvbj8gV2hhdCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHdvdWxkIHlvdSBuZWVkIHRvIGVpdGhlciBhY2NlcHQgb3IgcmVqZWN0IHRoZSBoeXBvdGhlc2lzIHRoYXQgdGhlc2UgcGF0dGVybnMgcmVmbGVjdCBldm9sdXRpb25hcnkgY2hhbmdlPwoKKlRoZSBncmFwaCBkb2VzIGluLWZhY3QgcmVmbGVjdCBldm9sdXRpb25hcnkgY2hhbmdlIHRocm91Z2hvdXQgYSBwZXJpb2Qgb2YgdGltZSwgYXMgaXQgc2hvd3MgbWFqb3IgcGF0dGVybnMgb2YgZGlmZmVyZW50IHRyYWl0cyBwcmVzZW50ZWQgYmV0d2VlbiB0aGUgZ2VuZXJhdGlvbnMgb2YgdGhlIGZpbmNoZXMuVXNlZnVsIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gd291bGQgYmUgd2VhdGhlciByZXBvcnRzLCBhbmQgb3RoZXIgcmVzcG91cmNlcyBvbiB0aGUgdHlwZXMgb2YgZW52aXJvbm1lbnRzIGluZmx1ZW5jaW5nIHRoZSBjaGFuZ2VzIGluIGJlYWsgc2l6ZSBiZXR3ZWVuIHRoZSBmaW5jaGVzLiAqCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgNS4gUmVzb3VyY2VzCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDUuMS4gRGF0YSBSZWZlcmVuY2VzCgpEYXRhIG9uIGJlYWsgc2l6ZSB2YXJpYXRpb24gaW4gRGFyd2luJ3MgZmluY2hlcyBjYW1lIGZyb20gdGhlIGZvbGxvd2luZyBwdWJsaWNhdGlvbjoKCi0gICBHcmFudCwgUFIgJiBCUiBHcmFudC4gMjAwMi4gW1VucHJlZGljdGFibGUgZXZvbHV0aW9uIGluIGEgMzAteWVhciBzdHVkeSBvZiBEYXJ3aW4ncyBmaW5jaGVzXShodHRwczovL3NjaWVuY2Uuc2NpZW5jZW1hZy5vcmcvY29udGVudC8yOTYvNTU2OC83MDcpLiAqU2NpZW5jZSogMjk2LCA3MDctNzExLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyA1LjIgUmVzb3VyY2VzIFlvdSBDb25zdWx0ZWQKCkNvbnN1bHRpbmcgYWRkaXRpb25hbCByZXNvdXJjZXMgdG8gc29sdmUgdGhpcyBhc3NpZ25tZW50IGlzIGFic29sdXRlbHkgYWxsb3dlZCwgYnV0IGZhaWx1cmUgdG8gZGlzY2xvc2UgdGhvc2UgcmVzb3VyY2VzIGlzIHBsYWdpYXJpc20uIFBsZWFzZSBsaXN0IGFueSBjb2xsYWJvcmF0b3JzIHlvdSB3b3JrZWQgd2l0aCBhbmQgcmVzb3VyY2VzIHlvdSB1c2VkIGJlbG93IG9yIHN0YXRlIHRoYXQgeW91IGhhdmUgbm90IHVzZWQgYW55LgoKKk5vIG91dHNpZGUgcmVzb3VyY2VzKgo=