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/states_purchase_orders.csv")
#loan_purpose = mydata$Loan.Purpose !Do the same for all the columns!
head(mydata)

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.

# Command to create a frequency table: variable_table = table(variable) 
vendorstate = mydata$VENDOR.STATE
vendorstatetable = table(vendorstate)
vendorstatetable
vendorstate
          ,    AL    AR    AZ    CA    CD    CO    CT    DC    FL    GA    IA    ID    IL    IN    KS    KY    LA    MA    MD    ME    MI    MN    MO    MS 
    2    62   400   125   189   877     1   114    99    69   418   555  1089    14   330   180    76   100 20178   149    32    12    55   233    74   361 
   NC    ND    NE    NH    NJ    NM    NV    NY    OH    OK    OR    PA    RI    SC    SD    TN    TX    UT    VA    VT    WA    WI    WV 
  313     4    56    14  1633     3    12   210   180     9    27   401    15    41     6   152  2561    77   295     3    60   583     3 
deptname = mydata$DEPARTMENT.NAME
deptnametable = table(deptname)
deptnametable
deptname
                      ANIMAL CONTROL CENTER BATON ROUGE CONVENTION & VISTORS COMMISSION                    BATON ROUGE RIVER CENTER 
                                         79                                           4                                         134 
                             CITY CONSTABLE                                  CITY COURT              COMMUNITY DEVELOPMENT PROGRAMS 
                                        115                                        1412                                        1674 
                      CONSTRUCTION PROJECTS                                     CORONER                       COUNCIL ADMINISTRATOR 
                                       2224                                          47                                         182 
                      COUNCIL BUDGET OFFICE                  DEPARTMENT OF PUBLIC WORKS               DEPT OF BUILDINGS AND GROUNDS 
                                         84                                        5523                                         326 
DEPT OF BUSINESS OPERATIONS AND CAPITAL PRO                         DEPT OF DEVELOPMENT                    DEPT OF FLEET MANAGEMENT 
                                        107                                          69                                         325 
                        DEPT OF MAINTENANCE         DEPT OF TRANSPORTATION AND DRAINAGE                              DISTRICT COURT 
                                        220                                         200                                          20 
              DOWNTOWN DEVELOPMENT DISTRICT                  EMERGENCY MEDICAL SERVICES                          FINANCE DEPARTMENT 
                                        182                                        1640                                         758 
                            FIRE DEPARTMENT                    FIRE PROTECTION DISTRICT        GREATER BATON ROUGE AIRPORT DISTRICT 
                                        498                                         217                                        1677 
             HUMAN DEVELOPMENT AND SERVICES                             HUMAN RESOURCES                        INFORMATION SERVICES 
                                       2733                                         561                                        1156 
                             JUVENILE COURT                           JUVENILE SERVICES                    LIBRARY BOARD OF CONTROL 
                                          1                                         376                                        2620 
                       METROPOLITAN COUNCIL                   MOSQUITO & RODENT CONTROL MUNICIPAL FIRE & POLICE CIVIL SERVICE BOARD 
                                        186                                         413                                          11 
OFC. OF HOMELAND SECURITY & EMERGENCY PREPA               OFFICE OF THE MAYOR-PRESIDENT                            OUTSIDE AGENCIES 
                                        472                                         386                                         161 
                            PARISH ATTORNEY                         PLANNING COMMISSION                           POLICE DEPARTMENT 
                                        259                                         138                                        4066 
                  PUBLIC INFORMATION OFFICE                                  PURCHASING                         REGISTRAR OF VOTERS 
                                         94                                         253                                          43 
                          RETIREMENT OFFICE                 ROAD REHABILITATION PROGRAM                            SHERIFF'S OFFICE 
                                          4                                         607                                         195 

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(vendorstatetable)

barplot(deptnametable)

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(vendorstatetable)

hist(deptnametable)

There are some notable differences between the barplots and histograms. The barplots appear to be more comprehansive and reveal more usable information to us as users of the data.The histograms have numbers on both axes and it makes it a little less meaningful. Also, with the vendor state graphs especially, it is hard to see how the two relate.

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)
pie(vendorstatetable)

pie(deptnametable)

# 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)
newvendor = vendorstatetable[vendorstatetable > 500]
newdept = deptnametable[deptnametable > 500]
pie(newvendor)

pie(newdept)

A pie chart does not appear to be a good representation of the data because it doesn’t really allow us to see how many there really are. Especially once we narrow it down to values greater than 500, it is not very accurate at all. The barplot at least shows us all of them in a clearer way and we are able to see how many there are of each, rather than just how they compare to others in size.


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

