About
R can be used to make basic visual analytics, which can be helpful in understanding the data holistically. Additionally, R can help find correlations between variables and create scatter plots.
In this lab we will delve deeper into the marketing data set with R visual analytics and use Tableau to visualize the credit risk data set.
Setup
Make sure to download the folder titled ‘bsad_lab04’ 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, read in the creditrisk.csv file and make sure all the columns are captured and check the first couple of rows of the dataset “head(mydata)”
#mydata = read.csv(file="data/creditrisk.csv")
mydata = read.csv("data/states_purchase_orders.csv")
dept_name = mydata$DEPARTMENT.NAME
For CATEGORICAL variables it is useful to know the frequency of the different categories/levels of the variable. We can do that by using the table() function.
- Create a frequency table for the Loan Purpose and Job
# Command to create a frequency table: variable_table = table(variable)
# variable_table
dept_table = table(dept_name)
dept_table
Now, we will visualize some of the veriables to observe some patterns and differences.
First create a bar chart of the loan purpose frequency table and job frequency table Remember to extract the sales variable before calling it.
VARIABLES: Job and Loan Purpose
# Plot a bar plot using the " barplot(variable) " command where variable is the extracted variable
barplot(dept_table)
Next, create a histogram of loan purpose frequency table and job frequency table
# Plot a histogram using the " hist(variable) " command where variable is the extracted variable
hist(dept_table)
- What are some observable differences between the boxplot and the histogram? Please record your observations here.
Lastly, create a pie chart of Loan purpose frequency table. Plot only values greather than 10.
VARIABLE: Loan Purpose
# Plot a pie chart using:
# pie(variable) (command to make a pie chart)
# To get only values greather than N from a frequency table use:
# new_table = my_table[ my_table > N ] (command to select values greather than N)
new_table = dept_table[ dept_table > 2000 ]
pie(new_table)
Why is this visual not a good representation of the data? What makes the barplot a better representation?
Task 2
Lets explore the Illinois Tax dataset (READ the “state_tax_illinois.csv” file) and create a scatterplot of corporate tax vs. personal income tax.
The dataset start in 1994 but we want to tax revenue since 2000 for the first quarter of the year “Q1”
VARIABLES: personal_income_tax and corporate_income_tax
mydata = read.csv("data/state_tax_illinois.csv")
# To change the way that R shows very large or small values we can use the following command:
options(scipen = 9999)
# read the dataset extract the year variable and order the dataset by year in decreasing order using the command:
year = mydata$year
# mydata = mydata[ order(year, decreasing = TRUE) , ] (! Order the data in decreasing order)
mydata = mydata[ order(year,decreasing = TRUE), ]
# From the ordered dataset Extract personal_income_tax variable
us_tax = mydata$total_tax_US
# From the ordered dataset Extract corporate_income_tax variable
state = mydata$total_state
The previous task focused on visualizing one variable. A good way to visualize two variables would be a scatter plot or a correlation matrix.
# Plot personal_income_tax vs. corporate_income_tax
# personal_income_tax will be on the x-axis
# corporate_income_tax will be on the y-axis
plot(X_VARIABLE,Y_VARIABLE)
plot(mydata)
plot(state,us_tax)
- Select only entries grather than year 1999
- After selecting entries greather than year 1999, select entries for quarter “Q1”
# To create a new_data filtering for an N NUMERIC value we can do the following
# new_data = mydata[ mydata$NUMERIC_VARIABLE > N , ]
new_data = mydata[ mydata$year<2000 , ]
# If we need to make another filter on a NON-NUMERIC we can do the following
# new_data = new_data[ new_data$CHAR_VARIABLE == "Q1", ]
new_data = new_data[ new_data$quarter == "Q4" , ]
head(new_data)
It might be easier to notice a trend if there was a line that fit through the points. So, lets repeat using the function ‘scatter.smooth’. This functions adds a smooth curve computed by loess, a method to locally smooth a curve.
us_tax = new_data$total_tax_US
state = new_data$total_state
scatter.smooth(us_tax,state)
Now, repeat below for total_tax_US vs. total_state, following the example that was just provided. Observe and note any trends in the scatter plots and potential relationships below. Do the same for all numeric variables.
# total_tax_US vs. total_state
scatter.smooth(new_data$motor_fuel_tax,new_data$personal_income_tax)
To quantify the data, its best to look at the correlation between two variables. What does this correlation explain?
cor(new_data[3:8])
Below, compute the correlation between every pair of variables (total_tax_US,total_state, personal_income_tax, corporate_income_tax, general_sales_tax, motor_fuel_tax ).
Make sure to extract the variables first and then compute the correlation.
# To make a correlation table of all the NUMERIC variables you can select some columns or a range of columns, with the following command:
# corr01 = mydata[ c(3,4) ] (The command c(3,4,...) inside the brackets selects a given column )
# cor(corr01) (will give you the correlation table for variables in columns 3 and 4)
# corr02 = mydata[3:5] ( the command [3:5] selects a range of columns from 3 to 5)
# cor(corr02)
Task 3 - TABLEAU
Follow the directions on the worksheet, download tableau academic on your personal computer or use one of the labs computers.
Refer to file ‘states_purchase_orders.csv’ in the data folder
Start Tableau and enter your LUC email if prompted.
Import the file into Tableau. Choose the Text File option when importing
- Under the dimensions tab located on the left side of the screen.
DOUBLE click on the ‘Department.Name’, then DOUBLE click on ‘Number of Records’ variable located on the bottom left of the screen. Note the bar like view and breakdowns.
- What department ‘bin’ has the highest count? What is the count?
- From the upper right corner of the screen select other views (select one of the other views, talk about it and post an screenshot)
# Change the image for your screenshots and MAKE COMMENTS
- Create a new sheet by clicking on the icon next to your current sheet.
Then DOUBLE click on ‘Number of Records’ variable then DOUBLE click on ‘Vendor.Zip’, then on the top left select the recommend view.
- What are the highlights on the map?
- Can you give an explanation of why there is a concentration on a particular region?
# Change the image for your screenshots and MAKE COMMENTS
Final Project Review
- After reviewing your data and defined your problem, you need to prepare and analize your data.
mydata = read.csv("data/cps_progress_report.csv")
head(mydata)
Identify variables that are relevant to your problem (model). Here we are using attedance as the Y-variable or predicted variables. The other variables are independent variables that could influence the attendance rate.
Clean and set the correct datatype
#### Dependent Variable (Y) - Predicted
Y_attendance_2011 = sub("%","",Y_attendance_2011) # Remove % sign from the values
Y_attendance_2011 = as.numeric(Y_attendance_2011) # Changing from character to numeric
#### Independent Variables (X1,X2,X3,... ) - Predictors
X1_grades_2011 = sub("%", "", X1_grades_2011)
X1_grades_2011 = as.numeric(X1_grades_2011)
X2_graduation_2011 = sub("%" , "" , X2_graduation_2011)
X2_graduation_2011 = as.numeric(X2_graduation_2011)
# Enviroment has different levels Weak, Strong, Very Strong ... hence its a categorical variable. We use the functions as.factor() to transform a character variable to factor
X3_enviroment_2011 = as.factor(X3_enviroment_2011)
Now start analyzing the relation between your independent variables (X1,X2,X3,…) and the dependent variable/predictor (Y).
scatter.smooth(Y_attendance_2011, X1_grades_2011)

