rm(list=ls(all=T))
options(digits=4, scipen=12)
library(dplyr)
library(ggplot2)
library(maps)
library(ggmap)

7.2 芝加哥汽車竊案、資料探索

7.2.1 讀進、轉換資料
# Load our data:
mvt = read.csv("data/mvt.csv", stringsAsFactors=FALSE)
str(mvt)
'data.frame':   191641 obs. of  3 variables:
 $ Date     : chr  "12/31/12 23:15" "12/31/12 22:00" "12/31/12 22:00" "12/31/12 22:00" ...
 $ Latitude : num  41.8 41.9 42 41.8 41.8 ...
 $ Longitude: num  -87.6 -87.7 -87.8 -87.7 -87.6 ...
# Convert the Date variable to a format that R will recognize:
mvt$Date = strptime(mvt$Date, format="%m/%d/%y %H:%M")
7.2.2 星期換算
# Extract the hour and the day of the week:
mvt$Weekday = weekdays(mvt$Date)
mvt$Hour = mvt$Date$hour
str(mvt)
'data.frame':   191641 obs. of  5 variables:
 $ Date     : POSIXlt, format: "2012-12-31 23:15:00" "2012-12-31 22:00:00" ...
 $ Latitude : num  41.8 41.9 42 41.8 41.8 ...
 $ Longitude: num  -87.6 -87.7 -87.8 -87.7 -87.6 ...
 $ Weekday  : chr  "Monday" "Monday" "Monday" "Monday" ...
 $ Hour     : int  23 22 22 22 21 20 20 20 19 18 ...
# Create a simple line plot - need the total number of crimes on 
#each day of the week. We can get this information by creating a table:
table(mvt$Weekday)

   Friday    Monday  Saturday    Sunday  Thursday   Tuesday Wednesday 
    29284     27397     27118     26316     27319     26791     27416 
# Save this table as a data frame:
WeekdayCounts = as.data.frame(table(mvt$Weekday))
str(WeekdayCounts) 
'data.frame':   7 obs. of  2 variables:
 $ Var1: Factor w/ 7 levels "Friday","Monday",..: 1 2 3 4 5 6 7
 $ Freq: int  29284 27397 27118 26316 27319 26791 27416
7.2.3 簡單線圖
# Load the ggplot2 library:
library(ggplot2)
ggplot(WeekdayCounts, aes(x=Var1, y=Freq)) + 
  geom_line(aes(group=1))  

7.2.4 星期類別順序
# Make the "Var1" variable an ORDERED factor variable
WeekdayCounts$Var1 = factor(WeekdayCounts$Var1, ordered=TRUE, 
  levels=c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", 
           "Friday","Saturday"))
# Try again:
ggplot(WeekdayCounts, aes(x=Var1, y=Freq)) + 
  geom_line(aes(group=1))

7.2.5 改變X、Y軸標題
# Change our x and y labels:
ggplot(WeekdayCounts, aes(x=Var1, y=Freq)) + 
  geom_line(aes(group=1), alpha=0.3) + 
  xlab("Day of the Week") + ylab("Total Motor Vehicle Thefts")

7.2.5 七天、24小時
# VIDEO 4 - Adding the Hour of the Day
# Create a counts table for the weekday and hour:
table(mvt$Weekday, mvt$Hour)
           
               0    1    2    3    4    5    6    7    8    9   10   11   12
  Friday    1873  932  743  560  473  602  839 1203 1268 1286  938  822 1207
  Monday    1900  825  712  527  415  542  772 1123 1323 1235  971  737 1129
  Saturday  2050 1267  985  836  652  508  541  650  858 1039  946  789 1204
  Sunday    2028 1236 1019  838  607  461  478  483  615  864  884  787 1192
  Thursday  1856  816  696  508  400  534  799 1135 1298 1301  932  731 1093
  Tuesday   1691  777  603  464  414  520  845 1118 1175 1174  948  786 1108
  Wednesday 1814  790  619  469  396  561  862 1140 1329 1237  947  763 1225
           
              13   14   15   16   17   18   19   20   21   22   23
  Friday     857  937 1140 1165 1318 1623 1652 1736 1881 2308 1921
  Monday     824  958 1059 1136 1252 1518 1503 1622 1815 2009 1490
  Saturday   767  963 1086 1055 1084 1348 1390 1570 1702 2078 1750
  Sunday     789  959 1037 1083 1160 1389 1342 1706 1696 2079 1584
  Thursday   752  831 1044 1131 1258 1510 1537 1668 1776 2134 1579
  Tuesday    762  908 1071 1090 1274 1553 1496 1696 1816 2044 1458
  Wednesday  804  863 1075 1076 1289 1580 1507 1718 1748 2093 1511
# Save this to a data frame:
DayHourCounts = as.data.frame(table(mvt$Weekday, mvt$Hour))
str(DayHourCounts)
'data.frame':   168 obs. of  3 variables:
 $ Var1: Factor w/ 7 levels "Friday","Monday",..: 1 2 3 4 5 6 7 1 2 3 ...
 $ Var2: Factor w/ 24 levels "0","1","2","3",..: 1 1 1 1 1 1 1 2 2 2 ...
 $ Freq: int  1873 1900 2050 2028 1856 1691 1814 932 825 1267 ...