# 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:
taxdata = read.csv(file = "data/state_tax_illinois.csv")
taxdata
year = taxdata$year
# mydata = mydata[ order(year, decreasing = TRUE) , ] (! Order the data in decreasing order)
taxdatabyyear = taxdata[order(year, decreasing = TRUE) , ] 
taxdatabyyear
# From the ordered dataset Extract personal_income_tax variable
personalinctax = taxdatabyyear$personal_income_tax
personalinctax
 [1] 3746068 3950197 3982255 4527933 3059415 3048487 4505921 4961971 3680480 3723148 4345335 5353786 3608644 3565618 4197619 4790521 3403778 3435763 3195378
[20] 4096206 3343258 3180912 2515231 2702995 2134865 2291055 2448000 2899039 2104226 2110793 2803540 3427232 2149834 1968785 2522527 3101128 2071646 2017821
[39] 2264920 2817633 1963943 1820838 2130841 2511261 1817907 1734644 1902394 2181615 1675372 1661305 1862628 2169229 1600339 1571274 1945837 2195228 1648066
[58] 1661059 1867375 2405920 1679520 1650800 2272950 2713373 1763852 1631196 1877350 1984974 1644788 1640535 1877350 1984974 1579539 1545132 1689205 1786043
[77] 1579539 1545132 1553374 1642423 1421240 1390281 1427336 1509160 1306955 1278486 1360884 1425714 1200911 1174752
# From the ordered dataset Extract corporate_income_tax variable
corpinctax = taxdatabyyear$corporate_income_tax
corpinctax
 [1]  903017 1163900 1055932 1425459  674725  625819 1105062 1508593  787764  785112 1028486 1764708  877978  948199  834075 1365912  778008  891425  632404
[20] 1160954  655115  639437  729180  971001  507167  504933  642923 1403105  459494  527011  790459 1225043  519552  439074  704820 1158924  537828  562274
[39]  591623  901551  556344  516272  557161  735924  438193  468903  431059  470507  324041  354688  362344  421964  222017  395572  362374  432374  261916
[58]  246964  583639  786706  274660  313983  792893  828315  433323  412970  473585  814038  476261  457064  473585  814038  370340  303603  435527  748621
[77]  370340  303603  391428  672820  340579  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(personalinctax,corpinctax)

# To create a new_data filtering for an N NUMERIC value we can do the following
# new_data = mydata[ mydata$NUMERIC_VARIABLE > N, ]
newtaxdata = taxdatabyyear[ taxdatabyyear$NUMERIC_VARIABLE > 1999]
newtaxdata
# 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 = newtaxdata[ newtaxdata$CHAR_VARIABLE == "Q1" , ]
new

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.

scatter.smooth(personalinctax,corpinctax)

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.

totalus = taxdatabyyear$total_tax_US
totalstate = taxdatabyyear$total_state
scatter.smooth(totalus,totalstate)

# total_tax_US vs. total_state

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

cor(totalus,totalstate)
[1] 0.9621443
cor(personalinctax,corpinctax)
[1] 0.8794823

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.

gentax = taxdatabyyear$general_sales_tax
motortax = taxdatabyyear$motor_fuel_tax
cor(gentax,motortax)
[1] 0.3603301
cor(totalus,gentax)
[1] 0.8811287
cor(personalinctax,motortax)
[1] -0.02182754
# 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 )
corr1 = taxdatabyyear [c(3,4)]
cor(corr1)
             total_tax_US total_state
total_tax_US    1.0000000   0.9621443
total_state     0.9621443   1.0000000
# cor(corr01) (will give you the correlation table for variables in columns 3 and 4)
corr2 = taxdatabyyear [c(3:8)]
cor(corr2)
                     total_tax_US total_state personal_income_tax corporate_income_tax general_sales_tax motor_fuel_tax
total_tax_US            1.0000000   0.9621443          0.89216270           0.83789591         0.8811287     0.21085187
total_state             0.9621443   1.0000000          0.96521760           0.85471906         0.8632035     0.13978644
personal_income_tax     0.8921627   0.9652176          1.00000000           0.87948231         0.7363658    -0.02182754
corporate_income_tax    0.8378959   0.8547191          0.87948231           1.00000000         0.5503725    -0.05636253
general_sales_tax       0.8811287   0.8632035          0.73636583           0.55037249         1.0000000     0.36033009
motor_fuel_tax          0.2108519   0.1397864         -0.02182754          -0.05636253         0.3603301     1.00000000
# 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.

  1. Refer to file ‘states_purchase_orders.csv’ in the data folder

  2. Start Tableau and enter your LUC email if prompted.

  3. Import the file into Tableau. Choose the Text File option when importing

  4. Under the dimensions tab located on the left side of the screen.

The Department of Public Works has the highest count which is 5,523.

The bar graph above shows the number of records for each department name. The department with the most records is Public Works, with 5,523 records. The next highest is the Police Department, with 4,066 records. Some departments have so few records that it doesn’t look like they have any when compared to others on the bar graph. Overall, there is a wide array of how many records there are for each department.

  1. Create a new sheet by clicking on the icon next to your current sheet.

