Installation

Make sure you have the newest versions of R and RStudio. R should be 4.1.0 “Camp Pontanezen” or higher. If you are just installing it now, the version will be 4.1.2 “Bird Hippie” (in case you are wondering, the interesting version names come from Peanut cartoons). RStudio should be 1.4.1717 or higher. The newest version is 2021.09.2-382.

  • Go to CRAN (Comprehensive R Archive Network) to install R. Choose the appropriate download (likely either Mac or PC). You want to download the precompiled binary distributions, not the source code. If you have a Mac, you should then choose the latest release that ends in .pkg and you can determine if you have an Intel-based processor by going to the Apple menu (top left of your screen) > About This Mac and seeing if the processor listed has the word Intel in it (e.g. Processor 2.3 GHz Dual-Core Intel Core i5). If you have a PC, you should click on base. Once it downloads, you will need to click on the file that was downloaded in order to install it. You can click through the prompts during installation. Once finished, it should tell you that it was installed successfully. (If you have a Mac, you should also download and install XQuartz here.)
  • Download RStudio from their website. You want the free RStudio Desktop version. Choose the one that matches your operating system (one will likely be suggested to you at the top of the page). Follow the prompts. On a Mac, be sure to drop RStudio into the applications folder at the end of the download. If you have downloaded it before, it will ask if you want to use the newer version. Choose yes.
  • To check your version of R, open RStudio and look in the console (bottom left box by default). At the top, it will say the version of R you are running. Make sure it is the version you expect. You can also type R.Version() into the console to find the version. To check your version of RStudio, click on the RStudio menu at the top of your RStudio session and choose About RStudio. Make sure you see the correct version. You can also type RStudio.Version() into the console to find the version. See the video below for a demonstration of how to do this (note that the video is from the summer of 2020 so will NOT have the most up-to-date versions).

Voicethread: Check R and RStudio version

  • If you have issues downloading or updating either of these, please contact your instructor as early as possible.
  • If you plan to use Macalester’s RStudio server, please see this video for a few things that will be different.

Setting up for success

Please watch the video below about setting up for success in this class. Details from the video are also written below, if you would rather not watch the video.

Voicethread: Setting up for Success

These are some steps you should take to set yourself up for an easier time using R and RStudio.

  • Create a folder on your desktop, in your Documents folder, or some other reasonable location on your computer. This should NOT be in your downloads. Let me say that again, more loudly, THIS SHOULD NOT BE IN YOUR DOWNLOADS. Give the folder a good name, like COMP_STAT_112, STAT155, or 2020SPRING_STAT253 (I use this document for all these courses but the name should match the course you are taking).
  • Save your documents to the course folder (or a folder within that) you created, NOT to your downloads! And save often! This is not like Google docs. It will not, in general, auto save for you.
  • When you download resources from moodle, save them to the course folder you created. On most computers, downloaded files will be saved to your downloads. You can either change the settings or be sure to save files somewhere else after downloading. If you use a Mac, do not use Safari when downloading R markdown files from moodle. Use some other browser (Chrome, Mozilla, etc.). Safari will add a .txt extension to the .rmd file and makes it difficult for you to fix it.
  • Change global settings! Go to Tools –> Global options. On the General tab, next to Save workspace to .RData on exit, choose Never and uncheck the box next to Restore .Rdata into workspace at startup. You can also go to the Appearance tab to customize the look of RStudio.
  • Spell check. There is a spell check button (ABC with a check mark underneath it). You should use that for your all assignments. In this newest version of RStudio there is also inline spellcheck so words it does not recognize will have a squiggly line under them.
  • Don’t be afraid to use the internet to search for answers to your questions. I do this all the time. And when I say all the time, I mean every single time I use R. I will try to show you examples of doing this in class.

Tour of RStudio

Watch the video below for a tour of RStudio. Most of what is covered in the video is also written out in the details of this section.

Voicethread: RStudio tour

There are four main panes in RStudio. I will discuss all four. If you ever want to change the layout, you can do that by clicking the down arrow in the menu at the top of RStudio that looks like a window with four panes. And, if you ever lose one or more of the panes, click that same down arrow and choose Show All Panes.

Source

The main pane in the top left has the file you are working from. In this class, we will work with R Markdown files, .rmd files for short. I talk about those more below.

Console

The console in the lower left is where the code is evaluated. Since we can also see the code evaluated within the .rmd file, I often keep the console minimized. I will sometimes do some quick math in the console. The > is the prompt, indicating where you should start your code.

When you knit (compile) your document, this pane will show the complication process in a tab called R Markdown. If you get an error, you will see it there.

Environment, History, Connections, Tutorial, (Git - later)

The pane in the upper right has a few tabs of interest. The Environment tab shows anything that has been saved to the workspace. So, if you read in a dataset or create a new named dataset, variable, etc., it will show up there. You can do some basic exploration of those items by clicking on them in the Environment.

The History tab shows your history of code that has been run in this session. It is sometimes helpful if you want to get to an old piece of code that you deleted from your .rmd file.

The Tutorials tab is new. I would encourage you to explore the resources available there.

Later in the course, we will be learning about Git and GitHub. Once we start using those tools, there will be a Git tab i this pane.

Files, Plots, Packages, Help, Viewer

I think the most important two tabs in the lower right are Files and Help. In the Files tab, you can navigate to various locations on your computer. By default, it will be in the folder where the file you have open is located.

The Help tab is where you can go to search for help with R functions. You can type in a function name and go to that function’s help page.

R Markdown

Voicethread: R Markdown Intro

This document was created from an R Markdown file that was compiled to an html document. After you have installed R and RStudio, you can download the R Markdown file from the moodle page and open it to see the “code” behind this document. We will use them to interweave text with R code and R output (tables/graphs/etc.) to create a beautiful HTML document. (Word docs and PDFs can also be created but we usually like the look and layout of HTML files the best so that’s our focus).

In the future, when you want to create your own document, I would recommend starting with the R_Markdown_Template.Rmd I posted on the moodle page. Otherwise, go to File –> New file and choose R Markdown. Follow the prompts and you are ready to begin!

Writing in an R Markdown document is a little different from writing in Word or other WYSIWYG (What You See Is What You Get) word processor. In R Markdown you have to explicitly tell it to do things like bold or italics. Then when you knit (compile) the document, you see those in the final product. The best way to learn these features is to try some things on your own. I recommend having the R Markdown Reference Guide open to help. This can also be found on the Help toolbar at the top under Cheatsheets –> R Markdown Reference Guide.

Like I mentioned above, you will knit your R Markdown file (.rmd file) which seemingly magically turns it into a beautiful html file. The html files are what you will submit for assignments on moodle. To knit an R Markdown file, either click on the icon above that looks like a ball of yarn with knitting needles in it, or click the arrow next to that and choose knit to html. When you knit the document, an html file with the same name as the .rmd file (but with an html extension) is saved to wherever the .rmd file was saved. This is why it is extremely important that you know where you saved your file initially!

DISCLAIMER: I have been using R since 2003. The first time I used it was in a statistics course right here at Macalester College. I was afraid of coding and completely overwhelmed at first. I thought I would never get the hang of it. I asked a lot of questions, often feeling like they were really silly questions. But, that helped me learn and conquer my fear. Since I have been using R for so long now, it is sometimes hard for me to remember what questions I had when I first started. So, please ask questions! It is very likely that if you have a question, someone else has the same one.

Good resources

These are great resources. I almost always have the cheatsheet open when using R because I know I’ll need to use something from it. I find the Pandoc’s Markdown section of the R Markdown Cheatsheet especially helpful to do some basic, but cool things.

Code chunks

An R code chunk is located below, with some simple math in it. You should use the shortcuts to insert a code chunk. You can do this by going to Insert –> R or by pressing Cmd+Option+I (Ctrl+Alt+I on a PC).

You can execute the code chunk “in line” by clicking the Run button (the green arrow) within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter (Ctrl+Shift+Enter on a PC).

You can also highlight a portion of the code and choose Run selected line(s) using the down arrow icon next to the Run button, near the top right corner of this file or the shortcut of Shift+Enter. The output is displayed beneath the code chunk within this markdown document. When the document is knit, it will be displayed in a slightly nicer fashion.

This is some really simple R code. In the output, the [1] you see means that is the first observation. So notice below, there are two [1]’s because we have two lines of code, thus two outputs.

2 + 5
## [1] 7
3 - 4
## [1] -1

Here is an example of more advanced R code that creates a summary of my garden data. The output is a table.

garden_harvest %>% 
  group_by(vegetable) %>% 
  summarize(weight = sum(weight),
            wt_lbs = weight*0.00220462) %>% 
  arrange(desc(wt_lbs))

And this is an example of code where the output is a plot.

garden_harvest %>% 
  filter(date < ymd("2020-09-01")) %>% 
  group_by(date) %>% 
  summarize(weight = sum(weight),
            wt_lbs = weight*0.00220462) %>% 
  ggplot(aes(x = date, y = wt_lbs)) +
  geom_point() +
  geom_line() +
  labs(title = "Daily harvest from the #junglegarden (lb)",
       y = "", x = "") +
  scale_y_continuous(breaks = seq(0,100,1))

Knit the R markdown file by choosing that option on the down arrow next to the Knit button. We will always Knit to HTML in this class.

Naming

We will often want to name something that we will use again later. We can do this in R using the <- notation. So, in the code below, I store 2 + 5 as seven. Notice it shows up in the Environment after doing this. Then I can use seven in later steps. You can store more complicated things as well. Also see the top of the file where I read in a dataset and name it garden_harvest.

seven <- 2 + 5
seven
## [1] 7
seven + 5
## [1] 12

Annotating code

We usually discuss our code and output outside of the code chunk itself, but sometimes you might want to write a note to yourself about the code and it is nice to do that inside of the code. The pound (or hashtag, as most of you probably know it) can be used to do that. Notice R ignores everything after the pound on that line, but runs the next line without a problem. You can see another example where I use this type of annotation in the loading library code chunk at the top.

2 + 5 #wow
## [1] 7
3 - 4
## [1] -1

Options

Within each R code chunk, we can control different options. For example, I added echo=FALSE to the chunk below which means the code will not be in the html file. Let’s knit it and take a look.

Sometimes, we want to control options throughout the whole document. If we go back to the first R code chunk, it contains knitr::opts_chunk$set(echo = TRUE). This means that the echo=TRUE (which means the code is displayed in the output along with the output) will be the default in all code chunks unless the chunk is overwritten. I also added warning=FALSE and message=FALSE to this document when I was finished. This omits all messages and warnings from the knitted file. Wait to do this until the end so that you don’t miss any important messages and warnings.

Datasets

Some of the datasets we’ll be using are contained in R packages. So, they are ready for us to access and use. For example, the mpg data is from the tidyverse package. To find out details about the dataset, type mpg in the help menu or ?mpg in the console.

