About
The goal of this lab is to introduce you to R and RStudio, which you’ll be using throughout the course both to learn the statistical concepts discussed in class, and also to analyze real data and come to informed conclusions. To straighten out which is which: R is the name of the programming language itself , and RStudio is a convenient interface. R provides a wide variety of statistical (linear and nonlinear modelling, classical statistical tests, time-series analysis, classification, clustering, .) and graphical techniques, and is highly extensible.
As the labs progress, you are encouraged to explore beyond what the labs cover; a willingness to experiment will make you a much better programmer. Before we get to that stage, however, you need to build some basic fluency in R.
Setup
Remember to always set your working directory to the source file location. Go to ‘Session’, scroll down to ‘Set Working Directory’, and click ‘To Source File Location’. Read carefully the below and follow the instructions to complete the tasks and answer any questions. Submit your work in Sakai as detailed in previous notes.
Note
For your assignment you may be using different data sets than what is included here. Always read carefully the instructions provided, before executing any included code chunks and/or adding your own code. For clarity, tasks/questions to be completed/answered are highlighted in red color and numbered according to their particular placement in the task section. The red color is only apparent when in Preview mode. Quite often you will need to add your own code chunk.
xecute all code chunks (already included and own added), preview, check integrity, and submit final work (\(html\) file) in Sakai.

