1 Introduction

As a Social Psychologist first trained in SPSS, I am used to collecting and organizing my data in wide format. When data in is wide format, a subject’s responses will be in a single row, and each response is in separate columns. However R prefers long format. We could melt and cast with reshape2 to reshape from wide to long format, but is there a way to reshape using even less code? Luckily for us, Hadley Wickham has created the easy to use tidyr!

tidyr allow us to quickly and easily tidy and reorganize our data for all sorts of analyses. This is particularly helpful with a disorganized dataset. tidyr is built for this function, and thus does less than reshape2. Specifically, tidyr can only be used with exisiting dataframes, and cannot aggregate.

In this chapter, I will go over the hallmark functions of tidyr: gather(), separate(), unite(), and spread().

First let’s install and call up the tidyr package. We will also need to use the dplyr package.

#install.packages("tidyr") # I have used "#" to "comment out" this line for this tutorial. Just take away the first "#" and you are good to go!
#install.packages("dplyr")

library(tidyr)
library(dplyr)

1.1 %>%

Why do we need dplyr? dplyr is a grammar of data manipulation. We need dplyr to use the pipe operator, %>%, in our code. %>% is not required to use tidyr, but it does make things easier!

%>% allows you to pipe a value forward into an expression or to function call; such that x %>% f, instead of f(x). This short hand was created by Stefan Milton Bache with the magrittr package. To read more about this function, click here

1.2 The Dataframe

Here I have created a messy wide dataset. Feel free to use it to follow along!

In this example study, participants were asked to categorize three faces by clicking various buttons that represent three different categories. The time it took to click a button is in milliseconds.

n=10
wide <- data.frame(
  ID = c(1:n),
  Face.1 = c(411,723,325,456,579,612,709,513,527,379),
  Face.2 = c(123,300,400,500,600,654,789,906,413,567),
  Face.3 = c(1457,1000,569,896,956,2345,780,599,1023,678)
)

This dataset I created is messy; As you can see below, only ID is in a column, Response time split between three columns, such that responses are in both rows and columns (by ID and Face.1, Face.2, and Face.3).

What we want instead is one column for the condition (Face.1, Face.2, or Face.3) responses and a column for response time, with each row being a singualar observation for each participant. Participant IDs should repeat as this is a within subject design (each participant saw each face).

##    ID Face.1 Face.2 Face.3
## 1   1    411    123   1457
## 2   2    723    300   1000
## 3   3    325    400    569
## 4   4    456    500    896
## 5   5    579    600    956
## 6   6    612    654   2345
## 7   7    709    789    780
## 8   8    513    906    599
## 9   9    527    413   1023
## 10 10    379    567    678

2 Gather()

By using the gather() function, we can transform the data from wide to long Here is the generic code for gather():

#gather(data, key, value, ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)

2.1 Gather() Arguments

Whoa! What does this all mean? Let’s find out more about the arguments of gather():

  • data: Your data frame.

  • key, value: The unquoted new names of key and value columns to create in the output. The key will become the name of the condition/IV column, and value will become the name of the response/DV column.

  • ...: The columns to gather. Use the exisiting variable names. Select a range of variables with : (e.g. if you have variables a, b, c, and d, and want to select all of these varibeles you will indicate this with a:d). If you want to exclude a variable, use - (e.g. exclude y with -y).

  • na.rm: If you indicate that na.rm=TRUE, this will remove rows from the output where the value is missing.

  • convert: If TRUE this will automatically convert the key column to a logical, integer, numeric, complex, or factor as appropriate. This is useful if the column names are actually numeric, integer, or logical.

  • factor_key: If FALSE, the default, the key values will be stored as a character vector. If TRUE, will be stored as a factor, which preserves the original ordering of the columns.

2.2 Using Gather()

Now that we have a better understanding of the arguements, lets make our data set long using gather()!

long <- wide %>% gather(Face, ResponseTime, Face.1:Face.3)
##    ID   Face ResponseTime
## 1   1 Face.1          411
## 2   2 Face.1          723
## 3   3 Face.1          325
## 4   4 Face.1          456
## 5   5 Face.1          579
## 6   6 Face.1          612
## 7   7 Face.1          709
## 8   8 Face.1          513
## 9   9 Face.1          527
## 10 10 Face.1          379
## 11  1 Face.2          123
## 12  2 Face.2          300
## 13  3 Face.2          400
## 14  4 Face.2          500
## 15  5 Face.2          600
## 16  6 Face.2          654
## 17  7 Face.2          789
## 18  8 Face.2          906
## 19  9 Face.2          413
## 20 10 Face.2          567
## 21  1 Face.3         1457
## 22  2 Face.3         1000
## 23  3 Face.3          569
## 24  4 Face.3          896
## 25  5 Face.3          956
## 26  6 Face.3         2345
## 27  7 Face.3          780
## 28  8 Face.3          599
## 29  9 Face.3         1023
## 30 10 Face.3          678

As you can see, now we have two columns: One for the the Faces, and one for response time. Each participant saw each face, so ID repeats three times.

3 Separate()

Although the long dataset we created using gather() is acceptable for use, we can break down the face variable even further using separate().

Here is the generic code for separate():

#separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE, convert = FALSE, extra = "warn", fill = "warn")

3.1 Separate() Arguments

