Welcome to R.

R is an interpreted languages, not a compiled one. This means, you type something into R and it does it. There is no data step. There are no procs. The SAS and R book is very useful for going between the two programs.

R uses libraries to do different types of analysis, so we will need to install lots of different libraries to do different things. These need to be downloaded from the internet, using the install.packages() command. You only need to install a package once. E.g.

install.packages("car") will install the lme4 library. To use the functions within it, type

library(car)

Now you have access to those functions.

I strongly recommend you install several packages prior to us beginning. I’ve written a short script on Github you can use it by running:

source("https://raw.githubusercontent.com/coreysparks/Rcode/master/install_first_7273.R")

Below we will go through a simple R session where we introduce some concepts that are important for R.

R is a calculator

#addition and subtraction
3+7
[1] 10
3-7
[1] -4
#multiplication and division
3*7
[1] 21
3/7
[1] 0.4285714
#powers
3^2
[1] 9
3^3
[1] 27
#functions
log(3/7)
[1] -0.8472979
exp(3/7)
[1] 1.535063
sin(3/7)
[1] 0.4155719

Variables and objects

In R we assign values to objects (object-oriented programming). These can generally have any name, but some names are reserved for R. For instance you probably wouldn’t want to call something ‘mean’ because there’s a ‘mean()’ function already in R. For instance:

x<-3
y<-7
x+y
[1] 10
x*y
[1] 21
log(x*y)
[1] 3.044522

vectors

R thinks everything is a matrix, or a vector, meaning a row or column of numbers, or characters. One of R’s big selling points is that much of it is completely vectorized. Meaning, I can apply an operation along all elements of a vector without having to write a loop. For example, if I want to multiply a vector of numbers by a constant, in SAS, I could do: #for (i in 1 to 5) # x[i]<-y[i]*5 #end

but in R, I can just do:

x<-c(3, 4, 5, 6, 7)
#c() makes a vector
y<-7
x*y
[1] 21 28 35 42 49

R is also very good about using vectors, let’s say I wanted to find the third element of x:

x[3]
[1] 5
#or if I want to test if this element is 10
x[3]==10
[1] FALSE
x[3]!=10
[1] TRUE
#of is it larger than another number:
x[3]>3
[1] TRUE
#or is any element of the whole vector greater than 3
x>3
[1] FALSE  TRUE  TRUE  TRUE  TRUE

If you want to see what’s in an object, use str(), for structure

str(x)
 num [1:5] 3 4 5 6 7

and we see that x is numeric, and has those values.

We can also see different characteristics of x

#how long is x?
length(x)
[1] 5
#is x numeric?
is.numeric(x)
[1] TRUE
#is any element of x missing?
is.na(x)
[1] FALSE FALSE FALSE FALSE FALSE
#now i'll modify x
x<-c(x, NA) #combine x and a missing value ==NA
x
[1]  3  4  5  6  7 NA
is.na(x)
[1] FALSE FALSE FALSE FALSE FALSE  TRUE

replacing elements of vectors

Above, we had a missing value in X, let’s say we want to replace it with another value:

x<-ifelse(test = is.na(x)==T, yes =  5, no =  x)
x
[1] 3 4 5 6 7 5

Done!

Dataframes

Traditionally, R organizes variables into data frames, these are like a spreadsheet. The columns can have names, and the dataframe itself can have data of different types. Here we make a short data frame with three columns, two numeric and one character:

Real data

Now let’s open a ‘real’ data file. This is the 2008 World population data sheet from the Population Reference Bureau. It contains summary information on many demographic and population level characteristics of nations around the world in 2008.

I’ve had this entered into a Comma Separated Values file by some poor previous GRA of mine and it lives happily on Github now for all the world to see. CSV files are a good way to store data coming out of a spreadsheet. R can read Excel files, but it digests text files easier. Save something from Excel as CSV.

I can read it from github directly by using a function in the readr library:

library(readr)
prb<-read_csv(file = "https://raw.githubusercontent.com/coreysparks/data/master/PRB2008_All.csv")
Parsed with column specification:
cols(
  .default = col_integer(),
  Country = col_character(),
  Continent = col_character(),
  Region = col_character(),
  Population. = col_double(),
  Rate.of.natural.increase = col_double(),
  ProjectedPopMid2025 = col_double(),
  ProjectedPopMid2050 = col_double(),
  IMR = col_double(),
  TFR = col_double(),
  PercPop1549HIVAIDS2001 = col_double(),
  PercPop1549HIVAIDS2007 = col_double(),
  PercPpUnderNourished0204 = col_double(),
  PopDensPerSqMile = col_double()
)
See spec(...) for full column specifications.
names(prb) #print the column names
 [1] "Y"                                 "X"                                 "ID"                               
 [4] "Country"                           "Continent"                         "Region"                           
 [7] "Year"                              "Population."                       "CBR"                              
[10] "CDR"                               "Rate.of.natural.increase"          "Net.Migration.Rate"               
[13] "ProjectedPopMid2025"               "ProjectedPopMid2050"               "ProjectedPopChange_08_50Perc"     
[16] "IMR"                               "WomandLifeTimeRiskMaternalDeath"   "TFR"                              
[19] "PercPopLT15"                       "PercPopGT65"                       "e0Total"                          
[22] "e0Male"                            "e0Female"                          "PercUrban"                        
[25] "PercPopinUrbanGT750k"              "PercPop1549HIVAIDS2001"            "PercPop1549HIVAIDS2007"           
[28] "PercMarWomContraALL"               "PercMarWomContraModern"            "PercPpUnderNourished0204"         
[31] "MotorVehper1000Pop0005"            "PercPopwAccessImprovedWaterSource" "GNIPPPperCapitaUSDollars"         
[34] "PopDensPerSqKM"                    "PopDensPerSqMile"                 
View(prb) #open it in a viewer

That’s handy. If the file lived on our computer, I could read it in like so: note, please make a folder on your computer so you can store things for this class in a single location!!!! Organization is Key to Success in Graduate School

prb<-read_csv("D:/GoogleDrive/classes/dem7273/class_17/data/PRB2008_All.csv")
Parsed with column specification:
cols(
  .default = col_integer(),
  Country = col_character(),
  Continent = col_character(),
  Region = col_character(),
  Population. = col_double(),
  Rate.of.natural.increase = col_double(),
  ProjectedPopMid2025 = col_double(),
  ProjectedPopMid2050 = col_double(),
  IMR = col_double(),
  TFR = col_double(),
  PercPop1549HIVAIDS2001 = col_double(),
  PercPop1549HIVAIDS2007 = col_double(),
  PercPpUnderNourished0204 = col_double(),
  PopDensPerSqMile = col_double()
)
See spec(...) for full column specifications.

Same result.

The haven library can read files from other statistical packages easily, so if you have data in Stata, SAS or SPSS (barf!), you can read it into R using those functions, for example, the read_dta() function reads stata files.

Don’t know what a function’s called use ??

??stata ??csv

and Rstudio will show you a list of functions that have these strings in them.

What if you know the function name, like read_csv() but you want to see all the function arguments?

?read_csv

will open up the help file for that specific function

Save a file

Want to save something as a R data file? Use save()

save(prb, file="D:/GoogleDrive/classes/dem7273/class_17/data/prb_2008.Rdata")

If you have an R data file, use load() to open it:

load("D:/GoogleDrive/classes/dem7273/class_17/data/prb_2008.Rdata")

Let’s have a look at some descriptive information about the data:

summary(prb$TFR)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  1.000   1.775   2.500   3.032   4.000   7.100       1 

There is one country missing the Total fertility rate variable. The minimum is 1 and the maximum is 7.1 children per woman.

More next week!!