In order get the dataset to show up in the Global Environment, you need to “load” the data. It will initially say <Promise> next to it, but that will change as soon as you actually use the dataset. Once you do, you can then go click on the dataset and a spreadsheet view of the data will open. We loaded this previously (see above).

External data can be loaded in various ways depending its format and where it is. Data stored in Googlesheets are easy to load with the googlesheets4 package. See an example of that in the dataset code chunk above (although I have now added that data to the gardenR package).

In addition to looking at the data in the spreadsheet viewer, you might find the following couple functions useful to explore some basic properties of the dataset.

The dim() function tells us the dimensions of the dataset, the number of observations (also called cases or rows) and the number of variables (also called columns).

dim(mpg)
## [1] 234  11

We may want to look at the first few rows of the dataset to make sure everything is as we expect.

head(mpg)

The glimpse() functions shows a brief summary of the data.

glimpse(mpg)
## Rows: 234
## Columns: 11
## $ manufacturer <chr> "audi", "audi", "audi", "audi", "audi", "audi", "audi", "…
## $ model        <chr> "a4", "a4", "a4", "a4", "a4", "a4", "a4", "a4 quattro", "…
## $ displ        <dbl> 1.8, 1.8, 2.0, 2.0, 2.8, 2.8, 3.1, 1.8, 1.8, 2.0, 2.0, 2.…
## $ year         <int> 1999, 1999, 2008, 2008, 1999, 1999, 2008, 1999, 1999, 200…
## $ cyl          <int> 4, 4, 4, 4, 6, 6, 6, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 8, 8, …
## $ trans        <chr> "auto(l5)", "manual(m5)", "manual(m6)", "auto(av)", "auto…
## $ drv          <chr> "f", "f", "f", "f", "f", "f", "f", "4", "4", "4", "4", "4…
## $ cty          <int> 18, 21, 20, 21, 16, 18, 18, 18, 16, 20, 19, 15, 17, 17, 1…
## $ hwy          <int> 29, 29, 31, 30, 26, 26, 27, 26, 25, 28, 27, 25, 25, 25, 2…
## $ fl           <chr> "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p…
## $ class        <chr> "compact", "compact", "compact", "compact", "compact", "c…

The summary() function also gives a summary of the data.

summary(mpg)
##  manufacturer          model               displ            year     
##  Length:234         Length:234         Min.   :1.600   Min.   :1999  
##  Class :character   Class :character   1st Qu.:2.400   1st Qu.:1999  
##  Mode  :character   Mode  :character   Median :3.300   Median :2004  
##                                        Mean   :3.472   Mean   :2004  
##                                        3rd Qu.:4.600   3rd Qu.:2008  
##                                        Max.   :7.000   Max.   :2008  
##       cyl           trans               drv                 cty       
##  Min.   :4.000   Length:234         Length:234         Min.   : 9.00  
##  1st Qu.:4.000   Class :character   Class :character   1st Qu.:14.00  
##  Median :6.000   Mode  :character   Mode  :character   Median :17.00  
##  Mean   :5.889                                         Mean   :16.86  
##  3rd Qu.:8.000                                         3rd Qu.:19.00  
##  Max.   :8.000                                         Max.   :35.00  
##       hwy             fl               class          
##  Min.   :12.00   Length:234         Length:234        
##  1st Qu.:18.00   Class :character   Class :character  
##  Median :24.00   Mode  :character   Mode  :character  
##  Mean   :23.44                                        
##  3rd Qu.:27.00                                        
##  Max.   :44.00

Packages/Libraries

You can run R as is without any additional features but many of the tasks we will want to do will require or be enhanced by extra packages/libraries (I use these words interchangeably). Download and install packages by going to the Packages tab (top of lower right box) and choosing Install. You can then list the packages you would like to install (alternatively, you can use install.packages() function in the console). Once installed, you need to run a library() statement with that package name to make the functions within them available for use. I like this analogy from the Modern Dive authors: libraries are to R as apps are to smart phones. How many of you use a smart phone without additional apps?

You should put an R code chunk that loads all the libraries you will use throughout the assignment at the top of your file. I have done that in this document.

There are over 11,000 packages on CRAN (and even more available other places like git, etc.). I WILL NOT cover them all!

Modifying the YAML

In the R Markdown file, the portion at the top within the two sets of three dashes, is called the YAML section. It is a place where you can control document settings. I’ll show you a few things you can do.

Themes

R Markdown supports numerous themes. Check them out here. You could modify the YAML to include a different theme, like I do below.

---
title: "My title"
author: "Lisa Lendway"
date: "8/10/2020"
output: 
  html_document:
    theme: journal
---

Table of Contents

We can add a table of contents so that each heading (and subheading) can be clicked. We often label homework exercises using headings so this can be a nice way for you to quickly navigate to a specific exercise.

---
title: "My title"
author: "Lisa Lendway"
date: "8/10/2020"
output: 
  html_document:
    theme: journal
    toc: true
---

Nicer tables

Tables don’t look great by default in the R output. There are many ways we can make them look better, but one quick way is to making them html tables by adding df_print: paged to the YAML heading.

---
title: "My title"
author: "Lisa Lendway"
date: "8/10/2020"
output: 
  html_document:
    theme: journal
    toc: true
    df_print: paged
---

Add a code download button

This can be helpful for sharing code so someone can access your .rmd file through the html file.

---
title: "My title"
author: "Lisa Lendway"
date: "8/10/2020"
output: 
  html_document:
    theme: journal
    toc: true
    df_print: paged
    code_download: true
---

YAML is VERY picky

Indentation and spacing need to be EXACT! Let’s see what happens if (when?) we make a mistake.

R Markdown tips

  1. Make sure you don’t have any spaces or weird characters in your file name. It is best to use letters, numbers, underscores, and dashes in your names. And, give it a name that helps you remember what it is. Take ~5 minutes to read through at least the first 4 sections of these slides by Danielle Navarro to help you learn best practices.
  2. Save your file to the course folder you created or a folder within that, NOT to your downloads.
Anakin says, “I knitted the .Rmd file to create the .html file.” To which Padme replies, “And you know where it is because you saved it somewhere other your downloads folder, right?”
  1. If you are not given a file to start from, use the R markdown template that you can download below.
  2. Knit your document often! That way if there are errors early on, you can catch them. If there are errors in your document, they will be indicated with the line number where the error started in the R Markdown section (lower left corner next to the Console).
  3. Use the internet to help you search for solutions! Stack overflow is a great place to start. When searching for R related topics, add R to your search. If it is related to R Markdown, add R Markdown. We will do some of this searching together in class, too.

Code style

Although R is not terribly picky about how code is written, we are! We want to write readable code. I try to follow the tidyverse styleguide and you should as well. For example, in all the ggplot code, a new line is started after a +. Later we will see that we start a new line of code after a pipe, %>%. Code that is difficult to read may be deducted points on homework assignments.