What are the arugments unique to separate()?

  • col: Unquoted name of the column to be separated.

  • into: Names for the new variables that you are separating out from the column.

  • sep: Separator between columns. If the seprator is a character, it is interpreted as a regular expression. The default value is a regular expression that matches any sequence of non-alphanumeric values. In the example, each face is indicated by a number that follows a period (.). I do not need speifcy this because this exists in each level of Face. If numeric, it is interpreted as the position to split at. Positive values start at 1 at the far-left of the string; negative value start at -1 at the far-right of the string. The length of sep should be one less than into.

  • remove: If this is TRUE, it removes the input column from output data frame.

  • extra: If sep is a character vector (like .), this controls what happens when there are too many pieces (e.g. Face.1.A, rather than Face.1). There are three valid options: “warn” (the default): emit a warning and drop extra values. “drop”: drop any extra values without a warning. “merge”: only splits at most length(into) times

  • fill: If sep is a character vector (like .), this controls what happens when there are not enough pieces (e.g. Face1, rather than Face.1). There are three valid options: “warn” (the default): emit a warning and fill from the right “right”: fill with missing values on the right “left”: fill with missing values on the left

3.2 Using Separate()

Each face is indicated by number after a period. This variable annotation allows us to separate the face variable into two. By using the separate function of tidyr we can tease apart single variables which sometimes capture multiple variables (or sometimes redundant information).

In this case, I want to split the Face from the number attached to it, which in this example represents the race of the face.

long_separate <- long %>% separate(Face, c("Target", "Number"))
##    ID Target Number ResponseTime
## 1   1   Face      1          411
## 2   2   Face      1          723
## 3   3   Face      1          325
## 4   4   Face      1          456
## 5   5   Face      1          579
## 6   6   Face      1          612
## 7   7   Face      1          709
## 8   8   Face      1          513
## 9   9   Face      1          527
## 10 10   Face      1          379
## 11  1   Face      2          123
## 12  2   Face      2          300
## 13  3   Face      2          400
## 14  4   Face      2          500
## 15  5   Face      2          600
## 16  6   Face      2          654
## 17  7   Face      2          789
## 18  8   Face      2          906
## 19  9   Face      2          413
## 20 10   Face      2          567
## 21  1   Face      3         1457
## 22  2   Face      3         1000
## 23  3   Face      3          569
## 24  4   Face      3          896
## 25  5   Face      3          956
## 26  6   Face      3         2345
## 27  7   Face      3          780
## 28  8   Face      3          599
## 29  9   Face      3         1023
## 30 10   Face      3          678

Now, We have two columns, one for Target, the values of which are all “Face”, and one for Number, which indicates which of the three faces it is.

4 Unite

To undo separate(), we can use unite(), which merges two variables into one.

Here is the generic code for unite():

#unite(data, col, ..., sep = ".", remove = TRUE)

4.1 Unite() Arguments

Here are the arugments unique to unite():

  • sep: In the code for unite() the sep indicated the separator we choose to to use to bind values. In this case, we are using .

4.2 Using Unite()

long_unite <- long_separate %>% unite(Face, Target, Number, sep = ".")
##    ID   Face ResponseTime
## 1   1 Face.1          411
## 2   2 Face.1          723
## 3   3 Face.1          325
## 4   4 Face.1          456
## 5   5 Face.1          579
## 6   6 Face.1          612
## 7   7 Face.1          709
## 8   8 Face.1          513
## 9   9 Face.1          527
## 10 10 Face.1          379
## 11  1 Face.2          123
## 12  2 Face.2          300
## 13  3 Face.2          400
## 14  4 Face.2          500
## 15  5 Face.2          600
## 16  6 Face.2          654
## 17  7 Face.2          789
## 18  8 Face.2          906
## 19  9 Face.2          413
## 20 10 Face.2          567
## 21  1 Face.3         1457
## 22  2 Face.3         1000
## 23  3 Face.3          569
## 24  4 Face.3          896
## 25  5 Face.3          956
## 26  6 Face.3         2345
## 27  7 Face.3          780
## 28  8 Face.3          599
## 29  9 Face.3         1023
## 30 10 Face.3          678

As you can see the data now looks like it did when we first transfromed from wide to long using gather()!

5 Spread

Finally, we will transform the data from long back to wide with the spread() function.

Here is the generic code for spread()

#spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)

5.1 Spread() Arguments

The arugments unique to spread():

  • key: The unquoted name of the column whose values will be used as column headings.

  • value: The unquoted name of the column whose values will populate the cells.

  • fill: If used, missing values will be replaced with this value. There are two types of missing in the input: explicit missing values (i.e. NA), and implicit missings, rows that simply aren’t present. Both types of missing value will be replaced by fill.

  • convert: If TRUE, this will automatically convert the new columns to a logical, integer, numeric, complex, or factor as appropriate.

  • drop: If FALSE, will keep factor levels that don’t appear in the data, filling in missing combinations with fill.

  • sep: If NULL, the column names will be taken from the values of key variable. If non-NULL, the column names will be created by stringing together the name, separator, and value.

back_to_wide <- long_unite %>% spread(Face, ResponseTime)
##    ID Face.1 Face.2 Face.3
## 1   1    411    123   1457
## 2   2    723    300   1000
## 3   3    325    400    569
## 4   4    456    500    896
## 5   5    579    600    956
## 6   6    612    654   2345
## 7   7    709    789    780
## 8   8    513    906    599
## 9   9    527    413   1023
## 10 10    379    567    678

And there we have it! We have come full circle back into wide.

6 References

https://priceonomics.com/hadley-wickham-the-man-who-revolutionized-r/ # Who is this Hadley Wickham guy?

https://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html # Further reading about %>%

https://blog.rstudio.org/2014/07/22/introducing-tidyr/ # Helpful overview of tidyr

http://ademos.people.uic.edu/Chapter8.html # Tim Carsel’s chapter on reshape2

