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.1. The Header

The header, which you can see at the beginning of this document, is delineated with three dashes (---) at the beginning and the end. It includes some code that is important for the formatting of output files, so I would recommend not altering that section. In general, there should be no reason for you to change the header for any exercises in this course. However, if you would like to learn more about the different header options, you can find a good tutorial here.


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:

  1. 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().
  2. 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=