Welcome to handout#5, let start by getting our working directory.

getwd()
[1] "E:/School/Summer 2021/Security and Data Governance/Handout/Handout 5"
pkg <- c("ggplot2","lattice")
new.pkg <-pkg[!(pkg %in% installed.packages())]
if (length(new.pkg)) {
  install.packages(new.pkg)
}
library(ggplot2)
library(lattice)
av <-read.csv("reputation.data",sep = "#",header = FALSE)
View(av)
#we just uploaded reputation data into our directory by giving it the name av each of our data points was separated by "#"
colnames(av) <-c("IP","reliability","Risk","Type",
                 "Country","Locale","Coords","x")
# Here we are naming the columns in the table av we uploaded earlier
av
str(av)#getting an overview of the data frame
'data.frame':   258626 obs. of  8 variables:
 $ IP         : chr  "222.76.212.189" "222.76.212.185" "222.76.212.186" "5.34.246.67" ...
 $ reliability: int  4 4 4 6 4 4 4 4 4 6 ...
 $ Risk       : int  2 2 2 3 5 2 2 2 2 3 ...
 $ Type       : chr  "Scanning Host" "Scanning Host" "Scanning Host" "Spamming" ...
 $ Country    : chr  "CN" "CN" "CN" "US" ...
 $ Locale     : chr  "Xiamen" "Xiamen" "Xiamen" "" ...
 $ Coords     : chr  "24.4797992706,118.08190155" "24.4797992706,118.08190155" "24.4797992706,118.08190155" "38.0,-97.0" ...
 $ x          : chr  "11" "11" "11" "12" ...
# we have our reputation.data we named it av in our file and then we named the columns so instead of having unnamed columns we have nice organized columns.
# Changes Country from a char to factor to be able to use in math functions. A factor behave a little bit like integer vector because R encodes the levels as integers.
#Factors are the data objects which are used to categorize the data and store it as levels. They can store both strings and integers. They are useful in the columns which have a limited number of unique values. Like "Male, "Female" and True, False etc. They are useful in data analysis for statistical modeling.
# this was need to correct errors we were having when running the ggplots and computations were getting errors.
av$Country<-as.factor(av$Country)
head(av)
# head av gives you an actual view of the header of the table with a more organized view , while str gives you a more messy but complete information of the table such as how many  levels per factor
summary(av$reliability)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   2.000   2.798   4.000  10.000 
summary(av$Risk)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   2.000   2.000   2.221   2.000   7.000 
table(av$reliability)

     1      2      3      4      5      6      7      8      9     10 
  5612 149117  10892  87040      7   4758    297     21    686    196 
table(av$Risk)

     1      2      3      4      5      6      7 
    39 213852  33719   9588   1328     90     10 
# here we got a summary of both reliability and of risk with numbers such as min,mean,median,max
#we also go the values in the table 
summary(av$Type,maxsum=10)
   Length     Class      Mode 
   258626 character character 
summary(av$Country, maxsum=40)
     CN      US      TR              DE      NL      RU      GB      IN      FR      TW      BR      UA      RO      KR      CA      AR 
  68583   50387   13958   10055    9953    7931    6346    6293    5480    5449    4399    3811    3443    3274    3101    3051    3046 
     MX      TH      IT      HK      ES      CL      AE      JP      HU      PL      VE      EG      ID      RS      PK      VN      LV 
   3039    2572    2448    2361    1929    1896    1827    1811    1636    1610    1589    1452    1378    1323    1309    1203    1056 
     NO      CZ      BG      SG      IR (Other) 
    958     928     871     868     866   15136 
# we are getting the summary of both these categories with max level of 10 and 40
library(ggplot2)
country.top20 <- names(summary(av$Country))[1:20]
# we just created a new column with the top 20 countries and we called it country.top20
country.top20
 [1] "CN" "US" "TR" ""   "DE" "NL" "RU" "GB" "IN" "FR" "TW" "BR" "UA" "RO" "KR" "CA" "AR" "MX" "TH" "IT"
gg <-ggplot(data=subset(av,Country %in% country.top20),
#gg <-ggplot(data=subset(av),
aes(x=reorder(Country,Country, length)))
gg <- gg + geom_bar(fill="#000099")



gg <- gg + labs(title="Country Counts", x="Country", y="Count")
# then we are going to rotate the chart to make it easier to read
gg <- gg + coord_flip()



print(gg)

# We are going to remove garbage from the chart we created in the last step
gg <- gg + theme(panel.grid=element_blank(),
                 panel.background=element_blank())
print(gg)

# here we have a chart with the top 20 countries by count from highest to lowest count we named out y value and our x value we gave the chart a title

I was getting the following err:

Continuous limits supplied to discrete scale.

Did you mean limits = factor(...) or scale_*_continuous()?

