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 states_purchase_orders.csv file and make sure all the columns are captured and check the first couple of rows of the dataset “head(mydata)”

#This function will allow the desired file 'states_purchase_order.csv' into R Studio and names it 'mydata'
mydata = read.csv(file="data/states_purchase_orders.csv")
head(mydata)
#The following commands will allow the columns to be called
vendorstate = mydata$VENDOR.STATE
departmentname = mydata$DEPARTMENT.NAME
recordtype = mydata$RECORD.TYPE
purchaseorder = mydata$PURCHASE.ORDER.NUMBER
inputdate = mydata$INPUT.DATE
totalamount = mydata$TOTAL.AMOUNT
departmentnumber = mydata$DEPARTMENT.NUMBER
POcategorydescription = mydata$PO.CATEGORY.DESCRIPTION
vouchedamount = mydata$VOUCHED.AMOUNT
vendorname1 = mydata$VENDOR.NAME.1
vendoraddress1 = mydata$VENDOR.ADDRESS.1
vendorcity = mydata$VENDOR.CITY
vendorzip = mydata$VENDOR.ZIP
totalitems = mydata$VENDOR.ZIP
itemunitcost = mydata$ITEM.UNIT.COST
itemtotalcost = mydata$ITEM.TOTAL.COST
uniqueid = mydata$UNIQUE.ID

Frequency Tables for columns ‘vendor.state’ and ‘department.name’

# Here, I will create a frequency table for the column 'vendor.state' and name it vendorstatefqtable. Using the command "variable_table = table(variable)"
vendorstatefqtable = table(vendorstate)
vendorstatefqtable
vendorstate
          ,    AL    AR    AZ    CA    CD    CO    CT    DC    FL    GA 
    2    62   400   125   189   877     1   114    99    69   418   555 
   IA    ID    IL    IN    KS    KY    LA    MA    MD    ME    MI    MN 
 1089    14   330   180    76   100 20178   149    32    12    55   233 
   MO    MS    NC    ND    NE    NH    NJ    NM    NV    NY    OH    OK 
   74   361   313     4    56    14  1633     3    12   210   180     9 
   OR    PA    RI    SC    SD    TN    TX    UT    VA    VT    WA    WI 
   27   401    15    41     6   152  2561    77   295     3    60   583 
   WV 
    3 

The table above is the frequency table that displays the vendors and the amount of orders that they have fulfilled for each state.

# Here, I will create a frequency table for the column 'department.name' and name it deptnamefqtable
deptnamefqtable = table(departmentname)
deptnamefqtable
departmentname
                      ANIMAL CONTROL CENTER 
                                         79 
BATON ROUGE CONVENTION & VISTORS COMMISSION 
                                          4 
                   BATON ROUGE RIVER CENTER 
                                        134 
                             CITY CONSTABLE 
                                        115 
                                 CITY COURT 
                                       1412 
             COMMUNITY DEVELOPMENT PROGRAMS 
                                       1674 
                      CONSTRUCTION PROJECTS 
                                       2224 
                                    CORONER 
                                         47 
                      COUNCIL ADMINISTRATOR 
                                        182 
                      COUNCIL BUDGET OFFICE 
                                         84 
                 DEPARTMENT OF PUBLIC WORKS 
                                       5523 
              DEPT OF BUILDINGS AND GROUNDS 
                                        326 
DEPT OF BUSINESS OPERATIONS AND CAPITAL PRO 
                                        107 
                        DEPT OF DEVELOPMENT 
                                         69 
                   DEPT OF FLEET MANAGEMENT 
                                        325 
                        DEPT OF MAINTENANCE 
                                        220 
        DEPT OF TRANSPORTATION AND DRAINAGE 
                                        200 
                             DISTRICT COURT 
                                         20 
              DOWNTOWN DEVELOPMENT DISTRICT 
                                        182 
                 EMERGENCY MEDICAL SERVICES 
                                       1640 
                         FINANCE DEPARTMENT 
                                        758 
                            FIRE DEPARTMENT 
                                        498 
                   FIRE PROTECTION DISTRICT 
                                        217 
       GREATER BATON ROUGE AIRPORT DISTRICT 
                                       1677 
             HUMAN DEVELOPMENT AND SERVICES 
                                       2733 
                            HUMAN RESOURCES 
                                        561 
                       INFORMATION SERVICES 
                                       1156 
                             JUVENILE COURT 
                                          1 
                          JUVENILE SERVICES 
                                        376 
                   LIBRARY BOARD OF CONTROL 
                                       2620 
                       METROPOLITAN COUNCIL 
                                        186 
                  MOSQUITO & RODENT CONTROL 
                                        413 
MUNICIPAL FIRE & POLICE CIVIL SERVICE BOARD 
                                         11 
OFC. OF HOMELAND SECURITY & EMERGENCY PREPA 
                                        472 
              OFFICE OF THE MAYOR-PRESIDENT 
                                        386 
                           OUTSIDE AGENCIES 
                                        161 
                            PARISH ATTORNEY 
                                        259 
                        PLANNING COMMISSION 
                                        138 
                          POLICE DEPARTMENT 
                                       4066 
                  PUBLIC INFORMATION OFFICE 
                                         94 
                                 PURCHASING 
                                        253 
                        REGISTRAR OF VOTERS 
                                         43 
                          RETIREMENT OFFICE 
                                          4 
                ROAD REHABILITATION PROGRAM 
                                        607 
                           SHERIFF'S OFFICE 
                                        195 

This frequency table displays the orders placed by each department. I.e. 195 orders placed by the Sheriff’s office, 259 by the Parish attorney, 161 by outside agencies, etc.

Now, we will visualize some of the variables 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.

BAR PLOTS FOR VENDOR STATE AND DEPARTMENT NAME

VARIABLES: VENDOR STATE AND DEPARTMENT NAME

# Here, I will create a bar plot for the variable vendor state. 
barplot(vendorstatefqtable)

