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.

Argument What it means Default Value
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")

Read Other Formats

In the example we are working with the data is stored in a csv file. The package readr from Tidyverse can also read other formats like read_tsv()(tab-separated values), read_delim()(delimited files CSV and TSV), read_table()(whitespace-separated files), read_log()(web log files).

There are other functions and packages that allow us to import different file types.

File Type Function Package
.csv read_csv() readr
.xlsx read.xlsx() xlsx
.sav read_sav() haven
.sas7bdat , .sas7bcat read_sas() haven
.dta read_dta() haven

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