Health Warning - I’ve have only just started learning this stuff myself, so this document is bound to contain some key omissions and errors. As I continue this journey, I will update and refine and hopefully, in a few years, it might be something like a definitive guide!!

In this practical session, you will learn how to produce work that is open, reproducible and portable using RStudio, RMarkdown, Git and Github. You will be able to use the information contained in this guide to prepare the submission for Part 1 of the assessment for this course. The tools you will use are:

1 Setting up GitHub to store your code

  1. If you are working on your own computer, you will first need to install git - https://git-scm.com/ - if you are working on the UCL Remote Desktop, you won’t need to do this as it is already installed for you.

  2. Go to http://github.com and install github (if working on your own computer). Create an account and create a new repository (call it anything you like - ‘gis_code’ or something similar), making sure it is public and you check the box that says ‘initialise new repository with a README’ - click ‘create repository’ at the bottom

Figure 1 - Setting Up Your GitHub Repo

Figure 1 - Setting Up Your GitHub Repo

  1. Your new repository (‘repo’) will be created and this is where you will be able to store your code online. You will notice that a README.md markdown file has also been created. This can be edited to tell people what they are likely to find in this repository.

  2. Now you have created your repo online, you need to ‘clone’ it so that there is an identical copy of it in a local folder on your computer.

There are a couple of ways of doing this, but the easy one is to use the GUI that comes packaged with your git installation.

  1. The first thing you need to do is copy the Clone URL for your repo from the github website - click the green button in your repo for ‘Clone or Download’ and copy the link:
Figure 2 - Getting Your Clone Link

Figure 2 - Getting Your Clone Link

  1. Now in the windows start menu, go to git > GUI
Figure 3 - Git GUI 1

Figure 3 - Git GUI 1

  1. Select ‘Clone Existing Repository’ and paste the link from your GitHub account into the top box and the local directory that you want to create to store your repo in the bottom box (note, you will need to add a name for a new folder, once you have selected an existing directory).
Figure 4 - Git GUI 2

Figure 4 - Git GUI 2

  1. After a few moments, you should now be able to view a copy of your GitHub repo on your local machine. This is where you will be able to store all of your code and some other files for your reproducible research.

2 Using RStudio with git

Now, as I’ve mentioned before, RStudio is totally bad-ass. Not only does it make R fun to use, but the lovely people who created it also built in support for things like git!

For a full and excellent tutorial on using Git with R Studio, watch this webinar: https://www.rstudio.com/resources/webinars/rstudio-essentials-webinar-series-managing-part-2/

If you don’t want to watch the vid, I’ll do a quick summary below. So, to use git, first you need to enable it in RStudio:

2.0.1 Issues with the RStudio Installation on the UCL Remote Desktop

At the time of writing, because of the way that RStudio has been installed on the UCL Remote Desktop, git integration does not work. As such, if you are working on the remote desktop, DO NOT follow instructions 9 to 19 below, jump straight to instruction 20. If you are working on your own computer then fine, carry on.

2.1 Using RStudio with git, continued…

  1. Open RStudio. In RStudio Tools > Global Options, under ‘Git/SVN’ check the box to allow version control and locate the folder on your computer where the git.exe file is located. Allow Version Control for new Projects and navigate to where the git.exe file is on your computer. Click OK.
Figure 5 - Allow Version Control

Figure 5 - Allow Version Control

  1. Now in RStudio, you should create a new project in an existing directory - File > New Project > Existing directory - choose your new git repository as your new project folder. You may not need to restart RStudio.

2.2 Saving your work to your local cloned repo

  1. Open a new R Notebook in RStudio: File > New File R Notebook

  2. Type some stuff (anything so that’s it’s not a blank empty file) at the top of the file and save it.

  3. As well as saving, which saves a copy to our local directory, we will also ‘commit’ or create a save point for our work on git. To do this, you should click the ‘git’ icon and up will pop a menu like the one below:

Figure 6a - Git Integration with RStudio 1

Figure 6a - Git Integration with RStudio 1

You can also click the Git tab that will have appeared in the top-right window of RStudio

Figure 6b - Git Integration with RStudio 2

Figure 6b - Git Integration with RStudio 2

  1. To Commit (save) the changes in this file to your local cloned git repository, first click ‘Commit’

  2. Up will then pop another window that looks a little like the one below:

Figure 7 - Reviewing Changes

Figure 7 - Reviewing Changes

  1. In this window, you will be able to review the differences between any previous saves you have made to your document and the current changes. If you are happy with the changes, you can then select the file and click ‘commit’ to save them to your current local repo. If you are not happy, then you can always revert back to a previous version that you know did work!

  2. If I were you, I would save R Scripts or RMarkdown Documents using the usual save button quite regularly, and then every time you, then you can commit your changes then.

2.3 Pushing your changes to GitHub

  1. Once you are happy with your progress, you should also then ‘Push’ your changes to your online GitHub repo. This is important, both for backing up your work, but also for keeping a reproducable record of your research.

  2. To do this, first make sure you have committed any changes to your local cloned repo and then click the ‘Push’ button to whizz your code up to your master GitHub repo - you will probably be prompted to enter your github username and password to enable this…

Figure 8 - Pushing to GitHub

Figure 8 - Pushing to GitHub

#Git without RStudio Integration

Now, if you would like to use git but your’re working on the UCL Remote Desktop or you are experiening other problems with getting git working in RStudio, fear not, you can just use your raw git installation.

  1. In the Start Menu, open the git GUI. Start > Git > Git GUI. You should open the existing repository that you have just created.

  2. Whenever you have made some changes to your files in your cloned repo, you can use git to review the changes and ‘Commit’ (save) them and then ‘Push’ them up to your master repository on GitHub.

  3. To review and commit your changes, in the commit menu, simply:

  1. scan for changes
  2. stage them ready for committing
  3. commit the changes
  4. push the changes to your GitHub repo
Figure 9 - Git Gui Commit

Figure 9 - Git Gui Commit

  1. Try it. Add some new text to your .Rmd file. Save it. Rescan in the Git GUI to check for changes. Stage those changes one-by-one. Commit them (remembering to input a commit message). Then once committed, try using Remote > Push to send the changes to github (*note, you will be asked for your username and password to complete this.)

2.4 Possible git problems - Merging

  1. There are many many possible git problems. I’ve just started with this and have come across loads (mainly to do with merging) already. As you continute to commit and push work, especially when using different clones, you may well run into things like merge conflicts and a whole load of other problems. I’ve just been trying to fix a merge conflict for the last hour and eventually got there. It’s not easy. It’s not pretty. But as ever, there is usually a guide somewhere on the internet to help you.

For merge conflicts, try here: https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

For general github help, try here: https://help.github.com/

  1. An initial tip from me - looks like whenever you are working with a local github repo, if you come back to your work after shutting down and restarting, then the first thing you should do is ‘Pull’ from your GitHub repo before going any further. If you don’t, you may well have all kinds of fun to solve with merging files together afterwards.

Good luck!!

3 Reproducible Research Using R Markdown

OK, so now you have set everything up so that you can become a reproducable research ninja! All that remains is to do some reproducable research!

For the definitive guide on R Markdown, please read R Markdown: The Definitive Guide - obviously! It will tell you everything you need to know, far beyond what I am telling you here.

There is also an excellent guide on the R Studio website -https://rmarkdown.rstudio.com/lesson-1.html

And a quick cheatsheet here: https://github.com/rstudio/cheatsheets/raw/master/rmarkdown-2.0.pdf

And an older one here: http://www.rstudio.com/wp-content/uploads/2016/03/rmarkdown-cheatsheet-2.0.pdf

One of the awesome things about R Markdown is it can be converted into a range of different formats - html for webpages, word documents, PDFs, blogs, books - virtually everything!

Now, earlier on in this exercise, I got you to open a new R Notebook or R Markdown file. They are both R Markdown Documents, but the Notebook allows chunks of code to be run independently.

  1. Go back to the notebook you created earlier in step 11. We are now going to insert some code from the practical last week and run it.

  2. In RStudio, you can either select Code > Insert Chunk or you can Click the ‘Insert’ button and insert an R Chunk

Figure 8 - Insert R Chunk

Figure 8 - Insert R Chunk

  1. A box will appear and in this box, you will be able to enter and run your R code. Try pasting in:
library(tidyverse)
library(geojsonio)
library(sf)
library(tmap)
library(tmaptools)
#read some data attributes
LondonData <- read_csv("https://files.datapress.com/london/dataset/ward-profiles-and-atlas/2015-09-24T14:21:24/ward-profiles-excel-version.csv", na = "n/a")
#read some geometries
EW <- geojson_read("http://geoportal.statistics.gov.uk/datasets/8edafbe3276d4b56aec60991cbddda50_2.geojson", what = "sp")
#pull out London
LondonMap <- EW[grep("^E09",EW@data$lad15cd),]
#convert to a simple features object
LondonMapSF <- st_as_sf(LondonMap)
#append the data to the geometries
LondonMapSF <- append_data(LondonMapSF,LondonData, key.shp = "lad15cd", key.data = "New code", ignore.duplicates = TRUE)
#plot a choropleth
qtm(LondonMapSF, fill = "% Not Born in UK - 2011")

  1. When including code chunks in your work, there are various options that allow you to do things like include the code, but not run it: display the output but not the code, hide warnings etc. Most of these can be input automatically by clicking the cog icon in the top-right of the chunk.
Figure 9 - Chunk Options

Figure 9 - Chunk Options

  1. Various other options and tips can be found in the full R Markdown guide on RStudio here: https://rmarkdown.rstudio.com/lesson-1.html and in this the cheatsheets linked to above.

4 Adding References to Your Work

Now, as you build up your documentation for the work you are doing, it is likely that you will want to include references to support your arguments.

Building a bibliography in your R Markdown document is quite simple, you will just need to install some additional packages that plug into RStudio and learn how to export your bibliography from your reference management software.

4.1 Exporting a bibliography from Zotero

Here I will assume that you are going to be using Zotero as your reference management software. If you use other software, there are probably similar options for exporting available to you, so don’t worry.

The aim is to get a list of references that are stored in a format known as BibTeX - http://www.bibtex.org/

I won’t go into BibTeX now, but if you go on to write your dissertation using LaTeX, then BibTeX is the format that you will use to store your references.

  1. Having built up a bibliograpy of relevant literature in zotero, you should export it in BibTeX format and save it to the same directory that your R Markdown project is located in. Go to File > Export Library and select BibTeX as your format.
Figure 10 - Zotero Export

Figure 10 - Zotero Export

  1. Once your BibTex file is saved into the same directory as your ## Using your bibliography in your R Markdown document

To find your bibliography, you need to insert its name into the YAML header at the very top of the file (more about the YAML header in a minute) - see below:

---
title: "Producing Reproducible Research Using RMarkdown and Github"
output:
  html_notebook: default
  word_document: default
  
author: Adam Dennett
bibliography: 
 - RReferences.bib
  
---

4.2 Adding References Using citr

  1. To add add citations from your bibliography, you can then use the citr package, which runs in an addin within RStudio
install.packages("citr")
library(citr)
  1. In the ‘Addins’ menu near the top of RStudio, you should (once RStudio has been restarted) have a citr option for ‘Insert citations’ and including them in your work.
Figure 11 - Citr Addin

Figure 11 - Citr Addin

  1. Try adding some citations from your BibTeX library… You will find that once you have added them into the text, citr will build a bibliography at the bottom of your document for you - neat, hey?!

Here is a reference for a seminal and totally game changing paper by Dennett and Page (2017). Here is another reference (Xie, Allaire, and Grolemund 2018) that heped me write this post. Once you knit your document into an output file, the references will all stack up alphabetically at the bottom of the file…

5 Knitting your final output

Once you have incorporated some text and code into a test .Rmd document, you should now be able to knit it into a format of your choice.

Information to help format your knitted file is contained in the YAML header at the top. In here, you can add things like tables of contents, apply specific themes, etc.

For a selection of nice themes, see here: http://www.datadreaming.org/post/r-markdown-theme-gallery/

For things like adding Tables of Contents, tabbed sections (in HTML), figure and table parameters: https://bookdown.org/yihui/rmarkdown/html-document.html

If you have selected an R Markdown Notebook, in the menu bar at the top of the page, you should see a ‘Preview’ button. If you click this, your .Rmd file will be knitted automatically into an interactive html document - try it!

If you click the small arrow next to the preview button, a menu will appear giving you the option to knit into a selection of other formats, including PDF and Word. Try those too…

Figure 12 - knitting

Figure 12 - knitting

6 Further Reading

Since starting this little guide, I have come across this amazing book on using R and GitHub, by Jenny Bryan and Jim Hester. It’s brilliant - taught me things like how to avoid entering user credentials every time I push to my GitHub repo (Ch 11) - get involved! http://happygitwithr.com/

7 References

Dennett, Adam, and Sam Page. 2017. “The Geography of London’s Recent Beer Brewing Revolution.” The Geographical Journal 183 (4): 440–54. https://doi.org/10.1111/geoj.12228.

Xie, Yihui, J.J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. https://bookdown.org/yihui/rmarkdown/.

