About

Today the lab focuses on data outliers, data preparation, and data modeling. This lab requires the use of Microsoft Excel, R, and ERDplus.

Setup

Make sure to download the folder titled ‘bsad_lab02’ zip folder and extract the folder to unzip it. Next, we must set this folder as the working directory. The way to do this is to open R Studio, go to ‘Session’, scroll down to ‘Set Working Directory’, and click ‘To Source File Location’. Now, follow the directions to complete the lab.


Task 1

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
scoring = read.csv(file = "data/scoring.csv")
#Name the extracted variable
seniority = scoring$Seniority
time = scoring$Time
age = scoring$Age
expenses = scoring$Expenses
income = scoring$Income
assets = scoring$Assets
debt = scoring$Debt
#Calculate the averages below. Refer to Worksheet 1 for the correct command.
Seniority_mean = mean(seniority)
Time_mean = mean(time)
Age_mean = mean(age)
Expenses_mean = mean(expenses)
Income_mean = mean(income)
Assets_mean = mean(assets)
Debt_mean = mean(Debt)

Seniority_mean
Time_mean
Age_mean
Expenses_mean
Income_mean
Assets_mean
Debt_mean
#Calculate standard deviations below. Refer to Worksheet 1 for the correct command. 
Seniority_sd = sd(seniority)
Time_sd = sd(time)
Age_sd = sd(age)
Expenses_sd = sd(expenses)
Income_sd = sd(income)
Assets_sd = sd(assets)
Debt_sd = sd(debt)

Seniority_sd
Time_sd
Age_sd
Expenses_sd
Income_sd
Assets_sd
Debt_sd
#Calculate the maximum of age below. The command to find the maximum is max(variable) where variable is the extracted variable.  
Seniority_max = max(seniority)
Time_max = max(time)
Age_max = max(age)
Expenses_max = max(expenses)
Income_max = max(income)
Assets_max = max(assets)
Debt_max = max(debt)

Seniority_max
Time_max
Age_max
Expenses_max
Income_max
Assets_max
Debt_max
#Calculate the minimum of age below. The command to find the minimum is min(variable) where variable is the extracted variable.  
Seniority__min = min(seniority)
Time_min = min(time)
Age_min = min(age)
Expenses_min = min(expenses)
Income_min = min(income)
Assets_min = min(assets)
Debt_min = min(debt)

Seniority__min
Time_min
Age_min
Expenses_min
Income_min
Assets_min
Debt_min

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

#Upper Threshold
Seniority_upper = Seniority_mean + (3) * Seniority_sd
Time_upper = Time_mean + (3) * Time_sd
Age_upper = Age_mean + (3) * Age_sd
Expenses_upper = Expenses_mean +(3) * Expenses_sd
Income_upper = Income_mean + (3) * Income_sd
Assets_upper = Assets_mean + (3) * Assets_sd
Debt_upper = Debt_mean + (3) * Debt_sd

Seniority_lower = Seniority_mean - (3) * Seniority_sd
Time_lower = Time_mean - (3) * Time_sd
Age_lower = Age_mean - (3) * Age_sd
Expenses_lower = Expenses_mean - (3) * Expenses_sd
Income_lower = Income_mean - (3) * Income_sd
Assets_lower = Assets_mean - (3) * Assets_sd
Debt_lower = Debt_mean - (3) * Debt_sd

Seniority_upper
Time_upper
Age_upper
Expenses_upper
Income_upper
Assets_upper
Debt_upper

Seniority_lower
Time_lower
Age_lower
Expenses_lower
Income_lower
Assets_lower
Debt_lower
#Find the quantile data for seniority
quantile(seniority)
lowerq = quantile(seniority)[2]
upperq = quantile(seniority)[4]

iqr = upperq - lowerq
iqr

The formula below calculates the threshold. The threshold is the boundaries that determine if a value is an outlier. If the value falls above the upper threshold or below the lower threshold, it is an outlier.