LS0tDQp0aXRsZTogIkRFTSA3MjczIC0gRXhhbXBsZSAxIC0gSW50cm9kdWN0aW9uIHRvIFIiDQphdXRob3I6ICJDb3JleSBTcGFya3MsIFBoRCINCmRhdGU6ICJBdWd1c3QgMjMsIDIwMTciDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICB0b2M6IHllcw0KICBodG1sX2RvY3VtZW50OiANCiAgICBrZWVwX21kOiBubw0KLS0tDQoNCiNXZWxjb21lIHRvIFIuDQpSIGlzIGFuIGludGVycHJldGVkIGxhbmd1YWdlcywgbm90IGEgY29tcGlsZWQgb25lLiBUaGlzIG1lYW5zLCB5b3UgdHlwZSBzb21ldGhpbmcgaW50byBSIGFuZCBpdCBkb2VzIGl0LiBUaGVyZSBpcyBubyBkYXRhIHN0ZXAuIFRoZXJlIGFyZSBubyBwcm9jcy4gVGhlIFNBUyBhbmQgUiBib29rIGlzIHZlcnkgdXNlZnVsIGZvciBnb2luZyBiZXR3ZWVuIHRoZSB0d28gcHJvZ3JhbXMuICANCg0KUiB1c2VzIGxpYnJhcmllcyB0byBkbyBkaWZmZXJlbnQgdHlwZXMgb2YgYW5hbHlzaXMsIHNvIHdlIHdpbGwgbmVlZCB0byBpbnN0YWxsIGxvdHMgb2YgZGlmZmVyZW50IGxpYnJhcmllcyB0byBkbyBkaWZmZXJlbnQgdGhpbmdzLiBUaGVzZSBuZWVkIHRvIGJlIGRvd25sb2FkZWQgZnJvbSB0aGUgaW50ZXJuZXQsIHVzaW5nIHRoZSBgaW5zdGFsbC5wYWNrYWdlcygpYCBjb21tYW5kLiBZb3Ugb25seSBuZWVkIHRvIGluc3RhbGwgYSBwYWNrYWdlIG9uY2UuIEUuZy4NCg0KYGluc3RhbGwucGFja2FnZXMoImNhciIpYA0Kd2lsbCBpbnN0YWxsIHRoZSBsbWU0IGxpYnJhcnkuIFRvIHVzZSB0aGUgZnVuY3Rpb25zIHdpdGhpbiBpdCwgdHlwZQ0KDQpgbGlicmFyeShjYXIpYA0KDQpOb3cgeW91IGhhdmUgYWNjZXNzIHRvIHRob3NlIGZ1bmN0aW9ucy4gDQoNCkkgc3Ryb25nbHkgcmVjb21tZW5kIHlvdSBpbnN0YWxsIHNldmVyYWwgcGFja2FnZXMgcHJpb3IgdG8gdXMgYmVnaW5uaW5nLiBJJ3ZlIHdyaXR0ZW4gYSBzaG9ydCBzY3JpcHQgb24gR2l0aHViIHlvdSBjYW4gdXNlIGl0IGJ5IHJ1bm5pbmc6DQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0Kc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vY29yZXlzcGFya3MvUmNvZGUvbWFzdGVyL2luc3RhbGxfZmlyc3RfNzI3My5SIikNCmBgYA0KDQpCZWxvdyB3ZSB3aWxsIGdvIHRocm91Z2ggYSBzaW1wbGUgUiBzZXNzaW9uIHdoZXJlIHdlIGludHJvZHVjZSBzb21lIGNvbmNlcHRzIHRoYXQgYXJlIGltcG9ydGFudCBmb3IgUi4NCg0KDQojIyNSIGlzIGEgY2FsY3VsYXRvcg0KYGBge3J9DQojYWRkaXRpb24gYW5kIHN1YnRyYWN0aW9uDQozKzcNCjMtNw0KDQojbXVsdGlwbGljYXRpb24gYW5kIGRpdmlzaW9uDQozKjcNCg0KMy83DQoNCiNwb3dlcnMNCjNeMg0KM14zDQoNCiNmdW5jdGlvbnMNCmxvZygzLzcpDQpleHAoMy83KQ0Kc2luKDMvNykNCg0KYGBgDQoNCg0KIyMjVmFyaWFibGVzIGFuZCBvYmplY3RzDQoNCkluIFIgd2UgYXNzaWduIHZhbHVlcyB0byBvYmplY3RzIChvYmplY3Qtb3JpZW50ZWQgcHJvZ3JhbW1pbmcpLiBUaGVzZSBjYW4gZ2VuZXJhbGx5IGhhdmUgYW55IG5hbWUsIGJ1dCBzb21lIG5hbWVzIGFyZSByZXNlcnZlZCBmb3IgUi4gRm9yIGluc3RhbmNlIHlvdSBwcm9iYWJseSB3b3VsZG4ndCB3YW50IHRvIGNhbGwgc29tZXRoaW5nICdtZWFuJyBiZWNhdXNlIHRoZXJlJ3MgYSAnbWVhbigpJyBmdW5jdGlvbiBhbHJlYWR5IGluIFIuIEZvciBpbnN0YW5jZToNCg0KYGBge3J9DQp4PC0zDQp5PC03DQp4K3kNCngqeQ0KbG9nKHgqeSkNCg0KYGBgDQoNCiMjdmVjdG9ycw0KUiB0aGlua3MgZXZlcnl0aGluZyBpcyBhIG1hdHJpeCwgb3IgYSB2ZWN0b3IsIG1lYW5pbmcgYSByb3cgb3IgY29sdW1uIG9mIG51bWJlcnMsIG9yIGNoYXJhY3RlcnMuIE9uZSBvZiBSJ3MgYmlnIHNlbGxpbmcgcG9pbnRzIGlzIHRoYXQgbXVjaCBvZiBpdCBpcyBjb21wbGV0ZWx5IHZlY3Rvcml6ZWQuIE1lYW5pbmcsIEkgY2FuIGFwcGx5IGFuIG9wZXJhdGlvbiBhbG9uZyBhbGwgZWxlbWVudHMgb2YgYSB2ZWN0b3Igd2l0aG91dCBoYXZpbmcgdG8gd3JpdGUgYSBsb29wLiBGb3IgZXhhbXBsZSwgaWYgSSB3YW50IHRvIG11bHRpcGx5IGEgdmVjdG9yIG9mIG51bWJlcnMgYnkgYSBjb25zdGFudCwgaW4gU0FTLCBJIGNvdWxkIGRvOg0KI2ZvciAoaSBpbiAxIHRvIDUpDQojICB4W2ldPC15W2ldKjUNCiNlbmQNCg0KYnV0IGluIFIsIEkgY2FuIGp1c3QgZG86DQpgYGB7cn0NCng8LWMoMywgNCwgNSwgNiwgNykNCiNjKCkgbWFrZXMgYSB2ZWN0b3INCnk8LTcNCg0KeCp5DQoNCmBgYA0KDQoNClIgaXMgYWxzbyB2ZXJ5IGdvb2QgYWJvdXQgdXNpbmcgdmVjdG9ycywgbGV0J3Mgc2F5IEkgd2FudGVkIHRvIGZpbmQgdGhlIHRoaXJkIGVsZW1lbnQgb2YgeDoNCmBgYHtyfQ0KeFszXQ0KDQojb3IgaWYgSSB3YW50IHRvIHRlc3QgaWYgdGhpcyBlbGVtZW50IGlzIDEwDQp4WzNdPT0xMA0KeFszXSE9MTANCg0KI29mIGlzIGl0IGxhcmdlciB0aGFuIGFub3RoZXIgbnVtYmVyOg0KeFszXT4zDQoNCiNvciBpcyBhbnkgZWxlbWVudCBvZiB0aGUgd2hvbGUgdmVjdG9yIGdyZWF0ZXIgdGhhbiAzDQp4PjMNCg0KYGBgDQoNCg0KSWYgeW91IHdhbnQgdG8gc2VlIHdoYXQncyBpbiBhbiBvYmplY3QsIHVzZSBgc3RyKClgLCBmb3IgYHN0cmB1Y3R1cmUNCg0KYGBge3J9DQpzdHIoeCkNCmBgYA0KDQphbmQgd2Ugc2VlIHRoYXQgeCBpcyBudW1lcmljLCBhbmQgaGFzIHRob3NlIHZhbHVlcy4NCg0KV2UgY2FuIGFsc28gc2VlIGRpZmZlcmVudCBjaGFyYWN0ZXJpc3RpY3Mgb2YgeA0KYGBge3J9DQojaG93IGxvbmcgaXMgeD8NCmxlbmd0aCh4KQ0KDQojaXMgeCBudW1lcmljPw0KaXMubnVtZXJpYyh4KQ0KDQojaXMgYW55IGVsZW1lbnQgb2YgeCBtaXNzaW5nPw0KaXMubmEoeCkNCg0KDQojbm93IGknbGwgbW9kaWZ5IHgNCng8LWMoeCwgTkEpICNjb21iaW5lIHggYW5kIGEgbWlzc2luZyB2YWx1ZSA9PU5BDQp4DQppcy5uYSh4KQ0KYGBgDQoNCiMjcmVwbGFjaW5nIGVsZW1lbnRzIG9mIHZlY3RvcnMNCkFib3ZlLCB3ZSBoYWQgYSBtaXNzaW5nIHZhbHVlIGluIFgsIGxldCdzIHNheSB3ZSB3YW50IHRvIHJlcGxhY2UgaXQgd2l0aCBhbm90aGVyIHZhbHVlOg0KYGBge3J9DQp4PC1pZmVsc2UodGVzdCA9IGlzLm5hKHgpPT1ULCB5ZXMgPSAgNSwgbm8gPSAgeCkNCngNCmBgYA0KDQpEb25lIQ0KDQojI0RhdGFmcmFtZXMNClRyYWRpdGlvbmFsbHksIFIgb3JnYW5pemVzIHZhcmlhYmxlcyBpbnRvIGRhdGEgZnJhbWVzLCB0aGVzZSBhcmUgbGlrZSBhIHNwcmVhZHNoZWV0LiBUaGUgY29sdW1ucyBjYW4gaGF2ZSBuYW1lcywgYW5kIHRoZSBkYXRhZnJhbWUgaXRzZWxmIGNhbiBoYXZlIGRhdGEgb2YgZGlmZmVyZW50IHR5cGVzLiBIZXJlIHdlIG1ha2UgYSBzaG9ydCBkYXRhIGZyYW1lIHdpdGggdGhyZWUgY29sdW1ucywgdHdvIG51bWVyaWMgYW5kIG9uZSBjaGFyYWN0ZXI6DQoNCmBgYHtyfQ0KbXlkYXQ8LWRhdGEuZnJhbWUoDQogIHg9YygxLDIsMyw0LDUpLA0KICB5PWMoMTAsIDIwLCAzNSwgNTcsIDM3KSwNCiAgZ3JvdXA9YygiQSIsICJBIiAsIkEiLCAiQiIsICJCIikNCikNCg0KI1NlZSB0aGUgc2l6ZSBvZiB0aGUgZGF0YWZyYW1lDQpkaW0obXlkYXQpDQoNCiNPcGVuIHRoZSBkYXRhZnJhbWUgaW4gYSB2aWV3ZXIgYW5kIGp1c3QgcHJpbnQgaXQNClZpZXcobXlkYXQpDQpwcmludChteWRhdCkNCmBgYA0KDQoNCiMjUmVhbCBkYXRhDQpOb3cgbGV0J3Mgb3BlbiBhICdyZWFsJyBkYXRhIGZpbGUuIFRoaXMgaXMgdGhlIFsyMDA4IFdvcmxkIHBvcHVsYXRpb24gZGF0YSBzaGVldF0oaHR0cDovL3d3dy5wcmIub3JnL1B1YmxpY2F0aW9ucy9EYXRhc2hlZXRzLzIwMDgvMjAwOHdwZHMuYXNweCkgZnJvbSB0aGUgW1BvcHVsYXRpb24gUmVmZXJlbmNlIEJ1cmVhdV0od3d3LnByYi5vcmcpLiBJdCBjb250YWlucyBzdW1tYXJ5IGluZm9ybWF0aW9uIG9uIG1hbnkgZGVtb2dyYXBoaWMgYW5kIHBvcHVsYXRpb24gbGV2ZWwgY2hhcmFjdGVyaXN0aWNzIG9mIG5hdGlvbnMgYXJvdW5kIHRoZSB3b3JsZCBpbiAyMDA4Lg0KDQpJJ3ZlIGhhZCB0aGlzIGVudGVyZWQgaW50byBhICoqQ29tbWEgU2VwYXJhdGVkIFZhbHVlcyoqIGZpbGUgYnkgc29tZSBwb29yIHByZXZpb3VzIEdSQSBvZiBtaW5lIGFuZCBpdCBsaXZlcyBoYXBwaWx5IG9uIEdpdGh1YiBub3cgZm9yIGFsbCB0aGUgd29ybGQgdG8gc2VlLiBDU1YgZmlsZXMgYXJlIGEgZ29vZCB3YXkgdG8gc3RvcmUgZGF0YSBjb21pbmcgb3V0IG9mIGEgc3ByZWFkc2hlZXQuIFIgY2FuIHJlYWQgRXhjZWwgZmlsZXMsIGJ1dCBpdCBkaWdlc3RzIHRleHQgZmlsZXMgZWFzaWVyLiBTYXZlIHNvbWV0aGluZyBmcm9tIEV4Y2VsIGFzIENTVi4gDQoNCkkgY2FuIHJlYWQgaXQgZnJvbSBnaXRodWIgZGlyZWN0bHkgYnkgdXNpbmcgYSBmdW5jdGlvbiBpbiB0aGUgYHJlYWRyYCBsaWJyYXJ5Og0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpwcmI8LXJlYWRfY3N2KGZpbGUgPSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2NvcmV5c3BhcmtzL2RhdGEvbWFzdGVyL1BSQjIwMDhfQWxsLmNzdiIpDQpuYW1lcyhwcmIpICNwcmludCB0aGUgY29sdW1uIG5hbWVzDQpWaWV3KHByYikgI29wZW4gaXQgaW4gYSB2aWV3ZXINCmBgYA0KDQpUaGF0J3MgaGFuZHkuIElmIHRoZSBmaWxlIGxpdmVkIG9uIG91ciBjb21wdXRlciwgSSBjb3VsZCByZWFkIGl0IGluIGxpa2Ugc286DQoqbm90ZSwgcGxlYXNlIG1ha2UgYSBmb2xkZXIgb24geW91ciBjb21wdXRlciBzbyB5b3UgY2FuIHN0b3JlIHRoaW5ncyBmb3IgdGhpcyBjbGFzcyBpbiBhIHNpbmdsZSBsb2NhdGlvbiEhISEgT3JnYW5pemF0aW9uIGlzIEtleSB0byBTdWNjZXNzIGluIEdyYWR1YXRlIFNjaG9vbCoNCg0KYGBge3J9DQoNCnByYjwtcmVhZF9jc3YoIkQ6L0dvb2dsZURyaXZlL2NsYXNzZXMvZGVtNzI3My9jbGFzc18xNy9kYXRhL1BSQjIwMDhfQWxsLmNzdiIpDQoNCmBgYA0KDQpTYW1lIHJlc3VsdC4NCg0KVGhlIGBoYXZlbmAgbGlicmFyeSBjYW4gcmVhZCBmaWxlcyBmcm9tIG90aGVyIHN0YXRpc3RpY2FsIHBhY2thZ2VzIGVhc2lseSwgc28gaWYgeW91IGhhdmUgZGF0YSBpbiBTdGF0YSwgU0FTIG9yIFNQU1MgKGJhcmYhKSwgeW91IGNhbiByZWFkIGl0IGludG8gUiB1c2luZyB0aG9zZSBmdW5jdGlvbnMsIGZvciBleGFtcGxlLCB0aGUgYHJlYWRfZHRhKClgIGZ1bmN0aW9uIHJlYWRzIHN0YXRhIGZpbGVzLiANCg0KRG9uJ3Qga25vdyB3aGF0IGEgZnVuY3Rpb24ncyBjYWxsZWQgdXNlID8/DQoNCmA/P3N0YXRhYA0KYD8/Y3N2YA0KDQphbmQgUnN0dWRpbyB3aWxsIHNob3cgeW91IGEgbGlzdCBvZiBmdW5jdGlvbnMgdGhhdCBoYXZlIHRoZXNlIHN0cmluZ3MgaW4gdGhlbS4gDQoNCldoYXQgaWYgeW91IGtub3cgdGhlIGZ1bmN0aW9uIG5hbWUsIGxpa2UgYHJlYWRfY3N2KClgIGJ1dCB5b3Ugd2FudCB0byBzZWUgYWxsIHRoZSBmdW5jdGlvbiBhcmd1bWVudHM/DQoNCmA/cmVhZF9jc3ZgDQoNCndpbGwgb3BlbiB1cCB0aGUgaGVscCBmaWxlIGZvciB0aGF0IHNwZWNpZmljIGZ1bmN0aW9uDQoNCg0KIyMjU2F2ZSBhIGZpbGUNCldhbnQgdG8gc2F2ZSBzb21ldGhpbmcgYXMgYSBSIGRhdGEgZmlsZT8gVXNlIGBzYXZlKClgDQoNCmBgYHtyfQ0Kc2F2ZShwcmIsIGZpbGU9IkQ6L0dvb2dsZURyaXZlL2NsYXNzZXMvZGVtNzI3My9jbGFzc18xNy9kYXRhL3ByYl8yMDA4LlJkYXRhIikNCmBgYA0KDQpJZiB5b3UgaGF2ZSBhbiBSIGRhdGEgZmlsZSwgdXNlIGBsb2FkKClgIHRvIG9wZW4gaXQ6DQoNCmBgYHtyfQ0KbG9hZCgiRDovR29vZ2xlRHJpdmUvY2xhc3Nlcy9kZW03MjczL2NsYXNzXzE3L2RhdGEvcHJiXzIwMDguUmRhdGEiKQ0KYGBgDQoNCg0KDQpMZXQncyBoYXZlIGEgbG9vayBhdCBzb21lIGRlc2NyaXB0aXZlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkYXRhOg0KYGBge3J9DQojRnJlcXVlbmN5IFRhYmxlIG9mICMgb2YgQ29udHJpZXMgYnkgQ29udGluZW50DQp0YWJsZShwcmIkQ29udGluZW50KQ0KDQoNCiNiYXNpYyBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSB2YXJpYWJsZSBURlIgb3IgdGhlIHRvdGFsIGZlcnRpbGl0eSByYXRlDQpzdW1tYXJ5KHByYiRURlIpDQoNCmBgYA0KDQpUaGVyZSBpcyBvbmUgY291bnRyeSBtaXNzaW5nIHRoZSBUb3RhbCBmZXJ0aWxpdHkgcmF0ZSB2YXJpYWJsZS4gVGhlIG1pbmltdW0gaXMgMSBhbmQgdGhlIG1heGltdW0gaXMgNy4xIGNoaWxkcmVuIHBlciB3b21hbi4NCg0KDQpNb3JlIG5leHQgd2VlayEhDQoNCg0K