scatter.smooth(Y_attendance_2011,X2_graduation_2011)

plot(X3_enviroment_2011,Y_attendance_2011)

Now that we look at the relation and interaction between that independent variables (x1,X2,X3,…) and dependent variable (y). We can build a predicted model.
## Build a model Y_Predicted ~ X1 + X2 + X3 ...
## How your independent variables (X1,X2,X3,...) interact with your dependent variable (Y_predicted)
# For this case how grades, graduation and enviroment affect attendance of students at a CPS school in 2011
# Linear Model Function - lm()
model_2011 = lm( Y_attendance_2011 ~ X1_grades_2011 + X2_graduation_2011 + X3_enviroment_2011)
summary(model_2011)
Call:
lm(formula = Y_attendance_2011 ~ X1_grades_2011 + X2_graduation_2011 +
X3_enviroment_2011)
Residuals:
Min 1Q Median 3Q Max
-18.8254 -4.0402 -0.4652 4.6193 9.6816
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 54.08827 5.70941 9.474 5.47e-14 ***
X1_grades_2011 0.20205 0.11039 1.830 0.0717 .
X2_graduation_2011 0.26619 0.05636 4.723 1.23e-05 ***
X3_enviroment_2011Not Enough Data 3.70131 2.81286 1.316 0.1927
X3_enviroment_2011Strong 5.97264 2.52024 2.370 0.0207 *
X3_enviroment_2011Very Strong -0.61935 4.92062 -0.126 0.9002
X3_enviroment_2011Weak -3.61651 1.81628 -1.991 0.0505 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 6.058 on 67 degrees of freedom
(18 observations deleted due to missingness)
Multiple R-squared: 0.5717, Adjusted R-squared: 0.5334
F-statistic: 14.91 on 6 and 67 DF, p-value: 9.599e-11
Notice the Adjusted R-squared value (coefficient of determination), that determines how close the data are to the fitted regression line. ( 0% indicates that the model explains none of the variability of the response data around its mean )
LS0tCnRpdGxlOiAiQnVzaW5lc3MgQW5hbHl0aWNzIExhYiBXb3Jrc2hlZXQgMDQiCmF1dGhvcjogIllvdXIgTmFtZSBIZXJlIgpkYXRlOiAiU3VtbWVyIDIwMTciCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdApzdWJ0aXRsZTogQ01FIEdyb3VwIEZvdW5kYXRpb24gQnVzaW5lc3MgQW5hbHl0aWNzIExhYgotLS0KCiMjIyBBYm91dAoKUiBjYW4gYmUgdXNlZCB0byBtYWtlIGJhc2ljIHZpc3VhbCBhbmFseXRpY3MsIHdoaWNoIGNhbiBiZSBoZWxwZnVsIGluIHVuZGVyc3RhbmRpbmcgdGhlIGRhdGEgaG9saXN0aWNhbGx5LiBBZGRpdGlvbmFsbHksIFIgY2FuIGhlbHAgZmluZCBjb3JyZWxhdGlvbnMgYmV0d2VlbiB2YXJpYWJsZXMgYW5kIGNyZWF0ZSBzY2F0dGVyIHBsb3RzLiAKCkluIHRoaXMgbGFiIHdlIHdpbGwgZGVsdmUgZGVlcGVyIGludG8gdGhlIG1hcmtldGluZyBkYXRhIHNldCB3aXRoIFIgdmlzdWFsIGFuYWx5dGljcyBhbmQgdXNlIFRhYmxlYXUgdG8gdmlzdWFsaXplIHRoZSBjcmVkaXQgcmlzayBkYXRhIHNldC4gCgojIyMgU2V0dXAKCk1ha2Ugc3VyZSB0byBkb3dubG9hZCB0aGUgZm9sZGVyIHRpdGxlZCAnYnNhZF9sYWIwNCcgemlwIGZvbGRlciBhbmQgZXh0cmFjdCB0aGUgZm9sZGVyIHRvIHVuemlwIGl0LiBOZXh0LCB3ZSBtdXN0IHNldCB0aGlzIGZvbGRlciBhcyB0aGUgd29ya2luZyBkaXJlY3RvcnkuIFRoZSB3YXkgdG8gZG8gdGhpcyBpcyB0byBvcGVuIFIgU3R1ZGlvLCBnbyB0byAnU2Vzc2lvbicsIHNjcm9sbCBkb3duIHRvICdTZXQgV29ya2luZyBEaXJlY3RvcnknLCBhbmQgY2xpY2sgJ1RvIFNvdXJjZSBGaWxlIExvY2F0aW9uJy4gTm93LCBmb2xsb3cgdGhlIGRpcmVjdGlvbnMgdG8gY29tcGxldGUgdGhlIGxhYi4KCi0tLS0tLS0tLS0KCgojIyMgVGFzayAxCgpGaXJzdCwgcmVhZCBpbiB0aGUgYGNyZWRpdHJpc2suY3N2YCBmaWxlIGFuZCBtYWtlIHN1cmUgYWxsIHRoZSBjb2x1bW5zIGFyZSBjYXB0dXJlZCBhbmQgY2hlY2sgdGhlIGZpcnN0IGNvdXBsZSBvZiByb3dzIG9mIHRoZSBkYXRhc2V0ICJoZWFkKG15ZGF0YSkiCgpgYGB7cn0KI215ZGF0YSA9IHJlYWQuY3N2KGZpbGU9ImRhdGEvY3JlZGl0cmlzay5jc3YiKQpteWRhdGEgPSByZWFkLmNzdigiZGF0YS9zdGF0ZXNfcHVyY2hhc2Vfb3JkZXJzLmNzdiIpCmRlcHRfbmFtZSA9IG15ZGF0YSRERVBBUlRNRU5ULk5BTUUKYGBgCgoKRm9yIENBVEVHT1JJQ0FMIHZhcmlhYmxlcyBpdCBpcyB1c2VmdWwgdG8ga25vdyB0aGUgZnJlcXVlbmN5IG9mIHRoZSBkaWZmZXJlbnQgY2F0ZWdvcmllcy9sZXZlbHMgb2YgdGhlIHZhcmlhYmxlLiBXZSBjYW4gZG8gdGhhdCBieSB1c2luZyB0aGUgdGFibGUoKSBmdW5jdGlvbi4gCgoqIENyZWF0ZSBhIGZyZXF1ZW5jeSB0YWJsZSBmb3IgdGhlIExvYW4gUHVycG9zZSBhbmQgSm9iCmBgYHtyfQojIENvbW1hbmQgdG8gY3JlYXRlIGEgZnJlcXVlbmN5IHRhYmxlOiB2YXJpYWJsZV90YWJsZSA9IHRhYmxlKHZhcmlhYmxlKSAKIyB2YXJpYWJsZV90YWJsZQpkZXB0X3RhYmxlID0gdGFibGUoZGVwdF9uYW1lKSAKZGVwdF90YWJsZQpgYGAKCk5vdywgd2Ugd2lsbCB2aXN1YWxpemUgc29tZSBvZiB0aGUgdmVyaWFibGVzIHRvIG9ic2VydmUgc29tZSBwYXR0ZXJucyBhbmQgZGlmZmVyZW5jZXMuIAoKRmlyc3QgY3JlYXRlIGEgYmFyIGNoYXJ0IG9mIHRoZSBsb2FuIHB1cnBvc2UgZnJlcXVlbmN5IHRhYmxlIGFuZCBqb2IgZnJlcXVlbmN5IHRhYmxlIFJlbWVtYmVyIHRvIGV4dHJhY3QgdGhlIHNhbGVzIHZhcmlhYmxlIGJlZm9yZSBjYWxsaW5nIGl0LgoKVkFSSUFCTEVTOiBKb2IgYW5kIExvYW4gUHVycG9zZQoKYGBge3J9CiMgUGxvdCBhIGJhciBwbG90IHVzaW5nIHRoZSAiIGJhcnBsb3QodmFyaWFibGUpICIgY29tbWFuZCB3aGVyZSB2YXJpYWJsZSBpcyB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlCmJhcnBsb3QoZGVwdF90YWJsZSkKYGBgCgpOZXh0LCBjcmVhdGUgYSBoaXN0b2dyYW0gb2YgbG9hbiBwdXJwb3NlIGZyZXF1ZW5jeSB0YWJsZSBhbmQgam9iIGZyZXF1ZW5jeSB0YWJsZQoKYGBge3J9CiMgUGxvdCBhIGhpc3RvZ3JhbSB1c2luZyB0aGUgIiBoaXN0KHZhcmlhYmxlKSAiIGNvbW1hbmQgd2hlcmUgdmFyaWFibGUgaXMgdGhlIGV4dHJhY3RlZCB2YXJpYWJsZQpoaXN0KGRlcHRfdGFibGUpCmBgYAoKKiBXaGF0IGFyZSBzb21lIG9ic2VydmFibGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgYm94cGxvdCBhbmQgdGhlIGhpc3RvZ3JhbT8gUGxlYXNlIHJlY29yZCB5b3VyIG9ic2VydmF0aW9ucyBoZXJlLiAKCgoKTGFzdGx5LCBjcmVhdGUgYSBwaWUgY2hhcnQgb2YgTG9hbiBwdXJwb3NlIGZyZXF1ZW5jeSB0YWJsZS4gUGxvdCBvbmx5IHZhbHVlcyBncmVhdGhlciB0aGFuIDEwLgoKVkFSSUFCTEU6IExvYW4gUHVycG9zZQpgYGB7cn0KIyBQbG90IGEgcGllIGNoYXJ0IHVzaW5nOgojIHBpZSh2YXJpYWJsZSkgIChjb21tYW5kIHRvIG1ha2UgYSBwaWUgY2hhcnQpCiMgVG8gZ2V0IG9ubHkgdmFsdWVzIGdyZWF0aGVyIHRoYW4gTiBmcm9tIGEgZnJlcXVlbmN5IHRhYmxlIHVzZToKIyBuZXdfdGFibGUgPSBteV90YWJsZVsgbXlfdGFibGUgPiBOIF0gIChjb21tYW5kIHRvIHNlbGVjdCB2YWx1ZXMgZ3JlYXRoZXIgdGhhbiBOKQoKbmV3X3RhYmxlID0gZGVwdF90YWJsZVsgZGVwdF90YWJsZSA+IDIwMDAgXQpwaWUobmV3X3RhYmxlKQpgYGAKCldoeSBpcyB0aGlzIHZpc3VhbCBub3QgYSBnb29kIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkYXRhPyBXaGF0IG1ha2VzIHRoZSBiYXJwbG90IGEgYmV0dGVyIHJlcHJlc2VudGF0aW9uPwoKLS0tLS0tLS0tLQoKIyMjIFRhc2sgMgoKTGV0cyBleHBsb3JlIHRoZSBJbGxpbm9pcyBUYXggZGF0YXNldCAoUkVBRCB0aGUgInN0YXRlX3RheF9pbGxpbm9pcy5jc3YiIGZpbGUpIGFuZCBjcmVhdGUgYSBzY2F0dGVycGxvdCBvZiBjb3Jwb3JhdGUgdGF4IHZzLiBwZXJzb25hbCBpbmNvbWUgdGF4LiAgCgpUaGUgZGF0YXNldCBzdGFydCBpbiAxOTk0IGJ1dCB3ZSB3YW50IHRvIHRheCByZXZlbnVlIHNpbmNlIDIwMDAgZm9yIHRoZSBmaXJzdCBxdWFydGVyIG9mIHRoZSB5ZWFyICJRMSIKClZBUklBQkxFUzogcGVyc29uYWxfaW5jb21lX3RheCBhbmQgY29ycG9yYXRlX2luY29tZV90YXgKCmBgYHtyfQoKbXlkYXRhID0gcmVhZC5jc3YoImRhdGEvc3RhdGVfdGF4X2lsbGlub2lzLmNzdiIpCiMgVG8gY2hhbmdlIHRoZSB3YXkgdGhhdCBSIHNob3dzIHZlcnkgbGFyZ2Ugb3Igc21hbGwgdmFsdWVzIHdlIGNhbiB1c2UgdGhlIGZvbGxvd2luZyBjb21tYW5kOgpvcHRpb25zKHNjaXBlbiA9IDk5OTkpCgojIHJlYWQgdGhlIGRhdGFzZXQgZXh0cmFjdCB0aGUgeWVhciB2YXJpYWJsZSBhbmQgb3JkZXIgdGhlIGRhdGFzZXQgYnkgeWVhciBpbiBkZWNyZWFzaW5nIG9yZGVyIHVzaW5nIHRoZSBjb21tYW5kOgoKeWVhciA9IG15ZGF0YSR5ZWFyCgojIG15ZGF0YSA9IG15ZGF0YVsgb3JkZXIoeWVhciwgZGVjcmVhc2luZyA9IFRSVUUpICwgXSAoISBPcmRlciB0aGUgZGF0YSBpbiBkZWNyZWFzaW5nIG9yZGVyKQoKbXlkYXRhID0gbXlkYXRhWyBvcmRlcih5ZWFyLGRlY3JlYXNpbmcgPSBUUlVFKSwgXQoKIyBGcm9tIHRoZSBvcmRlcmVkIGRhdGFzZXQgRXh0cmFjdCBwZXJzb25hbF9pbmNvbWVfdGF4IHZhcmlhYmxlCgp1c190YXggPSBteWRhdGEkdG90YWxfdGF4X1VTCgojIEZyb20gdGhlIG9yZGVyZWQgZGF0YXNldCBFeHRyYWN0IGNvcnBvcmF0ZV9pbmNvbWVfdGF4IHZhcmlhYmxlCgpzdGF0ZSA9IG15ZGF0YSR0b3RhbF9zdGF0ZQoKYGBgCgpUaGUgcHJldmlvdXMgdGFzayBmb2N1c2VkIG9uIHZpc3VhbGl6aW5nIG9uZSB2YXJpYWJsZS4gQSBnb29kIHdheSB0byB2aXN1YWxpemUgdHdvIHZhcmlhYmxlcyB3b3VsZCBiZSBhIHNjYXR0ZXIgcGxvdCBvciBhIGNvcnJlbGF0aW9uIG1hdHJpeC4KCmBgYHtyfQojIFBsb3QgcGVyc29uYWxfaW5jb21lX3RheCB2cy4gY29ycG9yYXRlX2luY29tZV90YXggCiMgcGVyc29uYWxfaW5jb21lX3RheCB3aWxsIGJlIG9uIHRoZSB4LWF4aXMKIyBjb3Jwb3JhdGVfaW5jb21lX3RheCB3aWxsIGJlIG9uIHRoZSB5LWF4aXMKCnBsb3QoWF9WQVJJQUJMRSxZX1ZBUklBQkxFKQpwbG90KG15ZGF0YSkKcGxvdChzdGF0ZSx1c190YXgpCgpgYGAKCiogU2VsZWN0IG9ubHkgZW50cmllcyBncmF0aGVyIHRoYW4geWVhciAxOTk5CiogQWZ0ZXIgc2VsZWN0aW5nIGVudHJpZXMgZ3JlYXRoZXIgdGhhbiB5ZWFyIDE5OTksIHNlbGVjdCBlbnRyaWVzIGZvciBxdWFydGVyICJRMSIKCmBgYHtyfQojIFRvIGNyZWF0ZSBhIG5ld19kYXRhIGZpbHRlcmluZyBmb3IgYW4gTiBOVU1FUklDIHZhbHVlIHdlIGNhbiBkbyB0aGUgZm9sbG93aW5nCiMgbmV3X2RhdGEgPSBteWRhdGFbIG15ZGF0YSROVU1FUklDX1ZBUklBQkxFID4gTiAsIF0KCm5ld19kYXRhID0gbXlkYXRhWyBteWRhdGEkeWVhcjwyMDAwICwgXQoKIyBJZiB3ZSBuZWVkIHRvIG1ha2UgYW5vdGhlciBmaWx0ZXIgb24gYSBOT04tTlVNRVJJQyB3ZSBjYW4gZG8gdGhlIGZvbGxvd2luZwojIG5ld19kYXRhID0gbmV3X2RhdGFbIG5ld19kYXRhJENIQVJfVkFSSUFCTEUgPT0gIlExIiwgXQoKbmV3X2RhdGEgPSBuZXdfZGF0YVsgbmV3X2RhdGEkcXVhcnRlciA9PSAiUTQiICwgXQoKaGVhZChuZXdfZGF0YSkKYGBgCgpJdCBtaWdodCBiZSBlYXNpZXIgdG8gbm90aWNlIGEgdHJlbmQgaWYgdGhlcmUgd2FzIGEgbGluZSB0aGF0IGZpdCB0aHJvdWdoIHRoZSBwb2ludHMuIFNvLCBsZXRzIHJlcGVhdCB1c2luZyB0aGUgZnVuY3Rpb24gJ3NjYXR0ZXIuc21vb3RoJy4gVGhpcyBmdW5jdGlvbnMgYWRkcyBhIHNtb290aCBjdXJ2ZSBjb21wdXRlZCBieSBsb2VzcywgYSBtZXRob2QgdG8gbG9jYWxseSBzbW9vdGggYSBjdXJ2ZS4gCgpgYGB7cn0KCnVzX3RheCA9IG5ld19kYXRhJHRvdGFsX3RheF9VUwpzdGF0ZSA9IG5ld19kYXRhJHRvdGFsX3N0YXRlCgpzY2F0dGVyLnNtb290aCh1c190YXgsc3RhdGUpCgpgYGAKCk5vdywgcmVwZWF0IGJlbG93IGZvciB0b3RhbF90YXhfVVMgdnMuIHRvdGFsX3N0YXRlLCBmb2xsb3dpbmcgdGhlIGV4YW1wbGUgdGhhdCB3YXMganVzdCBwcm92aWRlZC4gT2JzZXJ2ZSBhbmQgbm90ZSBhbnkgdHJlbmRzIGluIHRoZSBzY2F0dGVyIHBsb3RzIGFuZCBwb3RlbnRpYWwgcmVsYXRpb25zaGlwcyBiZWxvdy4gRG8gdGhlIHNhbWUgZm9yIGFsbCBudW1lcmljIHZhcmlhYmxlcy4KCmBgYHtyfQojIHRvdGFsX3RheF9VUyB2cy4gdG90YWxfc3RhdGUKc2NhdHRlci5zbW9vdGgobmV3X2RhdGEkbW90b3JfZnVlbF90YXgsbmV3X2RhdGEkcGVyc29uYWxfaW5jb21lX3RheCkKYGBgCgpUbyBxdWFudGlmeSB0aGUgZGF0YSwgaXRzIGJlc3QgdG8gbG9vayBhdCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0d28gdmFyaWFibGVzLgpXaGF0IGRvZXMgdGhpcyBjb3JyZWxhdGlvbiBleHBsYWluPwoKYGBge3J9CmNvcihuZXdfZGF0YVszOjhdKQpgYGAKCgpCZWxvdywgY29tcHV0ZSB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBldmVyeSBwYWlyIG9mIHZhcmlhYmxlcyAodG90YWxfdGF4X1VTLHRvdGFsX3N0YXRlLCBwZXJzb25hbF9pbmNvbWVfdGF4LCBjb3Jwb3JhdGVfaW5jb21lX3RheCwgZ2VuZXJhbF9zYWxlc190YXgsIG1vdG9yX2Z1ZWxfdGF4ICkuIAoKTWFrZSBzdXJlIHRvIGV4dHJhY3QgdGhlIHZhcmlhYmxlcyBmaXJzdCBhbmQgdGhlbiBjb21wdXRlIHRoZSBjb3JyZWxhdGlvbi4gCgpgYGB7cn0KIyBUbyBtYWtlIGEgY29ycmVsYXRpb24gdGFibGUgb2YgYWxsIHRoZSBOVU1FUklDIHZhcmlhYmxlcyB5b3UgY2FuIHNlbGVjdCBzb21lIGNvbHVtbnMgb3IgYSByYW5nZSBvZiBjb2x1bW5zLCB3aXRoIHRoZSBmb2xsb3dpbmcgY29tbWFuZDoKCiMgY29ycjAxID0gbXlkYXRhWyBjKDMsNCkgXSAoVGhlIGNvbW1hbmQgYygzLDQsLi4uKSBpbnNpZGUgdGhlIGJyYWNrZXRzIHNlbGVjdHMgYSBnaXZlbiBjb2x1bW4gKQojIGNvcihjb3JyMDEpICh3aWxsIGdpdmUgeW91IHRoZSBjb3JyZWxhdGlvbiB0YWJsZSBmb3IgdmFyaWFibGVzIGluIGNvbHVtbnMgMyBhbmQgNCkKCiMgY29ycjAyID0gbXlkYXRhWzM6NV0gKCB0aGUgY29tbWFuZCBbMzo1XSBzZWxlY3RzIGEgcmFuZ2Ugb2YgY29sdW1ucyBmcm9tIDMgdG8gNSkKIyBjb3IoY29ycjAyKQpgYGAKCi0tLS0tLS0tLS0KCiMjIyBUYXNrIDMgLSBUQUJMRUFVCgpGb2xsb3cgdGhlIGRpcmVjdGlvbnMgb24gdGhlIHdvcmtzaGVldCwgZG93bmxvYWQgdGFibGVhdSBhY2FkZW1pYyBvbiB5b3VyIHBlcnNvbmFsIGNvbXB1dGVyIG9yIHVzZSBvbmUgb2YgdGhlIGxhYnMgY29tcHV0ZXJzLgoKKiBEb3dubG9hZCBUYWJsZWEgYWNhZGVtaWMgaGVyZTogaHR0cHM6Ly93d3cudGFibGVhdS5jb20vYWNhZGVtaWMvc3R1ZGVudHMKCjEuIFJlZmVyIHRvIGZpbGUgJ3N0YXRlc19wdXJjaGFzZV9vcmRlcnMuY3N2JyBpbiB0aGUgZGF0YSBmb2xkZXIKCjIuIFN0YXJ0IFRhYmxlYXUgYW5kIGVudGVyIHlvdXIgTFVDIGVtYWlsIGlmIHByb21wdGVkLgoKMy4gSW1wb3J0IHRoZSBmaWxlIGludG8gVGFibGVhdS4gQ2hvb3NlIHRoZSBUZXh0IEZpbGUgb3B0aW9uIHdoZW4gaW1wb3J0aW5nCgohW10oaW1ncy90YWJsZWF1X2ltcG9ydGZpbGUucG5nKQoKCjQuIFVuZGVyIHRoZSBkaW1lbnNpb25zIHRhYiBsb2NhdGVkIG9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIHNjcmVlbi4KCiFbXShpbWdzL3RhYmxlYXVfdmFyaWFibGVzLnBuZykKCkRPVUJMRSBjbGljayAgb24gdGhlICdEZXBhcnRtZW50Lk5hbWUnLCB0aGVuIERPVUJMRSBjbGljayBvbiAnTnVtYmVyIG9mIFJlY29yZHMnIHZhcmlhYmxlIGxvY2F0ZWQgb24gdGhlIGJvdHRvbSBsZWZ0IG9mIHRoZSBzY3JlZW4uIE5vdGUgdGhlIGJhciBsaWtlIHZpZXcgYW5kIGJyZWFrZG93bnMuCgoqIFdoYXQgZGVwYXJ0bWVudCAnYmluJyBoYXMgdGhlIGhpZ2hlc3QgY291bnQ/IFdoYXQgaXMgdGhlIGNvdW50PyAKKiBGcm9tIHRoZSB1cHBlciByaWdodCBjb3JuZXIgb2YgdGhlIHNjcmVlbiBzZWxlY3Qgb3RoZXIgdmlld3MgKHNlbGVjdCBvbmUgb2YgdGhlIG90aGVyIHZpZXdzLCB0YWxrIGFib3V0IGl0IGFuZCBwb3N0IGFuIHNjcmVlbnNob3QpCgohW10oaW1ncy90YWJsZWF1X3Zpc3VhbGl6YXRpb25zLnBuZykKCmAjIENoYW5nZSB0aGUgaW1hZ2UgZm9yIHlvdXIgc2NyZWVuc2hvdHMgYW5kIE1BS0UgQ09NTUVOVFNgCgo1LiBDcmVhdGUgYSBuZXcgc2hlZXQgYnkgY2xpY2tpbmcgb24gdGhlIGljb24gbmV4dCB0byB5b3VyIGN1cnJlbnQgc2hlZXQuCgohW10oaW1ncy90YWJsZWF1X25ld3NoZWV0LnBuZykKClRoZW4gRE9VQkxFIGNsaWNrIG9uICdOdW1iZXIgb2YgUmVjb3JkcycgdmFyaWFibGUgdGhlbiBET1VCTEUgY2xpY2sgb24gJ1ZlbmRvci5aaXAnLCB0aGVuIG9uIHRoZSB0b3AgbGVmdCBzZWxlY3QgdGhlIHJlY29tbWVuZCB2aWV3LiAKCiogV2hhdCBhcmUgdGhlIGhpZ2hsaWdodHMgb24gdGhlIG1hcD8KKiBDYW4geW91IGdpdmUgYW4gZXhwbGFuYXRpb24gb2Ygd2h5IHRoZXJlIGlzIGEgY29uY2VudHJhdGlvbiBvbiBhIHBhcnRpY3VsYXIgcmVnaW9uPwoKIVtdKGltZ3MvdGFibGVhdV9zaG93bWUucG5nKQoKYCMgQ2hhbmdlIHRoZSBpbWFnZSBmb3IgeW91ciBzY3JlZW5zaG90cyBhbmQgTUFLRSBDT01NRU5UU2AKCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoKIyMjIyBGaW5hbCBQcm9qZWN0IFJldmlldwoKMSkgQWZ0ZXIgcmV2aWV3aW5nIHlvdXIgZGF0YSBhbmQgZGVmaW5lZCB5b3VyIHByb2JsZW0sIHlvdSBuZWVkIHRvIHByZXBhcmUgYW5kIGFuYWxpemUgeW91ciBkYXRhLgoKYGBge3J9Cm15ZGF0YSA9IHJlYWQuY3N2KCJkYXRhL2Nwc19wcm9ncmVzc19yZXBvcnQuY3N2IikKaGVhZChteWRhdGEpCmBgYAoKCgpJZGVudGlmeSB2YXJpYWJsZXMgdGhhdCBhcmUgcmVsZXZhbnQgdG8geW91ciBwcm9ibGVtIChtb2RlbCkuIEhlcmUgd2UgYXJlIHVzaW5nIGF0dGVkYW5jZSBhcyB0aGUgWS12YXJpYWJsZSBvciBwcmVkaWN0ZWQgdmFyaWFibGVzLiBUaGUgb3RoZXIgdmFyaWFibGVzIGFyZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgdGhhdCBjb3VsZCBpbmZsdWVuY2UgdGhlIGF0dGVuZGFuY2UgcmF0ZS4KCgojIyMjIEV4dHJhY3QgVmFyaWFibGVzCmBgYHtyfQojIEV4dHJhY3RpbmcgVmFyaWFibGVzIGZyb20gdGhlIHllYXIgMjAxMSB0byBwcmVkaWN0IGF0dGVuZGFuY2UgZm9yIDIwMTIKWV9hdHRlbmRhbmNlXzIwMTEgPSBteWRhdGEkU3R1ZGVudC5BdHRlbmRhbmNlLjIwMTEuLi5QZXJjZW50CiMgSW4gdGhpcyBtb2RlbCBncmFkZXMsIGVudmlyb25tZW50IGFuZCBncmFkdWF0aW9uIGFyZSB2YXJpYWJsZXMgdGhhdCBhZmZlY3QgYXR0ZW5kYW5jZQpYMV9ncmFkZXNfMjAxMSA9IG15ZGF0YSRHcm93dGguQWxsLkdyYWRlcwpYMl9ncmFkdWF0aW9uXzIwMTEgPSBteWRhdGEkWDUuWWVhci5Db2hvcnQuR3JhZHVhdGlvbi5SYXRlLjIwMTEKWDNfZW52aXJvbWVudF8yMDExID0gbXlkYXRhJFN1cHBvcnRpdmUuRW52aXJvbm1lbnQKYGBgCgojIyMjIENsZWFuIGFuZCBzZXQgdGhlIGNvcnJlY3QgZGF0YXR5cGUKYGBge3J9CgojIyMjIERlcGVuZGVudCBWYXJpYWJsZSAgKFkpIC0gUHJlZGljdGVkCllfYXR0ZW5kYW5jZV8yMDExID0gc3ViKCIlIiwiIixZX2F0dGVuZGFuY2VfMjAxMSkgIyBSZW1vdmUgJSBzaWduIGZyb20gdGhlIHZhbHVlcwpZX2F0dGVuZGFuY2VfMjAxMSA9IGFzLm51bWVyaWMoWV9hdHRlbmRhbmNlXzIwMTEpICMgQ2hhbmdpbmcgZnJvbSBjaGFyYWN0ZXIgdG8gbnVtZXJpYwoKIyMjIyBJbmRlcGVuZGVudCBWYXJpYWJsZXMgIChYMSxYMixYMywuLi4gKSAtIFByZWRpY3RvcnMKWDFfZ3JhZGVzXzIwMTEgPSBzdWIoIiUiLCAiIiwgWDFfZ3JhZGVzXzIwMTEpClgxX2dyYWRlc18yMDExID0gYXMubnVtZXJpYyhYMV9ncmFkZXNfMjAxMSkKClgyX2dyYWR1YXRpb25fMjAxMSA9IHN1YigiJSIgLCAiIiAsIFgyX2dyYWR1YXRpb25fMjAxMSkKWDJfZ3JhZHVhdGlvbl8yMDExID0gYXMubnVtZXJpYyhYMl9ncmFkdWF0aW9uXzIwMTEpCgojIEVudmlyb21lbnQgaGFzIGRpZmZlcmVudCBsZXZlbHMgV2VhaywgU3Ryb25nLCBWZXJ5IFN0cm9uZyAuLi4gaGVuY2UgaXRzIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUuIFdlIHVzZSB0aGUgZnVuY3Rpb25zIGFzLmZhY3RvcigpIHRvIHRyYW5zZm9ybSBhIGNoYXJhY3RlciB2YXJpYWJsZSB0byBmYWN0b3IKWDNfZW52aXJvbWVudF8yMDExID0gYXMuZmFjdG9yKFgzX2Vudmlyb21lbnRfMjAxMSkKYGBgCgoKIyMjIyBOb3cgc3RhcnQgYW5hbHl6aW5nIHRoZSByZWxhdGlvbiBiZXR3ZWVuIHlvdXIgaW5kZXBlbmRlbnQgdmFyaWFibGVzIChYMSxYMixYMywuLi4pIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlL3ByZWRpY3RvciAoWSkuIAoKYGBge3J9CnNjYXR0ZXIuc21vb3RoKFlfYXR0ZW5kYW5jZV8yMDExLCBYMV9ncmFkZXNfMjAxMSkKYGBgCgoKYGBge3J9CnNjYXR0ZXIuc21vb3RoKFlfYXR0ZW5kYW5jZV8yMDExLFgyX2dyYWR1YXRpb25fMjAxMSkKYGBgCgoKYGBge3J9CnBsb3QoWDNfZW52aXJvbWVudF8yMDExLFlfYXR0ZW5kYW5jZV8yMDExKQpgYGAKCgpOb3cgdGhhdCB3ZSBsb29rIGF0IHRoZSByZWxhdGlvbiBhbmQgaW50ZXJhY3Rpb24gYmV0d2VlbiB0aGF0IGluZGVwZW5kZW50IHZhcmlhYmxlcyAoeDEsWDIsWDMsLi4uKSBhbmQgZGVwZW5kZW50IHZhcmlhYmxlICh5KS4gV2UgY2FuIGJ1aWxkIGEgcHJlZGljdGVkIG1vZGVsLgoKYGBge3J9CiMjIEJ1aWxkIGEgbW9kZWwgWV9QcmVkaWN0ZWQgfiBYMSArIFgyICsgWDMgLi4uCiMjIEhvdyB5b3VyIGluZGVwZW5kZW50IHZhcmlhYmxlcyAoWDEsWDIsWDMsLi4uKSBpbnRlcmFjdCB3aXRoIHlvdXIgZGVwZW5kZW50IHZhcmlhYmxlIChZX3ByZWRpY3RlZCkgCgojIEZvciB0aGlzIGNhc2UgaG93IGdyYWRlcywgZ3JhZHVhdGlvbiBhbmQgZW52aXJvbWVudCBhZmZlY3QgYXR0ZW5kYW5jZSBvZiBzdHVkZW50cyBhdCBhIENQUyBzY2hvb2wgaW4gMjAxMSAKCiMgTGluZWFyIE1vZGVsIEZ1bmN0aW9uIC0gbG0oKQoKbW9kZWxfMjAxMSA9IGxtKCBZX2F0dGVuZGFuY2VfMjAxMSB+IFgxX2dyYWRlc18yMDExICsgWDJfZ3JhZHVhdGlvbl8yMDExICsgWDNfZW52aXJvbWVudF8yMDExKQpzdW1tYXJ5KG1vZGVsXzIwMTEpCgpgYGAKCk5vdGljZSB0aGUgQWRqdXN0ZWQgUi1zcXVhcmVkIHZhbHVlIChjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uKSwgdGhhdCBkZXRlcm1pbmVzIGhvdyBjbG9zZSB0aGUgZGF0YSBhcmUgdG8gdGhlIGZpdHRlZCByZWdyZXNzaW9uIGxpbmUuICggMCUgaW5kaWNhdGVzIHRoYXQgdGhlIG1vZGVsIGV4cGxhaW5zIG5vbmUgb2YgdGhlIHZhcmlhYmlsaXR5IG9mIHRoZSByZXNwb25zZSBkYXRhIGFyb3VuZCBpdHMgbWVhbiApCgo=