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
mydata = read.csv(file = "data/creditrisk.csv")
#Name the extracted variable
age = mydata$Age
#Calculate the average age below. Refer to Worksheet 1 for the correct command.
age_mean = mean(age)
age_mean
[1] 34.39765
#Calculate standard deviation of age below. Refer to Worksheet 1 for the correct command.
age_sd = sd(age)
age_sd
[1] 11.04513
#Calculate the maximum of age below. The command to find the maximum is max(variable) where variable is the extracted variable.
age_max = max(age)
age_max
[1] 73
#Calculate the minimum of age below. The command to find the minimum is min(variable) where variable is the extracted variable.
age_min = min(age)
age_min
[1] 18

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.

#Use the formula above to calculate the upper and lower threshold
age_lower = age_mean - (3) * age_sd
age_upper = age_mean + (3) * age_sd
age_upper
[1] 67.53302
age_lower
[1] 1.262269

A method to find the upper and lower thresholds discussed in introductory statistics courses involves finding the interquartile range. Follow along below to see how we first calculate the interquartile range.

quantile(age)
  0%  25%  50%  75% 100% 
  18   26   32   41   73 
lowerq = quantile(age)[2]
upperq = quantile(age)[4]
iqr = upperq - lowerq
iqr
75% 
 15 

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
 75% 
63.5 

Below is the lower threshold:

lowerthreshold = lowerq - (iqr * 1.5)
lowerthreshold
25% 
3.5 

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.

age[age>upperthreshold]
[1] 64 65 67 64 73 65 66 67 65
mydata[age>upperthreshold,]
age[age<lowerthreshold]
integer(0)
boxplot(age,horizontal = TRUE)


Task 2

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

mydata = read.csv(file = "data/creditriskorg.csv")
head(mydata)
#tail(mydata)

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.

mydata = read.csv("data/creditriskorg.csv",skip = 1)
head(mydata)
#str(mydata)
summary(mydata)
          Loan.Purpose      Checking        Savings    Months.Customer
 Small Appliance:105    $-      :251    $-      : 62   Min.   : 5.0   
 New Car        :104    $216.00 :  2    $127.00 :  3   1st Qu.:13.0   
 Furniture      : 85    $271.00 :  2    $836.00 :  3   Median :19.0   
 Business       : 44    $296.00 :  2    $904.00 :  3   Mean   :22.9   
 Used Car       : 40    $305.00 :  2    $922.00 :  3   3rd Qu.:28.0   
 Education      : 23    $497.00 :  2    $104.00 :  2   Max.   :73.0   
 (Other)        : 24   (Other)  :164   (Other)  :349                  
 Months.Employed Gender   Marital.Status      Age        Housing   
 Min.   :  0.0   F:135   Divorced:156    Min.   :18.0   Other: 52  
 1st Qu.:  6.0   M:290   Married : 36    1st Qu.:26.0   Own  :292  
 Median : 20.0           Single  :233    Median :32.0   Rent : 81  
 Mean   : 31.9                           Mean   :34.4              
 3rd Qu.: 47.0                           3rd Qu.:41.0              
 Max.   :119.0                           Max.   :73.0              
                                                                   
     Years              Job      Credit.Risk
 Min.   :1.00   Management: 54   High:211   
 1st Qu.:2.00   Skilled   :271   Low :214   
 Median :3.00   Unemployed: 11              
 Mean   :2.84   Unskilled : 89              
 3rd Qu.:4.00                               
 Max.   :4.00                               
                                            

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?

checkings
  [1]    NA    NA    NA   638   963  2827    NA    NA  6509   966    NA    NA
 [13]   322    NA   396    NA   652   708   207   287    NA   101    NA    NA
 [25]    NA   141    NA  2484   237    NA   335  3565    NA 16647    NA    NA
 [37]    NA   940    NA    NA   218    NA 16935   664   150    NA   216    NA
 [49]    NA    NA   265  4256   870   162    NA    NA    NA   461    NA    NA
 [61]    NA   580    NA    NA    NA    NA   758   399   513    NA    NA   565
 [73]    NA    NA    NA   166  9783   674    NA 15328    NA   713    NA    NA
 [85]    NA    NA    NA   303   900    NA  1257    NA   273   522    NA    NA
 [97]    NA    NA   514   457  5133    NA   644   305  9621    NA    NA    NA