Below is the upper threshold:

upperthreshold = (iqr * 1.5) + upperq 
upperthreshold

Below is the lower threshold:

lowerthreshold = lowerq - (iqr * 1.5)
lowerthreshold

Are there any outliers? How many? It can also be useful to visualize the data using a box and whisker plot. The boxplot below supports the IQR we found of 15 and upper and lower threshold.

150 Outliers

seniority[seniority>upperthreshold]
seniority[seniority<lowerthreshold]
boxplot(seniority,horizontal = TRUE)

Task 2

Next, we must read the ‘creditriskorg.csv’ file into R. This is the original dataset and contains missing values.

creditriskorig = read.csv(file = "data/creditriskorg.csv")

head(creditriskorig)

We observe that the column names are shifted down below. So, we must make sure to use the command skip and set the header to true.

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

To calculate the mean for Checking in R, follow Worksheet 1. Extract the Checking column first and then find the average using the function built in R. What happens when we try to use the function?

savings = creditriskorg$Savings
savings

To resolve the error, we must remove understand where it is coming from. There are missing values in the csv file, which 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 numerica symbol either.

The sub function replaces these symbols with something else. So, in order to remove the comma in the number “1,234”, we must substitute it with just an empty space.

As shown on the worksheet, type and copy the exact commands to find the mean with the NA values removed.

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

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

#numeric convert
clean = as.numeric(clean)

#mean with NA removed 
clean

What are some other ways to clean this data in R? How about in Excel? You can represent each unknown symbol as 0 if that is there value. In excel, you’d have to type in specific values.


Task 3

Now, we will look at Chicago taxi data. Go and explore the interactive dashboard and read the description of the data.

Chicago Taxi Dashboard: https://data.cityofchicago.org/Transportation/Taxi-Trips-Dashboard/spcw-brbq

Chicago Taxi Data Description: http://digital.cityofchicago.org/index.php/chicago-taxi-data-released/

Open in RStudio the csv file is located in the data folder, note the size of the file, the number of columns and of rows here. Use the functions learned in lab00 and lab01 to describe the data, identify unique entities, fields and summarize.

taxidata = read.csv(file = "data/taxi_trips_sample.csv")
Trip_Seconds = taxidata$Trip.Seconds
Trip_Seconds_max = max(Trip_Seconds)
Trip_Seconds_min = min(Trip_Seconds)
Trip_Seconds_mean = mean(Trip_Seconds)
Trip_Seconds_sd = sd(Trip_Seconds)

Define a relational business logic for the column field ‘Trip Seconds’.

Star Schema: Chicago Taxi

