Introduction
RMarkdown lets you combine R code and text in one document to create
dynamic, reproducible reports.
By embedding code directly within your written explanations,
RMarkdown ensures that your analysis, results, and visuals are
automatically updated if the data or code changes—making it easy for
others (and your future self!) to understand, verify, and rerun your
work exactly as it was done.
In this short tutorial, we will learn:
- How to use R code within a RMarkdown document
- How to import and explore our dataset
- How to recode column names
Intro to Data in R
Basic Syntax of R
The most important components of an R script are
objects and functions. Objects store
information and functions are used to manipulate the data.
Assignment operators, pipes and
arguments are used to link objects and functions and
communicate what we want to do.

Objects
An object is anything you create and name in R. It can be a number, a
dataset, a function, or even a plot. Objects take on content from
everything to the right of the assignment operator.
x <- 5 #x is now an object that holds the value 5
b <- "Anna" #b is now an object that holds the character Anna
Notes:
Since Anna is a character, it needs to be wrapped in quotations
(e will learn more about data types tomorrow).
The symbol #
is used within a code chunk to insert
comments. Comments won’t affect how the code runs, but text that is not
signaled as a comment will generate errors.
Functions
Functions are a set of instructions that accomplish a task. They are
often (though not always) instructions to be performed on an argument.
Functions do something—like calculate, sort, or plot. You call them by
their name and add parentheses.
Arguments
Arguments are the details you give a function so it knows what to do.
They go inside the parentheses of a function. Let’s take a look at the
function mean()
Type mean
in the Help tab of the bottom left panel. The
results will provide a description of the function, including its
arguments.
x |
x is an R object that contains the numbers we want to
find the mean of |
No default, required |
trim |
A number between 0 and 0.5. Removes a fraction of
highest and lowest values before computing mean (useful if you want a
trimmed mean that ignores outliers). |
0 means no trimming |
na.rm |
Indicates whether NA values should be included or not
in the calculation |
TRUE if NA values should be removed, FALSE if not |
Assignment Operators
This is how you store a value in R. It’s like saying: “Let this name
hold this value.” It assigns content from the
objects/functions/arguments on its right to the object on its left.
name <- "Maria" #Now name holds the string "Maria".
Note: The assignment operator <-
is
also considered a function. It is a ‘store’ function that assigns
information to an object. The arrow <-
is the most
common, but =
can also be used in some contexts.
You can overwrite a new value to the same object name. When you
assign again, the previous content is replaced.
name <- "Anna" #Now name replaces the previous information and holds the string "Anna".
Why Overwriting is Useful
As your analysis becomes more complicated, you often build your
results step-by-step.
Instead of creating dozens of different object names, you can
reuse the same object name to store updated versions of your data or
results.
This keeps your environment clean and your code easier to
read.
Pipes
This is used to chain steps together in a readable way. Instead of
nesting functions, you move step-by-step like a recipe.
mynumbers <- (c(1,2,3)) #storing the numbers 1, 2 and 3 in the object called "mynumbers"
mynumbers |> mean() #take the object mynumbers and pipe it into the mean function
## [1] 2
Note: In R, c()
stands for “combine” or
“concatenate”. The role of c()
is to combine the values
inside it into a vector — a basic data structure in R. It takes the
individual numbers 1, 2, and 3 and creates a single vector: 1 2 3. You
can think of c()
as “gluing” elements together into one
group. You will learn more about data types and structures tomorrow.
Packages and Libraries
Collections of R functions are stored in Packages. In order to use a
specific function we need to install the package that contains that
function.
Tidyverse
When we talk about “Base R” we refer to the original functions and
syntax included with R—no extra packages needed. Base R contains many
functions like read.csv()
, mean()
,
subset()
, and plot()
. It can be very powerful
and flexible but sometimes it is less intuitive for beginners.
We will install Tidyverse, which is a collection of
packages designed to make data analysis easier and more consistent.
Think of the tidyverse as a toolbox that gives you simple and
readable functions for the most common steps in working with data:
- Importing data (e.g., readr, readxl)
- Cleaning and transforming data (e.g., dplyr, tidyr)
- Visualizing data (e.g., ggplot2)
- Working with strings (e.g., stringr) or dates (e.g., lubridate)
All these packages follow the same logic and syntax, so once you
learn one, the others feel familiar too. For additional information,
visit the tidyverse info
page
We will be using packages from Tidyverse later today and
tomorrow…
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 'purrr' was built under R version 4.3.3
## Warning: package 'lubridate' was built under R version 4.3.3
Note that the package name needs to be in quotations when installing
the package, but not when loading the library.
Packages only need to be installed once.
Libraries need to be loaded in each work session.
Remember the Tidyverse Data Science Workflow? Today we will be
focusing on the first two steps:
Source
Read Data
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/timeuse_day1_na.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"
## [7] "EHG_ALL" "GTU_110" "GTU_130" "DUR01" "DUR05" "DUR06"
## [13] "DURS200" "DURL313" "DUR08" "DUR13" "DUR14" "DUR15"
## [19] "MRW_20" "MRW_30" "MRW_40" "MRW_D40A" "MRW_D40B" "EDM_02"
## [25] "TST_01" "TCS_110" "TCS_120" "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.
You will learn more about data types tomorrow.
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
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")
Did it work?
Your Turn!
Now, to change the rest of the column names copy the following code.
(click show to see the code)
js_data <- js_data |>
rename ("ageGrp" = "AGEGR10",
"sex" = "SEX",
"maritalStat" = "MARSTAT",
"province" = "PRV",
"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")
Use the functionnames(data)
to display the column
names.
names(js_data)
## [1] "id" "ageGrp" "sex"
## [4] "maritalStat" "province" "popCenter"
## [7] "eduLevel" "feelRushed" "extraTime"
## [10] "durSleep" "durMealPrep" "durEating"
## [13] "durAlone" "durDriving" "durWork"
## [16] "durShoolSite" "durSchoolOnline" "durStudy"
## [19] "mainStudy" "mainJobHunting" "mainWork"
## [22] "worked12m" "workedWeek" "enrollStat"
## [25] "dailyTexts" "timeSlowDown" "timeWorkaholic"
## [28] "timeNotFamFriends" "timeWantAlone"
Save your work
Saving in R format (RData) will preserve data types and metadata
assigned to the dataset. The text format (csv) will be the ideal format
to share the data.
save(js_data, file="data/timeuse_day2.RData")
write_csv(js_data, file="data/timeuse_day2.csv")
Upload to OSF
At the end of each work session, remember to save your data as .RData
and .csv, and also your RMarkdown file (.Rmd). We will upload those
files to OSF.