It is difficult to make assesments with this barplot since the ranges are so large, therefore I will create another barplot with a certain number of specified rows: 10-18

# Bar plot with variable vendor state- specified rows 
barplot(vendorstatefqtable[10:18])

This layout is much easier to view, with noting that Indiana had the most orders in comparison to Idaho with the least in this specified range.

# Bar plot with variable department name with also specified rows to allow better use for assessments. 
barplot(deptnamefqtable[12:18])

Histogram of Vendor State and Department Name

Below, I will creat histograms for the variables vendor state and department name using the function “hist(variable)”

# Plot a histogram using the " hist(variable) " command where variable is vendor state
hist(vendorstatefqtable)

# Plot a histogram using the " hist(variable) " command where variable is vendor state
hist(deptnamefqtable)

Pie Chart for Vendor state and Department Name

VARIABLE: VENDOR STATE

# 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)
newVendorStateTable = vendorstatefqtable[vendorstatefqtable >500]
pie(newVendorStateTable)

Why is this visual not a good representation of the data? What makes the barplot a better representation? The above visual is not a good representation because it fails to provide an accurate representation of all states. Plus there are states whose some orders encompass a little less than half of what the other states combined ordered which does not leave for a clear and readable graph.


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

mydata1 = read.csv(file="data/state_tax_illinois.csv")
head(mydata1)
# read the dataset extract the year variable and order the dataset by year in decreasing order using the command:
year = mydata1$year
year
 [1] 1994 1994 1994 1994 1995 1995 1995 1995 1996 1996 1996 1996 1997 1997
[15] 1997 1997 1998 1998 1998 1998 1999 1999 1999 1999 2000 2000 2000 2000
[29] 2001 2001 2001 2001 2002 2002 2002 2002 2003 2003 2003 2003 2004 2004
[43] 2004 2004 2005 2005 2005 2005 2006 2006 2006 2006 2007 2007 2007 2007
[57] 2008 2008 2008 2008 2009 2009 2009 2009 2010 2010 2010 2010 2011 2011
[71] 2011 2011 2012 2012 2012 2012 2013 2013 2013 2013 2014 2014 2014 2014
[85] 2015 2015 2015 2015 2016 2016
# To change the way that R shows very large or small values we can use the following command:
options(scipen = 9999)
# mydata = mydata[ order(year, decreasing = TRUE) , ] (! Order the data in decreasing order)
mydata1 = mydata1[ order(mydata1$year, decreasing = TRUE),] 
# From the ordered dataset Extract personal_income_tax variable
personalincometax = mydata$personal_income_tax
personalincometax
 [1] 3746068 3950197 3982255 4527933 3059415 3048487 4505921 4961971 3680480
[10] 3723148 4345335 5353786 3608644 3565618 4197619 4790521 3403778 3435763
[19] 3195378 4096206 3343258 3180912 2515231 2702995 2134865 2291055 2448000
[28] 2899039 2104226 2110793 2803540 3427232 2149834 1968785 2522527 3101128
[37] 2071646 2017821 2264920 2817633 1963943 1820838 2130841 2511261 1817907
[46] 1734644 1902394 2181615 1675372 1661305 1862628 2169229 1600339 1571274
[55] 1945837 2195228 1648066 1661059 1867375 2405920 1679520 1650800 2272950
[64] 2713373 1763852 1631196 1877350 1984974 1644788 1640535 1877350 1984974
[73] 1579539 1545132 1689205 1786043 1579539 1545132 1553374 1642423 1421240
[82] 1390281 1427336 1509160 1306955 1278486 1360884 1425714 1200911 1174752
#From the ordered dataset Extract corporate_income_tax variable
corpincometax = mydata$corporate_income_tax
corpincometax
 [1]  903017 1163900 1055932 1425459  674725  625819 1105062 1508593  787764
[10]  785112 1028486 1764708  877978  948199  834075 1365912  778008  891425
[19]  632404 1160954  655115  639437  729180  971001  507167  504933  642923
[28] 1403105  459494  527011  790459 1225043  519552  439074  704820 1158924
[37]  537828  562274  591623  901551  556344  516272  557161  735924  438193
[46]  468903  431059  470507  324041  354688  362344  421964  222017  395572
[55]  362374  432374  261916  246964  583639  786706  274660  313983  792893
[64]  828315  433323  412970  473585  814038  476261  457064  473585  814038
[73]  370340  303603  435527  748621  370340  303603  391428  672820  340579
[82]  279205  357650  614760  306094  250934  281377  532591  279680  229280

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(personalincometax, corpincometax, xlab = "Personal Income Tax", ylab = "Corporate Income Tax")

The above scatter plot features the two variables: personal income tax on the x-axis and corporate income tax on the y-axis. These two variables allow for a clearer represenation.

as.numeric(mydata1$year)
 [1] 1994 1994 1994 1994 1995 1995 1995 1995 1996 1996 1996 1996 1997 1997
[15] 1997 1997 1998 1998 1998 1998 1999 1999 1999 1999 2000 2000 2000 2000
[29] 2001 2001 2001 2001 2002 2002 2002 2002 2003 2003 2003 2003 2004 2004
[43] 2004 2004 2005 2005 2005 2005 2006 2006 2006 2006 2007 2007 2007 2007
[57] 2008 2008 2008 2008 2009 2009 2009 2009 2010 2010 2010 2010 2011 2011
[71] 2011 2011 2012 2012 2012 2012 2013 2013 2013 2013 2014 2014 2014 2014
[85] 2015 2015 2015 2015 2016 2016
# 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 = mydata1[ mydata1$year > 1999,]
# 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 =="Q1" , ]
head(mydata1)

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.

ScatterPlot In this seciton I will create a scatter plot for the dictated variables. I will use the funtion ‘scatter.smooth(variable, variable)’