Changed the line gg <- gg + scale_x_discrete(limits=seq(max(av\(Risk))) to # gg <- gg + scale_x_discrete(limits=factor(max(av\)Risk)))

# now we are going to create a bar graph of counts by risk
gg <- ggplot(data=av, aes(x=Risk))
gg <- gg + geom_bar(fill="#000099")
# force a X scale to be just the limits of the data and to be discrete vs continuous

#gg <- gg + scale_x_discrete(limits=seq(max(av$Risk)))
gg <- gg + scale_x_discrete(limits=factor(max(av$Risk)))
gg <- gg + labs(title= "'Risk' Counts", x="Risk Score", y="Count")
# remove garbage from chart to get more precise info
gg <- gg + theme(panel.grid=element_blank(),
                 panel.background=element_blank())
print(gg)

# We jsut crated a bar chart called risk counts we named our x and y axis we gave the graph a title and we got all of our data from our av table and the risk column

I was getting the following err:

Continuous limits supplied to discrete scale.

Did you mean limits = factor(...) or scale_*_continuous()?

I Change the line gg <- gg + scale_x_discrete(limits=seq(max(av\(reliability))) to # gg <- gg + scale_x_discrete(limits=factor(max(av\)reliability)))

this solved the error.

# In this part of the handout we are going to create yet another bar graph called bar graph of counts by reliability
gg <- ggplot(data=av, aes(x=reliability))
gg <- gg + geom_bar(fill="#000099")
# force a X scale to be just the limits of the data and to be discrete vs continuous
gg <- gg + scale_x_discrete(limits=factor(max(av$reliability)))
#gg <- gg + scale_x_discrete(limits=seq(max(av$reliability)))
gg <- gg + labs(title= "'Reliability' Counts", x="Reliability Score", y="Count")
# remove garbage from chart to get more precise info
gg <- gg + theme(panel.grid=element_blank(),
                 panel.background=element_blank())
print(gg)

# we created another bar graph called reliability counts with our y and x axis named and we got the data from our av table and our reliability column
country_top <- summary(av$Country, maxsum=10)
# now we are converting into a percentage by dividing it by the number of rows in av
country.perc10 <- country_top/nrow(av)

print(country.perc10)
        CN         US         TR                    DE         NL         RU         GB         IN    (Other) 
0.26518215 0.19482573 0.05396983 0.03887854 0.03848414 0.03066590 0.02453736 0.02433243 0.02118890 0.30793501 
# here we got the top 10 countries and we converted the value they sustained into a percentage by dividing by the number of rows in av and they we are displaying the top in percentage
#we are computing a contingency table for risk/reliability factors which is going to produce a matrix
#of counts of rows that have attributes at each (x,y) location
rr.tab <- xtabs(~Risk+reliability, data=av)
print(ftable(rr.tab)) #print the table 
     reliability      1      2      3      4      5      6      7      8      9     10
Risk                                                                                  
1                     0      0     16      7      0      8      8      0      0      0
2                   804 149114   3670  57653      4   2084     85     11    345     82
3                  2225      3   6668  22168      2   2151    156      7    260     79
4                  2129      0    481   6447      0    404     43      2     58     24
5                   432      0     55    700      1    103      5      1     20     11
6                    19      0      2     60      0      8      0      0      1      0
7                     3      0      0      5      0      0      0      0      2      0
# we just created another table that shows us what risk and reliability have in common
#graphical view
#we need to use a function called levelplot from the lattice package we downloaded at the begining of the handout
# and we are going to cast the table into a data frame
rr.df = data.frame(table(av$Risk, av$reliability))
# now we are going to name our columns
colnames(rr.df) <- c("Risk", "Reliability", "Freq")
levelplot(Freq~Reliability*Risk, data=rr.df, main="Risk ~ Reliability",
          ylab = "Reliability", xlab = "Risk", shrink = c (0.5,1),
          col.regions = colorRampPalette(c("#F5F5F5", "#01665E"))(20))

# we just created a levelplot wich we got from the lattice package we donwloaded and we used our Risk and reliability columns to see which is the perfect spot between both of those categories
# We are going to generate random samples for risk and Reliability and re-run xtab
#starting PRNG from reproducible point
set.seed(1492) # as it leads to discovery
#generate 260,00 random samples
rel=sample(1:7, 260000, replace=T)
rsk=sample(1:10,260000, replace=T)
#Cast the table into a data frame
tmp.df = data.frame(table(factor(rsk), factor(rel)))
# we are going to give the columns names
colnames(rr.df) <- c("Risk", "Reliability", "Freq")
levelplot(Freq~Reliability*Risk, data=rr.df, main="Risk ~ Reliability",
          ylab = "Reliability", xlab = "Risk", shrink = c (0.5,1),
          col.regions = colorRampPalette(c("#F5F5F5", "#01665E"))(20))

# We are going to create a new variable called "simpletype & replacing multiple categories with label of"multiples"
av$simpletype <- as.character(av$Type)
#Group all nodes with multiple categories into a new category
av$simpletype[grep(';', av$simpletype)] <- "Multiples"
#Turn it into a factor once again
av$simpletype <- factor(av$simpletype)
rrt.df = data.frame(table(av$Risk, av$reliability, av$simpletype))
colnames(rrt.df) <- c("Risk", "Reliability", "simpletype","Freq")
levelplot(Freq ~ Reliability*Risk|simpletype, data=rrt.df,
          main="Risk ~ Reliability | Type",ylab = "Risk",
          xlab = "Reliability", shrink = c(0.5,1),
          col.regions = colorRampPalette(c("#F5F5F5","#01665E"))(20))


# we jsut created a levelplotjsut like the one before but we added an new column called simpletype which shows us the types and where we see more risk a reliability per type
# we are going to go fro the same levelplot but we are filtering out scanning host which was the more popular one in the earlier levelplot
rrt.df <- subset(rrt.df, simpletype != "Scanning Host")
levelplot(Freq ~ Reliability*Risk|simpletype, data =rrt.df,
          main="Risk ~ Reliability | Type",ylab = "Risk",
          xlab = "Reliability", shrink = c(0.5, 1),
          col.regions = colorRampPalette(c("#F5F5F5","#01665E"))(20))

# here we have the same level plot we had in the earlier example but without scanning host as a category and we see the graph a lot more distributed than before
rrt.df = subset(rrt.df,
                !(simpletype %in% c("Malware distribution",
                                    "Malware Domain")))
sprintf("Count: %d; Percent: %2.1f%%",
        sum(rrt.df$Freq),
        100*sum(rrt.df$Freq)/nrow(av))
[1] "Count: 15171; Percent: 5.9%"
levelplot(Freq ~ Reliability*Risk|simpletype, data =rrt.df,
          main="Risk ~ Reliability | Type",ylab = "Risk",
          xlab = "Reliability", shrink = c(0.5, 1),
          col.regions = colorRampPalette(c("#F5F5F5","#01665E"))(20))

# here we created another levelplot but with less columns in this case we took off malware distribution and malware domain and yet again we see the numbers better distributed across the graph
LS0tDQp0aXRsZTogIkhhbmRvdXQjNSBSIE5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KV2VsY29tZSB0byBoYW5kb3V0IzUsIGxldCBzdGFydCBieSBnZXR0aW5nIG91ciB3b3JraW5nIGRpcmVjdG9yeS4NCg0KYGBge3J9DQpnZXR3ZCgpDQpgYGANCg0KDQpgYGB7cn0NCnBrZyA8LSBjKCJnZ3Bsb3QyIiwibGF0dGljZSIpDQpuZXcucGtnIDwtcGtnWyEocGtnICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpXQ0KaWYgKGxlbmd0aChuZXcucGtnKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKG5ldy5wa2cpDQp9DQpgYGANCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShsYXR0aWNlKQ0KYGBgDQoNCg0KYGBge3J9DQphdiA8LXJlYWQuY3N2KCJyZXB1dGF0aW9uLmRhdGEiLHNlcCA9ICIjIixoZWFkZXIgPSBGQUxTRSkNClZpZXcoYXYpDQojd2UganVzdCB1cGxvYWRlZCByZXB1dGF0aW9uIGRhdGEgaW50byBvdXIgZGlyZWN0b3J5IGJ5IGdpdmluZyBpdCB0aGUgbmFtZSBhdiBlYWNoIG9mIG91ciBkYXRhIHBvaW50cyB3YXMgc2VwYXJhdGVkIGJ5ICIjIg0KYGBgDQoNCg0KDQpgYGB7cn0NCmNvbG5hbWVzKGF2KSA8LWMoIklQIiwicmVsaWFiaWxpdHkiLCJSaXNrIiwiVHlwZSIsDQogICAgICAgICAgICAgICAgICJDb3VudHJ5IiwiTG9jYWxlIiwiQ29vcmRzIiwieCIpDQojIEhlcmUgd2UgYXJlIG5hbWluZyB0aGUgY29sdW1ucyBpbiB0aGUgdGFibGUgYXYgd2UgdXBsb2FkZWQgZWFybGllcg0KYXYNCmBgYA0KDQoNCg0KYGBge3J9DQpzdHIoYXYpI2dldHRpbmcgYW4gb3ZlcnZpZXcgb2YgdGhlIGRhdGEgZnJhbWUNCiMgd2UgaGF2ZSBvdXIgcmVwdXRhdGlvbi5kYXRhIHdlIG5hbWVkIGl0IGF2IGluIG91ciBmaWxlIGFuZCB0aGVuIHdlIG5hbWVkIHRoZSBjb2x1bW5zIHNvIGluc3RlYWQgb2YgaGF2aW5nIHVubmFtZWQgY29sdW1ucyB3ZSBoYXZlIG5pY2Ugb3JnYW5pemVkIGNvbHVtbnMuDQpgYGANCg0KYGBge3J9DQojIENoYW5nZXMgQ291bnRyeSBmcm9tIGEgY2hhciB0byBmYWN0b3IgdG8gYmUgYWJsZSB0byB1c2UgaW4gbWF0aCBmdW5jdGlvbnMuIEEgZmFjdG9yIGJlaGF2ZSBhIGxpdHRsZSBiaXQgbGlrZSBpbnRlZ2VyIHZlY3RvciBiZWNhdXNlIFIgZW5jb2RlcyB0aGUgbGV2ZWxzIGFzIGludGVnZXJzLg0KI0ZhY3RvcnMgYXJlIHRoZSBkYXRhIG9iamVjdHMgd2hpY2ggYXJlIHVzZWQgdG8gY2F0ZWdvcml6ZSB0aGUgZGF0YSBhbmQgc3RvcmUgaXQgYXMgbGV2ZWxzLiBUaGV5IGNhbiBzdG9yZSBib3RoIHN0cmluZ3MgYW5kIGludGVnZXJzLiBUaGV5IGFyZSB1c2VmdWwgaW4gdGhlIGNvbHVtbnMgd2hpY2ggaGF2ZSBhIGxpbWl0ZWQgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMuIExpa2UgIk1hbGUsICJGZW1hbGUiIGFuZCBUcnVlLCBGYWxzZSBldGMuIFRoZXkgYXJlIHVzZWZ1bCBpbiBkYXRhIGFuYWx5c2lzIGZvciBzdGF0aXN0aWNhbCBtb2RlbGluZy4NCiMgdGhpcyB3YXMgbmVlZCB0byBjb3JyZWN0IGVycm9ycyB3ZSB3ZXJlIGhhdmluZyB3aGVuIHJ1bm5pbmcgdGhlIGdncGxvdHMgYW5kIGNvbXB1dGF0aW9ucyB3ZXJlIGdldHRpbmcgZXJyb3JzLg0KYXYkQ291bnRyeTwtYXMuZmFjdG9yKGF2JENvdW50cnkpDQpgYGANCg0KDQpgYGB7cn0NCmhlYWQoYXYpDQojIGhlYWQgYXYgZ2l2ZXMgeW91IGFuIGFjdHVhbCB2aWV3IG9mIHRoZSBoZWFkZXIgb2YgdGhlIHRhYmxlIHdpdGggYSBtb3JlIG9yZ2FuaXplZCB2aWV3ICwgd2hpbGUgc3RyIGdpdmVzIHlvdSBhIG1vcmUgbWVzc3kgYnV0IGNvbXBsZXRlIGluZm9ybWF0aW9uIG9mIHRoZSB0YWJsZSBzdWNoIGFzIGhvdyBtYW55ICBsZXZlbHMgcGVyIGZhY3Rvcg0KYGBgDQoNCg0KDQpgYGB7cn0NCnN1bW1hcnkoYXYkcmVsaWFiaWxpdHkpDQpzdW1tYXJ5KGF2JFJpc2spDQp0YWJsZShhdiRyZWxpYWJpbGl0eSkNCnRhYmxlKGF2JFJpc2spDQojIGhlcmUgd2UgZ290IGEgc3VtbWFyeSBvZiBib3RoIHJlbGlhYmlsaXR5IGFuZCBvZiByaXNrIHdpdGggbnVtYmVycyBzdWNoIGFzIG1pbixtZWFuLG1lZGlhbixtYXgNCiN3ZSBhbHNvIGdvIHRoZSB2YWx1ZXMgaW4gdGhlIHRhYmxlIA0KDQpgYGANCg0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShhdiRUeXBlLG1heHN1bT0xMCkNCg0Kc3VtbWFyeShhdiRDb3VudHJ5LCBtYXhzdW09NDApDQojIHdlIGFyZSBnZXR0aW5nIHRoZSBzdW1tYXJ5IG9mIGJvdGggdGhlc2UgY2F0ZWdvcmllcyB3aXRoIG1heCBsZXZlbCBvZiAxMCBhbmQgNDANCmBgYA0KDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpjb3VudHJ5LnRvcDIwIDwtIG5hbWVzKHN1bW1hcnkoYXYkQ291bnRyeSkpWzE6MjBdDQojIHdlIGp1c3QgY3JlYXRlZCBhIG5ldyBjb2x1bW4gd2l0aCB0aGUgdG9wIDIwIGNvdW50cmllcyBhbmQgd2UgY2FsbGVkIGl0IGNvdW50cnkudG9wMjANCmNvdW50cnkudG9wMjANCmBgYA0KDQoNCmBgYHtyfQ0KZ2cgPC1nZ3Bsb3QoZGF0YT1zdWJzZXQoYXYsQ291bnRyeSAlaW4lIGNvdW50cnkudG9wMjApLA0KI2dnIDwtZ2dwbG90KGRhdGE9c3Vic2V0KGF2KSwNCmFlcyh4PXJlb3JkZXIoQ291bnRyeSxDb3VudHJ5LCBsZW5ndGgpKSkNCmdnIDwtIGdnICsgZ2VvbV9iYXIoZmlsbD0iIzAwMDA5OSIpDQoNCg0KDQpnZyA8LSBnZyArIGxhYnModGl0bGU9IkNvdW50cnkgQ291bnRzIiwgeD0iQ291bnRyeSIsIHk9IkNvdW50IikNCiMgdGhlbiB3ZSBhcmUgZ29pbmcgdG8gcm90YXRlIHRoZSBjaGFydCB0byBtYWtlIGl0IGVhc2llciB0byByZWFkDQpnZyA8LSBnZyArIGNvb3JkX2ZsaXAoKQ0KDQoNCg0KcHJpbnQoZ2cpDQpgYGANCg0KDQpgYGB7cn0NCiMgV2UgYXJlIGdvaW5nIHRvIHJlbW92ZSBnYXJiYWdlIGZyb20gdGhlIGNoYXJ0IHdlIGNyZWF0ZWQgaW4gdGhlIGxhc3Qgc3RlcA0KZ2cgPC0gZ2cgKyB0aGVtZShwYW5lbC5ncmlkPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkpDQpwcmludChnZykNCiMgaGVyZSB3ZSBoYXZlIGEgY2hhcnQgd2l0aCB0aGUgdG9wIDIwIGNvdW50cmllcyBieSBjb3VudCBmcm9tIGhpZ2hlc3QgdG8gbG93ZXN0IGNvdW50IHdlIG5hbWVkIG91dCB5IHZhbHVlIGFuZCBvdXIgeCB2YWx1ZSB3ZSBnYXZlIHRoZSBjaGFydCBhIHRpdGxlDQpgYGANCiMgSSB3YXMgZ2V0dGluZyB0aGUgZm9sbG93aW5nIGVycjoNCiMgQ29udGludW91cyBsaW1pdHMgc3VwcGxpZWQgdG8gZGlzY3JldGUgc2NhbGUuDQojIERpZCB5b3UgbWVhbiBgbGltaXRzID0gZmFjdG9yKC4uLilgIG9yIGBzY2FsZV8qX2NvbnRpbnVvdXMoKWA/DQoNCiMgQ2hhbmdlZCB0aGUgbGluZSBnZyA8LSBnZyArIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPXNlcShtYXgoYXYkUmlzaykpKSB0bw0KIyBnZyA8LSBnZyArIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPWZhY3RvcihtYXgoYXYkUmlzaykpKQ0KDQpgYGB7cn0NCiMgbm93IHdlIGFyZSBnb2luZyB0byBjcmVhdGUgYSBiYXIgZ3JhcGggb2YgY291bnRzIGJ5IHJpc2sNCmdnIDwtIGdncGxvdChkYXRhPWF2LCBhZXMoeD1SaXNrKSkNCmdnIDwtIGdnICsgZ2VvbV9iYXIoZmlsbD0iIzAwMDA5OSIpDQojIGZvcmNlIGEgWCBzY2FsZSB0byBiZSBqdXN0IHRoZSBsaW1pdHMgb2YgdGhlIGRhdGEgYW5kIHRvIGJlIGRpc2NyZXRlIHZzIGNvbnRpbnVvdXMNCg0KI2dnIDwtIGdnICsgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHM9c2VxKG1heChhdiRSaXNrKSkpDQpnZyA8LSBnZyArIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPWZhY3RvcihtYXgoYXYkUmlzaykpKQ0KZ2cgPC0gZ2cgKyBsYWJzKHRpdGxlPSAiJ1Jpc2snIENvdW50cyIsIHg9IlJpc2sgU2NvcmUiLCB5PSJDb3VudCIpDQojIHJlbW92ZSBnYXJiYWdlIGZyb20gY2hhcnQgdG8gZ2V0IG1vcmUgcHJlY2lzZSBpbmZvDQpnZyA8LSBnZyArIHRoZW1lKHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkNCnByaW50KGdnKQ0KIyBXZSBqc3V0IGNyYXRlZCBhIGJhciBjaGFydCBjYWxsZWQgcmlzayBjb3VudHMgd2UgbmFtZWQgb3VyIHggYW5kIHkgYXhpcyB3ZSBnYXZlIHRoZSBncmFwaCBhIHRpdGxlIGFuZCB3ZSBnb3QgYWxsIG9mIG91ciBkYXRhIGZyb20gb3VyIGF2IHRhYmxlIGFuZCB0aGUgcmlzayBjb2x1bW4NCmBgYA0KIyBJIHdhcyBnZXR0aW5nIHRoZSBmb2xsb3dpbmcgZXJyOg0KIyBDb250aW51b3VzIGxpbWl0cyBzdXBwbGllZCB0byBkaXNjcmV0ZSBzY2FsZS4NCiMgRGlkIHlvdSBtZWFuIGBsaW1pdHMgPSBmYWN0b3IoLi4uKWAgb3IgYHNjYWxlXypfY29udGludW91cygpYD8NCg0KIyBJIENoYW5nZSB0aGUgbGluZSBnZyA8LSBnZyArIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPXNlcShtYXgoYXYkcmVsaWFiaWxpdHkpKSkgdG8NCiMgZ2cgPC0gZ2cgKyBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cz1mYWN0b3IobWF4KGF2JHJlbGlhYmlsaXR5KSkpDQojIHRoaXMgc29sdmVkIHRoZSBlcnJvci4NCmBgYHtyfQ0KIyBJbiB0aGlzIHBhcnQgb2YgdGhlIGhhbmRvdXQgd2UgYXJlIGdvaW5nIHRvIGNyZWF0ZSB5ZXQgYW5vdGhlciBiYXIgZ3JhcGggY2FsbGVkIGJhciBncmFwaCBvZiBjb3VudHMgYnkgcmVsaWFiaWxpdHkNCmdnIDwtIGdncGxvdChkYXRhPWF2LCBhZXMoeD1yZWxpYWJpbGl0eSkpDQpnZyA8LSBnZyArIGdlb21fYmFyKGZpbGw9IiMwMDAwOTkiKQ0KIyBmb3JjZSBhIFggc2NhbGUgdG8gYmUganVzdCB0aGUgbGltaXRzIG9mIHRoZSBkYXRhIGFuZCB0byBiZSBkaXNjcmV0ZSB2cyBjb250aW51b3VzDQpnZyA8LSBnZyArIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPWZhY3RvcihtYXgoYXYkcmVsaWFiaWxpdHkpKSkNCiNnZyA8LSBnZyArIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPXNlcShtYXgoYXYkcmVsaWFiaWxpdHkpKSkNCmdnIDwtIGdnICsgbGFicyh0aXRsZT0gIidSZWxpYWJpbGl0eScgQ291bnRzIiwgeD0iUmVsaWFiaWxpdHkgU2NvcmUiLCB5PSJDb3VudCIpDQojIHJlbW92ZSBnYXJiYWdlIGZyb20gY2hhcnQgdG8gZ2V0IG1vcmUgcHJlY2lzZSBpbmZvDQpnZyA8LSBnZyArIHRoZW1lKHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSkNCnByaW50KGdnKQ0KIyB3ZSBjcmVhdGVkIGFub3RoZXIgYmFyIGdyYXBoIGNhbGxlZCByZWxpYWJpbGl0eSBjb3VudHMgd2l0aCBvdXIgeSBhbmQgeCBheGlzIG5hbWVkIGFuZCB3ZSBnb3QgdGhlIGRhdGEgZnJvbSBvdXIgYXYgdGFibGUgYW5kIG91ciByZWxpYWJpbGl0eSBjb2x1bW4NCmBgYA0KDQoNCmBgYHtyfQ0KY291bnRyeV90b3AgPC0gc3VtbWFyeShhdiRDb3VudHJ5LCBtYXhzdW09MTApDQojIG5vdyB3ZSBhcmUgY29udmVydGluZyBpbnRvIGEgcGVyY2VudGFnZSBieSBkaXZpZGluZyBpdCBieSB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYXYNCmNvdW50cnkucGVyYzEwIDwtIGNvdW50cnlfdG9wL25yb3coYXYpDQoNCnByaW50KGNvdW50cnkucGVyYzEwKQ0KIyBoZXJlIHdlIGdvdCB0aGUgdG9wIDEwIGNvdW50cmllcyBhbmQgd2UgY29udmVydGVkIHRoZSB2YWx1ZSB0aGV5IHN1c3RhaW5lZCBpbnRvIGEgcGVyY2VudGFnZSBieSBkaXZpZGluZyBieSB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYXYgYW5kIHRoZXkgd2UgYXJlIGRpc3BsYXlpbmcgdGhlIHRvcCBpbiBwZXJjZW50YWdlDQoNCmBgYA0KDQoNCmBgYHtyfQ0KI3dlIGFyZSBjb21wdXRpbmcgYSBjb250aW5nZW5jeSB0YWJsZSBmb3Igcmlzay9yZWxpYWJpbGl0eSBmYWN0b3JzIHdoaWNoIGlzIGdvaW5nIHRvIHByb2R1Y2UgYSBtYXRyaXgNCiNvZiBjb3VudHMgb2Ygcm93cyB0aGF0IGhhdmUgYXR0cmlidXRlcyBhdCBlYWNoICh4LHkpIGxvY2F0aW9uDQpyci50YWIgPC0geHRhYnMoflJpc2srcmVsaWFiaWxpdHksIGRhdGE9YXYpDQpwcmludChmdGFibGUocnIudGFiKSkgI3ByaW50IHRoZSB0YWJsZSANCiMgd2UganVzdCBjcmVhdGVkIGFub3RoZXIgdGFibGUgdGhhdCBzaG93cyB1cyB3aGF0IHJpc2sgYW5kIHJlbGlhYmlsaXR5IGhhdmUgaW4gY29tbW9uDQpgYGANCg0KDQoNCmBgYHtyfQ0KI2dyYXBoaWNhbCB2aWV3DQojd2UgbmVlZCB0byB1c2UgYSBmdW5jdGlvbiBjYWxsZWQgbGV2ZWxwbG90IGZyb20gdGhlIGxhdHRpY2UgcGFja2FnZSB3ZSBkb3dubG9hZGVkIGF0IHRoZSBiZWdpbmluZyBvZiB0aGUgaGFuZG91dA0KIyBhbmQgd2UgYXJlIGdvaW5nIHRvIGNhc3QgdGhlIHRhYmxlIGludG8gYSBkYXRhIGZyYW1lDQpyci5kZiA9IGRhdGEuZnJhbWUodGFibGUoYXYkUmlzaywgYXYkcmVsaWFiaWxpdHkpKQ0KIyBub3cgd2UgYXJlIGdvaW5nIHRvIG5hbWUgb3VyIGNvbHVtbnMNCmNvbG5hbWVzKHJyLmRmKSA8LSBjKCJSaXNrIiwgIlJlbGlhYmlsaXR5IiwgIkZyZXEiKQ0KbGV2ZWxwbG90KEZyZXF+UmVsaWFiaWxpdHkqUmlzaywgZGF0YT1yci5kZiwgbWFpbj0iUmlzayB+IFJlbGlhYmlsaXR5IiwNCiAgICAgICAgICB5bGFiID0gIlJlbGlhYmlsaXR5IiwgeGxhYiA9ICJSaXNrIiwgc2hyaW5rID0gYyAoMC41LDEpLA0KICAgICAgICAgIGNvbC5yZWdpb25zID0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRjVGNUY1IiwgIiMwMTY2NUUiKSkoMjApKQ0KIyB3ZSBqdXN0IGNyZWF0ZWQgYSBsZXZlbHBsb3Qgd2ljaCB3ZSBnb3QgZnJvbSB0aGUgbGF0dGljZSBwYWNrYWdlIHdlIGRvbndsb2FkZWQgYW5kIHdlIHVzZWQgb3VyIFJpc2sgYW5kIHJlbGlhYmlsaXR5IGNvbHVtbnMgdG8gc2VlIHdoaWNoIGlzIHRoZSBwZXJmZWN0IHNwb3QgYmV0d2VlbiBib3RoIG9mIHRob3NlIGNhdGVnb3JpZXMNCmBgYA0KDQoNCmBgYHtyfQ0KIyBXZSBhcmUgZ29pbmcgdG8gZ2VuZXJhdGUgcmFuZG9tIHNhbXBsZXMgZm9yIHJpc2sgYW5kIFJlbGlhYmlsaXR5IGFuZCByZS1ydW4geHRhYg0KI3N0YXJ0aW5nIFBSTkcgZnJvbSByZXByb2R1Y2libGUgcG9pbnQNCnNldC5zZWVkKDE0OTIpICMgYXMgaXQgbGVhZHMgdG8gZGlzY292ZXJ5DQojZ2VuZXJhdGUgMjYwLDAwIHJhbmRvbSBzYW1wbGVzDQpyZWw9c2FtcGxlKDE6NywgMjYwMDAwLCByZXBsYWNlPVQpDQpyc2s9c2FtcGxlKDE6MTAsMjYwMDAwLCByZXBsYWNlPVQpDQojQ2FzdCB0aGUgdGFibGUgaW50byBhIGRhdGEgZnJhbWUNCnRtcC5kZiA9IGRhdGEuZnJhbWUodGFibGUoZmFjdG9yKHJzayksIGZhY3RvcihyZWwpKSkNCiMgd2UgYXJlIGdvaW5nIHRvIGdpdmUgdGhlIGNvbHVtbnMgbmFtZXMNCmNvbG5hbWVzKHJyLmRmKSA8LSBjKCJSaXNrIiwgIlJlbGlhYmlsaXR5IiwgIkZyZXEiKQ0KbGV2ZWxwbG90KEZyZXF+UmVsaWFiaWxpdHkqUmlzaywgZGF0YT1yci5kZiwgbWFpbj0iUmlzayB+IFJlbGlhYmlsaXR5IiwNCiAgICAgICAgICB5bGFiID0gIlJlbGlhYmlsaXR5IiwgeGxhYiA9ICJSaXNrIiwgc2hyaW5rID0gYyAoMC41LDEpLA0KICAgICAgICAgIGNvbC5yZWdpb25zID0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRjVGNUY1IiwgIiMwMTY2NUUiKSkoMjApKQ0KYGBgDQoNCg0KYGBge3J9DQojIFdlIGFyZSBnb2luZyB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgY2FsbGVkICJzaW1wbGV0eXBlICYgcmVwbGFjaW5nIG11bHRpcGxlIGNhdGVnb3JpZXMgd2l0aCBsYWJlbCBvZiJtdWx0aXBsZXMiDQphdiRzaW1wbGV0eXBlIDwtIGFzLmNoYXJhY3RlcihhdiRUeXBlKQ0KI0dyb3VwIGFsbCBub2RlcyB3aXRoIG11bHRpcGxlIGNhdGVnb3JpZXMgaW50byBhIG5ldyBjYXRlZ29yeQ0KYXYkc2ltcGxldHlwZVtncmVwKCc7JywgYXYkc2ltcGxldHlwZSldIDwtICJNdWx0aXBsZXMiDQojVHVybiBpdCBpbnRvIGEgZmFjdG9yIG9uY2UgYWdhaW4NCmF2JHNpbXBsZXR5cGUgPC0gZmFjdG9yKGF2JHNpbXBsZXR5cGUpDQpycnQuZGYgPSBkYXRhLmZyYW1lKHRhYmxlKGF2JFJpc2ssIGF2JHJlbGlhYmlsaXR5LCBhdiRzaW1wbGV0eXBlKSkNCmNvbG5hbWVzKHJydC5kZikgPC0gYygiUmlzayIsICJSZWxpYWJpbGl0eSIsICJzaW1wbGV0eXBlIiwiRnJlcSIpDQpsZXZlbHBsb3QoRnJlcSB+IFJlbGlhYmlsaXR5KlJpc2t8c2ltcGxldHlwZSwgZGF0YT1ycnQuZGYsDQogICAgICAgICAgbWFpbj0iUmlzayB+IFJlbGlhYmlsaXR5IHwgVHlwZSIseWxhYiA9ICJSaXNrIiwNCiAgICAgICAgICB4bGFiID0gIlJlbGlhYmlsaXR5Iiwgc2hyaW5rID0gYygwLjUsMSksDQogICAgICAgICAgY29sLnJlZ2lvbnMgPSBjb2xvclJhbXBQYWxldHRlKGMoIiNGNUY1RjUiLCIjMDE2NjVFIikpKDIwKSkNCg0KIyB3ZSBqc3V0IGNyZWF0ZWQgYSBsZXZlbHBsb3Rqc3V0IGxpa2UgdGhlIG9uZSBiZWZvcmUgYnV0IHdlIGFkZGVkIGFuIG5ldyBjb2x1bW4gY2FsbGVkIHNpbXBsZXR5cGUgd2hpY2ggc2hvd3MgdXMgdGhlIHR5cGVzIGFuZCB3aGVyZSB3ZSBzZWUgbW9yZSByaXNrIGEgcmVsaWFiaWxpdHkgcGVyIHR5cGUNCmBgYA0KDQoNCg0KYGBge3J9DQojIHdlIGFyZSBnb2luZyB0byBnbyBmcm8gdGhlIHNhbWUgbGV2ZWxwbG90IGJ1dCB3ZSBhcmUgZmlsdGVyaW5nIG91dCBzY2FubmluZyBob3N0IHdoaWNoIHdhcyB0aGUgbW9yZSBwb3B1bGFyIG9uZSBpbiB0aGUgZWFybGllciBsZXZlbHBsb3QNCnJydC5kZiA8LSBzdWJzZXQocnJ0LmRmLCBzaW1wbGV0eXBlICE9ICJTY2FubmluZyBIb3N0IikNCmxldmVscGxvdChGcmVxIH4gUmVsaWFiaWxpdHkqUmlza3xzaW1wbGV0eXBlLCBkYXRhID1ycnQuZGYsDQogICAgICAgICAgbWFpbj0iUmlzayB+IFJlbGlhYmlsaXR5IHwgVHlwZSIseWxhYiA9ICJSaXNrIiwNCiAgICAgICAgICB4bGFiID0gIlJlbGlhYmlsaXR5Iiwgc2hyaW5rID0gYygwLjUsIDEpLA0KICAgICAgICAgIGNvbC5yZWdpb25zID0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRjVGNUY1IiwiIzAxNjY1RSIpKSgyMCkpDQojIGhlcmUgd2UgaGF2ZSB0aGUgc2FtZSBsZXZlbCBwbG90IHdlIGhhZCBpbiB0aGUgZWFybGllciBleGFtcGxlIGJ1dCB3aXRob3V0IHNjYW5uaW5nIGhvc3QgYXMgYSBjYXRlZ29yeSBhbmQgd2Ugc2VlIHRoZSBncmFwaCBhIGxvdCBtb3JlIGRpc3RyaWJ1dGVkIHRoYW4gYmVmb3JlDQoNCmBgYA0KDQoNCmBgYHtyfQ0KcnJ0LmRmID0gc3Vic2V0KHJydC5kZiwNCiAgICAgICAgICAgICAgICAhKHNpbXBsZXR5cGUgJWluJSBjKCJNYWx3YXJlIGRpc3RyaWJ1dGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFsd2FyZSBEb21haW4iKSkpDQpzcHJpbnRmKCJDb3VudDogJWQ7IFBlcmNlbnQ6ICUyLjFmJSUiLA0KICAgICAgICBzdW0ocnJ0LmRmJEZyZXEpLA0KICAgICAgICAxMDAqc3VtKHJydC5kZiRGcmVxKS9ucm93KGF2KSkNCmxldmVscGxvdChGcmVxIH4gUmVsaWFiaWxpdHkqUmlza3xzaW1wbGV0eXBlLCBkYXRhID1ycnQuZGYsDQogICAgICAgICAgbWFpbj0iUmlzayB+IFJlbGlhYmlsaXR5IHwgVHlwZSIseWxhYiA9ICJSaXNrIiwNCiAgICAgICAgICB4bGFiID0gIlJlbGlhYmlsaXR5Iiwgc2hyaW5rID0gYygwLjUsIDEpLA0KICAgICAgICAgIGNvbC5yZWdpb25zID0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRjVGNUY1IiwiIzAxNjY1RSIpKSgyMCkpDQojIGhlcmUgd2UgY3JlYXRlZCBhbm90aGVyIGxldmVscGxvdCBidXQgd2l0aCBsZXNzIGNvbHVtbnMgaW4gdGhpcyBjYXNlIHdlIHRvb2sgb2ZmIG1hbHdhcmUgZGlzdHJpYnV0aW9uIGFuZCBtYWx3YXJlIGRvbWFpbiBhbmQgeWV0IGFnYWluIHdlIHNlZSB0aGUgbnVtYmVycyBiZXR0ZXIgZGlzdHJpYnV0ZWQgYWNyb3NzIHRoZSBncmFwaA0KYGBgDQoNCg==