About

This worksheet includes three main tasks on data outliers, data preparation, and data modeling. The lab requires the use of Microsoft Excel, R, and ERDplus.

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 to RPubs 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 on Sakai. For clarity, tasks/questions to be completed/answered are highlighted in red color (visible in preview) and numbered according to their particular placement in the task section. Quite often you will need to add your own code chunk.

Execute all code chunks, preview, publish, and submit link on Sakai.


Task 1: Data Outliers

First, we must calculate the mean, standard deviation, maximum, and minimum for the Age column using R.

In R, we must read in the file again, extract the column and find the values that are asked for.

#Read File
mydata = read.csv(file="data/creditrisk.csv") 

#Name the extracted variable
age = mydata$Age 

##### 1A) Fill in the code chunk below to calculate and display each result. Refer to previous worksheets and on-line help for some commands.

#Calculate the average age below. 
meanAge = mean(age)
meanAge
[1] 34.39765
#Calculate the standard deviation of age below. 

spreadAge = sd (age)
spreadage
[1] 11.04513
#Calculate the maxima of age below. Look in Help to find the right command for maxima

maxage = max(age)
maxage
[1] 73
#Calculate the minima of age below. Look in Help to find the right command for minima

minage = min(age)
minage
[1] 18

Next, we will use the formula from class to detect any outliers. An outlier is a value that “lies outside” most of the other values in a set of data. A common way to estimate the upper and lower limits is to take the mean (+ or -) 3 * standard deviation.

##### 1B) Write and execute the code chunk corresponding to the above formula to calculate the upper and lower limits for age. Display your results. Based on the limits do you think there are outliers? Explain your answer.

upperl = meanAge + 3*spreadage
upperl
[1] 67.53302
lowerl = meanAge - 3*spreadage
lowerl
[1] 1.262269
#Based on the result, it means that the upper limit is 67.53; while the lower limit is 1.26. If we compare that with the data, or at least, with the maxima and minima age data we have, we could say that there is no oulier below the lowe limit ( because the minima is 18) but that there is at least an outlier above the upper limit which will be the maxima of age because it is 73 (that is greater than the upper limit).

Another similar method to find the upper and lower thresholds, discussed in many introductory statistics courses, involves finding the interquartile range. Follow along below to see how we first calculate the interquartile range..

quantile(age) 
  0%  25%  50%  75% 100% 
  18   26   32   41   73 
lowerq = quantile(age)[2]
upperq = quantile(age)[4]
iqr = upperq - lowerq

Next we calculate the limiting thresholds. A threshold here is the boundary that determines if a value is an outlier. If the value falls above the upper threshold or below the lower threshold, it is an outlier.

To calculate the upper threshold:

upperthreshold = (iqr * 1.5) + upperq 
upperthreshold
 75% 
63.5 

Below is the lower threshold:

lowerthreshold = lowerq - (iqr * 1.5)
lowerthreshold
25% 
3.5 

A good way to undertsand the above calculations is to visualize the results using a box and whisker plot. The top and lower ends of the box correspond to the upper and lower quartiles. The median is marked by a bolded line. The whiskers are the lines connecting the upper and lower quartiles to upper and lower thresholds. Any points beyond the thresholds is a potential outlier.

boxplot(age) 

##### 1C) From the box plot representation are there any outliers? How many can you count? How does your answer reconcile with the result from Task 1B?

#Yes, there are outliers (the circles above the upperlimit - upperline). The outliers are only on the upper quartile. I can differentiate one for sure, which is the one I mentioned on question 1B, however, there are a few more. In total, there are 9 outliers according to the data (if you calculate the data greater than the upperlimit of the boxplot - 63.5 - by an "if" statement). Below the lowerlimit of the first quartile, there is not any outlier.  

Task 2: Data Preparation

Next, we will read the file creditriskorg.csv into R as provided in its original form. Unlike the cleaned file creditrisk.csv, the original dataset will require some data preparation.

newdata = read.csv(file="data/creditriskorg.csv")
head(newdata)

We observe a new line is inserted with the header labels X, X.1, ... and that the true column headers are shifted down. This is because of the empty line in the original dataset. To account for this detail we must skip one line when reading the file.

newdata = read.csv(file="data/creditriskorg.csv",skip=1) 
head(newdata)

Next we want to extract the Checking column and then find the average of checking, smilar to what we did in the previous lab. When we try to execute the code chunk below notice that we get an error.

checking = newdata$Checking #command to extract the Checking column from the data file newdata
mean(checking)
argument is not numeric or logical: returning NA
[1] NA

To resolve the error, we must understand first where it’s source. There are missing values in the csv file represented by the symbol $-. Missing data is quite common as most datasets are not perfect. Additionally, there are commas within the excel spreadsheet, and R does not recognize that ‘1,234’ is equivalent to ‘1234’. Lastly, there are ‘$’ symbols throughout the file which is not a numerical symbol either.

To correct for the error we need to do some data cleanup. For this we will use the sub function sub() in R to replace unwanted symbols with something else. For example, in order to remove the comma in the number “1,234”, we can substitute it with blank. Below is a sequence of commands to help with the cleanup of the data in the Checking column and eventual calculation of the mean.