[109]    NA    NA  6851 13496   509    NA 19155    NA    NA   374    NA   828
[121]    NA   829    NA    NA   939    NA   889   876   893 12760    NA    NA
[133]   959    NA    NA    NA    NA   698    NA    NA    NA 12974    NA   317
[145]    NA    NA    NA   192    NA    NA    NA    NA    NA   942    NA  3329
[157]    NA    NA    NA    NA    NA    NA   339    NA    NA    NA   105    NA
[169]   216   113   109    NA    NA  8176    NA   468  7885    NA    NA    NA
[181]    NA    NA    NA    NA    NA    NA   734    NA    NA   172   644    NA
[193]   617    NA   586    NA    NA    NA    NA    NA   522   585  5588    NA
[205]   352    NA  2715   560   895   305    NA    NA    NA  8948    NA    NA
[217]    NA    NA    NA   483    NA    NA    NA   663   624    NA    NA   152
[229]    NA    NA   498    NA   156  1336    NA    NA    NA  2641    NA    NA
[241]    NA    NA    NA   887    NA    NA    NA    NA 18408   497    NA   946
[253]   986  8122    NA   778   645    NA   682 19812    NA    NA   859    NA
[265]    NA    NA    NA    NA    NA   795    NA    NA    NA    NA   852    NA
[277]    NA   425    NA    NA    NA 11072    NA   219  8060    NA    NA    NA
[289]    NA  1613   757    NA    NA   977   197    NA    NA    NA    NA    NA
[301]   256   296    NA    NA    NA   298    NA  8636    NA    NA 19766    NA
[313]    NA    NA    NA  4089    NA   271   949    NA   911    NA    NA    NA
[325]    NA   271    NA    NA    NA    NA  4802   177    NA    NA   996   705
[337]    NA    NA  5960    NA   759    NA   651   257   955    NA  8249    NA
[349]   956   382    NA   842  3111    NA    NA  2846   231    NA 17366    NA
[361]   332   242    NA   929    NA    NA    NA    NA    NA    NA    NA   646
[373]   538    NA    NA    NA    NA   135  2472    NA 10417   211 16630    NA
[385]   642    NA   296   898   478   315   122    NA    NA    NA   670   444
[397]  3880   819    NA    NA    NA    NA    NA    NA    NA    NA    NA   161
[409]    NA    NA   789   765    NA    NA   983    NA    NA   798    NA   193
[421]   497    NA    NA    NA    NA

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.

checkings[1:6]
[1]  $-          $-          $-          $638.00     $963.00     $2,827.00 
168 Levels:  $-     $1,257.00   $1,336.00   $1,613.00  ...  $996.00 
clean = checkings[1:10]
#substitute comma with blank in all of checking 
clean = sub(",","",clean)
#substitute dollar sign with blank in all of checking
clean = sub("\\$","",clean)
class(clean)
[1] "character"
#numeric convert
clean = as.numeric(clean)
NAs introduced by coercion
class(clean)
[1] "numeric"
#mean with NA removed 
clean
 [1]   NA   NA   NA  638  963 2827   NA   NA 6509  966
#substitute comma with blank in all of checking 
checkings = sub(",","",checkings)
#substitute dollar sign with blank in all of checking
checkings = sub("\\$","",checkings)
#numeric convert
checkings = as.numeric(checkings)
NAs introduced by coercion
#mean with NA removed 
checkings
  [1]    NA    NA    NA   638   963  2827    NA    NA  6509   966    NA    NA
 [13]   322    NA   396    NA   652   708   207   287    NA   101    NA    NA
 [25]    NA   141    NA  2484   237    NA   335  3565    NA 16647    NA    NA
 [37]    NA   940    NA    NA   218    NA 16935   664   150    NA   216    NA
 [49]    NA    NA   265  4256   870   162    NA    NA    NA   461    NA    NA
 [61]    NA   580    NA    NA    NA    NA   758   399   513    NA    NA   565
 [73]    NA    NA    NA   166  9783   674    NA 15328    NA   713    NA    NA
 [85]    NA    NA    NA   303   900    NA  1257    NA   273   522    NA    NA
 [97]    NA    NA   514   457  5133    NA   644   305  9621    NA    NA    NA