# Convert the second variable, Var2, to numbers and call it Hour:
DayHourCounts$Hour = as.numeric(as.character(DayHourCounts$Var2))
7.2.6 畫出 7 x 24 趨勢線圖
# Create out plot:
ggplot(DayHourCounts, aes(x=Hour, y=Freq)) +
  geom_line(aes(group=Var1))

# Change the colors
ggplot(DayHourCounts, aes(x=Hour, y=Freq)) + 
  geom_line(aes(group=Var1, color=Var1), size=2)

# 區分周末、周間
DayHourCounts$Type = ifelse(
  (DayHourCounts$Var1 == "Sunday") | (DayHourCounts$Var1 == "Saturday"), 
  "Weekend", "Weekday")
# Redo our plot, this time coloring by Type:
ggplot(DayHourCounts, aes(x=Hour, y=Freq)) + 
  geom_line(aes(group=Var1, color=Type), size=2) 

# Make the lines a little transparent:
ggplot(DayHourCounts, aes(x=Hour, y=Freq)) + 
  geom_line(aes(group=Var1, color=Type), size=2, alpha=0.5) 

7.2.6 畫出 7 x 24 熱圖
# 星期類別順序重整
DayHourCounts$Var1 = factor(DayHourCounts$Var1, ordered=TRUE, 
  levels=c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
           "Saturday", "Sunday"))
# Make a heatmap:
ggplot(DayHourCounts, aes(x = Hour, y = Var1)) + 
  geom_tile(aes(fill = Freq))

# Change the label on the legend, and get rid of the y-label:
ggplot(DayHourCounts, aes(x = Hour, y = Var1)) + 
  geom_tile(aes(fill = Freq)) + 
  scale_fill_gradient(name="Total MV Thefts") + 
  theme(axis.title.y = element_blank())

# Change the color scheme
ggplot(DayHourCounts, aes(x = Hour, y = Var1)) + 
  geom_tile(aes(fill = Freq)) + 
  scale_fill_gradient(name="Total MV Thefts", low="white", high="red") + 
  theme(axis.title.y = element_blank())

7.2.7 互動式熱圖
table(format(mvt$Date,'%H'), format(mvt$Date,'%w'))%>% t %>% 
  heatmap(NA,NA,scale='none',col=cm.colors(25))



7.2 芝加哥汽車竊案、地圖套製

7.2.8 透過 mapsggmap 套件抓取地圖
library(maps)
library(ggmap)
# Load a map of Chicago into R:
chicago = get_map(location = "chicago", zoom = 11)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=chicago&zoom=11&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=chicago&sensor=false
# Look at the map
chicago = ggmap(chicago)
chicago

# 可以畫高雄市嗎 ? 
ggmap(get_map(location = "kaohsiung", zoom = 12))
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=kaohsiung&zoom=12&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=kaohsiung&sensor=false

7.2.9 標記單一事件
# Plot the first 100 motor vehicle thefts:
chicago + geom_point(
  data = mvt[1:100,], aes(x = Longitude, y = Latitude))

7.2.9 依座標集收事件
# Round our latitude and longitude to 2 digits of accuracy, 
# and create a crime counts data frame for each area:
LatLonCounts = as.data.frame(table(round(mvt$Longitude,2), 
                                   round(mvt$Latitude,2)))
str(LatLonCounts)
'data.frame':   1638 obs. of  3 variables:
 $ Var1: Factor w/ 42 levels "-87.93","-87.92",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Var2: Factor w/ 39 levels "41.64","41.65",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Freq: int  0 0 0 0 0 0 0 0 0 0 ...
# Convert our Longitude and Latitude variable to numbers:
LatLonCounts$Long = as.numeric(as.character(LatLonCounts$Var1))
LatLonCounts$Lat = as.numeric(as.character(LatLonCounts$Var2))
# Plot these points on our map:
chicago + geom_point(data = LatLonCounts, 
                     aes(x = Long, y = Lat, color = Freq, size=Freq))

# Change the color scheme:
chicago + geom_point(data = LatLonCounts, 
                     aes(x=Long, y=Lat, color=Freq, size=Freq)) + 
  scale_colour_gradient(low="yellow", high="red")

7.2.10 格狀圖
# We can also use the geom_tile geometry
chicago + geom_tile(data = LatLonCounts, 
                    aes(x = Long, y = Lat, alpha = Freq), 
                    fill="red")

# 移除沒有事件的區格
LatLonCounts2 = subset(LatLonCounts, Freq > 0)
chicago + geom_tile(data = LatLonCounts2, 
                    aes(x = Long, y = Lat, alpha = Freq), 
                    fill="red")

7.2.11 事件密度圖
# density plot
chicago + stat_density_2d(data=mvt, 
    aes(x=Longitude, y=Latitude, alpha=..level..), 
    fill='orange', color='pink', size=0.01, bins=8, geom='polygon') +
  scale_alpha(range = c(0.05, 0.45))