#substitute comma with blank in all of checking  
checking= sub(",","",checking)

#substitute dollar sign with blank in all of checking 
# Example new = sub("\\$","",new)
checking = sub("\\$","",checking)

#Convert values to numeric. Any value that cannot be converted to numeric will be designated as NA (Not Applicable)
checking = as.numeric(checking)
NAs introduced by coercion
#Calculate mean of checking with all NAs removed 
mean(checking,na.rm=TRUE)
[1] 2559.805

##### 2A) Repeat the above commands to calculate the mean of the Savings column instead. Use a different variable naming.



Datos = read.csv(file="data/creditriskorg.csv",skip=1) 
head(Datos)
Savings = Datos$Savings

Savings = sub(",","",Savings)

Savings = sub("\\$","",Savings)

Savings = as.numeric(Savings)
NAs introduced by coercion
meanSavings = mean(Savings,na.rm=TRUE)

meanSavings
[1] 2122.146

##### 2B) Calculate now the mean of the Checking column in Excel using the Excel function Average. Compare the two results, from Excel and R and share your observation.

#The mean of the Checking column calculated in Excel is $2,559.8045977011500. The two values (Excel and Rstudio) are the same, therefore, my observation of this calculation is that Excel is treating the data the same way R does when we type the indications for the values. 
#Another observation is that the result in R is a bit rounded in comparison with Excel (Excel gives more decimals).

##### 2C) Based on your observation how did Excel treat the missing values represented by the symbol $-? Are they included in the calculation of the mean or excluded? Explain your answer.

#Excel treats the missing values represented by the symbol "$-" as blank spaces. So, they are excluded in the calculation of the mean. I know it because the result is the same as the one that you get in R after indicating to do it like that (to treat the values as numeric, substitute the $ for nothing, etc.)

#If Excel has treated the values on these cells differently, the result would be different. 

Task 3: Data Modeling

Here, we will look at Chicago Divvy bike data. The historical data sets with description of fields can be found at:

Chicago Divvy Data: https://www.divvybikes.com/data

###### 3A) Open in RStudio or Excel the file Divvy_Trips_2017_Q4.csv located in the data folder. What is the size of the file (measured in bytes), the number of columns and of rows?. Identify the column field(s) in the data that is/are unique identifier(s) (cannot have duplicate/repeated values)

#The size of the file is 83,930 KB. It has 12 columns and 669239 rows

#The column field that is a unique identifier is the trip_id.

Read carefully the file README.txt, located in same data folder, for the description of the data.

###### 3B) Define a relational business logic integrity rule for the column field Trip Duration.

#A relational business logic integrity rule for the field "Trip Duration" is between start_time and stop_time fields. The trip duration is the difference between stop time and start time, therefore, the time of the trip duration cannot exceed the difference between the stop and start time. For example, if the Trip Duration is 120 seconds, then the stop_time has to be two minutes after the time that is said in the start_time field.

###### 3C) Using https://erdplus.com/#/standalone draw a star like schema using the below three tables. Include an image capture of your schema here.

ERD diagram - Divvy Trips

ERD diagram - Divvy Trips

