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. 
mean(age)
[1] 34.39765
#Calculate the standard deviation of age below. 
sd(age)
[1] 11.04513
#Calculate the maxima of age below. Look in Help to find the right command for maxima
max(age)
[1] 73
#Calculate the minima of age below. Look in Help to find the right command for minima
min(age)
[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.

lowerthreshold = mean(age) - (3) * sd(age)
upperthreshold = mean(age) + (3) * sd(age)
lowerthreshold
[1] 1.262269
upperthreshold
[1] 67.53302

there are outliers because the max age is 73 but the upper limit is 67.5

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? it shows there are 5 outliers and it does because they are outside of the upper limit —————

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.

Savings = newdata$Savings
Savings= sub(",","",Savings)
Savings = sub("\\$","",Savings)
Savings = as.numeric(Savings)
NAs introduced by coercion
mean(Savings,na.rm=TRUE)
[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. they are the same R just rounded more ##### 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 corrected for the missing value ————-

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 file is 85.9 mb 12 columns 669240 rows

Divydata = read.csv(file="data/Divvy_Trips_2017_Q4.csv") 

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. Trip duration cant be negative or zero It must be a positive number less then 24 hours according to the readme doc

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

LS0tCnRpdGxlOiAiQlNBRDM0MyBGYWxsIDIwMTggTGFiIFdvcmtzaGVldCAwMyIKYXV0aG9yOiAiWW91ciBOYW1lIEhlcmUiCmRhdGU6ICJBZGQgRGF0ZSBIZXJlIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKc3VidGl0bGU6IERhdGEgUHJlcGFyYXRpb24gJiBGbG93IChic2FkLWxhYjAzKQotLS0KCiMjIyBBYm91dAoKVGhpcyB3b3Jrc2hlZXQgaW5jbHVkZXMgdGhyZWUgbWFpbiB0YXNrcyBvbiBkYXRhIG91dGxpZXJzLCBkYXRhIHByZXBhcmF0aW9uLCBhbmQgZGF0YSBtb2RlbGluZy4gVGhlIGxhYiByZXF1aXJlcyB0aGUgdXNlIG9mIE1pY3Jvc29mdCBFeGNlbCwgUiwgYW5kIEVSRHBsdXMuCgojIyMgU2V0dXAKClJlbWVtYmVyIHRvIGFsd2F5cyBzZXQgeW91ciB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGUgc291cmNlIGZpbGUgbG9jYXRpb24uIEdvIHRvICdTZXNzaW9uJywgc2Nyb2xsIGRvd24gdG8gJ1NldCBXb3JraW5nIERpcmVjdG9yeScsIGFuZCBjbGljayAnVG8gU291cmNlIEZpbGUgTG9jYXRpb24nLiBSZWFkIGNhcmVmdWxseSB0aGUgYmVsb3cgYW5kIGZvbGxvdyB0aGUgaW5zdHJ1Y3Rpb25zIHRvIGNvbXBsZXRlIHRoZSB0YXNrcyBhbmQgYW5zd2VyIGFueSBxdWVzdGlvbnMuICBTdWJtaXQgeW91ciB3b3JrIHRvIFJQdWJzIGFzIGRldGFpbGVkIGluIHByZXZpb3VzIG5vdGVzLiAKCiMjIyBOb3RlCgpGb3IgeW91ciBhc3NpZ25tZW50IHlvdSBtYXkgYmUgdXNpbmcgZGlmZmVyZW50IGRhdGEgc2V0cyB0aGFuIHdoYXQgaXMgaW5jbHVkZWQgaGVyZS4gQWx3YXlzIHJlYWQgY2FyZWZ1bGx5IHRoZSBpbnN0cnVjdGlvbnMgb24gU2FrYWkuICBGb3IgY2xhcml0eSwgdGFza3MvcXVlc3Rpb25zIHRvIGJlIGNvbXBsZXRlZC9hbnN3ZXJlZCBhcmUgaGlnaGxpZ2h0ZWQgaW4gcmVkIGNvbG9yICh2aXNpYmxlIGluIHByZXZpZXcpIGFuZCBudW1iZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgcGFydGljdWxhciBwbGFjZW1lbnQgaW4gdGhlIHRhc2sgc2VjdGlvbi4gIFF1aXRlIG9mdGVuIHlvdSB3aWxsIG5lZWQgdG8gYWRkIHlvdXIgb3duIGNvZGUgY2h1bmsuCgpFeGVjdXRlIGFsbCBjb2RlIGNodW5rcywgcHJldmlldywgcHVibGlzaCwgYW5kIHN1Ym1pdCBsaW5rIG9uIFNha2FpLgoKLS0tLS0tLS0tLS0tLS0KCiMjIyBUYXNrIDE6IERhdGEgT3V0bGllcnMKCkZpcnN0LCB3ZSBtdXN0IGNhbGN1bGF0ZSB0aGUgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uLCBtYXhpbXVtLCBhbmQgbWluaW11bSBmb3IgdGhlIEFnZSBjb2x1bW4gdXNpbmcgUi4KCkluIFIsIHdlIG11c3QgcmVhZCBpbiB0aGUgZmlsZSBhZ2FpbiwgZXh0cmFjdCB0aGUgY29sdW1uIGFuZCBmaW5kIHRoZSB2YWx1ZXMgdGhhdCBhcmUgYXNrZWQgZm9yLgoKYGBge3J9CiNSZWFkIEZpbGUKbXlkYXRhID0gcmVhZC5jc3YoZmlsZT0iZGF0YS9jcmVkaXRyaXNrLmNzdiIpIAoKI05hbWUgdGhlIGV4dHJhY3RlZCB2YXJpYWJsZQphZ2UgPSBteWRhdGEkQWdlIAoKYGBgCgo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4KIyMjIyMgMUEpIEZpbGwgaW4gdGhlIGNvZGUgY2h1bmsgYmVsb3cgdG8gY2FsY3VsYXRlIGFuZCBkaXNwbGF5IGVhY2ggcmVzdWx0LiAgUmVmZXIgdG8gcHJldmlvdXMgd29ya3NoZWV0cyBhbmQgb24tbGluZSBoZWxwIGZvciBzb21lIGNvbW1hbmRzLgo8L3NwYW4+CgpgYGB7cn0KI0NhbGN1bGF0ZSB0aGUgYXZlcmFnZSBhZ2UgYmVsb3cuIAptZWFuKGFnZSkKCiNDYWxjdWxhdGUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBhZ2UgYmVsb3cuIApzZChhZ2UpCgojQ2FsY3VsYXRlIHRoZSBtYXhpbWEgb2YgYWdlIGJlbG93LiBMb29rIGluIEhlbHAgdG8gZmluZCB0aGUgcmlnaHQgY29tbWFuZCBmb3IgbWF4aW1hCm1heChhZ2UpCgoKI0NhbGN1bGF0ZSB0aGUgbWluaW1hIG9mIGFnZSBiZWxvdy4gTG9vayBpbiBIZWxwIHRvIGZpbmQgdGhlIHJpZ2h0IGNvbW1hbmQgZm9yIG1pbmltYQptaW4oYWdlKQpgYGAKCk5leHQsIHdlIHdpbGwgdXNlIHRoZSBmb3JtdWxhIGZyb20gY2xhc3MgdG8gZGV0ZWN0IGFueSBvdXRsaWVycy4gQW4gb3V0bGllciBpcyBhIHZhbHVlIHRoYXQgImxpZXMgb3V0c2lkZSIgbW9zdCBvZiB0aGUgb3RoZXIgdmFsdWVzIGluIGEgc2V0IG9mIGRhdGEuIEEgY29tbW9uIHdheSB0byBlc3RpbWF0ZSB0aGUgdXBwZXIgYW5kIGxvd2VyIGxpbWl0cyBpcyB0byB0YWtlIHRoZSBgYGBtZWFuICgrIG9yIC0pIDMgKiBzdGFuZGFyZCBkZXZpYXRpb25gYGAuICAKCgo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4KIyMjIyMgMUIpIFdyaXRlIGFuZCBleGVjdXRlIHRoZSBjb2RlIGNodW5rIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGFib3ZlIGZvcm11bGEgdG8gY2FsY3VsYXRlIHRoZSB1cHBlciBhbmQgbG93ZXIgbGltaXRzIGZvciBhZ2UuIERpc3BsYXkgeW91ciByZXN1bHRzLiBCYXNlZCBvbiB0aGUgbGltaXRzIGRvIHlvdSB0aGluayB0aGVyZSBhcmUgb3V0bGllcnM/IEV4cGxhaW4geW91ciBhbnN3ZXIuCjwvc3Bhbj4KYGBge3J9Cmxvd2VydGhyZXNob2xkID0gbWVhbihhZ2UpIC0gKDMpICogc2QoYWdlKQp1cHBlcnRocmVzaG9sZCA9IG1lYW4oYWdlKSArICgzKSAqIHNkKGFnZSkKbG93ZXJ0aHJlc2hvbGQKdXBwZXJ0aHJlc2hvbGQKYGBgCnRoZXJlIGFyZSBvdXRsaWVycyBiZWNhdXNlIHRoZSBtYXggYWdlIGlzIDczIGJ1dCB0aGUgdXBwZXIgbGltaXQgaXMgNjcuNQoKCkFub3RoZXIgc2ltaWxhciBtZXRob2QgdG8gZmluZCB0aGUgdXBwZXIgYW5kIGxvd2VyIHRocmVzaG9sZHMsIGRpc2N1c3NlZCBpbiBtYW55IGludHJvZHVjdG9yeSBzdGF0aXN0aWNzIGNvdXJzZXMsIGludm9sdmVzIGZpbmRpbmcgdGhlIGludGVycXVhcnRpbGUgcmFuZ2UuIEZvbGxvdyBhbG9uZyBiZWxvdyB0byBzZWUgaG93IHdlIGZpcnN0IGNhbGN1bGF0ZSB0aGUgaW50ZXJxdWFydGlsZSByYW5nZS4uIAoKYGBge3J9IApxdWFudGlsZShhZ2UpIApsb3dlcnEgPSBxdWFudGlsZShhZ2UpWzJdCnVwcGVycSA9IHF1YW50aWxlKGFnZSlbNF0KaXFyID0gdXBwZXJxIC0gbG93ZXJxCmBgYAoKTmV4dCB3ZSBjYWxjdWxhdGUgdGhlIGxpbWl0aW5nIHRocmVzaG9sZHMuIEEgdGhyZXNob2xkIGhlcmUgaXMgdGhlIGJvdW5kYXJ5IHRoYXQgZGV0ZXJtaW5lcyBpZiBhIHZhbHVlIGlzIGFuIG91dGxpZXIuIElmIHRoZSB2YWx1ZSBmYWxscyBhYm92ZSB0aGUgdXBwZXIgdGhyZXNob2xkIG9yIGJlbG93IHRoZSBsb3dlciB0aHJlc2hvbGQsIGl0IGlzIGFuIG91dGxpZXIuIAoKVG8gY2FsY3VsYXRlIHRoZSB1cHBlciB0aHJlc2hvbGQ6CmBgYHtyfSAKdXBwZXJ0aHJlc2hvbGQgPSAoaXFyICogMS41KSArIHVwcGVycSAKdXBwZXJ0aHJlc2hvbGQKYGBgCgpCZWxvdyBpcyB0aGUgbG93ZXIgdGhyZXNob2xkOgpgYGB7cn0KbG93ZXJ0aHJlc2hvbGQgPSBsb3dlcnEgLSAoaXFyICogMS41KQpsb3dlcnRocmVzaG9sZApgYGAKCkEgZ29vZCB3YXkgdG8gdW5kZXJ0c2FuZCB0aGUgYWJvdmUgY2FsY3VsYXRpb25zIGlzIHRvIHZpc3VhbGl6ZSB0aGUgcmVzdWx0cyB1c2luZyBhIGJveCBhbmQgd2hpc2tlciBwbG90LiBUaGUgdG9wIGFuZCBsb3dlciBlbmRzIG9mIHRoZSBib3ggY29ycmVzcG9uZCB0byB0aGUgdXBwZXIgYW5kIGxvd2VyIHF1YXJ0aWxlcy4gVGhlIG1lZGlhbiBpcyBtYXJrZWQgYnkgYSBib2xkZWQgbGluZS4gVGhlIHdoaXNrZXJzIGFyZSB0aGUgbGluZXMgY29ubmVjdGluZyB0aGUgdXBwZXIgYW5kIGxvd2VyIHF1YXJ0aWxlcyB0byB1cHBlciBhbmQgbG93ZXIgdGhyZXNob2xkcy4gQW55IHBvaW50cyBiZXlvbmQgdGhlIHRocmVzaG9sZHMgaXMgYSBwb3RlbnRpYWwgb3V0bGllci4KCmBgYHtyfSAKYm94cGxvdChhZ2UpIApgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAxQykgRnJvbSB0aGUgYm94IHBsb3QgcmVwcmVzZW50YXRpb24gYXJlIHRoZXJlIGFueSBvdXRsaWVycz8gSG93IG1hbnkgY2FuIHlvdSBjb3VudD8gSG93IGRvZXMgeW91ciBhbnN3ZXIgcmVjb25jaWxlIHdpdGggdGhlIHJlc3VsdCBmcm9tIFRhc2sgMUI/Cjwvc3Bhbj4KaXQgc2hvd3MgdGhlcmUgYXJlIDUgb3V0bGllcnMgYW5kIGl0IGRvZXMgYmVjYXVzZSB0aGV5IGFyZSBvdXRzaWRlIG9mIHRoZSB1cHBlciBsaW1pdCAKLS0tLS0tLS0tLS0tLS0tCgojIyMgVGFzayAyOiBEYXRhIFByZXBhcmF0aW9uCgpOZXh0LCB3ZSB3aWxsIHJlYWQgdGhlIGZpbGUgYGNyZWRpdHJpc2tvcmcuY3N2YCBpbnRvIFIgYXMgcHJvdmlkZWQgaW4gaXRzIG9yaWdpbmFsIGZvcm0uIFVubGlrZSB0aGUgY2xlYW5lZCBmaWxlIGBjcmVkaXRyaXNrLmNzdmAsIHRoZSBvcmlnaW5hbCBkYXRhc2V0IHdpbGwgcmVxdWlyZSBzb21lIGRhdGEgcHJlcGFyYXRpb24uICAKCmBgYHtyfQpuZXdkYXRhID0gcmVhZC5jc3YoZmlsZT0iZGF0YS9jcmVkaXRyaXNrb3JnLmNzdiIpCmhlYWQobmV3ZGF0YSkKYGBgCgpXZSBvYnNlcnZlIGEgbmV3IGxpbmUgaXMgaW5zZXJ0ZWQgd2l0aCB0aGUgaGVhZGVyIGxhYmVscyBgWCwgWC4xLCAuLi5gIGFuZCB0aGF0IHRoZSB0cnVlIGNvbHVtbiBoZWFkZXJzIGFyZSBzaGlmdGVkIGRvd24uICBUaGlzIGlzIGJlY2F1c2Ugb2YgdGhlIGVtcHR5IGxpbmUgaW4gdGhlIG9yaWdpbmFsIGRhdGFzZXQuIFRvIGFjY291bnQgZm9yIHRoaXMgZGV0YWlsIHdlIG11c3Qgc2tpcCBvbmUgbGluZSB3aGVuIHJlYWRpbmcgdGhlIGZpbGUuCgpgYGB7cn0gCm5ld2RhdGEgPSByZWFkLmNzdihmaWxlPSJkYXRhL2NyZWRpdHJpc2tvcmcuY3N2Iixza2lwPTEpIApoZWFkKG5ld2RhdGEpCmBgYAoKTmV4dCB3ZSB3YW50IHRvIGV4dHJhY3QgdGhlIENoZWNraW5nIGNvbHVtbiBhbmQgdGhlbiBmaW5kIHRoZSBhdmVyYWdlIG9mIGNoZWNraW5nLCBzbWlsYXIgdG8gd2hhdCB3ZSBkaWQgaW4gdGhlIHByZXZpb3VzIGxhYi4gIFdoZW4gd2UgdHJ5IHRvIGV4ZWN1dGUgdGhlIGNvZGUgY2h1bmsgYmVsb3cgbm90aWNlIHRoYXQgd2UgZ2V0IGFuIGVycm9yLgoKYGBge3J9IApjaGVja2luZyA9IG5ld2RhdGEkQ2hlY2tpbmcgIyBjb21tYW5kIHRvIGV4dHJhY3QgdGhlIENoZWNraW5nIGNvbHVtbiBmcm9tIHRoZSBkYXRhIGZpbGUgbmV3ZGF0YQptZWFuKGNoZWNraW5nKQpgYGAKClRvIHJlc29sdmUgdGhlIGVycm9yLCB3ZSBtdXN0IHVuZGVyc3RhbmQgZmlyc3Qgd2hlcmUgaXQncyBzb3VyY2UuIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgY3N2IGZpbGUgcmVwcmVzZW50ZWQgYnkgdGhlIHN5bWJvbCBgJC1gLiBNaXNzaW5nIGRhdGEgaXMgcXVpdGUgY29tbW9uIGFzIG1vc3QgZGF0YXNldHMgYXJlIG5vdCBwZXJmZWN0LiBBZGRpdGlvbmFsbHksIHRoZXJlIGFyZSBjb21tYXMgd2l0aGluIHRoZSBleGNlbCBzcHJlYWRzaGVldCwgYW5kIFIgZG9lcyBub3QgcmVjb2duaXplIHRoYXQgJzEsMjM0JyBpcyBlcXVpdmFsZW50IHRvICcxMjM0Jy4gTGFzdGx5LCB0aGVyZSBhcmUgJyQnIHN5bWJvbHMgdGhyb3VnaG91dCB0aGUgZmlsZSB3aGljaCBpcyBub3QgYSBudW1lcmljYWwgc3ltYm9sIGVpdGhlci4KClRvIGNvcnJlY3QgZm9yIHRoZSBlcnJvciB3ZSBuZWVkIHRvIGRvIHNvbWUgZGF0YSBjbGVhbnVwLiBGb3IgdGhpcyB3ZSB3aWxsIHVzZSB0aGUgc3ViIGZ1bmN0aW9uIGBzdWIoKWAgaW4gUiB0byByZXBsYWNlIHVud2FudGVkIHN5bWJvbHMgd2l0aCBzb21ldGhpbmcgZWxzZS4gRm9yIGV4YW1wbGUsIGluIG9yZGVyIHRvIHJlbW92ZSB0aGUgY29tbWEgaW4gdGhlIG51bWJlciAiMSwyMzQiLCB3ZSBjYW4gc3Vic3RpdHV0ZSBpdCB3aXRoIGJsYW5rLiBCZWxvdyBpcyBhIHNlcXVlbmNlIG9mIGNvbW1hbmRzIHRvIGhlbHAgd2l0aCB0aGUgY2xlYW51cCBvZiB0aGUgZGF0YSBpbiB0aGUgQ2hlY2tpbmcgY29sdW1uIGFuZCBldmVudHVhbCBjYWxjdWxhdGlvbiBvZiB0aGUgbWVhbi4KCmBgYHtyfSAKI3N1YnN0aXR1dGUgY29tbWEgd2l0aCBibGFuayBpbiBhbGwgb2YgY2hlY2tpbmcgIApjaGVja2luZz0gc3ViKCIsIiwiIixjaGVja2luZykKCiNzdWJzdGl0dXRlIGRvbGxhciBzaWduIHdpdGggYmxhbmsgaW4gYWxsIG9mIGNoZWNraW5nIAojIEV4YW1wbGUgbmV3ID0gc3ViKCJcXCQiLCIiLG5ldykKY2hlY2tpbmcgPSBzdWIoIlxcJCIsIiIsY2hlY2tpbmcpCgojQ29udmVydCB2YWx1ZXMgdG8gbnVtZXJpYy4gQW55IHZhbHVlIHRoYXQgY2Fubm90IGJlIGNvbnZlcnRlZCB0byBudW1lcmljIHdpbGwgYmUgZGVzaWduYXRlZCBhcyBOQSAoTm90IEFwcGxpY2FibGUpCmNoZWNraW5nID0gYXMubnVtZXJpYyhjaGVja2luZykKCiNDYWxjdWxhdGUgbWVhbiBvZiBjaGVja2luZyB3aXRoIGFsbCBOQXMgcmVtb3ZlZCAKbWVhbihjaGVja2luZyxuYS5ybT1UUlVFKQpgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAyQSkgUmVwZWF0IHRoZSBhYm92ZSBjb21tYW5kcyB0byBjYWxjdWxhdGUgdGhlIG1lYW4gb2YgdGhlIFNhdmluZ3MgY29sdW1uIGluc3RlYWQuIFVzZSBhIGRpZmZlcmVudCB2YXJpYWJsZSBuYW1pbmcuCjwvc3Bhbj4KYGBge3J9ClNhdmluZ3MgPSBuZXdkYXRhJFNhdmluZ3MKU2F2aW5ncz0gc3ViKCIsIiwiIixTYXZpbmdzKQpTYXZpbmdzID0gc3ViKCJcXCQiLCIiLFNhdmluZ3MpClNhdmluZ3MgPSBhcy5udW1lcmljKFNhdmluZ3MpCm1lYW4oU2F2aW5ncyxuYS5ybT1UUlVFKQpgYGAKCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAyQikgQ2FsY3VsYXRlIG5vdyB0aGUgbWVhbiBvZiB0aGUgQ2hlY2tpbmcgY29sdW1uIGluIEV4Y2VsIHVzaW5nIHRoZSBFeGNlbCBmdW5jdGlvbiBgQXZlcmFnZWAuIENvbXBhcmUgdGhlIHR3byByZXN1bHRzLCBmcm9tIEV4Y2VsIGFuZCBSIGFuZCBzaGFyZSB5b3VyIG9ic2VydmF0aW9uLgo8L3NwYW4+CnRoZXkgYXJlIHRoZSBzYW1lIFIganVzdCByb3VuZGVkIG1vcmUgCjxzcGFuIHN0eWxlPSJjb2xvcjpyZWQiPgojIyMjIyAyQykgQmFzZWQgb24geW91ciBvYnNlcnZhdGlvbiBob3cgZGlkIEV4Y2VsIHRyZWF0IHRoZSBtaXNzaW5nIHZhbHVlcyByZXByZXNlbnRlZCBieSB0aGUgc3ltYm9sIGAkLWA/IEFyZSB0aGV5IGluY2x1ZGVkIGluIHRoZSBjYWxjdWxhdGlvbiBvZiB0aGUgbWVhbiBvciBleGNsdWRlZD8gIEV4cGxhaW4geW91ciBhbnN3ZXIuCmV4Y2VsIGNvcnJlY3RlZCBmb3IgdGhlIG1pc3NpbmcgdmFsdWUgCi0tLS0tLS0tLS0tLS0KCiMjIyBUYXNrIDM6IERhdGEgTW9kZWxpbmcKCkhlcmUsIHdlIHdpbGwgbG9vayBhdCBDaGljYWdvIERpdnZ5IGJpa2UgZGF0YS4gVGhlIGhpc3RvcmljYWwgZGF0YSBzZXRzIHdpdGggZGVzY3JpcHRpb24gb2YgZmllbGRzIGNhbiBiZSBmb3VuZCBhdDogIAoKQ2hpY2FnbyBEaXZ2eSBEYXRhOiBbaHR0cHM6Ly93d3cuZGl2dnliaWtlcy5jb20vZGF0YV0oaHR0cHM6Ly93d3cuZGl2dnliaWtlcy5jb20vc3lzdGVtLWRhdGEpCgo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4KIyMjIyMjIDNBKSBPcGVuIGluIFJTdHVkaW8gb3IgRXhjZWwgdGhlIGZpbGUgYERpdnZ5X1RyaXBzXzIwMTdfUTQuY3N2YCAgbG9jYXRlZCBpbiB0aGUgZGF0YSBmb2xkZXIuIFdoYXQgaXMgdGhlIHNpemUgb2YgdGhlIGZpbGUgKG1lYXN1cmVkIGluIGJ5dGVzKSwgdGhlIG51bWJlciBvZiBjb2x1bW5zIGFuZCBvZiByb3dzPy4gSWRlbnRpZnkgdGhlIGNvbHVtbiBmaWVsZChzKSBpbiB0aGUgZGF0YSB0aGF0IGlzL2FyZSB1bmlxdWUgaWRlbnRpZmllcihzKSAoY2Fubm90IGhhdmUgZHVwbGljYXRlL3JlcGVhdGVkIHZhbHVlcykKPC9zcGFuPiAKdGhlIGZpbGUgaXMgODUuOSBtYgoxMiBjb2x1bW5zIAo2NjkyNDAgcm93cyAKYGBge3J9CkRpdnlkYXRhID0gcmVhZC5jc3YoZmlsZT0iZGF0YS9EaXZ2eV9Ucmlwc18yMDE3X1E0LmNzdiIpIApgYGAKClJlYWQgY2FyZWZ1bGx5IHRoZSBmaWxlIGBSRUFETUUudHh0YCwgbG9jYXRlZCBpbiBzYW1lIGRhdGEgZm9sZGVyLCBmb3IgdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLgoKPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+CiMjIyMjIyAzQikgRGVmaW5lIGEgcmVsYXRpb25hbCBidXNpbmVzcyBsb2dpYyBpbnRlZ3JpdHkgcnVsZSBmb3IgdGhlIGNvbHVtbiBmaWVsZCBgVHJpcCBEdXJhdGlvbmAuCjwvc3Bhbj4KIFRyaXAgZHVyYXRpb24gY2FudCBiZSBuZWdhdGl2ZSBvciB6ZXJvIEl0IG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXIgbGVzcyB0aGVuIDI0IGhvdXJzIGFjY29yZGluZyB0byB0aGUgcmVhZG1lIGRvYwoKPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+CiMjIyMjIyAzQykgVXNpbmcgW2h0dHBzOi8vZXJkcGx1cy5jb20vIy9zdGFuZGFsb25lXShodHRwczovL2VyZHBsdXMuY29tLyMvc3RhbmRhbG9uZSkgZHJhdyBhIHN0YXIgbGlrZSBzY2hlbWEgdXNpbmcgdGhlIGJlbG93IHRocmVlIHRhYmxlcy4gSW5jbHVkZSBhbiBpbWFnZSBjYXB0dXJlIG9mIHlvdXIgc2NoZW1hIGhlcmUuCjwvc3Bhbj4gCgotIEEgRmFjdCB0YWJsZSBmb3IgVHJpcHMKLSBBIERpbWVuc2lvbiB0YWJsZSBmb3IgU3RhdGlvbnMKLSBBIERpbWVuc2lvbiB0YWJsZSBmb3IgVXNlcnMKCiFbXShpbWdzL2VyZHBsdXMtZGlhZ3JhbTEucG5nKQoKCgoK