The highlights on the map are centered in Southern Louisiana, Southeast Texas, Southeast Iowa, and Northern New Jersey. There are also highlights in some places in California, Wisconsin, Florida, and along the East Coast from Northern Virginia to Massachusetts. Overall, most of the highlights appear to be in the eastern part of the country, with the highest amount in Louisiana and Texas. This may be due to their proximity to water transportation. However, it seems more likely that the vendors are located in these areas because of the lower costs for production.

LS0tCnRpdGxlOiAiQnVzaW5lc3MgQW5hbHl0aWNzIExhYiBXb3Jrc2hlZXQgMDQiCmF1dGhvcjogIlJhY2hlbCBIbGF2YWNlayIKZGF0ZTogIkF1Z3VzdCA5LCAyMDE3IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKc3VidGl0bGU6IENNRSBHcm91cCBGb3VuZGF0aW9uIEJ1c2luZXNzIEFuYWx5dGljcyBMYWIKLS0tCgojIyMgQWJvdXQKClIgY2FuIGJlIHVzZWQgdG8gbWFrZSBiYXNpYyB2aXN1YWwgYW5hbHl0aWNzLCB3aGljaCBjYW4gYmUgaGVscGZ1bCBpbiB1bmRlcnN0YW5kaW5nIHRoZSBkYXRhIGhvbGlzdGljYWxseS4gQWRkaXRpb25hbGx5LCBSIGNhbiBoZWxwIGZpbmQgY29ycmVsYXRpb25zIGJldHdlZW4gdmFyaWFibGVzIGFuZCBjcmVhdGUgc2NhdHRlciBwbG90cy4gCgpJbiB0aGlzIGxhYiB3ZSB3aWxsIGRlbHZlIGRlZXBlciBpbnRvIHRoZSBtYXJrZXRpbmcgZGF0YSBzZXQgd2l0aCBSIHZpc3VhbCBhbmFseXRpY3MgYW5kIHVzZSBUYWJsZWF1IHRvIHZpc3VhbGl6ZSB0aGUgY3JlZGl0IHJpc2sgZGF0YSBzZXQuIAoKIyMjIFNldHVwCgpNYWtlIHN1cmUgdG8gZG93bmxvYWQgdGhlIGZvbGRlciB0aXRsZWQgJ2JzYWRfbGFiMDQnIHppcCBmb2xkZXIgYW5kIGV4dHJhY3QgdGhlIGZvbGRlciB0byB1bnppcCBpdC4gTmV4dCwgd2UgbXVzdCBzZXQgdGhpcyBmb2xkZXIgYXMgdGhlIHdvcmtpbmcgZGlyZWN0b3J5LiBUaGUgd2F5IHRvIGRvIHRoaXMgaXMgdG8gb3BlbiBSIFN0dWRpbywgZ28gdG8gJ1Nlc3Npb24nLCBzY3JvbGwgZG93biB0byAnU2V0IFdvcmtpbmcgRGlyZWN0b3J5JywgYW5kIGNsaWNrICdUbyBTb3VyY2UgRmlsZSBMb2NhdGlvbicuIE5vdywgZm9sbG93IHRoZSBkaXJlY3Rpb25zIHRvIGNvbXBsZXRlIHRoZSBsYWIuCgotLS0tLS0tLS0tCgojIyMgVGFzayAxCgpGaXJzdCwgcmVhZCBpbiB0aGUgYGNyZWRpdHJpc2suY3N2YCBmaWxlIGFuZCBtYWtlIHN1cmUgYWxsIHRoZSBjb2x1bW5zIGFyZSBjYXB0dXJlZCBhbmQgY2hlY2sgdGhlIGZpcnN0IGNvdXBsZSBvZiByb3dzIG9mIHRoZSBkYXRhc2V0ICJoZWFkKG15ZGF0YSkiCgpgYGB7cn0KbXlkYXRhID0gcmVhZC5jc3YoZmlsZT0iZGF0YS9zdGF0ZXNfcHVyY2hhc2Vfb3JkZXJzLmNzdiIpCiNsb2FuX3B1cnBvc2UgPSBteWRhdGEkTG9hbi5QdXJwb3NlICFEbyB0aGUgc2FtZSBmb3IgYWxsIHRoZSBjb2x1bW5zIQpoZWFkKG15ZGF0YSkKYGBgCgoKRm9yIENBVEVHT1JJQ0FMIHZhcmlhYmxlcyBpdCBpcyB1c2VmdWwgdG8ga25vdyB0aGUgZnJlcXVlbmN5IG9mIHRoZSBkaWZmZXJlbnQgY2F0ZWdvcmllcy9sZXZlbHMgb2YgdGhlIHZhcmlhYmxlLiBXZSBjYW4gZG8gdGhhdCBieSB1c2luZyB0aGUgdGFibGUoKSBmdW5jdGlvbi4gCgoqIENyZWF0ZSBhIGZyZXF1ZW5jeSB0YWJsZSBmb3IgdGhlIExvYW4gUHVycG9zZSBhbmQgSm9iCmBgYHtyfQojIENvbW1hbmQgdG8gY3JlYXRlIGEgZnJlcXVlbmN5IHRhYmxlOiB2YXJpYWJsZV90YWJsZSA9IHRhYmxlKHZhcmlhYmxlKSAKdmVuZG9yc3RhdGUgPSBteWRhdGEkVkVORE9SLlNUQVRFCnZlbmRvcnN0YXRldGFibGUgPSB0YWJsZSh2ZW5kb3JzdGF0ZSkKdmVuZG9yc3RhdGV0YWJsZQoKZGVwdG5hbWUgPSBteWRhdGEkREVQQVJUTUVOVC5OQU1FCmRlcHRuYW1ldGFibGUgPSB0YWJsZShkZXB0bmFtZSkKZGVwdG5hbWV0YWJsZQpgYGAKCk5vdywgd2Ugd2lsbCB2aXN1YWxpemUgc29tZSBvZiB0aGUgdmVyaWFibGVzIHRvIG9ic2VydmUgc29tZSBwYXR0ZXJucyBhbmQgZGlmZmVyZW5jZXMuIAoKRmlyc3QgY3JlYXRlIGEgYmFyIGNoYXJ0IG9mIHRoZSBsb2FuIHB1cnBvc2UgZnJlcXVlbmN5IHRhYmxlIGFuZCBqb2IgZnJlcXVlbmN5IHRhYmxlIFJlbWVtYmVyIHRvIGV4dHJhY3QgdGhlIHNhbGVzIHZhcmlhYmxlIGJlZm9yZSBjYWxsaW5nIGl0LgoKVkFSSUFCTEVTOiBKb2IgYW5kIExvYW4gUHVycG9zZQoKYGBge3J9CiMgUGxvdCBhIGJhciBwbG90IHVzaW5nIHRoZSAiIGJhcnBsb3QodmFyaWFibGUpICIgY29tbWFuZCB3aGVyZSB2YXJpYWJsZSBpcyB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlCmJhcnBsb3QodmVuZG9yc3RhdGV0YWJsZSkKYmFycGxvdChkZXB0bmFtZXRhYmxlKQpgYGAKCk5leHQsIGNyZWF0ZSBhIGhpc3RvZ3JhbSBvZiBsb2FuIHB1cnBvc2UgZnJlcXVlbmN5IHRhYmxlIGFuZCBqb2IgZnJlcXVlbmN5IHRhYmxlCgpgYGB7cn0KIyBQbG90IGEgaGlzdG9ncmFtIHVzaW5nIHRoZSAiIGhpc3QodmFyaWFibGUpICIgY29tbWFuZCB3aGVyZSB2YXJpYWJsZSBpcyB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlCmhpc3QodmVuZG9yc3RhdGV0YWJsZSkKaGlzdChkZXB0bmFtZXRhYmxlKQpgYGAKClRoZXJlIGFyZSBzb21lIG5vdGFibGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgYmFycGxvdHMgYW5kIGhpc3RvZ3JhbXMuIFRoZSBiYXJwbG90cyBhcHBlYXIgdG8gYmUgbW9yZSBjb21wcmVoYW5zaXZlIGFuZCByZXZlYWwgbW9yZSB1c2FibGUgaW5mb3JtYXRpb24gdG8gdXMgYXMgdXNlcnMgb2YgdGhlIGRhdGEuVGhlIGhpc3RvZ3JhbXMgaGF2ZSBudW1iZXJzIG9uIGJvdGggYXhlcyBhbmQgaXQgbWFrZXMgaXQgYSBsaXR0bGUgbGVzcyBtZWFuaW5nZnVsLiBBbHNvLCB3aXRoIHRoZSB2ZW5kb3Igc3RhdGUgZ3JhcGhzIGVzcGVjaWFsbHksIGl0IGlzIGhhcmQgdG8gc2VlIGhvdyB0aGUgdHdvIHJlbGF0ZS4KCgpMYXN0bHksIGNyZWF0ZSBhIHBpZSBjaGFydCBvZiBMb2FuIHB1cnBvc2UgZnJlcXVlbmN5IHRhYmxlLiBQbG90IG9ubHkgdmFsdWVzIGdyZWF0aGVyIHRoYW4gMTAuCgpWQVJJQUJMRTogTG9hbiBQdXJwb3NlCmBgYHtyfQojIFBsb3QgYSBwaWUgY2hhcnQgdXNpbmc6CiMgcGllKHZhcmlhYmxlKSAgKGNvbW1hbmQgdG8gbWFrZSBhIHBpZSBjaGFydCkKcGllKHZlbmRvcnN0YXRldGFibGUpCnBpZShkZXB0bmFtZXRhYmxlKQojIFRvIGdldCBvbmx5IHZhbHVlcyBncmVhdGhlciB0aGFuIE4gZnJvbSBhIGZyZXF1ZW5jeSB0YWJsZSB1c2U6CiMgbmV3X3RhYmxlID0gbXlfdGFibGVbIG15X3RhYmxlID4gTiBdICAoY29tbWFuZCB0byBzZWxlY3QgdmFsdWVzIGdyZWF0aGVyIHRoYW4gTikKbmV3dmVuZG9yID0gdmVuZG9yc3RhdGV0YWJsZVt2ZW5kb3JzdGF0ZXRhYmxlID4gNTAwXQpuZXdkZXB0ID0gZGVwdG5hbWV0YWJsZVtkZXB0bmFtZXRhYmxlID4gNTAwXQoKcGllKG5ld3ZlbmRvcikKcGllKG5ld2RlcHQpCmBgYAoKQSBwaWUgY2hhcnQgZG9lcyBub3QgYXBwZWFyIHRvIGJlIGEgZ29vZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgZGF0YSBiZWNhdXNlIGl0IGRvZXNuJ3QgcmVhbGx5IGFsbG93IHVzIHRvIHNlZSBob3cgbWFueSB0aGVyZSByZWFsbHkgYXJlLiBFc3BlY2lhbGx5IG9uY2Ugd2UgbmFycm93IGl0IGRvd24gdG8gdmFsdWVzIGdyZWF0ZXIgdGhhbiA1MDAsIGl0IGlzIG5vdCB2ZXJ5IGFjY3VyYXRlIGF0IGFsbC4gVGhlIGJhcnBsb3QgYXQgbGVhc3Qgc2hvd3MgdXMgYWxsIG9mIHRoZW0gaW4gYSBjbGVhcmVyIHdheSBhbmQgd2UgYXJlIGFibGUgdG8gc2VlIGhvdyBtYW55IHRoZXJlIGFyZSBvZiBlYWNoLCByYXRoZXIgdGhhbiBqdXN0IGhvdyB0aGV5IGNvbXBhcmUgdG8gb3RoZXJzIGluIHNpemUuIAoKLS0tLS0tLS0tLQoKIyMjIFRhc2sgMgoKTGV0cyBleHBsb3JlIHRoZSBJbGxpbm9pcyBUYXggZGF0YXNldCAoUkVBRCB0aGUgInN0YXRlX3RheF9pbGxpbm9pcy5jc3YiIGZpbGUpIGFuZCBjcmVhdGUgYSBzY2F0dGVycGxvdCBvZiBjb3Jwb3JhdGUgdGF4IHZzLiBwZXJzb25hbCBpbmNvbWUgdGF4LiAgCgpUaGUgZGF0YXNldCBzdGFydCBpbiAxOTk0IGJ1dCB3ZSB3YW50IHRvIHRheCByZXZlbnVlIHNpbmNlIDIwMDAgZm9yIHRoZSBmaXJzdCBxdWFydGVyIG9mIHRoZSB5ZWFyICJRMSIKClZBUklBQkxFUzogcGVyc29uYWxfaW5jb21lX3RheCBhbmQgY29ycG9yYXRlX2luY29tZV90YXgKCmBgYHtyfQojIFRvIGNoYW5nZSB0aGUgd2F5IHRoYXQgUiBzaG93cyB2ZXJ5IGxhcmdlIG9yIHNtYWxsIHZhbHVlcyB3ZSBjYW4gdXNlIHRoZSBmb2xsb3dpbmcgY29tbWFuZDoKb3B0aW9ucyhzY2lwZW4gPSA5OTk5KQoKIyByZWFkIHRoZSBkYXRhc2V0IGV4dHJhY3QgdGhlIHllYXIgdmFyaWFibGUgYW5kIG9yZGVyIHRoZSBkYXRhc2V0IGJ5IHllYXIgaW4gZGVjcmVhc2luZyBvcmRlciB1c2luZyB0aGUgY29tbWFuZDoKdGF4ZGF0YSA9IHJlYWQuY3N2KGZpbGUgPSAiZGF0YS9zdGF0ZV90YXhfaWxsaW5vaXMuY3N2IikKdGF4ZGF0YQp5ZWFyID0gdGF4ZGF0YSR5ZWFyCiMgbXlkYXRhID0gbXlkYXRhWyBvcmRlcih5ZWFyLCBkZWNyZWFzaW5nID0gVFJVRSkgLCBdICghIE9yZGVyIHRoZSBkYXRhIGluIGRlY3JlYXNpbmcgb3JkZXIpCnRheGRhdGFieXllYXIgPSB0YXhkYXRhW29yZGVyKHllYXIsIGRlY3JlYXNpbmcgPSBUUlVFKSAsIF0gCnRheGRhdGFieXllYXIKIyBGcm9tIHRoZSBvcmRlcmVkIGRhdGFzZXQgRXh0cmFjdCBwZXJzb25hbF9pbmNvbWVfdGF4IHZhcmlhYmxlCnBlcnNvbmFsaW5jdGF4ID0gdGF4ZGF0YWJ5eWVhciRwZXJzb25hbF9pbmNvbWVfdGF4CnBlcnNvbmFsaW5jdGF4CiMgRnJvbSB0aGUgb3JkZXJlZCBkYXRhc2V0IEV4dHJhY3QgY29ycG9yYXRlX2luY29tZV90YXggdmFyaWFibGUKY29ycGluY3RheCA9IHRheGRhdGFieXllYXIkY29ycG9yYXRlX2luY29tZV90YXgKY29ycGluY3RheApgYGAKClRoZSBwcmV2aW91cyB0YXNrIGZvY3VzZWQgb24gdmlzdWFsaXppbmcgb25lIHZhcmlhYmxlLiBBIGdvb2Qgd2F5IHRvIHZpc3VhbGl6ZSB0d28gdmFyaWFibGVzIHdvdWxkIGJlIGEgc2NhdHRlciBwbG90IG9yIGEgY29ycmVsYXRpb24gbWF0cml4LgoKYGBge3J9CiMgUGxvdCBwZXJzb25hbF9pbmNvbWVfdGF4IHZzLiBjb3Jwb3JhdGVfaW5jb21lX3RheCAKIyBwZXJzb25hbF9pbmNvbWVfdGF4IHdpbGwgYmUgb24gdGhlIHgtYXhpcwojIGNvcnBvcmF0ZV9pbmNvbWVfdGF4IHdpbGwgYmUgb24gdGhlIHktYXhpcwoKcGxvdChwZXJzb25hbGluY3RheCxjb3JwaW5jdGF4KQpgYGAKCiogU2VsZWN0IG9ubHkgZW50cmllcyBncmF0aGVyIHRoYW4geWVhciAxOTk5CiogQWZ0ZXIgc2VsZWN0aW5nIGVudHJpZXMgZ3JlYXRoZXIgdGhhbiB5ZWFyIDE5OTksIHNlbGVjdCBlbnRyaWVzIGZvciBxdWFydGVyICJRMSIKCmBgYHtyfQojIFRvIGNyZWF0ZSBhIG5ld19kYXRhIGZpbHRlcmluZyBmb3IgYW4gTiBOVU1FUklDIHZhbHVlIHdlIGNhbiBkbyB0aGUgZm9sbG93aW5nCiMgbmV3X2RhdGEgPSBteWRhdGFbIG15ZGF0YSROVU1FUklDX1ZBUklBQkxFID4gTiwgXQpuZXd0YXhkYXRhID0gdGF4ZGF0YWJ5eWVhclsgdGF4ZGF0YWJ5eWVhciROVU1FUklDX1ZBUklBQkxFID4gMTk5OV0KbmV3dGF4ZGF0YQoKIyBJZiB3ZSBuZWVkIHRvIG1ha2UgYW5vdGhlciBmaWx0ZXIgb24gYSBOT04tTlVNRVJJQyB3ZSBjYW4gZG8gdGhlIGZvbGxvd2luZwojIG5ld19kYXRhID0gbmV3X2RhdGFbIG5ld19kYXRhJENIQVJfVkFSSUFCTEUgPT0gIlExIiwgXQpuZXcgPSBuZXd0YXhkYXRhWyBuZXd0YXhkYXRhJENIQVJfVkFSSUFCTEUgPT0gIlExIiAsIF0KbmV3CmBgYAoKSXQgbWlnaHQgYmUgZWFzaWVyIHRvIG5vdGljZSBhIHRyZW5kIGlmIHRoZXJlIHdhcyBhIGxpbmUgdGhhdCBmaXQgdGhyb3VnaCB0aGUgcG9pbnRzLiBTbywgbGV0cyByZXBlYXQgdXNpbmcgdGhlIGZ1bmN0aW9uICdzY2F0dGVyLnNtb290aCcuIFRoaXMgZnVuY3Rpb25zIGFkZHMgYSBzbW9vdGggY3VydmUgY29tcHV0ZWQgYnkgbG9lc3MsIGEgbWV0aG9kIHRvIGxvY2FsbHkgc21vb3RoIGEgY3VydmUuIAoKYGBge3J9CnNjYXR0ZXIuc21vb3RoKHBlcnNvbmFsaW5jdGF4LGNvcnBpbmN0YXgpCmBgYAoKTm93LCByZXBlYXQgYmVsb3cgZm9yIHRvdGFsX3RheF9VUyB2cy4gdG90YWxfc3RhdGUsIGZvbGxvd2luZyB0aGUgZXhhbXBsZSB0aGF0IHdhcyBqdXN0IHByb3ZpZGVkLiBPYnNlcnZlIGFuZCBub3RlIGFueSB0cmVuZHMgaW4gdGhlIHNjYXR0ZXIgcGxvdHMgYW5kIHBvdGVudGlhbCByZWxhdGlvbnNoaXBzIGJlbG93LiBEbyB0aGUgc2FtZSBmb3IgYWxsIG51bWVyaWMgdmFyaWFibGVzLgoKYGBge3J9CnRvdGFsdXMgPSB0YXhkYXRhYnl5ZWFyJHRvdGFsX3RheF9VUwp0b3RhbHN0YXRlID0gdGF4ZGF0YWJ5eWVhciR0b3RhbF9zdGF0ZQpzY2F0dGVyLnNtb290aCh0b3RhbHVzLHRvdGFsc3RhdGUpCiMgdG90YWxfdGF4X1VTIHZzLiB0b3RhbF9zdGF0ZQpgYGAKClRvIHF1YW50aWZ5IHRoZSBkYXRhLCBpdHMgYmVzdCB0byBsb29rIGF0IHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHR3byB2YXJpYWJsZXMuCldoYXQgZG9lcyB0aGlzIGNvcnJlbGF0aW9uIGV4cGxhaW4/CgpgYGB7cn0KY29yKHRvdGFsdXMsdG90YWxzdGF0ZSkKY29yKHBlcnNvbmFsaW5jdGF4LGNvcnBpbmN0YXgpCmBgYAoKQmVsb3csIGNvbXB1dGUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gZXZlcnkgcGFpciBvZiB2YXJpYWJsZXMgKHRvdGFsX3RheF9VUyx0b3RhbF9zdGF0ZSwgcGVyc29uYWxfaW5jb21lX3RheCwgY29ycG9yYXRlX2luY29tZV90YXgsIGdlbmVyYWxfc2FsZXNfdGF4LCBtb3Rvcl9mdWVsX3RheCApLiAKCk1ha2Ugc3VyZSB0byBleHRyYWN0IHRoZSB2YXJpYWJsZXMgZmlyc3QgYW5kIHRoZW4gY29tcHV0ZSB0aGUgY29ycmVsYXRpb24uIAoKYGBge3J9CmdlbnRheCA9IHRheGRhdGFieXllYXIkZ2VuZXJhbF9zYWxlc190YXgKbW90b3J0YXggPSB0YXhkYXRhYnl5ZWFyJG1vdG9yX2Z1ZWxfdGF4CmNvcihnZW50YXgsbW90b3J0YXgpCmNvcih0b3RhbHVzLGdlbnRheCkKY29yKHBlcnNvbmFsaW5jdGF4LG1vdG9ydGF4KQojIFRvIG1ha2UgYSBjb3JyZWxhdGlvbiB0YWJsZSBvZiBhbGwgdGhlIE5VTUVSSUMgdmFyaWFibGVzIHlvdSBjYW4gc2VsZWN0IHNvbWUgY29sdW1ucyBvciBhIHJhbmdlIG9mIGNvbHVtbnMsIHdpdGggdGhlIGZvbGxvd2luZyBjb21tYW5kOgoKIyBjb3JyMDEgPSBteWRhdGFbIGMoMyw0KSBdIChUaGUgY29tbWFuZCBjKDMsNCwuLi4pIGluc2lkZSB0aGUgYnJhY2tldHMgc2VsZWN0cyBhIGdpdmVuIGNvbHVtbiApCmNvcnIxID0gdGF4ZGF0YWJ5eWVhciBbYygzLDQpXQpjb3IoY29ycjEpCiMgY29yKGNvcnIwMSkgKHdpbGwgZ2l2ZSB5b3UgdGhlIGNvcnJlbGF0aW9uIHRhYmxlIGZvciB2YXJpYWJsZXMgaW4gY29sdW1ucyAzIGFuZCA0KQpjb3JyMiA9IHRheGRhdGFieXllYXIgW2MoMzo4KV0KY29yKGNvcnIyKQojIGNvcnIwMiA9IG15ZGF0YVszOjVdICggdGhlIGNvbW1hbmQgWzM6NV0gc2VsZWN0cyBhIHJhbmdlIG9mIGNvbHVtbnMgZnJvbSAzIHRvIDUpCiMgY29yKGNvcnIwMikKYGBgCgotLS0tLS0tLS0tCgojIyMgVGFzayAzIC0gVEFCTEVBVQoKRm9sbG93IHRoZSBkaXJlY3Rpb25zIG9uIHRoZSB3b3Jrc2hlZXQsIGRvd25sb2FkIHRhYmxlYXUgYWNhZGVtaWMgb24geW91ciBwZXJzb25hbCBjb21wdXRlciBvciB1c2Ugb25lIG9mIHRoZSBsYWJzIGNvbXB1dGVycy4KCiogRG93bmxvYWQgVGFibGVhIGFjYWRlbWljIGhlcmU6IGh0dHBzOi8vd3d3LnRhYmxlYXUuY29tL2FjYWRlbWljL3N0dWRlbnRzCgoxLiBSZWZlciB0byBmaWxlICdzdGF0ZXNfcHVyY2hhc2Vfb3JkZXJzLmNzdicgaW4gdGhlIGRhdGEgZm9sZGVyCgoyLiBTdGFydCBUYWJsZWF1IGFuZCBlbnRlciB5b3VyIExVQyBlbWFpbCBpZiBwcm9tcHRlZC4KCjMuIEltcG9ydCB0aGUgZmlsZSBpbnRvIFRhYmxlYXUuIENob29zZSB0aGUgVGV4dCBGaWxlIG9wdGlvbiB3aGVuIGltcG9ydGluZwoKNC4gVW5kZXIgdGhlIGRpbWVuc2lvbnMgdGFiIGxvY2F0ZWQgb24gdGhlIGxlZnQgc2lkZSBvZiB0aGUgc2NyZWVuLgoKVGhlIERlcGFydG1lbnQgb2YgUHVibGljIFdvcmtzIGhhcyB0aGUgaGlnaGVzdCBjb3VudCB3aGljaCBpcyA1LDUyMy4KCiFbXShpbWdzL1NjcmVlbiBTaG90IDIwMTctMDgtMDkgYXQgMS41Mi40NiBQTS5wbmcpCgoKVGhlIGJhciBncmFwaCBhYm92ZSBzaG93cyB0aGUgbnVtYmVyIG9mIHJlY29yZHMgZm9yIGVhY2ggZGVwYXJ0bWVudCBuYW1lLiBUaGUgZGVwYXJ0bWVudCB3aXRoIHRoZSBtb3N0IHJlY29yZHMgaXMgUHVibGljIFdvcmtzLCB3aXRoIDUsNTIzIHJlY29yZHMuIFRoZSBuZXh0IGhpZ2hlc3QgaXMgdGhlIFBvbGljZSBEZXBhcnRtZW50LCB3aXRoIDQsMDY2IHJlY29yZHMuIFNvbWUgZGVwYXJ0bWVudHMgaGF2ZSBzbyBmZXcgcmVjb3JkcyB0aGF0IGl0IGRvZXNuJ3QgbG9vayBsaWtlIHRoZXkgaGF2ZSBhbnkgd2hlbiBjb21wYXJlZCB0byBvdGhlcnMgb24gdGhlIGJhciBncmFwaC4gT3ZlcmFsbCwgdGhlcmUgaXMgYSB3aWRlIGFycmF5IG9mIGhvdyBtYW55IHJlY29yZHMgdGhlcmUgYXJlIGZvciBlYWNoIGRlcGFydG1lbnQuIAoKCjUuIENyZWF0ZSBhIG5ldyBzaGVldCBieSBjbGlja2luZyBvbiB0aGUgaWNvbiBuZXh0IHRvIHlvdXIgY3VycmVudCBzaGVldC4KCiFbXShpbWdzL1NjcmVlbiBTaG90IDIwMTctMDgtMDkgYXQgMi4wMC4wMyBQTS5wbmcpCgoKVGhlIGhpZ2hsaWdodHMgb24gdGhlIG1hcCBhcmUgY2VudGVyZWQgaW4gU291dGhlcm4gTG91aXNpYW5hLCBTb3V0aGVhc3QgVGV4YXMsIFNvdXRoZWFzdCBJb3dhLCBhbmQgTm9ydGhlcm4gTmV3IEplcnNleS4gVGhlcmUgYXJlIGFsc28gaGlnaGxpZ2h0cyBpbiBzb21lIHBsYWNlcyBpbiBDYWxpZm9ybmlhLCBXaXNjb25zaW4sIEZsb3JpZGEsIGFuZCBhbG9uZyB0aGUgRWFzdCBDb2FzdCBmcm9tIE5vcnRoZXJuIFZpcmdpbmlhIHRvIE1hc3NhY2h1c2V0dHMuIE92ZXJhbGwsIG1vc3Qgb2YgdGhlIGhpZ2hsaWdodHMgYXBwZWFyIHRvIGJlIGluIHRoZSBlYXN0ZXJuIHBhcnQgb2YgdGhlIGNvdW50cnksIHdpdGggdGhlIGhpZ2hlc3QgYW1vdW50IGluIExvdWlzaWFuYSBhbmQgVGV4YXMuIFRoaXMgbWF5IGJlIGR1ZSB0byB0aGVpciBwcm94aW1pdHkgdG8gd2F0ZXIgdHJhbnNwb3J0YXRpb24uIEhvd2V2ZXIsIGl0IHNlZW1zIG1vcmUgbGlrZWx5IHRoYXQgdGhlIHZlbmRvcnMgYXJlIGxvY2F0ZWQgaW4gdGhlc2UgYXJlYXMgYmVjYXVzZSBvZiB0aGUgbG93ZXIgY29zdHMgZm9yIHByb2R1Y3Rpb24uCgoKCg==