First Steps with R Basic calculations You can use R for basic computations you would perform in a calculator

# Addition
2-3
[1] -1
4+5
[1] 9
# Division
2/3
[1] 0.6666667
5/2
[1] 2.5
# Exponentiation
2^3 
[1] 8
3^3
[1] 27
# Square root
sqrt(2)
[1] 1.414214
sqrt(16)
[1] 4
# Logarithms
log(2)
[1] 0.6931472
log10(10)
[1] 1
log10(100)
[1] 2
#Question_1: Compute the log base 5 of 10 and the log of 10.
log(10, base = 5)
[1] 1.430677
log(10)
[1] 2.302585

Computing some offensive metrics in Baseball

#Batting Average=(No. of Hits)/(No. of At Bats)
#What is the batting average of a player that bats 29 hits in 112 at bats?

BA=(29)/(112)
BA
[1] 0.2589286
Batting_Average=round(BA,digits = 3)
Batting_Average
[1] 0.259

Question_2:What is the batting average of a player that bats 42 hits in 212 at bats?

#On Base Percentage
#OBP=(H+BB+HBP)/(At Bats+H+BB+HBP+SF)
#Let us compute the OBP for a player with the following general stats
#AB=515,H=172,BB=84,HBP=5,SF=6
OBP=(172+84+5)/(515+172+84+5+6)
OBP
[1] 0.3337596
BA=(42)/(212)
BA
[1] 0.1981132
#
On_Base_Average=round(BA,digits = 3)
On_Base_Average
[1] 0.198
On_Base_Percentage=round(OBP,digits = 3)
On_Base_Percentage
[1] 0.334

Question_3:Compute the OBP for a player with the following general stats: #AB=565,H=156,BB=65,HBP=3,SF=7


#AB=565,H=156,BB=65,HBP=3,SF=7
OBP2=(156+65+3)/(565+156+65+3+7)
OBP2
[1] 0.281407

Often you will want to test whether something is less than, greater than or equal to something.

3 == 8# Does 3 equals 8?
[1] FALSE
3 != 8# Is 3 different from 8?
[1] TRUE
3 <= 8# Is 3 less than or equal to 8?
[1] TRUE

The logical operators are & for logical AND, | for logical OR, and ! for NOT. These are some examples:

# Logical Disjunction (or)
FALSE | FALSE # False OR False
[1] FALSE
# Logical Conjunction (and)
TRUE & FALSE #True AND False
[1] FALSE
# Negation
! FALSE # Not False
[1] TRUE
# Combination of statements
2 < 3 | 1 == 5 # 2<3 is True, 1==5 is False, True OR False is True
[1] TRUE

Assigning Values to Variables In R, you create a variable and assign it a value using <- as follows

Total_Bases <- 6 + 5
Total_Bases*3
[1] 33

To see the variables that are currently defined, use ls (as in “list”)

ls()
 [1] "allcontracts"               "BA"                         "Batting_Average"           
 [4] "con"                        "contract_length"            "contract_years"            
 [7] "contracts_mean"             "contracts_median"           "contracts_n"               
[10] "contracts_sd"               "contracts_w1sd"             "contracts_w2sd"            
[13] "contracts_w3sd"             "hits_per_9innings"          "HR_before"                 
[16] "JSn_seasons"                "n_1"                        "n_2"                       
[19] "n_3"                        "n_4"                        "n_seasons"                 
[22] "OBP"                        "OBP2"                       "On_Base_Average"           
[25] "On_Base_Average_Percentage" "On_Base_Percentage"         "pitches_by_innings"        
[28] "Robert_HRs"                 "runs_per_9innings"          "salary_ave"                
[31] "salary_ave_bask_nfl"        "strikes_by_innings"         "Total_Bases"               
[34] "Walks_before"               "wanted_HR"                  "wanted_walks"              
[37] "x_4"                        "x_6"                        "y_1"                       
[40] "y_2"                        "y_3"                        "y_4"                       

To delete a variable, use rm (as in “remove”)

rm(Total_Bases)
ls()
 [1] "allcontracts"               "BA"                         "Batting_Average"           
 [4] "con"                        "contract_length"            "contract_years"            
 [7] "contracts_mean"             "contracts_median"           "contracts_n"               
[10] "contracts_sd"               "contracts_w1sd"             "contracts_w2sd"            
[13] "contracts_w3sd"             "hits_per_9innings"          "HR_before"                 
[16] "JSn_seasons"                "n_1"                        "n_2"                       
[19] "n_3"                        "n_4"                        "n_seasons"                 
[22] "OBP"                        "OBP2"                       "On_Base_Average"           
[25] "On_Base_Average_Percentage" "On_Base_Percentage"         "pitches_by_innings"        
[28] "Robert_HRs"                 "runs_per_9innings"          "salary_ave"                
[31] "salary_ave_bask_nfl"        "strikes_by_innings"         "Walks_before"              
[34] "wanted_HR"                  "wanted_walks"               "x_4"                       
[37] "x_6"                        "y_1"                        "y_2"                       
[40] "y_3"                        "y_4"                       

Either <- or = can be used to assign a value to a variable, but I prefer <- because is less likely to be confused with the logical operator ==

Vectors The basic type of object in R is a vector, which is an ordered list of values of the same type. You can create a vector using the c() function (as in “concatenate”).

pitches_by_innings <- c(12, 15, 10, 20, 10) 
pitches_by_innings
[1] 12 15 10 20 10
strikes_by_innings <- c(9, 12, 6, 14, 9)
strikes_by_innings
[1]  9 12  6 14  9