LS0tDQp0aXRsZTogIlByb2R1Y2luZyBSZXByb2R1Y2libGUgUmVzZWFyY2ggVXNpbmcgUk1hcmtkb3duIGFuZCBHaXRodWIiDQphdXRob3I6ICJBZGFtIERlbm5ldHQiDQpkYXRlOiAiMTIvMTAvMjAxOCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgZmlnX2hlaWdodDogNA0KICAgIGZpZ193aWR0aDogNQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDINCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnMicNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnMicNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzInDQpiaWJsaW9ncmFwaHk6IFJSZWZlcmVuY2VzLmJpYg0KLS0tDQoNCioqSGVhbHRoIFdhcm5pbmcgLSBJJ3ZlIGhhdmUgb25seSBqdXN0IHN0YXJ0ZWQgbGVhcm5pbmcgdGhpcyBzdHVmZiBteXNlbGYsIHNvIHRoaXMgZG9jdW1lbnQgaXMgYm91bmQgdG8gY29udGFpbiBzb21lIGtleSBvbWlzc2lvbnMgYW5kIGVycm9ycy4gQXMgSSBjb250aW51ZSB0aGlzIGpvdXJuZXksIEkgd2lsbCB1cGRhdGUgYW5kIHJlZmluZSBhbmQgaG9wZWZ1bGx5LCBpbiBhIGZldyB5ZWFycywgaXQgbWlnaHQgYmUgc29tZXRoaW5nIGxpa2UgYSBkZWZpbml0aXZlIGd1aWRlISEqKg0KDQpJbiB0aGlzIHByYWN0aWNhbCBzZXNzaW9uLCB5b3Ugd2lsbCBsZWFybiBob3cgdG8gcHJvZHVjZSB3b3JrIHRoYXQgaXMgb3BlbiwgcmVwcm9kdWNpYmxlIGFuZCBwb3J0YWJsZSB1c2luZyBSU3R1ZGlvLCBSTWFya2Rvd24sIEdpdCBhbmQgR2l0aHViLiBZb3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSB0aGUgaW5mb3JtYXRpb24gY29udGFpbmVkIGluIHRoaXMgZ3VpZGUgdG8gcHJlcGFyZSB0aGUgc3VibWlzc2lvbiBmb3IgUGFydCAxIG9mIHRoZSBhc3Nlc3NtZW50IGZvciB0aGlzIGNvdXJzZS4gDQpUaGUgdG9vbHMgeW91IHdpbGwgdXNlIGFyZToNCg0KKiBbUlN0dWRpb10oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vKSBpcyBhIGdyYXBoaWNhbCB1c2VyIGludGVyZmFjZSAodGhhdCB5b3Ugc2hvdWxkIGFscmVhZHkgYmUgZmFtaWxpYXIgd2l0aCkgLSBpdCBjb250YWlucyBhIG51bWJlciBvZiBmZWF0dXJlcyB3aGljaCBtYWtlIGl0IGV4Y2VsbGVudCBmb3IgYXV0aG9yaW5nIHJlcHJvZHVjaWJsZSBhbmQgb3BlbiBnZW9ncmFwaGljIGRhdGEgc2NpZW5jZSB3b3JrLiANCg0KKiBSTWFya2Rvd24gaXMgYSB2ZXJzaW9uIG9mIHRoZSBbTWFya2Rvd25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hcmtkb3duKSBtYXJrdXAgbGFuZ3VhZ2Ugd2hpY2ggZW5hYmxlcyBwbGFpbiB0ZXh0IHRvIGJlIGZvcm1hdHRlZCB0byBjb250YWluIGxpbmtzIHRvIGRhdGEsIGNvZGUgdG8gcnVuLCB0ZXh0IHRvIGV4cGxhaW4gd2hhdCB5b3UgYSBwcm9kdWNpbmcgYW5kIG1ldGFkYXRhIHRvIHRlbGwgeW91ciBzb2Z0d2FyZSB3aGF0IGtpbmRzIG9mIG91dHB1dHMgdG8gZ2VuZXJhdGUgZnJvbSB5b3VyIG1hcmtkb3duIGNvZGUuIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIFJNYXJrZG93biwgdmlzaXQgW2hlcmVdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2xlc3Nvbi0xLmh0bWwpLg0KDQoqIFtHaXRdKGh0dHBzOi8vZ2l0LXNjbS5jb20vKSBpcyBhIHNvZnR3YXJlIHZlcnNpb24gY29udHJvbCBzeXN0ZW0gd2hpY2ggYWxsb3dzIHlvdSB0byBrZWVwIHRyYWNrIG9mIHRoZSBjb2RlIHlvdSBwcm9kdWNlIGFuZCB0aGUgY2hhbmdlcyB0aGF0IHlvdSBvciBvdGhlcnMgbWFrZSB0byBpdC4gDQoNCiogW0dpdEh1Yl0oaHR0cHM6Ly9naXRodWIuY29tLykgaXMgYW4gb25saW5lIHJlcG9zaXRvcnkgdGhhdCBhbGxvd3MgYW55b25lIHRvIHZpZXcgdGhlIGNvZGUgeW91IGhhdmUgcHJvZHVjZWQgKGluIHdoYXRldmVyIGxhbmd1YWdlIHlvdSBjaG9vc2UgdG8gcHJvZ3JhbSBpbikgYW5kIHVzZS9zY3J1dGluaXNlL2NvbnRyaWJ1dGUgdG8vY29tbWVudCBvbiBpdC4gIA0KDQojIFNldHRpbmcgdXAgR2l0SHViIHRvIHN0b3JlIHlvdXIgY29kZQ0KDQooQCkgSWYgeW91IGFyZSB3b3JraW5nIG9uIHlvdXIgb3duIGNvbXB1dGVyLCB5b3Ugd2lsbCBmaXJzdCBuZWVkIHRvIGluc3RhbGwgZ2l0IC0gaHR0cHM6Ly9naXQtc2NtLmNvbS8gLSBpZiB5b3UgYXJlIHdvcmtpbmcgb24gdGhlIFVDTCBSZW1vdGUgRGVza3RvcCwgeW91IHdvbid0IG5lZWQgdG8gZG8gdGhpcyBhcyBpdCBpcyBhbHJlYWR5IGluc3RhbGxlZCBmb3IgeW91LiANCg0KKEApIEdvIHRvIGh0dHA6Ly9naXRodWIuY29tIGFuZCBpbnN0YWxsIGdpdGh1YiAoaWYgd29ya2luZyBvbiB5b3VyIG93biBjb21wdXRlcikuIENyZWF0ZSBhbiBhY2NvdW50IGFuZCBjcmVhdGUgYSBuZXcgcmVwb3NpdG9yeSAoY2FsbCBpdCBhbnl0aGluZyB5b3UgbGlrZSAtICdnaXNfY29kZScgb3Igc29tZXRoaW5nIHNpbWlsYXIpLCBtYWtpbmcgc3VyZSBpdCBpcyBwdWJsaWMgYW5kIHlvdSBjaGVjayB0aGUgYm94IHRoYXQgc2F5cyAnaW5pdGlhbGlzZSBuZXcgcmVwb3NpdG9yeSB3aXRoIGEgUkVBRE1FJyAtIGNsaWNrICdjcmVhdGUgcmVwb3NpdG9yeScgYXQgdGhlIGJvdHRvbQ0KDQohW0ZpZ3VyZSAxIC0gU2V0dGluZyBVcCBZb3VyIEdpdEh1YiBSZXBvXShpbWFnZXMvZ2l0X3JlcG9fc2V0dXAucG5nKQ0KDQoNCihAKSBZb3VyIG5ldyByZXBvc2l0b3J5ICgncmVwbycpIHdpbGwgYmUgY3JlYXRlZCBhbmQgdGhpcyBpcyB3aGVyZSB5b3Ugd2lsbCBiZSBhYmxlIHRvIHN0b3JlIHlvdXIgY29kZSBvbmxpbmUuIFlvdSB3aWxsIG5vdGljZSB0aGF0IGEgUkVBRE1FLm1kIG1hcmtkb3duIGZpbGUgaGFzIGFsc28gYmVlbiBjcmVhdGVkLiBUaGlzIGNhbiBiZSBlZGl0ZWQgdG8gdGVsbCBwZW9wbGUgd2hhdCB0aGV5IGFyZSBsaWtlbHkgdG8gZmluZCBpbiB0aGlzIHJlcG9zaXRvcnkuICANCg0KKEApIE5vdyB5b3UgaGF2ZSBjcmVhdGVkIHlvdXIgcmVwbyBvbmxpbmUsIHlvdSBuZWVkIHRvICdjbG9uZScgaXQgc28gdGhhdCB0aGVyZSBpcyBhbiBpZGVudGljYWwgY29weSBvZiBpdCBpbiBhIGxvY2FsIGZvbGRlciBvbiB5b3VyIGNvbXB1dGVyLiANCg0KVGhlcmUgYXJlIGEgY291cGxlIG9mIHdheXMgb2YgZG9pbmcgdGhpcywgYnV0IHRoZSBlYXN5IG9uZSBpcyB0byB1c2UgdGhlIEdVSSB0aGF0IGNvbWVzIHBhY2thZ2VkIHdpdGggeW91ciBnaXQgaW5zdGFsbGF0aW9uLiANCg0KKEApIFRoZSBmaXJzdCB0aGluZyB5b3UgbmVlZCB0byBkbyBpcyBjb3B5IHRoZSBDbG9uZSBVUkwgZm9yIHlvdXIgcmVwbyBmcm9tIHRoZSBnaXRodWIgd2Vic2l0ZSAtIGNsaWNrIHRoZSBncmVlbiBidXR0b24gaW4geW91ciByZXBvIGZvciAnQ2xvbmUgb3IgRG93bmxvYWQnIGFuZCBjb3B5IHRoZSBsaW5rOg0KDQohW0ZpZ3VyZSAyIC0gR2V0dGluZyBZb3VyIENsb25lIExpbmtdKGltYWdlcy9jb3B5X2Nsb25lX2xpbmsucG5nKQ0KDQooQCkgTm93IGluIHRoZSB3aW5kb3dzIHN0YXJ0IG1lbnUsIGdvIHRvIGdpdCA+IEdVSSANCg0KIVtGaWd1cmUgMyAtIEdpdCBHVUkgMV0oaW1hZ2VzL2dpdF9ndWkxLnBuZykNCg0KDQooQCkgU2VsZWN0ICdDbG9uZSBFeGlzdGluZyBSZXBvc2l0b3J5JyBhbmQgcGFzdGUgdGhlIGxpbmsgZnJvbSB5b3VyIEdpdEh1YiBhY2NvdW50IGludG8gdGhlIHRvcCBib3ggYW5kIHRoZSBsb2NhbCBkaXJlY3RvcnkgdGhhdCB5b3Ugd2FudCB0byBjcmVhdGUgdG8gc3RvcmUgeW91ciByZXBvIGluIHRoZSBib3R0b20gYm94ICgqbm90ZSwgeW91IHdpbGwgbmVlZCB0byBhZGQgYSBuYW1lIGZvciBhIG5ldyBmb2xkZXIsIG9uY2UgeW91IGhhdmUgc2VsZWN0ZWQgYW4gZXhpc3RpbmcgZGlyZWN0b3J5KikuDQoNCiFbRmlndXJlIDQgLSBHaXQgR1VJIDJdKGltYWdlcy9naXRfZ3VpMi5wbmcpDQoNCihAKSBBZnRlciBhIGZldyBtb21lbnRzLCB5b3Ugc2hvdWxkIG5vdyBiZSBhYmxlIHRvIHZpZXcgYSBjb3B5IG9mIHlvdXIgR2l0SHViIHJlcG8gb24geW91ciBsb2NhbCBtYWNoaW5lLiBUaGlzIGlzIHdoZXJlIHlvdSB3aWxsIGJlIGFibGUgdG8gc3RvcmUgYWxsIG9mIHlvdXIgY29kZSBhbmQgc29tZSBvdGhlciBmaWxlcyBmb3IgeW91ciByZXByb2R1Y2libGUgcmVzZWFyY2guIA0KDQojIFVzaW5nIFJTdHVkaW8gd2l0aCBnaXQNCg0KTm93LCBhcyBJJ3ZlIG1lbnRpb25lZCBiZWZvcmUsIFJTdHVkaW8gaXMgdG90YWxseSBiYWQtYXNzLiBOb3Qgb25seSBkb2VzIGl0IG1ha2UgUiBmdW4gdG8gdXNlLCBidXQgdGhlIGxvdmVseSBwZW9wbGUgd2hvIGNyZWF0ZWQgaXQgYWxzbyBidWlsdCBpbiBzdXBwb3J0IGZvciB0aGluZ3MgbGlrZSBnaXQhDQoNCkZvciBhIGZ1bGwgYW5kIGV4Y2VsbGVudCB0dXRvcmlhbCBvbiB1c2luZyBHaXQgd2l0aCBSIFN0dWRpbywgd2F0Y2ggdGhpcyB3ZWJpbmFyOiBodHRwczovL3d3dy5yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvd2ViaW5hcnMvcnN0dWRpby1lc3NlbnRpYWxzLXdlYmluYXItc2VyaWVzLW1hbmFnaW5nLXBhcnQtMi8gDQoNCklmIHlvdSBkb24ndCB3YW50IHRvIHdhdGNoIHRoZSB2aWQsIEknbGwgZG8gYSBxdWljayBzdW1tYXJ5IGJlbG93LiBTbywgdG8gdXNlIGdpdCwgZmlyc3QgeW91IG5lZWQgdG8gZW5hYmxlIGl0IGluIFJTdHVkaW86DQoNCiMjIyBJc3N1ZXMgd2l0aCB0aGUgUlN0dWRpbyBJbnN0YWxsYXRpb24gb24gdGhlIFVDTCBSZW1vdGUgRGVza3RvcA0KDQpBdCB0aGUgdGltZSBvZiB3cml0aW5nLCBiZWNhdXNlIG9mIHRoZSB3YXkgdGhhdCBSU3R1ZGlvIGhhcyBiZWVuIGluc3RhbGxlZCBvbiB0aGUgVUNMIFJlbW90ZSBEZXNrdG9wLCBnaXQgaW50ZWdyYXRpb24gZG9lcyBub3Qgd29yay4gQXMgc3VjaCwgaWYgeW91IGFyZSB3b3JraW5nIG9uIHRoZSByZW1vdGUgZGVza3RvcCwgRE8gTk9UIGZvbGxvdyBpbnN0cnVjdGlvbnMgOSB0byAxOSBiZWxvdywganVtcCBzdHJhaWdodCB0byBpbnN0cnVjdGlvbiAyMC4gSWYgeW91IGFyZSB3b3JraW5nIG9uIHlvdXIgb3duIGNvbXB1dGVyIHRoZW4gZmluZSwgY2Fycnkgb24uIA0KDQojIyBVc2luZyBSU3R1ZGlvIHdpdGggZ2l0LCBjb250aW51ZWQuLi4gDQoNCihAKSBPcGVuIFJTdHVkaW8uIEluIFJTdHVkaW8gVG9vbHMgPiBHbG9iYWwgT3B0aW9ucywgdW5kZXIgJ0dpdC9TVk4nIGNoZWNrIHRoZSBib3ggdG8gYWxsb3cgdmVyc2lvbiBjb250cm9sIGFuZCBsb2NhdGUgdGhlIGZvbGRlciBvbiB5b3VyIGNvbXB1dGVyIHdoZXJlIHRoZSBnaXQuZXhlIGZpbGUgaXMgbG9jYXRlZC4gQWxsb3cgVmVyc2lvbiBDb250cm9sIGZvciBuZXcgUHJvamVjdHMgYW5kIG5hdmlnYXRlIHRvIHdoZXJlIHRoZSBnaXQuZXhlIGZpbGUgaXMgb24geW91ciBjb21wdXRlci4gQ2xpY2sgT0suIA0KDQohW0ZpZ3VyZSA1IC0gQWxsb3cgVmVyc2lvbiBDb250cm9sXShpbWFnZXMvcnN0dWRpb19hbGxvd192ZXJzaW9uLnBuZykNCg0KKEApIE5vdyBpbiBSU3R1ZGlvLCB5b3Ugc2hvdWxkIGNyZWF0ZSBhIG5ldyBwcm9qZWN0IGluIGFuIGV4aXN0aW5nIGRpcmVjdG9yeSAtIEZpbGUgPiBOZXcgUHJvamVjdCA+IEV4aXN0aW5nIGRpcmVjdG9yeSAtIGNob29zZSB5b3VyIG5ldyBnaXQgcmVwb3NpdG9yeSBhcyB5b3VyIG5ldyBwcm9qZWN0IGZvbGRlci4gWW91IG1heSBub3QgbmVlZCB0byByZXN0YXJ0IFJTdHVkaW8uIA0KDQojIyBTYXZpbmcgeW91ciB3b3JrIHRvIHlvdXIgbG9jYWwgY2xvbmVkIHJlcG8NCg0KKEApIE9wZW4gYSBuZXcgUiBOb3RlYm9vayBpbiBSU3R1ZGlvOiBGaWxlID4gTmV3IEZpbGUgUiBOb3RlYm9vaw0KDQooQCkgVHlwZSBzb21lIHN0dWZmIChhbnl0aGluZyBzbyB0aGF0J3MgaXQncyBub3QgYSBibGFuayBlbXB0eSBmaWxlKSBhdCB0aGUgdG9wIG9mIHRoZSBmaWxlIGFuZCBzYXZlIGl0Lg0KDQooQCkgQXMgd2VsbCBhcyBzYXZpbmcsIHdoaWNoIHNhdmVzIGEgY29weSB0byBvdXIgbG9jYWwgZGlyZWN0b3J5LCB3ZSB3aWxsIGFsc28gJ2NvbW1pdCcgb3IgY3JlYXRlIGEgc2F2ZSBwb2ludCBmb3Igb3VyIHdvcmsgb24gZ2l0LiBUbyBkbyB0aGlzLCB5b3Ugc2hvdWxkIGNsaWNrIHRoZSAnZ2l0JyBpY29uIGFuZCB1cCB3aWxsIHBvcCBhIG1lbnUgbGlrZSB0aGUgb25lIGJlbG93Og0KDQohW0ZpZ3VyZSA2YSAtIEdpdCBJbnRlZ3JhdGlvbiB3aXRoIFJTdHVkaW8gMV0oaW1hZ2VzL2dpdF9yc3R1ZGlvLnBuZykNCg0KWW91IGNhbiBhbHNvIGNsaWNrIHRoZSBHaXQgdGFiIHRoYXQgd2lsbCBoYXZlIGFwcGVhcmVkIGluIHRoZSB0b3AtcmlnaHQgd2luZG93IG9mIFJTdHVkaW8NCg0KIVtGaWd1cmUgNmIgLSBHaXQgSW50ZWdyYXRpb24gd2l0aCBSU3R1ZGlvIDJdKGltYWdlcy9naXRfaW50ZWdyYXRpb24yLnBuZykNCg0KKEApIFRvIENvbW1pdCAoc2F2ZSkgdGhlIGNoYW5nZXMgaW4gdGhpcyBmaWxlIHRvIHlvdXIgbG9jYWwgY2xvbmVkIGdpdCByZXBvc2l0b3J5LCBmaXJzdCBjbGljayAnQ29tbWl0JyANCg0KKEApIFVwIHdpbGwgdGhlbiBwb3AgYW5vdGhlciB3aW5kb3cgdGhhdCBsb29rcyBhIGxpdHRsZSBsaWtlIHRoZSBvbmUgYmVsb3c6DQoNCiFbRmlndXJlIDcgLSBSZXZpZXdpbmcgQ2hhbmdlc10oaW1hZ2VzL3JzdHVkaW9fcmV2aWV3X2NoYW5nZXMucG5nKQ0KDQooQCkgSW4gdGhpcyB3aW5kb3csIHlvdSB3aWxsIGJlIGFibGUgdG8gcmV2aWV3IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGFueSBwcmV2aW91cyBzYXZlcyB5b3UgaGF2ZSBtYWRlIHRvIHlvdXIgZG9jdW1lbnQgYW5kIHRoZSBjdXJyZW50IGNoYW5nZXMuIElmIHlvdSBhcmUgaGFwcHkgd2l0aCB0aGUgY2hhbmdlcywgeW91IGNhbiB0aGVuIHNlbGVjdCB0aGUgZmlsZSBhbmQgY2xpY2sgJ2NvbW1pdCcgdG8gc2F2ZSB0aGVtIHRvIHlvdXIgY3VycmVudCBsb2NhbCByZXBvLiBJZiB5b3UgYXJlIG5vdCBoYXBweSwgdGhlbiB5b3UgY2FuIGFsd2F5cyByZXZlcnQgYmFjayB0byBhIHByZXZpb3VzIHZlcnNpb24gdGhhdCB5b3Uga25vdyBkaWQgd29yayENCg0KKEApIElmIEkgd2VyZSB5b3UsIEkgd291bGQgc2F2ZSBSIFNjcmlwdHMgb3IgUk1hcmtkb3duIERvY3VtZW50cyB1c2luZyB0aGUgdXN1YWwgc2F2ZSBidXR0b24gcXVpdGUgcmVndWxhcmx5LCBhbmQgdGhlbiBldmVyeSB0aW1lIHlvdSwgdGhlbiB5b3UgY2FuIGNvbW1pdCB5b3VyIGNoYW5nZXMgdGhlbi4gDQoNCiMjIFB1c2hpbmcgeW91ciBjaGFuZ2VzIHRvIEdpdEh1Yg0KDQooQCkgT25jZSB5b3UgYXJlIGhhcHB5IHdpdGggeW91ciBwcm9ncmVzcywgeW91IHNob3VsZCBhbHNvIHRoZW4gJ1B1c2gnIHlvdXIgY2hhbmdlcyB0byB5b3VyIG9ubGluZSBHaXRIdWIgcmVwby4gVGhpcyBpcyBpbXBvcnRhbnQsIGJvdGggZm9yIGJhY2tpbmcgdXAgeW91ciB3b3JrLCBidXQgYWxzbyBmb3Iga2VlcGluZyBhIHJlcHJvZHVjYWJsZSByZWNvcmQgb2YgeW91ciByZXNlYXJjaC4gDQoNCihAKSBUbyBkbyB0aGlzLCBmaXJzdCBtYWtlIHN1cmUgeW91IGhhdmUgY29tbWl0dGVkIGFueSBjaGFuZ2VzIHRvIHlvdXIgbG9jYWwgY2xvbmVkIHJlcG8gYW5kIHRoZW4gY2xpY2sgdGhlICdQdXNoJyBidXR0b24gdG8gd2hpenogeW91ciBjb2RlIHVwIHRvIHlvdXIgbWFzdGVyIEdpdEh1YiByZXBvIC0geW91IHdpbGwgcHJvYmFibHkgYmUgcHJvbXB0ZWQgdG8gZW50ZXIgeW91ciBnaXRodWIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIHRvIGVuYWJsZSB0aGlzLi4uDQoNCiFbRmlndXJlIDggLSBQdXNoaW5nIHRvIEdpdEh1Yl0oaW1hZ2VzL2dpdF9wdXNoX3B3LnBuZykNCg0KI0dpdCB3aXRob3V0IFJTdHVkaW8gSW50ZWdyYXRpb24NCg0KTm93LCBpZiB5b3Ugd291bGQgbGlrZSB0byB1c2UgZ2l0IGJ1dCB5b3VyJ3JlIHdvcmtpbmcgb24gdGhlIFVDTCBSZW1vdGUgRGVza3RvcCBvciB5b3UgYXJlIGV4cGVyaWVuaW5nIG90aGVyIHByb2JsZW1zIHdpdGggZ2V0dGluZyBnaXQgd29ya2luZyBpbiBSU3R1ZGlvLCBmZWFyIG5vdCwgeW91IGNhbiBqdXN0IHVzZSB5b3VyIHJhdyBnaXQgaW5zdGFsbGF0aW9uLg0KDQooQCkgSW4gdGhlIFN0YXJ0IE1lbnUsIG9wZW4gdGhlIGdpdCBHVUkuIFN0YXJ0ID4gR2l0ID4gR2l0IEdVSS4gWW91IHNob3VsZCBvcGVuIHRoZSBleGlzdGluZyByZXBvc2l0b3J5IHRoYXQgeW91IGhhdmUganVzdCBjcmVhdGVkLg0KDQooQCkgV2hlbmV2ZXIgeW91IGhhdmUgbWFkZSBzb21lIGNoYW5nZXMgdG8geW91ciBmaWxlcyBpbiB5b3VyIGNsb25lZCByZXBvLCB5b3UgY2FuIHVzZSBnaXQgdG8gcmV2aWV3IHRoZSBjaGFuZ2VzIGFuZCAnQ29tbWl0JyAoc2F2ZSkgdGhlbSBhbmQgdGhlbiAnUHVzaCcgdGhlbSB1cCB0byB5b3VyIG1hc3RlciByZXBvc2l0b3J5IG9uIEdpdEh1Yi4NCg0KKEApIFRvIHJldmlldyBhbmQgY29tbWl0IHlvdXIgY2hhbmdlcywgaW4gdGhlIGNvbW1pdCBtZW51LCBzaW1wbHk6IA0KDQphKSBzY2FuIGZvciBjaGFuZ2VzDQpiKSBzdGFnZSB0aGVtIHJlYWR5IGZvciBjb21taXR0aW5nDQpjKSBjb21taXQgdGhlIGNoYW5nZXMNCmQpIHB1c2ggdGhlIGNoYW5nZXMgdG8geW91ciBHaXRIdWIgcmVwbw0KDQohW0ZpZ3VyZSA5IC0gR2l0IEd1aSBDb21taXRdKGltYWdlcy9naXRfZ3VpX2NvbW1pdC5wbmcpDQoNCihAKSBUcnkgaXQuIEFkZCBzb21lIG5ldyB0ZXh0IHRvIHlvdXIgLlJtZCBmaWxlLiBTYXZlIGl0LiBSZXNjYW4gaW4gdGhlIEdpdCBHVUkgdG8gY2hlY2sgZm9yIGNoYW5nZXMuIFN0YWdlIHRob3NlIGNoYW5nZXMgb25lLWJ5LW9uZS4gQ29tbWl0IHRoZW0gKHJlbWVtYmVyaW5nIHRvIGlucHV0IGEgY29tbWl0IG1lc3NhZ2UpLiBUaGVuIG9uY2UgY29tbWl0dGVkLCB0cnkgdXNpbmcgUmVtb3RlID4gUHVzaCB0byBzZW5kIHRoZSBjaGFuZ2VzIHRvIGdpdGh1YiAoKm5vdGUsIHlvdSB3aWxsIGJlIGFza2VkIGZvciB5b3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCB0byBjb21wbGV0ZSB0aGlzLikNCg0KIyMgUG9zc2libGUgZ2l0IHByb2JsZW1zIC0gTWVyZ2luZyANCg0KKEApIFRoZXJlIGFyZSBtYW55IG1hbnkgcG9zc2libGUgZ2l0IHByb2JsZW1zLiBJJ3ZlIGp1c3Qgc3RhcnRlZCB3aXRoIHRoaXMgYW5kIGhhdmUgY29tZSBhY3Jvc3MgbG9hZHMgKG1haW5seSB0byBkbyB3aXRoIG1lcmdpbmcpIGFscmVhZHkuIEFzIHlvdSBjb250aW51dGUgdG8gY29tbWl0IGFuZCBwdXNoIHdvcmssIGVzcGVjaWFsbHkgd2hlbiB1c2luZyBkaWZmZXJlbnQgY2xvbmVzLCB5b3UgbWF5IHdlbGwgcnVuIGludG8gdGhpbmdzIGxpa2UgbWVyZ2UgY29uZmxpY3RzIGFuZCBhIHdob2xlIGxvYWQgb2Ygb3RoZXIgcHJvYmxlbXMuIEkndmUganVzdCBiZWVuIHRyeWluZyB0byBmaXggYSBtZXJnZSBjb25mbGljdCBmb3IgdGhlIGxhc3QgaG91ciBhbmQgZXZlbnR1YWxseSBnb3QgdGhlcmUuIEl0J3Mgbm90IGVhc3kuIEl0J3Mgbm90IHByZXR0eS4gQnV0IGFzIGV2ZXIsIHRoZXJlIGlzIHVzdWFsbHkgYSBndWlkZSBzb21ld2hlcmUgb24gdGhlIGludGVybmV0IHRvIGhlbHAgeW91LiANCg0KRm9yIG1lcmdlIGNvbmZsaWN0cywgdHJ5IGhlcmU6IGh0dHBzOi8vaGVscC5naXRodWIuY29tL2FydGljbGVzL3Jlc29sdmluZy1hLW1lcmdlLWNvbmZsaWN0LXVzaW5nLXRoZS1jb21tYW5kLWxpbmUvIA0KDQpGb3IgZ2VuZXJhbCBnaXRodWIgaGVscCwgdHJ5IGhlcmU6IGh0dHBzOi8vaGVscC5naXRodWIuY29tLyANCg0KKEApIEFuIGluaXRpYWwgdGlwIGZyb20gbWUgLSBsb29rcyBsaWtlIHdoZW5ldmVyIHlvdSBhcmUgd29ya2luZyB3aXRoIGEgbG9jYWwgZ2l0aHViIHJlcG8sIGlmIHlvdSBjb21lIGJhY2sgdG8geW91ciB3b3JrIGFmdGVyIHNodXR0aW5nIGRvd24gYW5kIHJlc3RhcnRpbmcsIHRoZW4gdGhlIGZpcnN0IHRoaW5nIHlvdSBzaG91bGQgZG8gaXMgJ1B1bGwnIGZyb20geW91ciBHaXRIdWIgcmVwbyBiZWZvcmUgZ29pbmcgYW55IGZ1cnRoZXIuIElmIHlvdSBkb24ndCwgeW91IG1heSB3ZWxsIGhhdmUgYWxsIGtpbmRzIG9mIGZ1biB0byBzb2x2ZSB3aXRoIG1lcmdpbmcgZmlsZXMgdG9nZXRoZXIgYWZ0ZXJ3YXJkcy4gDQoNCkdvb2QgbHVjayEhDQoNCiMgUmVwcm9kdWNpYmxlIFJlc2VhcmNoIFVzaW5nIFIgTWFya2Rvd24NCg0KT0ssIHNvIG5vdyB5b3UgaGF2ZSBzZXQgZXZlcnl0aGluZyB1cCBzbyB0aGF0IHlvdSBjYW4gYmVjb21lIGEgcmVwcm9kdWNhYmxlIHJlc2VhcmNoIG5pbmphISBBbGwgdGhhdCByZW1haW5zIGlzIHRvIGRvIHNvbWUgcmVwcm9kdWNhYmxlIHJlc2VhcmNoIQ0KDQpGb3IgdGhlIGRlZmluaXRpdmUgZ3VpZGUgb24gUiBNYXJrZG93biwgcGxlYXNlIHJlYWQgW1IgTWFya2Rvd246IFRoZSBEZWZpbml0aXZlIEd1aWRlXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vKSAtIG9idmlvdXNseSEgSXQgd2lsbCB0ZWxsIHlvdSBldmVyeXRoaW5nIHlvdSBuZWVkIHRvIGtub3csIGZhciBiZXlvbmQgd2hhdCBJIGFtIHRlbGxpbmcgeW91IGhlcmUuDQoNClRoZXJlIGlzIGFsc28gYW4gZXhjZWxsZW50IGd1aWRlIG9uIHRoZSBSIFN0dWRpbyB3ZWJzaXRlIC1odHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tMS5odG1sIA0KDQpBbmQgYSBxdWljayBjaGVhdHNoZWV0IGhlcmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9yc3R1ZGlvL2NoZWF0c2hlZXRzL3Jhdy9tYXN0ZXIvcm1hcmtkb3duLTIuMC5wZGYgDQoNCkFuZCBhbiBvbGRlciBvbmUgaGVyZToNCmh0dHA6Ly93d3cucnN0dWRpby5jb20vd3AtY29udGVudC91cGxvYWRzLzIwMTYvMDMvcm1hcmtkb3duLWNoZWF0c2hlZXQtMi4wLnBkZiANCg0KT25lIG9mIHRoZSBhd2Vzb21lIHRoaW5ncyBhYm91dCBSIE1hcmtkb3duIGlzIGl0IGNhbiBiZSBjb252ZXJ0ZWQgaW50byBhIHJhbmdlIG9mIGRpZmZlcmVudCBmb3JtYXRzIC0gaHRtbCBmb3Igd2VicGFnZXMsIHdvcmQgZG9jdW1lbnRzLCBQREZzLCBibG9ncywgYm9va3MgLSB2aXJ0dWFsbHkgZXZlcnl0aGluZyENCg0KTm93LCBlYXJsaWVyIG9uIGluIHRoaXMgZXhlcmNpc2UsIEkgZ290IHlvdSB0byBvcGVuIGEgbmV3IFIgTm90ZWJvb2sgb3IgUiBNYXJrZG93biBmaWxlLiBUaGV5IGFyZSBib3RoIFIgTWFya2Rvd24gRG9jdW1lbnRzLCBidXQgdGhlIE5vdGVib29rIGFsbG93cyBjaHVua3Mgb2YgY29kZSB0byBiZSBydW4gaW5kZXBlbmRlbnRseS4gDQoNCihAKSBHbyBiYWNrIHRvIHRoZSBub3RlYm9vayB5b3UgY3JlYXRlZCBlYXJsaWVyIGluIHN0ZXAgMTEuIFdlIGFyZSBub3cgZ29pbmcgdG8gaW5zZXJ0IHNvbWUgY29kZSBmcm9tIHRoZSBwcmFjdGljYWwgbGFzdCB3ZWVrIGFuZCBydW4gaXQuIA0KDQooQCkgSW4gUlN0dWRpbywgeW91IGNhbiBlaXRoZXIgc2VsZWN0IENvZGUgPiBJbnNlcnQgQ2h1bmsgb3IgeW91IGNhbiBDbGljayB0aGUgJ0luc2VydCcgYnV0dG9uIGFuZCBpbnNlcnQgYW4gUiBDaHVuaw0KDQohW0ZpZ3VyZSA4IC0gSW5zZXJ0IFIgQ2h1bmtdKGltYWdlcy9JbnNlcnRfY29kZV9jaHVuay5wbmcpDQoNCihAKSBBIGJveCB3aWxsIGFwcGVhciBhbmQgaW4gdGhpcyBib3gsIHlvdSB3aWxsIGJlIGFibGUgdG8gZW50ZXIgYW5kIHJ1biB5b3VyIFIgY29kZS4gVHJ5IHBhc3RpbmcgaW46DQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZW9qc29uaW8pDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeSh0bWFwKQ0KbGlicmFyeSh0bWFwdG9vbHMpDQoNCiNyZWFkIHNvbWUgZGF0YSBhdHRyaWJ1dGVzDQpMb25kb25EYXRhIDwtIHJlYWRfY3N2KCJodHRwczovL2ZpbGVzLmRhdGFwcmVzcy5jb20vbG9uZG9uL2RhdGFzZXQvd2FyZC1wcm9maWxlcy1hbmQtYXRsYXMvMjAxNS0wOS0yNFQxNDoyMToyNC93YXJkLXByb2ZpbGVzLWV4Y2VsLXZlcnNpb24uY3N2IiwgbmEgPSAibi9hIikNCiNyZWFkIHNvbWUgZ2VvbWV0cmllcw0KRVcgPC0gZ2VvanNvbl9yZWFkKCJodHRwOi8vZ2VvcG9ydGFsLnN0YXRpc3RpY3MuZ292LnVrL2RhdGFzZXRzLzhlZGFmYmUzMjc2ZDRiNTZhZWM2MDk5MWNiZGRkYTUwXzIuZ2VvanNvbiIsIHdoYXQgPSAic3AiKQ0KI3B1bGwgb3V0IExvbmRvbg0KTG9uZG9uTWFwIDwtIEVXW2dyZXAoIl5FMDkiLEVXQGRhdGEkbGFkMTVjZCksXQ0KI2NvbnZlcnQgdG8gYSBzaW1wbGUgZmVhdHVyZXMgb2JqZWN0DQpMb25kb25NYXBTRiA8LSBzdF9hc19zZihMb25kb25NYXApDQojYXBwZW5kIHRoZSBkYXRhIHRvIHRoZSBnZW9tZXRyaWVzDQpMb25kb25NYXBTRiA8LSBhcHBlbmRfZGF0YShMb25kb25NYXBTRixMb25kb25EYXRhLCBrZXkuc2hwID0gImxhZDE1Y2QiLCBrZXkuZGF0YSA9ICJOZXcgY29kZSIsIGlnbm9yZS5kdXBsaWNhdGVzID0gVFJVRSkNCiNwbG90IGEgY2hvcm9wbGV0aA0KcXRtKExvbmRvbk1hcFNGLCBmaWxsID0gIiUgTm90IEJvcm4gaW4gVUsgLSAyMDExIikNCmBgYA0KDQooQCkgV2hlbiBpbmNsdWRpbmcgY29kZSBjaHVua3MgaW4geW91ciB3b3JrLCB0aGVyZSBhcmUgdmFyaW91cyBvcHRpb25zIHRoYXQgYWxsb3cgeW91IHRvIGRvIHRoaW5ncyBsaWtlIGluY2x1ZGUgdGhlIGNvZGUsIGJ1dCBub3QgcnVuIGl0OiBkaXNwbGF5IHRoZSBvdXRwdXQgYnV0IG5vdCB0aGUgY29kZSwgaGlkZSB3YXJuaW5ncyBldGMuIE1vc3Qgb2YgdGhlc2UgY2FuIGJlIGlucHV0IGF1dG9tYXRpY2FsbHkgYnkgY2xpY2tpbmcgdGhlIGNvZyBpY29uIGluIHRoZSB0b3AtcmlnaHQgb2YgdGhlIGNodW5rLg0KDQohW0ZpZ3VyZSA5IC0gQ2h1bmsgT3B0aW9uc10oaW1hZ2VzL2NodW5rX29wdGlvbnMucG5nKQ0KDQooQCkgVmFyaW91cyBvdGhlciBvcHRpb25zIGFuZCB0aXBzIGNhbiBiZSBmb3VuZCBpbiB0aGUgZnVsbCBSIE1hcmtkb3duIGd1aWRlIG9uIFJTdHVkaW8gaGVyZTogaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vbGVzc29uLTEuaHRtbCBhbmQgaW4gdGhpcyB0aGUgY2hlYXRzaGVldHMgbGlua2VkIHRvIGFib3ZlLg0KDQojIEFkZGluZyBSZWZlcmVuY2VzIHRvIFlvdXIgV29yaw0KDQpOb3csIGFzIHlvdSBidWlsZCB1cCB5b3VyIGRvY3VtZW50YXRpb24gZm9yIHRoZSB3b3JrIHlvdSBhcmUgZG9pbmcsIGl0IGlzIGxpa2VseSB0aGF0IHlvdSB3aWxsIHdhbnQgdG8gaW5jbHVkZSByZWZlcmVuY2VzIHRvIHN1cHBvcnQgeW91ciBhcmd1bWVudHMuIA0KDQpCdWlsZGluZyBhIGJpYmxpb2dyYXBoeSBpbiB5b3VyIFIgTWFya2Rvd24gZG9jdW1lbnQgaXMgcXVpdGUgc2ltcGxlLCB5b3Ugd2lsbCBqdXN0IG5lZWQgdG8gaW5zdGFsbCBzb21lIGFkZGl0aW9uYWwgcGFja2FnZXMgdGhhdCBwbHVnIGludG8gUlN0dWRpbyBhbmQgbGVhcm4gaG93IHRvIGV4cG9ydCB5b3VyIGJpYmxpb2dyYXBoeSBmcm9tIHlvdXIgcmVmZXJlbmNlIG1hbmFnZW1lbnQgc29mdHdhcmUuIA0KDQojIyBFeHBvcnRpbmcgYSBiaWJsaW9ncmFwaHkgZnJvbSBab3Rlcm8NCg0KSGVyZSBJIHdpbGwgYXNzdW1lIHRoYXQgeW91IGFyZSBnb2luZyB0byBiZSB1c2luZyBab3Rlcm8gYXMgeW91ciByZWZlcmVuY2UgbWFuYWdlbWVudCBzb2Z0d2FyZS4gSWYgeW91IHVzZSBvdGhlciBzb2Z0d2FyZSwgdGhlcmUgYXJlIHByb2JhYmx5IHNpbWlsYXIgb3B0aW9ucyBmb3IgZXhwb3J0aW5nIGF2YWlsYWJsZSB0byB5b3UsIHNvIGRvbid0IHdvcnJ5LiANCg0KVGhlIGFpbSBpcyB0byBnZXQgYSBsaXN0IG9mIHJlZmVyZW5jZXMgdGhhdCBhcmUgc3RvcmVkIGluIGEgZm9ybWF0IGtub3duIGFzIGBCaWJUZVhgIC0gaHR0cDovL3d3dy5iaWJ0ZXgub3JnLyANCg0KSSB3b24ndCBnbyBpbnRvIEJpYlRlWCBub3csIGJ1dCBpZiB5b3UgZ28gb24gdG8gd3JpdGUgeW91ciBkaXNzZXJ0YXRpb24gdXNpbmcgW0xhVGVYXShodHRwczovL3d3dy5sYXRleC1wcm9qZWN0Lm9yZy8pLCB0aGVuIEJpYlRlWCBpcyB0aGUgZm9ybWF0IHRoYXQgeW91IHdpbGwgdXNlIHRvIHN0b3JlIHlvdXIgcmVmZXJlbmNlcy4gDQoNCihAKSBIYXZpbmcgYnVpbHQgdXAgYSBiaWJsaW9ncmFweSBvZiByZWxldmFudCBsaXRlcmF0dXJlIGluIHpvdGVybywgeW91IHNob3VsZCBleHBvcnQgaXQgaW4gQmliVGVYIGZvcm1hdCBhbmQgc2F2ZSBpdCB0byB0aGUgc2FtZSBkaXJlY3RvcnkgdGhhdCB5b3VyIFIgTWFya2Rvd24gcHJvamVjdCBpcyBsb2NhdGVkIGluLiBHbyB0byBGaWxlID4gRXhwb3J0IExpYnJhcnkgYW5kIHNlbGVjdCBCaWJUZVggYXMgeW91ciBmb3JtYXQuIA0KDQogDQohW0ZpZ3VyZSAxMCAtIFpvdGVybyBFeHBvcnRdKGltYWdlcy96b3Rlcm9fZXhwb3J0LnBuZykNCg0KKEApIE9uY2UgeW91ciBCaWJUZXggZmlsZSBpcyBzYXZlZCBpbnRvIHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB5b3VyIA0KIyMgVXNpbmcgeW91ciBiaWJsaW9ncmFwaHkgaW4geW91ciBSIE1hcmtkb3duIGRvY3VtZW50DQoNClRvIGZpbmQgeW91ciBiaWJsaW9ncmFwaHksIHlvdSBuZWVkIHRvIGluc2VydCBpdHMgbmFtZSBpbnRvIHRoZSBZQU1MIGhlYWRlciBhdCB0aGUgdmVyeSB0b3Agb2YgdGhlIGZpbGUgKG1vcmUgYWJvdXQgdGhlIFlBTUwgaGVhZGVyIGluIGEgbWludXRlKSAtIHNlZSBiZWxvdzoNCg0KYGBge3IgZWNobz1UUlVFLCBldmFsPUZBTFNFfQ0KLS0tDQp0aXRsZTogIlByb2R1Y2luZyBSZXByb2R1Y2libGUgUmVzZWFyY2ggVXNpbmcgUk1hcmtkb3duIGFuZCBHaXRodWIiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgd29yZF9kb2N1bWVudDogZGVmYXVsdA0KICANCmF1dGhvcjogQWRhbSBEZW5uZXR0DQpiaWJsaW9ncmFwaHk6IA0KIC0gUlJlZmVyZW5jZXMuYmliDQogIA0KLS0tDQpgYGANCg0KIyMgQWRkaW5nIFJlZmVyZW5jZXMgVXNpbmcgYGNpdHJgIA0KDQooQCkgVG8gYWRkIGFkZCBjaXRhdGlvbnMgZnJvbSB5b3VyIGJpYmxpb2dyYXBoeSwgeW91IGNhbiB0aGVuIHVzZSB0aGUgYGNpdHJgIHBhY2thZ2UsIHdoaWNoIHJ1bnMgaW4gYW4gYWRkaW4gd2l0aGluIFJTdHVkaW8NCg0KYGBge3IgZWNobz1UUlVFLCBldmFsPUZBTFNFfQ0KaW5zdGFsbC5wYWNrYWdlcygiY2l0ciIpDQpsaWJyYXJ5KGNpdHIpDQpgYGANCg0KKEApIEluIHRoZSAnQWRkaW5zJyBtZW51IG5lYXIgdGhlIHRvcCBvZiBSU3R1ZGlvLCB5b3Ugc2hvdWxkIChvbmNlIFJTdHVkaW8gaGFzIGJlZW4gcmVzdGFydGVkKSBoYXZlIGEgYGNpdHJgIG9wdGlvbiBmb3IgJ0luc2VydCBjaXRhdGlvbnMnIGFuZCBpbmNsdWRpbmcgdGhlbSBpbiB5b3VyIHdvcmsuDQoNCiFbRmlndXJlIDExIC0gQ2l0ciBBZGRpbl0oaW1hZ2VzL2FkZGluc19jaXRyLnBuZykNCg0KKEApIFRyeSBhZGRpbmcgc29tZSBjaXRhdGlvbnMgZnJvbSB5b3VyIEJpYlRlWCBsaWJyYXJ5Li4uIFlvdSB3aWxsIGZpbmQgdGhhdCBvbmNlIHlvdSBoYXZlIGFkZGVkIHRoZW0gaW50byB0aGUgdGV4dCwgYGNpdHJgIHdpbGwgYnVpbGQgYSBiaWJsaW9ncmFwaHkgYXQgdGhlIGJvdHRvbSBvZiB5b3VyIGRvY3VtZW50IGZvciB5b3UgLSBuZWF0LCBoZXk/IQ0KDQpIZXJlIGlzIGEgcmVmZXJlbmNlIGZvciBhIHNlbWluYWwgYW5kIHRvdGFsbHkgZ2FtZSBjaGFuZ2luZyBwYXBlciBieSBAZGVubmV0dF9nZW9ncmFwaHlfMjAxNy4gSGVyZSBpcyBhbm90aGVyIHJlZmVyZW5jZSBbQHhpZV9yXzIwMThdIHRoYXQgaGVwZWQgbWUgd3JpdGUgdGhpcyBwb3N0LiBPbmNlIHlvdSBrbml0IHlvdXIgZG9jdW1lbnQgaW50byBhbiBvdXRwdXQgZmlsZSwgdGhlIHJlZmVyZW5jZXMgd2lsbCBhbGwgc3RhY2sgdXAgYWxwaGFiZXRpY2FsbHkgYXQgdGhlIGJvdHRvbSBvZiB0aGUgZmlsZS4uLg0KDQojIEtuaXR0aW5nIHlvdXIgZmluYWwgb3V0cHV0DQoNCk9uY2UgeW91IGhhdmUgaW5jb3Jwb3JhdGVkIHNvbWUgdGV4dCBhbmQgY29kZSBpbnRvIGEgdGVzdCAuUm1kIGRvY3VtZW50LCB5b3Ugc2hvdWxkIG5vdyBiZSBhYmxlIHRvIGtuaXQgaXQgaW50byBhIGZvcm1hdCBvZiB5b3VyIGNob2ljZS4gDQoNCkluZm9ybWF0aW9uIHRvIGhlbHAgZm9ybWF0IHlvdXIga25pdHRlZCBmaWxlIGlzIGNvbnRhaW5lZCBpbiB0aGUgWUFNTCBoZWFkZXIgYXQgdGhlIHRvcC4gSW4gaGVyZSwgeW91IGNhbiBhZGQgdGhpbmdzIGxpa2UgdGFibGVzIG9mIGNvbnRlbnRzLCBhcHBseSBzcGVjaWZpYyB0aGVtZXMsIGV0Yy4gDQoNCkZvciBhIHNlbGVjdGlvbiBvZiBuaWNlIHRoZW1lcywgc2VlIGhlcmU6IGh0dHA6Ly93d3cuZGF0YWRyZWFtaW5nLm9yZy9wb3N0L3ItbWFya2Rvd24tdGhlbWUtZ2FsbGVyeS8gDQoNCkZvciB0aGluZ3MgbGlrZSBhZGRpbmcgVGFibGVzIG9mIENvbnRlbnRzLCB0YWJiZWQgc2VjdGlvbnMgKGluIEhUTUwpLCBmaWd1cmUgYW5kIHRhYmxlIHBhcmFtZXRlcnM6DQpodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vaHRtbC1kb2N1bWVudC5odG1sIA0KDQpJZiB5b3UgaGF2ZSBzZWxlY3RlZCBhbiBSIE1hcmtkb3duIE5vdGVib29rLCBpbiB0aGUgbWVudSBiYXIgYXQgdGhlIHRvcCBvZiB0aGUgcGFnZSwgeW91IHNob3VsZCBzZWUgYSAnUHJldmlldycgYnV0dG9uLiBJZiB5b3UgY2xpY2sgdGhpcywgeW91ciAuUm1kIGZpbGUgd2lsbCBiZSBrbml0dGVkIGF1dG9tYXRpY2FsbHkgaW50byBhbiBpbnRlcmFjdGl2ZSBodG1sIGRvY3VtZW50IC0gdHJ5IGl0IQ0KDQpJZiB5b3UgY2xpY2sgdGhlIHNtYWxsIGFycm93IG5leHQgdG8gdGhlIHByZXZpZXcgYnV0dG9uLCBhIG1lbnUgd2lsbCBhcHBlYXIgZ2l2aW5nIHlvdSB0aGUgb3B0aW9uIHRvIGtuaXQgaW50byBhIHNlbGVjdGlvbiBvZiBvdGhlciBmb3JtYXRzLCBpbmNsdWRpbmcgUERGIGFuZCBXb3JkLiBUcnkgdGhvc2UgdG9vLi4uDQoNCiFbRmlndXJlIDEyIC0ga25pdHRpbmddKGltYWdlcy9rbml0dGluZy5wbmcpDQoNCiMgRnVydGhlciBSZWFkaW5nDQoNClNpbmNlIHN0YXJ0aW5nIHRoaXMgbGl0dGxlIGd1aWRlLCBJIGhhdmUgY29tZSBhY3Jvc3MgdGhpcyBhbWF6aW5nIGJvb2sgb24gdXNpbmcgUiBhbmQgR2l0SHViLCBieSBKZW5ueSBCcnlhbiBhbmQgSmltIEhlc3Rlci4gSXQncyBicmlsbGlhbnQgLSB0YXVnaHQgbWUgdGhpbmdzIGxpa2UgaG93IHRvIGF2b2lkIGVudGVyaW5nIHVzZXIgY3JlZGVudGlhbHMgZXZlcnkgdGltZSBJIHB1c2ggdG8gbXkgR2l0SHViIHJlcG8gKENoIDExKSAtIGdldCBpbnZvbHZlZCEgaHR0cDovL2hhcHB5Z2l0d2l0aHIuY29tLyANCg0KIyBSZWZlcmVuY2VzDQoNCg0K