7.2 槍枝持有率與謀殺比率

# VIDEO 6 - Geographical Map on US
# Load our data:
murders = read.csv("data/murders.csv")
str(murders)
'data.frame':   51 obs. of  6 variables:
 $ State            : Factor w/ 51 levels "Alabama","Alaska",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Population       : int  4779736 710231 6392017 2915918 37253956 5029196 3574097 897934 601723 19687653 ...
 $ PopulationDensity: num  94.65 1.26 57.05 56.43 244.2 ...
 $ Murders          : int  199 31 352 130 1811 117 131 48 131 987 ...
 $ GunMurders       : int  135 19 232 93 1257 65 97 38 99 669 ...
 $ GunOwnership     : num  0.517 0.578 0.311 0.553 0.213 0.347 0.167 0.255 0.036 0.245 ...
7.2.12 Read and Plot US Map
# Load the map of the US
statesMap = map_data("state")
str(statesMap)
'data.frame':   15537 obs. of  6 variables:
 $ long     : num  -87.5 -87.5 -87.5 -87.5 -87.6 ...
 $ lat      : num  30.4 30.4 30.4 30.3 30.3 ...
 $ group    : num  1 1 1 1 1 1 1 1 1 1 ...
 $ order    : int  1 2 3 4 5 6 7 8 9 10 ...
 $ region   : chr  "alabama" "alabama" "alabama" "alabama" ...
 $ subregion: chr  NA NA NA NA ...
# Plot the map:
ggplot(statesMap, aes(x = long, y = lat, group = group)) + 
  geom_polygon(fill = "white", color = "black") 

7.2.13 Merge the Dataframes (stateMap and murders)
# Create a new variable called region with the lowercase names to 
# match the statesMap:
murders$region = tolower(murders$State)
# Join the statesMap data and the murders data into one dataframe:
murderMap = merge(statesMap, murders, by="region")
str(murderMap)
'data.frame':   15537 obs. of  12 variables:
 $ region           : chr  "alabama" "alabama" "alabama" "alabama" ...
 $ long             : num  -87.5 -87.5 -87.5 -87.5 -87.6 ...
 $ lat              : num  30.4 30.4 30.4 30.3 30.3 ...
 $ group            : num  1 1 1 1 1 1 1 1 1 1 ...
 $ order            : int  1 2 3 4 5 6 7 8 9 10 ...
 $ subregion        : chr  NA NA NA NA ...
 $ State            : Factor w/ 51 levels "Alabama","Alaska",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Population       : int  4779736 4779736 4779736 4779736 4779736 4779736 4779736 4779736 4779736 4779736 ...
 $ PopulationDensity: num  94.7 94.7 94.7 94.7 94.7 ...
 $ Murders          : int  199 199 199 199 199 199 199 199 199 199 ...
 $ GunMurders       : int  135 135 135 135 135 135 135 135 135 135 ...
 $ GunOwnership     : num  0.517 0.517 0.517 0.517 0.517 0.517 0.517 0.517 0.517 0.517 ...
7.2.14 Map-1: No. Murders per State
# Plot the number of murder on our map of the United States:
ggplot(murderMap, aes(x = long, y = lat, group = group, fill = Murders)) + 
  geom_polygon(color = "black") + 
  scale_fill_gradient(low = "black", high = "red", guide = "legend")

7.2.15 Map-2: Populations per State
# Plot a map of the population:
ggplot(murderMap, aes(x = long, y = lat, group = group, fill = Population)) + 
  geom_polygon(color = "black") + 
  scale_fill_gradient(low = "black", high = "red", guide = "legend")

7.2.16 Map-3: No. Murders per 100K Population
# Create a new variable that is the number of murders per 100,000 population:
murderMap$MurderRate = murderMap$Murders / murderMap$Population * 100000
# Redo our plot with murder rate:
ggplot(murderMap, aes(x = long, y = lat, group = group, fill = MurderRate)) + 
  geom_polygon(color = "black") + 
  scale_fill_gradient(low = "black", high = "red", guide = "legend")

7.2.17 Map-4: No. Murders per 100K Population with Filter
# Redo the plot, Cap the Murderrate at 10:
ggplot(murderMap, aes(x = long, y = lat, group = group, fill = MurderRate)) + 
  geom_polygon(color = "black") + 
  scale_fill_gradient(low = "black", high = "red", 
                      guide = "legend", limits = c(0,10))

7.2.18 Map-5: Gun Ownership (%) by States
ggplot(murderMap,aes(x=long,y=lat,group=group,fill=GunOwnership)) + 
  geom_polygon(color = "black") + 
  scale_fill_gradient(low = "black", high = "red", guide = "legend")

7.2.19 Gun Ownership (%) by States
tapply(murderMap$GunOwnership, murderMap$region, mean) %>% sort %>% 
  barplot(las=2, cex.names=0.6, main="Averge GunOwnerShip (%)")