scatter.smooth(personalincometax,corpincometax, xlab = "Personal Income Tax", ylab = "Corporate Income Tax")

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
# I will first call and extract the desired numeric variables
totaltaxUS = mydata1$total_tax_US
totalstate = mydata1$total_state
generalsalestax = mydata1$general_sales_tax
motorfueltax = mydata1$motor_fuel_tax
scatter.smooth(mydata1$total_tax_US, mydata1$total_state, xlab = "Total Tax US", ylab = "Total State")

To quantify the data, its best to look at the correlation between two variables. What does this correlation explain?

cor(mydata1$total_state,mydata1$personal_income_tax)
[1] 0.9652176

The number above, 0.9652176, indicates that the two variable are strongly and positively correlated.

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.

corr01 = mydata1[c(3:6)]
cor(corr01)
                     total_tax_US total_state personal_income_tax
total_tax_US            1.0000000   0.9621443           0.8921627
total_state             0.9621443   1.0000000           0.9652176
personal_income_tax     0.8921627   0.9652176           1.0000000
corporate_income_tax    0.8378959   0.8547191           0.8794823
                     corporate_income_tax
total_tax_US                    0.8378959
total_state                     0.8547191
personal_income_tax             0.8794823
corporate_income_tax            1.0000000

Task 3 - TABLEAU

To begin this task, I imported the state_purchases file into Tableau. I selected the dimension ‘Department name’ and measure ‘Number of Records’.

Next, I chose the ‘treemap’ view. This assembled all the departments into squares that were sized accordingly to the number of records they had. Therefore the largest was the Department of Public Works. This was a nice visually appealing representation of the departments and their records. It would be very effective in a presentation setting.

I then created a new sheet and selected ‘Number of records’ and dimension ‘Vendor.zip’. Then I selected the recommended map view. This presented the data in a readable, visually pleasing format. The circles on the map represented the zip codes location and their size represented their number of records that corresponded. A concentration for example, in Louisiana or Georgia is due to the fact that there are many zip codes represented in this particular area.