LS0tDQp0aXRsZTogIkJ1c2luZXNzIEFuYWx5dGljcyBMYWIgV29ya3NoZWV0IDAyIg0KYXV0aG9yOiAiTWFyayBHcnVobGtlIg0KZGF0ZTogIlN1bW1lciAyMDE3Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQpzdWJ0aXRsZTogQ01FIEdyb3VwIEZvdW5kYXRpb24gQnVzaW5lc3MgQW5hbHl0aWNzIExhYg0KLS0tDQoNCiMjIyBBYm91dA0KDQpUb2RheSB0aGUgbGFiIGZvY3VzZXMgb24gZGF0YSBvdXRsaWVycywgZGF0YSBwcmVwYXJhdGlvbiwgYW5kIGRhdGEgbW9kZWxpbmcuIFRoaXMgbGFiIHJlcXVpcmVzIHRoZSB1c2Ugb2YgTWljcm9zb2Z0IEV4Y2VsLCBSLCBhbmQgRVJEcGx1cy4NCg0KIyMjIFNldHVwDQoNCk1ha2Ugc3VyZSB0byBkb3dubG9hZCB0aGUgZm9sZGVyIHRpdGxlZCAnYnNhZF9sYWIwMicgemlwIGZvbGRlciBhbmQgZXh0cmFjdCB0aGUgZm9sZGVyIHRvIHVuemlwIGl0LiBOZXh0LCB3ZSBtdXN0IHNldCB0aGlzIGZvbGRlciBhcyB0aGUgd29ya2luZyBkaXJlY3RvcnkuIFRoZQ0Kd2F5IHRvIGRvIHRoaXMgaXMgdG8gb3BlbiBSIFN0dWRpbywgZ28gdG8gJ1Nlc3Npb24nLCBzY3JvbGwgZG93biB0byAnU2V0IFdvcmtpbmcgRGlyZWN0b3J5JywgYW5kIGNsaWNrICdUbyBTb3VyY2UgRmlsZSBMb2NhdGlvbicuIE5vdywgZm9sbG93IHRoZSBkaXJlY3Rpb25zIHRvIGNvbXBsZXRlIHRoZSBsYWIuDQoNCi0tLS0tLS0tLQ0KDQojIyMgVGFzayAxDQoNCkZpcnN0LCB3ZSBtdXN0IGNhbGN1bGF0ZSB0aGUgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uLCBtYXhpbXVtLCBhbmQgbWluaW11bSBmb3IgdGhlIEFnZSBjb2x1bW4gdXNpbmcgUi4NCg0KSW4gUiwgd2UgbXVzdCByZWFkIGluIHRoZSBmaWxlIGFnYWluLCBleHRyYWN0IHRoZSBjb2x1bW4gYW5kIGZpbmQgdGhlIHZhbHVlcyB0aGF0IGFyZSBhc2tlZCBmb3IuDQoNCmBgYHtyfQ0KI1JlYWQgRmlsZQ0Kc2NvcmluZyA9IHJlYWQuY3N2KGZpbGUgPSAiZGF0YS9zY29yaW5nLmNzdiIpDQojTmFtZSB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlDQpzZW5pb3JpdHkgPSBzY29yaW5nJFNlbmlvcml0eQ0KdGltZSA9IHNjb3JpbmckVGltZQ0KYWdlID0gc2NvcmluZyRBZ2UNCmV4cGVuc2VzID0gc2NvcmluZyRFeHBlbnNlcw0KaW5jb21lID0gc2NvcmluZyRJbmNvbWUNCmFzc2V0cyA9IHNjb3JpbmckQXNzZXRzDQpkZWJ0ID0gc2NvcmluZyREZWJ0DQpgYGANCg0KYGBge3J9DQojQ2FsY3VsYXRlIHRoZSBhdmVyYWdlcyBiZWxvdy4gUmVmZXIgdG8gV29ya3NoZWV0IDEgZm9yIHRoZSBjb3JyZWN0IGNvbW1hbmQuDQpTZW5pb3JpdHlfbWVhbiA9IG1lYW4oc2VuaW9yaXR5KQ0KVGltZV9tZWFuID0gbWVhbih0aW1lKQ0KQWdlX21lYW4gPSBtZWFuKGFnZSkNCkV4cGVuc2VzX21lYW4gPSBtZWFuKGV4cGVuc2VzKQ0KSW5jb21lX21lYW4gPSBtZWFuKGluY29tZSkNCkFzc2V0c19tZWFuID0gbWVhbihhc3NldHMpDQpEZWJ0X21lYW4gPSBtZWFuKERlYnQpDQoNClNlbmlvcml0eV9tZWFuDQpUaW1lX21lYW4NCkFnZV9tZWFuDQpFeHBlbnNlc19tZWFuDQpJbmNvbWVfbWVhbg0KQXNzZXRzX21lYW4NCkRlYnRfbWVhbg0KYGBgDQoNCmBgYHtyfQ0KI0NhbGN1bGF0ZSBzdGFuZGFyZCBkZXZpYXRpb25zIGJlbG93LiBSZWZlciB0byBXb3Jrc2hlZXQgMSBmb3IgdGhlIGNvcnJlY3QgY29tbWFuZC4gDQpTZW5pb3JpdHlfc2QgPSBzZChzZW5pb3JpdHkpDQpUaW1lX3NkID0gc2QodGltZSkNCkFnZV9zZCA9IHNkKGFnZSkNCkV4cGVuc2VzX3NkID0gc2QoZXhwZW5zZXMpDQpJbmNvbWVfc2QgPSBzZChpbmNvbWUpDQpBc3NldHNfc2QgPSBzZChhc3NldHMpDQpEZWJ0X3NkID0gc2QoZGVidCkNCg0KU2VuaW9yaXR5X3NkDQpUaW1lX3NkDQpBZ2Vfc2QNCkV4cGVuc2VzX3NkDQpJbmNvbWVfc2QNCkFzc2V0c19zZA0KRGVidF9zZA0KYGBgDQoNCmBgYHtyfQ0KI0NhbGN1bGF0ZSB0aGUgbWF4aW11bSBvZiBhZ2UgYmVsb3cuIFRoZSBjb21tYW5kIHRvIGZpbmQgdGhlIG1heGltdW0gaXMgbWF4KHZhcmlhYmxlKSB3aGVyZSB2YXJpYWJsZSBpcyB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlLiAgDQpTZW5pb3JpdHlfbWF4ID0gbWF4KHNlbmlvcml0eSkNClRpbWVfbWF4ID0gbWF4KHRpbWUpDQpBZ2VfbWF4ID0gbWF4KGFnZSkNCkV4cGVuc2VzX21heCA9IG1heChleHBlbnNlcykNCkluY29tZV9tYXggPSBtYXgoaW5jb21lKQ0KQXNzZXRzX21heCA9IG1heChhc3NldHMpDQpEZWJ0X21heCA9IG1heChkZWJ0KQ0KDQpTZW5pb3JpdHlfbWF4DQpUaW1lX21heA0KQWdlX21heA0KRXhwZW5zZXNfbWF4DQpJbmNvbWVfbWF4DQpBc3NldHNfbWF4DQpEZWJ0X21heA0KYGBgDQoNCmBgYHtyfQ0KI0NhbGN1bGF0ZSB0aGUgbWluaW11bSBvZiBhZ2UgYmVsb3cuIFRoZSBjb21tYW5kIHRvIGZpbmQgdGhlIG1pbmltdW0gaXMgbWluKHZhcmlhYmxlKSB3aGVyZSB2YXJpYWJsZSBpcyB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlLiAgDQpTZW5pb3JpdHlfX21pbiA9IG1pbihzZW5pb3JpdHkpDQpUaW1lX21pbiA9IG1pbih0aW1lKQ0KQWdlX21pbiA9IG1pbihhZ2UpDQpFeHBlbnNlc19taW4gPSBtaW4oZXhwZW5zZXMpDQpJbmNvbWVfbWluID0gbWluKGluY29tZSkNCkFzc2V0c19taW4gPSBtaW4oYXNzZXRzKQ0KRGVidF9taW4gPSBtaW4oZGVidCkNCg0KU2VuaW9yaXR5X19taW4NClRpbWVfbWluDQpBZ2VfbWluDQpFeHBlbnNlc19taW4NCkluY29tZV9taW4NCkFzc2V0c19taW4NCkRlYnRfbWluDQpgYGANCg0KTmV4dCwgdXNlIHRoZSBmb3JtdWxhIGZyb20gY2xhc3MgdG8gZGV0ZWN0IGFueSBvdXRsaWVycy4gQW4gb3V0bGllciBpcyB2YWx1ZSB0aGF0ICJsaWVzIG91dHNpZGUiIG1vc3Qgb2YgdGhlIG90aGVyIHZhbHVlcyBpbiBhIHNldCBvZiBkYXRhLiBBIGNvbW1vbiB3YXkgdG8gZXN0aW1hdGUgdGhlIHVwcGVyIGFuZCBsb3dlciB0aHJlc2hvbGQgaXMgdG8gdGFrZSB0aGUgYGBgbWVhbiAoKyBvciAtKSAzICogc3RhbmRhcmQgZGV2aWF0aW9uYGBgLiBUcnkgdXNpbmcgdGhpcyBmb3JtdWxhIHRvIGZpbmQgdGhlIHVwcGVyIGFuZCBsb3dlciBsaW1pdCBmb3IgYWdlLiANCg0KYGBge3J9DQojVXBwZXIgVGhyZXNob2xkDQpTZW5pb3JpdHlfdXBwZXIgPSBTZW5pb3JpdHlfbWVhbiArICgzKSAqIFNlbmlvcml0eV9zZA0KVGltZV91cHBlciA9IFRpbWVfbWVhbiArICgzKSAqIFRpbWVfc2QNCkFnZV91cHBlciA9IEFnZV9tZWFuICsgKDMpICogQWdlX3NkDQpFeHBlbnNlc191cHBlciA9IEV4cGVuc2VzX21lYW4gKygzKSAqIEV4cGVuc2VzX3NkDQpJbmNvbWVfdXBwZXIgPSBJbmNvbWVfbWVhbiArICgzKSAqIEluY29tZV9zZA0KQXNzZXRzX3VwcGVyID0gQXNzZXRzX21lYW4gKyAoMykgKiBBc3NldHNfc2QNCkRlYnRfdXBwZXIgPSBEZWJ0X21lYW4gKyAoMykgKiBEZWJ0X3NkDQoNClNlbmlvcml0eV9sb3dlciA9IFNlbmlvcml0eV9tZWFuIC0gKDMpICogU2VuaW9yaXR5X3NkDQpUaW1lX2xvd2VyID0gVGltZV9tZWFuIC0gKDMpICogVGltZV9zZA0KQWdlX2xvd2VyID0gQWdlX21lYW4gLSAoMykgKiBBZ2Vfc2QNCkV4cGVuc2VzX2xvd2VyID0gRXhwZW5zZXNfbWVhbiAtICgzKSAqIEV4cGVuc2VzX3NkDQpJbmNvbWVfbG93ZXIgPSBJbmNvbWVfbWVhbiAtICgzKSAqIEluY29tZV9zZA0KQXNzZXRzX2xvd2VyID0gQXNzZXRzX21lYW4gLSAoMykgKiBBc3NldHNfc2QNCkRlYnRfbG93ZXIgPSBEZWJ0X21lYW4gLSAoMykgKiBEZWJ0X3NkDQoNClNlbmlvcml0eV91cHBlcg0KVGltZV91cHBlcg0KQWdlX3VwcGVyDQpFeHBlbnNlc191cHBlcg0KSW5jb21lX3VwcGVyDQpBc3NldHNfdXBwZXINCkRlYnRfdXBwZXINCg0KU2VuaW9yaXR5X2xvd2VyDQpUaW1lX2xvd2VyDQpBZ2VfbG93ZXINCkV4cGVuc2VzX2xvd2VyDQpJbmNvbWVfbG93ZXINCkFzc2V0c19sb3dlcg0KRGVidF9sb3dlcg0KYGBgDQoNCmBgYHtyfSANCiNGaW5kIHRoZSBxdWFudGlsZSBkYXRhIGZvciBzZW5pb3JpdHkNCnF1YW50aWxlKHNlbmlvcml0eSkNCmxvd2VycSA9IHF1YW50aWxlKHNlbmlvcml0eSlbMl0NCnVwcGVycSA9IHF1YW50aWxlKHNlbmlvcml0eSlbNF0NCg0KaXFyID0gdXBwZXJxIC0gbG93ZXJxDQppcXINCmBgYA0KDQpUaGUgZm9ybXVsYSBiZWxvdyBjYWxjdWxhdGVzIHRoZSB0aHJlc2hvbGQuIFRoZSB0aHJlc2hvbGQgaXMgdGhlIGJvdW5kYXJpZXMgdGhhdCBkZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhbiBvdXRsaWVyLiBJZiB0aGUgdmFsdWUgZmFsbHMgYWJvdmUgdGhlIHVwcGVyIHRocmVzaG9sZCBvciBiZWxvdyB0aGUgbG93ZXIgdGhyZXNob2xkLCBpdCBpcyBhbiBvdXRsaWVyLiANCg0KQmVsb3cgaXMgdGhlIHVwcGVyIHRocmVzaG9sZDoNCmBgYHtyfSANCnVwcGVydGhyZXNob2xkID0gKGlxciAqIDEuNSkgKyB1cHBlcnEgDQp1cHBlcnRocmVzaG9sZA0KYGBgDQoNCkJlbG93IGlzIHRoZSBsb3dlciB0aHJlc2hvbGQ6DQpgYGB7cn0NCmxvd2VydGhyZXNob2xkID0gbG93ZXJxIC0gKGlxciAqIDEuNSkNCmxvd2VydGhyZXNob2xkDQpgYGANCg0KQXJlIHRoZXJlIGFueSBvdXRsaWVycz8gSG93IG1hbnk/IEl0IGNhbiBhbHNvIGJlIHVzZWZ1bCB0byB2aXN1YWxpemUgdGhlIGRhdGEgdXNpbmcgYSBib3ggYW5kIHdoaXNrZXIgcGxvdC4gVGhlIGJveHBsb3QgYmVsb3cgc3VwcG9ydHMgdGhlIElRUiB3ZSBmb3VuZCBvZiAxNSBhbmQgdXBwZXIgYW5kIGxvd2VyIHRocmVzaG9sZC4NCg0KMTUwIE91dGxpZXJzDQoNCmBgYHtyfSANCnNlbmlvcml0eVtzZW5pb3JpdHk+dXBwZXJ0aHJlc2hvbGRdDQpzZW5pb3JpdHlbc2VuaW9yaXR5PGxvd2VydGhyZXNob2xkXQ0KYGBgDQpgYGB7cn0NCmJveHBsb3Qoc2VuaW9yaXR5LGhvcml6b250YWwgPSBUUlVFKQ0KYGBgDQotLS0tLS0tLS0tLS0tLS0NCg0KIyMjIFRhc2sgMg0KDQpOZXh0LCB3ZSBtdXN0IHJlYWQgdGhlICdjcmVkaXRyaXNrb3JnLmNzdicgZmlsZSBpbnRvIFIuIFRoaXMgaXMgdGhlIG9yaWdpbmFsIGRhdGFzZXQgYW5kIGNvbnRhaW5zIG1pc3NpbmcgdmFsdWVzLiANCg0KYGBge3J9DQpjcmVkaXRyaXNrb3JpZyA9IHJlYWQuY3N2KGZpbGUgPSAiZGF0YS9jcmVkaXRyaXNrb3JnLmNzdiIpDQoNCmhlYWQoY3JlZGl0cmlza29yaWcpDQoNCmBgYA0KDQpXZSBvYnNlcnZlIHRoYXQgdGhlIGNvbHVtbiBuYW1lcyBhcmUgc2hpZnRlZCBkb3duIGJlbG93LiBTbywgd2UgbXVzdCBtYWtlIHN1cmUgdG8gdXNlIHRoZSBjb21tYW5kIHNraXAgYW5kIHNldCB0aGUgaGVhZGVyIHRvIHRydWUuDQoNCmBgYHtyfQ0KY3JlZGl0cmlza29yZyA9IHJlYWQuY3N2KCJkYXRhL2NyZWRpdHJpc2tvcmcuY3N2Iixza2lwID0gMSkNCmhlYWQoY3JlZGl0cmlza29yZykNCmBgYA0KDQoNClRvIGNhbGN1bGF0ZSB0aGUgbWVhbiBmb3IgQ2hlY2tpbmcgaW4gUiwgZm9sbG93IFdvcmtzaGVldCAxLiBFeHRyYWN0IHRoZSBDaGVja2luZyBjb2x1bW4gZmlyc3QgYW5kIHRoZW4gZmluZCB0aGUgYXZlcmFnZSB1c2luZyB0aGUgZnVuY3Rpb24gYnVpbHQgaW4gUi4NCldoYXQgaGFwcGVucyB3aGVuIHdlIHRyeSB0byB1c2UgdGhlIGZ1bmN0aW9uPw0KDQpgYGB7cn0NCnNhdmluZ3MgPSBjcmVkaXRyaXNrb3JnJFNhdmluZ3MNCnNhdmluZ3MNCmBgYA0KDQpUbyByZXNvbHZlIHRoZSBlcnJvciwgd2UgbXVzdCByZW1vdmUgdW5kZXJzdGFuZCB3aGVyZSBpdCBpcyBjb21pbmcgZnJvbS4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGluIHRoZSBjc3YgZmlsZSwgd2hpY2ggaXMgcXVpdGUgY29tbW9uIGFzIG1vc3QgZGF0YXNldHMgYXJlIG5vdCBwZXJmZWN0LiBBZGRpdGlvbmFsbHksIHRoZXJlIGFyZSBjb21tYXMgd2l0aGluIHRoZSBleGNlbCBzcHJlYWRzaGVldCwgYW5kIFIgZG9lcyBub3QgcmVjb2duaXplIHRoYXQgJzEsMjM0JyBpcyBlcXVpdmFsZW50IHRvICcxMjM0Jy4gTGFzdGx5LCB0aGVyZSBhcmUgJyQnIHN5bWJvbHMgdGhyb3VnaG91dCB0aGUgZmlsZSB3aGljaCBpcyBub3QgYSBudW1lcmljYSBzeW1ib2wgZWl0aGVyLg0KDQpUaGUgc3ViIGZ1bmN0aW9uIHJlcGxhY2VzIHRoZXNlIHN5bWJvbHMgd2l0aCBzb21ldGhpbmcgZWxzZS4gU28sIGluIG9yZGVyIHRvIHJlbW92ZSB0aGUgY29tbWEgaW4gdGhlIG51bWJlciAiMSwyMzQiLCB3ZSBtdXN0IHN1YnN0aXR1dGUgaXQgd2l0aCBqdXN0IGFuIGVtcHR5IHNwYWNlLg0KDQpBcyBzaG93biBvbiB0aGUgd29ya3NoZWV0LCB0eXBlIGFuZCBjb3B5IHRoZSBleGFjdCBjb21tYW5kcyB0byBmaW5kIHRoZSBtZWFuIHdpdGggdGhlIE5BIHZhbHVlcyByZW1vdmVkLg0KDQpgYGB7cn0gDQpjbGVhbiA9IHNhdmluZ3MNCiNzdWJzdGl0dXRlIGNvbW1hIHdpdGggYmxhbmsgaW4gYWxsIG9mIGNoZWNraW5nIA0KY2xlYW4gPSBzdWIoIiwiLCIiLGNsZWFuKQ0KDQojc3Vic3RpdHV0ZSBkb2xsYXIgc2lnbiB3aXRoIGJsYW5rIGluIGFsbCBvZiBjaGVja2luZyANCmNsZWFuID0gc3ViKCJcXCQiLCIiLGNsZWFuKQ0KDQojbnVtZXJpYyBjb252ZXJ0DQpjbGVhbiA9IGFzLm51bWVyaWMoY2xlYW4pDQoNCiNtZWFuIHdpdGggTkEgcmVtb3ZlZCANCmNsZWFuDQpgYGANCg0KV2hhdCBhcmUgc29tZSBvdGhlciB3YXlzIHRvIGNsZWFuIHRoaXMgZGF0YSBpbiBSPyBIb3cgYWJvdXQgaW4gRXhjZWw/IA0KWW91IGNhbiByZXByZXNlbnQgZWFjaCB1bmtub3duIHN5bWJvbCBhcyAwIGlmIHRoYXQgaXMgdGhlcmUgdmFsdWUuIEluIGV4Y2VsLCB5b3UnZCBoYXZlIHRvIHR5cGUgaW4gc3BlY2lmaWMgdmFsdWVzLg0KDQotLS0tLS0tLS0tLS0tDQoNCiMjIyBUYXNrIDMNCg0KTm93LCB3ZSB3aWxsIGxvb2sgYXQgQ2hpY2FnbyB0YXhpIGRhdGEuIEdvIGFuZCBleHBsb3JlIHRoZSBpbnRlcmFjdGl2ZSBkYXNoYm9hcmQgYW5kIHJlYWQgdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLg0KDQpDaGljYWdvIFRheGkgRGFzaGJvYXJkOiBbaHR0cHM6Ly9kYXRhLmNpdHlvZmNoaWNhZ28ub3JnL1RyYW5zcG9ydGF0aW9uL1RheGktVHJpcHMtRGFzaGJvYXJkL3NwY3ctYnJicV0oaHR0cHM6Ly9kYXRhLmNpdHlvZmNoaWNhZ28ub3JnL1RyYW5zcG9ydGF0aW9uL1RheGktVHJpcHMtRGFzaGJvYXJkL3NwY3ctYnJicSkNCg0KQ2hpY2FnbyBUYXhpIERhdGEgRGVzY3JpcHRpb246DQpbaHR0cDovL2RpZ2l0YWwuY2l0eW9mY2hpY2Fnby5vcmcvaW5kZXgucGhwL2NoaWNhZ28tdGF4aS1kYXRhLXJlbGVhc2VkL10oaHR0cDovL2RpZ2l0YWwuY2l0eW9mY2hpY2Fnby5vcmcvaW5kZXgucGhwL2NoaWNhZ28tdGF4aS1kYXRhLXJlbGVhc2VkLykgDQoNCk9wZW4gaW4gUlN0dWRpbyB0aGUgY3N2IGZpbGUgaXMgbG9jYXRlZCBpbiB0aGUgZGF0YSBmb2xkZXIsIG5vdGUgdGhlIHNpemUgb2YgdGhlIGZpbGUsIHRoZSBudW1iZXIgb2YgY29sdW1ucyBhbmQgb2Ygcm93cyBoZXJlLiBVc2UgdGhlIGZ1bmN0aW9ucyBsZWFybmVkIGluIGxhYjAwIGFuZCBsYWIwMSB0byBkZXNjcmliZSB0aGUgZGF0YSwgaWRlbnRpZnkgdW5pcXVlIGVudGl0aWVzLCBmaWVsZHMgYW5kIHN1bW1hcml6ZS4NCmBgYHtyfQ0KdGF4aWRhdGEgPSByZWFkLmNzdihmaWxlID0gImRhdGEvdGF4aV90cmlwc19zYW1wbGUuY3N2IikNClRyaXBfU2Vjb25kcyA9IHRheGlkYXRhJFRyaXAuU2Vjb25kcw0KVHJpcF9TZWNvbmRzX21heCA9IG1heChUcmlwX1NlY29uZHMpDQpUcmlwX1NlY29uZHNfbWluID0gbWluKFRyaXBfU2Vjb25kcykNClRyaXBfU2Vjb25kc19tZWFuID0gbWVhbihUcmlwX1NlY29uZHMpDQpUcmlwX1NlY29uZHNfc2QgPSBzZChUcmlwX1NlY29uZHMpDQpgYGANCg0KRGVmaW5lIGEgcmVsYXRpb25hbCBidXNpbmVzcyBsb2dpYyBmb3IgdGhlIGNvbHVtbiBmaWVsZCAnVHJpcCBTZWNvbmRzJy4NCg0KU3RhciBTY2hlbWE6DQohW0NoaWNhZ28gVGF4aV0oZGF0YS9pbWcwMS5wbmcpDQo=