https://cran.r-project.org/web/packages/tidyr/tidyr.pdf # A full guide of tidy r and all the arguments for each function of the package

http://garrettgman.github.io/tidying/ # Different types of messy data and how to fix with tidyr

LS0tDQp0aXRsZTogIkNoYXB0ZXIgOTogUmVzaGFwaW5nIERhdGEgVXNpbmcgVGlkeXIiDQphdXRob3I6ICJPbGl2aWEgTC4gSG9sbWVzIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUNCiAgICBmb250c2l6ZTogOHB0DQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KI0ludHJvZHVjdGlvbg0KDQpBcyBhIFNvY2lhbCBQc3ljaG9sb2dpc3QgZmlyc3QgdHJhaW5lZCBpbiBTUFNTLCBJIGFtIHVzZWQgdG8gY29sbGVjdGluZyBhbmQgb3JnYW5pemluZyBteSBkYXRhIGluIHdpZGUgZm9ybWF0LiBXaGVuIGRhdGEgaW4gaXMgd2lkZSBmb3JtYXQsIGEgc3ViamVjdOKAmXMgcmVzcG9uc2VzIHdpbGwgYmUgaW4gYSBzaW5nbGUgcm93LCBhbmQgZWFjaCByZXNwb25zZSBpcyBpbiBzZXBhcmF0ZSBjb2x1bW5zLiBIb3dldmVyIFIgcHJlZmVycyBsb25nIGZvcm1hdC4gV2UgY291bGQgYG1lbHRgIGFuZCBgY2FzdGAgd2l0aCBgcmVzaGFwZTJgIHRvIHJlc2hhcGUgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0LCBidXQgaXMgdGhlcmUgYSB3YXkgdG8gcmVzaGFwZSB1c2luZyBldmVuIGxlc3MgY29kZT8gTHVja2lseSBmb3IgdXMsIFtIYWRsZXkgV2lja2hhbV0oaHR0cHM6Ly9wcmljZW9ub21pY3MuY29tL2hhZGxleS13aWNraGFtLXRoZS1tYW4td2hvLXJldm9sdXRpb25pemVkLXIvKSBoYXMgY3JlYXRlZCB0aGUgZWFzeSB0byB1c2UgYHRpZHlyYCEgDQoNCmB0aWR5cmAgYWxsb3cgdXMgdG8gcXVpY2tseSBhbmQgZWFzaWx5IHRpZHkgYW5kIHJlb3JnYW5pemUgb3VyIGRhdGEgZm9yIGFsbCBzb3J0cyBvZiBhbmFseXNlcy4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgaGVscGZ1bCB3aXRoIGEgZGlzb3JnYW5pemVkIGRhdGFzZXQuIGB0aWR5cmAgaXMgYnVpbHQgZm9yIHRoaXMgZnVuY3Rpb24sIGFuZCB0aHVzIGRvZXMgbGVzcyB0aGFuIFtyZXNoYXBlMl0oaHR0cDovL2FkZW1vcy5wZW9wbGUudWljLmVkdS9DaGFwdGVyOC5odG1sKS4gU3BlY2lmaWNhbGx5LCBgdGlkeXJgIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCBleGlzaXRpbmcgZGF0YWZyYW1lcywgYW5kIGNhbm5vdCBhZ2dyZWdhdGUuDQoNCkluIHRoaXMgY2hhcHRlciwgSSB3aWxsIGdvIG92ZXIgdGhlIGhhbGxtYXJrIGZ1bmN0aW9ucyBvZiBgdGlkeXJgOiBgZ2F0aGVyKClgLCBgc2VwYXJhdGUoKWAsIGB1bml0ZSgpYCwgYW5kIGBzcHJlYWQoKWAuIA0KDQpGaXJzdCBsZXQncyBpbnN0YWxsIGFuZCBjYWxsIHVwIHRoZSBgdGlkeXJgIHBhY2thZ2UuIFdlIHdpbGwgYWxzbyBuZWVkIHRvIHVzZSB0aGUgYGRwbHlyYCBwYWNrYWdlLiANCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQojaW5zdGFsbC5wYWNrYWdlcygidGlkeXIiKSAjIEkgaGF2ZSB1c2VkICIjIiB0byAiY29tbWVudCBvdXQiIHRoaXMgbGluZSBmb3IgdGhpcyB0dXRvcmlhbC4gSnVzdCB0YWtlIGF3YXkgdGhlIGZpcnN0ICIjIiBhbmQgeW91IGFyZSBnb29kIHRvIGdvIQ0KI2luc3RhbGwucGFja2FnZXMoImRwbHlyIikNCg0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZHBseXIpDQpgYGANCg0KIyMlPiUNCldoeSBkbyB3ZSBuZWVkIGBkcGx5cmA/IGBkcGx5cmAgaXMgYSBncmFtbWFyIG9mIGRhdGEgbWFuaXB1bGF0aW9uLiBXZSBuZWVkIGBkcGx5cmAgdG8gdXNlIHRoZSBwaXBlIG9wZXJhdG9yLCBgJT4lYCwgaW4gb3VyIGNvZGUuIGAlPiVgIGlzIG5vdCByZXF1aXJlZCB0byB1c2UgdGlkeXIsIGJ1dCBpdCBkb2VzIG1ha2UgdGhpbmdzIGVhc2llciENCg0KYCU+JWAgYWxsb3dzIHlvdSB0byBwaXBlIGEgdmFsdWUgZm9yd2FyZCBpbnRvIGFuIGV4cHJlc3Npb24gb3IgdG8gZnVuY3Rpb24gY2FsbDsgc3VjaCB0aGF0IGB4ICU+JSBmYCwgaW5zdGVhZCBvZiBgZih4KWAuIFRoaXMgc2hvcnQgaGFuZCB3YXMgY3JlYXRlZCBieSBTdGVmYW4gTWlsdG9uIEJhY2hlIHdpdGggdGhlIGBtYWdyaXR0cmAgcGFja2FnZS4gVG8gcmVhZCBtb3JlIGFib3V0IHRoaXMgZnVuY3Rpb24sIGNsaWNrIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFncml0dHIvdmlnbmV0dGVzL21hZ3JpdHRyLmh0bWwpDQoNCiMjVGhlIERhdGFmcmFtZQ0KSGVyZSBJIGhhdmUgY3JlYXRlZCBhIG1lc3N5IHdpZGUgZGF0YXNldC4gRmVlbCBmcmVlIHRvIHVzZSBpdCB0byBmb2xsb3cgYWxvbmchDQoNCkluIHRoaXMgZXhhbXBsZSBzdHVkeSwgcGFydGljaXBhbnRzIHdlcmUgYXNrZWQgdG8gY2F0ZWdvcml6ZSB0aHJlZSBmYWNlcyBieSBjbGlja2luZyB2YXJpb3VzIGJ1dHRvbnMgdGhhdCByZXByZXNlbnQgdGhyZWUgZGlmZmVyZW50IGNhdGVnb3JpZXMuIFRoZSB0aW1lIGl0IHRvb2sgdG8gY2xpY2sgYSBidXR0b24gaXMgaW4gbWlsbGlzZWNvbmRzLiANCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpuPTEwDQp3aWRlIDwtIGRhdGEuZnJhbWUoDQogIElEID0gYygxOm4pLA0KICBGYWNlLjEgPSBjKDQxMSw3MjMsMzI1LDQ1Niw1NzksNjEyLDcwOSw1MTMsNTI3LDM3OSksDQogIEZhY2UuMiA9IGMoMTIzLDMwMCw0MDAsNTAwLDYwMCw2NTQsNzg5LDkwNiw0MTMsNTY3KSwNCiAgRmFjZS4zID0gYygxNDU3LDEwMDAsNTY5LDg5Niw5NTYsMjM0NSw3ODAsNTk5LDEwMjMsNjc4KQ0KKQ0KYGBgDQoNClRoaXMgZGF0YXNldCBJIGNyZWF0ZWQgaXMgbWVzc3k7IEFzIHlvdSBjYW4gc2VlIGJlbG93LCBvbmx5IElEIGlzIGluIGEgY29sdW1uLCBSZXNwb25zZSB0aW1lIHNwbGl0IGJldHdlZW4gdGhyZWUgY29sdW1ucywgc3VjaCB0aGF0IHJlc3BvbnNlcyBhcmUgaW4gYm90aCByb3dzIGFuZCBjb2x1bW5zIChieSBJRCBhbmQgRmFjZS4xLCBGYWNlLjIsIGFuZCBGYWNlLjMpLg0KDQpXaGF0IHdlIHdhbnQgaW5zdGVhZCBpcyBvbmUgY29sdW1uIGZvciB0aGUgY29uZGl0aW9uIChGYWNlLjEsIEZhY2UuMiwgb3IgRmFjZS4zKSByZXNwb25zZXMgYW5kIGEgY29sdW1uIGZvciByZXNwb25zZSB0aW1lLCB3aXRoIGVhY2ggcm93IGJlaW5nIGEgc2luZ3VhbGFyIG9ic2VydmF0aW9uIGZvciBlYWNoIHBhcnRpY2lwYW50LiBQYXJ0aWNpcGFudCBJRHMgc2hvdWxkIHJlcGVhdCBhcyB0aGlzIGlzIGEgd2l0aGluIHN1YmplY3QgZGVzaWduIChlYWNoIHBhcnRpY2lwYW50IHNhdyBlYWNoIGZhY2UpLg0KDQpgYGAge3IsIG1lc3NhZ2U9VFJVRSwgZWNobz1GQUxTRX0NCndpZGUNCmBgYA0KDQojIEdhdGhlcigpDQpCeSB1c2luZyB0aGUgYGdhdGhlcigpYCBmdW5jdGlvbiwgd2UgY2FuIHRyYW5zZm9ybSB0aGUgZGF0YSBmcm9tIHdpZGUgdG8gbG9uZw0KSGVyZSBpcyB0aGUgZ2VuZXJpYyBjb2RlIGZvciBgZ2F0aGVyKClgOg0KDQpgYGAge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89VFJVRX0NCiNnYXRoZXIoZGF0YSwga2V5LCB2YWx1ZSwgLi4uLCBuYS5ybSA9IEZBTFNFLCBjb252ZXJ0ID0gRkFMU0UsIGZhY3Rvcl9rZXkgPSBGQUxTRSkNCmBgYA0KDQojIyBHYXRoZXIoKSBBcmd1bWVudHMNCg0KV2hvYSEgV2hhdCBkb2VzIHRoaXMgYWxsIG1lYW4/IExldCdzIGZpbmQgb3V0IG1vcmUgYWJvdXQgdGhlIGFyZ3VtZW50cyBvZiBgZ2F0aGVyKClgOg0KDQotIGBkYXRhYDoJWW91ciBkYXRhIGZyYW1lLg0KDQotIGBrZXksIHZhbHVlYDoJVGhlIHVucXVvdGVkIG5ldyBuYW1lcyBvZiBrZXkgYW5kIHZhbHVlIGNvbHVtbnMgdG8gY3JlYXRlIGluIHRoZSBvdXRwdXQuIFRoZSBrZXkgd2lsbCBiZWNvbWUgdGhlIG5hbWUgb2YgdGhlIGNvbmRpdGlvbi9JViBjb2x1bW4sIGFuZCB2YWx1ZSB3aWxsIGJlY29tZSB0aGUgbmFtZSBvZiB0aGUgcmVzcG9uc2UvRFYgY29sdW1uLg0KDQotIGAuLi5gOiBUaGUgY29sdW1ucyB0byBnYXRoZXIuIFVzZSB0aGUgZXhpc2l0aW5nIHZhcmlhYmxlIG5hbWVzLiBTZWxlY3QgYSByYW5nZSBvZiB2YXJpYWJsZXMgd2l0aCBgOmAgKGUuZy4gaWYgeW91IGhhdmUgdmFyaWFibGVzIGEsIGIsIGMsIGFuZCBkLCBhbmQgd2FudCB0byBzZWxlY3QgYWxsIG9mIHRoZXNlIHZhcmliZWxlcyB5b3Ugd2lsbCBpbmRpY2F0ZSB0aGlzIHdpdGggYTpkKS4gSWYgeW91IHdhbnQgdG8gZXhjbHVkZSBhIHZhcmlhYmxlLCB1c2UgYC1gIChlLmcuIGV4Y2x1ZGUgeSB3aXRoIC15KS4gDQoNCi0gYG5hLnJtYDogSWYgeW91IGluZGljYXRlIHRoYXQgbmEucm09VFJVRSwgdGhpcyB3aWxsIHJlbW92ZSByb3dzIGZyb20gdGhlIG91dHB1dCB3aGVyZSB0aGUgdmFsdWUgaXMgbWlzc2luZy4NCg0KLSBgY29udmVydGA6CUlmIFRSVUUgdGhpcyB3aWxsIGF1dG9tYXRpY2FsbHkgY29udmVydCB0aGUga2V5IGNvbHVtbiB0byBhIGxvZ2ljYWwsIGludGVnZXIsIG51bWVyaWMsIGNvbXBsZXgsIG9yIGZhY3RvciBhcyBhcHByb3ByaWF0ZS4gVGhpcyBpcyB1c2VmdWwgaWYgdGhlIGNvbHVtbiBuYW1lcyBhcmUgYWN0dWFsbHkgbnVtZXJpYywgaW50ZWdlciwgb3IgbG9naWNhbC4NCg0KLSBgZmFjdG9yX2tleWA6CUlmIEZBTFNFLCB0aGUgZGVmYXVsdCwgdGhlIGtleSB2YWx1ZXMgd2lsbCBiZSBzdG9yZWQgYXMgYSBjaGFyYWN0ZXIgdmVjdG9yLiBJZiBUUlVFLCB3aWxsIGJlIHN0b3JlZCBhcyBhIGZhY3Rvciwgd2hpY2ggcHJlc2VydmVzIHRoZSBvcmlnaW5hbCBvcmRlcmluZyBvZiB0aGUgY29sdW1ucy4NCg0KIyNVc2luZyBHYXRoZXIoKQ0KTm93IHRoYXQgd2UgaGF2ZSBhIGJldHRlciB1bmRlcnN0YW5kaW5nIG9mIHRoZSBhcmd1ZW1lbnRzLCBsZXRzIG1ha2Ugb3VyIGRhdGEgc2V0IGxvbmcgdXNpbmcgYGdhdGhlcigpYCENCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpsb25nIDwtIHdpZGUgJT4lIGdhdGhlcihGYWNlLCBSZXNwb25zZVRpbWUsIEZhY2UuMTpGYWNlLjMpDQpgYGANCmBgYCB7ciwgbWVzc2FnZT1UUlVFLCBlY2hvPUZBTFNFfQ0KbG9uZw0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlLCBub3cgd2UgaGF2ZSB0d28gY29sdW1uczogT25lIGZvciB0aGUgdGhlIEZhY2VzLCBhbmQgb25lIGZvciByZXNwb25zZSB0aW1lLiBFYWNoIHBhcnRpY2lwYW50IHNhdyBlYWNoIGZhY2UsIHNvIElEIHJlcGVhdHMgdGhyZWUgdGltZXMuIA0KDQojIFNlcGFyYXRlKCkNCg0KQWx0aG91Z2ggdGhlIGxvbmcgZGF0YXNldCB3ZSBjcmVhdGVkIHVzaW5nIGBnYXRoZXIoKWAgaXMgYWNjZXB0YWJsZSBmb3IgdXNlLCB3ZSBjYW4gYnJlYWsgZG93biB0aGUgZmFjZSB2YXJpYWJsZSBldmVuIGZ1cnRoZXIgdXNpbmcgYHNlcGFyYXRlKClgLiANCg0KSGVyZSBpcyB0aGUgZ2VuZXJpYyBjb2RlIGZvciBgc2VwYXJhdGUoKWA6DQoNCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1UUlVFfQ0KI3NlcGFyYXRlKGRhdGEsIGNvbCwgaW50bywgc2VwID0gIlteWzphbG51bTpdXSsiLCByZW1vdmUgPSBUUlVFLCBjb252ZXJ0ID0gRkFMU0UsIGV4dHJhID0gIndhcm4iLCBmaWxsID0gIndhcm4iKQ0KYGBgDQojI1NlcGFyYXRlKCkgQXJndW1lbnRzDQoNCldoYXQgYXJlIHRoZSBhcnVnbWVudHMgdW5pcXVlIHRvIGBzZXBhcmF0ZSgpYD8gDQoNCi0gYGNvbGA6CVVucXVvdGVkIG5hbWUgb2YgdGhlIGNvbHVtbiB0byBiZSBzZXBhcmF0ZWQuDQoNCi0gYGludG9gOiBOYW1lcyBmb3IgdGhlIG5ldyB2YXJpYWJsZXMgdGhhdCB5b3UgYXJlIHNlcGFyYXRpbmcgb3V0IGZyb20gdGhlIGNvbHVtbi4NCg0KLSBgc2VwYDogU2VwYXJhdG9yIGJldHdlZW4gY29sdW1ucy4gSWYgdGhlIHNlcHJhdG9yIGlzIGEgY2hhcmFjdGVyLCBpdCBpcyBpbnRlcnByZXRlZCBhcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24gdGhhdCBtYXRjaGVzIGFueSBzZXF1ZW5jZSBvZiBub24tYWxwaGFudW1lcmljIHZhbHVlcy4gSW4gdGhlIGV4YW1wbGUsIGVhY2ggZmFjZSBpcyBpbmRpY2F0ZWQgYnkgYSBudW1iZXIgdGhhdCBmb2xsb3dzIGEgcGVyaW9kIChgLmApLiBJIGRvIG5vdCBuZWVkIHNwZWlmY3kgdGhpcyBiZWNhdXNlIHRoaXMgZXhpc3RzIGluIGVhY2ggbGV2ZWwgb2YgRmFjZS4gSWYgbnVtZXJpYywgaXQgaXMgaW50ZXJwcmV0ZWQgYXMgdGhlIHBvc2l0aW9uIHRvIHNwbGl0IGF0LiBQb3NpdGl2ZSB2YWx1ZXMgc3RhcnQgYXQgMSBhdCB0aGUgZmFyLWxlZnQgb2YgdGhlIHN0cmluZzsgbmVnYXRpdmUgdmFsdWUgc3RhcnQgYXQgLTEgYXQgdGhlIGZhci1yaWdodCBvZiB0aGUgc3RyaW5nLiBUaGUgbGVuZ3RoIG9mIGBzZXBgIHNob3VsZCBiZSBvbmUgbGVzcyB0aGFuIGBpbnRvYC4NCg0KLSBgcmVtb3ZlYDoJSWYgdGhpcyBpcyBUUlVFLCBpdCByZW1vdmVzIHRoZSBpbnB1dCBjb2x1bW4gZnJvbSBvdXRwdXQgZGF0YSBmcmFtZS4NCg0KLSBgZXh0cmFgOiBJZiBgc2VwYCBpcyBhIGNoYXJhY3RlciB2ZWN0b3IgKGxpa2UgYC5gKSwgdGhpcyBjb250cm9scyB3aGF0IGhhcHBlbnMgd2hlbiB0aGVyZSBhcmUgdG9vIG1hbnkgcGllY2VzIChlLmcuIEZhY2UuMS5BLCByYXRoZXIgdGhhbiBGYWNlLjEpLiBUaGVyZSBhcmUgdGhyZWUgdmFsaWQgb3B0aW9uczoNCiJ3YXJuIiAodGhlIGRlZmF1bHQpOiBlbWl0IGEgd2FybmluZyBhbmQgZHJvcCBleHRyYSB2YWx1ZXMuDQoiZHJvcCI6IGRyb3AgYW55IGV4dHJhIHZhbHVlcyB3aXRob3V0IGEgd2FybmluZy4NCiJtZXJnZSI6IG9ubHkgc3BsaXRzIGF0IG1vc3QgbGVuZ3RoKGludG8pIHRpbWVzDQoNCi0gYGZpbGxgOgkgSWYgYHNlcGAgaXMgYSBjaGFyYWN0ZXIgdmVjdG9yIChsaWtlIGAuYCksIHRoaXMgY29udHJvbHMgd2hhdCBoYXBwZW5zIHdoZW4gdGhlcmUgYXJlIG5vdCBlbm91Z2ggcGllY2VzIChlLmcuIEZhY2UxLCByYXRoZXIgdGhhbiBGYWNlLjEpLiBUaGVyZSBhcmUgdGhyZWUgdmFsaWQgb3B0aW9uczoNCiJ3YXJuIiAodGhlIGRlZmF1bHQpOiBlbWl0IGEgd2FybmluZyBhbmQgZmlsbCBmcm9tIHRoZSByaWdodA0KInJpZ2h0IjogZmlsbCB3aXRoIG1pc3NpbmcgdmFsdWVzIG9uIHRoZSByaWdodA0KImxlZnQiOiBmaWxsIHdpdGggbWlzc2luZyB2YWx1ZXMgb24gdGhlIGxlZnQNCg0KIyNVc2luZyBTZXBhcmF0ZSgpDQoNCkVhY2ggZmFjZSBpcyBpbmRpY2F0ZWQgYnkgbnVtYmVyIGFmdGVyIGEgcGVyaW9kLiBUaGlzIHZhcmlhYmxlIGFubm90YXRpb24gYWxsb3dzIHVzIHRvIHNlcGFyYXRlIHRoZSBmYWNlIHZhcmlhYmxlIGludG8gdHdvLiBCeSB1c2luZyB0aGUgYHNlcGFyYXRlYCBmdW5jdGlvbiBvZiBgdGlkeXJgIHdlIGNhbiB0ZWFzZSBhcGFydCBzaW5nbGUgdmFyaWFibGVzIHdoaWNoIHNvbWV0aW1lcyBjYXB0dXJlIG11bHRpcGxlIHZhcmlhYmxlcyAob3Igc29tZXRpbWVzIHJlZHVuZGFudCBpbmZvcm1hdGlvbikuIA0KDQpJbiB0aGlzIGNhc2UsIEkgd2FudCB0byBzcGxpdCB0aGUgRmFjZSBmcm9tIHRoZSBudW1iZXIgYXR0YWNoZWQgdG8gaXQsIHdoaWNoIGluIHRoaXMgZXhhbXBsZSByZXByZXNlbnRzIHRoZSByYWNlIG9mIHRoZSBmYWNlLiANCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpsb25nX3NlcGFyYXRlIDwtIGxvbmcgJT4lIHNlcGFyYXRlKEZhY2UsIGMoIlRhcmdldCIsICJOdW1iZXIiKSkNCmBgYA0KYGBgIHtyLCBtZXNzYWdlPVRSVUUsIGVjaG89RkFMU0V9DQpsb25nX3NlcGFyYXRlDQpgYGANCk5vdywgV2UgaGF2ZSB0d28gY29sdW1ucywgb25lIGZvciBUYXJnZXQsIHRoZSB2YWx1ZXMgb2Ygd2hpY2ggYXJlIGFsbCAiRmFjZSIsIGFuZCBvbmUgZm9yIE51bWJlciwgd2hpY2ggaW5kaWNhdGVzIHdoaWNoIG9mIHRoZSB0aHJlZSBmYWNlcyBpdCBpcy4gDQoNCiMgVW5pdGUNClRvIHVuZG8gYHNlcGFyYXRlKClgLCB3ZSBjYW4gdXNlIGB1bml0ZSgpYCwgd2hpY2ggbWVyZ2VzIHR3byB2YXJpYWJsZXMgaW50byBvbmUuIA0KDQpIZXJlIGlzIHRoZSBnZW5lcmljIGNvZGUgZm9yIGB1bml0ZSgpYDoNCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQojdW5pdGUoZGF0YSwgY29sLCAuLi4sIHNlcCA9ICIuIiwgcmVtb3ZlID0gVFJVRSkNCmBgYA0KDQojI1VuaXRlKCkgQXJndW1lbnRzDQoNCkhlcmUgYXJlIHRoZSBhcnVnbWVudHMgdW5pcXVlIHRvIGB1bml0ZSgpYDogDQoNCi0gYHNlcGA6IEluIHRoZSBjb2RlIGZvciBgdW5pdGUoKWAgdGhlIGBzZXBgIGluZGljYXRlZCB0aGUgc2VwYXJhdG9yIHdlIGNob29zZSB0byB0byB1c2UgdG8gYmluZCB2YWx1ZXMuIEluIHRoaXMgY2FzZSwgd2UgYXJlIHVzaW5nIGAuYA0KDQojI1VzaW5nIFVuaXRlKCkNCg0KYGBgIHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPVRSVUV9DQpsb25nX3VuaXRlIDwtIGxvbmdfc2VwYXJhdGUgJT4lIHVuaXRlKEZhY2UsIFRhcmdldCwgTnVtYmVyLCBzZXAgPSAiLiIpDQpgYGANCmBgYCB7ciwgbWVzc2FnZT1UUlVFLCBlY2hvPUZBTFNFfQ0KbG9uZ191bml0ZQ0KYGBgDQpBcyB5b3UgY2FuIHNlZSB0aGUgZGF0YSBub3cgbG9va3MgbGlrZSBpdCBkaWQgd2hlbiB3ZSBmaXJzdCB0cmFuc2Zyb21lZCBmcm9tIHdpZGUgdG8gbG9uZyB1c2luZyBgZ2F0aGVyKClgIQ0KDQojIFNwcmVhZA0KRmluYWxseSwgd2Ugd2lsbCB0cmFuc2Zvcm0gdGhlIGRhdGEgZnJvbSBsb25nIGJhY2sgdG8gd2lkZSB3aXRoIHRoZSBgc3ByZWFkKClgIGZ1bmN0aW9uLg0KDQpIZXJlIGlzIHRoZSBnZW5lcmljIGNvZGUgZm9yIGBzcHJlYWQoKWANCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1UUlVFfQ0KI3NwcmVhZChkYXRhLCBrZXksIHZhbHVlLCBmaWxsID0gTkEsIGNvbnZlcnQgPSBGQUxTRSwgZHJvcCA9IFRSVUUsIHNlcCA9IE5VTEwpDQpgYGANCg0KIyNTcHJlYWQoKSBBcmd1bWVudHMNCg0KVGhlIGFydWdtZW50cyB1bmlxdWUgdG8gYHNwcmVhZCgpYDoNCg0KLSBga2V5YDoJVGhlIHVucXVvdGVkIG5hbWUgb2YgdGhlIGNvbHVtbiB3aG9zZSB2YWx1ZXMgd2lsbCBiZSB1c2VkIGFzIGNvbHVtbiBoZWFkaW5ncy4NCg0KLSBgdmFsdWVgOglUaGUgdW5xdW90ZWQgbmFtZSBvZiB0aGUgY29sdW1uIHdob3NlIHZhbHVlcyB3aWxsIHBvcHVsYXRlIHRoZSBjZWxscy4gDQoNCi0gYGZpbGxgOglJZiB1c2VkLCBtaXNzaW5nIHZhbHVlcyB3aWxsIGJlIHJlcGxhY2VkIHdpdGggdGhpcyB2YWx1ZS4gVGhlcmUgYXJlIHR3byB0eXBlcyBvZiBtaXNzaW5nIGluIHRoZSBpbnB1dDogZXhwbGljaXQgbWlzc2luZyB2YWx1ZXMgKGkuZS4gYE5BYCksIGFuZCBpbXBsaWNpdCBtaXNzaW5ncywgcm93cyB0aGF0IHNpbXBseSBhcmVuJ3QgcHJlc2VudC4gQm90aCB0eXBlcyBvZiBtaXNzaW5nIHZhbHVlIHdpbGwgYmUgcmVwbGFjZWQgYnkgYGZpbGxgLg0KDQotIGBjb252ZXJ0YDogSWYgYFRSVUVgLCB0aGlzIHdpbGwgYXV0b21hdGljYWxseSBjb252ZXJ0IHRoZSBuZXcgY29sdW1ucyB0byBhIGxvZ2ljYWwsIGludGVnZXIsIG51bWVyaWMsIGNvbXBsZXgsIG9yIGZhY3RvciBhcyBhcHByb3ByaWF0ZS4NCg0KLSBgZHJvcGA6IElmIGBGQUxTRWAsIHdpbGwga2VlcCBmYWN0b3IgbGV2ZWxzIHRoYXQgZG9uJ3QgYXBwZWFyIGluIHRoZSBkYXRhLCBmaWxsaW5nIGluIG1pc3NpbmcgY29tYmluYXRpb25zIHdpdGggYGZpbGxgLg0KDQotIGBzZXBgOiBJZiBgTlVMTGAsIHRoZSBjb2x1bW4gbmFtZXMgd2lsbCBiZSB0YWtlbiBmcm9tIHRoZSB2YWx1ZXMgb2Yga2V5IHZhcmlhYmxlLiBJZiBub24tYE5VTExgLCB0aGUgY29sdW1uIG5hbWVzIHdpbGwgYmUgY3JlYXRlZCBieSBzdHJpbmdpbmcgdG9nZXRoZXIgdGhlIG5hbWUsIHNlcGFyYXRvciwgYW5kIHZhbHVlLg0KDQoNCmBgYCB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1UUlVFfQ0KYmFja190b193aWRlIDwtIGxvbmdfdW5pdGUgJT4lIHNwcmVhZChGYWNlLCBSZXNwb25zZVRpbWUpDQpgYGANCmBgYCB7ciwgbWVzc2FnZT1UUlVFLCBlY2hvPUZBTFNFfQ0KYmFja190b193aWRlDQpgYGANCg0KQW5kIHRoZXJlIHdlIGhhdmUgaXQhIFdlIGhhdmUgY29tZSBmdWxsIGNpcmNsZSBiYWNrIGludG8gd2lkZS4gDQoNCiNSZWZlcmVuY2VzDQpodHRwczovL3ByaWNlb25vbWljcy5jb20vaGFkbGV5LXdpY2toYW0tdGhlLW1hbi13aG8tcmV2b2x1dGlvbml6ZWQtci8gIyBXaG8gaXMgdGhpcyBIYWRsZXkgV2lja2hhbSBndXk/DQoNCmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYWdyaXR0ci92aWduZXR0ZXMvbWFncml0dHIuaHRtbCAjIEZ1cnRoZXIgcmVhZGluZyBhYm91dCBgJT4lYA0KDQpodHRwczovL2Jsb2cucnN0dWRpby5vcmcvMjAxNC8wNy8yMi9pbnRyb2R1Y2luZy10aWR5ci8gIyBIZWxwZnVsIG92ZXJ2aWV3IG9mIHRpZHlyDQoNCmh0dHA6Ly9hZGVtb3MucGVvcGxlLnVpYy5lZHUvQ2hhcHRlcjguaHRtbCAjIFRpbSBDYXJzZWwncyBjaGFwdGVyIG9uIHJlc2hhcGUyDQoNCmh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90aWR5ci90aWR5ci5wZGYgIyBBIGZ1bGwgZ3VpZGUgb2YgdGlkeSByIGFuZCBhbGwgdGhlIGFyZ3VtZW50cyBmb3IgZWFjaCBmdW5jdGlvbiBvZiB0aGUgcGFja2FnZQ0KDQpodHRwOi8vZ2FycmV0dGdtYW4uZ2l0aHViLmlvL3RpZHlpbmcvICMgRGlmZmVyZW50IHR5cGVzIG9mIG1lc3N5IGRhdGEgYW5kIGhvdyB0byBmaXggd2l0aCB0aWR5cg0KDQo8c2NyaXB0Pg0KICAoZnVuY3Rpb24oaSxzLG8sZyxyLGEsbSl7aVsnR29vZ2xlQW5hbHl0aWNzT2JqZWN0J109cjtpW3JdPWlbcl18fGZ1bmN0aW9uKCl7DQogIChpW3JdLnE9aVtyXS5xfHxbXSkucHVzaChhcmd1bWVudHMpfSxpW3JdLmw9MSpuZXcgRGF0ZSgpO2E9cy5jcmVhdGVFbGVtZW50KG8pLA0KICBtPXMuZ2V0RWxlbWVudHNCeVRhZ05hbWUobylbMF07YS5hc3luYz0xO2Euc3JjPWc7bS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShhLG0pDQogIH0pKHdpbmRvdyxkb2N1bWVudCwnc2NyaXB0JywnaHR0cHM6Ly93d3cuZ29vZ2xlLWFuYWx5dGljcy5jb20vYW5hbHl0aWNzLmpzJywnZ2EnKTsNCg0KICBnYSgnY3JlYXRlJywgJ1VBLTk4ODc4NzkzLTEnLCAnYXV0bycpOw0KICBnYSgnc2VuZCcsICdwYWdldmlldycpOw0KDQo8L3NjcmlwdD4NCg==