–Welcome to Lecture#8,Chapter V.

Let us start by finding our working directoty.

getwd()
[1] "C:/Users/antho/OneDrive/Documents/School/4.DataSecurity&Governance"
# make sure the packages for this chapter
# are installed, install if necessary
pkg <- c("ggplot2", "scales", "maptools",
              "sp", "maps", "grid", "car" )
new.pkg <- pkg[!(pkg %in% installed.packages())]
if (length(new.pkg)) {
  install.packages(new.pkg)  
}

Let us now make sure that the file zeroaccess is uploaded into your new project. Then let us define the variable za.

# read the CSV with headers
za <- read.csv("zeroaccess.csv", header=T,sep ="," )
#View(za)
head(za)

The file zeroaccess.csv was in my working directory folder so it uploaded We import the zeroaccess.csv using the read() function, notice the header is true(T) so the first row is considered headers. the values are separated by commas as should be in a comma separated file.

Notice above I used the head() function to view the fields, their data types, and weather they match.

# Load ggplot2 to create graphics
library(ggplot2)


# create a ggplot instance with zeroaccess data
gg <- ggplot(data=za, aes(x=long, y=lat)) 
# add the points, set transparency to 1/40th 
gg <- gg + geom_point(size=1, color="#000099", alpha=1/40) 
# add axes labels
gg <- gg + xlab("Longitude") + ylab("Latitude")
# simplify the theme for aesthetics
gg <- gg + theme_bw() 
# this may take a while, over 800,000 points plotted
print(gg)

Notice ggplot plots the points we provide it from our dataframe, and we can see that points cluster in the shape of what appears to be a map. That is because we are charting geographical cordinates latitude and longitude.

install.packages("mapproj")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/antho/AppData/Local/R/win-library/4.2’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.2/mapproj_1.2.8.zip'
Content type 'application/zip' length 59376 bytes (57 KB)
downloaded 57 KB
package ‘mapproj’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\antho\AppData\Local\Temp\RtmpIJe7Qo\downloaded_packages

We install the package mapproj above and load it to our notebook below.

library(mapproj)
Warning: package ‘mapproj’ was built under R version 4.2.1Loading required package: maps
Warning: package ‘maps’ was built under R version 4.2.1
# requires package : ggplot2
# requires object: za (5-1)
# the "maps" and "mapproj" packages are used by ggplot
# load map data of the world
world <- map_data("world")
#Remove Antarctica
world <- subset(world, world$region!="Antarctica")
# load world data into ggplot object
gg <- ggplot(data=world, aes(x=long, y=lat))
# trace along the lat/long coords by group (countries)
gg <- gg + geom_path(aes(group=group), colour="gray70")
# now project using the mercator projection
# try different projections with ?mapproject
gg <- gg + coord_map("mercator", xlim=c(-200, 200))
# load up the ZeroAccess points, overiding the default data set
gg <- gg + geom_point(data=za, aes(long, lat), 
                      colour="#000099", alpha=1/40, size=1)
# remove text, axes ticks, grid lines and do gray border on white
gg <- gg + theme(text=element_blank(), 
                 axis.ticks=element_blank(),
                 panel.grid=element_blank(),
                 panel.background=element_rect(color="gray50",
                                               fill="white"))
print(gg)

Notice by using the map_data() function from the “mapproj” package we are able to get the outline of the couninents and countries and not just the geographic lat/long points plotted on a scatter plot. Also notice we had to exclude some of the loaded map, antartica specifically which makes sense since we dont have records from there.

#Let us proceed to define the file county.dataset found on blackboard.

# read up census data per county
county.data <- read.csv("countydataset.csv", header=T,sep = ",")
View(county.data)

After importing the countydataset.csv file from my working directory folder and using the view() function we can see we have 3,072 records 7 columns on infections, ip address, ufo sighting, population and area

set.seed(1) 
# generate 200 random numbers around 10
input <- rnorm(200, mean=10)
summary(input)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  7.785   9.386   9.951  10.036  10.613  12.402 

Above we test the summary function on 200 random numbers that are meant to have a mean of ~10. Interesting we can ensure that that we get the same random numbers by setting the seed to a specific number in the seed function, this is helpful when trying test thing with the same randomization everytime so that the values dont change inbetween tests.

The summary function outputs the Min, Max, Median and Mean, Not to mention the 1st and 3rd quantile values. We cab see that the mean did stay around 10

# requires objects: input (5-16)
# generate output around a mean of 2 x input
output <- rnorm(200, mean=input*2)
# put into data frame to plot it
our.data <- data.frame(input, output)
gg <- ggplot(our.data, aes(input, output))
gg <- gg + geom_point()
gg <- gg + geom_smooth(method = "lm", se=F, color="red")
gg <- gg + theme_bw()
print(gg)

Make comments about both the syntax and the output of the task executed above. Is it possible to customize this graph to make it more explanatory? If so explain and run the code.