Basics Operations
First we will begin with a few basic operations.
Variable assignment
We assign values to variables using the assignment operator ‘=’. Another form of assignment, more general, is the ‘<-’ operator. A variable allows you to store values or an object (e.g. a function).
x = 128
y = 16
z <- 5
vars = c(2,4,8,16,32) # Creates a vector list using the generic combine function 'c'
x # display value of variable x
[1] 128
z # displays value of variable z
[1] 5
vars[1] #This calls the first value in the vector vars
[1] 2
vars[2] #This calls the second value in the vector vars
[1] 4
vars[1:3] #This calls the first through third values in the vector vars
[1] 2 4 8
vars #This calls the vector list
[1] 2 4 8 16 32
Common Arithmetic Operations
Below shows some simple arithmetic operations.
12*6
128/16
9^2
Basic Data Types
R works with numerous data types. Some of the most basic types are: numeric,integers, logical (Boolean-TRUE/FALSE) and characters (string-"TEXT").
#Type: Character
#Example:"TRUE",'23.4'
v = "TRUE"
class(v)
[1] "character"
#Type: Numeric
#Example: 12.3,5
v = 23.5
class(v)
[1] "numeric"
#Type: Logical
#Example: TRUE,FALSE
v = TRUE
class(v)
[1] "logical"
#Type: Factor (nominal, categorical)
#Example: m f m f m
v = as.factor(c("m", "f", "m"))
class(v)
[1] "factor"
Functions
R Functions are invoked by its name, followed by the parenthesis, and zero or more arguments.
# The following applies the function 'c' (seen earlier) to combine three numeric values into a vector
c(1,2,3)
[1] 1 2 3
# Example of function mean() to calcule the mean of three values
mean(c(5,6,7))
[1] 6
# Square root of a number
sqrt(99)
[1] 9.949874
Importing Data and Variable Assignment
# Here we are reading a file of type csv (comma seperated values) typical of many Excel files
il_income = read.csv(file = "il_income.csv")
top_il_income = read.csv(file = "top_il_income.csv")
Arithmetic Operations with Data
We can extract values from the dataset to perform calculations.
DuPage = top_il_income$per_capita_income[1]
Lake = top_il_income$per_capita_income[2]
DuPage-Lake
[1] 472
DuPage+Lake
[1] 77390
(DuPage+Lake)/2
[1] 38695
McHenry = top_il_income$per_capita_income[3]
Sangamon = top_il_income$per_capita_income[10]
McHenry-Sangamon
[1] 2524
McHenry+Sangamon
[1] 63712
(McHenry+Sangamon)/2
[1] 31856
##### 1) Repeat here the above arithmetic operations code chunk using instead the columns for McHenry and Sangamon counties (4pts)
Basic Statistics
mean(il_income$per_capita_income)
median(il_income$per_capita_income)
quantile(il_income$per_capita_income)
# Summary
summary(il_income)
mean(top_il_income$per_capita_income)
[1] 32918.5
median(top_il_income$per_capita_income)
[1] 31430
quantile(top_il_income$per_capita_income)
0% 25% 50% 75% 100%
30594.00 30743.75 31430.00 33103.25 38931.00
# Summary
summary(top_il_income)
rank county per_capita_income
Min. : 2.00 DuPage :1 Min. :30594
1st Qu.: 4.25 Kane :1 1st Qu.:30744
Median :12.00 Kendall:1 Median :31430
Mean :27.10 Lake :1 Mean :32919
3rd Qu.:41.00 McHenry:1 3rd Qu.:33103
Max. :90.00 McLean :1 Max. :38931
(Other):4
population region
Min. : 7032 Min. :2.0
1st Qu.: 36921 1st Qu.:2.0
Median :194782 Median :3.0
Mean :334866 Mean :3.2
3rd Qu.:648159 3rd Qu.:4.0
Max. :933736 Max. :5.0
##### 2) Repeat here the above basic statistics code chunk using instead the data from the file top_il_income (4pts)
Vectors
Defining a Vector
A sequence of data elements of the same basic type is defined as a vector.
# vector of numeric values
c(2, 3, 5, 8)
[1] 2 3 5 8
# vector of logical values.
c(TRUE, FALSE, TRUE)
[1] TRUE FALSE TRUE
# vector of character strings.
c("A", "B", "B-", "C", "D")
[1] "A" "B" "B-" "C" "D"
Lists
Defining a List
Lists, as opposed to vectors, can hold components of different types.
scores = c(80, 75, 55) # vector of numeric values
grades = c("B", "C", "D-") # vector of character strings.
office_hours = c(TRUE, FALSE, FALSE) # vector of logical values.
student = list(scores,grades,office_hours) # list of vectors
student
[[1]]
[1] 80 75 55
[[2]]
[1] "B" "C" "D-"
[[3]]
[1] TRUE FALSE FALSE
List Slicing
We can retrieve components of the list with the single square bracket [] operator.
student[1]
$myscores
[1] 80 75 55
student[2]
$mygrades
[1] "B" "C" "D-"
student[3]
$myoffice_hours
[1] TRUE FALSE FALSE
# first two components of the list
student[1:2]
$myscores
[1] 80 75 55
$mygrades
[1] "B" "C" "D-"
Member Reference
Using the double square bracket [[]] operator we can reference a member of the list directly. Using one bracket [] would still reference the list but will not allow you to extract a particular member of the list.
student[[1]] # Components of the Scores Vector
[1] 80 75 55
First element of the Scores vector
student[[1]][1]
[1] 80
First three elements of the Scores vector
student[[1]][1:3]
[1] 80 75 55
student[[2]][2]
[1] "C"
grades[2]
[1] "C"
##### 3) Repeat here the above code chunk to extract instead the second element of the grades vector (3pts)
Named List Members
It’s possible to assign names to list members and reference them by names instead of by numeric indexes.
student = list(myscores = scores, mygrades = grades , myoffice_hours = office_hours)
student
$myscores
[1] 80 75 55
$mygrades
[1] "B" "C" "D-"
$myoffice_hours
[1] TRUE FALSE FALSE
student$myscores
[1] 80 75 55
student$mygrades
[1] "B" "C" "D-"
student$myoffice_hours
[1] TRUE FALSE FALSE
Matrices
All columns in a matrix must have the same data type and the same length.
Create a numeric matrix of 5 rows and 4 columns made of sequential numbers 1:20
x_mat = matrix(1:20, nrow=5, ncol=4)
x_mat
[,1] [,2] [,3] [,4]
[1,] 1 6 11 16
[2,] 2 7 12 17
[3,] 3 8 13 18
[4,] 4 9 14 19
[5,] 5 10 15 20
Retrieve the 4th column of matrix
x_mat[,4]
[1] 16 17 18 19 20
Retrieve the 3rd row of matrix
x_mat[3,]
[1] 3 8 13 18
Retrieve rows 2,3,4 of columns 1,2,3
x_mat[2:4,1:3]
[,1] [,2] [,3]
[1,] 2 7 12
[2,] 3 8 13
[3,] 4 9 14
x_mat[3,3]
[1] 13
x_mat[3,]
[1] 3 8 13 18
x_mat[,3]
[1] 11 12 13 14 15
##### 4) Repeat here the above code chunk to extract instead the third row and thrid column of the matrix (3pts)
Data Frames
A data frame is more general than a matrix, in that different columns can have different data types (numeric, character, logic, factor). It is a powerful way to work with mixed data structures.
Defining a Data Frame
When we need to store data in table form, we use data frames, which are created by combining lists of vectors of equal length. The variables of a data set are the columns and the observations are the rows.
The str() function helps us to display the internal structure of any R data structure or object to make sure that it’s correct.
str(il_income)
'data.frame': 102 obs. of 5 variables:
$ rank : int 1 2 3 4 5 6 7 8 9 10 ...
$ county : Factor w/ 102 levels "Adams","Alexander",..: 16 22 49 99 45 60 101 64 86 10 ...
$ per_capita_income: int 30468 38931 38459 30791 30645 23937 24802 30728 23279 26087 ...
$ population : int 5238216 933736 703910 687263 530847 307343 287078 266209 264052 208861 ...
$ region : int 1 2 2 2 2 2 2 5 5 3 ...
Creating a Data Frame
Snapshot of the solar system.
name = c("Earth", "Mars", "Jupiter")
type = c("Terrestrial","Terrestrial", "Gas giant")
diameter = c(1, 0.532, 11.209)
rotation = c(1, 1.03, 0.41)
rings = c(FALSE, FALSE, TRUE)
Now, by combining the vectors of equal size, we can create a data frame object.
planets_df = data.frame(name,type,diameter,rotation,rings)
planets_df
NA
Sentiment Analysis
This is an added section for the honored class section only. The purpose is to conduct a sample text analysis investigation, and assess the results.
And they wishin’ and wishin’ and wishin’ and wishin’ They wishin’ on me, yuh
[Verse 1] I been movin’ calm, don’t start no trouble with me Tryna keep it peaceful is a struggle for me Don’t pull up at 6 AM to cuddle with me You know how I like it when you lovin’ on me I don’t wanna die for them to miss me Yes, I see the things that they wishin’ on me Hope I got some brothers that outlive me They gon’ tell the story, shit was different with me
[Chorus] God’s plan, God’s plan I hold back, sometimes I won’t, yuh I feel good, sometimes I don’t, ayy, don’t I finessed down Weston Road, ayy, ’nessed Might go down a G.O.D., yeah, wait I go hard on Southside G, yuh, wait I make sure that north-side eat
[Post-Chorus] And still, bad things It’s a lot of bad things That they wishin’ and wishin’ and wishin’ and wishin’ They wishin’ on me Bad things It’s a lot of bad things That they wishin’ and wishin’ and wishin’ and wishin’ They wishin’ on me Yuh, ayy, ayy
I analyzed a rap song by Drake, and the song is about overcoming struggles because it’s “God’s Plan.” The sentiment had a lot of negative values for words like struggle, trouble, and the profain words. Overall, the verses I inputed had a score of 0, meaning neither a positive nor negative result. The maginitude of the words analyzed were not very strong, with the highest being 2.2. Most of the words were around .5, meaning the strength of the sentiment was not very strong.
Select a small text article (10 to 20 lines) from an online source of your choice and a topic of your interest. You can also make up your own text. Copy and paste the paragraph here. Use the Google Cloud NLP API demo at https://cloud.google.com/natural-language/ to paste your text in the appropriate space, and run a sentiment analysis. Without diving much into the analytics and the coding details behind the API, write a half paragraph summarizing your assessment of the sentiment analysis results as given by Google NLP. You probably want to investigate the meaning of \(score\) and \(magnitude\) in the results displayed by Google (6pts)
Suggested Exercises & Resources
Data Sources
Data samples used in this worksheet were downloaded from the U.S. Census Bureau American FactFinder site.
LS0tDQp0aXRsZTogIldvcmtpbmcgd2l0aCBSL1JTdHVkaW8gKGxhYjAyKSINCmF1dGhvcjogTGF1cmVuIEtyb2xsDQpkYXRlOiBKYW51YXJ5IDMwLCAyMDIwDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0Kc3VidGl0bGU6IEJTQUQzNDNILCBCdXNpbmVzcyBBbmFseXRpY3MsIFNwcmluZyAyMDIwDQotLS0NCg0KIyMjIEFib3V0DQoNClRoZSBnb2FsIG9mIHRoaXMgbGFiIGlzIHRvIGludHJvZHVjZSB5b3UgdG8gIFIgYW5kIFJTdHVkaW8sIHdoaWNoIHlvdSdsbCBiZSB1c2luZyB0aHJvdWdob3V0IHRoZSBjb3Vyc2UgYm90aCB0byBsZWFybiB0aGUgc3RhdGlzdGljYWwgY29uY2VwdHMgZGlzY3Vzc2VkIGluIGNsYXNzLCAgYW5kIGFsc28gdG8gYW5hbHl6ZSByZWFsIGRhdGEgYW5kIGNvbWUgdG8gaW5mb3JtZWQgY29uY2x1c2lvbnMuICBUbyBzdHJhaWdodGVuIG91dCB3aGljaCBpcyB3aGljaDogUiBpcyB0aGUgbmFtZSBvZiB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UgaXRzZWxmICwgYW5kIFJTdHVkaW8gaXMgYSBjb252ZW5pZW50IGludGVyZmFjZS4gIFIgcHJvdmlkZXMgYSB3aWRlIHZhcmlldHkgb2Ygc3RhdGlzdGljYWwgKGxpbmVhciBhbmQgbm9ubGluZWFyIG1vZGVsbGluZywgY2xhc3NpY2FsIHN0YXRpc3RpY2FsIHRlc3RzLCB0aW1lLXNlcmllcyBhbmFseXNpcywgY2xhc3NpZmljYXRpb24sIGNsdXN0ZXJpbmcsIC4pIGFuZCBncmFwaGljYWwgdGVjaG5pcXVlcywgYW5kIGlzIGhpZ2hseSBleHRlbnNpYmxlLiANCg0KQXMgdGhlIGxhYnMgcHJvZ3Jlc3MsIHlvdSBhcmUgZW5jb3VyYWdlZCB0byBleHBsb3JlIGJleW9uZCB3aGF0IHRoZSBsYWJzIGNvdmVyOyBhIHdpbGxpbmduZXNzIHRvIGV4cGVyaW1lbnQgd2lsbCBtYWtlIHlvdSBhIG11Y2ggYmV0dGVyIHByb2dyYW1tZXIuICBCZWZvcmUgd2UgIGdldCB0byB0aGF0IHN0YWdlLCBob3dldmVyLCB5b3UgbmVlZCB0byBidWlsZCBzb21lIGJhc2ljIGZsdWVuY3kgaW4gUi4gDQoNCiMjIyBTZXR1cA0KDQpSZW1lbWJlciB0byBhbHdheXMgc2V0IHlvdXIgd29ya2luZyBkaXJlY3RvcnkgdG8gdGhlIHNvdXJjZSBmaWxlIGxvY2F0aW9uLiBHbyB0byAnU2Vzc2lvbicsIHNjcm9sbCBkb3duIHRvICdTZXQgV29ya2luZyBEaXJlY3RvcnknLCBhbmQgY2xpY2sgJ1RvIFNvdXJjZSBGaWxlIExvY2F0aW9uJy4gUmVhZCBjYXJlZnVsbHkgdGhlIGJlbG93IGFuZCBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyB0byBjb21wbGV0ZSB0aGUgdGFza3MgYW5kIGFuc3dlciBhbnkgcXVlc3Rpb25zLiAgU3VibWl0IHlvdXIgd29yayBpbiBTYWthaSBhcyBkZXRhaWxlZCBpbiBwcmV2aW91cyBub3Rlcy4gDQoNCiMjIyBOb3RlDQoNCkZvciB5b3VyIGFzc2lnbm1lbnQgeW91IG1heSBiZSB1c2luZyBkaWZmZXJlbnQgZGF0YSBzZXRzIHRoYW4gd2hhdCBpcyBpbmNsdWRlZCBoZXJlLiBBbHdheXMgcmVhZCBjYXJlZnVsbHkgdGhlIGluc3RydWN0aW9ucyBwcm92aWRlZCwgYmVmb3JlIGV4ZWN1dGluZyBhbnkgaW5jbHVkZWQgY29kZSBjaHVua3MgYW5kL29yIGFkZGluZyB5b3VyIG93biBjb2RlLiAgRm9yIGNsYXJpdHksIHRhc2tzL3F1ZXN0aW9ucyB0byBiZSBjb21wbGV0ZWQvYW5zd2VyZWQgYXJlIGhpZ2hsaWdodGVkIGluIHJlZCBjb2xvciBhbmQgbnVtYmVyZWQgYWNjb3JkaW5nIHRvIHRoZWlyIHBhcnRpY3VsYXIgcGxhY2VtZW50IGluIHRoZSB0YXNrIHNlY3Rpb24uICBUaGUgcmVkIGNvbG9yIGlzIG9ubHkgYXBwYXJlbnQgd2hlbiBpbiBQcmV2aWV3IG1vZGUuIFF1aXRlIG9mdGVuIHlvdSB3aWxsIG5lZWQgdG8gYWRkIHlvdXIgb3duIGNvZGUgY2h1bmsuDQoNCnhlY3V0ZSBhbGwgY29kZSBjaHVua3MgKGFscmVhZHkgaW5jbHVkZWQgYW5kIG93biBhZGRlZCksIHByZXZpZXcsIGNoZWNrIGludGVncml0eSwgYW5kIHN1Ym1pdCBmaW5hbCB3b3JrICgkaHRtbCQgZmlsZSkgaW4gU2FrYWkuDQoNCi0tLS0tLS0tLS0NCg0KIVtdKGltZzAxLnBuZykNCg0KDQojIEJhc2ljcyBPcGVyYXRpb25zIA0KRmlyc3Qgd2Ugd2lsbCBiZWdpbiB3aXRoIGEgZmV3IGJhc2ljIG9wZXJhdGlvbnMuIA0KDQojIyBWYXJpYWJsZSBhc3NpZ25tZW50DQpXZSBhc3NpZ24gdmFsdWVzIHRvIHZhcmlhYmxlcyB1c2luZyB0aGUgYXNzaWdubWVudCBvcGVyYXRvciAnPScuIEFub3RoZXIgZm9ybSBvZiBhc3NpZ25tZW50LCBtb3JlIGdlbmVyYWwsIGlzIHRoZSAnPC0nIG9wZXJhdG9yLiANCkEgdmFyaWFibGUgYWxsb3dzIHlvdSB0byBzdG9yZSB2YWx1ZXMgb3IgYW4gb2JqZWN0IChlLmcuIGEgZnVuY3Rpb24pLg0KDQpgYGB7cn0NCnggPSAxMjgNCnkgPSAxNg0KeiA8LSA1DQp2YXJzID0gYygyLDQsOCwxNiwzMikgIyBDcmVhdGVzIGEgdmVjdG9yIGxpc3QgdXNpbmcgdGhlIGdlbmVyaWMgY29tYmluZSBmdW5jdGlvbiAnYycgDQpgYGANCg0KYGBge3J9DQp4ICMgZGlzcGxheSB2YWx1ZSBvZiB2YXJpYWJsZSB4DQp6ICMgZGlzcGxheXMgdmFsdWUgb2YgdmFyaWFibGUgeg0KYGBgDQoNCmBgYHtyfQ0KdmFyc1sxXSAjVGhpcyBjYWxscyB0aGUgZmlyc3QgdmFsdWUgaW4gdGhlIHZlY3RvciB2YXJzDQpgYGANCg0KYGBge3J9DQp2YXJzWzJdICNUaGlzIGNhbGxzIHRoZSBzZWNvbmQgdmFsdWUgaW4gdGhlIHZlY3RvciB2YXJzDQpgYGANCg0KYGBge3J9DQp2YXJzWzE6M10gI1RoaXMgY2FsbHMgdGhlIGZpcnN0IHRocm91Z2ggdGhpcmQgdmFsdWVzIGluIHRoZSB2ZWN0b3IgdmFycw0KYGBgDQoNCmBgYHtyfQ0KdmFycyAjVGhpcyBjYWxscyB0aGUgdmVjdG9yIGxpc3QNCmBgYA0KDQojIyBDb21tb24gQXJpdGhtZXRpYyBPcGVyYXRpb25zDQpCZWxvdyBzaG93cyBzb21lIHNpbXBsZSBhcml0aG1ldGljIG9wZXJhdGlvbnMuDQpgYGB7cixldmFsPVRSVUV9DQoxMio2DQoxMjgvMTYNCjleMg0KYGBgDQoNCiMjIEJhc2ljIERhdGEgVHlwZXMNClIgd29ya3Mgd2l0aCBudW1lcm91cyBkYXRhIHR5cGVzLiBTb21lIG9mIHRoZSBtb3N0IGJhc2ljIHR5cGVzIGFyZTogbnVtZXJpYyxpbnRlZ2VycywgbG9naWNhbCAoQm9vbGVhbi1gVFJVRS9GQUxTRWApIGFuZCBjaGFyYWN0ZXJzIChzdHJpbmctYCJURVhUImApLg0KDQpgYGB7cixldmFsPVRSVUV9DQojVHlwZTogQ2hhcmFjdGVyICAgICAgICAgICAgICAgICAgIA0KI0V4YW1wbGU6IlRSVUUiLCcyMy40Jw0KDQp2ID0gIlRSVUUiICAgICAgICAgICAgICAgICAgICAgICANCmNsYXNzKHYpICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiNUeXBlOiBOdW1lcmljICAgICAgICAgICAgICAgIA0KI0V4YW1wbGU6IDEyLjMsNQ0KDQp2ID0gMjMuNSAgICAgICAgICAgICAgICAgIA0KY2xhc3ModikgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgIA0KI1R5cGU6IExvZ2ljYWwgICAgDQojRXhhbXBsZTogVFJVRSxGQUxTRQ0KDQp2ID0gVFJVRQ0KY2xhc3ModikNCg0KI1R5cGU6IEZhY3RvciAobm9taW5hbCwgY2F0ZWdvcmljYWwpDQojRXhhbXBsZTogbSBmIG0gZiBtDQoNCnYgPSBhcy5mYWN0b3IoYygibSIsICJmIiwgIm0iKSkNCmNsYXNzKHYpDQpgYGANCg0KIyMgIEZ1bmN0aW9ucw0KDQpSIEZ1bmN0aW9ucyBhcmUgaW52b2tlZCBieSBpdHMgbmFtZSwgZm9sbG93ZWQgYnkgdGhlIHBhcmVudGhlc2lzLCBhbmQgemVybyBvciBtb3JlIGFyZ3VtZW50cy4gDQpgYGB7cn0NCiMgVGhlIGZvbGxvd2luZyBhcHBsaWVzIHRoZSBmdW5jdGlvbiAnYycgKHNlZW4gZWFybGllcikgdG8gY29tYmluZSB0aHJlZSBudW1lcmljIHZhbHVlcyBpbnRvIGEgdmVjdG9yIA0KYygxLDIsMykNCg0KIyBFeGFtcGxlIG9mIGZ1bmN0aW9uIG1lYW4oKSB0byBjYWxjdWxlIHRoZSBtZWFuIG9mIHRocmVlIHZhbHVlcw0KbWVhbihjKDUsNiw3KSkNCg0KIyBTcXVhcmUgcm9vdCBvZiBhIG51bWJlcg0Kc3FydCg5OSkNCmBgYA0KDQojIyBJbXBvcnRpbmcgRGF0YSBhbmQgVmFyaWFibGUgQXNzaWdubWVudA0KDQpgYGB7cixldmFsPVRSVUV9DQojIEhlcmUgd2UgYXJlIHJlYWRpbmcgYSBmaWxlIG9mIHR5cGUgY3N2IChjb21tYSBzZXBlcmF0ZWQgdmFsdWVzKSB0eXBpY2FsIG9mIG1hbnkgRXhjZWwgZmlsZXMNCmlsX2luY29tZSA9IHJlYWQuY3N2KGZpbGUgPSAiaWxfaW5jb21lLmNzdiIpDQp0b3BfaWxfaW5jb21lID0gcmVhZC5jc3YoZmlsZSA9ICJ0b3BfaWxfaW5jb21lLmNzdiIpDQpgYGANCg0KDQojIyBBcml0aG1ldGljIE9wZXJhdGlvbnMgd2l0aCBEYXRhDQoNCldlIGNhbiBleHRyYWN0IHZhbHVlcyBmcm9tIHRoZSBkYXRhc2V0IHRvIHBlcmZvcm0gY2FsY3VsYXRpb25zLg0KYGBge3IsZXZhbD1UUlVFfQ0KRHVQYWdlID0gdG9wX2lsX2luY29tZSRwZXJfY2FwaXRhX2luY29tZVsxXQ0KTGFrZSA9IHRvcF9pbF9pbmNvbWUkcGVyX2NhcGl0YV9pbmNvbWVbMl0NCkR1UGFnZS1MYWtlDQpEdVBhZ2UrTGFrZQ0KKER1UGFnZStMYWtlKS8yDQpgYGANCmBgYHtyLGV2YWw9VFJVRX0NCk1jSGVucnkgPSB0b3BfaWxfaW5jb21lJHBlcl9jYXBpdGFfaW5jb21lWzNdDQpTYW5nYW1vbiA9IHRvcF9pbF9pbmNvbWUkcGVyX2NhcGl0YV9pbmNvbWVbMTBdDQpNY0hlbnJ5LVNhbmdhbW9uDQpNY0hlbnJ5K1NhbmdhbW9uDQooTWNIZW5yeStTYW5nYW1vbikvMg0KYGBgDQoNCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPg0KIyMjIyMgMSkgUmVwZWF0IGhlcmUgdGhlIGFib3ZlIGFyaXRobWV0aWMgb3BlcmF0aW9ucyBjb2RlIGNodW5rIHVzaW5nIGluc3RlYWQgdGhlIGNvbHVtbnMgZm9yIE1jSGVucnkgYW5kIFNhbmdhbW9uIGNvdW50aWVzICg0cHRzKQ0KPC9zcGFuPg0KDQoNCiMjIEJhc2ljIFN0YXRpc3RpY3MNCg0KYGBge3IsZXZhbD1UUlVFfQ0KbWVhbihpbF9pbmNvbWUkcGVyX2NhcGl0YV9pbmNvbWUpDQptZWRpYW4oaWxfaW5jb21lJHBlcl9jYXBpdGFfaW5jb21lKQ0KcXVhbnRpbGUoaWxfaW5jb21lJHBlcl9jYXBpdGFfaW5jb21lKQ0KIyBTdW1tYXJ5IA0Kc3VtbWFyeShpbF9pbmNvbWUpDQpgYGANCmBgYHtyLGV2YWw9VFJVRX0NCm1lYW4odG9wX2lsX2luY29tZSRwZXJfY2FwaXRhX2luY29tZSkNCm1lZGlhbih0b3BfaWxfaW5jb21lJHBlcl9jYXBpdGFfaW5jb21lKQ0KcXVhbnRpbGUodG9wX2lsX2luY29tZSRwZXJfY2FwaXRhX2luY29tZSkNCiMgU3VtbWFyeSANCnN1bW1hcnkodG9wX2lsX2luY29tZSkNCmBgYA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDIpIFJlcGVhdCBoZXJlIHRoZSBhYm92ZSBiYXNpYyBzdGF0aXN0aWNzIGNvZGUgY2h1bmsgdXNpbmcgaW5zdGVhZCB0aGUgZGF0YSBmcm9tIHRoZSBmaWxlIHRvcF9pbF9pbmNvbWUgKDRwdHMpDQo8L3NwYW4+DQoNCiMgVmVjdG9ycw0KDQojIyBEZWZpbmluZyBhIFZlY3Rvcg0KDQpBIHNlcXVlbmNlIG9mIGRhdGEgZWxlbWVudHMgb2YgdGhlIHNhbWUgYmFzaWMgdHlwZSBpcyBkZWZpbmVkIGFzIGEgdmVjdG9yLg0KYGBge3IsZXZhbD1UUlVFfQ0KIyB2ZWN0b3Igb2YgbnVtZXJpYyB2YWx1ZXMNCmMoMiwgMywgNSwgOCkNCg0KIyB2ZWN0b3Igb2YgbG9naWNhbCB2YWx1ZXMuDQpjKFRSVUUsIEZBTFNFLCBUUlVFKQ0KDQojIHZlY3RvciBvZiBjaGFyYWN0ZXIgc3RyaW5ncy4NCmMoIkEiLCAiQiIsICJCLSIsICJDIiwgIkQiKQ0KYGBgDQoNCiMgTGlzdHMNCg0KIyMgRGVmaW5pbmcgYSBMaXN0DQoNCkxpc3RzLCBhcyBvcHBvc2VkIHRvIHZlY3RvcnMsIGNhbiBob2xkIGNvbXBvbmVudHMgb2YgZGlmZmVyZW50IHR5cGVzLg0KDQpgYGB7cixldmFsPVRSVUV9DQpzY29yZXMgPSBjKDgwLCA3NSwgNTUpICAjIHZlY3RvciBvZiBudW1lcmljIHZhbHVlcyAgICAgICAgICAgICAgICAgICANCmdyYWRlcyA9IGMoIkIiLCAiQyIsICJELSIpICAjIHZlY3RvciBvZiBjaGFyYWN0ZXIgc3RyaW5ncy4gICAgICAgICAgDQoNCm9mZmljZV9ob3VycyA9IGMoVFJVRSwgRkFMU0UsIEZBTFNFKSAjIHZlY3RvciBvZiBsb2dpY2FsIHZhbHVlcy4NCnN0dWRlbnQgPSBsaXN0KHNjb3JlcyxncmFkZXMsb2ZmaWNlX2hvdXJzKSAjIGxpc3Qgb2YgdmVjdG9ycw0Kc3R1ZGVudA0KYGBgDQoNCiMjIExpc3QgU2xpY2luZyANCg0KV2UgY2FuIHJldHJpZXZlIGNvbXBvbmVudHMgb2YgdGhlIGxpc3Qgd2l0aCB0aGUgc2luZ2xlIHNxdWFyZSBicmFja2V0IGBbXWAgb3BlcmF0b3IuDQoNCg0KYGBge3IsZXZhbD1UUlVFfQ0Kc3R1ZGVudFsxXSAgICAgDQpzdHVkZW50WzJdDQpzdHVkZW50WzNdDQoNCiMgZmlyc3QgdHdvIGNvbXBvbmVudHMgb2YgdGhlIGxpc3QNCnN0dWRlbnRbMToyXQ0KYGBgDQoNCiMjIE1lbWJlciBSZWZlcmVuY2UNCg0KVXNpbmcgdGhlIGRvdWJsZSBzcXVhcmUgYnJhY2tldCBgW1tdXWAgb3BlcmF0b3Igd2UgY2FuIHJlZmVyZW5jZSBhIG1lbWJlciBvZiB0aGUgbGlzdCBkaXJlY3RseS4gVXNpbmcgb25lIGJyYWNrZXQgW10gd291bGQgc3RpbGwgcmVmZXJlbmNlIHRoZSBsaXN0IGJ1dCB3aWxsIG5vdCBhbGxvdyB5b3UgdG8gZXh0cmFjdCBhIHBhcnRpY3VsYXIgbWVtYmVyIG9mIHRoZSBsaXN0Lg0KDQpgYGB7cixldmFsPVRSVUV9DQpzdHVkZW50W1sxXV0gIyBDb21wb25lbnRzIG9mIHRoZSBTY29yZXMgVmVjdG9yDQpgYGANCg0KKkZpcnN0IGVsZW1lbnQgb2YgdGhlIFNjb3JlcyB2ZWN0b3IqDQoNCmBgYHtyLGV2YWw9VFJVRX0NCnN0dWRlbnRbWzFdXVsxXQ0KYGBgDQoNCg0KKkZpcnN0IHRocmVlIGVsZW1lbnRzIG9mIHRoZSBTY29yZXMgdmVjdG9yKg0KDQpgYGB7cixldmFsPVRSVUV9DQpzdHVkZW50W1sxXV1bMTozXQ0KYGBgDQpgYGB7cixldmFsPVRSVUV9DQpzdHVkZW50W1syXV1bMl0NCmBgYA0KYGBge3J9DQpncmFkZXNbMl0NCmBgYA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDMpIFJlcGVhdCBoZXJlIHRoZSBhYm92ZSBjb2RlIGNodW5rIHRvIGV4dHJhY3QgaW5zdGVhZCB0aGUgc2Vjb25kIGVsZW1lbnQgb2YgdGhlIGdyYWRlcyB2ZWN0b3IgKDNwdHMpDQo8L3NwYW4+DQoNCiMjIE5hbWVkIExpc3QgTWVtYmVycw0KDQpJdCdzIHBvc3NpYmxlIHRvIGFzc2lnbiBuYW1lcyB0byBsaXN0IG1lbWJlcnMgYW5kIHJlZmVyZW5jZSB0aGVtIGJ5IG5hbWVzIGluc3RlYWQgb2YgYnkgbnVtZXJpYyBpbmRleGVzLg0KDQpgYGB7cixldmFsPVRSVUV9DQpzdHVkZW50ID0gbGlzdChteXNjb3JlcyA9IHNjb3JlcywgbXlncmFkZXMgPSBncmFkZXMgLCBteW9mZmljZV9ob3VycyA9IG9mZmljZV9ob3VycykgDQoNCnN0dWRlbnQNCnN0dWRlbnQkbXlzY29yZXMNCnN0dWRlbnQkbXlncmFkZXMNCnN0dWRlbnQkbXlvZmZpY2VfaG91cnMNCmBgYA0KDQojIE1hdHJpY2VzDQoNCkFsbCBjb2x1bW5zIGluIGEgbWF0cml4IG11c3QgaGF2ZSB0aGUgc2FtZSBkYXRhIHR5cGUgYW5kIHRoZSBzYW1lIGxlbmd0aC4NCg0KKkNyZWF0ZSBhIG51bWVyaWMgbWF0cml4IG9mIDUgcm93cyBhbmQgNCBjb2x1bW5zIG1hZGUgb2Ygc2VxdWVudGlhbCBudW1iZXJzIDE6MjAqDQpgYGB7cn0NCnhfbWF0ID0gbWF0cml4KDE6MjAsIG5yb3c9NSwgbmNvbD00KQ0KeF9tYXQNCmBgYA0KDQoqUmV0cmlldmUgdGhlIDR0aCBjb2x1bW4gb2YgbWF0cml4Kg0KYGBge3J9DQp4X21hdFssNF0NCmBgYA0KDQoNCipSZXRyaWV2ZSB0aGUgM3JkIHJvdyBvZiBtYXRyaXgqDQpgYGB7cn0NCnhfbWF0WzMsXQ0KYGBgDQoNCipSZXRyaWV2ZSByb3dzIDIsMyw0IG9mIGNvbHVtbnMgMSwyLDMqDQpgYGB7cn0NCnhfbWF0WzI6NCwxOjNdDQpgYGANCmBgYHtyfQ0KeF9tYXRbMywzXQ0KeF9tYXRbMyxdDQp4X21hdFssM10NCmBgYA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDQpIFJlcGVhdCBoZXJlIHRoZSBhYm92ZSBjb2RlIGNodW5rIHRvIGV4dHJhY3QgaW5zdGVhZCB0aGUgdGhpcmQgcm93IGFuZCB0aHJpZCBjb2x1bW4gb2YgdGhlIG1hdHJpeCAoM3B0cykNCjwvc3Bhbj4NCg0KDQojIERhdGEgRnJhbWVzDQoNCkEgZGF0YSBmcmFtZSBpcyBtb3JlIGdlbmVyYWwgdGhhbiBhIG1hdHJpeCwgaW4gdGhhdCBkaWZmZXJlbnQgY29sdW1ucyBjYW4gaGF2ZSBkaWZmZXJlbnQgZGF0YSB0eXBlcyAobnVtZXJpYywgY2hhcmFjdGVyLCBsb2dpYywgZmFjdG9yKS4gSXQgaXMgYSBwb3dlcmZ1bCB3YXkgdG8gd29yayB3aXRoIG1peGVkIGRhdGEgc3RydWN0dXJlcy4NCg0KIyMgRGVmaW5pbmcgYSBEYXRhIEZyYW1lDQoNCldoZW4gd2UgbmVlZCB0byBzdG9yZSBkYXRhIGluIHRhYmxlIGZvcm0sIHdlIHVzZSBkYXRhIGZyYW1lcywgd2hpY2ggYXJlIGNyZWF0ZWQgYnkgY29tYmluaW5nIGxpc3RzIG9mIHZlY3RvcnMgb2YgZXF1YWwgbGVuZ3RoLiBUaGUgdmFyaWFibGVzIG9mIGEgZGF0YSBzZXQgYXJlIHRoZSBjb2x1bW5zIGFuZCB0aGUgb2JzZXJ2YXRpb25zIGFyZSB0aGUgcm93cy4gDQoNCg0KVGhlIGBzdHIoKWAgZnVuY3Rpb24gaGVscHMgdXMgdG8gZGlzcGxheSB0aGUgaW50ZXJuYWwgc3RydWN0dXJlIG9mIGFueSBSIGRhdGEgc3RydWN0dXJlIG9yIG9iamVjdCB0byBtYWtlIHN1cmUgdGhhdCBpdCdzIGNvcnJlY3QuDQoNCg0KYGBge3IsZXZhbD1UUlVFfQ0Kc3RyKGlsX2luY29tZSkNCmBgYA0KDQojIyBDcmVhdGluZyBhIERhdGEgRnJhbWUNCg0KU25hcHNob3Qgb2YgdGhlIHNvbGFyIHN5c3RlbS4NCg0KYGBge3IsIGV2YWw9VFJVRX0NCm5hbWUgPSBjKCJFYXJ0aCIsICJNYXJzIiwgIkp1cGl0ZXIiKQ0KdHlwZSA9IGMoIlRlcnJlc3RyaWFsIiwiVGVycmVzdHJpYWwiLCAiR2FzIGdpYW50IikNCmRpYW1ldGVyID0gYygxLCAwLjUzMiwgMTEuMjA5KQ0Kcm90YXRpb24gPSBjKDEsIDEuMDMsIDAuNDEpDQpyaW5ncyA9IGMoRkFMU0UsIEZBTFNFLCBUUlVFKQ0KYGBgDQoNCk5vdywgYnkgY29tYmluaW5nIHRoZSB2ZWN0b3JzIG9mIGVxdWFsIHNpemUsIHdlIGNhbiBjcmVhdGUgYSBkYXRhIGZyYW1lIG9iamVjdC4NCg0KYGBge3IsIGV2YWw9VFJVRX0NCnBsYW5ldHNfZGYgPSBkYXRhLmZyYW1lKG5hbWUsdHlwZSxkaWFtZXRlcixyb3RhdGlvbixyaW5ncykNCnBsYW5ldHNfZGYNCg0KYGBgDQoNCiMjIFNlbnRpbWVudCBBbmFseXNpcw0KDQpUaGlzIGlzIGFuIGFkZGVkIHNlY3Rpb24gZm9yIHRoZSBob25vcmVkIGNsYXNzIHNlY3Rpb24gb25seS4gIFRoZSBwdXJwb3NlIGlzIHRvIGNvbmR1Y3QgYSBzYW1wbGUgdGV4dCBhbmFseXNpcyBpbnZlc3RpZ2F0aW9uLCBhbmQgYXNzZXNzIHRoZSByZXN1bHRzLg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCg0KQW5kIHRoZXkgd2lzaGluJyBhbmQgd2lzaGluJyBhbmQgd2lzaGluJyBhbmQgd2lzaGluJw0KVGhleSB3aXNoaW4nIG9uIG1lLCB5dWgNCg0KW1ZlcnNlIDFdDQpJIGJlZW4gbW92aW4nIGNhbG0sIGRvbid0IHN0YXJ0IG5vIHRyb3VibGUgd2l0aCBtZQ0KVHJ5bmEga2VlcCBpdCBwZWFjZWZ1bCBpcyBhIHN0cnVnZ2xlIGZvciBtZQ0KRG9uJ3QgcHVsbCB1cCBhdCA2IEFNIHRvIGN1ZGRsZSB3aXRoIG1lDQpZb3Uga25vdyBob3cgSSBsaWtlIGl0IHdoZW4geW91IGxvdmluJyBvbiBtZQ0KSSBkb24ndCB3YW5uYSBkaWUgZm9yIHRoZW0gdG8gbWlzcyBtZQ0KWWVzLCBJIHNlZSB0aGUgdGhpbmdzIHRoYXQgdGhleSB3aXNoaW4nIG9uIG1lDQpIb3BlIEkgZ290IHNvbWUgYnJvdGhlcnMgdGhhdCBvdXRsaXZlIG1lDQpUaGV5IGdvbicgdGVsbCB0aGUgc3RvcnksIHNoaXQgd2FzIGRpZmZlcmVudCB3aXRoIG1lDQoNCltDaG9ydXNdDQpHb2QncyBwbGFuLCBHb2QncyBwbGFuDQpJIGhvbGQgYmFjaywgc29tZXRpbWVzIEkgd29uJ3QsIHl1aA0KSSBmZWVsIGdvb2QsIHNvbWV0aW1lcyBJIGRvbid0LCBheXksIGRvbid0DQpJIGZpbmVzc2VkIGRvd24gV2VzdG9uIFJvYWQsIGF5eSwgJ25lc3NlZA0KTWlnaHQgZ28gZG93biBhIEcuTy5ELiwgeWVhaCwgd2FpdA0KSSBnbyBoYXJkIG9uIFNvdXRoc2lkZSBHLCB5dWgsIHdhaXQNCkkgbWFrZSBzdXJlIHRoYXQgbm9ydGgtc2lkZSBlYXQNCg0KW1Bvc3QtQ2hvcnVzXQ0KQW5kIHN0aWxsLCBiYWQgdGhpbmdzDQpJdCdzIGEgbG90IG9mIGJhZCB0aGluZ3MNClRoYXQgdGhleSB3aXNoaW4nIGFuZCB3aXNoaW4nIGFuZCB3aXNoaW4nIGFuZCB3aXNoaW4nDQpUaGV5IHdpc2hpbicgb24gbWUNCkJhZCB0aGluZ3MNCkl0J3MgYSBsb3Qgb2YgYmFkIHRoaW5ncw0KVGhhdCB0aGV5IHdpc2hpbicgYW5kIHdpc2hpbicgYW5kIHdpc2hpbicgYW5kIHdpc2hpbicNClRoZXkgd2lzaGluJyBvbiBtZQ0KWXVoLCBheXksIGF5eQ0KDQoNCkkgYW5hbHl6ZWQgYSByYXAgc29uZyBieSBEcmFrZSwgYW5kIHRoZSBzb25nIGlzIGFib3V0IG92ZXJjb21pbmcgc3RydWdnbGVzIGJlY2F1c2UgaXQncyAiR29kJ3MgUGxhbi4iIFRoZSBzZW50aW1lbnQgaGFkIGEgbG90IG9mIG5lZ2F0aXZlIHZhbHVlcyBmb3Igd29yZHMgbGlrZSBzdHJ1Z2dsZSwgdHJvdWJsZSwgYW5kIHRoZSBwcm9mYWluIHdvcmRzLiAgT3ZlcmFsbCwgdGhlIHZlcnNlcyBJIGlucHV0ZWQgaGFkIGEgc2NvcmUgb2YgMCwgbWVhbmluZyBuZWl0aGVyIGEgcG9zaXRpdmUgbm9yIG5lZ2F0aXZlIHJlc3VsdC4gVGhlIG1hZ2luaXR1ZGUgb2YgdGhlIHdvcmRzIGFuYWx5emVkIHdlcmUgbm90IHZlcnkgc3Ryb25nLCB3aXRoIHRoZSBoaWdoZXN0IGJlaW5nIDIuMi4gTW9zdCBvZiB0aGUgd29yZHMgd2VyZSBhcm91bmQgLjUsIG1lYW5pbmcgdGhlIHN0cmVuZ3RoIG9mIHRoZSBzZW50aW1lbnQgd2FzIG5vdCB2ZXJ5IHN0cm9uZy4gDQoNClNlbGVjdCBhIHNtYWxsIHRleHQgYXJ0aWNsZSAoMTAgdG8gMjAgbGluZXMpIGZyb20gYW4gb25saW5lIHNvdXJjZSBvZiB5b3VyIGNob2ljZSBhbmQgYSB0b3BpYyBvZiB5b3VyIGludGVyZXN0LiAgWW91IGNhbiBhbHNvIG1ha2UgdXAgeW91ciBvd24gdGV4dC4gQ29weSBhbmQgcGFzdGUgdGhlIHBhcmFncmFwaCBoZXJlLiAgVXNlIHRoZSBHb29nbGUgQ2xvdWQgTkxQIEFQSSBkZW1vIGF0IGh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9uYXR1cmFsLWxhbmd1YWdlLyB0byBwYXN0ZSB5b3VyIHRleHQgaW4gdGhlIGFwcHJvcHJpYXRlIHNwYWNlLCBhbmQgcnVuIGEgc2VudGltZW50IGFuYWx5c2lzLiAgV2l0aG91dCBkaXZpbmcgbXVjaCBpbnRvIHRoZSBhbmFseXRpY3MgYW5kIHRoZSBjb2RpbmcgZGV0YWlscyBiZWhpbmQgdGhlIEFQSSwgd3JpdGUgYSBoYWxmIHBhcmFncmFwaCBzdW1tYXJpemluZyB5b3VyIGFzc2Vzc21lbnQgb2YgdGhlIHNlbnRpbWVudCBhbmFseXNpcyByZXN1bHRzIGFzIGdpdmVuIGJ5IEdvb2dsZSBOTFAuIFlvdSBwcm9iYWJseSB3YW50IHRvIGludmVzdGlnYXRlIHRoZSBtZWFuaW5nIG9mICRzY29yZSQgYW5kICRtYWduaXR1ZGUkIGluIHRoZSByZXN1bHRzIGRpc3BsYXllZCBieSBHb29nbGUgKDZwdHMpDQo8L3NwYW4+DQoNCiMgU3VnZ2VzdGVkIEV4ZXJjaXNlcyAmIFJlc291cmNlcw0KDQojIyBFeGVyY2lzZXMNCg0KKiBEYXRhY2FtcCAtIExlYXJuIERhdGEgU2NpZW5jZSBmcm9tIHlvdXIgYnJvd3NlcjogDQpodHRwczovL3d3dy5kYXRhY2FtcC5jb20vY291cnNlcy9mcmVlLWludHJvZHVjdGlvbi10by1yDQoNCiogUi10dXRvciAtIEFuIFIgaW50cm8gdG8gc3RhdHMgdGhhdCBleHBsYWlucyBiYXNpYyBSIGNvbmNlcHRzOg0KaHR0cDovL3d3dy5yLXR1dG9yLmNvbS9yLWludHJvZHVjdGlvbg0KDQojIyBEYXRhIFNvdXJjZXMNCkRhdGEgc2FtcGxlcyB1c2VkIGluIHRoaXMgd29ya3NoZWV0IHdlcmUgZG93bmxvYWRlZCBmcm9tIHRoZSBVLlMuIENlbnN1cyBCdXJlYXUgQW1lcmljYW4gRmFjdEZpbmRlciBzaXRlLg0KDQoqICJTRUxFQ1RFRCBFQ09OT01JQyBDSEFSQUNURVJJU1RJQ1MgMjAwNi0yMDEwIEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgNS1ZZWFyIEVzdGltYXRlcyIgLSBVLlMuIENlbnN1cyBCdXJlYXUuIFJldHJpZXZlZCAyMDE2LTA5LTA5Og0KaHR0cHM6Ly9mYWN0ZmluZGVyLmNlbnN1cy5nb3YvZmFjZXMvbmF2L2pzZi9wYWdlcy9pbmRleC54aHRtbA0K