LS0tCnRpdGxlOiAiUiBCYXNpY3MiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgo8c2NyaXB0IGFzeW5jIGRlZmVyIGRhdGEtZG9tYWluPSJyLWJhc2ljcy5uZXRsaWZ5LmFwcCIgc3JjPSJodHRwczovL3BsYXVzaWJsZS5pby9qcy9wbGF1c2libGUuanMiPjwvc2NyaXB0PgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgpgYGB7ciBsaWJyYXJpZXMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKSAgICAgICAgICMgZm9yIGdyYXBoaW5nIGFuZCBkYXRhIGNsZWFuaW5nCmxpYnJhcnkobHVicmlkYXRlKSAgICAgICAgICMgZm9yIHdvcmtpbmcgd2l0aCBkYXRlcwpsaWJyYXJ5KGRvd25sb2FkdGhpcykgICAgICAjIGZvciBhZGRpbmcgZG93bmxvYWRhYmxlIGZpbGVzIHRvIGRvY3VtZW50CmxpYnJhcnkoZGV2dG9vbHMpICAgICAgICAgICMgZm9yIGRvd25sb2FkaW5nIHBhY2thZ2VzIGZyb20gR2l0SHViLCBpbmNsdWRpbmcgZ2FyZGVuUgojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJsbGVuZHdheS9nYXJkZW5SIikgIyBydW4gaWYgcGFja2FnZSBpcyBub3QgYWxyZWFkeSBpbnN0YWxsZWQKbGlicmFyeShnYXJkZW5SKQp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKSAjIG15IGZhdm9yaXRlIGdncGxvdCB0aGVtZQojIG9sZCB3YXkgb2YgcmVhZGluZyBpbiBnYXJkZW4gZGF0YQojIGxpYnJhcnkoZ29vZ2xlc2hlZXRzNCkgICAgICMgZm9yIHJlYWRpbmcgaW4gZGF0YSBmcm9tIGdvb2dsZXNoZWV0cwojIGdzNF9kZWF1dGgoKSAgICAgICAgICAgICAgICNUbyBub3QgaGF2ZSB0byBhdXRob3JpemUgZWFjaCB0aW1lCmBgYAoKYGBge3IgZGF0YSwgaW5jbHVkZT1GQUxTRX0KZGF0YShtcGcpICMgdGhpcyBkYXRhc2V0IGlzIHBhcnQgb2YgYW4gUiBwYWNrYWdlCmRhdGEoZ2FyZGVuX2hhcnZlc3QpICMgcGFydCBvZiB0aGUgZ2FyZGVuUiBSIHBhY2thZ2UKIyB0aGlzIGRhdGFzZXQgaXMgZnJvbSBhIGdvb2dsZXNoZWV0IC0gb2xkIHdheSBvZiByZWFkaW5nIGluIGdhcmRlbiBkYXRhCiMgZ2FyZGVuX2hhcnZlc3QgPC0gcmVhZF9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMURla1NhekN6S3FQUzJqbkdoS3VlN3RMeFJVM0dWTDFveGktNGJFTTVJV3cvZWRpdD91c3A9c2hhcmluZyIpICU+JSAKIyAgIG11dGF0ZShkYXRlID0geW1kKGRhdGUpKQpgYGAKCgojIEluc3RhbGxhdGlvbgoKTWFrZSBzdXJlIHlvdSBoYXZlIHRoZSBuZXdlc3QgdmVyc2lvbnMgb2YgUiBhbmQgUlN0dWRpby4gUiBzaG91bGQgYmUgNC4xLjAgIkNhbXAgUG9udGFuZXplbiIgb3IgaGlnaGVyLiBJZiB5b3UgYXJlIGp1c3QgaW5zdGFsbGluZyBpdCBub3csIHRoZSB2ZXJzaW9uIHdpbGwgYmUgNC4xLjIgIkJpcmQgSGlwcGllIiAoaW4gY2FzZSB5b3UgYXJlIHdvbmRlcmluZywgdGhlIGludGVyZXN0aW5nIHZlcnNpb24gbmFtZXMgY29tZSBmcm9tIFtQZWFudXQgY2FydG9vbnNdKGh0dHBzOi8vbGl2ZWZyZWVvcmRpY2hvdG9taXplLmNvbS8yMDE4LzA0LzIzL3ItcmVsZWFzZS1uYW1lcy8pKS4gUlN0dWRpbyBzaG91bGQgYmUgMS40LjE3MTcgb3IgaGlnaGVyLiBUaGUgbmV3ZXN0IHZlcnNpb24gaXMgMjAyMS4wOS4yLTM4Mi4KCiAgKiBHbyB0byBbQ1JBTl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvKSAoQ29tcHJlaGVuc2l2ZSBSIEFyY2hpdmUgTmV0d29yaykgdG8gaW5zdGFsbCBSLiBDaG9vc2UgdGhlIGFwcHJvcHJpYXRlIGRvd25sb2FkIChsaWtlbHkgZWl0aGVyIE1hYyBvciBQQykuIFlvdSB3YW50IHRvIGRvd25sb2FkIHRoZSBwcmVjb21waWxlZCBiaW5hcnkgZGlzdHJpYnV0aW9ucywgbm90IHRoZSBzb3VyY2UgY29kZS4gSWYgeW91IGhhdmUgYSBNYWMsIHlvdSBzaG91bGQgdGhlbiBjaG9vc2UgdGhlIGxhdGVzdCByZWxlYXNlIHRoYXQgZW5kcyBpbiAucGtnIGFuZCB5b3UgY2FuIGRldGVybWluZSBpZiB5b3UgaGF2ZSBhbiBJbnRlbC1iYXNlZCBwcm9jZXNzb3IgYnkgZ29pbmcgdG8gdGhlIEFwcGxlIG1lbnUgKHRvcCBsZWZ0IG9mIHlvdXIgc2NyZWVuKSA+IEFib3V0IFRoaXMgTWFjIGFuZCBzZWVpbmcgaWYgdGhlIHByb2Nlc3NvciBsaXN0ZWQgaGFzIHRoZSB3b3JkIEludGVsIGluIGl0IChlLmcuIFByb2Nlc3NvciAyLjMgR0h6IER1YWwtQ29yZSBJbnRlbCBDb3JlIGk1KS4gSWYgeW91IGhhdmUgYSBQQywgeW91IHNob3VsZCBjbGljayBvbiBgYmFzZWAuIE9uY2UgaXQgZG93bmxvYWRzLCB5b3Ugd2lsbCBuZWVkIHRvIGNsaWNrIG9uIHRoZSBmaWxlIHRoYXQgd2FzIGRvd25sb2FkZWQgaW4gb3JkZXIgdG8gaW5zdGFsbCBpdC4gWW91IGNhbiBjbGljayB0aHJvdWdoIHRoZSBwcm9tcHRzIGR1cmluZyBpbnN0YWxsYXRpb24uIE9uY2UgZmluaXNoZWQsIGl0IHNob3VsZCB0ZWxsIHlvdSB0aGF0IGl0IHdhcyBpbnN0YWxsZWQgc3VjY2Vzc2Z1bGx5LiAoSWYgeW91IGhhdmUgYSBNYWMsIHlvdSBzaG91bGQgYWxzbyBkb3dubG9hZCBhbmQgaW5zdGFsbCBYUXVhcnR6IFtoZXJlXShodHRwczovL3d3dy54cXVhcnR6Lm9yZy8pLikKICAqIERvd25sb2FkIFJTdHVkaW8gZnJvbSBbdGhlaXIgd2Vic2l0ZV0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8jZG93bmxvYWQpLiBZb3Ugd2FudCB0aGUgZnJlZSBSU3R1ZGlvIERlc2t0b3AgdmVyc2lvbi4gQ2hvb3NlIHRoZSBvbmUgdGhhdCBtYXRjaGVzIHlvdXIgb3BlcmF0aW5nIHN5c3RlbSAob25lIHdpbGwgbGlrZWx5IGJlIHN1Z2dlc3RlZCB0byB5b3UgYXQgdGhlIHRvcCBvZiB0aGUgcGFnZSkuIEZvbGxvdyB0aGUgcHJvbXB0cy4gT24gYSBNYWMsIGJlIHN1cmUgdG8gZHJvcCBSU3R1ZGlvIGludG8gdGhlIGFwcGxpY2F0aW9ucyBmb2xkZXIgYXQgdGhlIGVuZCBvZiB0aGUgZG93bmxvYWQuIElmIHlvdSBoYXZlIGRvd25sb2FkZWQgaXQgYmVmb3JlLCBpdCB3aWxsIGFzayBpZiB5b3Ugd2FudCB0byB1c2UgdGhlIG5ld2VyIHZlcnNpb24uIENob29zZSB5ZXMuCiAgKiBUbyBjaGVjayB5b3VyIHZlcnNpb24gb2YgUiwgb3BlbiBSU3R1ZGlvIGFuZCBsb29rIGluIHRoZSBjb25zb2xlIChib3R0b20gbGVmdCBib3ggYnkgZGVmYXVsdCkuIEF0IHRoZSB0b3AsIGl0IHdpbGwgc2F5IHRoZSB2ZXJzaW9uIG9mIFIgeW91IGFyZSBydW5uaW5nLiBNYWtlIHN1cmUgaXQgaXMgdGhlIHZlcnNpb24geW91IGV4cGVjdC4gWW91IGNhbiBhbHNvIHR5cGUgYFIuVmVyc2lvbigpYCBpbnRvIHRoZSBjb25zb2xlIHRvIGZpbmQgdGhlIHZlcnNpb24uIFRvIGNoZWNrIHlvdXIgdmVyc2lvbiBvZiBSU3R1ZGlvLCBjbGljayBvbiB0aGUgUlN0dWRpbyBtZW51IGF0IHRoZSB0b3Agb2YgeW91ciBSU3R1ZGlvIHNlc3Npb24gYW5kIGNob29zZSBBYm91dCBSU3R1ZGlvLiBNYWtlIHN1cmUgeW91IHNlZSB0aGUgY29ycmVjdCB2ZXJzaW9uLiBZb3UgY2FuIGFsc28gdHlwZSBgUlN0dWRpby5WZXJzaW9uKClgIGludG8gdGhlIGNvbnNvbGUgdG8gZmluZCB0aGUgdmVyc2lvbi4gU2VlIHRoZSB2aWRlbyBiZWxvdyBmb3IgYSBkZW1vbnN0cmF0aW9uIG9mIGhvdyB0byBkbyB0aGlzIChub3RlIHRoYXQgdGhlIHZpZGVvIGlzIGZyb20gdGhlIHN1bW1lciBvZiAyMDIwIHNvIHdpbGwgTk9UIGhhdmUgdGhlIG1vc3QgdXAtdG8tZGF0ZSB2ZXJzaW9ucykuCgoKPGlmcmFtZSB3aWR0aD0iNTYwIiBoZWlnaHQ9IjMxNSIgc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC9XdnE1LVV1eGtRWSIgdGl0bGU9IllvdVR1YmUgdmlkZW8gcGxheWVyIiBmcmFtZWJvcmRlcj0iMCIgYWxsb3c9ImFjY2VsZXJvbWV0ZXI7IGF1dG9wbGF5OyBjbGlwYm9hcmQtd3JpdGU7IGVuY3J5cHRlZC1tZWRpYTsgZ3lyb3Njb3BlOyBwaWN0dXJlLWluLXBpY3R1cmUiIGFsbG93ZnVsbHNjcmVlbiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4KCltWb2ljZXRocmVhZDogQ2hlY2sgUiBhbmQgUlN0dWRpbyB2ZXJzaW9uXShodHRwczovL3ZvaWNldGhyZWFkLmNvbS9teXZvaWNlL3RocmVhZC8xNTAwMjU3Ny85Mzg3ODY5OCkKCiAgKiBJZiB5b3UgaGF2ZSBpc3N1ZXMgZG93bmxvYWRpbmcgb3IgdXBkYXRpbmcgZWl0aGVyIG9mIHRoZXNlLCBwbGVhc2UgY29udGFjdCB5b3VyIGluc3RydWN0b3IgYXMgZWFybHkgYXMgcG9zc2libGUuICAKICAqIElmIHlvdSBwbGFuIHRvIHVzZSBNYWNhbGVzdGVyJ3MgUlN0dWRpbyBzZXJ2ZXIsIHBsZWFzZSBzZWUgdGhpcyBbdmlkZW9dKGh0dHBzOi8vdm9pY2V0aHJlYWQuY29tL3NoYXJlLzE1MTk5MDE0LykgZm9yIGEgZmV3IHRoaW5ncyB0aGF0IHdpbGwgYmUgZGlmZmVyZW50LgoKIyBTZXR0aW5nIHVwIGZvciBzdWNjZXNzCgpQbGVhc2Ugd2F0Y2ggdGhlIHZpZGVvIGJlbG93IGFib3V0IHNldHRpbmcgdXAgZm9yIHN1Y2Nlc3MgaW4gdGhpcyBjbGFzcy4gRGV0YWlscyBmcm9tIHRoZSB2aWRlbyBhcmUgYWxzbyB3cml0dGVuIGJlbG93LCBpZiB5b3Ugd291bGQgcmF0aGVyIG5vdCB3YXRjaCB0aGUgdmlkZW8uCgo8aWZyYW1lIHdpZHRoPSI1NjAiIGhlaWdodD0iMzE1IiBzcmM9Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2VtYmVkLzB2bVk2YURXbWdVIiBmcmFtZWJvcmRlcj0iMCIgYWxsb3c9ImFjY2VsZXJvbWV0ZXI7IGF1dG9wbGF5OyBlbmNyeXB0ZWQtbWVkaWE7IGd5cm9zY29wZTsgcGljdHVyZS1pbi1waWN0dXJlIiBhbGxvd2Z1bGxzY3JlZW4gZGF0YS1leHRlcm5hbD0iMSI+PC9pZnJhbWU+CgpbVm9pY2V0aHJlYWQ6IFNldHRpbmcgdXAgZm9yIFN1Y2Nlc3NdKGh0dHBzOi8vdm9pY2V0aHJlYWQuY29tL3NoYXJlLzE1MDA5OTgyLykKClRoZXNlIGFyZSBzb21lIHN0ZXBzIHlvdSBzaG91bGQgdGFrZSB0byBzZXQgeW91cnNlbGYgdXAgZm9yIGFuIGVhc2llciB0aW1lIHVzaW5nIFIgYW5kIFJTdHVkaW8uIAoKICAqIENyZWF0ZSBhIGZvbGRlciBvbiB5b3VyIGRlc2t0b3AsIGluIHlvdXIgRG9jdW1lbnRzIGZvbGRlciwgb3Igc29tZSBvdGhlciByZWFzb25hYmxlIGxvY2F0aW9uIG9uIHlvdXIgY29tcHV0ZXIuIFRoaXMgc2hvdWxkIE5PVCBiZSBpbiB5b3VyIGRvd25sb2Fkcy4gTGV0IG1lIHNheSB0aGF0IGFnYWluLCBtb3JlIGxvdWRseSwgKipUSElTIFNIT1VMRCBOT1QgQkUgSU4gWU9VUiBET1dOTE9BRFMqKi4gR2l2ZSB0aGUgZm9sZGVyIGEgZ29vZCBuYW1lLCBsaWtlIENPTVBfU1RBVF8xMTIsIFNUQVQxNTUsIG9yIDIwMjBTUFJJTkdfU1RBVDI1MyAoSSB1c2UgdGhpcyBkb2N1bWVudCBmb3IgYWxsIHRoZXNlIGNvdXJzZXMgYnV0IHRoZSBuYW1lIHNob3VsZCBtYXRjaCB0aGUgY291cnNlIHlvdSBhcmUgdGFraW5nKS4gCiAgKiBTYXZlIHlvdXIgZG9jdW1lbnRzIHRvIHRoZSBjb3Vyc2UgZm9sZGVyIChvciBhIGZvbGRlciB3aXRoaW4gdGhhdCkgeW91IGNyZWF0ZWQsICoqTk9UKiogdG8geW91ciBkb3dubG9hZHMhIEFuZCBzYXZlIG9mdGVuISBUaGlzIGlzIG5vdCBsaWtlIEdvb2dsZSBkb2NzLiBJdCB3aWxsIG5vdCwgaW4gZ2VuZXJhbCwgYXV0byBzYXZlIGZvciB5b3UuCiAgKiBXaGVuIHlvdSBkb3dubG9hZCByZXNvdXJjZXMgZnJvbSBtb29kbGUsIHNhdmUgdGhlbSB0byB0aGUgY291cnNlIGZvbGRlciB5b3UgY3JlYXRlZC4gT24gbW9zdCBjb21wdXRlcnMsIGRvd25sb2FkZWQgZmlsZXMgd2lsbCBiZSBzYXZlZCB0byB5b3VyIGRvd25sb2Fkcy4gWW91IGNhbiBlaXRoZXIgY2hhbmdlIHRoZSBzZXR0aW5ncyBvciBiZSBzdXJlIHRvIHNhdmUgZmlsZXMgc29tZXdoZXJlIGVsc2UgYWZ0ZXIgZG93bmxvYWRpbmcuIElmIHlvdSB1c2UgYSBNYWMsIGRvIG5vdCB1c2UgU2FmYXJpIHdoZW4gZG93bmxvYWRpbmcgUiBtYXJrZG93biBmaWxlcyBmcm9tIG1vb2RsZS4gVXNlIHNvbWUgb3RoZXIgYnJvd3NlciAoQ2hyb21lLCBNb3ppbGxhLCBldGMuKS4gU2FmYXJpIHdpbGwgYWRkIGEgLnR4dCBleHRlbnNpb24gdG8gdGhlIC5ybWQgZmlsZSBhbmQgbWFrZXMgaXQgZGlmZmljdWx0IGZvciB5b3UgdG8gZml4IGl0LgogICogQ2hhbmdlIGdsb2JhbCBzZXR0aW5ncyEgR28gdG8gVG9vbHMgLS0+IEdsb2JhbCBvcHRpb25zLiBPbiB0aGUgR2VuZXJhbCB0YWIsIG5leHQgdG8gKlNhdmUgd29ya3NwYWNlIHRvIC5SRGF0YSBvbiBleGl0KiwgY2hvb3NlICpOZXZlciogYW5kIHVuY2hlY2sgdGhlIGJveCBuZXh0IHRvICpSZXN0b3JlIC5SZGF0YSBpbnRvIHdvcmtzcGFjZSBhdCBzdGFydHVwKi4gWW91IGNhbiBhbHNvIGdvIHRvIHRoZSBBcHBlYXJhbmNlIHRhYiB0byBjdXN0b21pemUgdGhlIGxvb2sgb2YgUlN0dWRpby4gCiAgKiBTcGVsbCBjaGVjay4gVGhlcmUgaXMgYSBzcGVsbCBjaGVjayBidXR0b24gKEFCQyB3aXRoIGEgY2hlY2sgbWFyayB1bmRlcm5lYXRoIGl0KS4gWW91IHNob3VsZCB1c2UgdGhhdCBmb3IgeW91ciBhbGwgYXNzaWdubWVudHMuIEluIHRoaXMgbmV3ZXN0IHZlcnNpb24gb2YgUlN0dWRpbyB0aGVyZSBpcyBhbHNvIGlubGluZSBzcGVsbGNoZWNrIHNvIHdvcmRzIGl0IGRvZXMgbm90IHJlY29nbml6ZSB3aWxsIGhhdmUgYSBzcXVpZ2dseSBsaW5lIHVuZGVyIHRoZW0uICAKICAqIERvbid0IGJlIGFmcmFpZCB0byB1c2UgdGhlIGludGVybmV0IHRvIHNlYXJjaCBmb3IgYW5zd2VycyB0byB5b3VyIHF1ZXN0aW9ucy4gSSBkbyB0aGlzIGFsbCB0aGUgdGltZS4gQW5kIHdoZW4gSSBzYXkgYWxsIHRoZSB0aW1lLCBJIG1lYW4gZXZlcnkgc2luZ2xlIHRpbWUgSSB1c2UgUi4gSSB3aWxsIHRyeSB0byBzaG93IHlvdSBleGFtcGxlcyBvZiBkb2luZyB0aGlzIGluIGNsYXNzLgoKIyBUb3VyIG9mIFJTdHVkaW8KCldhdGNoIHRoZSB2aWRlbyBiZWxvdyBmb3IgYSB0b3VyIG9mIFJTdHVkaW8uIE1vc3Qgb2Ygd2hhdCBpcyBjb3ZlcmVkIGluIHRoZSB2aWRlbyBpcyBhbHNvIHdyaXR0ZW4gb3V0IGluIHRoZSBkZXRhaWxzIG9mIHRoaXMgc2VjdGlvbi4KCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiIHNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvRktsNFYxbEdrbVUiIGZyYW1lYm9yZGVyPSIwIiBhbGxvdz0iYWNjZWxlcm9tZXRlcjsgYXV0b3BsYXk7IGVuY3J5cHRlZC1tZWRpYTsgZ3lyb3Njb3BlOyBwaWN0dXJlLWluLXBpY3R1cmUiIGFsbG93ZnVsbHNjcmVlbiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4KCltWb2ljZXRocmVhZDogUlN0dWRpbyB0b3VyXShodHRwczovL3ZvaWNldGhyZWFkLmNvbS9zaGFyZS8xNTAxMDgwNS8pCgpUaGVyZSBhcmUgZm91ciBtYWluIHBhbmVzIGluIFJTdHVkaW8uIEkgd2lsbCBkaXNjdXNzIGFsbCBmb3VyLiBJZiB5b3UgZXZlciB3YW50IHRvIGNoYW5nZSB0aGUgbGF5b3V0LCB5b3UgY2FuIGRvIHRoYXQgYnkgY2xpY2tpbmcgdGhlIGRvd24gYXJyb3cgaW4gdGhlIG1lbnUgYXQgdGhlIHRvcCBvZiBSU3R1ZGlvIHRoYXQgbG9va3MgbGlrZSBhIHdpbmRvdyB3aXRoIGZvdXIgcGFuZXMuIEFuZCwgaWYgeW91IGV2ZXIgbG9zZSBvbmUgb3IgbW9yZSBvZiB0aGUgcGFuZXMsIGNsaWNrIHRoYXQgc2FtZSBkb3duIGFycm93IGFuZCBjaG9vc2UgKlNob3cgQWxsIFBhbmVzKi4gCgojIyBTb3VyY2UKClRoZSAqbWFpbiogcGFuZSBpbiB0aGUgdG9wIGxlZnQgaGFzIHRoZSBmaWxlIHlvdSBhcmUgd29ya2luZyBmcm9tLiBJbiB0aGlzIGNsYXNzLCB3ZSB3aWxsIHdvcmsgd2l0aCBSIE1hcmtkb3duIGZpbGVzLCAucm1kIGZpbGVzIGZvciBzaG9ydC4gSSB0YWxrIGFib3V0IHRob3NlIG1vcmUgYmVsb3cuIAoKIyMgQ29uc29sZQoKVGhlICpjb25zb2xlKiBpbiB0aGUgbG93ZXIgbGVmdCBpcyB3aGVyZSB0aGUgY29kZSBpcyBldmFsdWF0ZWQuIFNpbmNlIHdlIGNhbiBhbHNvIHNlZSB0aGUgY29kZSBldmFsdWF0ZWQgd2l0aGluIHRoZSAucm1kIGZpbGUsIEkgb2Z0ZW4ga2VlcCB0aGUgY29uc29sZSBtaW5pbWl6ZWQuIEkgd2lsbCBzb21ldGltZXMgZG8gc29tZSBxdWljayBtYXRoIGluIHRoZSBjb25zb2xlLiBUaGUgYD5gIGlzICB0aGUgcHJvbXB0LCBpbmRpY2F0aW5nIHdoZXJlIHlvdSBzaG91bGQgc3RhcnQgeW91ciBjb2RlLiAKCldoZW4geW91IGtuaXQgKGNvbXBpbGUpIHlvdXIgZG9jdW1lbnQsIHRoaXMgcGFuZSB3aWxsIHNob3cgdGhlIGNvbXBsaWNhdGlvbiBwcm9jZXNzIGluIGEgdGFiIGNhbGxlZCAqUiBNYXJrZG93biouIElmIHlvdSBnZXQgYW4gZXJyb3IsIHlvdSB3aWxsIHNlZSBpdCB0aGVyZS4KCiMjIEVudmlyb25tZW50LCBIaXN0b3J5LCBDb25uZWN0aW9ucywgVHV0b3JpYWwsIChHaXQgLSBsYXRlcikKClRoZSBwYW5lIGluIHRoZSB1cHBlciByaWdodCBoYXMgYSBmZXcgdGFicyBvZiBpbnRlcmVzdC4gVGhlICpFbnZpcm9ubWVudCogdGFiIHNob3dzIGFueXRoaW5nIHRoYXQgaGFzIGJlZW4gc2F2ZWQgdG8gdGhlIHdvcmtzcGFjZS4gU28sIGlmIHlvdSByZWFkIGluIGEgZGF0YXNldCBvciBjcmVhdGUgYSBuZXcgbmFtZWQgZGF0YXNldCwgdmFyaWFibGUsIGV0Yy4sIGl0IHdpbGwgc2hvdyB1cCB0aGVyZS4gWW91IGNhbiBkbyBzb21lIGJhc2ljIGV4cGxvcmF0aW9uIG9mIHRob3NlIGl0ZW1zIGJ5IGNsaWNraW5nIG9uIHRoZW0gaW4gdGhlIEVudmlyb25tZW50LgoKVGhlICpIaXN0b3J5KiB0YWIgc2hvd3MgeW91ciBoaXN0b3J5IG9mIGNvZGUgdGhhdCBoYXMgYmVlbiBydW4gaW4gdGhpcyBzZXNzaW9uLiBJdCBpcyBzb21ldGltZXMgaGVscGZ1bCBpZiB5b3Ugd2FudCB0byBnZXQgdG8gYW4gb2xkIHBpZWNlIG9mIGNvZGUgdGhhdCB5b3UgZGVsZXRlZCBmcm9tIHlvdXIgLnJtZCBmaWxlLiAKClRoZSAqVHV0b3JpYWxzKiB0YWIgaXMgbmV3LiBJIHdvdWxkIGVuY291cmFnZSB5b3UgdG8gZXhwbG9yZSB0aGUgcmVzb3VyY2VzIGF2YWlsYWJsZSB0aGVyZS4gCgpMYXRlciBpbiB0aGUgY291cnNlLCB3ZSB3aWxsIGJlIGxlYXJuaW5nIGFib3V0IEdpdCBhbmQgR2l0SHViLiBPbmNlIHdlIHN0YXJ0IHVzaW5nIHRob3NlIHRvb2xzLCB0aGVyZSB3aWxsIGJlIGEgKkdpdCogdGFiIGkgdGhpcyBwYW5lLgoKIyMgRmlsZXMsIFBsb3RzLCBQYWNrYWdlcywgSGVscCwgVmlld2VyCgpJIHRoaW5rIHRoZSBtb3N0IGltcG9ydGFudCB0d28gdGFicyBpbiB0aGUgbG93ZXIgcmlnaHQgYXJlICpGaWxlcyogYW5kICpIZWxwKi4gSW4gdGhlICpGaWxlcyogdGFiLCB5b3UgY2FuIG5hdmlnYXRlIHRvIHZhcmlvdXMgbG9jYXRpb25zIG9uIHlvdXIgY29tcHV0ZXIuIEJ5IGRlZmF1bHQsIGl0IHdpbGwgYmUgaW4gdGhlIGZvbGRlciB3aGVyZSB0aGUgZmlsZSB5b3UgaGF2ZSBvcGVuIGlzIGxvY2F0ZWQuIAoKVGhlICpIZWxwKiB0YWIgaXMgd2hlcmUgeW91IGNhbiBnbyB0byBzZWFyY2ggZm9yIGhlbHAgd2l0aCBSIGZ1bmN0aW9ucy4gWW91IGNhbiB0eXBlIGluIGEgZnVuY3Rpb24gbmFtZSBhbmQgZ28gdG8gdGhhdCBmdW5jdGlvbidzIGhlbHAgcGFnZS4gCgojIFIgTWFya2Rvd24KCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiIHNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvTUJmYUdVZ0VQYnMiIGZyYW1lYm9yZGVyPSIwIiBhbGxvdz0iYWNjZWxlcm9tZXRlcjsgYXV0b3BsYXk7IGVuY3J5cHRlZC1tZWRpYTsgZ3lyb3Njb3BlOyBwaWN0dXJlLWluLXBpY3R1cmUiIGFsbG93ZnVsbHNjcmVlbiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4KCltWb2ljZXRocmVhZDogUiBNYXJrZG93biBJbnRyb10oaHR0cHM6Ly92b2ljZXRocmVhZC5jb20vbXl2b2ljZS90aHJlYWQvMTUwMDg1MzIvOTM5MjgzMDgpCgpUaGlzIGRvY3VtZW50IHdhcyBjcmVhdGVkIGZyb20gYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIGZpbGUgdGhhdCB3YXMgY29tcGlsZWQgdG8gYW4gaHRtbCBkb2N1bWVudC4gQWZ0ZXIgeW91IGhhdmUgaW5zdGFsbGVkIFIgYW5kIFJTdHVkaW8sIHlvdSBjYW4gZG93bmxvYWQgdGhlIFIgTWFya2Rvd24gZmlsZSBmcm9tIHRoZSBtb29kbGUgcGFnZSBhbmQgb3BlbiBpdCB0byBzZWUgdGhlICJjb2RlIiBiZWhpbmQgdGhpcyBkb2N1bWVudC4gV2Ugd2lsbCB1c2UgdGhlbSB0byBpbnRlcndlYXZlIHRleHQgd2l0aCBSIGNvZGUgYW5kIFIgb3V0cHV0ICh0YWJsZXMvZ3JhcGhzL2V0Yy4pIHRvIGNyZWF0ZSBhIGJlYXV0aWZ1bCBIVE1MIGRvY3VtZW50LiAoV29yZCBkb2NzIGFuZCBQREZzIGNhbiBhbHNvIGJlIGNyZWF0ZWQgYnV0IHdlIHVzdWFsbHkgbGlrZSB0aGUgbG9vayBhbmQgbGF5b3V0IG9mIEhUTUwgZmlsZXMgdGhlIGJlc3Qgc28gdGhhdCdzIG91ciBmb2N1cykuCgpJbiB0aGUgZnV0dXJlLCB3aGVuIHlvdSB3YW50IHRvIGNyZWF0ZSB5b3VyIG93biBkb2N1bWVudCwgSSB3b3VsZCByZWNvbW1lbmQgc3RhcnRpbmcgd2l0aCB0aGUgKlJfTWFya2Rvd25fVGVtcGxhdGUuUm1kKiBJIHBvc3RlZCBvbiB0aGUgbW9vZGxlIHBhZ2UuIE90aGVyd2lzZSwgZ28gdG8gRmlsZSAtLT4gTmV3IGZpbGUgYW5kIGNob29zZSBSIE1hcmtkb3duLiBGb2xsb3cgdGhlIHByb21wdHMgYW5kIHlvdSBhcmUgcmVhZHkgdG8gYmVnaW4hCgpXcml0aW5nIGluIGFuIFIgTWFya2Rvd24gZG9jdW1lbnQgaXMgYSBsaXR0bGUgZGlmZmVyZW50IGZyb20gd3JpdGluZyBpbiBXb3JkIG9yIG90aGVyIFdZU0lXWUcgKFdoYXQgWW91IFNlZSBJcyBXaGF0IFlvdSBHZXQpIHdvcmQgcHJvY2Vzc29yLiBJbiBSIE1hcmtkb3duIHlvdSBoYXZlIHRvIGV4cGxpY2l0bHkgdGVsbCBpdCB0byBkbyB0aGluZ3MgbGlrZSBib2xkIG9yIGl0YWxpY3MuIFRoZW4gd2hlbiB5b3Uga25pdCAoY29tcGlsZSkgdGhlIGRvY3VtZW50LCB5b3Ugc2VlIHRob3NlIGluIHRoZSBmaW5hbCBwcm9kdWN0LiBUaGUgYmVzdCB3YXkgdG8gbGVhcm4gdGhlc2UgZmVhdHVyZXMgaXMgdG8gdHJ5IHNvbWUgdGhpbmdzIG9uIHlvdXIgb3duLiBJIHJlY29tbWVuZCBoYXZpbmcgdGhlIFtSIE1hcmtkb3duIFJlZmVyZW5jZSBHdWlkZV0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTUvMDMvcm1hcmtkb3duLXJlZmVyZW5jZS5wZGYpIG9wZW4gdG8gaGVscC4gVGhpcyBjYW4gYWxzbyBiZSBmb3VuZCBvbiB0aGUgSGVscCB0b29sYmFyIGF0IHRoZSB0b3AgdW5kZXIgQ2hlYXRzaGVldHMgLS0+IFIgTWFya2Rvd24gUmVmZXJlbmNlIEd1aWRlLiAKCkxpa2UgSSBtZW50aW9uZWQgYWJvdmUsIHlvdSB3aWxsIGtuaXQgeW91ciBSIE1hcmtkb3duIGZpbGUgKC5ybWQgZmlsZSkgd2hpY2ggc2VlbWluZ2x5IG1hZ2ljYWxseSB0dXJucyBpdCBpbnRvIGEgYmVhdXRpZnVsIGh0bWwgZmlsZS4gVGhlIGh0bWwgZmlsZXMgYXJlIHdoYXQgeW91IHdpbGwgc3VibWl0IGZvciBhc3NpZ25tZW50cyBvbiBtb29kbGUuIFRvIGtuaXQgYW4gUiBNYXJrZG93biBmaWxlLCBlaXRoZXIgY2xpY2sgb24gdGhlIGljb24gYWJvdmUgdGhhdCBsb29rcyBsaWtlIGEgYmFsbCBvZiB5YXJuIHdpdGgga25pdHRpbmcgbmVlZGxlcyBpbiBpdCwgb3IgY2xpY2sgdGhlIGFycm93IG5leHQgdG8gdGhhdCBhbmQgY2hvb3NlIGtuaXQgdG8gaHRtbC4gV2hlbiB5b3Uga25pdCB0aGUgZG9jdW1lbnQsIGFuIGh0bWwgZmlsZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgdGhlIC5ybWQgZmlsZSAoYnV0IHdpdGggYW4gaHRtbCBleHRlbnNpb24pIGlzIHNhdmVkIHRvIHdoZXJldmVyIHRoZSAucm1kIGZpbGUgd2FzIHNhdmVkLiBUaGlzIGlzIHdoeSBpdCBpcyBleHRyZW1lbHkgaW1wb3J0YW50IHRoYXQgeW91IGtub3cgd2hlcmUgeW91IHNhdmVkIHlvdXIgZmlsZSBpbml0aWFsbHkhCgoqKkRJU0NMQUlNRVIqKjogSSBoYXZlIGJlZW4gdXNpbmcgUiBzaW5jZSAyMDAzLiBUaGUgZmlyc3QgdGltZSBJIHVzZWQgaXQgd2FzIGluIGEgc3RhdGlzdGljcyBjb3Vyc2UgcmlnaHQgaGVyZSBhdCBNYWNhbGVzdGVyIENvbGxlZ2UuIEkgd2FzIGFmcmFpZCBvZiBjb2RpbmcgYW5kIGNvbXBsZXRlbHkgb3ZlcndoZWxtZWQgYXQgZmlyc3QuIEkgdGhvdWdodCBJIHdvdWxkIG5ldmVyIGdldCB0aGUgaGFuZyBvZiBpdC4gSSBhc2tlZCBhIGxvdCBvZiBxdWVzdGlvbnMsIG9mdGVuIGZlZWxpbmcgbGlrZSB0aGV5IHdlcmUgcmVhbGx5IHNpbGx5IHF1ZXN0aW9ucy4gQnV0LCB0aGF0IGhlbHBlZCBtZSBsZWFybiBhbmQgY29ucXVlciBteSBmZWFyLiBTaW5jZSBJIGhhdmUgYmVlbiB1c2luZyBSIGZvciBzbyBsb25nIG5vdywgaXQgaXMgc29tZXRpbWVzIGhhcmQgZm9yIG1lIHRvIHJlbWVtYmVyIHdoYXQgcXVlc3Rpb25zIEkgaGFkIHdoZW4gSSBmaXJzdCBzdGFydGVkLiBTbywgcGxlYXNlIGFzayBxdWVzdGlvbnMhIEl0IGlzIHZlcnkgbGlrZWx5IHRoYXQgaWYgeW91IGhhdmUgYSBxdWVzdGlvbiwgc29tZW9uZSBlbHNlIGhhcyB0aGUgc2FtZSBvbmUuCgojIyBHb29kIHJlc291cmNlcwoKVGhlc2UgYXJlIGdyZWF0IHJlc291cmNlcy4gSSBhbG1vc3QgYWx3YXlzIGhhdmUgdGhlIGNoZWF0c2hlZXQgb3BlbiB3aGVuIHVzaW5nIFIgYmVjYXVzZSBJIGtub3cgSSdsbCBuZWVkIHRvIHVzZSBzb21ldGhpbmcgZnJvbSBpdC4gSSBmaW5kIHRoZSBQYW5kb2MncyBNYXJrZG93biBzZWN0aW9uIG9mIHRoZSBSIE1hcmtkb3duIENoZWF0c2hlZXQgZXNwZWNpYWxseSBoZWxwZnVsIHRvIGRvIHNvbWUgYmFzaWMsIGJ1dCBjb29sIHRoaW5ncy4gCgoqIFtSIE1hcmtkb3duIENoZWF0c2hlZXRdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLykgIAoqIFtSIE1hcmtkb3duOiBUaGUgRGVmaW5pdGl2ZSBHdWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duL2Jhc2ljcy5odG1sKSAgCiogW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9yLW1hcmtkb3duLmh0bWwpICAKCgojIyBDb2RlIGNodW5rcwoKQW4gUiBjb2RlIGNodW5rIGlzIGxvY2F0ZWQgYmVsb3csIHdpdGggc29tZSBzaW1wbGUgbWF0aCBpbiBpdC4gWW91IHNob3VsZCB1c2UgdGhlIHNob3J0Y3V0cyB0byBpbnNlcnQgYSBjb2RlIGNodW5rLiBZb3UgY2FuIGRvIHRoaXMgYnkgZ29pbmcgdG8gSW5zZXJ0IC0tPiBSICBvciBieSBwcmVzc2luZyAqQ21kK09wdGlvbitJKiAoKkN0cmwrQWx0K0kqIG9uIGEgUEMpLiAKCllvdSBjYW4gZXhlY3V0ZSB0aGUgY29kZSBjaHVuayAiaW4gbGluZSIgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiAodGhlIGdyZWVuIGFycm93KSB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ21kK1NoaWZ0K0VudGVyKiAoKkN0cmwrU2hpZnQrRW50ZXIqIG9uIGEgUEMpLiAKCllvdSBjYW4gYWxzbyBoaWdobGlnaHQgYSBwb3J0aW9uIG9mIHRoZSBjb2RlIGFuZCBjaG9vc2UgUnVuIHNlbGVjdGVkIGxpbmUocykgdXNpbmcgdGhlIGRvd24gYXJyb3cgaWNvbiBuZXh0IHRvIHRoZSBSdW4gYnV0dG9uLCBuZWFyIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIHRoaXMgZmlsZSBvciB0aGUgc2hvcnRjdXQgb2YgKlNoaWZ0K0VudGVyKi4gVGhlIG91dHB1dCBpcyBkaXNwbGF5ZWQgYmVuZWF0aCB0aGUgY29kZSBjaHVuayB3aXRoaW4gdGhpcyBtYXJrZG93biBkb2N1bWVudC4gV2hlbiB0aGUgZG9jdW1lbnQgaXMga25pdCwgaXQgd2lsbCBiZSBkaXNwbGF5ZWQgaW4gYSBzbGlnaHRseSBuaWNlciBmYXNoaW9uLgoKVGhpcyBpcyBzb21lIHJlYWxseSBzaW1wbGUgUiBjb2RlLiBJbiB0aGUgb3V0cHV0LCB0aGUgWzFdIHlvdSBzZWUgbWVhbnMgdGhhdCBpcyB0aGUgZmlyc3Qgb2JzZXJ2YXRpb24uIFNvIG5vdGljZSBiZWxvdywgdGhlcmUgYXJlIHR3byBbMV0ncyBiZWNhdXNlIHdlIGhhdmUgdHdvIGxpbmVzIG9mIGNvZGUsIHRodXMgdHdvIG91dHB1dHMuCgpgYGB7cn0KMiArIDUKMyAtIDQKYGBgCgpIZXJlIGlzIGFuIGV4YW1wbGUgb2YgbW9yZSBhZHZhbmNlZCBSIGNvZGUgdGhhdCBjcmVhdGVzIGEgc3VtbWFyeSBvZiBteSBnYXJkZW4gZGF0YS4gVGhlIG91dHB1dCBpcyBhIHRhYmxlLgoKYGBge3J9CmdhcmRlbl9oYXJ2ZXN0ICU+JSAKICBncm91cF9ieSh2ZWdldGFibGUpICU+JSAKICBzdW1tYXJpemUod2VpZ2h0ID0gc3VtKHdlaWdodCksCiAgICAgICAgICAgIHd0X2xicyA9IHdlaWdodCowLjAwMjIwNDYyKSAlPiUgCiAgYXJyYW5nZShkZXNjKHd0X2xicykpCmBgYAoKQW5kIHRoaXMgaXMgYW4gZXhhbXBsZSBvZiBjb2RlIHdoZXJlIHRoZSBvdXRwdXQgaXMgYSBwbG90LgoKYGBge3J9CmdhcmRlbl9oYXJ2ZXN0ICU+JSAKICBmaWx0ZXIoZGF0ZSA8IHltZCgiMjAyMC0wOS0wMSIpKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcml6ZSh3ZWlnaHQgPSBzdW0od2VpZ2h0KSwKICAgICAgICAgICAgd3RfbGJzID0gd2VpZ2h0KjAuMDAyMjA0NjIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gd3RfbGJzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiRGFpbHkgaGFydmVzdCBmcm9tIHRoZSAjanVuZ2xlZ2FyZGVuIChsYikiLAogICAgICAgeSA9ICIiLCB4ID0gIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTAwLDEpKQpgYGAKCktuaXQgdGhlIFIgbWFya2Rvd24gZmlsZSBieSBjaG9vc2luZyB0aGF0IG9wdGlvbiBvbiB0aGUgZG93biBhcnJvdyBuZXh0IHRvIHRoZSBLbml0IGJ1dHRvbi4gV2Ugd2lsbCBhbHdheXMgS25pdCB0byBIVE1MIGluIHRoaXMgY2xhc3MuIAoKIyMgTmFtaW5nCgpXZSB3aWxsIG9mdGVuIHdhbnQgdG8gbmFtZSBzb21ldGhpbmcgdGhhdCB3ZSB3aWxsIHVzZSBhZ2FpbiBsYXRlci4gV2UgY2FuIGRvIHRoaXMgaW4gUiB1c2luZyB0aGUgYDwtYCBub3RhdGlvbi4gIFNvLCBpbiB0aGUgY29kZSBiZWxvdywgSSBzdG9yZSBgMiArIDVgIGFzIGBzZXZlbmAuIE5vdGljZSBpdCBzaG93cyB1cCBpbiB0aGUgRW52aXJvbm1lbnQgYWZ0ZXIgZG9pbmcgdGhpcy4gVGhlbiBJIGNhbiB1c2UgYHNldmVuYCBpbiBsYXRlciBzdGVwcy4gWW91IGNhbiBzdG9yZSBtb3JlIGNvbXBsaWNhdGVkIHRoaW5ncyBhcyB3ZWxsLiBBbHNvIHNlZSB0aGUgdG9wIG9mIHRoZSBmaWxlIHdoZXJlIEkgcmVhZCBpbiBhIGRhdGFzZXQgYW5kIG5hbWUgaXQgYGdhcmRlbl9oYXJ2ZXN0YC4KCmBgYHtyfQpzZXZlbiA8LSAyICsgNQpzZXZlbgoKc2V2ZW4gKyA1CmBgYAoKIyMgQW5ub3RhdGluZyBjb2RlIAoKV2UgdXN1YWxseSBkaXNjdXNzIG91ciBjb2RlIGFuZCBvdXRwdXQgb3V0c2lkZSBvZiB0aGUgY29kZSBjaHVuayBpdHNlbGYsIGJ1dCBzb21ldGltZXMgeW91IG1pZ2h0IHdhbnQgdG8gd3JpdGUgYSBub3RlIHRvIHlvdXJzZWxmIGFib3V0IHRoZSBjb2RlIGFuZCBpdCBpcyBuaWNlIHRvIGRvIHRoYXQgaW5zaWRlIG9mIHRoZSBjb2RlLiAgVGhlIHBvdW5kIChvciBoYXNodGFnLCBhcyBtb3N0IG9mIHlvdSBwcm9iYWJseSBrbm93IGl0KSBjYW4gYmUgdXNlZCB0byBkbyB0aGF0LiBOb3RpY2UgUiBpZ25vcmVzIGV2ZXJ5dGhpbmcgYWZ0ZXIgdGhlIHBvdW5kIG9uIHRoYXQgbGluZSwgYnV0IHJ1bnMgdGhlIG5leHQgbGluZSB3aXRob3V0IGEgcHJvYmxlbS4gWW91IGNhbiBzZWUgYW5vdGhlciBleGFtcGxlIHdoZXJlIEkgdXNlIHRoaXMgdHlwZSBvZiBhbm5vdGF0aW9uIGluIHRoZSBsb2FkaW5nIGxpYnJhcnkgY29kZSBjaHVuayBhdCB0aGUgdG9wLiAKCmBgYHtyfQoyICsgNSAjd293CjMgLSA0CmBgYAoKCiMjIE9wdGlvbnMKCldpdGhpbiBlYWNoIFIgY29kZSBjaHVuaywgd2UgY2FuIGNvbnRyb2wgZGlmZmVyZW50IG9wdGlvbnMuIEZvciBleGFtcGxlLCBJIGFkZGVkIGBlY2hvPUZBTFNFYCB0byB0aGUgY2h1bmsgYmVsb3cgd2hpY2ggbWVhbnMgdGhlIGNvZGUgd2lsbCBub3QgYmUgaW4gdGhlIGh0bWwgZmlsZS4gTGV0J3Mga25pdCBpdCBhbmQgdGFrZSBhIGxvb2suCgpgYGB7ciwgZWNobz1GQUxTRX0KZ2FyZGVuX2hhcnZlc3QgJT4lIAogIGZpbHRlcihkYXRlIDwgeW1kKCIyMDIwLTA5LTAxIikpICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXplKHdlaWdodCA9IHN1bSh3ZWlnaHQpLAogICAgICAgICAgICB3dF9sYnMgPSB3ZWlnaHQqMC4wMDIyMDQ2MikgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB3dF9sYnMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJEYWlseSBoYXJ2ZXN0IGZyb20gdGhlICNqdW5nbGVnYXJkZW4gKGxiKSIsCiAgICAgICB5ID0gIiIsIHggPSAiIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAsMSkpCmBgYAoKU29tZXRpbWVzLCB3ZSB3YW50IHRvIGNvbnRyb2wgb3B0aW9ucyB0aHJvdWdob3V0IHRoZSB3aG9sZSBkb2N1bWVudC4gSWYgd2UgZ28gYmFjayB0byB0aGUgZmlyc3QgUiBjb2RlIGNodW5rLCBpdCBjb250YWlucyBga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKWAuIFRoaXMgbWVhbnMgdGhhdCB0aGUgYGVjaG89VFJVRWAgKHdoaWNoIG1lYW5zIHRoZSBjb2RlIGlzIGRpc3BsYXllZCBpbiB0aGUgb3V0cHV0IGFsb25nIHdpdGggdGhlIG91dHB1dCkgd2lsbCBiZSB0aGUgZGVmYXVsdCBpbiBhbGwgY29kZSBjaHVua3MgdW5sZXNzIHRoZSBjaHVuayBpcyBvdmVyd3JpdHRlbi4gSSBhbHNvIGFkZGVkIGB3YXJuaW5nPUZBTFNFYCBhbmQgYG1lc3NhZ2U9RkFMU0VgIHRvIHRoaXMgZG9jdW1lbnQgd2hlbiBJIHdhcyBmaW5pc2hlZC4gVGhpcyBvbWl0cyBhbGwgbWVzc2FnZXMgYW5kIHdhcm5pbmdzIGZyb20gdGhlIGtuaXR0ZWQgZmlsZS4gV2FpdCB0byBkbyB0aGlzIHVudGlsIHRoZSBlbmQgc28gdGhhdCB5b3UgZG9uJ3QgbWlzcyBhbnkgaW1wb3J0YW50IG1lc3NhZ2VzIGFuZCB3YXJuaW5ncy4KCiMjIERhdGFzZXRzCgpTb21lIG9mIHRoZSBkYXRhc2V0cyB3ZeKAmWxsIGJlIHVzaW5nIGFyZSBjb250YWluZWQgaW4gUiBwYWNrYWdlcy4gU28sIHRoZXkgYXJlIHJlYWR5IGZvciB1cyB0byBhY2Nlc3MgYW5kIHVzZS4gRm9yIGV4YW1wbGUsIHRoZSBgbXBnYCBkYXRhIGlzIGZyb20gdGhlIGB0aWR5dmVyc2VgIHBhY2thZ2UuIFRvIGZpbmQgb3V0IGRldGFpbHMgYWJvdXQgdGhlIGRhdGFzZXQsIHR5cGUgYG1wZ2AgaW4gdGhlIGhlbHAgbWVudSBvciBgP21wZ2AgaW4gdGhlIGNvbnNvbGUuCgpJbiBvcmRlciBnZXQgdGhlIGRhdGFzZXQgdG8gc2hvdyB1cCBpbiB0aGUgR2xvYmFsIEVudmlyb25tZW50LCB5b3UgbmVlZCB0byAibG9hZCIgdGhlIGRhdGEuIEl0IHdpbGwgaW5pdGlhbGx5IHNheSBgPFByb21pc2U+YCBuZXh0IHRvIGl0LCBidXQgdGhhdCB3aWxsIGNoYW5nZSBhcyBzb29uIGFzIHlvdSBhY3R1YWxseSB1c2UgdGhlIGRhdGFzZXQuIE9uY2UgeW91IGRvLCB5b3UgY2FuIHRoZW4gZ28gY2xpY2sgb24gdGhlIGRhdGFzZXQgYW5kIGEgc3ByZWFkc2hlZXQgdmlldyBvZiB0aGUgZGF0YSB3aWxsIG9wZW4uIFdlIGxvYWRlZCB0aGlzIHByZXZpb3VzbHkgKHNlZSBhYm92ZSkuIAoKRXh0ZXJuYWwgZGF0YSBjYW4gYmUgbG9hZGVkIGluIHZhcmlvdXMgd2F5cyBkZXBlbmRpbmcgaXRzIGZvcm1hdCBhbmQgd2hlcmUgaXQgaXMuIERhdGEgc3RvcmVkIGluIEdvb2dsZXNoZWV0cyBhcmUgZWFzeSB0byBsb2FkIHdpdGggdGhlIGBnb29nbGVzaGVldHM0YCBwYWNrYWdlLiBTZWUgYW4gZXhhbXBsZSBvZiB0aGF0IGluIHRoZSBkYXRhc2V0IGNvZGUgY2h1bmsgYWJvdmUgKGFsdGhvdWdoIEkgaGF2ZSBub3cgYWRkZWQgdGhhdCBkYXRhIHRvIHRoZSBgZ2FyZGVuUmAgcGFja2FnZSkuCgpJbiBhZGRpdGlvbiB0byBsb29raW5nIGF0IHRoZSBkYXRhIGluIHRoZSBzcHJlYWRzaGVldCB2aWV3ZXIsIHlvdSBtaWdodCBmaW5kIHRoZSBmb2xsb3dpbmcgY291cGxlIGZ1bmN0aW9ucyB1c2VmdWwgdG8gZXhwbG9yZSBzb21lIGJhc2ljIHByb3BlcnRpZXMgb2YgdGhlIGRhdGFzZXQuCgpUaGUgYGRpbSgpYCBmdW5jdGlvbiB0ZWxscyB1cyB0aGUgZGltZW5zaW9ucyBvZiB0aGUgZGF0YXNldCwgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgKGFsc28gY2FsbGVkIGNhc2VzIG9yIHJvd3MpIGFuZCB0aGUgbnVtYmVyIG9mIHZhcmlhYmxlcyAoYWxzbyBjYWxsZWQgY29sdW1ucykuCgpgYGB7cn0KZGltKG1wZykKYGBgCgpXZSBtYXkgd2FudCB0byBsb29rIGF0IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZGF0YXNldCB0byBtYWtlIHN1cmUgZXZlcnl0aGluZyBpcyBhcyB3ZSBleHBlY3QuCgpgYGB7cn0KaGVhZChtcGcpCmBgYAoKVGhlIGBnbGltcHNlKClgIGZ1bmN0aW9ucyBzaG93cyBhIGJyaWVmIHN1bW1hcnkgb2YgdGhlIGRhdGEuCgpgYGB7cn0KZ2xpbXBzZShtcGcpCmBgYAoKVGhlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uIGFsc28gZ2l2ZXMgYSBzdW1tYXJ5IG9mIHRoZSBkYXRhLgoKYGBge3J9CnN1bW1hcnkobXBnKQpgYGAKCiMjIFBhY2thZ2VzL0xpYnJhcmllcwoKWW91IGNhbiBydW4gUiBhcyBpcyB3aXRob3V0IGFueSBhZGRpdGlvbmFsIGZlYXR1cmVzIGJ1dCBtYW55IG9mIHRoZSB0YXNrcyB3ZSB3aWxsIHdhbnQgdG8gZG8gd2lsbCByZXF1aXJlIG9yIGJlIGVuaGFuY2VkIGJ5IGV4dHJhIHBhY2thZ2VzL2xpYnJhcmllcyAoSSB1c2UgdGhlc2Ugd29yZHMgaW50ZXJjaGFuZ2VhYmx5KS4gRG93bmxvYWQgYW5kIGluc3RhbGwgcGFja2FnZXMgYnkgZ29pbmcgdG8gdGhlIFBhY2thZ2VzIHRhYiAodG9wIG9mIGxvd2VyIHJpZ2h0IGJveCkgYW5kIGNob29zaW5nIEluc3RhbGwuIFlvdSBjYW4gdGhlbiBsaXN0IHRoZSBwYWNrYWdlcyB5b3Ugd291bGQgbGlrZSB0byBpbnN0YWxsIChhbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHVzZSBgaW5zdGFsbC5wYWNrYWdlcygpYCBmdW5jdGlvbiBpbiB0aGUgY29uc29sZSkuIE9uY2UgaW5zdGFsbGVkLCB5b3UgbmVlZCB0byBydW4gYSBgbGlicmFyeSgpYCBzdGF0ZW1lbnQgd2l0aCB0aGF0IHBhY2thZ2UgbmFtZSB0byBtYWtlIHRoZSBmdW5jdGlvbnMgd2l0aGluIHRoZW0gYXZhaWxhYmxlIGZvciB1c2UuIEkgbGlrZSB0aGlzIGFuYWxvZ3kgZnJvbSB0aGUgW01vZGVybiBEaXZlXShodHRwczovL21vZGVybmRpdmUuY29tLzEtZ2V0dGluZy1zdGFydGVkLmh0bWwjcGFja2FnZXMpIGF1dGhvcnM6IGxpYnJhcmllcyBhcmUgdG8gUiBhcyBhcHBzIGFyZSB0byBzbWFydCBwaG9uZXMuIEhvdyBtYW55IG9mIHlvdSB1c2UgYSBzbWFydCBwaG9uZSB3aXRob3V0IGFkZGl0aW9uYWwgYXBwcz8KCllvdSBzaG91bGQgcHV0IGFuIFIgY29kZSBjaHVuayB0aGF0IGxvYWRzIGFsbCB0aGUgbGlicmFyaWVzIHlvdSB3aWxsIHVzZSB0aHJvdWdob3V0IHRoZSBhc3NpZ25tZW50IGF0IHRoZSB0b3Agb2YgeW91ciBmaWxlLiBJIGhhdmUgZG9uZSB0aGF0IGluIHRoaXMgZG9jdW1lbnQuCgpUaGVyZSBhcmUgb3ZlciAxMSwwMDAgcGFja2FnZXMgb24gQ1JBTiAoYW5kIGV2ZW4gbW9yZSBhdmFpbGFibGUgb3RoZXIgcGxhY2VzIGxpa2UgZ2l0LCBldGMuKS4gSSBXSUxMIE5PVCBjb3ZlciB0aGVtIGFsbCEKCiMjIE1vZGlmeWluZyB0aGUgWUFNTAoKSW4gdGhlIFIgTWFya2Rvd24gZmlsZSwgdGhlIHBvcnRpb24gYXQgdGhlIHRvcCB3aXRoaW4gdGhlIHR3byBzZXRzIG9mIHRocmVlIGRhc2hlcywgaXMgY2FsbGVkIHRoZSBZQU1MIHNlY3Rpb24uIEl0IGlzIGEgcGxhY2Ugd2hlcmUgeW91IGNhbiBjb250cm9sIGRvY3VtZW50IHNldHRpbmdzLiBJJ2xsIHNob3cgeW91IGEgZmV3IHRoaW5ncyB5b3UgY2FuIGRvLgoKIyMjIFRoZW1lcwoKUiBNYXJrZG93biBzdXBwb3J0cyBudW1lcm91cyB0aGVtZXMuIENoZWNrIHRoZW0gb3V0IFtoZXJlXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vaHRtbC1kb2N1bWVudC5odG1sI2FwcGVhcmFuY2UtYW5kLXN0eWxlKS4gWW91IGNvdWxkIG1vZGlmeSB0aGUgWUFNTCB0byBpbmNsdWRlIGEgZGlmZmVyZW50IHRoZW1lLCBsaWtlIEkgZG8gYmVsb3cuCgpgYGAKLS0tCnRpdGxlOiAiTXkgdGl0bGUiCmF1dGhvcjogIkxpc2EgTGVuZHdheSIKZGF0ZTogIjgvMTAvMjAyMCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGpvdXJuYWwKLS0tCmBgYAojIyMgVGFibGUgb2YgQ29udGVudHMKCldlIGNhbiBhZGQgYSB0YWJsZSBvZiBjb250ZW50cyBzbyB0aGF0IGVhY2ggaGVhZGluZyAoYW5kIHN1YmhlYWRpbmcpIGNhbiBiZSBjbGlja2VkLiBXZSBvZnRlbiBsYWJlbCBob21ld29yayBleGVyY2lzZXMgdXNpbmcgaGVhZGluZ3Mgc28gdGhpcyBjYW4gYmUgYSBuaWNlIHdheSBmb3IgeW91IHRvIHF1aWNrbHkgbmF2aWdhdGUgdG8gYSBzcGVjaWZpYyBleGVyY2lzZS4KCmBgYAotLS0KdGl0bGU6ICJNeSB0aXRsZSIKYXV0aG9yOiAiTGlzYSBMZW5kd2F5IgpkYXRlOiAiOC8xMC8yMDIwIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogam91cm5hbAogICAgdG9jOiB0cnVlCi0tLQpgYGAKCiMjIyBOaWNlciB0YWJsZXMKClRhYmxlcyBkb24ndCBsb29rIGdyZWF0IGJ5IGRlZmF1bHQgaW4gdGhlIFIgb3V0cHV0LiBUaGVyZSBhcmUgbWFueSB3YXlzIHdlIGNhbiBtYWtlIHRoZW0gbG9vayBiZXR0ZXIsIGJ1dCBvbmUgcXVpY2sgd2F5IGlzIHRvIG1ha2luZyB0aGVtIGh0bWwgdGFibGVzIGJ5IGFkZGluZyBgZGZfcHJpbnQ6IHBhZ2VkYCB0byB0aGUgWUFNTCBoZWFkaW5nLgoKYGBgCi0tLQp0aXRsZTogIk15IHRpdGxlIgphdXRob3I6ICJMaXNhIExlbmR3YXkiCmRhdGU6ICI4LzEwLzIwMjAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBqb3VybmFsCiAgICB0b2M6IHRydWUKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KYGBgCgojIyMgQWRkIGEgY29kZSBkb3dubG9hZCBidXR0b24KClRoaXMgY2FuIGJlIGhlbHBmdWwgZm9yIHNoYXJpbmcgY29kZSBzbyBzb21lb25lIGNhbiBhY2Nlc3MgeW91ciAucm1kIGZpbGUgdGhyb3VnaCB0aGUgaHRtbCBmaWxlLgoKYGBgCi0tLQp0aXRsZTogIk15IHRpdGxlIgphdXRob3I6ICJMaXNhIExlbmR3YXkiCmRhdGU6ICI4LzEwLzIwMjAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBqb3VybmFsCiAgICB0b2M6IHRydWUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KYGBgCgojIyMgWUFNTCBpcyBWRVJZIHBpY2t5CgpJbmRlbnRhdGlvbiBhbmQgc3BhY2luZyBuZWVkIHRvIGJlIEVYQUNUISBMZXQncyBzZWUgd2hhdCBoYXBwZW5zIGlmICh3aGVuPykgd2UgbWFrZSBhIG1pc3Rha2UuCgoKIyMgUiBNYXJrZG93biB0aXBzCgoxLiBNYWtlIHN1cmUgeW91IGRvbid0IGhhdmUgYW55IHNwYWNlcyBvciB3ZWlyZCBjaGFyYWN0ZXJzIGluIHlvdXIgZmlsZSBuYW1lLiBJdCBpcyBiZXN0IHRvIHVzZSBsZXR0ZXJzLCBudW1iZXJzLCB1bmRlcnNjb3JlcywgYW5kIGRhc2hlcyBpbiB5b3VyIG5hbWVzLiBBbmQsIGdpdmUgaXQgYSBuYW1lIHRoYXQgaGVscHMgeW91IHJlbWVtYmVyIHdoYXQgaXQgaXMuIFRha2UgfjUgbWludXRlcyB0byByZWFkIHRocm91Z2ggYXQgbGVhc3QgdGhlIGZpcnN0IDQgc2VjdGlvbnMgb2YgdGhlc2UgW3NsaWRlc10oaHR0cHM6Ly9zbGlkZXMuZGpuYXZhcnJvLm5ldC9wcm9qZWN0LXN0cnVjdHVyZSkgYnkgRGFuaWVsbGUgTmF2YXJybyB0byBoZWxwIHlvdSBsZWFybiBiZXN0IHByYWN0aWNlcy4gIAoyLiBTYXZlIHlvdXIgZmlsZSB0byB0aGUgY291cnNlIGZvbGRlciB5b3UgY3JlYXRlZCBvciBhIGZvbGRlciB3aXRoaW4gdGhhdCwgTk9UIHRvIHlvdXIgZG93bmxvYWRzLiAgCgo8Y2VudGVyPgohW0FuYWtpbiBzYXlzLCAiSSBrbml0dGVkIHRoZSAuUm1kIGZpbGUgdG8gY3JlYXRlIHRoZSAuaHRtbCBmaWxlLiIgVG8gd2hpY2ggUGFkbWUgcmVwbGllcywgIkFuZCB5b3Uga25vdyB3aGVyZSBpdCBpcyBiZWNhdXNlIHlvdSBzYXZlZCBpdCBzb21ld2hlcmUgb3RoZXIgeW91ciBkb3dubG9hZHMgZm9sZGVyLCByaWdodD8iXShnb29kLW5hbWUtbWVtZS5qcGcpe3dpZHRoPSI1MCUifQo8L2NlbnRlcj4KCjMuIElmIHlvdSBhcmUgbm90IGdpdmVuIGEgZmlsZSB0byBzdGFydCBmcm9tLCB1c2UgdGhlIFIgbWFya2Rvd24gdGVtcGxhdGUgdGhhdCB5b3UgY2FuIGRvd25sb2FkIGJlbG93LiAgCjQuIEtuaXQgeW91ciBkb2N1bWVudCBvZnRlbiEgVGhhdCB3YXkgaWYgdGhlcmUgYXJlIGVycm9ycyBlYXJseSBvbiwgeW91IGNhbiBjYXRjaCB0aGVtLiBJZiB0aGVyZSBhcmUgZXJyb3JzIGluIHlvdXIgZG9jdW1lbnQsIHRoZXkgd2lsbCBiZSBpbmRpY2F0ZWQgd2l0aCB0aGUgbGluZSBudW1iZXIgd2hlcmUgdGhlIGVycm9yIHN0YXJ0ZWQgaW4gdGhlIFIgTWFya2Rvd24gc2VjdGlvbiAobG93ZXIgbGVmdCBjb3JuZXIgbmV4dCB0byB0aGUgQ29uc29sZSkuICAKNS4gVXNlIHRoZSBpbnRlcm5ldCB0byBoZWxwIHlvdSBzZWFyY2ggZm9yIHNvbHV0aW9ucyEgU3RhY2sgb3ZlcmZsb3cgaXMgYSBncmVhdCBwbGFjZSB0byBzdGFydC4gV2hlbiBzZWFyY2hpbmcgZm9yIFIgcmVsYXRlZCB0b3BpY3MsIGFkZCBSIHRvIHlvdXIgc2VhcmNoLiBJZiBpdCBpcyByZWxhdGVkIHRvIFIgTWFya2Rvd24sIGFkZCBSIE1hcmtkb3duLiBXZSB3aWxsIGRvIHNvbWUgb2YgdGhpcyBzZWFyY2hpbmcgdG9nZXRoZXIgaW4gY2xhc3MsIHRvby4KCmBgYHtyLCBlY2hvPUZBTFNFfQpkb3dubG9hZF9maWxlKAogIHBhdGggPSAiLi4vUl9NYXJrZG93bl9UZW1wbGF0ZS5SbWQiLAogIGJ1dHRvbl9sYWJlbCA9ICJEb3dubG9hZCBSX01hcmtkb3duX1RlbXBsYXRlIiwKICBidXR0b25fdHlwZSA9ICJpbmZvIiwKICBoYXNfaWNvbiA9IFRSVUUsCiAgaWNvbiA9ICJmYSBmYS1zYXZlIiwKICBzZWxmX2NvbnRhaW5lZCA9IEZBTFNFCikKYGBgCgojIyBDb2RlIHN0eWxlCgpBbHRob3VnaCBSIGlzIG5vdCB0ZXJyaWJseSBwaWNreSBhYm91dCBob3cgY29kZSBpcyB3cml0dGVuLCB3ZSBhcmUhIFdlIHdhbnQgdG8gd3JpdGUgcmVhZGFibGUgY29kZS4gSSB0cnkgdG8gZm9sbG93IHRoZSBbdGlkeXZlcnNlIHN0eWxlZ3VpZGVdKGh0dHA6Ly9zdHlsZS50aWR5dmVyc2Uub3JnL2luZGV4Lmh0bWwpIGFuZCB5b3Ugc2hvdWxkIGFzIHdlbGwuIEZvciBleGFtcGxlLCBpbiBhbGwgdGhlIGBnZ3Bsb3RgIGNvZGUsIGEgbmV3IGxpbmUgaXMgc3RhcnRlZCBhZnRlciBhIGArYC4gTGF0ZXIgd2Ugd2lsbCBzZWUgdGhhdCB3ZSBzdGFydCBhIG5ldyBsaW5lIG9mIGNvZGUgYWZ0ZXIgYSBwaXBlLCBgJT4lYC4gQ29kZSB0aGF0IGlzIGRpZmZpY3VsdCB0byByZWFkIG1heSBiZSBkZWR1Y3RlZCBwb2ludHMgb24gaG9tZXdvcmsgYXNzaWdubWVudHMuCgoKCg==