Question_4: Define two vectors,runs_per_9innings and hits_per_9innings, each with five elements.

runs_per_9innings <- c(0, 1, 0, 3, 0)
runs_per_9innings
[1] 0 1 0 3 0
hits_per_9innings <- c(5, 0, 0, 1, 2)
hits_per_9innings
[1] 5 0 0 1 2

There are also some functions that will create vectors with regular patterns, like repeated elements.

# replicate function
rep(2, 5)
[1] 2 2 2 2 2
# consecutive numbers
1:5
[1] 1 2 3 4 5
# sequence from 1 to 10 with a step of 2
seq(1, 10, by=2)
[1] 1 3 5 7 9

Many functions and operators like + or - will work on all elements of the vector.

# add vectors
pitches_by_innings
[1] 12 15 10 20 10
strikes_by_innings
[1]  9 12  6 14  9
pitches_by_innings+strikes_by_innings
[1] 21 27 16 34 19
# compare vectors
pitches_by_innings == strikes_by_innings
[1] FALSE FALSE FALSE FALSE FALSE
# find length of vector
length(pitches_by_innings)
[1] 5
# find minimum value in vector
min(pitches_by_innings)
[1] 10
# find average value in vector
mean(pitches_by_innings)
[1] 13.4

You can access parts of a vector by using [. Recall what the value is of the vector pitches_by_innings.

pitches_by_innings
[1] 12 15 10 20 10
# If you want to get the first element:
pitches_by_innings[1]
[1] 12

Question_5: Get the first element of hits_per_9innings.

hits_per_9innings
[1] 5 0 0 1 2
hits_per_9innings[1]
[1] 5

If you want to get the last element of pitches_by_innings without explicitly typing the number of elements of pitches_by_innings, make use of the length function, which calculates the length of a vector:

pitches_by_innings[length(pitches_by_innings)]
[1] 10

Question_6: Get the last element of hits_per_9innings.

hits_per_9innings
[1] 5 0 0 1 2
hits_per_9innings[length(hits_per_9innings)]
[1] 2

You can also extract multiple values from a vector. For instance to get the 2nd through 4th values use

pitches_by_innings[c(2, 3, 4)]
[1] 15 10 20

Vectors can also be strings or logical values

player_positions <- c("catcher", "pitcher", "infielders", "outfielders")
player_positions
[1] "catcher"     "pitcher"     "infielders"  "outfielders"

Data Frames In statistical applications, data is often stored as a data frame, which is like a spreadsheet, with rows as observations and columns as variables.

To manually create a data frame, use the data.frame() function.

data.frame(bonus = c(2, 3, 1),#in millions 
           active_roster = c("yes", "no", "yes"), 
           salary = c(1.5, 2.5, 1))#in millions 

Most often you will be using data frames loaded from a file. For example, load the results of a fan’s survey. The function load or read.table can be used for this.

How to Make a Random Sample To randomly select a sample use the function sample(). The following code selects 5 numbers between 1 and 10 at random (without duplication)

sample(1:10, size=5)
[1] 2 8 7 9 3

The first argument gives the vector of data to select elements from. The second argument (size=) gives the size of the sample to select. Taking a simple random sample from a data frame is only slightly more complicated, having two steps:

Use sample() to select a sample of size n from a vector of the row numbers of the data frame. Use the index operator [ to select those rows from the data frame. Consider the following example with fake data. First, make up a data frame with two columns. (LETTERS is a character vector of length 26 with capital letters A to Z; LETTERS is automatically defined and pre-loaded in R)

bar <- data.frame(var1 = LETTERS[1:10], var2 = 1:10)
# Check data frame
bar

Suppose you want to select a random sample of size 5. First, define a variable n with the size of the sample, i.e. 5

n <- 5

Now, select a sample of size 5 from the vector with 1 to 10 (the number of rows in bar). Use the function nrow() to find the number of rows in bar instead of manually entering that number.

Use : to create a vector with all the integers between 1 and the number of rows in bar.

samplerows <- sample(1:nrow(bar), size=n) 
# print sample rows
samplerows
[1] 10  2  6  4  8

The variable samplerows contains the rows of bar which make a random sample from all the rows in bar. Extract those rows from bar with

# extract rows
barsample <- bar[samplerows, ]
# print sample
print(barsample)

The code above creates a new data frame called barsample with a random sample of rows from bar.

In a single line of code:

bar[sample(1:nrow(bar), n), ]

Using Tables The table() command allows us to look at tables. Its simplest usage looks like table(x) where x is a categorical variable.

For example, a survey asks people if they support the home team or not. The data is

Yes, No, No, Yes, Yes

We can enter this into R with the c() command, and summarize with the table() command as follows

x <- c("Yes","No","No","Yes","Yes") 
table(x)
x
 No Yes 
  2   3 

Numerical measures of center and spread Suppose, MLB Teams’ CEOs yearly compensations are sampled and the following are found (in millions)

12 .4 5 2 50 8 3 1 4 0.25

sals <- c(12, .4, 5, 2, 50, 8, 3, 1, 4, 0.25)
# the average
mean(sals) 
[1] 8.565
# the variance
var(sals)
[1] 225.5145
# the standard deviation
sd(sals)
[1] 15.01714
# the median
median(sals)
[1] 3.5
# Tukey's five number summary, usefull for boxplots
# five numbers: min, lower hinge, median, upper hinge, max
fivenum(sals)
[1]  0.25  1.00  3.50  8.00 50.00
# summary statistics
summary(sals)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.250   1.250   3.500   8.565   7.250  50.000 

How about the mode? In R we can write our own functions, and a first example of a function is shown below in order to compute the mode of a vector of observations x

# Function to find the mode, i.e. most frequent value
getMode <- function(x) {
     ux <- unique(x)
     ux[which.max(tabulate(match(x, ux)))]
 }

As an example, we can use the function defined above to find the most frequent value of the number of pitches_by_innings

# Most frequent value in baz

pitches_by_innings
[1] 12 15 10 20 10
getMode(pitches_by_innings)
[1] 10

Question_7: Find the most frequent value of hits_per_9innings.

hits_per_9innings
[1] 5 0 0 1 2
getMode(hits_per_9innings)
[1] 0

Question_8: Summarize the following survey with the table() command: What is your favorite day of the week to watch baseball? A total of 10 fans submitted this survey. Saturday, Saturday, Sunday, Monday, Saturday,Tuesday, Sunday, Friday, Friday, Monday

survey <- c("Saturday","Saturday","Sunday","Monday","Saturday","Tuesday","Sunday","Friday","Friday","Monday")
summary_table <-table(survey)
summary_table
survey
  Friday   Monday Saturday   Sunday  Tuesday 
       2        2        3        2        1 
favorite_day <- names(summary_table[summary_table==max(summary_table)])
favorite_day
[1] "Saturday"

Question_9: What is the most frequent answer recorded in the survey? Use the getMode function to compute results.

frequent_answer <- getMode(survey)
frequent_answer
[1] "Saturday"
LS0tDQp0aXRsZTogIkluLWNsYXNzIGFjdGl2aXR5ICM0KEhXKTogSW50cm9kdWN0aW9uIHRvIFIgZm9yIFNwb3J0cyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCl9fRmlyc3QgU3RlcHMgd2l0aCBSDQpCYXNpYyBjYWxjdWxhdGlvbnNfXw0KWW91IGNhbiB1c2UgUiBmb3IgYmFzaWMgY29tcHV0YXRpb25zIHlvdSB3b3VsZCBwZXJmb3JtIGluIGEgY2FsY3VsYXRvcg0KDQoNCmBgYHtyfQ0KIyBBZGRpdGlvbg0KMi0zDQo0KzUNCmBgYA0KDQpgYGB7cn0NCiMgRGl2aXNpb24NCjIvMw0KNS8yDQpgYGANCg0KDQpgYGB7cn0NCiMgRXhwb25lbnRpYXRpb24NCjJeMyANCjNeMw0KYGBgDQoNCmBgYHtyfQ0KIyBTcXVhcmUgcm9vdA0Kc3FydCgyKQ0Kc3FydCgxNikNCmBgYA0KYGBge3J9DQojIExvZ2FyaXRobXMNCmxvZygyKQ0KbG9nMTAoMTApDQpsb2cxMCgxMDApDQpgYGANCg0KYGBge3J9DQojUXVlc3Rpb25fMTogQ29tcHV0ZSB0aGUgbG9nIGJhc2UgNSBvZiAxMCBhbmQgdGhlIGxvZyBvZiAxMC4NCmxvZygxMCwgYmFzZSA9IDUpDQpsb2coMTApDQpgYGANCl9fQ29tcHV0aW5nIHNvbWUgb2ZmZW5zaXZlIG1ldHJpY3MgaW4gQmFzZWJhbGxfXw0KDQpgYGB7cn0NCiNCYXR0aW5nIEF2ZXJhZ2U9KE5vLiBvZiBIaXRzKS8oTm8uIG9mIEF0IEJhdHMpDQojV2hhdCBpcyB0aGUgYmF0dGluZyBhdmVyYWdlIG9mIGEgcGxheWVyIHRoYXQgYmF0cyAyOSBoaXRzIGluIDExMiBhdCBiYXRzPw0KDQpCQT0oMjkpLygxMTIpDQpCQQ0KYGBgDQpgYGB7cn0NCkJhdHRpbmdfQXZlcmFnZT1yb3VuZChCQSxkaWdpdHMgPSAzKQ0KQmF0dGluZ19BdmVyYWdlDQpgYGANCl9fUXVlc3Rpb25fMl9fOldoYXQgaXMgdGhlIGJhdHRpbmcgYXZlcmFnZSBvZiBhIHBsYXllciB0aGF0IGJhdHMgNDIgaGl0cyBpbiAyMTIgYXQgYmF0cz8NCg0KYGBge3J9DQojT24gQmFzZSBQZXJjZW50YWdlDQojT0JQPShIK0JCK0hCUCkvKEF0IEJhdHMrSCtCQitIQlArU0YpDQojTGV0IHVzIGNvbXB1dGUgdGhlIE9CUCBmb3IgYSBwbGF5ZXIgd2l0aCB0aGUgZm9sbG93aW5nIGdlbmVyYWwgc3RhdHMNCiNBQj01MTUsSD0xNzIsQkI9ODQsSEJQPTUsU0Y9Ng0KT0JQPSgxNzIrODQrNSkvKDUxNSsxNzIrODQrNSs2KQ0KT0JQDQpCQT0oNDIpLygyMTIpDQpCQQ0KIw0KT25fQmFzZV9BdmVyYWdlPXJvdW5kKEJBLGRpZ2l0cyA9IDMpDQpPbl9CYXNlX0F2ZXJhZ2UNCmBgYA0KDQpgYGB7cn0NCk9uX0Jhc2VfUGVyY2VudGFnZT1yb3VuZChPQlAsZGlnaXRzID0gMykNCk9uX0Jhc2VfUGVyY2VudGFnZQ0KYGBgDQpfX1F1ZXN0aW9uXzNfXzpDb21wdXRlIHRoZSBPQlAgZm9yIGEgcGxheWVyIHdpdGggdGhlIGZvbGxvd2luZyBnZW5lcmFsIHN0YXRzOiAjQUI9NTY1LEg9MTU2LEJCPTY1LEhCUD0zLFNGPTcNCg0KYGBge3J9DQoNCiNBQj01NjUsSD0xNTYsQkI9NjUsSEJQPTMsU0Y9Nw0KT0JQMj0oMTU2KzY1KzMpLyg1NjUrMTU2KzY1KzMrNykNCk9CUDINCmBgYA0KDQpPZnRlbiB5b3Ugd2lsbCB3YW50IHRvIHRlc3Qgd2hldGhlciBzb21ldGhpbmcgaXMgbGVzcyB0aGFuLCBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gc29tZXRoaW5nLg0KDQpgYGB7cn0NCjMgPT0gOCMgRG9lcyAzIGVxdWFscyA4Pw0KYGBgDQoNCmBgYHtyfQ0KMyAhPSA4IyBJcyAzIGRpZmZlcmVudCBmcm9tIDg/DQpgYGANCg0KYGBge3J9DQozIDw9IDgjIElzIDMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDg/DQpgYGANClRoZSBsb2dpY2FsIG9wZXJhdG9ycyBhcmUgJiBmb3IgbG9naWNhbCBBTkQsIHwgZm9yIGxvZ2ljYWwgT1IsIGFuZCAhIGZvciBOT1QuIFRoZXNlIGFyZSBzb21lIGV4YW1wbGVzOg0KDQpgYGB7cn0NCiMgTG9naWNhbCBEaXNqdW5jdGlvbiAob3IpDQpGQUxTRSB8IEZBTFNFICMgRmFsc2UgT1IgRmFsc2UNCmBgYA0KDQpgYGB7cn0NCiMgTG9naWNhbCBDb25qdW5jdGlvbiAoYW5kKQ0KVFJVRSAmIEZBTFNFICNUcnVlIEFORCBGYWxzZQ0KYGBgDQoNCg0KYGBge3J9DQojIE5lZ2F0aW9uDQohIEZBTFNFICMgTm90IEZhbHNlDQpgYGANCg0KYGBge3J9DQojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMNCjIgPCAzIHwgMSA9PSA1ICMgMjwzIGlzIFRydWUsIDE9PTUgaXMgRmFsc2UsIFRydWUgT1IgRmFsc2UgaXMgVHJ1ZQ0KYGBgDQpfX0Fzc2lnbmluZyBWYWx1ZXMgdG8gVmFyaWFibGVzX18NCkluIFIsIHlvdSBjcmVhdGUgYSB2YXJpYWJsZSBhbmQgYXNzaWduIGl0IGEgdmFsdWUgdXNpbmcgPC0gYXMgZm9sbG93cw0KDQoNCmBgYHtyfQ0KVG90YWxfQmFzZXMgPC0gNiArIDUNClRvdGFsX0Jhc2VzKjMNCmBgYA0KVG8gc2VlIHRoZSB2YXJpYWJsZXMgdGhhdCBhcmUgY3VycmVudGx5IGRlZmluZWQsIHVzZSBscyAoYXMgaW4g4oCcbGlzdOKAnSkNCg0KDQpgYGB7cn0NCmxzKCkNCmBgYA0KDQpUbyBkZWxldGUgYSB2YXJpYWJsZSwgdXNlIHJtIChhcyBpbiDigJxyZW1vdmXigJ0pDQoNCmBgYHtyfQ0Kcm0oVG90YWxfQmFzZXMpDQpgYGANCg0KYGBge3J9DQpscygpDQpgYGANCg0KDQpFaXRoZXIgPC0gb3IgPSBjYW4gYmUgdXNlZCB0byBhc3NpZ24gYSB2YWx1ZSB0byBhIHZhcmlhYmxlLCBidXQgSSBwcmVmZXIgPC0gYmVjYXVzZSBpcyBsZXNzIGxpa2VseSB0byBiZSBjb25mdXNlZCB3aXRoIHRoZSBsb2dpY2FsIG9wZXJhdG9yID09DQoNCl9fX1ZlY3RvcnNfX18NClRoZSBiYXNpYyB0eXBlIG9mIG9iamVjdCBpbiBSIGlzIGEgdmVjdG9yLCB3aGljaCBpcyBhbiBvcmRlcmVkIGxpc3Qgb2YgdmFsdWVzIG9mIHRoZSBzYW1lIHR5cGUuIFlvdSBjYW4gY3JlYXRlIGEgdmVjdG9yIHVzaW5nIHRoZSBjKCkgZnVuY3Rpb24gKGFzIGluIOKAnGNvbmNhdGVuYXRl4oCdKS4NCg0KDQpgYGB7cn0NCnBpdGNoZXNfYnlfaW5uaW5ncyA8LSBjKDEyLCAxNSwgMTAsIDIwLCAxMCkgDQpwaXRjaGVzX2J5X2lubmluZ3MNCmBgYA0KDQpgYGB7cn0NCnN0cmlrZXNfYnlfaW5uaW5ncyA8LSBjKDksIDEyLCA2LCAxNCwgOSkNCnN0cmlrZXNfYnlfaW5uaW5ncw0KYGBgDQoNCl9fUXVlc3Rpb25fNF9fOiBEZWZpbmUgdHdvIHZlY3RvcnMscnVuc19wZXJfOWlubmluZ3MgYW5kIGhpdHNfcGVyXzlpbm5pbmdzLCBlYWNoIHdpdGggZml2ZSBlbGVtZW50cy4gDQoNCmBgYHtyfQ0KcnVuc19wZXJfOWlubmluZ3MgPC0gYygwLCAxLCAwLCAzLCAwKQ0KcnVuc19wZXJfOWlubmluZ3MNCmhpdHNfcGVyXzlpbm5pbmdzIDwtIGMoNSwgMCwgMCwgMSwgMikNCmhpdHNfcGVyXzlpbm5pbmdzDQoNCmBgYA0KDQpUaGVyZSBhcmUgYWxzbyBzb21lIGZ1bmN0aW9ucyB0aGF0IHdpbGwgY3JlYXRlIHZlY3RvcnMgd2l0aCByZWd1bGFyIHBhdHRlcm5zLCBsaWtlIHJlcGVhdGVkIGVsZW1lbnRzLg0KDQpgYGB7cn0NCiMgcmVwbGljYXRlIGZ1bmN0aW9uDQpyZXAoMiwgNSkNCmBgYA0KDQpgYGB7cn0NCiMgY29uc2VjdXRpdmUgbnVtYmVycw0KMTo1DQpgYGANCg0KYGBge3J9DQojIHNlcXVlbmNlIGZyb20gMSB0byAxMCB3aXRoIGEgc3RlcCBvZiAyDQpzZXEoMSwgMTAsIGJ5PTIpDQpgYGANCg0KTWFueSBmdW5jdGlvbnMgYW5kIG9wZXJhdG9ycyBsaWtlICsgb3IgLSB3aWxsIHdvcmsgb24gYWxsIGVsZW1lbnRzIG9mIHRoZSB2ZWN0b3IuDQoNCg0KYGBge3J9DQojIGFkZCB2ZWN0b3JzDQpwaXRjaGVzX2J5X2lubmluZ3MNCnN0cmlrZXNfYnlfaW5uaW5ncw0KcGl0Y2hlc19ieV9pbm5pbmdzK3N0cmlrZXNfYnlfaW5uaW5ncw0KDQpgYGANCg0KYGBge3J9DQojIGNvbXBhcmUgdmVjdG9ycw0KcGl0Y2hlc19ieV9pbm5pbmdzID09IHN0cmlrZXNfYnlfaW5uaW5ncw0KYGBgDQoNCmBgYHtyfQ0KIyBmaW5kIGxlbmd0aCBvZiB2ZWN0b3INCmxlbmd0aChwaXRjaGVzX2J5X2lubmluZ3MpDQpgYGANCg0KYGBge3J9DQojIGZpbmQgbWluaW11bSB2YWx1ZSBpbiB2ZWN0b3IgLSBpbiB0aGUgY2FzZSBvZiB0aGUgNSBpbm5pbmdzIGdhbWUNCm1pbihwaXRjaGVzX2J5X2lubmluZ3MpDQpgYGANCg0KYGBge3J9DQojIGZpbmQgYXZlcmFnZSB2YWx1ZSBpbiB2ZWN0b3ItIHRoZSBhdmVyYWdlIHBpdGNoZXMgaW4gdGhlIGdhbWUNCm1lYW4ocGl0Y2hlc19ieV9pbm5pbmdzKQ0KYGBgDQoNCllvdSBjYW4gYWNjZXNzIHBhcnRzIG9mIGEgdmVjdG9yIGJ5IHVzaW5nIFsuIFJlY2FsbCB3aGF0IHRoZSB2YWx1ZSBpcyBvZiB0aGUgdmVjdG9yIHBpdGNoZXNfYnlfaW5uaW5ncy4NCg0KYGBge3J9DQpwaXRjaGVzX2J5X2lubmluZ3MNCmBgYA0KDQpgYGB7cn0NCiMgSWYgeW91IHdhbnQgdG8gZ2V0IHRoZSBmaXJzdCBlbGVtZW50Og0KcGl0Y2hlc19ieV9pbm5pbmdzWzFdDQpgYGANCg0KX19RdWVzdGlvbl81X186IEdldCB0aGUgZmlyc3QgZWxlbWVudCBvZiBoaXRzX3Blcl85aW5uaW5ncy4NCg0KYGBge3J9DQpoaXRzX3Blcl85aW5uaW5ncw0KaGl0c19wZXJfOWlubmluZ3NbMV0NCmBgYA0KSWYgeW91IHdhbnQgdG8gZ2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgcGl0Y2hlc19ieV9pbm5pbmdzIHdpdGhvdXQgZXhwbGljaXRseSB0eXBpbmcgdGhlIG51bWJlciBvZiBlbGVtZW50cyBvZiBwaXRjaGVzX2J5X2lubmluZ3MsIG1ha2UgdXNlIG9mIHRoZSBsZW5ndGggZnVuY3Rpb24sIHdoaWNoIGNhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlY3RvcjoNCg0KYGBge3J9DQpwaXRjaGVzX2J5X2lubmluZ3NbbGVuZ3RoKHBpdGNoZXNfYnlfaW5uaW5ncyldDQpgYGANCg0KX19RdWVzdGlvbl82X186IEdldCB0aGUgbGFzdCBlbGVtZW50IG9mIGhpdHNfcGVyXzlpbm5pbmdzLg0KDQpgYGB7cn0NCmhpdHNfcGVyXzlpbm5pbmdzDQpoaXRzX3Blcl85aW5uaW5nc1tsZW5ndGgoaGl0c19wZXJfOWlubmluZ3MpXQ0KYGBgDQoNCllvdSBjYW4gYWxzbyBleHRyYWN0IG11bHRpcGxlIHZhbHVlcyBmcm9tIGEgdmVjdG9yLiBGb3IgaW5zdGFuY2UgdG8gZ2V0IHRoZSAybmQgdGhyb3VnaCA0dGggdmFsdWVzIHVzZQ0KDQpgYGB7cn0NCnBpdGNoZXNfYnlfaW5uaW5nc1tjKDIsIDMsIDQpXQ0KYGBgDQoNClZlY3RvcnMgY2FuIGFsc28gYmUgc3RyaW5ncyBvciBsb2dpY2FsIHZhbHVlcw0KDQpgYGB7cn0NCnBsYXllcl9wb3NpdGlvbnMgPC0gYygiY2F0Y2hlciIsICJwaXRjaGVyIiwgImluZmllbGRlcnMiLCAib3V0ZmllbGRlcnMiKQ0KcGxheWVyX3Bvc2l0aW9ucw0KYGBgDQoNCl9fX0RhdGEgRnJhbWVzX19fDQpJbiBzdGF0aXN0aWNhbCBhcHBsaWNhdGlvbnMsIGRhdGEgaXMgb2Z0ZW4gc3RvcmVkIGFzIGEgZGF0YSBmcmFtZSwgd2hpY2ggaXMgbGlrZSBhIHNwcmVhZHNoZWV0LCB3aXRoIHJvd3MgYXMgb2JzZXJ2YXRpb25zIGFuZCBjb2x1bW5zIGFzIHZhcmlhYmxlcy4NCg0KVG8gbWFudWFsbHkgY3JlYXRlIGEgZGF0YSBmcmFtZSwgdXNlIHRoZSBkYXRhLmZyYW1lKCkgZnVuY3Rpb24uDQoNCg0KYGBge3J9DQpkYXRhLmZyYW1lKGJvbnVzID0gYygyLCAzLCAxKSwjaW4gbWlsbGlvbnMgDQogICAgICAgICAgIGFjdGl2ZV9yb3N0ZXIgPSBjKCJ5ZXMiLCAibm8iLCAieWVzIiksIA0KICAgICAgICAgICBzYWxhcnkgPSBjKDEuNSwgMi41LCAxKSkjaW4gbWlsbGlvbnMgDQpgYGANCg0KTW9zdCBvZnRlbiB5b3Ugd2lsbCBiZSB1c2luZyBkYXRhIGZyYW1lcyBsb2FkZWQgZnJvbSBhIGZpbGUuIEZvciBleGFtcGxlLCBsb2FkIHRoZSByZXN1bHRzIG9mIGEgZmFu4oCZcyBzdXJ2ZXkuIFRoZSBmdW5jdGlvbiBsb2FkIG9yIHJlYWQudGFibGUgY2FuIGJlIHVzZWQgZm9yIHRoaXMuDQoNCl9fX0hvdyB0byBNYWtlIGEgUmFuZG9tIFNhbXBsZV9fXw0KVG8gcmFuZG9tbHkgc2VsZWN0IGEgc2FtcGxlIHVzZSB0aGUgZnVuY3Rpb24gc2FtcGxlKCkuIFRoZSBmb2xsb3dpbmcgY29kZSBzZWxlY3RzIDUgbnVtYmVycyBiZXR3ZWVuIDEgYW5kIDEwIGF0IHJhbmRvbSAod2l0aG91dCBkdXBsaWNhdGlvbikNCg0KYGBge3J9DQpzYW1wbGUoMToxMCwgc2l6ZT01KQ0KYGBgDQoNClRoZSBmaXJzdCBhcmd1bWVudCBnaXZlcyB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gc2VsZWN0IGVsZW1lbnRzIGZyb20uDQpUaGUgc2Vjb25kIGFyZ3VtZW50IChzaXplPSkgZ2l2ZXMgdGhlIHNpemUgb2YgdGhlIHNhbXBsZSB0byBzZWxlY3QuDQpUYWtpbmcgYSBzaW1wbGUgcmFuZG9tIHNhbXBsZSBmcm9tIGEgZGF0YSBmcmFtZSBpcyBvbmx5IHNsaWdodGx5IG1vcmUgY29tcGxpY2F0ZWQsIGhhdmluZyB0d28gc3RlcHM6DQoNClVzZSBzYW1wbGUoKSB0byBzZWxlY3QgYSBzYW1wbGUgb2Ygc2l6ZSBuIGZyb20gYSB2ZWN0b3Igb2YgdGhlIHJvdyBudW1iZXJzIG9mIHRoZSBkYXRhIGZyYW1lLg0KVXNlIHRoZSBpbmRleCBvcGVyYXRvciBbIHRvIHNlbGVjdCB0aG9zZSByb3dzIGZyb20gdGhlIGRhdGEgZnJhbWUuDQpDb25zaWRlciB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2l0aCBmYWtlIGRhdGEuIEZpcnN0LCBtYWtlIHVwIGEgZGF0YSBmcmFtZSB3aXRoIHR3byBjb2x1bW5zLiAoTEVUVEVSUyBpcyBhIGNoYXJhY3RlciB2ZWN0b3Igb2YgbGVuZ3RoIDI2IHdpdGggY2FwaXRhbCBsZXR0ZXJzIEEgdG8gWjsgTEVUVEVSUyBpcyBhdXRvbWF0aWNhbGx5IGRlZmluZWQgYW5kIHByZS1sb2FkZWQgaW4gUikNCg0KYGBge3J9DQpiYXIgPC0gZGF0YS5mcmFtZSh2YXIxID0gTEVUVEVSU1sxOjEwXSwgdmFyMiA9IDE6MTApDQojIENoZWNrIGRhdGEgZnJhbWUNCmJhcg0KYGBgDQoNClN1cHBvc2UgeW91IHdhbnQgdG8gc2VsZWN0IGEgcmFuZG9tIHNhbXBsZSBvZiBzaXplIDUuIEZpcnN0LCBkZWZpbmUgYSB2YXJpYWJsZSBuIHdpdGggdGhlIHNpemUgb2YgdGhlIHNhbXBsZSwgaS5lLiA1DQoNCmBgYHtyfQ0KbiA8LSA1DQpgYGANCg0KTm93LCBzZWxlY3QgYSBzYW1wbGUgb2Ygc2l6ZSA1IGZyb20gdGhlIHZlY3RvciB3aXRoIDEgdG8gMTAgKHRoZSBudW1iZXIgb2Ygcm93cyBpbiBiYXIpLiBVc2UgdGhlIGZ1bmN0aW9uIG5yb3coKSB0byBmaW5kIHRoZSBudW1iZXIgb2Ygcm93cyBpbiBiYXIgaW5zdGVhZCBvZiBtYW51YWxseSBlbnRlcmluZyB0aGF0IG51bWJlci4NCg0KVXNlIDogdG8gY3JlYXRlIGEgdmVjdG9yIHdpdGggYWxsIHRoZSBpbnRlZ2VycyBiZXR3ZWVuIDEgYW5kIHRoZSBudW1iZXIgb2Ygcm93cyBpbiBiYXIuDQoNCmBgYHtyfQ0Kc2FtcGxlcm93cyA8LSBzYW1wbGUoMTpucm93KGJhciksIHNpemU9bikgDQojIHByaW50IHNhbXBsZSByb3dzDQpzYW1wbGVyb3dzDQpgYGANClRoZSB2YXJpYWJsZSBzYW1wbGVyb3dzIGNvbnRhaW5zIHRoZSByb3dzIG9mIGJhciB3aGljaCBtYWtlIGEgcmFuZG9tIHNhbXBsZSBmcm9tIGFsbCB0aGUgcm93cyBpbiBiYXIuIEV4dHJhY3QgdGhvc2Ugcm93cyBmcm9tIGJhciB3aXRoDQoNCmBgYHtyfQ0KIyBleHRyYWN0IHJvd3MNCmJhcnNhbXBsZSA8LSBiYXJbc2FtcGxlcm93cywgXQ0KIyBwcmludCBzYW1wbGUNCnByaW50KGJhcnNhbXBsZSkNCmBgYA0KDQpUaGUgY29kZSBhYm92ZSBjcmVhdGVzIGEgbmV3IGRhdGEgZnJhbWUgY2FsbGVkIGJhcnNhbXBsZSB3aXRoIGEgcmFuZG9tIHNhbXBsZSBvZiByb3dzIGZyb20gYmFyLg0KDQpJbiBhIHNpbmdsZSBsaW5lIG9mIGNvZGU6DQoNCg0KYGBge3J9DQpiYXJbc2FtcGxlKDE6bnJvdyhiYXIpLCBuKSwgXQ0KYGBgDQoNCl9fX1VzaW5nIFRhYmxlc19fXw0KVGhlIHRhYmxlKCkgY29tbWFuZCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0YWJsZXMuIEl0cyBzaW1wbGVzdCB1c2FnZSBsb29rcyBsaWtlIHRhYmxlKHgpIHdoZXJlIHggaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZS4NCg0KRm9yIGV4YW1wbGUsIGEgc3VydmV5IGFza3MgcGVvcGxlIGlmIHRoZXkgc3VwcG9ydCB0aGUgaG9tZSB0ZWFtIG9yIG5vdC4gVGhlIGRhdGEgaXMNCg0KWWVzLCBObywgTm8sIFllcywgWWVzDQoNCldlIGNhbiBlbnRlciB0aGlzIGludG8gUiB3aXRoIHRoZSBjKCkgY29tbWFuZCwgYW5kIHN1bW1hcml6ZSB3aXRoIHRoZSB0YWJsZSgpIGNvbW1hbmQgYXMgZm9sbG93cw0KDQpgYGB7cn0NCnggPC0gYygiWWVzIiwiTm8iLCJObyIsIlllcyIsIlllcyIpIA0KdGFibGUoeCkNCmBgYA0KDQpfX19OdW1lcmljYWwgbWVhc3VyZXMgb2YgY2VudGVyIGFuZCBzcHJlYWRfX18NClN1cHBvc2UsIE1MQiBUZWFtc+KAmSBDRU9zIHllYXJseSBjb21wZW5zYXRpb25zIGFyZSBzYW1wbGVkIGFuZCB0aGUgZm9sbG93aW5nIGFyZSBmb3VuZCAoaW4gbWlsbGlvbnMpDQoNCjEyIC40IDUgMiA1MCA4IDMgMSA0IDAuMjUNCg0KDQpgYGB7cn0NCnNhbHMgPC0gYygxMiwgLjQsIDUsIDIsIDUwLCA4LCAzLCAxLCA0LCAwLjI1KQ0KIyB0aGUgYXZlcmFnZQ0KbWVhbihzYWxzKSANCmBgYA0KDQpgYGB7cn0NCiMgdGhlIHZhcmlhbmNlDQp2YXIoc2FscykNCmBgYA0KDQpgYGB7cn0NCiMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbg0Kc2Qoc2FscykNCmBgYA0KDQpgYGB7cn0NCiMgdGhlIG1lZGlhbg0KbWVkaWFuKHNhbHMpDQpgYGANCg0KYGBge3J9DQojIFR1a2V5J3MgZml2ZSBudW1iZXIgc3VtbWFyeSwgdXNlZnVsbCBmb3IgYm94cGxvdHMNCiMgZml2ZSBudW1iZXJzOiBtaW4sIGxvd2VyIGhpbmdlLCBtZWRpYW4sIHVwcGVyIGhpbmdlLCBtYXgNCmZpdmVudW0oc2FscykNCmBgYA0KDQpgYGB7cn0NCiMgc3VtbWFyeSBzdGF0aXN0aWNzDQpzdW1tYXJ5KHNhbHMpDQpgYGANCg0KX19Ib3cgYWJvdXQgdGhlIG1vZGU/X18NCkluIFIgd2UgY2FuIHdyaXRlIG91ciBvd24gZnVuY3Rpb25zLCBhbmQgYSBmaXJzdCBleGFtcGxlIG9mIGEgZnVuY3Rpb24gaXMgc2hvd24gYmVsb3cgaW4gb3JkZXIgdG8gY29tcHV0ZSB0aGUgbW9kZSBvZiBhIHZlY3RvciBvZiBvYnNlcnZhdGlvbnMgeA0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gZmluZCB0aGUgbW9kZSwgaS5lLiBtb3N0IGZyZXF1ZW50IHZhbHVlDQpnZXRNb2RlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICAgdXggPC0gdW5pcXVlKHgpDQogICAgIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0NCiB9DQpgYGANCg0KDQpBcyBhbiBleGFtcGxlLCB3ZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBkZWZpbmVkIGFib3ZlIHRvIGZpbmQgdGhlIG1vc3QgZnJlcXVlbnQgdmFsdWUgb2YgdGhlIG51bWJlciBvZiBwaXRjaGVzX2J5X2lubmluZ3MNCg0KDQpgYGB7cn0NCiMgTW9zdCBmcmVxdWVudCB2YWx1ZSBpbiBiYXoNCg0KcGl0Y2hlc19ieV9pbm5pbmdzDQpnZXRNb2RlKHBpdGNoZXNfYnlfaW5uaW5ncykNCmBgYA0KDQoNCl9fUXVlc3Rpb25fN19fOiBGaW5kIHRoZSBtb3N0IGZyZXF1ZW50IHZhbHVlIG9mIGhpdHNfcGVyXzlpbm5pbmdzLg0KDQpgYGB7cn0NCmhpdHNfcGVyXzlpbm5pbmdzDQpnZXRNb2RlKGhpdHNfcGVyXzlpbm5pbmdzKQ0KYGBgDQpfX1F1ZXN0aW9uXzhfXzogU3VtbWFyaXplIHRoZSBmb2xsb3dpbmcgc3VydmV5IHdpdGggdGhlIGB0YWJsZSgpYCBjb21tYW5kOg0KV2hhdCBpcyB5b3VyIGZhdm9yaXRlIGRheSBvZiB0aGUgd2VlayB0byB3YXRjaCBiYXNlYmFsbD8gQSB0b3RhbCBvZiAxMCBmYW5zIHN1Ym1pdHRlZCB0aGlzIHN1cnZleS4NClNhdHVyZGF5LCBTYXR1cmRheSwgU3VuZGF5LCBNb25kYXksIFNhdHVyZGF5LFR1ZXNkYXksIFN1bmRheSwgRnJpZGF5LCBGcmlkYXksIE1vbmRheQ0KDQpgYGB7cn0NCnN1cnZleSA8LSBjKCJTYXR1cmRheSIsIlNhdHVyZGF5IiwiU3VuZGF5IiwiTW9uZGF5IiwiU2F0dXJkYXkiLCJUdWVzZGF5IiwiU3VuZGF5IiwiRnJpZGF5IiwiRnJpZGF5IiwiTW9uZGF5IikNCnN1bW1hcnlfdGFibGUgPC10YWJsZShzdXJ2ZXkpDQpzdW1tYXJ5X3RhYmxlDQpmYXZvcml0ZV9kYXkgPC0gbmFtZXMoc3VtbWFyeV90YWJsZVtzdW1tYXJ5X3RhYmxlPT1tYXgoc3VtbWFyeV90YWJsZSldKQ0KZmF2b3JpdGVfZGF5DQpgYGANCg0KX19RdWVzdGlvbl85X186IFdoYXQgaXMgdGhlIG1vc3QgZnJlcXVlbnQgYW5zd2VyIHJlY29yZGVkIGluIHRoZSBzdXJ2ZXk/IFVzZSB0aGUgZ2V0TW9kZSBmdW5jdGlvbiB0byBjb21wdXRlIHJlc3VsdHMuIA0KDQpgYGB7cn0NCmZyZXF1ZW50X2Fuc3dlciA8LSBnZXRNb2RlKHN1cnZleSkNCmZyZXF1ZW50X2Fuc3dlcg0KYGBgDQoNCg==