We use the variable we previously created with random number (input) to create a new variable also with 200 random numbers but this time their mean is twice that of the input. Then we use ggpplot again to graph these two points and a line using the the geo_smooth() function notice the “lm” method which creates the linear regression trend line.

We can add more information to the graph to convey more by adding a Title to it or naming the x and y variables. below i will give an example of renaming the chart.

print(gg + ggtitle("Random Input Vs Output-Mean Multiplied"))

Let us now run output vs input.

model <- lm(output ~ input)
summary(model)

Call:
lm(formula = output ~ input)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.93275 -0.54273 -0.02523  0.66833  2.58615 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.27224    0.77896   0.349    0.727    
input        1.97692    0.07729  25.577   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.013 on 198 degrees of freedom
Multiple R-squared:  0.7677,    Adjusted R-squared:  0.7665 
F-statistic: 654.2 on 1 and 198 DF,  p-value: < 2.2e-16

Is the input significant at a 5% significance level?1%?

Yes our p-value is 2.2e-16 which is almost 0 and less than 1% This is good. We also don’t have the worst r-squared at 76%

Let us now proceed to get the confidence interval for this model.

confint(model)
                2.5 %   97.5 %
(Intercept) -1.263895 1.808368
input        1.824502 2.129343

We can se that we have a 95% confidence level between the input coefficients 1.82 - 2.13

Using the county.data dataset, let us run a model of Infections vs ufo2010(Aliens Visits according to the UFO).

summary(lm(county.data$Infections ~ county.data$ufo2010, data= county.data))

Call:
lm(formula = county.data$Infections ~ county.data$ufo2010, data = county.data)

Residuals:
    Min      1Q  Median      3Q     Max 
-407.50  -70.35   -5.78   60.05 2736.39 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)         124.77740    2.38569  52.302  < 2e-16 ***
county.data$ufo2010   0.56899    0.07998   7.114  1.4e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 127.5 on 3070 degrees of freedom
Multiple R-squared:  0.01622,   Adjusted R-squared:  0.0159 
F-statistic: 50.61 on 1 and 3070 DF,  p-value: 1.398e-12

Given the output printed above, is ufo2010 significant at a 5% significance level?1%?

The p-value is significant since it is far below 1% sadly the r-squared value is very low. So ufo sighings do not predict infections well.

Let us now run a model of Infections vs every single quantitative variable that is included in the dataset.

View(county.data)
summary(lm(Infections ~ pop + income + ipaddr + ufo2010, 
           data=county.data))

Call:
lm(formula = Infections ~ pop + income + ipaddr + ufo2010, data = county.data)

Residuals:
    Min      1Q  Median      3Q     Max 
-342.94  -70.34   -5.40   58.85 2745.36 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  1.000e+02  9.426e+00  10.610  < 2e-16 ***
pop         -1.615e-05  1.543e-05  -1.047  0.29510    
income       5.670e-04  2.066e-04   2.745  0.00609 ** 
ipaddr      -9.865e-08  5.148e-07  -0.192  0.84803    
ufo2010      6.804e-01  1.691e-01   4.024 5.85e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 127.3 on 3067 degrees of freedom
Multiple R-squared:  0.01879,   Adjusted R-squared:  0.01751 
F-statistic: 14.69 on 4 and 3067 DF,  p-value: 6.915e-12

Interpret the output. How would you proceed from now on in this handout given the results obtained above.

We can see that the p value for for population and ip address is high so they are least probable for predicting a high accuracy linear model. It would be in our interest to remove them(“pop” & “ipaddr”) from our model.

install.packages("carData")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/antho/AppData/Local/R/win-library/4.2’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.2/carData_3.0-5.zip'
Content type 'application/zip' length 1821225 bytes (1.7 MB)
downloaded 1.7 MB
package ‘carData’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\antho\AppData\Local\Temp\RtmpIJe7Qo\downloaded_packages

We install the package carData above and load the car package to our notebook below.

library(car) # for the vif() function
Warning: package ‘car’ was built under R version 4.2.1Loading required package: carData
Warning: package ‘carData’ was built under R version 4.2.1

Let us just explore the variance inflation factor(VIF) of the model to see if there is a chance of high correlation between my predictors. I remind you that a strong correlation between two of my predictors will likely end up in heteroskedasticity, and therefore our model would not be accurate.

model <- lm(Infections ~ pop + income + ipaddr + ufo2010, 
            data=county.data)
sqrt(vif(model))
     pop   income   ipaddr  ufo2010 
2.165458 1.038467 1.046051 2.115512 

We get the variance inflation factors for our predictors variables.

Let us see if population affects the number of infections in this data set. Write the null and alternative hypothesis you would use to test this relationship.

The null hypothesis is we would see that populations changes, while infections wouldn’t The alternative hypothesis we would see is that populations changes, as well as infections

summary(lm(Infections ~ pop, data=county.data))