LS0tCnRpdGxlOiAiRmlyc3Qgc3RlcHMgaW4gUiIKcGFnZXRpdGxlOiAiRmlyc3Qgc3RlcHMgaW4gUiIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IHNob3cgIyBhbGxvd3MgdG9nZ2xpbmcgb2Ygc2hvd2luZyBhbmQgaGlkaW5nIGNvZGUuIFJlbW92ZSBpZiBub3QgdXNpbmcgY29kZS4KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgIyBhbGxvd3MgdGhlIHVzZXIgdG8gZG93bmxvYWQgdGhlIHNvdXJjZSAuUm1kIGZpbGUuIFJlbW92ZSBpZiBub3QgdXNpbmcgY29kZS4KICAgIGluY2x1ZGVzOgogICAgICBhZnRlcl9ib2R5OiBmb290ZXIuaHRtbCAjIGluY2x1ZGUgYSBjdXN0b20gZm9vdGVyLgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmdzID0gRkFMU0UpCmBgYAoKIyMgSW50cm9kdWN0aW9uCgo6OjppYm50cm8KUk1hcmtkb3duIGxldHMgeW91IGNvbWJpbmUgUiBjb2RlIGFuZCB0ZXh0IGluIG9uZSBkb2N1bWVudCB0byBjcmVhdGUgZHluYW1pYywgcmVwcm9kdWNpYmxlIHJlcG9ydHMuCjo6OgoKQnkgZW1iZWRkaW5nIGNvZGUgZGlyZWN0bHkgd2l0aGluIHlvdXIgd3JpdHRlbiBleHBsYW5hdGlvbnMsIFJNYXJrZG93biBlbnN1cmVzIHRoYXQgeW91ciBhbmFseXNpcywgcmVzdWx0cywgYW5kIHZpc3VhbHMgYXJlIGF1dG9tYXRpY2FsbHkgdXBkYXRlZCBpZiB0aGUgZGF0YSBvciBjb2RlIGNoYW5nZXPigJRtYWtpbmcgaXQgZWFzeSBmb3Igb3RoZXJzIChhbmQgeW91ciBmdXR1cmUgc2VsZiEpIHRvIHVuZGVyc3RhbmQsIHZlcmlmeSwgYW5kIHJlcnVuIHlvdXIgd29yayBleGFjdGx5IGFzIGl0IHdhcyBkb25lLgoKSW4gdGhpcyBzaG9ydCB0dXRvcmlhbCwgd2Ugd2lsbCBsZWFybjoKCi0gSG93IHRvIHVzZSBSIGNvZGUgd2l0aGluIGEgUk1hcmtkb3duIGRvY3VtZW50Ci0gSG93IHRvIGltcG9ydCBhbmQgZXhwbG9yZSBvdXIgZGF0YXNldAotIEhvdyB0byByZWNvZGUgY29sdW1uIG5hbWVzIAoKCiMjIEludHJvIHRvIERhdGEgaW4gUgoKIyMjIEJhc2ljIFN5bnRheCBvZiBSIAoKVGhlIG1vc3QgaW1wb3J0YW50IGNvbXBvbmVudHMgb2YgYW4gUiBzY3JpcHQgYXJlICoqb2JqZWN0cyoqIGFuZCAqKmZ1bmN0aW9ucyoqLiBPYmplY3RzIHN0b3JlIGluZm9ybWF0aW9uIGFuZCBmdW5jdGlvbnMgYXJlIHVzZWQgdG8gbWFuaXB1bGF0ZSB0aGUgZGF0YS4gCgoqKkFzc2lnbm1lbnQgb3BlcmF0b3JzKiosICoqcGlwZXMqKiBhbmQgKiphcmd1bWVudHMqKiBhcmUgdXNlZCB0byBsaW5rIG9iamVjdHMgYW5kIGZ1bmN0aW9ucyBhbmQgY29tbXVuaWNhdGUgd2hhdCB3ZSB3YW50IHRvIGRvLgoKIVtdKGltYWdlcy9kYXkyX1JTeW50YXgucG5nKQoKCiMjIyMgT2JqZWN0cwpBbiBvYmplY3QgaXMgYW55dGhpbmcgeW91IGNyZWF0ZSBhbmQgbmFtZSBpbiBSLiBJdCBjYW4gYmUgYSBudW1iZXIsIGEgZGF0YXNldCwgYSBmdW5jdGlvbiwgb3IgZXZlbiBhIHBsb3QuIE9iamVjdHMgdGFrZSBvbiBjb250ZW50IGZyb20gZXZlcnl0aGluZyB0byB0aGUgcmlnaHQgb2YgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IuCgpgYGB7cn0KeCA8LSA1ICN4IGlzIG5vdyBhbiBvYmplY3QgdGhhdCBob2xkcyB0aGUgdmFsdWUgNQpiIDwtICJBbm5hIiAjYiBpcyBub3cgYW4gb2JqZWN0IHRoYXQgaG9sZHMgdGhlIGNoYXJhY3RlciBBbm5hCmBgYAoqKk5vdGVzOioqIAoKIC0gU2luY2UgQW5uYSBpcyBhIGNoYXJhY3RlciwgaXQgbmVlZHMgdG8gYmUgd3JhcHBlZCBpbiBxdW90YXRpb25zIChlIHdpbGwgbGVhcm4gbW9yZSBhYm91dCBkYXRhIHR5cGVzIHRvbW9ycm93KS4KIAogLSBUaGUgc3ltYm9sIGAjYCBpcyB1c2VkIHdpdGhpbiBhIGNvZGUgY2h1bmsgdG8gaW5zZXJ0IGNvbW1lbnRzLiBDb21tZW50cyB3b24ndCBhZmZlY3QgaG93IHRoZSBjb2RlIHJ1bnMsIGJ1dCB0ZXh0IHRoYXQgaXMgbm90IHNpZ25hbGVkIGFzIGEgY29tbWVudCB3aWxsIGdlbmVyYXRlIGVycm9ycy4KCiMjIyMgRnVuY3Rpb25zCkZ1bmN0aW9ucyBhcmUgYSBzZXQgb2YgaW5zdHJ1Y3Rpb25zIHRoYXQgYWNjb21wbGlzaCBhIHRhc2suIFRoZXkgYXJlIG9mdGVuICh0aG91Z2ggbm90IGFsd2F5cykgaW5zdHJ1Y3Rpb25zIHRvIGJlIHBlcmZvcm1lZCBvbiBhbiBhcmd1bWVudC4gRnVuY3Rpb25zIGRvIHNvbWV0aGluZ+KAlGxpa2UgY2FsY3VsYXRlLCBzb3J0LCBvciBwbG90LiBZb3UgY2FsbCB0aGVtIGJ5IHRoZWlyIG5hbWUgYW5kIGFkZCBwYXJlbnRoZXNlcy4KCiMjIyMgQXJndW1lbnRzCkFyZ3VtZW50cyBhcmUgdGhlIGRldGFpbHMgeW91IGdpdmUgYSBmdW5jdGlvbiBzbyBpdCBrbm93cyB3aGF0IHRvIGRvLiBUaGV5IGdvIGluc2lkZSB0aGUgcGFyZW50aGVzZXMgb2YgYSBmdW5jdGlvbi4gTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIGZ1bmN0aW9uIGBtZWFuKClgCgo6OjpxdWVzdGlvbgpUeXBlIGBtZWFuYCBpbiB0aGUgSGVscCB0YWIgb2YgdGhlIGJvdHRvbSBsZWZ0IHBhbmVsLiBUaGUgcmVzdWx0cyB3aWxsIHByb3ZpZGUgYSBkZXNjcmlwdGlvbiBvZiB0aGUgZnVuY3Rpb24sIGluY2x1ZGluZyBpdHMgYXJndW1lbnRzLgo6OjoKCgoqKkFyZ3VtZW50KiogfCoqV2hhdCBpdCBtZWFucyoqIHwgKipEZWZhdWx0IFZhbHVlKioKfDotLS0tLS18Oi0tLS0tLXw6LS0tLS0tLXwKfCB4IHwgeCBpcyBhbiBSIG9iamVjdCB0aGF0IGNvbnRhaW5zIHRoZSBudW1iZXJzIHdlIHdhbnQgdG8gZmluZCB0aGUgbWVhbiBvZnxObyBkZWZhdWx0LCByZXF1aXJlZHwKfCB0cmltIHwgQSBudW1iZXIgYmV0d2VlbiAwIGFuZCAwLjUuIFJlbW92ZXMgYSBmcmFjdGlvbiBvZiBoaWdoZXN0IGFuZCBsb3dlc3QgdmFsdWVzIGJlZm9yZSBjb21wdXRpbmcgbWVhbiAodXNlZnVsIGlmIHlvdSB3YW50IGEgdHJpbW1lZCBtZWFuIHRoYXQgaWdub3JlcyBvdXRsaWVycykuIHwgMCBtZWFucyBubyB0cmltbWluZyB8CnwgbmEucm0gfCBJbmRpY2F0ZXMgd2hldGhlciBOQSB2YWx1ZXMgc2hvdWxkIGJlIGluY2x1ZGVkIG9yIG5vdCBpbiB0aGUgY2FsY3VsYXRpb258IFRSVUUgaWYgTkEgdmFsdWVzIHNob3VsZCBiZSByZW1vdmVkLCBGQUxTRSBpZiBub3QgfAoKCgojIyMjIEFzc2lnbm1lbnQgT3BlcmF0b3JzClRoaXMgaXMgaG93IHlvdSBzdG9yZSBhIHZhbHVlIGluIFIuIEl04oCZcyBsaWtlIHNheWluZzog4oCcTGV0IHRoaXMgbmFtZSBob2xkIHRoaXMgdmFsdWUu4oCdIEl0IGFzc2lnbnMgY29udGVudCBmcm9tIHRoZSBvYmplY3RzL2Z1bmN0aW9ucy9hcmd1bWVudHMgb24gaXRzIHJpZ2h0IHRvIHRoZSBvYmplY3Qgb24gaXRzIGxlZnQuCgpgYGB7cn0KbmFtZSA8LSAiTWFyaWEiICNOb3cgbmFtZSBob2xkcyB0aGUgc3RyaW5nICJNYXJpYSIuCmBgYAoKKipOb3RlOioqIFRoZSBhc3NpZ25tZW50IG9wZXJhdG9yIGA8LWAgaXMgYWxzbyBjb25zaWRlcmVkIGEgZnVuY3Rpb24uIEl0IGlzIGEgJ3N0b3JlJyBmdW5jdGlvbiB0aGF0IGFzc2lnbnMgaW5mb3JtYXRpb24gdG8gYW4gb2JqZWN0LiBUaGUgYXJyb3cgYDwtYCBpcyB0aGUgbW9zdCBjb21tb24sIGJ1dCBgPWAgY2FuIGFsc28gYmUgdXNlZCBpbiBzb21lIGNvbnRleHRzLgoKWW91IGNhbiBvdmVyd3JpdGUgYSBuZXcgdmFsdWUgdG8gdGhlIHNhbWUgb2JqZWN0IG5hbWUuIFdoZW4geW91IGFzc2lnbiBhZ2FpbiwgdGhlIHByZXZpb3VzIGNvbnRlbnQgaXMgcmVwbGFjZWQuCgpgYGB7cn0KbmFtZSA8LSAiQW5uYSIgI05vdyBuYW1lIHJlcGxhY2VzIHRoZSBwcmV2aW91cyBpbmZvcm1hdGlvbiBhbmQgaG9sZHMgdGhlIHN0cmluZyAiQW5uYSIuCmBgYAoKKipXaHkgT3ZlcndyaXRpbmcgaXMgVXNlZnVsKioKCiAtIEFzIHlvdXIgYW5hbHlzaXMgYmVjb21lcyBtb3JlIGNvbXBsaWNhdGVkLCB5b3Ugb2Z0ZW4gYnVpbGQgeW91ciByZXN1bHRzIHN0ZXAtYnktc3RlcC4KIAogLSBJbnN0ZWFkIG9mIGNyZWF0aW5nIGRvemVucyBvZiBkaWZmZXJlbnQgb2JqZWN0IG5hbWVzLCB5b3UgY2FuIHJldXNlIHRoZSBzYW1lIG9iamVjdCBuYW1lIHRvIHN0b3JlIHVwZGF0ZWQgdmVyc2lvbnMgb2YgeW91ciBkYXRhIG9yIHJlc3VsdHMuCiAKIC0gVGhpcyBrZWVwcyB5b3VyIGVudmlyb25tZW50IGNsZWFuIGFuZCB5b3VyIGNvZGUgZWFzaWVyIHRvIHJlYWQuCgoKIyMjIyBQaXBlcwpUaGlzIGlzIHVzZWQgdG8gY2hhaW4gc3RlcHMgdG9nZXRoZXIgaW4gYSByZWFkYWJsZSB3YXkuIEluc3RlYWQgb2YgbmVzdGluZyBmdW5jdGlvbnMsIHlvdSBtb3ZlIHN0ZXAtYnktc3RlcCBsaWtlIGEgcmVjaXBlLgoKYGBge3J9Cm15bnVtYmVycyA8LSAoYygxLDIsMykpICNzdG9yaW5nIHRoZSBudW1iZXJzIDEsIDIgYW5kIDMgaW4gdGhlIG9iamVjdCBjYWxsZWQgIm15bnVtYmVycyIKbXludW1iZXJzIHw+IG1lYW4oKSAjdGFrZSB0aGUgb2JqZWN0IG15bnVtYmVycyBhbmQgcGlwZSBpdCBpbnRvIHRoZSBtZWFuIGZ1bmN0aW9uCmBgYAoqKk5vdGU6KiogSW4gUiwgYGMoKWAgc3RhbmRzIGZvciDigJxjb21iaW5l4oCdIG9yIOKAnGNvbmNhdGVuYXRl4oCdLiBUaGUgcm9sZSBvZiBgYygpYCBpcyB0byBjb21iaW5lIHRoZSB2YWx1ZXMgaW5zaWRlIGl0IGludG8gYSB2ZWN0b3Ig4oCUIGEgYmFzaWMgZGF0YSBzdHJ1Y3R1cmUgaW4gUi4gSXQgdGFrZXMgdGhlIGluZGl2aWR1YWwgbnVtYmVycyAxLCAyLCBhbmQgMyBhbmQgY3JlYXRlcyBhIHNpbmdsZSB2ZWN0b3I6IDEgMiAzLiBZb3UgY2FuIHRoaW5rIG9mIGBjKClgIGFzIOKAnGdsdWluZ+KAnSBlbGVtZW50cyB0b2dldGhlciBpbnRvIG9uZSBncm91cC4gWW91IHdpbGwgbGVhcm4gbW9yZSBhYm91dCBkYXRhIHR5cGVzIGFuZCBzdHJ1Y3R1cmVzIHRvbW9ycm93LgoKIyMgUGFja2FnZXMgYW5kIExpYnJhcmllcwoKQ29sbGVjdGlvbnMgb2YgUiBmdW5jdGlvbnMgYXJlIHN0b3JlZCBpbiBQYWNrYWdlcy4gSW4gb3JkZXIgdG8gdXNlIGEgc3BlY2lmaWMgZnVuY3Rpb24gd2UgbmVlZCB0byBpbnN0YWxsIHRoZSBwYWNrYWdlIHRoYXQgY29udGFpbnMgdGhhdCBmdW5jdGlvbi4KCiMjIyBUaWR5dmVyc2UKCldoZW4gd2UgdGFsayBhYm91dCAiQmFzZSBSIiB3ZSByZWZlciB0byB0aGUgb3JpZ2luYWwgZnVuY3Rpb25zIGFuZCBzeW50YXggaW5jbHVkZWQgd2l0aCBS4oCUbm8gZXh0cmEgcGFja2FnZXMgbmVlZGVkLiBCYXNlIFIgY29udGFpbnMgbWFueSBmdW5jdGlvbnMgbGlrZSBgcmVhZC5jc3YoKWAsIGBtZWFuKClgLCBgc3Vic2V0KClgLCBhbmQgYHBsb3QoKWAuIEl0IGNhbiBiZSB2ZXJ5IHBvd2VyZnVsIGFuZCBmbGV4aWJsZSBidXQgc29tZXRpbWVzIGl0IGlzIGxlc3MgaW50dWl0aXZlIGZvciBiZWdpbm5lcnMuCgpXZSB3aWxsIGluc3RhbGwgKipUaWR5dmVyc2UqKiwgd2hpY2ggaXMgYSBjb2xsZWN0aW9uIG9mIHBhY2thZ2VzIGRlc2lnbmVkIHRvIG1ha2UgZGF0YSBhbmFseXNpcyBlYXNpZXIgYW5kIG1vcmUgY29uc2lzdGVudC4KClRoaW5rIG9mIHRoZSB0aWR5dmVyc2UgYXMgYSB0b29sYm94IHRoYXQgZ2l2ZXMgeW91IHNpbXBsZSBhbmQgcmVhZGFibGUgZnVuY3Rpb25zIGZvciB0aGUgbW9zdCBjb21tb24gc3RlcHMgaW4gd29ya2luZyB3aXRoIGRhdGE6CgogLSBJbXBvcnRpbmcgZGF0YSAoZS5nLiwgcmVhZHIsIHJlYWR4bCkKIC0gQ2xlYW5pbmcgYW5kIHRyYW5zZm9ybWluZyBkYXRhIChlLmcuLCBkcGx5ciwgdGlkeXIpCiAtIFZpc3VhbGl6aW5nIGRhdGEgKGUuZy4sIGdncGxvdDIpCiAtIFdvcmtpbmcgd2l0aCBzdHJpbmdzIChlLmcuLCBzdHJpbmdyKSBvciBkYXRlcyAoZS5nLiwgbHVicmlkYXRlKQoKQWxsIHRoZXNlIHBhY2thZ2VzIGZvbGxvdyB0aGUgc2FtZSBsb2dpYyBhbmQgc3ludGF4LCBzbyBvbmNlIHlvdSBsZWFybiBvbmUsIHRoZSBvdGhlcnMgZmVlbCBmYW1pbGlhciB0b28uCkZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uLCB2aXNpdCB0aGUgPGEgaHJlZj0iaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8iPnRpZHl2ZXJzZSBpbmZvIHBhZ2U8L2E+CgpXZSB3aWxsIGJlIHVzaW5nIHBhY2thZ2VzIGZyb20gVGlkeXZlcnNlIGxhdGVyIHRvZGF5IGFuZCB0b21vcnJvdy4uLgoKIyMjIEluc3RhbGwgUGFja2FnZQpUbyBpbnN0YWxsIGEgcGFja2FnZSB3ZSB1c2UgdGhlIGZ1bmN0aW9uIGBpbnN0YWxsLnBhY2thZ2VzKClgLiAKCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKYGBgCgojIyMgTG9hZCBMaWJyYXJpZXMKUGFja2FnZXMgYXJlIHN0b3JlZCBpbiBsaWJyYXJpZXMuIE9uY2UgYSBwYWNrYWdlIGlzIGluc3RhbGxlZCwgd2UgbmVlZCB0byBjYWxsIHRoZSBsaWJyYXJ5IHdpdGggdGhlIGZ1bmN0aW9uIGBsaWJyYXJ5KClgLgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCjo6OmZsYWcKTm90ZSB0aGF0IHRoZSBwYWNrYWdlIG5hbWUgbmVlZHMgdG8gYmUgaW4gcXVvdGF0aW9ucyB3aGVuIGluc3RhbGxpbmcgdGhlIHBhY2thZ2UsIGJ1dCBub3Qgd2hlbiBsb2FkaW5nIHRoZSBsaWJyYXJ5LgoKUGFja2FnZXMgb25seSBuZWVkIHRvIGJlIGluc3RhbGxlZCBvbmNlLgoKTGlicmFyaWVzIG5lZWQgdG8gYmUgbG9hZGVkIGluIGVhY2ggd29yayBzZXNzaW9uLgo6OjoKCgpSZW1lbWJlciB0aGUgVGlkeXZlcnNlIERhdGEgU2NpZW5jZSBXb3JrZmxvdz8gVG9kYXkgd2Ugd2lsbCBiZSBmb2N1c2luZyBvbiB0aGUgZmlyc3QgdHdvIHN0ZXBzOgoKIVtdKGltYWdlcy9kYXkyX3dvcmtmbG93LnBuZykKPGEgaHJlZj0iaHR0cHM6Ly90ZWxhcHBzLmxvbmRvbi5lZHUvYW5hbHl0aWNzX3dpdGhfUi90aWR5dmVyc2UuaHRtbCI+U291cmNlPC9hPgoKIyMgUmVhZCBEYXRhCgojIyMgUmVhZCBhIGNzdiBmaWxlClRvIGltcG9ydCBhIGNzdiBmaWxlIHdlIGNhbiB1c2UgdGhlIGByZWFkX2NzdigpYCBmdW5jdGlvbiBhbmQgYXNzaWduIGl0IHRvIGEgbmV3IG9iamVjdCB3ZSB3aWxsIGNhbGwgKmpzX2RhdGEqLiBXZSBjcmVhdGUgYSBuZXcgb2JqZWN0IHRvIGJlIGFibGUgdG8gY2FsbCBpdCBpbiBkaWZmZXJlbnQgZnVuY3Rpb25zIGxhdGVyIG9uLgpgYGB7cn0KanNfZGF0YSA8LSByZWFkX2NzdigiZGF0YS90aW1ldXNlX2RheTFfbmEuY3N2IikKYGBgCgojIyMgUmVhZCBPdGhlciBGb3JtYXRzCkluIHRoZSBleGFtcGxlIHdlIGFyZSB3b3JraW5nIHdpdGggdGhlIGRhdGEgaXMgc3RvcmVkIGluIGEgY3N2IGZpbGUuIFRoZSBwYWNrYWdlICoqcmVhZHIqKiBmcm9tIFRpZHl2ZXJzZSBjYW4gYWxzbyByZWFkIG90aGVyIGZvcm1hdHMgbGlrZSBgcmVhZF90c3YoKWAodGFiLXNlcGFyYXRlZCB2YWx1ZXMpLCBgcmVhZF9kZWxpbSgpYChkZWxpbWl0ZWQgZmlsZXMgQ1NWIGFuZCBUU1YpLCBgcmVhZF90YWJsZSgpYCh3aGl0ZXNwYWNlLXNlcGFyYXRlZCBmaWxlcyksIGByZWFkX2xvZygpYCh3ZWIgbG9nIGZpbGVzKS4KClRoZXJlIGFyZSBvdGhlciBmdW5jdGlvbnMgYW5kIHBhY2thZ2VzIHRoYXQgYWxsb3cgdXMgdG8gaW1wb3J0IGRpZmZlcmVudCBmaWxlIHR5cGVzLiAKCioqRmlsZSBUeXBlKiogfCoqRnVuY3Rpb24qKiB8ICoqUGFja2FnZSoqCnw6LS0tLS0tfDotLS0tLS18Oi0tLS0tLS18CnwuY3N2IHwgYHJlYWRfY3N2KClgfCByZWFkciB8CnwgLnhsc3ggfCBgcmVhZC54bHN4KClgfCB4bHN4IHwKfCAuc2F2IHwgYHJlYWRfc2F2KClgfCBoYXZlbiB8CnwgLnNhczdiZGF0ICwgLnNhczdiY2F0IHwgYHJlYWRfc2FzKClgfCBoYXZlbiB8CnwgLmR0YSB8IGByZWFkX2R0YSgpYHwgaGF2ZW4gfAoKIyMgTGlzdGluZyBDb2x1bW4gTmFtZXMKVG8gYXNrIGZvciBhIGxpc3Qgb2YgYWxsIHRoZSBjb2x1bW4gbmFtZXMgaW4gb3VyIGRhdGFzZXQgd2UgY2FuIHVzZSB0aGUgYG5hbWVzKClgIGZ1bmN0aW9uLgpgYGB7cn0KbmFtZXMoanNfZGF0YSkKYGBgCgpOb3RpY2UgdGhhdCB0aGUgY29sdW1uIG5hbWVzIGZyb20gdGhlIG9yaWdpbmFsIGRhdGFzZXQgZG9uJ3QgcHJvdmlkZSBhIGNsZWFyIGRlc2NyaXB0aW9uIG9mIHdoYXQgdGhlIHZhcmlhYmxlIGlzLiBXZSB3aWxsIGNoYW5nZSB0aGUgY29sdW1uIG5hbWVzIGxhdGVyIHRvIGZhY2lsaXRhdGUgd29ya2luZyB3aXRoIG91ciBkYXRhIGluIHRoZSBmdXR1cmUuCgojIyBIZWFkIEZ1bmN0aW9uClRoZSBoZWFkIGZ1bmN0aW9uIHdpbGwgZGlzcGxheSB0aGUgdG9wIHJvd3Mgb2YgdGhlIGRhdGFzZXQuIEl0IHdpbGwgaW5jbHVkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGVmYXVsdCBkYXRhIHR5cGUgYXNzaWduZWQgdG8gZWFjaCBjb2x1bW4uIFlvdSB3aWxsIGxlYXJuIG1vcmUgYWJvdXQgZGF0YSB0eXBlcyB0b21vcnJvdy4KCmBgYHtyLCBkYXRhLWlzb2xhdGlvbiwgcmVzdWx0cyA9IEZBTFNFfQpoZWFkKGpzX2RhdGEpCmBgYAoKYGBge3IsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGthYmxlRXh0cmEpCmhlYWQoanNfZGF0YSl8PgogIGtibCgpIHw+CiAgI2thYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIpCmthYmxlX3BhcGVyKCkgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICI1MDBweCIsIGhlaWdodCA9ICIyMDBweCIpCgpgYGAKCiMjIFZpZXdpbmcgRGF0YQpUbyB2aXN1YWxpemUgdGhlIGZ1bGwgZGF0YXNldCB3ZSB1c2UgdGhlIGBWaWV3KClgIGZ1bmN0aW9uLiBUaGlzIHdpbGwgb3BlbiBvdXIgZGF0YXNldCBpbiBhIHNlcGFyYXRlIHdpbmRvdy4KYGBge3IsIGV2YWw9RkFMU0V9ClZpZXcoanNfZGF0YSkKYGBgCgoKIyMgQ2hhbmdlIENvbHVtbiBOYW1lcwpXZSBtZW50aW9uZWQgZWFybGllciB0aGF0IHdlIHdhbnRlZCB0byB3b3JrIHdpdGggY29sdW1uIG5hbWVzIHRoYXQgd2VyZSBtb3JlIGRlc2NyaXB0aXZlIG9mIHRoZSBjb250ZW50IG9mIGVhY2ggdmFyaWFibGUuIFRvIGNoYW5nZSBjb2x1bW4gbmFtZXMgd2UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gYHJlbmFtZSgpYC4KClRoZSBmdW5jdGlvbiBgcmVuYW1lKClgIGlzIHBhcnQgb2Ygb25lIG9mIHRoZSBwYWNrYWdlcyB0aGF0IHdhcyBpbnN0YWxsZWQgd2l0aCB0aWR5dmVyc2UuCgo6Ojp3YWxrdGhyb3VnaApUeXBlIHRoZSBmb2xsb3dpbmcgY29kZSB0byBjaGFuZ2UgdGhlIGNvbHVtbiBuYW1lIGZyb20gIlBVTUZJRCIgdG8gImlkIgpgYGB7cn0KanNfZGF0YSA8LSBqc19kYXRhIHw+CiAgcmVuYW1lICgiaWQiID0gIlBVTUZJRCIpCmBgYApEaWQgaXQgd29yaz8KOjo6CgojIyBZb3VyIFR1cm4hCgo6OjpxdWVzdGlvbgpOb3csIHRvIGNoYW5nZSB0aGUgcmVzdCBvZiB0aGUgY29sdW1uIG5hbWVzIGNvcHkgdGhlIGZvbGxvd2luZyBjb2RlLiAoY2xpY2sgc2hvdyB0byBzZWUgdGhlIGNvZGUpCgpgYGB7ciwgY2xhc3Muc291cmNlID0gJ2ZvbGQtaGlkZSd9CmpzX2RhdGEgPC0ganNfZGF0YSB8PgogIHJlbmFtZSAoImFnZUdycCIgPSAiQUdFR1IxMCIsCiAgICAgICAgICAic2V4IiA9ICJTRVgiLAogICAgICAgICAgIm1hcml0YWxTdGF0IiA9ICJNQVJTVEFUIiwKICAgICAgICAgICJwcm92aW5jZSIgPSAgIlBSViIsCiAgICAgICAgICAicG9wQ2VudGVyIiA9ICJMVUNfUlNUIiwKICAgICAgICAgICJlZHVMZXZlbCIgPSAiRUhHX0FMTCIsCiAgICAgICAgICAiZmVlbFJ1c2hlZCIgPSAiR1RVXzExMCIsCiAgICAgICAgICAiZXh0cmFUaW1lIiA9ICJHVFVfMTMwIiwKICAgICAgICAgICJkdXJTbGVlcCIgPSAiRFVSMDEiLAogICAgICAgICAgImR1ck1lYWxQcmVwIiA9ICJEVVIwNSIsCiAgICAgICAgICAiZHVyRWF0aW5nIiA9ICJEVVIwNiIsCiAgICAgICAgICAiZHVyQWxvbmUiID0gIkRVUlMyMDAiLAogICAgICAgICAgImR1ckRyaXZpbmciID0gIkRVUkwzMTMiLAogICAgICAgICAgImR1cldvcmsiID0gIkRVUjA4IiwKICAgICAgICAgICJkdXJTaG9vbFNpdGUiID0gIkRVUjEzIiwKICAgICAgICAgICJkdXJTY2hvb2xPbmxpbmUiID0gIkRVUjE0IiwKICAgICAgICAgICJkdXJTdHVkeSIgPSAiRFVSMTUiLAogICAgICAgICAgIm1haW5TdHVkeSIgPSAiTVJXXzIwIiwKICAgICAgICAgICJtYWluSm9iSHVudGluZyIgPSAiTVJXXzMwIiwKICAgICAgICAgICJtYWluV29yayIgPSAiTVJXXzQwIiwKICAgICAgICAgICJ3b3JrZWQxMm0iID0gIk1SV19ENDBBIiwKICAgICAgICAgICJ3b3JrZWRXZWVrIiA9ICJNUldfRDQwQiIsCiAgICAgICAgICAiZW5yb2xsU3RhdCIgPSAiRURNXzAyIiwKICAgICAgICAgICJkYWlseVRleHRzIiA9ICJUU1RfMDEiLAogICAgICAgICAgInRpbWVTbG93RG93biIgPSAiVENTXzExMCIsCiAgICAgICAgICAidGltZVdvcmthaG9saWMiID0gIlRDU18xMjAiLAogICAgICAgICAgInRpbWVOb3RGYW1GcmllbmRzIiA9ICJUQ1NfMTUwIiwKICAgICAgICAgICJ0aW1lV2FudEFsb25lIiA9ICJUQ1NfMjAwIikKYGBgCgo6OjoKCjo6OnF1ZXN0aW9uClVzZSB0aGUgZnVuY3Rpb25gbmFtZXMoZGF0YSlgIHRvIGRpc3BsYXkgdGhlIGNvbHVtbiBuYW1lcy4KYGBge3J9Cm5hbWVzKGpzX2RhdGEpCmBgYAo6OjoKCgojIyBTYXZlIHlvdXIgd29yawpTYXZpbmcgaW4gUiBmb3JtYXQgKFJEYXRhKSB3aWxsIHByZXNlcnZlIGRhdGEgdHlwZXMgYW5kIG1ldGFkYXRhIGFzc2lnbmVkIHRvIHRoZSBkYXRhc2V0LiAKVGhlIHRleHQgZm9ybWF0IChjc3YpIHdpbGwgYmUgdGhlIGlkZWFsIGZvcm1hdCB0byBzaGFyZSB0aGUgZGF0YS4KCmBgYHtyfQpzYXZlKGpzX2RhdGEsIGZpbGU9ImRhdGEvdGltZXVzZV9kYXkyLlJEYXRhIikKYGBgCgpgYGB7cn0Kd3JpdGVfY3N2KGpzX2RhdGEsIGZpbGU9ImRhdGEvdGltZXVzZV9kYXkyLmNzdiIpCmBgYAoKIyMgVXBsb2FkIHRvIE9TRgoKQXQgdGhlIGVuZCBvZiBlYWNoIHdvcmsgc2Vzc2lvbiwgcmVtZW1iZXIgdG8gc2F2ZSB5b3VyIGRhdGEgYXMgLlJEYXRhIGFuZCAuY3N2LCBhbmQgYWxzbyB5b3VyIFJNYXJrZG93biBmaWxlICguUm1kKS4gV2Ugd2lsbCB1cGxvYWQgdGhvc2UgZmlsZXMgdG8gT1NGLgoKIVtdKGltYWdlcy9vc2Yvb3NmVXBsb2FkLmdpZikKCgoK