LS0tCnRpdGxlOiAiQlNBRDM0MyBGYWxsIDIwMTggTGFiIFdvcmtzaGVldCAwMyIKYXV0aG9yOiAiRWxlbmEgUMOpcmV6IFZlbGFzY28iCmRhdGU6ICI5LzI3LzIwMTgiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdApzdWJ0aXRsZTogRGF0YSBQcmVwYXJhdGlvbiAmIEZsb3cgKGJzYWQtbGFiMDMpCi0tLQoKIyMjIEFib3V0CgpUaGlzIHdvcmtzaGVldCBpbmNsdWRlcyB0aHJlZSBtYWluIHRhc2tzIG9uIGRhdGEgb3V0bGllcnMsIGRhdGEgcHJlcGFyYXRpb24sIGFuZCBkYXRhIG1vZGVsaW5nLiBUaGUgbGFiIHJlcXVpcmVzIHRoZSB1c2Ugb2YgTWljcm9zb2Z0IEV4Y2VsLCBSLCBhbmQgRVJEcGx1cy4KCiMjIyBTZXR1cAoKUmVtZW1iZXIgdG8gYWx3YXlzIHNldCB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IHRvIHRoZSBzb3VyY2UgZmlsZSBsb2NhdGlvbi4gR28gdG8gJ1Nlc3Npb24nLCBzY3JvbGwgZG93biB0byAnU2V0IFdvcmtpbmcgRGlyZWN0b3J5JywgYW5kIGNsaWNrICdUbyBTb3VyY2UgRmlsZSBMb2NhdGlvbicuIFJlYWQgY2FyZWZ1bGx5IHRoZSBiZWxvdyBhbmQgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgdG8gY29tcGxldGUgdGhlIHRhc2tzIGFuZCBhbnN3ZXIgYW55IHF1ZXN0aW9ucy4gIFN1Ym1pdCB5b3VyIHdvcmsgdG8gUlB1YnMgYXMgZGV0YWlsZWQgaW4gcHJldmlvdXMgbm90ZXMuIAoKIyMjIE5vdGUKCkZvciB5b3VyIGFzc2lnbm1lbnQgeW91IG1heSBiZSB1c2luZyBkaWZmZXJlbnQgZGF0YSBzZXRzIHRoYW4gd2hhdCBpcyBpbmNsdWRlZCBoZXJlLiBBbHdheXMgcmVhZCBjYXJlZnVsbHkgdGhlIGluc3RydWN0aW9ucyBvbiBTYWthaS4gIEZvciBjbGFyaXR5LCB0YXNrcy9xdWVzdGlvbnMgdG8gYmUgY29tcGxldGVkL2Fuc3dlcmVkIGFyZSBoaWdobGlnaHRlZCBpbiByZWQgY29sb3IgKHZpc2libGUgaW4gcHJldmlldykgYW5kIG51bWJlcmVkIGFjY29yZGluZyB0byB0aGVpciBwYXJ0aWN1bGFyIHBsYWNlbWVudCBpbiB0aGUgdGFzayBzZWN0aW9uLiAgUXVpdGUgb2Z0ZW4geW91IHdpbGwgbmVlZCB0byBhZGQgeW91ciBvd24gY29kZSBjaHVuay4KCkV4ZWN1dGUgYWxsIGNvZGUgY2h1bmtzLCBwcmV2aWV3LCBwdWJsaXNoLCBhbmQgc3VibWl0IGxpbmsgb24gU2FrYWkuCgotLS0tLS0tLS0tLS0tLQoKIyMjIFRhc2sgMTogRGF0YSBPdXRsaWVycwoKRmlyc3QsIHdlIG11c3QgY2FsY3VsYXRlIHRoZSBtZWFuLCBzdGFuZGFyZCBkZXZpYXRpb24sIG1heGltdW0sIGFuZCBtaW5pbXVtIGZvciB0aGUgQWdlIGNvbHVtbiB1c2luZyBSLgoKSW4gUiwgd2UgbXVzdCByZWFkIGluIHRoZSBmaWxlIGFnYWluLCBleHRyYWN0IHRoZSBjb2x1bW4gYW5kIGZpbmQgdGhlIHZhbHVlcyB0aGF0IGFyZSBhc2tlZCBmb3IuCgpgYGB7cn0KI1JlYWQgRmlsZQpteWRhdGEgPSByZWFkLmNzdihmaWxlPSJkYXRhL2NyZWRpdHJpc2suY3N2IikgCgojTmFtZSB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlCmFnZSA9IG15ZGF0YSRBZ2UgCgpgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAxQSkgRmlsbCBpbiB0aGUgY29kZSBjaHVuayBiZWxvdyB0byBjYWxjdWxhdGUgYW5kIGRpc3BsYXkgZWFjaCByZXN1bHQuICBSZWZlciB0byBwcmV2aW91cyB3b3Jrc2hlZXRzIGFuZCBvbi1saW5lIGhlbHAgZm9yIHNvbWUgY29tbWFuZHMuCjwvc3Bhbj4KCmBgYHtyfQojQ2FsY3VsYXRlIHRoZSBhdmVyYWdlIGFnZSBiZWxvdy4gCm1lYW5BZ2UgPSBtZWFuKGFnZSkKbWVhbkFnZQoKI0NhbGN1bGF0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGFnZSBiZWxvdy4gCgpzcHJlYWRBZ2UgPSBzZCAoYWdlKQpzcHJlYWRhZ2UKCiNDYWxjdWxhdGUgdGhlIG1heGltYSBvZiBhZ2UgYmVsb3cuIExvb2sgaW4gSGVscCB0byBmaW5kIHRoZSByaWdodCBjb21tYW5kIGZvciBtYXhpbWEKCm1heGFnZSA9IG1heChhZ2UpCm1heGFnZQoKI0NhbGN1bGF0ZSB0aGUgbWluaW1hIG9mIGFnZSBiZWxvdy4gTG9vayBpbiBIZWxwIHRvIGZpbmQgdGhlIHJpZ2h0IGNvbW1hbmQgZm9yIG1pbmltYQoKbWluYWdlID0gbWluKGFnZSkKbWluYWdlCmBgYAoKTmV4dCwgd2Ugd2lsbCB1c2UgdGhlIGZvcm11bGEgZnJvbSBjbGFzcyB0byBkZXRlY3QgYW55IG91dGxpZXJzLiBBbiBvdXRsaWVyIGlzIGEgdmFsdWUgdGhhdCAibGllcyBvdXRzaWRlIiBtb3N0IG9mIHRoZSBvdGhlciB2YWx1ZXMgaW4gYSBzZXQgb2YgZGF0YS4gQSBjb21tb24gd2F5IHRvIGVzdGltYXRlIHRoZSB1cHBlciBhbmQgbG93ZXIgbGltaXRzIGlzIHRvIHRha2UgdGhlIGBgYG1lYW4gKCsgb3IgLSkgMyAqIHN0YW5kYXJkIGRldmlhdGlvbmBgYC4gIAoKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAxQikgV3JpdGUgYW5kIGV4ZWN1dGUgdGhlIGNvZGUgY2h1bmsgY29ycmVzcG9uZGluZyB0byB0aGUgYWJvdmUgZm9ybXVsYSB0byBjYWxjdWxhdGUgdGhlIHVwcGVyIGFuZCBsb3dlciBsaW1pdHMgZm9yIGFnZS4gRGlzcGxheSB5b3VyIHJlc3VsdHMuIEJhc2VkIG9uIHRoZSBsaW1pdHMgZG8geW91IHRoaW5rIHRoZXJlIGFyZSBvdXRsaWVycz8gRXhwbGFpbiB5b3VyIGFuc3dlci4KPC9zcGFuPgpgYGB7cn0KdXBwZXJsID0gbWVhbkFnZSArIDMqc3ByZWFkYWdlCnVwcGVybApsb3dlcmwgPSBtZWFuQWdlIC0gMypzcHJlYWRhZ2UKbG93ZXJsCmBgYAoKCmBgYHtyfQojQmFzZWQgb24gdGhlIHJlc3VsdCwgaXQgbWVhbnMgdGhhdCB0aGUgdXBwZXIgbGltaXQgaXMgNjcuNTM7IHdoaWxlIHRoZSBsb3dlciBsaW1pdCBpcyAxLjI2LiBJZiB3ZSBjb21wYXJlIHRoYXQgd2l0aCB0aGUgZGF0YSwgb3IgYXQgbGVhc3QsIHdpdGggdGhlIG1heGltYSBhbmQgbWluaW1hIGFnZSBkYXRhIHdlIGhhdmUsIHdlIGNvdWxkIHNheSB0aGF0IHRoZXJlIGlzIG5vIG91bGllciBiZWxvdyB0aGUgbG93ZSBsaW1pdCAoIGJlY2F1c2UgdGhlIG1pbmltYSBpcyAxOCkgYnV0IHRoYXQgdGhlcmUgaXMgYXQgbGVhc3QgYW4gb3V0bGllciBhYm92ZSB0aGUgdXBwZXIgbGltaXQgd2hpY2ggd2lsbCBiZSB0aGUgbWF4aW1hIG9mIGFnZSBiZWNhdXNlIGl0IGlzIDczICh0aGF0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgdXBwZXIgbGltaXQpLgpgYGAKCkFub3RoZXIgc2ltaWxhciBtZXRob2QgdG8gZmluZCB0aGUgdXBwZXIgYW5kIGxvd2VyIHRocmVzaG9sZHMsIGRpc2N1c3NlZCBpbiBtYW55IGludHJvZHVjdG9yeSBzdGF0aXN0aWNzIGNvdXJzZXMsIGludm9sdmVzIGZpbmRpbmcgdGhlIGludGVycXVhcnRpbGUgcmFuZ2UuIEZvbGxvdyBhbG9uZyBiZWxvdyB0byBzZWUgaG93IHdlIGZpcnN0IGNhbGN1bGF0ZSB0aGUgaW50ZXJxdWFydGlsZSByYW5nZS4uIAoKYGBge3J9IApxdWFudGlsZShhZ2UpIApsb3dlcnEgPSBxdWFudGlsZShhZ2UpWzJdCnVwcGVycSA9IHF1YW50aWxlKGFnZSlbNF0KaXFyID0gdXBwZXJxIC0gbG93ZXJxCmBgYAoKTmV4dCB3ZSBjYWxjdWxhdGUgdGhlIGxpbWl0aW5nIHRocmVzaG9sZHMuIEEgdGhyZXNob2xkIGhlcmUgaXMgdGhlIGJvdW5kYXJ5IHRoYXQgZGV0ZXJtaW5lcyBpZiBhIHZhbHVlIGlzIGFuIG91dGxpZXIuIElmIHRoZSB2YWx1ZSBmYWxscyBhYm92ZSB0aGUgdXBwZXIgdGhyZXNob2xkIG9yIGJlbG93IHRoZSBsb3dlciB0aHJlc2hvbGQsIGl0IGlzIGFuIG91dGxpZXIuIAoKVG8gY2FsY3VsYXRlIHRoZSB1cHBlciB0aHJlc2hvbGQ6CmBgYHtyfSAKdXBwZXJ0aHJlc2hvbGQgPSAoaXFyICogMS41KSArIHVwcGVycSAKdXBwZXJ0aHJlc2hvbGQKYGBgCgpCZWxvdyBpcyB0aGUgbG93ZXIgdGhyZXNob2xkOgpgYGB7cn0KbG93ZXJ0aHJlc2hvbGQgPSBsb3dlcnEgLSAoaXFyICogMS41KQpsb3dlcnRocmVzaG9sZApgYGAKCkEgZ29vZCB3YXkgdG8gdW5kZXJ0c2FuZCB0aGUgYWJvdmUgY2FsY3VsYXRpb25zIGlzIHRvIHZpc3VhbGl6ZSB0aGUgcmVzdWx0cyB1c2luZyBhIGJveCBhbmQgd2hpc2tlciBwbG90LiBUaGUgdG9wIGFuZCBsb3dlciBlbmRzIG9mIHRoZSBib3ggY29ycmVzcG9uZCB0byB0aGUgdXBwZXIgYW5kIGxvd2VyIHF1YXJ0aWxlcy4gVGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgYSBib2xkZWQgbGluZS4gVGhlIHdoaXNrZXJzIGFyZSB0aGUgbGluZXMgY29ubmVjdGluZyB0aGUgdXBwZXIgYW5kIGxvd2VyIHF1YXJ0aWxlcyB0byB1cHBlciBhbmQgbG93ZXIgdGhyZXNob2xkcy4gQW55IHBvaW50cyBiZXlvbmQgdGhlIHRocmVzaG9sZHMgaXMgYSBwb3RlbnRpYWwgb3V0bGllci4KCmBgYHtyfSAKYm94cGxvdChhZ2UpIApgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAxQykgRnJvbSB0aGUgYm94IHBsb3QgcmVwcmVzZW50YXRpb24gYXJlIHRoZXJlIGFueSBvdXRsaWVycz8gSG93IG1hbnkgY2FuIHlvdSBjb3VudD8gSG93IGRvZXMgeW91ciBhbnN3ZXIgcmVjb25jaWxlIHdpdGggdGhlIHJlc3VsdCBmcm9tIFRhc2sgMUI/Cjwvc3Bhbj4KCmBgYHtyfQojWWVzLCB0aGVyZSBhcmUgb3V0bGllcnMgKHRoZSBjaXJjbGVzIGFib3ZlIHRoZSB1cHBlcmxpbWl0IC0gdXBwZXJsaW5lKS4gVGhlIG91dGxpZXJzIGFyZSBvbmx5IG9uIHRoZSB1cHBlciBxdWFydGlsZS4gSSBjYW4gZGlmZmVyZW50aWF0ZSBvbmUgZm9yIHN1cmUsIHdoaWNoIGlzIHRoZSBvbmUgSSBtZW50aW9uZWQgb24gcXVlc3Rpb24gMUIsIGhvd2V2ZXIsIHRoZXJlIGFyZSBhIGZldyBtb3JlLiBJbiB0b3RhbCwgdGhlcmUgYXJlIDkgb3V0bGllcnMgYWNjb3JkaW5nIHRvIHRoZSBkYXRhIChpZiB5b3UgY2FsY3VsYXRlIHRoZSBkYXRhIGdyZWF0ZXIgdGhhbiB0aGUgdXBwZXJsaW1pdCBvZiB0aGUgYm94cGxvdCAtIDYzLjUgLSBieSBhbiAiaWYiIHN0YXRlbWVudCkuIEJlbG93IHRoZSBsb3dlcmxpbWl0IG9mIHRoZSBmaXJzdCBxdWFydGlsZSwgdGhlcmUgaXMgbm90IGFueSBvdXRsaWVyLiAgCmBgYAoKLS0tLS0tLS0tLS0tLS0tCgojIyMgVGFzayAyOiBEYXRhIFByZXBhcmF0aW9uCgpOZXh0LCB3ZSB3aWxsIHJlYWQgdGhlIGZpbGUgYGNyZWRpdHJpc2tvcmcuY3N2YCBpbnRvIFIgYXMgcHJvdmlkZWQgaW4gaXRzIG9yaWdpbmFsIGZvcm0uIFVubGlrZSB0aGUgY2xlYW5lZCBmaWxlIGBjcmVkaXRyaXNrLmNzdmAsIHRoZSBvcmlnaW5hbCBkYXRhc2V0IHdpbGwgcmVxdWlyZSBzb21lIGRhdGEgcHJlcGFyYXRpb24uICAKCmBgYHtyfQpuZXdkYXRhID0gcmVhZC5jc3YoZmlsZT0iZGF0YS9jcmVkaXRyaXNrb3JnLmNzdiIpCmhlYWQobmV3ZGF0YSkKYGBgCgpXZSBvYnNlcnZlIGEgbmV3IGxpbmUgaXMgaW5zZXJ0ZWQgd2l0aCB0aGUgaGVhZGVyIGxhYmVscyBgWCwgWC4xLCAuLi5gIGFuZCB0aGF0IHRoZSB0cnVlIGNvbHVtbiBoZWFkZXJzIGFyZSBzaGlmdGVkIGRvd24uICBUaGlzIGlzIGJlY2F1c2Ugb2YgdGhlIGVtcHR5IGxpbmUgaW4gdGhlIG9yaWdpbmFsIGRhdGFzZXQuIFRvIGFjY291bnQgZm9yIHRoaXMgZGV0YWlsIHdlIG11c3Qgc2tpcCBvbmUgbGluZSB3aGVuIHJlYWRpbmcgdGhlIGZpbGUuCgpgYGB7cn0gCm5ld2RhdGEgPSByZWFkLmNzdihmaWxlPSJkYXRhL2NyZWRpdHJpc2tvcmcuY3N2Iixza2lwPTEpIApoZWFkKG5ld2RhdGEpCmBgYAoKTmV4dCB3ZSB3YW50IHRvIGV4dHJhY3QgdGhlIENoZWNraW5nIGNvbHVtbiBhbmQgdGhlbiBmaW5kIHRoZSBhdmVyYWdlIG9mIGNoZWNraW5nLCBzbWlsYXIgdG8gd2hhdCB3ZSBkaWQgaW4gdGhlIHByZXZpb3VzIGxhYi4gIFdoZW4gd2UgdHJ5IHRvIGV4ZWN1dGUgdGhlIGNvZGUgY2h1bmsgYmVsb3cgbm90aWNlIHRoYXQgd2UgZ2V0IGFuIGVycm9yLgoKYGBge3J9IApjaGVja2luZyA9IG5ld2RhdGEkQ2hlY2tpbmcgI2NvbW1hbmQgdG8gZXh0cmFjdCB0aGUgQ2hlY2tpbmcgY29sdW1uIGZyb20gdGhlIGRhdGEgZmlsZSBuZXdkYXRhCm1lYW4oY2hlY2tpbmcpCmBgYAoKVG8gcmVzb2x2ZSB0aGUgZXJyb3IsIHdlIG11c3QgdW5kZXJzdGFuZCBmaXJzdCB3aGVyZSBpdCdzIHNvdXJjZS4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGluIHRoZSBjc3YgZmlsZSByZXByZXNlbnRlZCBieSB0aGUgc3ltYm9sIGAkLWAuIE1pc3NpbmcgZGF0YSBpcyBxdWl0ZSBjb21tb24gYXMgbW9zdCBkYXRhc2V0cyBhcmUgbm90IHBlcmZlY3QuIEFkZGl0aW9uYWxseSwgdGhlcmUgYXJlIGNvbW1hcyB3aXRoaW4gdGhlIGV4Y2VsIHNwcmVhZHNoZWV0LCBhbmQgUiBkb2VzIG5vdCByZWNvZ25pemUgdGhhdCAnMSwyMzQnIGlzIGVxdWl2YWxlbnQgdG8gJzEyMzQnLiBMYXN0bHksIHRoZXJlIGFyZSAnJCcgc3ltYm9scyB0aHJvdWdob3V0IHRoZSBmaWxlIHdoaWNoIGlzIG5vdCBhIG51bWVyaWNhbCBzeW1ib2wgZWl0aGVyLgoKVG8gY29ycmVjdCBmb3IgdGhlIGVycm9yIHdlIG5lZWQgdG8gZG8gc29tZSBkYXRhIGNsZWFudXAuIEZvciB0aGlzIHdlIHdpbGwgdXNlIHRoZSBzdWIgZnVuY3Rpb24gYHN1YigpYCBpbiBSIHRvIHJlcGxhY2UgdW53YW50ZWQgc3ltYm9scyB3aXRoIHNvbWV0aGluZyBlbHNlLiBGb3IgZXhhbXBsZSwgaW4gb3JkZXIgdG8gcmVtb3ZlIHRoZSBjb21tYSBpbiB0aGUgbnVtYmVyICIxLDIzNCIsIHdlIGNhbiBzdWJzdGl0dXRlIGl0IHdpdGggYmxhbmsuIEJlbG93IGlzIGEgc2VxdWVuY2Ugb2YgY29tbWFuZHMgdG8gaGVscCB3aXRoIHRoZSBjbGVhbnVwIG9mIHRoZSBkYXRhIGluIHRoZSBDaGVja2luZyBjb2x1bW4gYW5kIGV2ZW50dWFsIGNhbGN1bGF0aW9uIG9mIHRoZSBtZWFuLgoKYGBge3J9IAojc3Vic3RpdHV0ZSBjb21tYSB3aXRoIGJsYW5rIGluIGFsbCBvZiBjaGVja2luZyAgCmNoZWNraW5nPSBzdWIoIiwiLCIiLGNoZWNraW5nKQoKI3N1YnN0aXR1dGUgZG9sbGFyIHNpZ24gd2l0aCBibGFuayBpbiBhbGwgb2YgY2hlY2tpbmcgCiMgRXhhbXBsZSBuZXcgPSBzdWIoIlxcJCIsIiIsbmV3KQpjaGVja2luZyA9IHN1YigiXFwkIiwiIixjaGVja2luZykKCiNDb252ZXJ0IHZhbHVlcyB0byBudW1lcmljLiBBbnkgdmFsdWUgdGhhdCBjYW5ub3QgYmUgY29udmVydGVkIHRvIG51bWVyaWMgd2lsbCBiZSBkZXNpZ25hdGVkIGFzIE5BIChOb3QgQXBwbGljYWJsZSkKY2hlY2tpbmcgPSBhcy5udW1lcmljKGNoZWNraW5nKQoKI0NhbGN1bGF0ZSBtZWFuIG9mIGNoZWNraW5nIHdpdGggYWxsIE5BcyByZW1vdmVkIAptZWFuKGNoZWNraW5nLG5hLnJtPVRSVUUpCmBgYAoKPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+CiMjIyMjIDJBKSBSZXBlYXQgdGhlIGFib3ZlIGNvbW1hbmRzIHRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiB0aGUgU2F2aW5ncyBjb2x1bW4gaW5zdGVhZC4gVXNlIGEgZGlmZmVyZW50IHZhcmlhYmxlIG5hbWluZy4KPC9zcGFuPgpgYGB7cn0KCgpEYXRvcyA9IHJlYWQuY3N2KGZpbGU9ImRhdGEvY3JlZGl0cmlza29yZy5jc3YiLHNraXA9MSkgCmhlYWQoRGF0b3MpCmBgYAoKCmBgYHtyfQpTYXZpbmdzID0gRGF0b3MkU2F2aW5ncwoKU2F2aW5ncyA9IHN1YigiLCIsIiIsU2F2aW5ncykKClNhdmluZ3MgPSBzdWIoIlxcJCIsIiIsU2F2aW5ncykKClNhdmluZ3MgPSBhcy5udW1lcmljKFNhdmluZ3MpCm1lYW5TYXZpbmdzID0gbWVhbihTYXZpbmdzLG5hLnJtPVRSVUUpCgptZWFuU2F2aW5ncwpgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAyQikgQ2FsY3VsYXRlIG5vdyB0aGUgbWVhbiBvZiB0aGUgQ2hlY2tpbmcgY29sdW1uIGluIEV4Y2VsIHVzaW5nIHRoZSBFeGNlbCBmdW5jdGlvbiBgQXZlcmFnZWAuIENvbXBhcmUgdGhlIHR3byByZXN1bHRzLCBmcm9tIEV4Y2VsIGFuZCBSIGFuZCBzaGFyZSB5b3VyIG9ic2VydmF0aW9uLgo8L3NwYW4+CmBgYHtyfQojVGhlIG1lYW4gb2YgdGhlIENoZWNraW5nIGNvbHVtbiBjYWxjdWxhdGVkIGluIEV4Y2VsIGlzICQyLDU1OS44MDQ1OTc3MDExNTAwLiBUaGUgdHdvIHZhbHVlcyAoRXhjZWwgYW5kIFJzdHVkaW8pIGFyZSB0aGUgc2FtZSwgdGhlcmVmb3JlLCBteSBvYnNlcnZhdGlvbiBvZiB0aGlzIGNhbGN1bGF0aW9uIGlzIHRoYXQgRXhjZWwgaXMgdHJlYXRpbmcgdGhlIGRhdGEgdGhlIHNhbWUgd2F5IFIgZG9lcyB3aGVuIHdlIHR5cGUgdGhlIGluZGljYXRpb25zIGZvciB0aGUgdmFsdWVzLiAKI0Fub3RoZXIgb2JzZXJ2YXRpb24gaXMgdGhhdCB0aGUgcmVzdWx0IGluIFIgaXMgYSBiaXQgcm91bmRlZCBpbiBjb21wYXJpc29uIHdpdGggRXhjZWwgKEV4Y2VsIGdpdmVzIG1vcmUgZGVjaW1hbHMpLgpgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAyQykgQmFzZWQgb24geW91ciBvYnNlcnZhdGlvbiBob3cgZGlkIEV4Y2VsIHRyZWF0IHRoZSBtaXNzaW5nIHZhbHVlcyByZXByZXNlbnRlZCBieSB0aGUgc3ltYm9sIGAkLWA/IEFyZSB0aGV5IGluY2x1ZGVkIGluIHRoZSBjYWxjdWxhdGlvbiBvZiB0aGUgbWVhbiBvciBleGNsdWRlZD8gIEV4cGxhaW4geW91ciBhbnN3ZXIuCmBgYHtyfQojRXhjZWwgdHJlYXRzIHRoZSBtaXNzaW5nIHZhbHVlcyByZXByZXNlbnRlZCBieSB0aGUgc3ltYm9sICIkLSIgYXMgYmxhbmsgc3BhY2VzLiBTbywgdGhleSBhcmUgZXhjbHVkZWQgaW4gdGhlIGNhbGN1bGF0aW9uIG9mIHRoZSBtZWFuLiBJIGtub3cgaXQgYmVjYXVzZSB0aGUgcmVzdWx0IGlzIHRoZSBzYW1lIGFzIHRoZSBvbmUgdGhhdCB5b3UgZ2V0IGluIFIgYWZ0ZXIgaW5kaWNhdGluZyB0byBkbyBpdCBsaWtlIHRoYXQgKHRvIHRyZWF0IHRoZSB2YWx1ZXMgYXMgbnVtZXJpYywgc3Vic3RpdHV0ZSB0aGUgJCBmb3Igbm90aGluZywgZXRjLikKCiNJZiBFeGNlbCBoYXMgdHJlYXRlZCB0aGUgdmFsdWVzIG9uIHRoZXNlIGNlbGxzIGRpZmZlcmVudGx5LCB0aGUgcmVzdWx0IHdvdWxkIGJlIGRpZmZlcmVudC4gCmBgYAoKLS0tLS0tLS0tLS0tLQoKIyMjIFRhc2sgMzogRGF0YSBNb2RlbGluZwoKSGVyZSwgd2Ugd2lsbCBsb29rIGF0IENoaWNhZ28gRGl2dnkgYmlrZSBkYXRhLiBUaGUgaGlzdG9yaWNhbCBkYXRhIHNldHMgd2l0aCBkZXNjcmlwdGlvbiBvZiBmaWVsZHMgY2FuIGJlIGZvdW5kIGF0OiAgCgpDaGljYWdvIERpdnZ5IERhdGE6IFtodHRwczovL3d3dy5kaXZ2eWJpa2VzLmNvbS9kYXRhXShodHRwczovL3d3dy5kaXZ2eWJpa2VzLmNvbS9zeXN0ZW0tZGF0YSkKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyMgM0EpIE9wZW4gaW4gUlN0dWRpbyBvciBFeGNlbCB0aGUgZmlsZSBgRGl2dnlfVHJpcHNfMjAxN19RNC5jc3ZgICBsb2NhdGVkIGluIHRoZSBkYXRhIGZvbGRlci4gV2hhdCBpcyB0aGUgc2l6ZSBvZiB0aGUgZmlsZSAobWVhc3VyZWQgaW4gYnl0ZXMpLCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgYW5kIG9mIHJvd3M/LiBJZGVudGlmeSB0aGUgY29sdW1uIGZpZWxkKHMpIGluIHRoZSBkYXRhIHRoYXQgaXMvYXJlIHVuaXF1ZSBpZGVudGlmaWVyKHMpIChjYW5ub3QgaGF2ZSBkdXBsaWNhdGUvcmVwZWF0ZWQgdmFsdWVzKQo8L3NwYW4+IApgYGB7cn0KI1RoZSBzaXplIG9mIHRoZSBmaWxlIGlzIDgzLDkzMCBLQi4gSXQgaGFzIDEyIGNvbHVtbnMgYW5kIDY2OTIzOSByb3dzCgojVGhlIGNvbHVtbiBmaWVsZCB0aGF0IGlzIGEgdW5pcXVlIGlkZW50aWZpZXIgaXMgdGhlIHRyaXBfaWQuCmBgYAoKClJlYWQgY2FyZWZ1bGx5IHRoZSBmaWxlIGBSRUFETUUudHh0YCwgbG9jYXRlZCBpbiBzYW1lIGRhdGEgZm9sZGVyLCBmb3IgdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLgoKPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+CiMjIyMjIyAzQikgRGVmaW5lIGEgcmVsYXRpb25hbCBidXNpbmVzcyBsb2dpYyBpbnRlZ3JpdHkgcnVsZSBmb3IgdGhlIGNvbHVtbiBmaWVsZCBgVHJpcCBEdXJhdGlvbmAuCjwvc3Bhbj4KYGBge3J9CiNBIHJlbGF0aW9uYWwgYnVzaW5lc3MgbG9naWMgaW50ZWdyaXR5IHJ1bGUgZm9yIHRoZSBmaWVsZCAiVHJpcCBEdXJhdGlvbiIgaXMgYmV0d2VlbiBzdGFydF90aW1lIGFuZCBzdG9wX3RpbWUgZmllbGRzLiBUaGUgdHJpcCBkdXJhdGlvbiBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHN0b3AgdGltZSBhbmQgc3RhcnQgdGltZSwgdGhlcmVmb3JlLCB0aGUgdGltZSBvZiB0aGUgdHJpcCBkdXJhdGlvbiBjYW5ub3QgZXhjZWVkIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHN0b3AgYW5kIHN0YXJ0IHRpbWUuIEZvciBleGFtcGxlLCBpZiB0aGUgVHJpcCBEdXJhdGlvbiBpcyAxMjAgc2Vjb25kcywgdGhlbiB0aGUgc3RvcF90aW1lIGhhcyB0byBiZSB0d28gbWludXRlcyBhZnRlciB0aGUgdGltZSB0aGF0IGlzIHNhaWQgaW4gdGhlIHN0YXJ0X3RpbWUgZmllbGQuCmBgYAoKPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+CiMjIyMjIyAzQykgVXNpbmcgW2h0dHBzOi8vZXJkcGx1cy5jb20vIy9zdGFuZGFsb25lXShodHRwczovL2VyZHBsdXMuY29tLyMvc3RhbmRhbG9uZSkgZHJhdyBhIHN0YXIgbGlrZSBzY2hlbWEgdXNpbmcgdGhlIGJlbG93IHRocmVlIHRhYmxlcy4gSW5jbHVkZSBhbiBpbWFnZSBjYXB0dXJlIG9mIHlvdXIgc2NoZW1hIGhlcmUuCjwvc3Bhbj4gCgotIEEgRmFjdCB0YWJsZSBmb3IgVHJpcHMKLSBBIERpbWVuc2lvbiB0YWJsZSBmb3IgU3RhdGlvbnMKLSBBIERpbWVuc2lvbiB0YWJsZSBmb3IgVXNlcnMKCiFbRVJEIGRpYWdyYW0gLSBEaXZ2eSBUcmlwc10oZGF0YS9EaXZ2eS1lcmRwbHVzLWRpYWdyYW0ucG5nKQoKCg==