Call:
lm(formula = Infections ~ pop, data = county.data)

Residuals:
    Min      1Q  Median      3Q     Max 
-365.26  -70.35   -5.70   59.59 2724.00 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 1.250e+02  2.416e+00  51.755  < 2e-16 ***
pop         4.228e-05  7.147e-06   5.916 3.67e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 127.8 on 3070 degrees of freedom
Multiple R-squared:  0.01127,   Adjusted R-squared:  0.01095 
F-statistic:    35 on 1 and 3070 DF,  p-value: 3.668e-09

Interpret the results obtained above.

We can see from the output above that the p-value is less than 1% so we have statistical significance but since we have such a low r-squared this has nearly no provability of predicting for infections.

Now let us define the regression of Infections vs pop as pop.lm and predict the number of infections based on the variable population.

pop.lm <- lm(Infections ~ pop, data=county.data)
predict(pop.lm, data.frame(pop=6000000), interval="confidence")
       fit      lwr      upr
1 378.7109 295.9209 461.5009

Interpret the results obtained above.

Above we predict the population that will be infected of 6000000, of which the there is 95% confidence the value will fall between 296 and 462. The prediction of our fitted model is 379 which we wont value since the r-squared above showed our model was only accessing 1% of the populations variability.

LS0tDQp0aXRsZTogIkhhbmRvdXQ5X0NoNV9WaXNfUmVnIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KLS1XZWxjb21lIHRvIExlY3R1cmUjOCxDaGFwdGVyIFYuDQoNCkxldCB1cyBzdGFydCBieSBmaW5kaW5nIG91ciB3b3JraW5nIGRpcmVjdG90eS4NCg0KYGBge3J9DQpnZXR3ZCgpDQpgYGANCg0KDQpgYGB7cn0NCiMgbWFrZSBzdXJlIHRoZSBwYWNrYWdlcyBmb3IgdGhpcyBjaGFwdGVyDQojIGFyZSBpbnN0YWxsZWQsIGluc3RhbGwgaWYgbmVjZXNzYXJ5DQpwa2cgPC0gYygiZ2dwbG90MiIsICJzY2FsZXMiLCAibWFwdG9vbHMiLA0KICAgICAgICAgICAgICAic3AiLCAibWFwcyIsICJncmlkIiwgImNhciIgKQ0KbmV3LnBrZyA8LSBwa2dbIShwa2cgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSldDQppZiAobGVuZ3RoKG5ldy5wa2cpKSB7DQogIGluc3RhbGwucGFja2FnZXMobmV3LnBrZykgIA0KfQ0KYGBgDQoNCkxldCB1cyBub3cgbWFrZSBzdXJlIHRoYXQgdGhlIGZpbGUgemVyb2FjY2VzcyBpcyB1cGxvYWRlZCBpbnRvIHlvdXIgbmV3IHByb2plY3QuIFRoZW4gbGV0IHVzIGRlZmluZSB0aGUgdmFyaWFibGUgemEuDQoNCmBgYHtyfQ0KIyByZWFkIHRoZSBDU1Ygd2l0aCBoZWFkZXJzDQp6YSA8LSByZWFkLmNzdigiemVyb2FjY2Vzcy5jc3YiLCBoZWFkZXI9VCxzZXAgPSIsIiApDQojVmlldyh6YSkNCmhlYWQoemEpDQpgYGANCg0KVGhlIGZpbGUgemVyb2FjY2Vzcy5jc3Ygd2FzIGluIG15IHdvcmtpbmcgZGlyZWN0b3J5IGZvbGRlciBzbyBpdCB1cGxvYWRlZCANCldlIGltcG9ydCB0aGUgemVyb2FjY2Vzcy5jc3YgdXNpbmcgdGhlIHJlYWQoKSBmdW5jdGlvbiwgbm90aWNlIHRoZSBoZWFkZXIgaXMgdHJ1ZShUKSBzbyB0aGUgZmlyc3Qgcm93IGlzIGNvbnNpZGVyZWQgaGVhZGVycy4gdGhlIHZhbHVlcyBhcmUgc2VwYXJhdGVkIGJ5IGNvbW1hcyBhcyBzaG91bGQgYmUgaW4gYSBjb21tYSBzZXBhcmF0ZWQgZmlsZS4gIA0KDQpOb3RpY2UgYWJvdmUgSSB1c2VkIHRoZSBoZWFkKCkgZnVuY3Rpb24gdG8gdmlldyB0aGUgZmllbGRzLCB0aGVpciBkYXRhIHR5cGVzLCBhbmQgd2VhdGhlciB0aGV5IG1hdGNoLiANCg0KDQpgYGB7cn0NCiMgTG9hZCBnZ3Bsb3QyIHRvIGNyZWF0ZSBncmFwaGljcw0KbGlicmFyeShnZ3Bsb3QyKQ0KDQoNCiMgY3JlYXRlIGEgZ2dwbG90IGluc3RhbmNlIHdpdGggemVyb2FjY2VzcyBkYXRhDQpnZyA8LSBnZ3Bsb3QoZGF0YT16YSwgYWVzKHg9bG9uZywgeT1sYXQpKSANCiMgYWRkIHRoZSBwb2ludHMsIHNldCB0cmFuc3BhcmVuY3kgdG8gMS80MHRoIA0KZ2cgPC0gZ2cgKyBnZW9tX3BvaW50KHNpemU9MSwgY29sb3I9IiMwMDAwOTkiLCBhbHBoYT0xLzQwKSANCiMgYWRkIGF4ZXMgbGFiZWxzDQpnZyA8LSBnZyArIHhsYWIoIkxvbmdpdHVkZSIpICsgeWxhYigiTGF0aXR1ZGUiKQ0KIyBzaW1wbGlmeSB0aGUgdGhlbWUgZm9yIGFlc3RoZXRpY3MNCmdnIDwtIGdnICsgdGhlbWVfYncoKSANCiMgdGhpcyBtYXkgdGFrZSBhIHdoaWxlLCBvdmVyIDgwMCwwMDAgcG9pbnRzIHBsb3R0ZWQNCnByaW50KGdnKQ0KYGBgDQoNCk5vdGljZSBnZ3Bsb3QgcGxvdHMgdGhlIHBvaW50cyB3ZSBwcm92aWRlIGl0IGZyb20gb3VyIGRhdGFmcmFtZSwgYW5kIHdlIGNhbiBzZWUgdGhhdCBwb2ludHMgY2x1c3RlciBpbiB0aGUgc2hhcGUgb2Ygd2hhdCBhcHBlYXJzIHRvIGJlIGEgbWFwLiANClRoYXQgaXMgYmVjYXVzZSB3ZSBhcmUgY2hhcnRpbmcgZ2VvZ3JhcGhpY2FsIGNvcmRpbmF0ZXMgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS4gDQoNCmBgYHtyfQ0KDQojaW5zdGFsbC5wYWNrYWdlcygibWFwcHJvaiIpDQoNCmBgYA0KV2UgaW5zdGFsbCB0aGUgcGFja2FnZSBtYXBwcm9qIGFib3ZlIGFuZCBsb2FkIGl0IHRvIG91ciBub3RlYm9vayBiZWxvdy4gDQoNCmBgYHtyfQ0KbGlicmFyeShtYXBwcm9qKQ0KYGBgDQoNCg0KYGBge3J9DQojIHJlcXVpcmVzIHBhY2thZ2UgOiBnZ3Bsb3QyDQojIHJlcXVpcmVzIG9iamVjdDogemEgKDUtMSkNCiMgdGhlICJtYXBzIiBhbmQgIm1hcHByb2oiIHBhY2thZ2VzIGFyZSB1c2VkIGJ5IGdncGxvdA0KIyBsb2FkIG1hcCBkYXRhIG9mIHRoZSB3b3JsZA0Kd29ybGQgPC0gbWFwX2RhdGEoIndvcmxkIikNCiNSZW1vdmUgQW50YXJjdGljYQ0Kd29ybGQgPC0gc3Vic2V0KHdvcmxkLCB3b3JsZCRyZWdpb24hPSJBbnRhcmN0aWNhIikNCiMgbG9hZCB3b3JsZCBkYXRhIGludG8gZ2dwbG90IG9iamVjdA0KZ2cgPC0gZ2dwbG90KGRhdGE9d29ybGQsIGFlcyh4PWxvbmcsIHk9bGF0KSkNCiMgdHJhY2UgYWxvbmcgdGhlIGxhdC9sb25nIGNvb3JkcyBieSBncm91cCAoY291bnRyaWVzKQ0KZ2cgPC0gZ2cgKyBnZW9tX3BhdGgoYWVzKGdyb3VwPWdyb3VwKSwgY29sb3VyPSJncmF5NzAiKQ0KIyBub3cgcHJvamVjdCB1c2luZyB0aGUgbWVyY2F0b3IgcHJvamVjdGlvbg0KIyB0cnkgZGlmZmVyZW50IHByb2plY3Rpb25zIHdpdGggP21hcHByb2plY3QNCmdnIDwtIGdnICsgY29vcmRfbWFwKCJtZXJjYXRvciIsIHhsaW09YygtMjAwLCAyMDApKQ0KIyBsb2FkIHVwIHRoZSBaZXJvQWNjZXNzIHBvaW50cywgb3ZlcmlkaW5nIHRoZSBkZWZhdWx0IGRhdGEgc2V0DQpnZyA8LSBnZyArIGdlb21fcG9pbnQoZGF0YT16YSwgYWVzKGxvbmcsIGxhdCksIA0KICAgICAgICAgICAgICAgICAgICAgIGNvbG91cj0iIzAwMDA5OSIsIGFscGhhPTEvNDAsIHNpemU9MSkNCiMgcmVtb3ZlIHRleHQsIGF4ZXMgdGlja3MsIGdyaWQgbGluZXMgYW5kIGRvIGdyYXkgYm9yZGVyIG9uIHdoaXRlDQpnZyA8LSBnZyArIHRoZW1lKHRleHQ9ZWxlbWVudF9ibGFuaygpLCANCiAgICAgICAgICAgICAgICAgYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfcmVjdChjb2xvcj0iZ3JheTUwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD0id2hpdGUiKSkNCnByaW50KGdnKQ0KDQpgYGANCg0KTm90aWNlIGJ5IHVzaW5nIHRoZSBtYXBfZGF0YSgpIGZ1bmN0aW9uIGZyb20gdGhlICJtYXBwcm9qIiBwYWNrYWdlIHdlIGFyZSBhYmxlIHRvIGdldCB0aGUgb3V0bGluZSBvZiB0aGUgY291bmluZW50cyBhbmQgY291bnRyaWVzIGFuZCBub3QganVzdCB0aGUgZ2VvZ3JhcGhpYyBsYXQvbG9uZyBwb2ludHMgcGxvdHRlZCBvbiBhIHNjYXR0ZXIgcGxvdC4NCkFsc28gbm90aWNlIHdlIGhhZCB0byBleGNsdWRlIHNvbWUgb2YgdGhlIGxvYWRlZCBtYXAsIGFudGFydGljYSBzcGVjaWZpY2FsbHkgd2hpY2ggbWFrZXMgc2Vuc2Ugc2luY2Ugd2UgZG9udCBoYXZlIHJlY29yZHMgZnJvbSB0aGVyZS4gDQoNCiNMZXQgdXMgcHJvY2VlZCB0byBkZWZpbmUgdGhlIGZpbGUgY291bnR5LmRhdGFzZXQgZm91bmQgb24gYmxhY2tib2FyZC4NCg0KDQpgYGB7cn0NCiMgcmVhZCB1cCBjZW5zdXMgZGF0YSBwZXIgY291bnR5DQpjb3VudHkuZGF0YSA8LSByZWFkLmNzdigiY291bnR5ZGF0YXNldC5jc3YiLCBoZWFkZXI9VCxzZXAgPSAiLCIpDQoNCmBgYA0KDQpgYGB7cn0NClZpZXcoY291bnR5LmRhdGEpDQpgYGANCg0KQWZ0ZXIgaW1wb3J0aW5nIHRoZSBjb3VudHlkYXRhc2V0LmNzdiBmaWxlIGZyb20gbXkgd29ya2luZyBkaXJlY3RvcnkgZm9sZGVyIGFuZCB1c2luZyB0aGUgdmlldygpIGZ1bmN0aW9uIHdlIGNhbiBzZWUgd2UgaGF2ZSAzLDA3MiByZWNvcmRzIDcgY29sdW1ucyBvbiBpbmZlY3Rpb25zLCBpcCBhZGRyZXNzLCB1Zm8gc2lnaHRpbmcsIHBvcHVsYXRpb24gYW5kIGFyZWENCg0KDQpgYGB7cn0NCnNldC5zZWVkKDEpICMgdGhpcyB3aWxsIGVuc3VyZSB0aGF0IHdlIGdldCB0aGUgc2FtZSByYW5kb20gbnVtYmVycw0KDQojIGdlbmVyYXRlIDIwMCByYW5kb20gbnVtYmVycyBhcm91bmQgMTANCmlucHV0IDwtIHJub3JtKDIwMCwgbWVhbj0xMCkNCnN1bW1hcnkoaW5wdXQpDQpgYGANCkFib3ZlIHdlIHRlc3QgdGhlIHN1bW1hcnkgZnVuY3Rpb24gb24gMjAwIHJhbmRvbSBudW1iZXJzIHRoYXQgYXJlIG1lYW50IHRvIGhhdmUgYSBtZWFuIG9mIH4xMC4gSW50ZXJlc3Rpbmcgd2UgY2FuIGVuc3VyZSB0aGF0ICB0aGF0IHdlIGdldCB0aGUgc2FtZSByYW5kb20gbnVtYmVycyBieSBzZXR0aW5nIHRoZSBzZWVkIHRvIGEgc3BlY2lmaWMgbnVtYmVyIGluIHRoZSBzZWVkIGZ1bmN0aW9uLCB0aGlzIGlzIGhlbHBmdWwgd2hlbiB0cnlpbmcgdGVzdCB0aGluZyB3aXRoIHRoZSBzYW1lIHJhbmRvbWl6YXRpb24gZXZlcnl0aW1lIHNvIHRoYXQgdGhlIHZhbHVlcyBkb250IGNoYW5nZSBpbmJldHdlZW4gdGVzdHMuICANCg0KVGhlIHN1bW1hcnkgZnVuY3Rpb24gb3V0cHV0cyB0aGUgTWluLCBNYXgsIE1lZGlhbiBhbmQgTWVhbiwgTm90IHRvIG1lbnRpb24gdGhlIDFzdCBhbmQgM3JkIHF1YW50aWxlIHZhbHVlcy4gV2UgY2FiIHNlZSB0aGF0IHRoZSBtZWFuIGRpZCBzdGF5IGFyb3VuZCAxMA0KDQpgYGB7cn0NCiMgcmVxdWlyZXMgb2JqZWN0czogaW5wdXQgKDUtMTYpDQojIGdlbmVyYXRlIG91dHB1dCBhcm91bmQgYSBtZWFuIG9mIDIgeCBpbnB1dA0Kb3V0cHV0IDwtIHJub3JtKDIwMCwgbWVhbj1pbnB1dCoyKQ0KIyBwdXQgaW50byBkYXRhIGZyYW1lIHRvIHBsb3QgaXQNCm91ci5kYXRhIDwtIGRhdGEuZnJhbWUoaW5wdXQsIG91dHB1dCkNCmdnIDwtIGdncGxvdChvdXIuZGF0YSwgYWVzKGlucHV0LCBvdXRwdXQpKQ0KZ2cgPC0gZ2cgKyBnZW9tX3BvaW50KCkNCmdnIDwtIGdnICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2U9RiwgY29sb3I9InJlZCIpDQpnZyA8LSBnZyArIHRoZW1lX2J3KCkNCnByaW50KGdnKQ0KYGBgDQoNCg0KTWFrZSBjb21tZW50cyBhYm91dCBib3RoIHRoZSBzeW50YXggYW5kIHRoZSBvdXRwdXQgb2YgdGhlIHRhc2sgZXhlY3V0ZWQgYWJvdmUuIElzIGl0IHBvc3NpYmxlIHRvIGN1c3RvbWl6ZSB0aGlzIGdyYXBoIHRvIG1ha2UgaXQgbW9yZSBleHBsYW5hdG9yeT8gSWYgc28gZXhwbGFpbiBhbmQgcnVuIHRoZSBjb2RlLg0KDQoNCldlIHVzZSB0aGUgdmFyaWFibGUgd2UgcHJldmlvdXNseSBjcmVhdGVkIHdpdGggcmFuZG9tIG51bWJlciAoaW5wdXQpIHRvIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSBhbHNvIHdpdGggMjAwIHJhbmRvbSBudW1iZXJzIGJ1dCB0aGlzIHRpbWUgdGhlaXIgbWVhbiBpcyB0d2ljZSB0aGF0IG9mIHRoZSBpbnB1dC4gVGhlbiB3ZSB1c2UgZ2dwcGxvdCBhZ2FpbiB0byBncmFwaCB0aGVzZSB0d28gcG9pbnRzIGFuZCBhIGxpbmUgdXNpbmcgdGhlIHRoZSBnZW9fc21vb3RoKCkgZnVuY3Rpb24gbm90aWNlIHRoZSAibG0iIG1ldGhvZCB3aGljaCBjcmVhdGVzIHRoZSBsaW5lYXIgcmVncmVzc2lvbiB0cmVuZCBsaW5lLg0KDQpXZSBjYW4gYWRkIG1vcmUgaW5mb3JtYXRpb24gdG8gdGhlIGdyYXBoIHRvIGNvbnZleSBtb3JlIGJ5IGFkZGluZyBhIFRpdGxlIHRvIGl0IG9yIG5hbWluZyB0aGUgeCBhbmQgeSB2YXJpYWJsZXMuDQpiZWxvdyBpIHdpbGwgZ2l2ZSBhbiBleGFtcGxlIG9mIHJlbmFtaW5nIHRoZSBjaGFydC4gDQoNCg0KYGBge3J9DQpwcmludChnZyArIGdndGl0bGUoIlJhbmRvbSBJbnB1dCBWcyBPdXRwdXQtTWVhbiBNdWx0aXBsaWVkIikpDQoNCmBgYA0KDQpMZXQgdXMgbm93IHJ1biAqKm91dHB1dCoqIHZzICoqaW5wdXQqKi4NCg0KYGBge3J9DQptb2RlbCA8LSBsbShvdXRwdXQgfiBpbnB1dCkNCnN1bW1hcnkobW9kZWwpDQpgYGANCg0KSXMgdGhlIGlucHV0IHNpZ25pZmljYW50IGF0IGEgNSUgc2lnbmlmaWNhbmNlIGxldmVsPzElPw0KDQpZZXMgb3VyIHAtdmFsdWUgaXMgMi4yZS0xNiB3aGljaCBpcyBhbG1vc3QgMCBhbmQgbGVzcyB0aGFuIDElIFRoaXMgaXMgZ29vZC4gV2UgYWxzbyBkb24ndCBoYXZlIHRoZSB3b3JzdCByLXNxdWFyZWQgYXQgNzYlDQoNCkxldCB1cyBub3cgcHJvY2VlZCB0byBnZXQgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoaXMgbW9kZWwuDQoNCmBgYHtyfQ0KY29uZmludChtb2RlbCkNCmBgYA0KDQpXZSBjYW4gc2UgdGhhdCB3ZSBoYXZlIGEgOTUlIGNvbmZpZGVuY2UgbGV2ZWwgYmV0d2VlbiB0aGUgaW5wdXQgY29lZmZpY2llbnRzIDEuODIgLSAyLjEzDQoNCg0KVXNpbmcgdGhlIGNvdW50eS5kYXRhIGRhdGFzZXQsIGxldCB1cyBydW4gYSBtb2RlbCBvZiBJbmZlY3Rpb25zIHZzIHVmbzIwMTAoQWxpZW5zIFZpc2l0cyBhY2NvcmRpbmcgdG8gdGhlIFVGTykuDQoNCmBgYHtyfQ0Kc3VtbWFyeShsbShjb3VudHkuZGF0YSRJbmZlY3Rpb25zIH4gY291bnR5LmRhdGEkdWZvMjAxMCwgZGF0YT0gY291bnR5LmRhdGEpKQ0KYGBgDQpHaXZlbiB0aGUgb3V0cHV0IHByaW50ZWQgYWJvdmUsIGlzIHVmbzIwMTAgc2lnbmlmaWNhbnQgYXQgYSA1JSBzaWduaWZpY2FuY2UgbGV2ZWw/MSU/DQoNClRoZSBwLXZhbHVlIGlzIHNpZ25pZmljYW50IHNpbmNlIGl0IGlzIGZhciBiZWxvdyAxJSBzYWRseSB0aGUgci1zcXVhcmVkIHZhbHVlIGlzIHZlcnkgbG93Lg0KU28gdWZvIHNpZ2hpbmdzIGRvIG5vdCBwcmVkaWN0IGluZmVjdGlvbnMgd2VsbC4gDQoNCg0KTGV0IHVzIG5vdyBydW4gYSBtb2RlbCBvZiBJbmZlY3Rpb25zIHZzIGV2ZXJ5IHNpbmdsZSBxdWFudGl0YXRpdmUgdmFyaWFibGUgdGhhdCBpcyBpbmNsdWRlZCBpbiB0aGUgZGF0YXNldC4NCg0KYGBge3J9DQpWaWV3KGNvdW50eS5kYXRhKQ0KYGBgDQoNCg0KYGBge3J9DQpzdW1tYXJ5KGxtKEluZmVjdGlvbnMgfiBwb3AgKyBpbmNvbWUgKyBpcGFkZHIgKyB1Zm8yMDEwLCANCiAgICAgICAgICAgZGF0YT1jb3VudHkuZGF0YSkpDQpgYGANCg0KDQpJbnRlcnByZXQgdGhlIG91dHB1dC4gSG93IHdvdWxkIHlvdSBwcm9jZWVkIGZyb20gbm93IG9uIGluIHRoaXMgaGFuZG91dCBnaXZlbiB0aGUgcmVzdWx0cyBvYnRhaW5lZCBhYm92ZS4gDQoNCldlIGNhbiBzZWUgdGhhdCB0aGUgcCB2YWx1ZSBmb3IgZm9yIHBvcHVsYXRpb24gYW5kIGlwIGFkZHJlc3MgaXMgaGlnaCBzbyB0aGV5IGFyZSBsZWFzdCBwcm9iYWJsZSBmb3IgcHJlZGljdGluZyBhIGhpZ2ggYWNjdXJhY3kgbGluZWFyIG1vZGVsLiBJdCB3b3VsZCBiZSBpbiBvdXIgaW50ZXJlc3QgdG8gcmVtb3ZlIHRoZW0oInBvcCIgJiAiaXBhZGRyIikgZnJvbSBvdXIgbW9kZWwuIA0KDQoNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoImNhckRhdGEiKQ0KYGBgDQpXZSBpbnN0YWxsIHRoZSBwYWNrYWdlIGNhckRhdGEgYWJvdmUgYW5kIGxvYWQgdGhlIGNhciBwYWNrYWdlIHRvIG91ciBub3RlYm9vayBiZWxvdy4gDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGNhcikgIyBmb3IgdGhlIHZpZigpIGZ1bmN0aW9uDQpgYGANCg0KTGV0IHVzIGp1c3QgZXhwbG9yZSB0aGUgdmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvcihWSUYpIG9mIHRoZSBtb2RlbCB0byBzZWUgaWYgdGhlcmUgaXMgYSBjaGFuY2Ugb2YgaGlnaCBjb3JyZWxhdGlvbiBiZXR3ZWVuIG15IHByZWRpY3RvcnMuIEkgcmVtaW5kIHlvdSB0aGF0IGEgc3Ryb25nIGNvcnJlbGF0aW9uIGJldHdlZW4gdHdvIG9mIG15IHByZWRpY3RvcnMgd2lsbCBsaWtlbHkgZW5kIHVwIGluIGhldGVyb3NrZWRhc3RpY2l0eSwgYW5kIHRoZXJlZm9yZSBvdXIgbW9kZWwgd291bGQgbm90IGJlIGFjY3VyYXRlLiAgDQoNCmBgYHtyfQ0KbW9kZWwgPC0gbG0oSW5mZWN0aW9ucyB+IHBvcCArIGluY29tZSArIGlwYWRkciArIHVmbzIwMTAsIA0KICAgICAgICAgICAgZGF0YT1jb3VudHkuZGF0YSkNCnNxcnQodmlmKG1vZGVsKSkNCmBgYA0KV2UgZ2V0IHRoZSB2YXJpYW5jZSBpbmZsYXRpb24gZmFjdG9ycyBmb3Igb3VyIHByZWRpY3RvcnMgdmFyaWFibGVzLg0KDQpMZXQgdXMgc2VlIGlmIHBvcHVsYXRpb24gYWZmZWN0cyB0aGUgbnVtYmVyIG9mIGluZmVjdGlvbnMgaW4gdGhpcyBkYXRhIHNldC4gV3JpdGUgdGhlIG51bGwgYW5kIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgeW91IHdvdWxkIHVzZSB0byB0ZXN0IHRoaXMgcmVsYXRpb25zaGlwLiANCg0KVGhlIG51bGwgaHlwb3RoZXNpcyBpcyB3ZSB3b3VsZCBzZWUgdGhhdCBwb3B1bGF0aW9ucyBjaGFuZ2VzLCB3aGlsZSBpbmZlY3Rpb25zIHdvdWxkbid0IA0KVGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgd2Ugd291bGQgc2VlIGlzIHRoYXQgcG9wdWxhdGlvbnMgY2hhbmdlcywgYXMgd2VsbCBhcyBpbmZlY3Rpb25zICANCg0KDQpgYGB7cn0NCnN1bW1hcnkobG0oSW5mZWN0aW9ucyB+IHBvcCwgZGF0YT1jb3VudHkuZGF0YSkpDQpgYGANCg0KSW50ZXJwcmV0IHRoZSByZXN1bHRzIG9idGFpbmVkIGFib3ZlLiANCg0KV2UgY2FuIHNlZSBmcm9tIHRoZSBvdXRwdXQgYWJvdmUgdGhhdCB0aGUgcC12YWx1ZSBpcyBsZXNzIHRoYW4gMSUgc28gd2UgaGF2ZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UgYnV0IHNpbmNlIHdlIGhhdmUgc3VjaCBhIGxvdyByLXNxdWFyZWQgdGhpcyBoYXMgbmVhcmx5IG5vIHByb3ZhYmlsaXR5IG9mIHByZWRpY3RpbmcgZm9yIGluZmVjdGlvbnMuIA0KDQpOb3cgbGV0IHVzIGRlZmluZSB0aGUgcmVncmVzc2lvbiBvZiBJbmZlY3Rpb25zIHZzIHBvcCBhcyBwb3AubG0gYW5kIHByZWRpY3QgdGhlIG51bWJlciBvZiBpbmZlY3Rpb25zIGJhc2VkIG9uIHRoZSB2YXJpYWJsZSBwb3B1bGF0aW9uLiANCg0KDQpgYGB7cn0NCnBvcC5sbSA8LSBsbShJbmZlY3Rpb25zIH4gcG9wLCBkYXRhPWNvdW50eS5kYXRhKQ0KcHJlZGljdChwb3AubG0sIGRhdGEuZnJhbWUocG9wPTYwMDAwMDApLCBpbnRlcnZhbD0iY29uZmlkZW5jZSIpDQpgYGANCg0KDQpJbnRlcnByZXQgdGhlIHJlc3VsdHMgb2J0YWluZWQgYWJvdmUuDQoNCkFib3ZlIHdlIHByZWRpY3QgdGhlIHBvcHVsYXRpb24gdGhhdCB3aWxsIGJlIGluZmVjdGVkIG9mIDYwMDAwMDAsIG9mIHdoaWNoIHRoZSB0aGVyZSBpcyA5NSUgY29uZmlkZW5jZSB0aGUgdmFsdWUgd2lsbCBmYWxsIGJldHdlZW4gMjk2IGFuZCA0NjIuIFRoZSBwcmVkaWN0aW9uIG9mIG91ciBmaXR0ZWQgbW9kZWwgaXMgMzc5IHdoaWNoIHdlIHdvbnQgdmFsdWUgc2luY2UgdGhlIHItc3F1YXJlZCBhYm92ZSBzaG93ZWQgb3VyIG1vZGVsIHdhcyBvbmx5IGFjY2Vzc2luZyAxJSBvZiB0aGUgcG9wdWxhdGlvbnMgdmFyaWFiaWxpdHkuIA0K