[109]    NA    NA  6851 13496   509    NA 19155    NA    NA   374    NA   828
[121]    NA   829    NA    NA   939    NA   889   876   893 12760    NA    NA
[133]   959    NA    NA    NA    NA   698    NA    NA    NA 12974    NA   317
[145]    NA    NA    NA   192    NA    NA    NA    NA    NA   942    NA  3329
[157]    NA    NA    NA    NA    NA    NA   339    NA    NA    NA   105    NA
[169]   216   113   109    NA    NA  8176    NA   468  7885    NA    NA    NA
[181]    NA    NA    NA    NA    NA    NA   734    NA    NA   172   644    NA
[193]   617    NA   586    NA    NA    NA    NA    NA   522   585  5588    NA
[205]   352    NA  2715   560   895   305    NA    NA    NA  8948    NA    NA
[217]    NA    NA    NA   483    NA    NA    NA   663   624    NA    NA   152
[229]    NA    NA   498    NA   156  1336    NA    NA    NA  2641    NA    NA
[241]    NA    NA    NA   887    NA    NA    NA    NA 18408   497    NA   946
[253]   986  8122    NA   778   645    NA   682 19812    NA    NA   859    NA
[265]    NA    NA    NA    NA    NA   795    NA    NA    NA    NA   852    NA
[277]    NA   425    NA    NA    NA 11072    NA   219  8060    NA    NA    NA
[289]    NA  1613   757    NA    NA   977   197    NA    NA    NA    NA    NA
[301]   256   296    NA    NA    NA   298    NA  8636    NA    NA 19766    NA
[313]    NA    NA    NA  4089    NA   271   949    NA   911    NA    NA    NA
[325]    NA   271    NA    NA    NA    NA  4802   177    NA    NA   996   705
[337]    NA    NA  5960    NA   759    NA   651   257   955    NA  8249    NA
[349]   956   382    NA   842  3111    NA    NA  2846   231    NA 17366    NA
[361]   332   242    NA   929    NA    NA    NA    NA    NA    NA    NA   646
[373]   538    NA    NA    NA    NA   135  2472    NA 10417   211 16630    NA
[385]   642    NA   296   898   478   315   122    NA    NA    NA   670   444
[397]  3880   819    NA    NA    NA    NA    NA    NA    NA    NA    NA   161
[409]    NA    NA   789   765    NA    NA   983    NA    NA   798    NA   193
[421]   497    NA    NA    NA    NA

What are some other ways to clean this data in R? How about in Excel?

mean(checkings,na.rm = TRUE)
[1] 2559.805
sum(checkings,na.rm = TRUE)/length(checkings)
[1] 1048.014

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.

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

Using https://erdplus.com/#/standalone draw a star schema using the following three tables:

LS0tCnRpdGxlOiAiQnVzaW5lc3MgQW5hbHl0aWNzIExhYiBXb3Jrc2hlZXQgMDIiCmF1dGhvcjogIllvdXIgTmFtZSBIZXJlIgpkYXRlOiAiU3VtbWVyIDIwMTciCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdApzdWJ0aXRsZTogQ01FIEdyb3VwIEZvdW5kYXRpb24gQnVzaW5lc3MgQW5hbHl0aWNzIExhYgotLS0KCiMjIyBUYXNrIDEKCkZpcnN0LCB3ZSBtdXN0IGNhbGN1bGF0ZSB0aGUgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uLCBtYXhpbXVtLCBhbmQgbWluaW11bSBmb3IgdGhlIEFnZSBjb2x1bW4gdXNpbmcgUi4KCkluIFIsIHdlIG11c3QgcmVhZCBpbiB0aGUgZmlsZSBhZ2FpbiwgZXh0cmFjdCB0aGUgY29sdW1uIGFuZCBmaW5kIHRoZSB2YWx1ZXMgdGhhdCBhcmUgYXNrZWQgZm9yLgoKYGBge3J9CiNSZWFkIEZpbGUKbXlkYXRhID0gcmVhZC5jc3YoZmlsZSA9ICJkYXRhL2NyZWRpdHJpc2suY3N2IikKI05hbWUgdGhlIGV4dHJhY3RlZCB2YXJpYWJsZQphZ2UgPSBteWRhdGEkQWdlCmBgYAoKYGBge3J9CiNDYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgYWdlIGJlbG93LiBSZWZlciB0byBXb3Jrc2hlZXQgMSBmb3IgdGhlIGNvcnJlY3QgY29tbWFuZC4KYWdlX21lYW4gPSBtZWFuKGFnZSkKYWdlX21lYW4KYGBgCgpgYGB7cn0KI0NhbGN1bGF0ZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYWdlIGJlbG93LiBSZWZlciB0byBXb3Jrc2hlZXQgMSBmb3IgdGhlIGNvcnJlY3QgY29tbWFuZC4KYWdlX3NkID0gc2QoYWdlKQphZ2Vfc2QKYGBgCgpgYGB7cn0KI0NhbGN1bGF0ZSB0aGUgbWF4aW11bSBvZiBhZ2UgYmVsb3cuIFRoZSBjb21tYW5kIHRvIGZpbmQgdGhlIG1heGltdW0gaXMgbWF4KHZhcmlhYmxlKSB3aGVyZSB2YXJpYWJsZSBpcyB0aGUgZXh0cmFjdGVkIHZhcmlhYmxlLgphZ2VfbWF4ID0gbWF4KGFnZSkKYWdlX21heApgYGAKCmBgYHtyfQojQ2FsY3VsYXRlIHRoZSBtaW5pbXVtIG9mIGFnZSBiZWxvdy4gVGhlIGNvbW1hbmQgdG8gZmluZCB0aGUgbWluaW11bSBpcyBtaW4odmFyaWFibGUpIHdoZXJlIHZhcmlhYmxlIGlzIHRoZSBleHRyYWN0ZWQgdmFyaWFibGUuCmFnZV9taW4gPSBtaW4oYWdlKQphZ2VfbWluCmBgYAoKTmV4dCwgdXNlIHRoZSBmb3JtdWxhIGZyb20gY2xhc3MgdG8gZGV0ZWN0IGFueSBvdXRsaWVycy4gQW4gb3V0bGllciBpcyB2YWx1ZSB0aGF0ICJsaWVzIG91dHNpZGUiIG1vc3Qgb2YgdGhlIG90aGVyIHZhbHVlcyBpbiBhIHNldCBvZiBkYXRhLiBBIGNvbW1vbiB3YXkgdG8gZXN0aW1hdGUgdGhlIHVwcGVyIGFuZCBsb3dlciB0aHJlc2hvbGQgaXMgdG8gdGFrZSB0aGUgYGBgbWVhbiAoKyBvciAtKSAzICogc3RhbmRhcmQgZGV2aWF0aW9uYGBgLiBUcnkgdXNpbmcgdGhpcyBmb3JtdWxhIHRvIGZpbmQgdGhlIHVwcGVyIGFuZCBsb3dlciBsaW1pdCBmb3IgYWdlLiAKCmBgYHtyfQojVXNlIHRoZSBmb3JtdWxhIGFib3ZlIHRvIGNhbGN1bGF0ZSB0aGUgdXBwZXIgYW5kIGxvd2VyIHRocmVzaG9sZAphZ2VfbG93ZXIgPSBhZ2VfbWVhbiAtICgzKSAqIGFnZV9zZAphZ2VfdXBwZXIgPSBhZ2VfbWVhbiArICgzKSAqIGFnZV9zZAphZ2VfdXBwZXIKYWdlX2xvd2VyCmBgYAoKQSBtZXRob2QgdG8gZmluZCB0aGUgdXBwZXIgYW5kIGxvd2VyIHRocmVzaG9sZHMgZGlzY3Vzc2VkIGluIGludHJvZHVjdG9yeSBzdGF0aXN0aWNzIGNvdXJzZXMgaW52b2x2ZXMgZmluZGluZyB0aGUgaW50ZXJxdWFydGlsZSByYW5nZS4gRm9sbG93IGFsb25nIGJlbG93IHRvIHNlZSBob3cgd2UgZmlyc3QgY2FsY3VsYXRlIHRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlLiAKCmBgYHtyfSAKcXVhbnRpbGUoYWdlKQpsb3dlcnEgPSBxdWFudGlsZShhZ2UpWzJdCnVwcGVycSA9IHF1YW50aWxlKGFnZSlbNF0KaXFyID0gdXBwZXJxIC0gbG93ZXJxCmlxcgpgYGAKClRoZSBmb3JtdWxhIGJlbG93IGNhbGN1bGF0ZXMgdGhlIHRocmVzaG9sZC4gVGhlIHRocmVzaG9sZCBpcyB0aGUgYm91bmRhcmllcyB0aGF0IGRldGVybWluZSBpZiBhIHZhbHVlIGlzIGFuIG91dGxpZXIuIElmIHRoZSB2YWx1ZSBmYWxscyBhYm92ZSB0aGUgdXBwZXIgdGhyZXNob2xkIG9yIGJlbG93IHRoZSBsb3dlciB0aHJlc2hvbGQsIGl0IGlzIGFuIG91dGxpZXIuIAoKQmVsb3cgaXMgdGhlIHVwcGVyIHRocmVzaG9sZDoKYGBge3J9IAp1cHBlcnRocmVzaG9sZCA9IChpcXIgKiAxLjUpICsgdXBwZXJxCnVwcGVydGhyZXNob2xkCmBgYAoKQmVsb3cgaXMgdGhlIGxvd2VyIHRocmVzaG9sZDoKYGBge3J9Cmxvd2VydGhyZXNob2xkID0gbG93ZXJxIC0gKGlxciAqIDEuNSkKbG93ZXJ0aHJlc2hvbGQKYGBgCgpBcmUgdGhlcmUgYW55IG91dGxpZXJzPyBIb3cgbWFueT8gSXQgY2FuIGFsc28gYmUgdXNlZnVsIHRvIHZpc3VhbGl6ZSB0aGUgZGF0YSB1c2luZyBhIGJveCBhbmQgd2hpc2tlciBwbG90LiBUaGUgYm94cGxvdCBiZWxvdyBzdXBwb3J0cyB0aGUgSVFSIHdlIGZvdW5kIG9mIDE1IGFuZCB1cHBlciBhbmQgbG93ZXIgdGhyZXNob2xkLgoKYGBge3J9CmFnZVthZ2U+dXBwZXJ0aHJlc2hvbGRdCmBgYAoKYGBge3J9Cm15ZGF0YVthZ2U+dXBwZXJ0aHJlc2hvbGQsXQpgYGAKCmBgYHtyfQphZ2VbYWdlPGxvd2VydGhyZXNob2xkXQpgYGAKCmBgYHtyfSAKYm94cGxvdChhZ2UsaG9yaXpvbnRhbCA9IFRSVUUpCmBgYAoKLS0tLS0tLS0tLS0tLS0tCgojIyMgVGFzayAyCgpOZXh0LCB3ZSBtdXN0IHJlYWQgdGhlICdjcmVkaXRyaXNrb3JnLmNzdicgZmlsZSBpbnRvIFIuIFRoaXMgaXMgdGhlIG9yaWdpbmFsIGRhdGFzZXQgYW5kIGNvbnRhaW5zIG1pc3NpbmcgdmFsdWVzLiAKCmBgYHtyfQpteWRhdGEgPSByZWFkLmNzdihmaWxlID0gImRhdGEvY3JlZGl0cmlza29yZy5jc3YiKQpoZWFkKG15ZGF0YSkKI3RhaWwobXlkYXRhKQpgYGAKCldlIG9ic2VydmUgdGhhdCB0aGUgY29sdW1uIG5hbWVzIGFyZSBzaGlmdGVkIGRvd24gYmVsb3cuIFNvLCB3ZSBtdXN0IG1ha2Ugc3VyZSB0byB1c2UgdGhlIGNvbW1hbmQgc2tpcCBhbmQgc2V0IHRoZSBoZWFkZXIgdG8gdHJ1ZS4KCmBgYHtyfQpteWRhdGEgPSByZWFkLmNzdigiZGF0YS9jcmVkaXRyaXNrb3JnLmNzdiIsc2tpcCA9IDEpCmhlYWQobXlkYXRhKQpgYGAKCmBgYHtyfQojc3RyKG15ZGF0YSkKc3VtbWFyeShteWRhdGEpCmBgYAoKVG8gY2FsY3VsYXRlIHRoZSBtZWFuIGZvciBDaGVja2luZyBpbiBSLCBmb2xsb3cgV29ya3NoZWV0IDEuIEV4dHJhY3QgdGhlIENoZWNraW5nIGNvbHVtbiBmaXJzdCBhbmQgdGhlbiBmaW5kIHRoZSBhdmVyYWdlIHVzaW5nIHRoZSBmdW5jdGlvbiBidWlsdCBpbiBSLgpXaGF0IGhhcHBlbnMgd2hlbiB3ZSB0cnkgdG8gdXNlIHRoZSBmdW5jdGlvbj8KCmBgYHtyfQpjaGVja2luZ3MgPSBteWRhdGEkQ2hlY2tpbmcKCiNjbGFzcyhjaGVja2luZ3MpCiNzdHIoY2hlY2tpbmdzKQojc3VtbWFyeShjaGVja2luZ3MpCiNtZWFuKGNoZWNraW5ncykKY2hlY2tpbmdzCmBgYAoKVG8gcmVzb2x2ZSB0aGUgZXJyb3IsIHdlIG11c3QgcmVtb3ZlIHVuZGVyc3RhbmQgd2hlcmUgaXQgaXMgY29taW5nIGZyb20uIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgY3N2IGZpbGUsIHdoaWNoIGlzIHF1aXRlIGNvbW1vbiBhcyBtb3N0IGRhdGFzZXRzIGFyZSBub3QgcGVyZmVjdC4gQWRkaXRpb25hbGx5LCB0aGVyZSBhcmUgY29tbWFzIHdpdGhpbiB0aGUgZXhjZWwgc3ByZWFkc2hlZXQsIGFuZCBSIGRvZXMgbm90IHJlY29nbml6ZSB0aGF0ICcxLDIzNCcgaXMgZXF1aXZhbGVudCB0byAnMTIzNCcuIExhc3RseSwgdGhlcmUgYXJlICckJyBzeW1ib2xzIHRocm91Z2hvdXQgdGhlIGZpbGUgd2hpY2ggaXMgbm90IGEgbnVtZXJpY2Egc3ltYm9sIGVpdGhlci4KClRoZSBzdWIgZnVuY3Rpb24gcmVwbGFjZXMgdGhlc2Ugc3ltYm9scyB3aXRoIHNvbWV0aGluZyBlbHNlLiBTbywgaW4gb3JkZXIgdG8gcmVtb3ZlIHRoZSBjb21tYSBpbiB0aGUgbnVtYmVyICIxLDIzNCIsIHdlIG11c3Qgc3Vic3RpdHV0ZSBpdCB3aXRoIGp1c3QgYW4gZW1wdHkgc3BhY2UuCgpBcyBzaG93biBvbiB0aGUgd29ya3NoZWV0LCB0eXBlIGFuZCBjb3B5IHRoZSBleGFjdCBjb21tYW5kcyB0byBmaW5kIHRoZSBtZWFuIHdpdGggdGhlIE5BIHZhbHVlcyByZW1vdmVkLgoKYGBge3J9CmNoZWNraW5nc1sxOjZdCmBgYAoKYGBge3J9CmNsZWFuID0gY2hlY2tpbmdzWzE6MTBdCiNzdWJzdGl0dXRlIGNvbW1hIHdpdGggYmxhbmsgaW4gYWxsIG9mIGNoZWNraW5nIApjbGVhbiA9IHN1YigiLCIsIiIsY2xlYW4pCiNzdWJzdGl0dXRlIGRvbGxhciBzaWduIHdpdGggYmxhbmsgaW4gYWxsIG9mIGNoZWNraW5nCmNsZWFuID0gc3ViKCJcXCQiLCIiLGNsZWFuKQojbnVtZXJpYyBjb252ZXJ0CmNsZWFuID0gYXMubnVtZXJpYyhjbGVhbikKI21lYW4gd2l0aCBOQSByZW1vdmVkIApjbGVhbgpgYGAKCmBgYHtyfQojc3Vic3RpdHV0ZSBjb21tYSB3aXRoIGJsYW5rIGluIGFsbCBvZiBjaGVja2luZyAKY2hlY2tpbmdzID0gc3ViKCIsIiwiIixjaGVja2luZ3MpCiNzdWJzdGl0dXRlIGRvbGxhciBzaWduIHdpdGggYmxhbmsgaW4gYWxsIG9mIGNoZWNraW5nCmNoZWNraW5ncyA9IHN1YigiXFwkIiwiIixjaGVja2luZ3MpCiNudW1lcmljIGNvbnZlcnQKY2hlY2tpbmdzID0gYXMubnVtZXJpYyhjaGVja2luZ3MpCiNtZWFuIHdpdGggTkEgcmVtb3ZlZCAKY2hlY2tpbmdzCmBgYAoKV2hhdCBhcmUgc29tZSBvdGhlciB3YXlzIHRvIGNsZWFuIHRoaXMgZGF0YSBpbiBSPyBIb3cgYWJvdXQgaW4gRXhjZWw/IAoKYGBge3J9Cm1lYW4oY2hlY2tpbmdzLG5hLnJtID0gVFJVRSkKc3VtKGNoZWNraW5ncyxuYS5ybSA9IFRSVUUpL2xlbmd0aChjaGVja2luZ3MpCmBgYAoKLS0tLS0tLS0tLS0tLQoKIyMjIFRhc2sgMwoKTm93LCB3ZSB3aWxsIGxvb2sgYXQgQ2hpY2FnbyB0YXhpIGRhdGEuIEdvIGFuZCBleHBsb3JlIHRoZSBpbnRlcmFjdGl2ZSBkYXNoYm9hcmQgYW5kIHJlYWQgdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLgoKQ2hpY2FnbyBUYXhpIERhc2hib2FyZDogW2h0dHBzOi8vZGF0YS5jaXR5b2ZjaGljYWdvLm9yZy9UcmFuc3BvcnRhdGlvbi9UYXhpLVRyaXBzLURhc2hib2FyZC9zcGN3LWJyYnFdKGh0dHBzOi8vZGF0YS5jaXR5b2ZjaGljYWdvLm9yZy9UcmFuc3BvcnRhdGlvbi9UYXhpLVRyaXBzLURhc2hib2FyZC9zcGN3LWJyYnEpCgpDaGljYWdvIFRheGkgRGF0YSBEZXNjcmlwdGlvbjoKW2h0dHA6Ly9kaWdpdGFsLmNpdHlvZmNoaWNhZ28ub3JnL2luZGV4LnBocC9jaGljYWdvLXRheGktZGF0YS1yZWxlYXNlZC9dKGh0dHA6Ly9kaWdpdGFsLmNpdHlvZmNoaWNhZ28ub3JnL2luZGV4LnBocC9jaGljYWdvLXRheGktZGF0YS1yZWxlYXNlZC8pIAoKT3BlbiBpbiBSU3R1ZGlvIHRoZSBjc3YgZmlsZSBpcyBsb2NhdGVkIGluIHRoZSBkYXRhIGZvbGRlciwgbm90ZSB0aGUgc2l6ZSBvZiB0aGUgZmlsZSwgdGhlIG51bWJlciBvZiBjb2x1bW5zIGFuZCBvZiByb3dzIGhlcmUuIFVzZSB0aGUgZnVuY3Rpb25zIGxlYXJuZWQgaW4gbGFiMDAgYW5kIGxhYjAxIHRvIGRlc2NyaWJlIHRoZSBkYXRhLCBpZGVudGlmeSB1bmlxdWUgZW50aXRpZXMsIGZpZWxkcyBhbmQgc3VtbWFyaXplLgoKRGVmaW5lIGEgcmVsYXRpb25hbCBidXNpbmVzcyBsb2dpYyBmb3IgdGhlIGNvbHVtbiBmaWVsZCAnVHJpcCBTZWNvbmRzJy4KClVzaW5nIFtodHRwczovL2VyZHBsdXMuY29tLyMvc3RhbmRhbG9uZV0oaHR0cHM6Ly9lcmRwbHVzLmNvbS8jL3N0YW5kYWxvbmUpIGRyYXcgYSBzdGFyIHNjaGVtYSB1c2luZyB0aGUgZm9sbG93aW5nIHRocmVlIHRhYmxlczoKCi0gQSBGYWN0IHRhYmxlIGZvciBUcmlwCi0gQSBEaW1lbnNpb24gdGFibGUgZm9yIENvbW11bml0eSBBcmVhCi0gQSBEaW1lbnNpb24gdGFibGUgZm9yIFJpZGVyCgo=