First Steps in R
In order to follow along with this session, you’ll need to
have downloaded some of the files in the OSF repo for this series. If
you haven’t done so, go to this page and select the “Download this
folder” button on the top right of the screen: download OSF files
If you have any issues, please ask your instructor, or refer to
“Block 1: Introduction to OSF”.
Introduction
Now that we’ve familiarized ourselves a bit with R and RStudio, we
can start moving forward to working with data in R, which is where the
real fun begins!
R Projects
Setting working directory
When we talked about relative file paths in the previous session, it
was revolving around this idea of where you are in the file
system. In a coding environment, this translates to the idea of
setting a working directory, which is a way of telling
R (or other coding languages) where you want to be in your computer’s
file system when you’re doing your work.
A common way to set a working directory is to use the
setwd() function. This function manually sets the working
directory during an R session. It tells R where to look for files and
where to save outputs just for that session.
This can be done in 2 ways:
- Manually in R, by writing
setwd("path-to-director/secondary-part/etc...")
- Setting it by selecting the
Session tab in the toolbar,
and selecting Set Working Directory:

But here’s the problem…
Using setwd() can break your code when:
- Someone else tries to run it on their machine.
- You move your project folder.
- You’re running your code on a server or in cloud environments like
RStudio Cloud.
Since file paths are hardcoded and depend on your machine,
it’s not reproducible.
Create an R Project
An R Project is a feature in RStudio (and supported in base R too)
that provides a self-contained working environment. When you create an R
Project it creates a .Rproj file in a folder and that folder becomes the
root directory of your project. Every time you open the project (via the
.Rproj file), R automatically sets the working directory to that folder.
You can reference files relative to the project root — no need to
hardcode file paths.
This is super useful when you’re working on multiple analyses,
sharing code with collaborators, or version-controlling with Git.
It is a good practice for reproducible research
To create an R Project, select File > New Project

Your Turn!
Create your first RProject. Let’s figure out what we should call
it!
Packages and Libraries
When you first download R, it comes equipped with a number of
pre-installed functions, or capabilities, that you can start using
immediately. This is often called “Base R:. However, for certain tasks
and workflows, it can be beneficial to use more specialized tools, or
functions, to accomplish work and facilitate workflows for efficiently.
This is where packages and libraries come into play.
Packages: Packages are an extension of the
pre-built functions in R, and can be installed to bring in specific
functions to accomplish tasks, bring in sample datasets to play with,
among other things. There are tons of R packages out
there, but here is a list of some of the most common/useful ones: Quick
list of useful R packages
Libraries: Once you have installed a package,
they are stored as libraries in R. You only have to install them once,
and anytime you want to use the package you can use the
library() function, which is described below.
Tidyverse
As mentioned in the session “Reproducible Research: Moving
From Excel to Scripting”, we will be using an R package called
the “Tidyverse”. The Tidyverse is a very commonly used
package for research and data science activities, and instead of being a
single package, it is a collection of packages that are designed to work
together and which focus on the connections between activities in the
data science workflow. Each package follows the same syntax, which makes
learning them easier, and the website functions as a really good
reference point if you’re struggling with how to approach a specific
task.

Let’s take a closer look! Tidyverse
Let’s get started!
First, let’s create a new R script.
To create an R script file, select File > New File > R
Script

Install Package
To install a package we use the function
install.packages().
#install.packages("tidyverse")
Load Libraries
Packages are stored in libraries. Once a package is installed, we
need to call the library with the function library().
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.1
Note that the package name needs to be in quotations when installing
the package, but not when loading the library.
Because packages only need to be installed once, we can do this in
the R console as opposed to in the script.
Because libraries need to be loaded in each working session, we can
do this in the R script so that others can see what libraries we are
using and need to be loaded.
Referring again to the Tidyverse Data Science Workflow, in this
session we’ll be focusing on the first two steps:
Source
Reading Data
In order to start working with a dataset in R, we first need to
import, or “read in”, the data. As mentioned in the session
“Reproducible Research: Moving From Excel to
Scripting”, we will be working with .csv files,
but R is capable of reading in other file types as well.
Read a csv file
To import a csv file we can use the read_csv() function
and assign it to a new object we will call js_data. We create a
new object to be able to call it in different functions later on.
js_data <- read_csv("data/block-4_first-steps.csv")
Listing Column Names
To ask for a list of all the column names in our dataset we can use
the names() function.
names(js_data)
## [1] "PUMFID" "AGEGR10" "SEX" "MARSTAT" "PRV" "LUC_RST" "EHG_ALL" "GTU_110" "GTU_130"
## [10] "DUR01" "DUR05" "DUR06" "DURS200" "DURL313" "DUR08" "DUR13" "DUR14" "DUR15"
## [19] "MRW_20" "MRW_30" "MRW_40" "MRW_D40A" "MRW_D40B" "EDM_02" "TST_01" "TCS_110" "TCS_120"
## [28] "TCS_150" "TCS_200"
Notice that the column names from the original dataset don’t provide
a clear description of what the variable is. We will change the column
names later to facilitate working with our data in the future.
Head Function
The head function will display the top rows of the dataset. It will
include information about the default data type assigned to each column.
We will cover data types more in the next session.
head(js_data)
|
PUMFID
|
AGEGR10
|
SEX
|
MARSTAT
|
PRV
|
LUC_RST
|
EHG_ALL
|
GTU_110
|
GTU_130
|
DUR01
|
DUR05
|
DUR06
|
DURS200
|
DURL313
|
DUR08
|
DUR13
|
DUR14
|
DUR15
|
MRW_20
|
MRW_30
|
MRW_40
|
MRW_D40A
|
MRW_D40B
|
EDM_02
|
TST_01
|
TCS_110
|
TCS_120
|
TCS_150
|
TCS_200
|
|
10000
|
5
|
1
|
5
|
46
|
1
|
3
|
1
|
1
|
510
|
60
|
120
|
770
|
90
|
0
|
0
|
0
|
0
|
NA
|
1
|
1
|
1
|
2
|
NA
|
8
|
2
|
2
|
2
|
2
|
|
10001
|
5
|
1
|
1
|
59
|
1
|
4
|
3
|
4
|
420
|
150
|
0
|
0
|
0
|
0
|
0
|
0
|
0
|
NA
|
2
|
1
|
1
|
2
|
NA
|
1
|
2
|
2
|
2
|
2
|
|
10002
|
4
|
2
|
1
|
47
|
1
|
5
|
1
|
6
|
570
|
0
|
0
|
630
|
30
|
480
|
0
|
0
|
0
|
NA
|
NA
|
NA
|
1
|
1
|
NA
|
7
|
2
|
1
|
1
|
1
|
|
10003
|
6
|
2
|
5
|
35
|
1
|
4
|
2
|
4
|
510
|
10
|
45
|
875
|
80
|
20
|
0
|
0
|
0
|
NA
|
NA
|
NA
|
1
|
1
|
NA
|
1
|
2
|
2
|
2
|
2
|
|
10004
|
2
|
1
|
6
|
35
|
1
|
NA
|
1
|
3
|
525
|
90
|
40
|
815
|
0
|
0
|
0
|
0
|
0
|
NA
|
NA
|
NA
|
2
|
2
|
NA
|
1
|
2
|
2
|
2
|
2
|
|
10005
|
1
|
1
|
6
|
35
|
1
|
1
|
1
|
6
|
435
|
0
|
0
|
430
|
40
|
530
|
0
|
0
|
0
|
NA
|
NA
|
NA
|
1
|
1
|
NA
|
2
|
2
|
1
|
1
|
2
|
Viewing Data
To visualize the full dataset we use the View()
function. This will open our dataset in a separate window.
View(js_data)
Change Column Names
Let’s now return to the R syntax diagram that we looked at in Block
3:

In that session, we discussed objects and
functions, and played with the idea of objects storing
information, and functions manipulating the object/data.
Now we’re going to start implementing pipes as a way
to connect objects to functions and
arguments.
Pipes
Pipes are used to chain steps of instructions or actions together,
and often involve writing over an object to give it a new value. We’ll
walk through some examples of how this works, and start to see how the
full syntax of R comes together.
We mentioned earlier that we wanted to work with column names that
were more descriptive of the content of each variable. To change column
names we can use the function rename().
The function rename() is part of one of the packages
that was installed with tidyverse.
Type the following code to change the column name from “PUMFID” to
“id”
js_data <- js_data |>
rename("id" = "PUMFID")
Step-by-step explanation:
- This command first starts off with the
js_data object,
which is our dataset.
- The assignment operator comes next, and will re-write the
information stored in
js_data with all the information that
is to the right side of the operator.
- We then use the
js_data object and the pipe
|> to tell R that we want to take the data that is
stored in js_data, and then do something to it (which is
what comes after the pipe).
- The
rename function is used to rename columns, and is
always followed by brackets. Inside those brackets, we’ll put the new
column name that we want in quotation marks "", followed by
an equal sign =, followed by the existing column name in
quotation marks "".
- We then run the command and hope it works!
Your Turn!
First, use the functionnames() to display the column
names.
names(js_data)
Now, see if you can change the AGEGR10 column name to
ageGrp
js_data <- js_data |>
rename("ageGrp" = "AGEGR10")
Next, try to change the following 3 column names:
- Change
SEX to sex
- Change
MARSTAT to maritalStat
- Change
PRV to province
Hint: It can be tedious to do these changes one by
one, but by using commas , you can rename column names with
a single code chunk.
js_data <- js_data |>
rename("sex" = "SEX",
"maritalStat" = "MARSTAT",
"province" = "PRV")
Now, to change the rest of the column names copy the following code.
(If you feel you’re starting to understand how this works, you can show
the code below and cope + paste it into your script, or if
you want some more practice, feel free to do it yourself!
js_data <- js_data |>
rename("popCenter" = "LUC_RST",
"eduLevel" = "EHG_ALL",
"feelRushed" = "GTU_110",
"extraTime" = "GTU_130",
"durSleep" = "DUR01",
"durMealPrep" = "DUR05",
"durEating" = "DUR06",
"durAlone" = "DURS200",
"durDriving" = "DURL313",
"durWork" = "DUR08",
"durShoolSite" = "DUR13",
"durSchoolOnline" = "DUR14",
"durStudy" = "DUR15",
"mainStudy" = "MRW_20",
"mainJobHunting" = "MRW_30",
"mainWork" = "MRW_40",
"worked12m" = "MRW_D40A",
"workedWeek" = "MRW_D40B",
"enrollStat" = "EDM_02",
"dailyTexts" = "TST_01",
"timeSlowDown" = "TCS_110",
"timeWorkaholic" = "TCS_120",
"timeNotFamFriends" = "TCS_150",
"timeWantAlone" = "TCS_200")
Save Your Work
Now that we’ve created a dataset that has some significant changes,
it can be helpful to save this as a version that we can easily return
to. Much like we did with reading .csv data into R, there
is a similar command to save, or “write” .csv data back to
your computer called write_csv(). The syntax is as
follows:
write_csv(data-object-name, file="file-path/datafile-name.csv")
The file name below is for example purposes, and feel free to use a
file naming convention that you developed:
write_csv(js_data, file="data/clean-cols.csv")
.RData Files
An additional way to save data files in R is as an
.Rdata file. Unlike a simple .csv file,
.RData files are designed to store R objects and your
entire R workspace, while maintain their data types and structures
(covered in the next session!). This allows you to return to your R
environment exactly as you left it when you reload the file, and allows
others opening your files to have that environment as well, acting as a
great way to faciliate reproducibility.
The syntax is similar is the same as write_csv, but uses
the function save():
save(js_data, file="data/clean-cols.RData")
When opening an .RData file, instead of using
read_csv(), you use the load() command. The
syntax is the same, and to reopen the file you just saved would look
like this:
`load("data/clean-cols.RData")`
LS0tDQp0aXRsZTogIkZpcnN0IHN0ZXBzIGluIFIiDQpwYWdldGl0bGU6ICJGaXJzdCBzdGVwcyBpbiBSIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZm9sZGluZzogc2hvdyAjIGFsbG93cyB0b2dnbGluZyBvZiBzaG93aW5nIGFuZCBoaWRpbmcgY29kZS4gUmVtb3ZlIGlmIG5vdCB1c2luZyBjb2RlLg0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgIyBhbGxvd3MgdGhlIHVzZXIgdG8gZG93bmxvYWQgdGhlIHNvdXJjZSAuUm1kIGZpbGUuIFJlbW92ZSBpZiBub3QgdXNpbmcgY29kZS4NCiAgICBpbmNsdWRlczoNCiAgICAgIGFmdGVyX2JvZHk6IGZvb3Rlci5odG1sICMgaW5jbHVkZSBhIGN1c3RvbSBmb290ZXIuDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UNCi0tLQ0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5ncyA9IEZBTFNFKQ0KYGBgDQoNCiMjIEZpcnN0IFN0ZXBzIGluIFINCg0KKipJbiBvcmRlciB0byBmb2xsb3cgYWxvbmcgd2l0aCB0aGlzIHNlc3Npb24sIHlvdSdsbCBuZWVkIHRvIGhhdmUgZG93bmxvYWRlZCBzb21lIG9mIHRoZSBmaWxlcyBpbiB0aGUgT1NGIHJlcG8gZm9yIHRoaXMgc2VyaWVzLiAgSWYgeW91IGhhdmVuJ3QgZG9uZSBzbywgZ28gdG8gdGhpcyBwYWdlIGFuZCBzZWxlY3QgdGhlICJEb3dubG9hZCB0aGlzIGZvbGRlciIgYnV0dG9uIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhlIHNjcmVlbjoqKiBbZG93bmxvYWQgT1NGIGZpbGVzXShodHRwczovL29zZi5pby9yeDVhMy9maWxlcy9vc2ZzdG9yYWdlKQ0KDQpJZiB5b3UgaGF2ZSBhbnkgaXNzdWVzLCBwbGVhc2UgYXNrIHlvdXIgaW5zdHJ1Y3Rvciwgb3IgcmVmZXIgdG8gKioiQmxvY2sgMTogSW50cm9kdWN0aW9uIHRvIE9TRiIqKi4NCg0KDQojIyBJbnRyb2R1Y3Rpb24NCg0KOjo6aW50cm8NCk5vdyB0aGF0IHdlJ3ZlIGZhbWlsaWFyaXplZCBvdXJzZWx2ZXMgYSBiaXQgd2l0aCBSIGFuZCBSU3R1ZGlvLCB3ZSBjYW4gc3RhcnQgbW92aW5nIGZvcndhcmQgdG8gd29ya2luZyB3aXRoIGRhdGEgaW4gUiwgd2hpY2ggaXMgd2hlcmUgdGhlIHJlYWwgZnVuIGJlZ2lucyENCjo6Og0KDQojIyBSIFByb2plY3RzIA0KDQojIyMgU2V0dGluZyB3b3JraW5nIGRpcmVjdG9yeQ0KDQpXaGVuIHdlIHRhbGtlZCBhYm91dCByZWxhdGl2ZSBmaWxlIHBhdGhzIGluIHRoZSBwcmV2aW91cyBzZXNzaW9uLCBpdCB3YXMgcmV2b2x2aW5nIGFyb3VuZCB0aGlzIGlkZWEgb2YgKndoZXJlIHlvdSBhcmUgaW4gdGhlIGZpbGUgc3lzdGVtKi4gIEluIGEgY29kaW5nIGVudmlyb25tZW50LCB0aGlzIHRyYW5zbGF0ZXMgdG8gdGhlIGlkZWEgb2YgKipzZXR0aW5nIGEgd29ya2luZyBkaXJlY3RvcnkqKiwgd2hpY2ggaXMgYSB3YXkgb2YgdGVsbGluZyBSIChvciBvdGhlciBjb2RpbmcgbGFuZ3VhZ2VzKSB3aGVyZSB5b3Ugd2FudCB0byBiZSBpbiB5b3VyIGNvbXB1dGVyJ3MgZmlsZSBzeXN0ZW0gd2hlbiB5b3UncmUgZG9pbmcgeW91ciB3b3JrLiAgDQoNCkEgY29tbW9uIHdheSB0byBzZXQgYSB3b3JraW5nIGRpcmVjdG9yeSBpcyB0byB1c2UgdGhlIGBzZXR3ZCgpYCBmdW5jdGlvbi4gVGhpcyBmdW5jdGlvbiBtYW51YWxseSBzZXRzIHRoZSB3b3JraW5nIGRpcmVjdG9yeSBkdXJpbmcgYW4gUiBzZXNzaW9uLiBJdCB0ZWxscyBSIHdoZXJlIHRvIGxvb2sgZm9yIGZpbGVzIGFuZCB3aGVyZSB0byBzYXZlIG91dHB1dHMganVzdCBmb3IgdGhhdCBzZXNzaW9uLg0KDQpUaGlzIGNhbiBiZSBkb25lIGluIDIgd2F5czoNCg0KKiBNYW51YWxseSBpbiBSLCBieSB3cml0aW5nIGBzZXR3ZCgicGF0aC10by1kaXJlY3Rvci9zZWNvbmRhcnktcGFydC9ldGMuLi4iKWANCiogU2V0dGluZyBpdCBieSBzZWxlY3RpbmcgdGhlIGBTZXNzaW9uYCB0YWIgaW4gdGhlIHRvb2xiYXIsIGFuZCBzZWxlY3RpbmcgYFNldCBXb3JraW5nIERpcmVjdG9yeWA6DQoNCiFbXShpbWFnZXMvYmxvY2s0LTFfc2V0LXdkLmdpZikNCg0KDQpCdXQgaGVyZeKAmXMgdGhlIHByb2JsZW0uLi4NCg0KVXNpbmcgYHNldHdkKClgIGNhbiBicmVhayB5b3VyIGNvZGUgd2hlbjoNCg0KIC0gU29tZW9uZSBlbHNlIHRyaWVzIHRvIHJ1biBpdCBvbiB0aGVpciBtYWNoaW5lLg0KIC0gWW91IG1vdmUgeW91ciBwcm9qZWN0IGZvbGRlci4NCiAtIFlvdSdyZSBydW5uaW5nIHlvdXIgY29kZSBvbiBhIHNlcnZlciBvciBpbiBjbG91ZCBlbnZpcm9ubWVudHMgbGlrZSBSU3R1ZGlvIENsb3VkLg0KDQpTaW5jZSBmaWxlIHBhdGhzIGFyZSBoYXJkY29kZWQgYW5kIGRlcGVuZCBvbiB5b3VyIG1hY2hpbmUsICoqaXQncyBub3QgcmVwcm9kdWNpYmxlKiouDQoNCiMjIyBDcmVhdGUgYW4gUiBQcm9qZWN0DQoNCkFuIFIgUHJvamVjdCBpcyBhIGZlYXR1cmUgaW4gUlN0dWRpbyAoYW5kIHN1cHBvcnRlZCBpbiBiYXNlIFIgdG9vKSB0aGF0IHByb3ZpZGVzIGEgc2VsZi1jb250YWluZWQgd29ya2luZyBlbnZpcm9ubWVudC4gV2hlbiB5b3UgY3JlYXRlIGFuIFIgUHJvamVjdCBpdCBjcmVhdGVzIGEgLlJwcm9qIGZpbGUgaW4gYSBmb2xkZXIgYW5kIHRoYXQgZm9sZGVyIGJlY29tZXMgdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHlvdXIgcHJvamVjdC4gRXZlcnkgdGltZSB5b3Ugb3BlbiB0aGUgcHJvamVjdCAodmlhIHRoZSAuUnByb2ogZmlsZSksIFIgYXV0b21hdGljYWxseSBzZXRzIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGF0IGZvbGRlci4gWW91IGNhbiByZWZlcmVuY2UgZmlsZXMgcmVsYXRpdmUgdG8gdGhlIHByb2plY3Qgcm9vdCDigJQgbm8gbmVlZCB0byBoYXJkY29kZSBmaWxlIHBhdGhzLg0KDQpUaGlzIGlzIHN1cGVyIHVzZWZ1bCB3aGVuIHlvdSdyZSB3b3JraW5nIG9uIG11bHRpcGxlIGFuYWx5c2VzLCBzaGFyaW5nIGNvZGUgd2l0aCBjb2xsYWJvcmF0b3JzLCBvciB2ZXJzaW9uLWNvbnRyb2xsaW5nIHdpdGggR2l0LiAqKkl0IGlzIGEgZ29vZCBwcmFjdGljZSBmb3IgcmVwcm9kdWNpYmxlIHJlc2VhcmNoKioNCg0KVG8gY3JlYXRlIGFuIFIgUHJvamVjdCwgc2VsZWN0IEZpbGUgPiBOZXcgUHJvamVjdA0KDQohW10oaW1hZ2VzL2RheTJfQ3JlYXRlUHJvamVjdC5naWYpDQoNCg0KIyMgWW91ciBUdXJuIQ0KDQo6OjpxdWVzdGlvbg0KQ3JlYXRlIHlvdXIgZmlyc3QgUlByb2plY3QuIExldCdzIGZpZ3VyZSBvdXQgd2hhdCB3ZSBzaG91bGQgY2FsbCBpdCENCjo6Og0KDQoNCiMjIFBhY2thZ2VzIGFuZCBMaWJyYXJpZXMNCg0KV2hlbiB5b3UgZmlyc3QgZG93bmxvYWQgUiwgaXQgY29tZXMgZXF1aXBwZWQgd2l0aCBhIG51bWJlciBvZiBwcmUtaW5zdGFsbGVkIGZ1bmN0aW9ucywgb3IgY2FwYWJpbGl0aWVzLCB0aGF0IHlvdSBjYW4gc3RhcnQgdXNpbmcgaW1tZWRpYXRlbHkuICBUaGlzIGlzIG9mdGVuIGNhbGxlZCAiQmFzZSBSOi4gIEhvd2V2ZXIsIGZvciBjZXJ0YWluIHRhc2tzIGFuZCB3b3JrZmxvd3MsIGl0IGNhbiBiZSBiZW5lZmljaWFsIHRvIHVzZSBtb3JlIHNwZWNpYWxpemVkIHRvb2xzLCBvciBmdW5jdGlvbnMsIHRvIGFjY29tcGxpc2ggd29yayBhbmQgZmFjaWxpdGF0ZSB3b3JrZmxvd3MgZm9yIGVmZmljaWVudGx5LiAgVGhpcyBpcyB3aGVyZSBwYWNrYWdlcyBhbmQgbGlicmFyaWVzIGNvbWUgaW50byBwbGF5Lg0KDQo6Ojpub3RlDQoNCiogKipQYWNrYWdlcyoqOiBQYWNrYWdlcyBhcmUgYW4gZXh0ZW5zaW9uIG9mIHRoZSBwcmUtYnVpbHQgZnVuY3Rpb25zIGluIFIsIGFuZCBjYW4gYmUgaW5zdGFsbGVkIHRvIGJyaW5nIGluIHNwZWNpZmljIGZ1bmN0aW9ucyB0byBhY2NvbXBsaXNoIHRhc2tzLCBicmluZyBpbiBzYW1wbGUgZGF0YXNldHMgdG8gcGxheSB3aXRoLCBhbW9uZyBvdGhlciB0aGluZ3MuICBUaGVyZSBhcmUgKip0b25zKiogb2YgUiBwYWNrYWdlcyBvdXQgdGhlcmUsIGJ1dCBoZXJlIGlzIGEgbGlzdCBvZiBzb21lIG9mIHRoZSBtb3N0IGNvbW1vbi91c2VmdWwgb25lczogW1F1aWNrIGxpc3Qgb2YgdXNlZnVsIFIgcGFja2FnZXNdKGh0dHBzOi8vc3VwcG9ydC5wb3NpdC5jby9oYy9lbi11cy9hcnRpY2xlcy8yMDEwNTc5ODctUXVpY2stbGlzdC1vZi11c2VmdWwtUi1wYWNrYWdlcykNCg0KKiAqKkxpYnJhcmllcyoqOiBPbmNlIHlvdSBoYXZlIGluc3RhbGxlZCBhIHBhY2thZ2UsIHRoZXkgYXJlIHN0b3JlZCBhcyBsaWJyYXJpZXMgaW4gUi4gIFlvdSBvbmx5IGhhdmUgdG8gaW5zdGFsbCB0aGVtIG9uY2UsIGFuZCBhbnl0aW1lIHlvdSB3YW50IHRvIHVzZSB0aGUgcGFja2FnZSB5b3UgY2FuIHVzZSB0aGUgYGxpYnJhcnkoKWAgZnVuY3Rpb24sIHdoaWNoIGlzIGRlc2NyaWJlZCBiZWxvdy4NCg0KOjo6DQoNCg0KIyMjIFRpZHl2ZXJzZQ0KDQpBcyBtZW50aW9uZWQgaW4gdGhlIHNlc3Npb24gKioiUmVwcm9kdWNpYmxlIFJlc2VhcmNoOiBNb3ZpbmcgRnJvbSBFeGNlbCB0byBTY3JpcHRpbmciKiosIHdlIHdpbGwgYmUgdXNpbmcgYW4gUiBwYWNrYWdlIGNhbGxlZCB0aGUgKioiVGlkeXZlcnNlIioqLiAgVGhlIFRpZHl2ZXJzZSBpcyBhIHZlcnkgY29tbW9ubHkgdXNlZCBwYWNrYWdlIGZvciByZXNlYXJjaCBhbmQgZGF0YSBzY2llbmNlIGFjdGl2aXRpZXMsIGFuZCBpbnN0ZWFkIG9mIGJlaW5nIGEgc2luZ2xlIHBhY2thZ2UsIGl0IGlzIGEgY29sbGVjdGlvbiBvZiBwYWNrYWdlcyB0aGF0IGFyZSBkZXNpZ25lZCB0byB3b3JrIHRvZ2V0aGVyIGFuZCB3aGljaCBmb2N1cyBvbiB0aGUgY29ubmVjdGlvbnMgYmV0d2VlbiBhY3Rpdml0aWVzIGluIHRoZSBkYXRhIHNjaWVuY2Ugd29ya2Zsb3cuICBFYWNoIHBhY2thZ2UgZm9sbG93cyB0aGUgc2FtZSBzeW50YXgsIHdoaWNoIG1ha2VzIGxlYXJuaW5nIHRoZW0gZWFzaWVyLCBhbmQgdGhlIHdlYnNpdGUgZnVuY3Rpb25zIGFzIGEgcmVhbGx5IGdvb2QgcmVmZXJlbmNlIHBvaW50IGlmIHlvdSdyZSBzdHJ1Z2dsaW5nIHdpdGggaG93IHRvIGFwcHJvYWNoIGEgc3BlY2lmaWMgdGFzay4NCg0KIVtdKGltYWdlcy9ibG9jazRfZGF0YS1zY2llbmNlLXdvcmtmbG93LmpwZykNCg0KDQpMZXQncyB0YWtlIGEgY2xvc2VyIGxvb2shICBbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL3BhY2thZ2VzLykNCg0KPGJyPg0KDQojIyBMZXQncyBnZXQgc3RhcnRlZCENCg0KRmlyc3QsIGxldCdzIGNyZWF0ZSBhIG5ldyBSIHNjcmlwdC4NCg0KVG8gY3JlYXRlIGFuIFIgc2NyaXB0IGZpbGUsIHNlbGVjdCBGaWxlID4gTmV3IEZpbGUgPiBSIFNjcmlwdA0KDQohW10oaW1hZ2VzL2Jsb2NrM19jcmVhdGUtci1zY3JpcHQuZ2lmKQ0KDQoNCiMjIyBJbnN0YWxsIFBhY2thZ2UNClRvIGluc3RhbGwgYSBwYWNrYWdlIHdlIHVzZSB0aGUgZnVuY3Rpb24gYGluc3RhbGwucGFja2FnZXMoKWAuIA0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KYGBgDQoNCiMjIyBMb2FkIExpYnJhcmllcw0KUGFja2FnZXMgYXJlIHN0b3JlZCBpbiBsaWJyYXJpZXMuIE9uY2UgYSBwYWNrYWdlIGlzIGluc3RhbGxlZCwgd2UgbmVlZCB0byBjYWxsIHRoZSBsaWJyYXJ5IHdpdGggdGhlIGZ1bmN0aW9uIGBsaWJyYXJ5KClgLg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCjo6OmZsYWcNCk5vdGUgdGhhdCB0aGUgcGFja2FnZSBuYW1lIG5lZWRzIHRvIGJlIGluIHF1b3RhdGlvbnMgd2hlbiBpbnN0YWxsaW5nIHRoZSBwYWNrYWdlLCBidXQgbm90IHdoZW4gbG9hZGluZyB0aGUgbGlicmFyeS4NCg0KQmVjYXVzZSBwYWNrYWdlcyBvbmx5IG5lZWQgdG8gYmUgaW5zdGFsbGVkIG9uY2UsIHdlIGNhbiBkbyB0aGlzIGluIHRoZSBSIGNvbnNvbGUgYXMgb3Bwb3NlZCB0byBpbiB0aGUgc2NyaXB0Lg0KDQpCZWNhdXNlIGxpYnJhcmllcyBuZWVkIHRvIGJlIGxvYWRlZCBpbiBlYWNoIHdvcmtpbmcgc2Vzc2lvbiwgd2UgY2FuIGRvIHRoaXMgaW4gdGhlIFIgc2NyaXB0IHNvIHRoYXQgb3RoZXJzIGNhbiBzZWUgd2hhdCBsaWJyYXJpZXMgd2UgYXJlIHVzaW5nIGFuZCBuZWVkIHRvIGJlIGxvYWRlZC4NCjo6Og0KDQoNClJlZmVycmluZyBhZ2FpbiB0byB0aGUgVGlkeXZlcnNlIERhdGEgU2NpZW5jZSBXb3JrZmxvdywgaW4gdGhpcyBzZXNzaW9uIHdlJ2xsIGJlIGZvY3VzaW5nIG9uIHRoZSBmaXJzdCB0d28gc3RlcHM6DQoNCiFbXShpbWFnZXMvZGF5Ml93b3JrZmxvdy5wbmcpDQo8YSBocmVmPSJodHRwczovL3RlbGFwcHMubG9uZG9uLmVkdS9hbmFseXRpY3Nfd2l0aF9SL3RpZHl2ZXJzZS5odG1sIj5Tb3VyY2U8L2E+DQoNCiMjIFJlYWRpbmcgRGF0YQ0KDQpJbiBvcmRlciB0byBzdGFydCB3b3JraW5nIHdpdGggYSBkYXRhc2V0IGluIFIsIHdlIGZpcnN0IG5lZWQgdG8gaW1wb3J0LCBvciAicmVhZCBpbiIsIHRoZSBkYXRhLiAgQXMgbWVudGlvbmVkIGluIHRoZSBzZXNzaW9uICoqIlJlcHJvZHVjaWJsZSBSZXNlYXJjaDogTW92aW5nIEZyb20gRXhjZWwgdG8gU2NyaXB0aW5nIioqLCB3ZSB3aWxsIGJlIHdvcmtpbmcgd2l0aCBgLmNzdmAgZmlsZXMsIGJ1dCBSIGlzIGNhcGFibGUgb2YgcmVhZGluZyBpbiBvdGhlciBmaWxlIHR5cGVzIGFzIHdlbGwuDQoNCg0KIyMjIFJlYWQgYSBjc3YgZmlsZQ0KVG8gaW1wb3J0IGEgY3N2IGZpbGUgd2UgY2FuIHVzZSB0aGUgYHJlYWRfY3N2KClgIGZ1bmN0aW9uIGFuZCBhc3NpZ24gaXQgdG8gYSBuZXcgb2JqZWN0IHdlIHdpbGwgY2FsbCAqanNfZGF0YSouIFdlIGNyZWF0ZSBhIG5ldyBvYmplY3QgdG8gYmUgYWJsZSB0byBjYWxsIGl0IGluIGRpZmZlcmVudCBmdW5jdGlvbnMgbGF0ZXIgb24uDQpgYGB7cn0NCmpzX2RhdGEgPC0gcmVhZF9jc3YoImRhdGEvYmxvY2stNF9maXJzdC1zdGVwcy5jc3YiKQ0KYGBgDQoNCiMjIyBSZWFkIE90aGVyIEZvcm1hdHMNCkluIHRoZSBleGFtcGxlIHdlIGFyZSB3b3JraW5nIHdpdGggdGhlIGRhdGEgaXMgc3RvcmVkIGluIGEgY3N2IGZpbGUuIFRoZSBwYWNrYWdlICoqcmVhZHIqKiBmcm9tIFRpZHl2ZXJzZSBjYW4gYWxzbyByZWFkIG90aGVyIGZvcm1hdHMgbGlrZSBgcmVhZF90c3YoKWAodGFiLXNlcGFyYXRlZCB2YWx1ZXMpLCBgcmVhZF9kZWxpbSgpYChkZWxpbWl0ZWQgZmlsZXMgQ1NWIGFuZCBUU1YpLCBgcmVhZF90YWJsZSgpYCh3aGl0ZXNwYWNlLXNlcGFyYXRlZCBmaWxlcyksIGByZWFkX2xvZygpYCh3ZWIgbG9nIGZpbGVzKS4NCg0KVGhlcmUgYXJlIG90aGVyIGZ1bmN0aW9ucyBhbmQgcGFja2FnZXMgdGhhdCBhbGxvdyB1cyB0byBpbXBvcnQgZGlmZmVyZW50IGZpbGUgdHlwZXMuIA0KDQoqKkZpbGUgVHlwZSoqIHwqKkZ1bmN0aW9uKiogfCAqKlBhY2thZ2UqKg0KfDotLS0tLS18Oi0tLS0tLXw6LS0tLS0tLXwNCnwuY3N2IHwgYHJlYWRfY3N2KClgfCByZWFkciB8DQp8IC54bHN4IHwgYHJlYWQueGxzeCgpYHwgeGxzeCB8DQp8IC5zYXYgfCBgcmVhZF9zYXYoKWB8IGhhdmVuIHwNCnwgLnNhczdiZGF0ICwgLnNhczdiY2F0IHwgYHJlYWRfc2FzKClgfCBoYXZlbiB8DQp8IC5kdGEgfCBgcmVhZF9kdGEoKWB8IGhhdmVuIHwNCg0KIyMgTGlzdGluZyBDb2x1bW4gTmFtZXMNClRvIGFzayBmb3IgYSBsaXN0IG9mIGFsbCB0aGUgY29sdW1uIG5hbWVzIGluIG91ciBkYXRhc2V0IHdlIGNhbiB1c2UgdGhlIGBuYW1lcygpYCBmdW5jdGlvbi4NCmBgYHtyfQ0KbmFtZXMoanNfZGF0YSkNCmBgYA0KDQpOb3RpY2UgdGhhdCB0aGUgY29sdW1uIG5hbWVzIGZyb20gdGhlIG9yaWdpbmFsIGRhdGFzZXQgZG9uJ3QgcHJvdmlkZSBhIGNsZWFyIGRlc2NyaXB0aW9uIG9mIHdoYXQgdGhlIHZhcmlhYmxlIGlzLiBXZSB3aWxsIGNoYW5nZSB0aGUgY29sdW1uIG5hbWVzIGxhdGVyIHRvIGZhY2lsaXRhdGUgd29ya2luZyB3aXRoIG91ciBkYXRhIGluIHRoZSBmdXR1cmUuDQoNCiMjIEhlYWQgRnVuY3Rpb24NClRoZSBoZWFkIGZ1bmN0aW9uIHdpbGwgZGlzcGxheSB0aGUgdG9wIHJvd3Mgb2YgdGhlIGRhdGFzZXQuIEl0IHdpbGwgaW5jbHVkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGVmYXVsdCBkYXRhIHR5cGUgYXNzaWduZWQgdG8gZWFjaCBjb2x1bW4uIFdlIHdpbGwgY292ZXIgZGF0YSB0eXBlcyBtb3JlIGluIHRoZSBuZXh0IHNlc3Npb24uDQoNCmBgYHtyLCBkYXRhLWlzb2xhdGlvbiwgcmVzdWx0cyA9IEZBTFNFfQ0KaGVhZChqc19kYXRhKQ0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoa2FibGVFeHRyYSkNCmhlYWQoanNfZGF0YSl8Pg0KICBrYmwoKSB8Pg0KICAja2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIikNCmthYmxlX3BhcGVyKCkgJT4lDQogIHNjcm9sbF9ib3god2lkdGggPSAiNTAwcHgiLCBoZWlnaHQgPSAiMjAwcHgiKQ0KDQpgYGANCg0KIyMgVmlld2luZyBEYXRhDQpUbyB2aXN1YWxpemUgdGhlIGZ1bGwgZGF0YXNldCB3ZSB1c2UgdGhlIGBWaWV3KClgIGZ1bmN0aW9uLiBUaGlzIHdpbGwgb3BlbiBvdXIgZGF0YXNldCBpbiBhIHNlcGFyYXRlIHdpbmRvdy4NCmBgYHtyLCBldmFsPUZBTFNFfQ0KVmlldyhqc19kYXRhKQ0KYGBgDQoNCg0KIyMgQ2hhbmdlIENvbHVtbiBOYW1lcw0KDQpMZXQncyBub3cgcmV0dXJuIHRvIHRoZSBSIHN5bnRheCBkaWFncmFtIHRoYXQgd2UgbG9va2VkIGF0IGluIEJsb2NrIDM6DQoNCiFbXShpbWFnZXMvZGF5Ml9SU3ludGF4LnBuZykNCg0KSW4gdGhhdCBzZXNzaW9uLCB3ZSBkaXNjdXNzZWQgKipvYmplY3RzKiogYW5kICoqZnVuY3Rpb25zKiosIGFuZCBwbGF5ZWQgd2l0aCB0aGUgaWRlYSBvZiBvYmplY3RzIHN0b3JpbmcgaW5mb3JtYXRpb24sIGFuZCBmdW5jdGlvbnMgbWFuaXB1bGF0aW5nIHRoZSBvYmplY3QvZGF0YS4NCg0KTm93IHdlJ3JlIGdvaW5nIHRvIHN0YXJ0IGltcGxlbWVudGluZyAqKnBpcGVzKiogYXMgYSB3YXkgdG8gY29ubmVjdCBvYmplY3RzIHRvICoqZnVuY3Rpb25zKiogYW5kICoqYXJndW1lbnRzKiouDQoNCiMjIyMgUGlwZXMNCg0KUGlwZXMgYXJlIHVzZWQgdG8gY2hhaW4gc3RlcHMgb2YgaW5zdHJ1Y3Rpb25zIG9yIGFjdGlvbnMgdG9nZXRoZXIsIGFuZCBvZnRlbiBpbnZvbHZlIHdyaXRpbmcgb3ZlciBhbiBvYmplY3QgdG8gZ2l2ZSBpdCBhIG5ldyB2YWx1ZS4gV2UnbGwgd2FsayB0aHJvdWdoIHNvbWUgZXhhbXBsZXMgb2YgaG93IHRoaXMgd29ya3MsIGFuZCBzdGFydCB0byBzZWUgaG93IHRoZSBmdWxsIHN5bnRheCBvZiBSIGNvbWVzIHRvZ2V0aGVyLg0KDQo8YnI+DQoNCldlIG1lbnRpb25lZCBlYXJsaWVyIHRoYXQgd2Ugd2FudGVkIHRvIHdvcmsgd2l0aCBjb2x1bW4gbmFtZXMgdGhhdCB3ZXJlIG1vcmUgZGVzY3JpcHRpdmUgb2YgdGhlIGNvbnRlbnQgb2YgZWFjaCB2YXJpYWJsZS4gVG8gY2hhbmdlIGNvbHVtbiBuYW1lcyB3ZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcmVuYW1lKClgLg0KDQpUaGUgZnVuY3Rpb24gYHJlbmFtZSgpYCBpcyBwYXJ0IG9mIG9uZSBvZiB0aGUgcGFja2FnZXMgdGhhdCB3YXMgaW5zdGFsbGVkIHdpdGggdGlkeXZlcnNlLg0KDQo6Ojp3YWxrdGhyb3VnaA0KVHlwZSB0aGUgZm9sbG93aW5nIGNvZGUgdG8gY2hhbmdlIHRoZSBjb2x1bW4gbmFtZSBmcm9tICJQVU1GSUQiIHRvICJpZCINCmBgYHtyfQ0KanNfZGF0YSA8LSBqc19kYXRhIHw+DQogIHJlbmFtZSgiaWQiID0gIlBVTUZJRCIpDQpgYGANCg0KKipTdGVwLWJ5LXN0ZXAgZXhwbGFuYXRpb246KioNCg0KKiBUaGlzIGNvbW1hbmQgZmlyc3Qgc3RhcnRzIG9mZiB3aXRoIHRoZSBganNfZGF0YWAgb2JqZWN0LCB3aGljaCBpcyBvdXIgZGF0YXNldC4NCiogVGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IgY29tZXMgbmV4dCwgYW5kIHdpbGwgcmUtd3JpdGUgdGhlIGluZm9ybWF0aW9uIHN0b3JlZCBpbiBganNfZGF0YWAgd2l0aCBhbGwgdGhlIGluZm9ybWF0aW9uIHRoYXQgaXMgdG8gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIG9wZXJhdG9yLg0KKiBXZSB0aGVuIHVzZSB0aGUgYGpzX2RhdGFgIG9iamVjdCBhbmQgdGhlIHBpcGUgYHw+YCB0byB0ZWxsIFIgdGhhdCB3ZSB3YW50IHRvIHRha2UgdGhlIGRhdGEgdGhhdCBpcyBzdG9yZWQgaW4gYGpzX2RhdGFgLCBhbmQgdGhlbiBkbyBzb21ldGhpbmcgdG8gaXQgKHdoaWNoIGlzIHdoYXQgY29tZXMgYWZ0ZXIgdGhlIHBpcGUpLg0KKiBUaGUgYHJlbmFtZWAgZnVuY3Rpb24gaXMgdXNlZCB0byByZW5hbWUgY29sdW1ucywgYW5kIGlzIGFsd2F5cyBmb2xsb3dlZCBieSBicmFja2V0cy4gIEluc2lkZSB0aG9zZSBicmFja2V0cywgd2UnbGwgcHV0IHRoZSBuZXcgY29sdW1uIG5hbWUgdGhhdCB3ZSB3YW50IGluIHF1b3RhdGlvbiBtYXJrcyBgIiJgLCBmb2xsb3dlZCBieSBhbiBlcXVhbCBzaWduIGA9YCwgZm9sbG93ZWQgYnkgdGhlIGV4aXN0aW5nIGNvbHVtbiBuYW1lIGluIHF1b3RhdGlvbiBtYXJrcyBgIiJgLg0KKiBXZSB0aGVuIHJ1biB0aGUgY29tbWFuZCBhbmQgaG9wZSBpdCB3b3JrcyENCjo6Og0KDQojIyBZb3VyIFR1cm4hDQoNCjo6OnF1ZXN0aW9uDQpGaXJzdCwgdXNlIHRoZSBmdW5jdGlvbmBuYW1lcygpYCB0byBkaXNwbGF5IHRoZSBjb2x1bW4gbmFtZXMuDQpgYGB7ciwgZXZhbD1GQUxTRX0NCm5hbWVzKGpzX2RhdGEpDQpgYGANCjo6Og0KDQo6OjpxdWVzdGlvbg0KTm93LCBzZWUgaWYgeW91IGNhbiBjaGFuZ2UgdGhlIGBBR0VHUjEwYCBjb2x1bW4gbmFtZSB0byBgYWdlR3JwYA0KYGBge3IsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnfQ0KanNfZGF0YSA8LSBqc19kYXRhIHw+DQogIHJlbmFtZSgiYWdlR3JwIiA9ICJBR0VHUjEwIikNCmBgYA0KDQo6OjoNCg0KOjo6cXVlc3Rpb24NCk5leHQsIHRyeSB0byBjaGFuZ2UgdGhlIGZvbGxvd2luZyAzIGNvbHVtbiBuYW1lczoNCg0KKiBDaGFuZ2UgYFNFWGAgdG8gYHNleGANCiogQ2hhbmdlIGBNQVJTVEFUYCB0byBgbWFyaXRhbFN0YXRgDQoqIENoYW5nZSBgUFJWYCB0byBgcHJvdmluY2VgDQoNCioqSGludDoqKiBJdCBjYW4gYmUgdGVkaW91cyB0byBkbyB0aGVzZSBjaGFuZ2VzIG9uZSBieSBvbmUsIGJ1dCBieSB1c2luZyBjb21tYXMgYCxgIHlvdSBjYW4gcmVuYW1lIGNvbHVtbiBuYW1lcyB3aXRoIGEgc2luZ2xlIGNvZGUgY2h1bmsuICANCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJ30NCmpzX2RhdGEgPC0ganNfZGF0YSB8Pg0KICByZW5hbWUoInNleCIgPSAiU0VYIiwNCiAgICAgICAgICAibWFyaXRhbFN0YXQiID0gIk1BUlNUQVQiLA0KICAgICAgICAgICJwcm92aW5jZSIgPSAiUFJWIikNCmBgYA0KOjo6DQoNCjo6OnF1ZXN0aW9uDQpOb3csIHRvIGNoYW5nZSB0aGUgcmVzdCBvZiB0aGUgY29sdW1uIG5hbWVzIGNvcHkgdGhlIGZvbGxvd2luZyBjb2RlLiAoSWYgeW91IGZlZWwgeW91J3JlIHN0YXJ0aW5nIHRvIHVuZGVyc3RhbmQgaG93IHRoaXMgd29ya3MsIHlvdSBjYW4gc2hvdyB0aGUgY29kZSBiZWxvdyBhbmQgYGNvcGUgKyBwYXN0ZWAgaXQgaW50byB5b3VyIHNjcmlwdCwgb3IgaWYgeW91IHdhbnQgc29tZSBtb3JlIHByYWN0aWNlLCBmZWVsIGZyZWUgdG8gZG8gaXQgeW91cnNlbGYhDQoNCmBgYHtyLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJ30NCmpzX2RhdGEgPC0ganNfZGF0YSB8Pg0KICByZW5hbWUoInBvcENlbnRlciIgPSAiTFVDX1JTVCIsDQogICAgICAgICAgImVkdUxldmVsIiA9ICJFSEdfQUxMIiwNCiAgICAgICAgICAiZmVlbFJ1c2hlZCIgPSAiR1RVXzExMCIsDQogICAgICAgICAgImV4dHJhVGltZSIgPSAiR1RVXzEzMCIsDQogICAgICAgICAgImR1clNsZWVwIiA9ICJEVVIwMSIsDQogICAgICAgICAgImR1ck1lYWxQcmVwIiA9ICJEVVIwNSIsDQogICAgICAgICAgImR1ckVhdGluZyIgPSAiRFVSMDYiLA0KICAgICAgICAgICJkdXJBbG9uZSIgPSAiRFVSUzIwMCIsDQogICAgICAgICAgImR1ckRyaXZpbmciID0gIkRVUkwzMTMiLA0KICAgICAgICAgICJkdXJXb3JrIiA9ICJEVVIwOCIsDQogICAgICAgICAgImR1clNob29sU2l0ZSIgPSAiRFVSMTMiLA0KICAgICAgICAgICJkdXJTY2hvb2xPbmxpbmUiID0gIkRVUjE0IiwNCiAgICAgICAgICAiZHVyU3R1ZHkiID0gIkRVUjE1IiwNCiAgICAgICAgICAibWFpblN0dWR5IiA9ICJNUldfMjAiLA0KICAgICAgICAgICJtYWluSm9iSHVudGluZyIgPSAiTVJXXzMwIiwNCiAgICAgICAgICAibWFpbldvcmsiID0gIk1SV180MCIsDQogICAgICAgICAgIndvcmtlZDEybSIgPSAiTVJXX0Q0MEEiLA0KICAgICAgICAgICJ3b3JrZWRXZWVrIiA9ICJNUldfRDQwQiIsDQogICAgICAgICAgImVucm9sbFN0YXQiID0gIkVETV8wMiIsDQogICAgICAgICAgImRhaWx5VGV4dHMiID0gIlRTVF8wMSIsDQogICAgICAgICAgInRpbWVTbG93RG93biIgPSAiVENTXzExMCIsDQogICAgICAgICAgInRpbWVXb3JrYWhvbGljIiA9ICJUQ1NfMTIwIiwNCiAgICAgICAgICAidGltZU5vdEZhbUZyaWVuZHMiID0gIlRDU18xNTAiLA0KICAgICAgICAgICJ0aW1lV2FudEFsb25lIiA9ICJUQ1NfMjAwIikNCmBgYA0KDQo6OjoNCg0KIyMgU2F2ZSBZb3VyIFdvcmsNCg0KDQpOb3cgdGhhdCB3ZSd2ZSBjcmVhdGVkIGEgZGF0YXNldCB0aGF0IGhhcyBzb21lIHNpZ25pZmljYW50IGNoYW5nZXMsIGl0IGNhbiBiZSBoZWxwZnVsIHRvIHNhdmUgdGhpcyBhcyBhIHZlcnNpb24gdGhhdCB3ZSBjYW4gZWFzaWx5IHJldHVybiB0by4gIE11Y2ggbGlrZSB3ZSBkaWQgd2l0aCByZWFkaW5nIGAuY3N2YCBkYXRhIGludG8gUiwgdGhlcmUgaXMgYSBzaW1pbGFyIGNvbW1hbmQgdG8gc2F2ZSwgb3IgIndyaXRlIiBgLmNzdmAgZGF0YSBiYWNrIHRvIHlvdXIgY29tcHV0ZXIgY2FsbGVkIGB3cml0ZV9jc3YoKWAuICBUaGUgc3ludGF4IGlzIGFzIGZvbGxvd3M6DQoNCmB3cml0ZV9jc3YoZGF0YS1vYmplY3QtbmFtZSwgZmlsZT0iZmlsZS1wYXRoL2RhdGFmaWxlLW5hbWUuY3N2IilgDQoNClRoZSBmaWxlIG5hbWUgYmVsb3cgaXMgZm9yIGV4YW1wbGUgcHVycG9zZXMsIGFuZCBmZWVsIGZyZWUgdG8gdXNlIGEgZmlsZSBuYW1pbmcgY29udmVudGlvbiB0aGF0IHlvdSBkZXZlbG9wZWQ6DQoNCmBgYHtyfQ0Kd3JpdGVfY3N2KGpzX2RhdGEsIGZpbGU9ImRhdGEvY2xlYW4tY29scy5jc3YiKQ0KYGBgDQoNCjxicj4NCg0KIyMjIC5SRGF0YSBGaWxlcw0KDQpBbiBhZGRpdGlvbmFsIHdheSB0byBzYXZlIGRhdGEgZmlsZXMgaW4gUiBpcyBhcyBhbiBgLlJkYXRhYCBmaWxlLiAgVW5saWtlIGEgc2ltcGxlIGAuY3N2YCBmaWxlLCBgLlJEYXRhYCBmaWxlcyBhcmUgZGVzaWduZWQgdG8gc3RvcmUgUiBvYmplY3RzIGFuZCB5b3VyIGVudGlyZSBSIHdvcmtzcGFjZSwgd2hpbGUgbWFpbnRhaW4gdGhlaXIgZGF0YSB0eXBlcyBhbmQgc3RydWN0dXJlcyAoY292ZXJlZCBpbiB0aGUgbmV4dCBzZXNzaW9uISkuICBUaGlzIGFsbG93cyB5b3UgdG8gcmV0dXJuIHRvIHlvdXIgUiBlbnZpcm9ubWVudCBleGFjdGx5IGFzIHlvdSBsZWZ0IGl0IHdoZW4geW91IHJlbG9hZCB0aGUgZmlsZSwgYW5kIGFsbG93cyBvdGhlcnMgb3BlbmluZyB5b3VyIGZpbGVzIHRvIGhhdmUgdGhhdCBlbnZpcm9ubWVudCBhcyB3ZWxsLCBhY3RpbmcgYXMgYSBncmVhdCB3YXkgdG8gZmFjaWxpYXRlIHJlcHJvZHVjaWJpbGl0eS4NCg0KVGhlIHN5bnRheCBpcyBzaW1pbGFyIGlzIHRoZSBzYW1lIGFzIGB3cml0ZV9jc3ZgLCBidXQgdXNlcyB0aGUgZnVuY3Rpb24gYHNhdmUoKWA6DQoNCmBgYHtyfQ0Kc2F2ZShqc19kYXRhLCBmaWxlPSJkYXRhL2NsZWFuLWNvbHMuUkRhdGEiKQ0KYGBgDQoNCjxicj4NCg0KOjo6bm90ZQ0KV2hlbiBvcGVuaW5nIGFuIGAuUkRhdGFgIGZpbGUsIGluc3RlYWQgb2YgdXNpbmcgYHJlYWRfY3N2KClgLCB5b3UgdXNlIHRoZSBgbG9hZCgpYCBjb21tYW5kLiAgVGhlIHN5bnRheCBpcyB0aGUgc2FtZSwgYW5kIHRvIHJlb3BlbiB0aGUgZmlsZSB5b3UganVzdCBzYXZlZCB3b3VsZCBsb29rIGxpa2UgdGhpczoNCmBgYHtyLCBldmFsID0gRkFMU0V9DQpgbG9hZCgiZGF0YS9jbGVhbi1jb2xzLlJEYXRhIilgDQpgYGANCg0KDQo6OjoNCg0KDQoNCg0K