LS0tDQp0aXRsZTogIkFTNy0wQiDlnLDnkIbos4fmlpnoo73lnJYiDQphdXRob3I6ICLljZPpm43nhLYgRDk5NDAxMDAwMSwgMjAxOC8wNy8yMiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjxicj4NCg0KYGBge3IgZWNobz1ULCBtZXNzYWdlPUYsIGNhY2hlPUYsIHdhcm5pbmc9Rn0NCnJtKGxpc3Q9bHMoYWxsPVQpKQ0Kb3B0aW9ucyhkaWdpdHM9NCwgc2NpcGVuPTEyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobWFwcykNCmxpYnJhcnkoZ2dtYXApDQpgYGANCg0KLSAtIC0NCg0KIyMjIDcuMiDoip3liqDlk6Xmsb3ou4rnq4rmoYjjgIHos4fmlpnmjqLntKINCg0KIyMjIyMgNy4yLjEg6K6A6YCy44CB6L2J5o+b6LOH5paZDQpgYGB7cn0NCiMgTG9hZCBvdXIgZGF0YToNCm12dCA9IHJlYWQuY3N2KCJkYXRhL212dC5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQ0Kc3RyKG12dCkNCg0KIyBDb252ZXJ0IHRoZSBEYXRlIHZhcmlhYmxlIHRvIGEgZm9ybWF0IHRoYXQgUiB3aWxsIHJlY29nbml6ZToNCm12dCREYXRlID0gc3RycHRpbWUobXZ0JERhdGUsIGZvcm1hdD0iJW0vJWQvJXkgJUg6JU0iKQ0KYGBgDQoNCiMjIyMjIDcuMi4yIOaYn+acn+aPm+eulw0KYGBge3J9DQojIEV4dHJhY3QgdGhlIGhvdXIgYW5kIHRoZSBkYXkgb2YgdGhlIHdlZWs6DQptdnQkV2Vla2RheSA9IHdlZWtkYXlzKG12dCREYXRlKQ0KbXZ0JEhvdXIgPSBtdnQkRGF0ZSRob3VyDQpzdHIobXZ0KQ0KDQojIENyZWF0ZSBhIHNpbXBsZSBsaW5lIHBsb3QgLSBuZWVkIHRoZSB0b3RhbCBudW1iZXIgb2YgY3JpbWVzIG9uIA0KI2VhY2ggZGF5IG9mIHRoZSB3ZWVrLiBXZSBjYW4gZ2V0IHRoaXMgaW5mb3JtYXRpb24gYnkgY3JlYXRpbmcgYSB0YWJsZToNCnRhYmxlKG12dCRXZWVrZGF5KQ0KDQojIFNhdmUgdGhpcyB0YWJsZSBhcyBhIGRhdGEgZnJhbWU6DQpXZWVrZGF5Q291bnRzID0gYXMuZGF0YS5mcmFtZSh0YWJsZShtdnQkV2Vla2RheSkpDQpzdHIoV2Vla2RheUNvdW50cykgDQpgYGANCg0KIyMjIyMgNy4yLjMg57Ch5Zau57ea5ZyWDQpgYGB7cn0NCiMgTG9hZCB0aGUgZ2dwbG90MiBsaWJyYXJ5Og0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KFdlZWtkYXlDb3VudHMsIGFlcyh4PVZhcjEsIHk9RnJlcSkpICsgDQogIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICANCmBgYA0KDQojIyMjIyA3LjIuNCDmmJ/mnJ/poZ7liKXpoIbluo8NCmBgYHtyfQ0KIyBNYWtlIHRoZSAiVmFyMSIgdmFyaWFibGUgYW4gT1JERVJFRCBmYWN0b3IgdmFyaWFibGUNCldlZWtkYXlDb3VudHMkVmFyMSA9IGZhY3RvcihXZWVrZGF5Q291bnRzJFZhcjEsIG9yZGVyZWQ9VFJVRSwgDQogIGxldmVscz1jKCJTdW5kYXkiLCAiTW9uZGF5IiwgIlR1ZXNkYXkiLCAiV2VkbmVzZGF5IiwgIlRodXJzZGF5IiwgDQogICAgICAgICAgICJGcmlkYXkiLCJTYXR1cmRheSIpKQ0KDQojIFRyeSBhZ2FpbjoNCmdncGxvdChXZWVrZGF5Q291bnRzLCBhZXMoeD1WYXIxLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKQ0KYGBgDQoNCiMjIyMjIDcuMi41IOaUueiuiljjgIFZ6Lu45qiZ6aGMDQpgYGB7cn0NCiMgQ2hhbmdlIG91ciB4IGFuZCB5IGxhYmVsczoNCmdncGxvdChXZWVrZGF5Q291bnRzLCBhZXMoeD1WYXIxLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpLCBhbHBoYT0wLjMpICsgDQogIHhsYWIoIkRheSBvZiB0aGUgV2VlayIpICsgeWxhYigiVG90YWwgTW90b3IgVmVoaWNsZSBUaGVmdHMiKQ0KYGBgDQoNCiMjIyMjIDcuMi41IOS4g+WkqeOAgTI05bCP5pmCDQpgYGB7cn0NCiMgVklERU8gNCAtIEFkZGluZyB0aGUgSG91ciBvZiB0aGUgRGF5DQojIENyZWF0ZSBhIGNvdW50cyB0YWJsZSBmb3IgdGhlIHdlZWtkYXkgYW5kIGhvdXI6DQp0YWJsZShtdnQkV2Vla2RheSwgbXZ0JEhvdXIpDQoNCiMgU2F2ZSB0aGlzIHRvIGEgZGF0YSBmcmFtZToNCkRheUhvdXJDb3VudHMgPSBhcy5kYXRhLmZyYW1lKHRhYmxlKG12dCRXZWVrZGF5LCBtdnQkSG91cikpDQpzdHIoRGF5SG91ckNvdW50cykNCg0KIyBDb252ZXJ0IHRoZSBzZWNvbmQgdmFyaWFibGUsIFZhcjIsIHRvIG51bWJlcnMgYW5kIGNhbGwgaXQgSG91cjoNCkRheUhvdXJDb3VudHMkSG91ciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKERheUhvdXJDb3VudHMkVmFyMikpDQpgYGANCg0KIyMjIyMgNy4yLjYg55Wr5Ye6IDcgeCAyNCDotqjli6Lnt5rlnJYgDQpgYGB7cn0NCiMgQ3JlYXRlIG91dCBwbG90Og0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4PUhvdXIsIHk9RnJlcSkpICsNCiAgZ2VvbV9saW5lKGFlcyhncm91cD1WYXIxKSkNCmBgYA0KDQpgYGB7cn0NCiMgQ2hhbmdlIHRoZSBjb2xvcnMNCmdncGxvdChEYXlIb3VyQ291bnRzLCBhZXMoeD1Ib3VyLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPVZhcjEsIGNvbG9yPVZhcjEpLCBzaXplPTIpDQpgYGANCg0KYGBge3J9DQojIOWNgOWIhuWRqOacq+OAgeWRqOmWkw0KRGF5SG91ckNvdW50cyRUeXBlID0gaWZlbHNlKA0KICAoRGF5SG91ckNvdW50cyRWYXIxID09ICJTdW5kYXkiKSB8IChEYXlIb3VyQ291bnRzJFZhcjEgPT0gIlNhdHVyZGF5IiksIA0KICAiV2Vla2VuZCIsICJXZWVrZGF5IikNCg0KIyBSZWRvIG91ciBwbG90LCB0aGlzIHRpbWUgY29sb3JpbmcgYnkgVHlwZToNCmdncGxvdChEYXlIb3VyQ291bnRzLCBhZXMoeD1Ib3VyLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPVZhcjEsIGNvbG9yPVR5cGUpLCBzaXplPTIpIA0KYGBgDQoNCmBgYHtyfQ0KIyBNYWtlIHRoZSBsaW5lcyBhIGxpdHRsZSB0cmFuc3BhcmVudDoNCmdncGxvdChEYXlIb3VyQ291bnRzLCBhZXMoeD1Ib3VyLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPVZhcjEsIGNvbG9yPVR5cGUpLCBzaXplPTIsIGFscGhhPTAuNSkgDQpgYGANCg0KIyMjIyMgNy4yLjYg55Wr5Ye6IDcgeCAyNCDnhrHlnJYNCg0KYGBge3J9DQojIOaYn+acn+mhnuWIpemghuW6j+mHjeaVtA0KRGF5SG91ckNvdW50cyRWYXIxID0gZmFjdG9yKERheUhvdXJDb3VudHMkVmFyMSwgb3JkZXJlZD1UUlVFLCANCiAgbGV2ZWxzPWMoIk1vbmRheSIsICJUdWVzZGF5IiwgIldlZG5lc2RheSIsICJUaHVyc2RheSIsICJGcmlkYXkiLCANCiAgICAgICAgICAgIlNhdHVyZGF5IiwgIlN1bmRheSIpKQ0KDQojIE1ha2UgYSBoZWF0bWFwOg0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4ID0gSG91ciwgeSA9IFZhcjEpKSArIA0KICBnZW9tX3RpbGUoYWVzKGZpbGwgPSBGcmVxKSkNCmBgYA0KDQpgYGB7cn0NCiMgQ2hhbmdlIHRoZSBsYWJlbCBvbiB0aGUgbGVnZW5kLCBhbmQgZ2V0IHJpZCBvZiB0aGUgeS1sYWJlbDoNCmdncGxvdChEYXlIb3VyQ291bnRzLCBhZXMoeCA9IEhvdXIsIHkgPSBWYXIxKSkgKyANCiAgZ2VvbV90aWxlKGFlcyhmaWxsID0gRnJlcSkpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobmFtZT0iVG90YWwgTVYgVGhlZnRzIikgKyANCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDaGFuZ2UgdGhlIGNvbG9yIHNjaGVtZQ0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4ID0gSG91ciwgeSA9IFZhcjEpKSArIA0KICBnZW9tX3RpbGUoYWVzKGZpbGwgPSBGcmVxKSkgKyANCiAgc2NhbGVfZmlsbF9ncmFkaWVudChuYW1lPSJUb3RhbCBNViBUaGVmdHMiLCBsb3c9IndoaXRlIiwgaGlnaD0icmVkIikgKyANCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKQ0KYGBgDQoNCiMjIyMjIDcuMi43IOS6kuWLleW8j+eGseWclg0KYGBge3J9DQp0YWJsZShmb3JtYXQobXZ0JERhdGUsJyVIJyksIGZvcm1hdChtdnQkRGF0ZSwnJXcnKSklPiUgdCAlPiUgDQogIGhlYXRtYXAoTkEsTkEsc2NhbGU9J25vbmUnLGNvbD1jbS5jb2xvcnMoMjUpKQ0KYGBgDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyA3LjIg6Iqd5Yqg5ZOl5rG96LuK56uK5qGI44CB5Zyw5ZyW5aWX6KO9DQoNCiMjIyMjIDcuMi44IOmAj+mBjiBgbWFwc2Ag5ZKMIGBnZ21hcGAg5aWX5Lu25oqT5Y+W5Zyw5ZyWDQpgYGB7cn0NCmxpYnJhcnkobWFwcykNCmxpYnJhcnkoZ2dtYXApDQoNCiMgTG9hZCBhIG1hcCBvZiBDaGljYWdvIGludG8gUjoNCmNoaWNhZ28gPSBnZXRfbWFwKGxvY2F0aW9uID0gImNoaWNhZ28iLCB6b29tID0gMTEpDQoNCiMgTG9vayBhdCB0aGUgbWFwDQpjaGljYWdvID0gZ2dtYXAoY2hpY2FnbykNCmNoaWNhZ28NCmBgYA0KDQpgYGB7cn0NCiMg5Y+v5Lul55Wr6auY6ZuE5biC5ZeOID8gDQpnZ21hcChnZXRfbWFwKGxvY2F0aW9uID0gImthb2hzaXVuZyIsIHpvb20gPSAxMikpDQpgYGANCg0KIyMjIyMgNy4yLjkg5qiZ6KiY5Zau5LiA5LqL5Lu2DQpgYGB7cn0NCiMgUGxvdCB0aGUgZmlyc3QgMTAwIG1vdG9yIHZlaGljbGUgdGhlZnRzOg0KY2hpY2FnbyArIGdlb21fcG9pbnQoDQogIGRhdGEgPSBtdnRbMToxMDAsXSwgYWVzKHggPSBMb25naXR1ZGUsIHkgPSBMYXRpdHVkZSkpDQpgYGANCg0KIyMjIyMgNy4yLjkg5L6d5bqn5qiZ6ZuG5pS25LqL5Lu2DQpgYGB7cn0NCiMgUm91bmQgb3VyIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgdG8gMiBkaWdpdHMgb2YgYWNjdXJhY3ksIA0KIyBhbmQgY3JlYXRlIGEgY3JpbWUgY291bnRzIGRhdGEgZnJhbWUgZm9yIGVhY2ggYXJlYToNCkxhdExvbkNvdW50cyA9IGFzLmRhdGEuZnJhbWUodGFibGUocm91bmQobXZ0JExvbmdpdHVkZSwyKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKG12dCRMYXRpdHVkZSwyKSkpDQpzdHIoTGF0TG9uQ291bnRzKQ0KDQojIENvbnZlcnQgb3VyIExvbmdpdHVkZSBhbmQgTGF0aXR1ZGUgdmFyaWFibGUgdG8gbnVtYmVyczoNCkxhdExvbkNvdW50cyRMb25nID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoTGF0TG9uQ291bnRzJFZhcjEpKQ0KTGF0TG9uQ291bnRzJExhdCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKExhdExvbkNvdW50cyRWYXIyKSkNCg0KIyBQbG90IHRoZXNlIHBvaW50cyBvbiBvdXIgbWFwOg0KY2hpY2FnbyArIGdlb21fcG9pbnQoZGF0YSA9IExhdExvbkNvdW50cywgDQogICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IExvbmcsIHkgPSBMYXQsIGNvbG9yID0gRnJlcSwgc2l6ZT1GcmVxKSkNCmBgYA0KDQpgYGB7cn0NCiMgQ2hhbmdlIHRoZSBjb2xvciBzY2hlbWU6DQpjaGljYWdvICsgZ2VvbV9wb2ludChkYXRhID0gTGF0TG9uQ291bnRzLCANCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4PUxvbmcsIHk9TGF0LCBjb2xvcj1GcmVxLCBzaXplPUZyZXEpKSArIA0KICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobG93PSJ5ZWxsb3ciLCBoaWdoPSJyZWQiKQ0KYGBgDQoNCiMjIyMjIDcuMi4xMCDmoLzni4DlnJYNCmBgYHtyfQ0KIyBXZSBjYW4gYWxzbyB1c2UgdGhlIGdlb21fdGlsZSBnZW9tZXRyeQ0KY2hpY2FnbyArIGdlb21fdGlsZShkYXRhID0gTGF0TG9uQ291bnRzLCANCiAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBMb25nLCB5ID0gTGF0LCBhbHBoYSA9IEZyZXEpLCANCiAgICAgICAgICAgICAgICAgICAgZmlsbD0icmVkIikNCmBgYA0KDQpgYGB7cn0NCiMg56e76Zmk5rKS5pyJ5LqL5Lu255qE5Y2A5qC8DQpMYXRMb25Db3VudHMyID0gc3Vic2V0KExhdExvbkNvdW50cywgRnJlcSA+IDApDQpjaGljYWdvICsgZ2VvbV90aWxlKGRhdGEgPSBMYXRMb25Db3VudHMyLCANCiAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBMb25nLCB5ID0gTGF0LCBhbHBoYSA9IEZyZXEpLCANCiAgICAgICAgICAgICAgICAgICAgZmlsbD0icmVkIikNCmBgYA0KDQojIyMjIyA3LjIuMTEg5LqL5Lu25a+G5bqm5ZyWDQpgYGB7cn0NCiMgZGVuc2l0eSBwbG90DQpjaGljYWdvICsgc3RhdF9kZW5zaXR5XzJkKGRhdGE9bXZ0LCANCiAgICBhZXMoeD1Mb25naXR1ZGUsIHk9TGF0aXR1ZGUsIGFscGhhPS4ubGV2ZWwuLiksIA0KICAgIGZpbGw9J29yYW5nZScsIGNvbG9yPSdwaW5rJywgc2l6ZT0wLjAxLCBiaW5zPTgsIGdlb209J3BvbHlnb24nKSArDQogIHNjYWxlX2FscGhhKHJhbmdlID0gYygwLjA1LCAwLjQ1KSkNCmBgYA0KPGJyPg0KDQotIC0gLQ0KDQojIyMgNy4yIOanjeaeneaMgeacieeOh+iIh+isgOauuuavlOeOhw0KDQpgYGB7cn0NCiMgVklERU8gNiAtIEdlb2dyYXBoaWNhbCBNYXAgb24gVVMNCiMgTG9hZCBvdXIgZGF0YToNCm11cmRlcnMgPSByZWFkLmNzdigiZGF0YS9tdXJkZXJzLmNzdiIpDQpzdHIobXVyZGVycykNCmBgYA0KDQojIyMjIyA3LjIuMTIgUmVhZCBhbmQgUGxvdCBVUyBNYXANCmBgYHtyfQ0KIyBMb2FkIHRoZSBtYXAgb2YgdGhlIFVTDQpzdGF0ZXNNYXAgPSBtYXBfZGF0YSgic3RhdGUiKQ0Kc3RyKHN0YXRlc01hcCkNCg0KIyBQbG90IHRoZSBtYXA6DQpnZ3Bsb3Qoc3RhdGVzTWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApKSArIA0KICBnZW9tX3BvbHlnb24oZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikgDQoNCmBgYA0KDQojIyMjIyA3LjIuMTMgTWVyZ2UgdGhlIERhdGFmcmFtZXMgKGBzdGF0ZU1hcGAgYW5kIGBtdXJkZXJzYCkNCmBgYHtyfQ0KIyBDcmVhdGUgYSBuZXcgdmFyaWFibGUgY2FsbGVkIHJlZ2lvbiB3aXRoIHRoZSBsb3dlcmNhc2UgbmFtZXMgdG8gDQojIG1hdGNoIHRoZSBzdGF0ZXNNYXA6DQptdXJkZXJzJHJlZ2lvbiA9IHRvbG93ZXIobXVyZGVycyRTdGF0ZSkNCg0KIyBKb2luIHRoZSBzdGF0ZXNNYXAgZGF0YSBhbmQgdGhlIG11cmRlcnMgZGF0YSBpbnRvIG9uZSBkYXRhZnJhbWU6DQptdXJkZXJNYXAgPSBtZXJnZShzdGF0ZXNNYXAsIG11cmRlcnMsIGJ5PSJyZWdpb24iKQ0Kc3RyKG11cmRlck1hcCkNCmBgYA0KDQojIyMjIyA3LjIuMTQgTWFwLTE6IE5vLiBNdXJkZXJzIHBlciBTdGF0ZQ0KYGBge3J9DQojIFBsb3QgdGhlIG51bWJlciBvZiBtdXJkZXIgb24gb3VyIG1hcCBvZiB0aGUgVW5pdGVkIFN0YXRlczoNCmdncGxvdChtdXJkZXJNYXAsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IE11cmRlcnMpKSArIA0KICBnZW9tX3BvbHlnb24oY29sb3IgPSAiYmxhY2siKSArIA0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAicmVkIiwgZ3VpZGUgPSAibGVnZW5kIikNCmBgYA0KDQojIyMjIyA3LjIuMTUgTWFwLTI6IFBvcHVsYXRpb25zIHBlciBTdGF0ZQ0KYGBge3J9DQojIFBsb3QgYSBtYXAgb2YgdGhlIHBvcHVsYXRpb246DQpnZ3Bsb3QobXVyZGVyTWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBQb3B1bGF0aW9uKSkgKyANCiAgZ2VvbV9wb2x5Z29uKGNvbG9yID0gImJsYWNrIikgKyANCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gInJlZCIsIGd1aWRlID0gImxlZ2VuZCIpDQpgYGANCg0KIyMjIyMgNy4yLjE2IE1hcC0zOiBOby4gTXVyZGVycyBwZXIgMTAwSyBQb3B1bGF0aW9uDQpgYGB7cn0NCiMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIHRoYXQgaXMgdGhlIG51bWJlciBvZiBtdXJkZXJzIHBlciAxMDAsMDAwIHBvcHVsYXRpb246DQptdXJkZXJNYXAkTXVyZGVyUmF0ZSA9IG11cmRlck1hcCRNdXJkZXJzIC8gbXVyZGVyTWFwJFBvcHVsYXRpb24gKiAxMDAwMDANCg0KIyBSZWRvIG91ciBwbG90IHdpdGggbXVyZGVyIHJhdGU6DQpnZ3Bsb3QobXVyZGVyTWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBNdXJkZXJSYXRlKSkgKyANCiAgZ2VvbV9wb2x5Z29uKGNvbG9yID0gImJsYWNrIikgKyANCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gInJlZCIsIGd1aWRlID0gImxlZ2VuZCIpDQpgYGANCg0KIyMjIyMgNy4yLjE3IE1hcC00OiBOby4gTXVyZGVycyBwZXIgMTAwSyBQb3B1bGF0aW9uIHdpdGggRmlsdGVyDQpgYGB7cn0NCiMgUmVkbyB0aGUgcGxvdCwgQ2FwIHRoZSBNdXJkZXJyYXRlIGF0IDEwOg0KZ2dwbG90KG11cmRlck1hcCwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gTXVyZGVyUmF0ZSkpICsgDQogIGdlb21fcG9seWdvbihjb2xvciA9ICJibGFjayIpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiLCANCiAgICAgICAgICAgICAgICAgICAgICBndWlkZSA9ICJsZWdlbmQiLCBsaW1pdHMgPSBjKDAsMTApKQ0KYGBgDQoNCiMjIyMjIDcuMi4xOCBNYXAtNTogR3VuIE93bmVyc2hpcCAoJSkgYnkgU3RhdGVzDQpgYGB7cn0NCmdncGxvdChtdXJkZXJNYXAsYWVzKHg9bG9uZyx5PWxhdCxncm91cD1ncm91cCxmaWxsPUd1bk93bmVyc2hpcCkpICsgDQogIGdlb21fcG9seWdvbihjb2xvciA9ICJibGFjayIpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiLCBndWlkZSA9ICJsZWdlbmQiKQ0KYGBgDQoNCiMjIyMjIDcuMi4xOSBHdW4gT3duZXJzaGlwICglKSBieSBTdGF0ZXMNCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTMuMn0NCnRhcHBseShtdXJkZXJNYXAkR3VuT3duZXJzaGlwLCBtdXJkZXJNYXAkcmVnaW9uLCBtZWFuKSAlPiUgc29ydCAlPiUgDQogIGJhcnBsb3QobGFzPTIsIGNleC5uYW1lcz0wLjYsIG1haW49IkF2ZXJnZSBHdW5Pd25lclNoaXAgKCUpIikNCmBgYA0KPGJyPg0KDQotIC0gLQ0KDQo8YnI+PGJyPjxicj48YnI+PGJyPg0KDQo8c3R5bGU+DQouY2FwdGlvbiB7DQogIGNvbG9yOiAjNzc3Ow0KICBtYXJnaW4tdG9wOiAxMHB4Ow0KfQ0KcCBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwcmUgew0KICB3b3JkLWJyZWFrOiBub3JtYWw7DQogIHdvcmQtd3JhcDogbm9ybWFsOw0KICBsaW5lLWhlaWdodDogMTsNCn0NCnByZSBjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7DQp9DQpwLGxpIHsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCi5yew0KICBsaW5lLWhlaWdodDogMS4yOw0KfQ0KDQp0aXRsZXsNCiAgY29sb3I6ICNjYzAwMDA7DQogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOw0KfQ0KDQpib2R5ew0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KaDEsaDIsaDMsaDQsaDV7DQogIGNvbG9yOiAjMDA4ODAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KaDN7DQogIGNvbG9yOiAjYjM2YjAwOw0KICBiYWNrZ3JvdW5kOiAjZmZlMGIzOw0KICBsaW5lLWhlaWdodDogMjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCmg1ew0KICBjb2xvcjogIzAwNjAwMDsNCiAgYmFja2dyb3VuZDogI2ZmZmZlMDsNCiAgbGluZS1oZWlnaHQ6IDI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KDQplbXsNCiAgY29sb3I6ICMwMDAwYzA7DQogIGJhY2tncm91bmQ6ICNmMGYwZjA7DQogIH0NCjwvc3R5bGU+DQoNCg==