LS0tCnRpdGxlOiAiQnVzaW5lc3MgQW5hbHl0aWNzIExhYiBXb3Jrc2hlZXQgMDQiCmF1dGhvcjogIkthcmluYSBSb2NoYSIKZGF0ZTogIlN1bW1lciAyMDE3IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKc3VidGl0bGU6IENNRSBHcm91cCBGb3VuZGF0aW9uIEJ1c2luZXNzIEFuYWx5dGljcyBMYWIKLS0tCgojIyMgQWJvdXQKClIgY2FuIGJlIHVzZWQgdG8gbWFrZSBiYXNpYyB2aXN1YWwgYW5hbHl0aWNzLCB3aGljaCBjYW4gYmUgaGVscGZ1bCBpbiB1bmRlcnN0YW5kaW5nIHRoZSBkYXRhIGhvbGlzdGljYWxseS4gQWRkaXRpb25hbGx5LCBSIGNhbiBoZWxwIGZpbmQgY29ycmVsYXRpb25zIGJldHdlZW4gdmFyaWFibGVzIGFuZCBjcmVhdGUgc2NhdHRlciBwbG90cy4gCgpJbiB0aGlzIGxhYiB3ZSB3aWxsIGRlbHZlIGRlZXBlciBpbnRvIHRoZSBtYXJrZXRpbmcgZGF0YSBzZXQgd2l0aCBSIHZpc3VhbCBhbmFseXRpY3MgYW5kIHVzZSBUYWJsZWF1IHRvIHZpc3VhbGl6ZSB0aGUgY3JlZGl0IHJpc2sgZGF0YSBzZXQuIAoKIyMjIFNldHVwCgpNYWtlIHN1cmUgdG8gZG93bmxvYWQgdGhlIGZvbGRlciB0aXRsZWQgJ2JzYWRfbGFiMDQnIHppcCBmb2xkZXIgYW5kIGV4dHJhY3QgdGhlIGZvbGRlciB0byB1bnppcCBpdC4gTmV4dCwgd2UgbXVzdCBzZXQgdGhpcyBmb2xkZXIgYXMgdGhlIHdvcmtpbmcgZGlyZWN0b3J5LiBUaGUgd2F5IHRvIGRvIHRoaXMgaXMgdG8gb3BlbiBSIFN0dWRpbywgZ28gdG8gJ1Nlc3Npb24nLCBzY3JvbGwgZG93biB0byAnU2V0IFdvcmtpbmcgRGlyZWN0b3J5JywgYW5kIGNsaWNrICdUbyBTb3VyY2UgRmlsZSBMb2NhdGlvbicuIE5vdywgZm9sbG93IHRoZSBkaXJlY3Rpb25zIHRvIGNvbXBsZXRlIHRoZSBsYWIuCgotLS0tLS0tLS0tCgojIyMgVGFzayAxCgpGaXJzdCwgcmVhZCBpbiB0aGUgYHN0YXRlc19wdXJjaGFzZV9vcmRlcnMuY3N2YCBmaWxlIGFuZCBtYWtlIHN1cmUgYWxsIHRoZSBjb2x1bW5zIGFyZSBjYXB0dXJlZCBhbmQgY2hlY2sgdGhlIGZpcnN0IGNvdXBsZSBvZiByb3dzIG9mIHRoZSBkYXRhc2V0ICJoZWFkKG15ZGF0YSkiCgpgYGB7cn0KI1RoaXMgZnVuY3Rpb24gd2lsbCBhbGxvdyB0aGUgZGVzaXJlZCBmaWxlICdzdGF0ZXNfcHVyY2hhc2Vfb3JkZXIuY3N2JyBpbnRvIFIgU3R1ZGlvIGFuZCBuYW1lcyBpdCAnbXlkYXRhJwpteWRhdGEgPSByZWFkLmNzdihmaWxlPSJkYXRhL3N0YXRlc19wdXJjaGFzZV9vcmRlcnMuY3N2IikKaGVhZChteWRhdGEpCmBgYAoKCgoKYGBge3J9CiNUaGUgZm9sbG93aW5nIGNvbW1hbmRzIHdpbGwgYWxsb3cgdGhlIGNvbHVtbnMgdG8gYmUgY2FsbGVkCnZlbmRvcnN0YXRlID0gbXlkYXRhJFZFTkRPUi5TVEFURQpkZXBhcnRtZW50bmFtZSA9IG15ZGF0YSRERVBBUlRNRU5ULk5BTUUKcmVjb3JkdHlwZSA9IG15ZGF0YSRSRUNPUkQuVFlQRQpwdXJjaGFzZW9yZGVyID0gbXlkYXRhJFBVUkNIQVNFLk9SREVSLk5VTUJFUgppbnB1dGRhdGUgPSBteWRhdGEkSU5QVVQuREFURQp0b3RhbGFtb3VudCA9IG15ZGF0YSRUT1RBTC5BTU9VTlQKZGVwYXJ0bWVudG51bWJlciA9IG15ZGF0YSRERVBBUlRNRU5ULk5VTUJFUgpQT2NhdGVnb3J5ZGVzY3JpcHRpb24gPSBteWRhdGEkUE8uQ0FURUdPUlkuREVTQ1JJUFRJT04Kdm91Y2hlZGFtb3VudCA9IG15ZGF0YSRWT1VDSEVELkFNT1VOVAp2ZW5kb3JuYW1lMSA9IG15ZGF0YSRWRU5ET1IuTkFNRS4xCnZlbmRvcmFkZHJlc3MxID0gbXlkYXRhJFZFTkRPUi5BRERSRVNTLjEKdmVuZG9yY2l0eSA9IG15ZGF0YSRWRU5ET1IuQ0lUWQp2ZW5kb3J6aXAgPSBteWRhdGEkVkVORE9SLlpJUAp0b3RhbGl0ZW1zID0gbXlkYXRhJFZFTkRPUi5aSVAKaXRlbXVuaXRjb3N0ID0gbXlkYXRhJElURU0uVU5JVC5DT1NUCml0ZW10b3RhbGNvc3QgPSBteWRhdGEkSVRFTS5UT1RBTC5DT1NUCnVuaXF1ZWlkID0gbXlkYXRhJFVOSVFVRS5JRApgYGAKCgoqKkZyZXF1ZW5jeSBUYWJsZXMgZm9yIGNvbHVtbnMgJ3ZlbmRvci5zdGF0ZScgYW5kICdkZXBhcnRtZW50Lm5hbWUnKioKYGBge3J9CiMgSGVyZSwgSSB3aWxsIGNyZWF0ZSBhIGZyZXF1ZW5jeSB0YWJsZSBmb3IgdGhlIGNvbHVtbiAndmVuZG9yLnN0YXRlJyBhbmQgbmFtZSBpdCB2ZW5kb3JzdGF0ZWZxdGFibGUuIFVzaW5nIHRoZSBjb21tYW5kICJ2YXJpYWJsZV90YWJsZSA9IHRhYmxlKHZhcmlhYmxlKSIKdmVuZG9yc3RhdGVmcXRhYmxlID0gdGFibGUodmVuZG9yc3RhdGUpCnZlbmRvcnN0YXRlZnF0YWJsZQpgYGAKClRoZSB0YWJsZSBhYm92ZSBpcyB0aGUgZnJlcXVlbmN5IHRhYmxlIHRoYXQgZGlzcGxheXMgdGhlIHZlbmRvcnMgYW5kIHRoZSBhbW91bnQgb2Ygb3JkZXJzIHRoYXQgdGhleSBoYXZlIGZ1bGZpbGxlZCBmb3IgZWFjaCBzdGF0ZS4gCmBgYHtyfQojIEhlcmUsIEkgd2lsbCBjcmVhdGUgYSBmcmVxdWVuY3kgdGFibGUgZm9yIHRoZSBjb2x1bW4gJ2RlcGFydG1lbnQubmFtZScgYW5kIG5hbWUgaXQgZGVwdG5hbWVmcXRhYmxlCmRlcHRuYW1lZnF0YWJsZSA9IHRhYmxlKGRlcGFydG1lbnRuYW1lKQpkZXB0bmFtZWZxdGFibGUKYGBgClRoaXMgZnJlcXVlbmN5IHRhYmxlIGRpc3BsYXlzIHRoZSBvcmRlcnMgcGxhY2VkIGJ5IGVhY2ggZGVwYXJ0bWVudC4gSS5lLiAxOTUgb3JkZXJzIHBsYWNlZCBieSB0aGUgU2hlcmlmZidzIG9mZmljZSwgMjU5IGJ5IHRoZSBQYXJpc2ggYXR0b3JuZXksIDE2MSBieSBvdXRzaWRlIGFnZW5jaWVzLCBldGMuIAoKCgpOb3csIHdlIHdpbGwgdmlzdWFsaXplIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyB0byBvYnNlcnZlIHNvbWUgcGF0dGVybnMgYW5kIGRpZmZlcmVuY2VzLiAKCkZpcnN0IGNyZWF0ZSBhIGJhciBjaGFydCBvZiB0aGUgbG9hbiBwdXJwb3NlIGZyZXF1ZW5jeSB0YWJsZSBhbmQgam9iIGZyZXF1ZW5jeSB0YWJsZSBSZW1lbWJlciB0byBleHRyYWN0IHRoZSBzYWxlcyB2YXJpYWJsZSBiZWZvcmUgY2FsbGluZyBpdC4KCgoqKkJBUiBQTE9UUyBGT1IgVkVORE9SIFNUQVRFIEFORCBERVBBUlRNRU5UIE5BTUUqKgoKVkFSSUFCTEVTOiBWRU5ET1IgU1RBVEUgQU5EIERFUEFSVE1FTlQgTkFNRSAKCmBgYHtyfQojIEhlcmUsIEkgd2lsbCBjcmVhdGUgYSBiYXIgcGxvdCBmb3IgdGhlIHZhcmlhYmxlIHZlbmRvciBzdGF0ZS4gCmJhcnBsb3QodmVuZG9yc3RhdGVmcXRhYmxlKQpgYGAKSXQgaXMgZGlmZmljdWx0IHRvIG1ha2UgYXNzZXNtZW50cyB3aXRoIHRoaXMgYmFycGxvdCBzaW5jZSB0aGUgcmFuZ2VzIGFyZSBzbyBsYXJnZSwgdGhlcmVmb3JlIEkgd2lsbCBjcmVhdGUgYW5vdGhlciBiYXJwbG90IHdpdGggYSBjZXJ0YWluIG51bWJlciBvZiBzcGVjaWZpZWQgcm93czogMTAtMTgKCmBgYHtyfQojIEJhciBwbG90IHdpdGggdmFyaWFibGUgdmVuZG9yIHN0YXRlLSBzcGVjaWZpZWQgcm93cyAKYmFycGxvdCh2ZW5kb3JzdGF0ZWZxdGFibGVbMTA6MThdKQpgYGAKVGhpcyBsYXlvdXQgaXMgbXVjaCBlYXNpZXIgdG8gdmlldywgd2l0aCBub3RpbmcgdGhhdCBJbmRpYW5hIGhhZCB0aGUgbW9zdCBvcmRlcnMgaW4gY29tcGFyaXNvbiB0byBJZGFobyB3aXRoIHRoZSBsZWFzdCBpbiB0aGlzIHNwZWNpZmllZCByYW5nZS4gCgoKYGBge3J9CiMgQmFyIHBsb3Qgd2l0aCB2YXJpYWJsZSBkZXBhcnRtZW50IG5hbWUgd2l0aCBhbHNvIHNwZWNpZmllZCByb3dzIHRvIGFsbG93IGJldHRlciB1c2UgZm9yIGFzc2Vzc21lbnRzLiAKYmFycGxvdChkZXB0bmFtZWZxdGFibGVbMTI6MThdKQpgYGAKCgoqKkhpc3RvZ3JhbSBvZiBWZW5kb3IgU3RhdGUgYW5kIERlcGFydG1lbnQgTmFtZSoqCgpCZWxvdywgSSB3aWxsIGNyZWF0IGhpc3RvZ3JhbXMgZm9yIHRoZSB2YXJpYWJsZXMgdmVuZG9yIHN0YXRlIGFuZCBkZXBhcnRtZW50IG5hbWUgdXNpbmcgdGhlIGZ1bmN0aW9uICJoaXN0KHZhcmlhYmxlKSIKCgpgYGB7cn0KIyBQbG90IGEgaGlzdG9ncmFtIHVzaW5nIHRoZSAiIGhpc3QodmFyaWFibGUpICIgY29tbWFuZCB3aGVyZSB2YXJpYWJsZSBpcyB2ZW5kb3Igc3RhdGUKaGlzdCh2ZW5kb3JzdGF0ZWZxdGFibGUpCmBgYAoKYGBge3J9CiMgUGxvdCBhIGhpc3RvZ3JhbSB1c2luZyB0aGUgIiBoaXN0KHZhcmlhYmxlKSAiIGNvbW1hbmQgd2hlcmUgdmFyaWFibGUgaXMgdmVuZG9yIHN0YXRlCmhpc3QoZGVwdG5hbWVmcXRhYmxlKQpgYGAKCgoKKiBXaGF0IGFyZSBzb21lIG9ic2VydmFibGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgYm94cGxvdCBhbmQgdGhlIGhpc3RvZ3JhbT8gUGxlYXNlIHJlY29yZCB5b3VyIG9ic2VydmF0aW9ucyBoZXJlLiAKVGhlIGRpZmZlcmVuY2VzIGJldHdlZW0gdGhlIGJveHBsb3QgYW5kIGhpc3RvZ3JhbSBpcyB0aGF0IHRoZSBib3hwbG90IGlzIGEgbXVjaCBzaW1wbGlmaWVkIHZpZXcgd2hpbGUgdGhlIGhpc3RvZ3JhbSBmcmVxdWVuY3kgcmVxdWlyZXMgZnVydGhlciBhbmFseXNpcyB3aXRoIGNvcnJlbGF0aW9ucyB0byBza2V3cyBhbmQgdGhlaXIgcmVsYXRpb24uIAoKKipQaWUgQ2hhcnQgZm9yIFZlbmRvciBzdGF0ZSBhbmQgRGVwYXJ0bWVudCBOYW1lKioKClZBUklBQkxFOiBWRU5ET1IgU1RBVEUgCmBgYHtyfQojIFBsb3QgYSBwaWUgY2hhcnQgdXNpbmc6CiMgcGllKHZhcmlhYmxlKSAgKGNvbW1hbmQgdG8gbWFrZSBhIHBpZSBjaGFydCkKIyBUbyBnZXQgb25seSB2YWx1ZXMgZ3JlYXRoZXIgdGhhbiBOIGZyb20gYSBmcmVxdWVuY3kgdGFibGUgdXNlOgojIG5ld190YWJsZSA9IG15X3RhYmxlWyBteV90YWJsZSA+IE4gXSAgKGNvbW1hbmQgdG8gc2VsZWN0IHZhbHVlcyBncmVhdGhlciB0aGFuIE4pCm5ld1ZlbmRvclN0YXRlVGFibGUgPSB2ZW5kb3JzdGF0ZWZxdGFibGVbdmVuZG9yc3RhdGVmcXRhYmxlID41MDBdCnBpZShuZXdWZW5kb3JTdGF0ZVRhYmxlKQpgYGAKCldoeSBpcyB0aGlzIHZpc3VhbCBub3QgYSBnb29kIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkYXRhPyBXaGF0IG1ha2VzIHRoZSBiYXJwbG90IGEgYmV0dGVyIHJlcHJlc2VudGF0aW9uPwpUaGUgYWJvdmUgdmlzdWFsIGlzIG5vdCBhIGdvb2QgcmVwcmVzZW50YXRpb24gYmVjYXVzZSBpdCBmYWlscyB0byBwcm92aWRlIGFuIGFjY3VyYXRlIHJlcHJlc2VudGF0aW9uIG9mIGFsbCBzdGF0ZXMuIFBsdXMgdGhlcmUgYXJlIHN0YXRlcyB3aG9zZSBzb21lIG9yZGVycyBlbmNvbXBhc3MgYSBsaXR0bGUgbGVzcyB0aGFuIGhhbGYgb2Ygd2hhdCB0aGUgb3RoZXIgc3RhdGVzIGNvbWJpbmVkIG9yZGVyZWQgd2hpY2ggZG9lcyBub3QgbGVhdmUgZm9yIGEgY2xlYXIgYW5kIHJlYWRhYmxlIGdyYXBoLiAKCgoKLS0tLS0tLS0tLQoKIyMjIFRhc2sgMgoKTGV0cyBleHBsb3JlIHRoZSBJbGxpbm9pcyBUYXggZGF0YXNldCAoUkVBRCB0aGUgInN0YXRlX3RheF9pbGxpbm9pcy5jc3YiIGZpbGUpIGFuZCBjcmVhdGUgYSBzY2F0dGVycGxvdCBvZiBjb3Jwb3JhdGUgdGF4IHZzLiBwZXJzb25hbCBpbmNvbWUgdGF4LiAgCgpUaGUgZGF0YXNldCBzdGFydCBpbiAxOTk0IGJ1dCB3ZSB3YW50IHRvIHRheCByZXZlbnVlIHNpbmNlIDIwMDAgZm9yIHRoZSBmaXJzdCBxdWFydGVyIG9mIHRoZSB5ZWFyICJRMSIKClZBUklBQkxFUzogcGVyc29uYWxfaW5jb21lX3RheCBhbmQgY29ycG9yYXRlX2luY29tZV90YXgKCmBgYHtyfQpteWRhdGExID0gcmVhZC5jc3YoZmlsZT0iZGF0YS9zdGF0ZV90YXhfaWxsaW5vaXMuY3N2IikKaGVhZChteWRhdGExKQpgYGAKCgoKCmBgYHtyfQojIHJlYWQgdGhlIGRhdGFzZXQgZXh0cmFjdCB0aGUgeWVhciB2YXJpYWJsZSBhbmQgb3JkZXIgdGhlIGRhdGFzZXQgYnkgeWVhciBpbiBkZWNyZWFzaW5nIG9yZGVyIHVzaW5nIHRoZSBjb21tYW5kOgp5ZWFyID0gbXlkYXRhMSR5ZWFyCnllYXIKYGBgCgpgYGB7cn0KIyBUbyBjaGFuZ2UgdGhlIHdheSB0aGF0IFIgc2hvd3MgdmVyeSBsYXJnZSBvciBzbWFsbCB2YWx1ZXMgd2UgY2FuIHVzZSB0aGUgZm9sbG93aW5nIGNvbW1hbmQ6Cm9wdGlvbnMoc2NpcGVuID0gOTk5OSkKCiMgbXlkYXRhID0gbXlkYXRhWyBvcmRlcih5ZWFyLCBkZWNyZWFzaW5nID0gVFJVRSkgLCBdICghIE9yZGVyIHRoZSBkYXRhIGluIGRlY3JlYXNpbmcgb3JkZXIpCm15ZGF0YTEgPSBteWRhdGExWyBvcmRlcihteWRhdGExJHllYXIsIGRlY3JlYXNpbmcgPSBUUlVFKSxdIApgYGAKCmBgYHtyfQojIEZyb20gdGhlIG9yZGVyZWQgZGF0YXNldCBFeHRyYWN0IHBlcnNvbmFsX2luY29tZV90YXggdmFyaWFibGUKcGVyc29uYWxpbmNvbWV0YXggPSBteWRhdGEkcGVyc29uYWxfaW5jb21lX3RheApwZXJzb25hbGluY29tZXRheApgYGAKCmBgYHtyfQojRnJvbSB0aGUgb3JkZXJlZCBkYXRhc2V0IEV4dHJhY3QgY29ycG9yYXRlX2luY29tZV90YXggdmFyaWFibGUKY29ycGluY29tZXRheCA9IG15ZGF0YTEkY29ycG9yYXRlX2luY29tZV90YXgKY29ycGluY29tZXRheApgYGAKClRoZSBwcmV2aW91cyB0YXNrIGZvY3VzZWQgb24gdmlzdWFsaXppbmcgb25lIHZhcmlhYmxlLiBBIGdvb2Qgd2F5IHRvIHZpc3VhbGl6ZSB0d28gdmFyaWFibGVzIHdvdWxkIGJlIGEgc2NhdHRlciBwbG90IG9yIGEgY29ycmVsYXRpb24gbWF0cml4LgoKYGBge3J9CiMgUGxvdCBwZXJzb25hbF9pbmNvbWVfdGF4IHZzLiBjb3Jwb3JhdGVfaW5jb21lX3RheCAKIyBwZXJzb25hbF9pbmNvbWVfdGF4IHdpbGwgYmUgb24gdGhlIHgtYXhpcwojIGNvcnBvcmF0ZV9pbmNvbWVfdGF4IHdpbGwgYmUgb24gdGhlIHktYXhpcwpwbG90KHBlcnNvbmFsaW5jb21ldGF4LCBjb3JwaW5jb21ldGF4LCB4bGFiID0gIlBlcnNvbmFsIEluY29tZSBUYXgiLCB5bGFiID0gIkNvcnBvcmF0ZSBJbmNvbWUgVGF4IikKYGBgClRoZSBhYm92ZSBzY2F0dGVyIHBsb3QgZmVhdHVyZXMgdGhlIHR3byB2YXJpYWJsZXM6IHBlcnNvbmFsIGluY29tZSB0YXggb24gdGhlIHgtYXhpcyBhbmQgY29ycG9yYXRlIGluY29tZSB0YXggb24gdGhlIHktYXhpcy4gVGhlc2UgdHdvIHZhcmlhYmxlcyBhbGxvdyBmb3IgYSBjbGVhcmVyIHJlcHJlc2VuYXRpb24uIAoKCiogU2VsZWN0IG9ubHkgZW50cmllcyBncmF0aGVyIHRoYW4geWVhciAxOTk5CiogQWZ0ZXIgc2VsZWN0aW5nIGVudHJpZXMgZ3JlYXRoZXIgdGhhbiB5ZWFyIDE5OTksIHNlbGVjdCBlbnRyaWVzIGZvciBxdWFydGVyICJRMSIKCgpgYGB7cn0KYXMubnVtZXJpYyhteWRhdGExJHllYXIpCmBgYAoKCmBgYHtyfQojIFRvIGNyZWF0ZSBhIG5ld19kYXRhIGZpbHRlcmluZyBmb3IgYW4gTiBOVU1FUklDIHZhbHVlIHdlIGNhbiBkbyB0aGUgZm9sbG93aW5nCiMgbmV3X2RhdGEgPSBteWRhdGFbIG15ZGF0YSROVU1FUklDX1ZBUklBQkxFID4gTiwgXQoKbmV3X2RhdGEgPSBteWRhdGExWyBteWRhdGExJHllYXIgPiAxOTk5LF0KYGBgCgpgYGB7cn0KIyBJZiB3ZSBuZWVkIHRvIG1ha2UgYW5vdGhlciBmaWx0ZXIgb24gYSBOT04tTlVNRVJJQyB3ZSBjYW4gZG8gdGhlIGZvbGxvd2luZwojIG5ld19kYXRhID0gbmV3X2RhdGFbIG5ld19kYXRhJENIQVJfVkFSSUFCTEUgPT0gIlExIiwgXQpuZXdfZGF0YSA9IG5ld19kYXRhWyBuZXdfZGF0YSRxdWFydGVyID09IlExIiAsIF0KaGVhZChteWRhdGExKQpgYGAKCgpJdCBtaWdodCBiZSBlYXNpZXIgdG8gbm90aWNlIGEgdHJlbmQgaWYgdGhlcmUgd2FzIGEgbGluZSB0aGF0IGZpdCB0aHJvdWdoIHRoZSBwb2ludHMuIFNvLCBsZXRzIHJlcGVhdCB1c2luZyB0aGUgZnVuY3Rpb24gJ3NjYXR0ZXIuc21vb3RoJy4gVGhpcyBmdW5jdGlvbnMgYWRkcyBhIHNtb290aCBjdXJ2ZSBjb21wdXRlZCBieSBsb2VzcywgYSBtZXRob2QgdG8gbG9jYWxseSBzbW9vdGggYSBjdXJ2ZS4gCgoqKlNjYXR0ZXJQbG90KioKSW4gdGhpcyBzZWNpdG9uIEkgd2lsbCBjcmVhdGUgYSBzY2F0dGVyIHBsb3QgZm9yIHRoZSBkaWN0YXRlZCB2YXJpYWJsZXMuIEkgd2lsbCB1c2UgdGhlIGZ1bnRpb24gJ3NjYXR0ZXIuc21vb3RoKHZhcmlhYmxlLCB2YXJpYWJsZSknCgpgYGB7cn0Kc2NhdHRlci5zbW9vdGgocGVyc29uYWxpbmNvbWV0YXgsY29ycGluY29tZXRheCwgeGxhYiA9ICJQZXJzb25hbCBJbmNvbWUgVGF4IiwgeWxhYiA9ICJDb3Jwb3JhdGUgSW5jb21lIFRheCIpCmBgYAoKTm93LCByZXBlYXQgYmVsb3cgZm9yIHRvdGFsX3RheF9VUyB2cy4gdG90YWxfc3RhdGUsIGZvbGxvd2luZyB0aGUgZXhhbXBsZSB0aGF0IHdhcyBqdXN0IHByb3ZpZGVkLiBPYnNlcnZlIGFuZCBub3RlIGFueSB0cmVuZHMgaW4gdGhlIHNjYXR0ZXIgcGxvdHMgYW5kIHBvdGVudGlhbCByZWxhdGlvbnNoaXBzIGJlbG93LiBEbyB0aGUgc2FtZSBmb3IgYWxsIG51bWVyaWMgdmFyaWFibGVzLgoKYGBge3J9CiMgdG90YWxfdGF4X1VTIHZzLiB0b3RhbF9zdGF0ZQojIEkgd2lsbCBmaXJzdCBjYWxsIGFuZCBleHRyYWN0IHRoZSBkZXNpcmVkIG51bWVyaWMgdmFyaWFibGVzCgp0b3RhbHRheFVTID0gbXlkYXRhMSR0b3RhbF90YXhfVVMKCnRvdGFsc3RhdGUgPSBteWRhdGExJHRvdGFsX3N0YXRlCgpnZW5lcmFsc2FsZXN0YXggPSBteWRhdGExJGdlbmVyYWxfc2FsZXNfdGF4Cgptb3RvcmZ1ZWx0YXggPSBteWRhdGExJG1vdG9yX2Z1ZWxfdGF4CmBgYAoKYGBge3J9CnNjYXR0ZXIuc21vb3RoKG15ZGF0YTEkdG90YWxfdGF4X1VTLCBteWRhdGExJHRvdGFsX3N0YXRlLCB4bGFiID0gIlRvdGFsIFRheCBVUyIsIHlsYWIgPSAiVG90YWwgU3RhdGUiKQpgYGAKCgpUbyBxdWFudGlmeSB0aGUgZGF0YSwgaXRzIGJlc3QgdG8gbG9vayBhdCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0d28gdmFyaWFibGVzLgpXaGF0IGRvZXMgdGhpcyBjb3JyZWxhdGlvbiBleHBsYWluPwoKYGBge3J9CmNvcihteWRhdGExJHRvdGFsX3N0YXRlLG15ZGF0YTEkcGVyc29uYWxfaW5jb21lX3RheCkKYGBgCgpUaGUgbnVtYmVyIGFib3ZlLCAwLjk2NTIxNzYsIGluZGljYXRlcyB0aGF0IHRoZSB0d28gdmFyaWFibGUgYXJlIHN0cm9uZ2x5IGFuZCBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQuIAoKCgpCZWxvdywgY29tcHV0ZSB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBldmVyeSBwYWlyIG9mIHZhcmlhYmxlcyAodG90YWxfdGF4X1VTLHRvdGFsX3N0YXRlLCBwZXJzb25hbF9pbmNvbWVfdGF4LCBjb3Jwb3JhdGVfaW5jb21lX3RheCwgZ2VuZXJhbF9zYWxlc190YXgsIG1vdG9yX2Z1ZWxfdGF4ICkuIAoKTWFrZSBzdXJlIHRvIGV4dHJhY3QgdGhlIHZhcmlhYmxlcyBmaXJzdCBhbmQgdGhlbiBjb21wdXRlIHRoZSBjb3JyZWxhdGlvbi4gCgpgYGB7cn0KI0hlcmUsIEkgY3JlYXRlZCBhIGNvcnJlbGFpdG9uIHRhYmxlIG9mIHRoZSBudW1lcmljIHZhcmlhYmxlcyB1c2luZyB0aGUgY29tbWFuZCBjb3JyMDEgPSBteWRhdGFbIGMoMyw0KSBdIApjb3JyMDEgPSBteWRhdGExW2MoMzo2KV0KY29yKGNvcnIwMSkKYGBgCgoKCi0tLS0tLS0tLS0KCiMjIyBUYXNrIDMgLSBUQUJMRUFVCgoKVG8gYmVnaW4gdGhpcyB0YXNrLCBJIGltcG9ydGVkIHRoZSBzdGF0ZV9wdXJjaGFzZXMgZmlsZSBpbnRvIFRhYmxlYXUuIEkgc2VsZWN0ZWQgdGhlIGRpbWVuc2lvbiAnRGVwYXJ0bWVudCBuYW1lJyBhbmQgbWVhc3VyZSAnTnVtYmVyIG9mIFJlY29yZHMnLiAKCiFbXShpbWdzL2JhciAucG5nKQoKKiBXaGF0IGRlcGFydG1lbnQgJ2JpbicgaGFzIHRoZSBoaWdoZXN0IGNvdW50PyBXaGF0IGlzIHRoZSBjb3VudD8gClRoZSBEZXBhcnRtZW50IG9mIFB1YmxpYyBXb3JrcyB3aXRoIDUsNTIzCgoKTmV4dCwgSSBjaG9zZSB0aGUgJ3RyZWVtYXAnIHZpZXcuIFRoaXMgYXNzZW1ibGVkIGFsbCB0aGUgZGVwYXJ0bWVudHMgaW50byBzcXVhcmVzIHRoYXQgd2VyZSBzaXplZCBhY2NvcmRpbmdseSB0byB0aGUgbnVtYmVyIG9mIHJlY29yZHMgdGhleSBoYWQuIFRoZXJlZm9yZSB0aGUgbGFyZ2VzdCB3YXMgdGhlIERlcGFydG1lbnQgb2YgUHVibGljIFdvcmtzLiBUaGlzIHdhcyBhIG5pY2UgdmlzdWFsbHkgYXBwZWFsaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkZXBhcnRtZW50cyBhbmQgdGhlaXIgcmVjb3Jkcy4gSXQgd291bGQgYmUgdmVyeSBlZmZlY3RpdmUgaW4gYSBwcmVzZW50YXRpb24gc2V0dGluZy4gCiFbXShpbWdzL3RyZWVtYXAucG5nKQoKCgoKSSB0aGVuIGNyZWF0ZWQgYSBuZXcgc2hlZXQgYW5kIHNlbGVjdGVkICdOdW1iZXIgb2YgcmVjb3JkcycgYW5kIGRpbWVuc2lvbiAnVmVuZG9yLnppcCcuIFRoZW4gSSBzZWxlY3RlZCB0aGUgcmVjb21tZW5kZWQgbWFwIHZpZXcuIFRoaXMgcHJlc2VudGVkIHRoZSBkYXRhIGluIGEgcmVhZGFibGUsIHZpc3VhbGx5IHBsZWFzaW5nIGZvcm1hdC4gVGhlIGNpcmNsZXMgb24gdGhlIG1hcCByZXByZXNlbnRlZCB0aGUgemlwIGNvZGVzIGxvY2F0aW9uIGFuZCB0aGVpciBzaXplIHJlcHJlc2VudGVkIHRoZWlyIG51bWJlciBvZiByZWNvcmRzIHRoYXQgY29ycmVzcG9uZGVkLiAKQSBjb25jZW50cmF0aW9uIGZvciBleGFtcGxlLCBpbiBMb3Vpc2lhbmEgb3IgR2VvcmdpYSBpcyBkdWUgdG8gdGhlIGZhY3QgdGhhdCB0aGVyZSBhcmUgbWFueSB6aXAgY29kZXMgcmVwcmVzZW50ZWQgaW4gdGhpcyBwYXJ0aWN1bGFyIGFyZWEuIAoKIVtdKGltZ3MvbWFwVGFiLnBuZykKCgoK