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) #we have a text field, and we want to make sure it's read in properly.
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" ...
 $ 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 
    29284     27397     27118     26316     27319     26791 
Wednesday 
    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))  #This just groups all of our data into one line,since we want one line in our plot.

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   13   14   15
  星期一 1900  825  712  527  415  542  772 1123 1323 1235  971  737 1129  824  958 1059
  星期二 1691  777  603  464  414  520  845 1118 1175 1174  948  786 1108  762  908 1071
  星期三 1814  790  619  469  396  561  862 1140 1329 1237  947  763 1225  804  863 1075
  星期五 1873  932  743  560  473  602  839 1203 1268 1286  938  822 1207  857  937 1140
  星期六 2050 1267  985  836  652  508  541  650  858 1039  946  789 1204  767  963 1086
  星期日 2028 1236 1019  838  607  461  478  483  615  864  884  787 1192  789  959 1037
  星期四 1856  816  696  508  400  534  799 1135 1298 1301  932  731 1093  752  831 1044
        
           16   17   18   19   20   21   22   23
  星期一 1136 1252 1518 1503 1622 1815 2009 1490
  星期二 1090 1274 1553 1496 1696 1816 2044 1458
  星期三 1076 1289 1580 1507 1718 1748 2093 1511
  星期五 1165 1318 1623 1652 1736 1881 2308 1921
  星期六 1055 1084 1348 1390 1570 1702 2078 1750
  星期日 1083 1160 1389 1342 1706 1696 2079 1584
  星期四 1131 1258 1510 1537 1668 1776 2134 1579
# 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 "星期一","星期二",..: 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  1900 1691 1814 1873 2050 2028 1856 825 777 790 ...
# 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))  #Var1就是weekday

# 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")
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
# 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)  #alpha變透明
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale

7.2.6 畫出 7 x 24 熱圖
# 星期類別順序重整  #The x and y-axes in a heat map don't need to be continuous.
DayHourCounts$Var1 = factor(DayHourCounts$Var1, ordered=TRUE, 
  levels=c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
           "Saturday", "Sunday"))  #the third argument is the order we want the days of the week to show up in.
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
# Make a heatmap:
ggplot(DayHourCounts, aes(x = Hour, y = Var1)) + 
  geom_tile(aes(fill = Freq))  #geom_tile畫熱圖

# 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)
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
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)  #ggmap畫地圖
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
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale

7.2.9 標記單一事件
# Plot the first 100 motor vehicle thefts:
chicago + geom_point(
  data = mvt[1:100,], aes(x = Longitude, y = Latitude))  #經緯度
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale

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),   #把小數點2位以下集收起來
                                   round(mvt$Latitude,2)))
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
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")

# 移除沒有事件的區格(0的濾掉)
LatLonCounts2 = subset(LatLonCounts, Freq > 0)
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
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")  #map_data("state")將行政州界圖抓下來
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
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)
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
# Join the statesMap data and the murders data into one dataframe:
murderMap = merge(statesMap, murders, by="region")
str(murderMap)  #15537之所以會那麼多是因為他會把很多個多邊形接起來變成州界
'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 ...
                #group要整理,否則資料不順會畫不出來
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 (%)")








LS0tDQp0aXRsZTogIkFTNy0wQiDlnLDnkIbos4fmlpnoo73lnJYiDQphdXRob3I6ICLkvZXoqp7lqZUgTTA2NDAyMDA0MCwgMjAxOC8wNy8zMSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjxicj4NCg0KYGBge3IgZWNobz1ULCBtZXNzYWdlPUYsIGNhY2hlPUYsIHdhcm5pbmc9Rn0NCnJtKGxpc3Q9bHMoYWxsPVQpKQ0Kb3B0aW9ucyhkaWdpdHM9NCwgc2NpcGVuPTEyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobWFwcykNCmxpYnJhcnkoZ2dtYXApDQpgYGANCg0KLSAtIC0NCg0KIyMjIDcuMiDoip3liqDlk6Xmsb3ou4rnq4rmoYjjgIHos4fmlpnmjqLntKINCg0KIyMjIyMgNy4yLjEg6K6A6YCy44CB6L2J5o+b6LOH5paZDQpgYGB7cn0NCiMgTG9hZCBvdXIgZGF0YToNCm12dCA9IHJlYWQuY3N2KCJkYXRhL212dC5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKSAjd2UgaGF2ZSBhIHRleHQgZmllbGQsIGFuZCB3ZSB3YW50IHRvIG1ha2Ugc3VyZSBpdCdzIHJlYWQgaW4gcHJvcGVybHkuDQpzdHIobXZ0KQ0KDQojIENvbnZlcnQgdGhlIERhdGUgdmFyaWFibGUgdG8gYSBmb3JtYXQgdGhhdCBSIHdpbGwgcmVjb2duaXplOg0KbXZ0JERhdGUgPSBzdHJwdGltZShtdnQkRGF0ZSwgZm9ybWF0PSIlbS8lZC8leSAlSDolTSIpICAj6YCZ5qij5bCx5pyD5pyJ5pel5pyf6Lef5pmC6ZaTDQpgYGANCg0KIyMjIyMgNy4yLjIg5pif5pyf5o+b566XDQpgYGB7cn0NCiMgRXh0cmFjdCB0aGUgaG91ciBhbmQgdGhlIGRheSBvZiB0aGUgd2VlazoNCm12dCRXZWVrZGF5ID0gd2Vla2RheXMobXZ0JERhdGUpDQptdnQkSG91ciA9IG12dCREYXRlJGhvdXINCnN0cihtdnQpDQoNCiMgQ3JlYXRlIGEgc2ltcGxlIGxpbmUgcGxvdCAtIG5lZWQgdGhlIHRvdGFsIG51bWJlciBvZiBjcmltZXMgb24gDQojIGVhY2ggZGF5IG9mIHRoZSB3ZWVrLiBXZSBjYW4gZ2V0IHRoaXMgaW5mb3JtYXRpb24gYnkgY3JlYXRpbmcgYSB0YWJsZToNCnRhYmxlKG12dCRXZWVrZGF5KQ0KDQojIFNhdmUgdGhpcyB0YWJsZSBhcyBhIGRhdGEgZnJhbWU6DQpXZWVrZGF5Q291bnRzID0gYXMuZGF0YS5mcmFtZSh0YWJsZShtdnQkV2Vla2RheSkpDQpzdHIoV2Vla2RheUNvdW50cykgDQpgYGANCg0KIyMjIyMgNy4yLjMg57Ch5Zau57ea5ZyWDQpgYGB7cn0NCiMgTG9hZCB0aGUgZ2dwbG90MiBsaWJyYXJ5Og0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KFdlZWtkYXlDb3VudHMsIGFlcyh4PVZhcjEsIHk9RnJlcSkpICsgDQogIGdlb21fbGluZShhZXMoZ3JvdXA9MSkpICAjVGhpcyBqdXN0IGdyb3VwcyBhbGwgb2Ygb3VyIGRhdGEgaW50byBvbmUgbGluZSxzaW5jZSB3ZSB3YW50IG9uZSBsaW5lIGluIG91ciBwbG90Lg0KYGBgDQoNCiMjIyMjIDcuMi40IOaYn+acn+mhnuWIpemghuW6jw0KYGBge3J9DQojIE1ha2UgdGhlICJWYXIxIiB2YXJpYWJsZSBhbiBPUkRFUkVEIGZhY3RvciB2YXJpYWJsZQ0KV2Vla2RheUNvdW50cyRWYXIxID0gZmFjdG9yKFdlZWtkYXlDb3VudHMkVmFyMSwgb3JkZXJlZD1UUlVFLCANCiAgbGV2ZWxzPWMoIlN1bmRheSIsICJNb25kYXkiLCAiVHVlc2RheSIsICJXZWRuZXNkYXkiLCAiVGh1cnNkYXkiLCANCiAgICAgICAgICAgIkZyaWRheSIsIlNhdHVyZGF5IikpICAgI+acg+aMieeFp+mAmeWAi+mghuW6j+eVqw0KDQojIFRyeSBhZ2FpbjoNCmdncGxvdChXZWVrZGF5Q291bnRzLCBhZXMoeD1WYXIxLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpKQ0KYGBgDQoNCiMjIyMjIDcuMi41IOaUueiuiljjgIFZ6Lu45qiZ6aGMDQpgYGB7cn0NCiMgQ2hhbmdlIG91ciB4IGFuZCB5IGxhYmVsczoNCmdncGxvdChXZWVrZGF5Q291bnRzLCBhZXMoeD1WYXIxLCB5PUZyZXEpKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPTEpLCBhbHBoYT0wLjMpICsgDQogIHhsYWIoIkRheSBvZiB0aGUgV2VlayIpICsgeWxhYigiVG90YWwgTW90b3IgVmVoaWNsZSBUaGVmdHMiKQ0KYGBgDQoNCiMjIyMjIDcuMi41IOS4g+WkqeOAgTI05bCP5pmCDQpgYGB7cn0NCiMgVklERU8gNCAtIEFkZGluZyB0aGUgSG91ciBvZiB0aGUgRGF5DQojIENyZWF0ZSBhIGNvdW50cyB0YWJsZSBmb3IgdGhlIHdlZWtkYXkgYW5kIGhvdXI6DQp0YWJsZShtdnQkV2Vla2RheSwgbXZ0JEhvdXIpDQoNCiMgU2F2ZSB0aGlzIHRvIGEgZGF0YSBmcmFtZToNCkRheUhvdXJDb3VudHMgPSBhcy5kYXRhLmZyYW1lKHRhYmxlKG12dCRXZWVrZGF5LCBtdnQkSG91cikpDQpzdHIoRGF5SG91ckNvdW50cykNCg0KIyBDb252ZXJ0IHRoZSBzZWNvbmQgdmFyaWFibGUsIFZhcjIsIHRvIG51bWJlcnMgYW5kIGNhbGwgaXQgSG91cjoNCkRheUhvdXJDb3VudHMkSG91ciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKERheUhvdXJDb3VudHMkVmFyMikpDQpgYGANCg0KIyMjIyMgNy4yLjYg55Wr5Ye6IDcgeCAyNCDotqjli6Lnt5rlnJYgDQpgYGB7cn0NCiMgQ3JlYXRlIG91dCBwbG90Og0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4PUhvdXIsIHk9RnJlcSkpICsNCiAgZ2VvbV9saW5lKGFlcyhncm91cD1WYXIxKSkgICNWYXIx5bCx5pivd2Vla2RheQ0KYGBgDQoNCmBgYHtyfQ0KIyBDaGFuZ2UgdGhlIGNvbG9ycw0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4PUhvdXIsIHk9RnJlcSkpICsgDQogIGdlb21fbGluZShhZXMoZ3JvdXA9VmFyMSwgY29sb3I9VmFyMSksIHNpemU9MikNCmBgYA0KDQpgYGB7cn0NCiMg5Y2A5YiG5ZGo5pyr44CB5ZGo6ZaTDQpEYXlIb3VyQ291bnRzJFR5cGUgPSBpZmVsc2UoDQogIChEYXlIb3VyQ291bnRzJFZhcjEgPT0gIlN1bmRheSIpIHwgKERheUhvdXJDb3VudHMkVmFyMSA9PSAiU2F0dXJkYXkiKSwgDQogICJXZWVrZW5kIiwgIldlZWtkYXkiKQ0KDQojIFJlZG8gb3VyIHBsb3QsIHRoaXMgdGltZSBjb2xvcmluZyBieSBUeXBlOg0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4PUhvdXIsIHk9RnJlcSkpICsgDQogIGdlb21fbGluZShhZXMoZ3JvdXA9VmFyMSwgY29sb3I9VHlwZSksIHNpemU9MikgDQpgYGANCg0KYGBge3J9DQojIE1ha2UgdGhlIGxpbmVzIGEgbGl0dGxlIHRyYW5zcGFyZW50Og0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4PUhvdXIsIHk9RnJlcSkpICsgDQogIGdlb21fbGluZShhZXMoZ3JvdXA9VmFyMSwgY29sb3I9VHlwZSksIHNpemU9MiwgYWxwaGE9MC41KSAgI2FscGhh6K6K6YCP5piODQpgYGANCg0KIyMjIyMgNy4yLjYg55Wr5Ye6IDcgeCAyNCDnhrHlnJYNCg0KYGBge3J9DQojIOaYn+acn+mhnuWIpemghuW6j+mHjeaVtCAgI1RoZSB4IGFuZCB5LWF4ZXMgaW4gYSBoZWF0IG1hcCBkb24ndCBuZWVkIHRvIGJlIGNvbnRpbnVvdXMuDQpEYXlIb3VyQ291bnRzJFZhcjEgPSBmYWN0b3IoRGF5SG91ckNvdW50cyRWYXIxLCBvcmRlcmVkPVRSVUUsIA0KICBsZXZlbHM9YygiTW9uZGF5IiwgIlR1ZXNkYXkiLCAiV2VkbmVzZGF5IiwgIlRodXJzZGF5IiwgIkZyaWRheSIsIA0KICAgICAgICAgICAiU2F0dXJkYXkiLCAiU3VuZGF5IikpICAjdGhlIHRoaXJkIGFyZ3VtZW50IGlzIHRoZSBvcmRlciB3ZSB3YW50IHRoZSBkYXlzIG9mIHRoZSB3ZWVrIHRvIHNob3cgdXAgaW4uDQoNCiMgTWFrZSBhIGhlYXRtYXA6DQpnZ3Bsb3QoRGF5SG91ckNvdW50cywgYWVzKHggPSBIb3VyLCB5ID0gVmFyMSkpICsgDQogIGdlb21fdGlsZShhZXMoZmlsbCA9IEZyZXEpKSAgI2dlb21fdGlsZeeVq+eGseWclg0KYGBgDQoNCmBgYHtyfQ0KIyBDaGFuZ2UgdGhlIGxhYmVsIG9uIHRoZSBsZWdlbmQsIGFuZCBnZXQgcmlkIG9mIHRoZSB5LWxhYmVsOg0KZ2dwbG90KERheUhvdXJDb3VudHMsIGFlcyh4ID0gSG91ciwgeSA9IFZhcjEpKSArIA0KICBnZW9tX3RpbGUoYWVzKGZpbGwgPSBGcmVxKSkgKyANCiAgc2NhbGVfZmlsbF9ncmFkaWVudChuYW1lPSJUb3RhbCBNViBUaGVmdHMiKSArIA0KICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KYGBge3J9DQojIENoYW5nZSB0aGUgY29sb3Igc2NoZW1lDQpnZ3Bsb3QoRGF5SG91ckNvdW50cywgYWVzKHggPSBIb3VyLCB5ID0gVmFyMSkpICsgDQogIGdlb21fdGlsZShhZXMoZmlsbCA9IEZyZXEpKSArIA0KICBzY2FsZV9maWxsX2dyYWRpZW50KG5hbWU9IlRvdGFsIE1WIFRoZWZ0cyIsIGxvdz0id2hpdGUiLCBoaWdoPSJyZWQiKSArIA0KICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpDQpgYGANCg0KIyMjIyMgNy4yLjcg5LqS5YuV5byP54ax5ZyWDQpgYGB7cn0NCnRhYmxlKGZvcm1hdChtdnQkRGF0ZSwnJUgnKSwgZm9ybWF0KG12dCREYXRlLCcldycpKSU+JSB0ICU+JSANCiAgaGVhdG1hcChOQSxOQSxzY2FsZT0nbm9uZScsY29sPWNtLmNvbG9ycygyNSkpDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIDcuMiDoip3liqDlk6Xmsb3ou4rnq4rmoYjjgIHlnLDlnJblpZfoo70NCg0KIyMjIyMgNy4yLjgg6YCP6YGOIGBtYXBzYCDlkowgYGdnbWFwYCDlpZfku7bmipPlj5blnLDlnJYNCmBgYHtyfQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShnZ21hcCkNCg0KIyBMb2FkIGEgbWFwIG9mIENoaWNhZ28gaW50byBSOg0KY2hpY2FnbyA9IGdldF9tYXAobG9jYXRpb24gPSAiY2hpY2FnbyIsIHpvb20gPSAxMSkgICPlhYjmiorlnLDlnJbmipPkuIvkvoblrZjlnKjkuIDlgIvlnLDmlrkNCg0KIyBMb29rIGF0IHRoZSBtYXANCmNoaWNhZ28gPSBnZ21hcChjaGljYWdvKSAgI2dnbWFw55Wr5Zyw5ZyWDQpjaGljYWdvDQpgYGANCg0KYGBge3J9DQojIOWPr+S7peeVq+mrmOmbhOW4guWXjiA/IA0KZ2dtYXAoZ2V0X21hcChsb2NhdGlvbiA9ICJrYW9oc2l1bmciLCB6b29tID0gMTIpKQ0KYGBgDQoNCiMjIyMjIDcuMi45IOaomeiomOWWruS4gOS6i+S7tg0KYGBge3J9DQojIFBsb3QgdGhlIGZpcnN0IDEwMCBtb3RvciB2ZWhpY2xlIHRoZWZ0czoNCmNoaWNhZ28gKyBnZW9tX3BvaW50KA0KICBkYXRhID0gbXZ0WzE6MTAwLF0sIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpKSAgI+e2k+e3r+W6pg0KYGBgDQoNCiMjIyMjIDcuMi45IOS+neW6p+aomembhuaUtuS6i+S7tg0KYGBge3J9DQojIFJvdW5kIG91ciBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIHRvIDIgZGlnaXRzIG9mIGFjY3VyYWN5LCANCiMgYW5kIGNyZWF0ZSBhIGNyaW1lIGNvdW50cyBkYXRhIGZyYW1lIGZvciBlYWNoIGFyZWE6DQpMYXRMb25Db3VudHMgPSBhcy5kYXRhLmZyYW1lKHRhYmxlKHJvdW5kKG12dCRMb25naXR1ZGUsMiksICAgI+aKiuWwj+aVuOm7njLkvY3ku6XkuIvpm4bmlLbotbfkvoYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQobXZ0JExhdGl0dWRlLDIpKSkNCnN0cihMYXRMb25Db3VudHMpDQoNCiMgQ29udmVydCBvdXIgTG9uZ2l0dWRlIGFuZCBMYXRpdHVkZSB2YXJpYWJsZSB0byBudW1iZXJzOg0KTGF0TG9uQ291bnRzJExvbmcgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihMYXRMb25Db3VudHMkVmFyMSkpDQpMYXRMb25Db3VudHMkTGF0ID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoTGF0TG9uQ291bnRzJFZhcjIpKQ0KDQojIFBsb3QgdGhlc2UgcG9pbnRzIG9uIG91ciBtYXA6DQpjaGljYWdvICsgZ2VvbV9wb2ludChkYXRhID0gTGF0TG9uQ291bnRzLCANCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gTG9uZywgeSA9IExhdCwgY29sb3IgPSBGcmVxLCBzaXplPUZyZXEpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDaGFuZ2UgdGhlIGNvbG9yIHNjaGVtZToNCmNoaWNhZ28gKyBnZW9tX3BvaW50KGRhdGEgPSBMYXRMb25Db3VudHMsIA0KICAgICAgICAgICAgICAgICAgICAgYWVzKHg9TG9uZywgeT1MYXQsIGNvbG9yPUZyZXEsIHNpemU9RnJlcSkpICsgDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudChsb3c9InllbGxvdyIsIGhpZ2g9InJlZCIpDQpgYGANCg0KIyMjIyMgNy4yLjEwIOagvOeLgOWclg0KYGBge3J9DQojIFdlIGNhbiBhbHNvIHVzZSB0aGUgZ2VvbV90aWxlIGdlb21ldHJ5DQpjaGljYWdvICsgZ2VvbV90aWxlKGRhdGEgPSBMYXRMb25Db3VudHMsIA0KICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IExvbmcsIHkgPSBMYXQsIGFscGhhID0gRnJlcSksIA0KICAgICAgICAgICAgICAgICAgICBmaWxsPSJyZWQiKQ0KYGBgDQoNCmBgYHtyfQ0KIyDnp7vpmaTmspLmnInkuovku7bnmoTljYDmoLwoMOeahOa/vuaOiSkNCkxhdExvbkNvdW50czIgPSBzdWJzZXQoTGF0TG9uQ291bnRzLCBGcmVxID4gMCkNCmNoaWNhZ28gKyBnZW9tX3RpbGUoZGF0YSA9IExhdExvbkNvdW50czIsIA0KICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IExvbmcsIHkgPSBMYXQsIGFscGhhID0gRnJlcSksIA0KICAgICAgICAgICAgICAgICAgICBmaWxsPSJyZWQiKQ0KYGBgDQoNCiMjIyMjIDcuMi4xMSDkuovku7blr4bluqblnJYNCmBgYHtyfQ0KIyBkZW5zaXR5IHBsb3QNCmNoaWNhZ28gKyBzdGF0X2RlbnNpdHlfMmQoZGF0YT1tdnQsIA0KICAgIGFlcyh4PUxvbmdpdHVkZSwgeT1MYXRpdHVkZSwgYWxwaGE9Li5sZXZlbC4uKSwgDQogICAgZmlsbD0nb3JhbmdlJywgY29sb3I9J3BpbmsnLCBzaXplPTAuMDEsIGJpbnM9OCwgZ2VvbT0ncG9seWdvbicpICsNCiAgc2NhbGVfYWxwaGEocmFuZ2UgPSBjKDAuMDUsIDAuNDUpKQ0KYGBgDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyA3LjIg5qeN5p6d5oyB5pyJ546H6IiH6KyA5q665q+U546HDQoNCmBgYHtyfQ0KIyBWSURFTyA2IC0gR2VvZ3JhcGhpY2FsIE1hcCBvbiBVUw0KIyBMb2FkIG91ciBkYXRhOg0KbXVyZGVycyA9IHJlYWQuY3N2KCJkYXRhL211cmRlcnMuY3N2IikNCnN0cihtdXJkZXJzKQ0KYGBgDQoNCiMjIyMjIDcuMi4xMiBSZWFkIGFuZCBQbG90IFVTIE1hcA0KYGBge3J9DQojIExvYWQgdGhlIG1hcCBvZiB0aGUgVVMgICAgDQpzdGF0ZXNNYXAgPSBtYXBfZGF0YSgic3RhdGUiKSAgI21hcF9kYXRhKCJzdGF0ZSIp5bCH6KGM5pS/5bee55WM5ZyW5oqT5LiL5L6GDQpzdHIoc3RhdGVzTWFwKQ0KDQojIFBsb3QgdGhlIG1hcDoNCmdncGxvdChzdGF0ZXNNYXAsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCkpICsgDQogIGdlb21fcG9seWdvbihmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSANCg0KYGBgDQoNCiMjIyMjIDcuMi4xMyBNZXJnZSB0aGUgRGF0YWZyYW1lcyAoYHN0YXRlTWFwYCBhbmQgYG11cmRlcnNgKQ0KYGBge3J9DQojIENyZWF0ZSBhIG5ldyB2YXJpYWJsZSBjYWxsZWQgcmVnaW9uIHdpdGggdGhlIGxvd2VyY2FzZSBuYW1lcyB0byANCiMgbWF0Y2ggdGhlIHN0YXRlc01hcDoNCm11cmRlcnMkcmVnaW9uID0gdG9sb3dlcihtdXJkZXJzJFN0YXRlKQ0KDQojIEpvaW4gdGhlIHN0YXRlc01hcCBkYXRhIGFuZCB0aGUgbXVyZGVycyBkYXRhIGludG8gb25lIGRhdGFmcmFtZToNCm11cmRlck1hcCA9IG1lcmdlKHN0YXRlc01hcCwgbXVyZGVycywgYnk9InJlZ2lvbiIpDQpzdHIobXVyZGVyTWFwKSAgIzE1NTM35LmL5omA5Lul5pyD6YKj6bq85aSa5piv5Zug54K65LuW5pyD5oqK5b6I5aSa5YCL5aSa6YKK5b2i5o6l6LW35L6G6K6K5oiQ5bee55WMDQogICAgICAgICAgICAgICAgI2dyb3Vw6KaB5pW055CG77yM5ZCm5YmH6LOH5paZ5LiN6aCG5pyD55Wr5LiN5Ye65L6GDQpgYGANCg0KIyMjIyMgNy4yLjE0IE1hcC0xOiBOby4gTXVyZGVycyBwZXIgU3RhdGUNCmBgYHtyfQ0KIyBQbG90IHRoZSBudW1iZXIgb2YgbXVyZGVyIG9uIG91ciBtYXAgb2YgdGhlIFVuaXRlZCBTdGF0ZXM6DQpnZ3Bsb3QobXVyZGVyTWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBNdXJkZXJzKSkgKyANCiAgZ2VvbV9wb2x5Z29uKGNvbG9yID0gImJsYWNrIikgKyANCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmxhY2siLCBoaWdoID0gInJlZCIsIGd1aWRlID0gImxlZ2VuZCIpDQpgYGANCg0KIyMjIyMgNy4yLjE1IE1hcC0yOiBQb3B1bGF0aW9ucyBwZXIgU3RhdGUNCmBgYHtyfQ0KIyBQbG90IGEgbWFwIG9mIHRoZSBwb3B1bGF0aW9uOg0KZ2dwbG90KG11cmRlck1hcCwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gUG9wdWxhdGlvbikpICsgDQogIGdlb21fcG9seWdvbihjb2xvciA9ICJibGFjayIpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiLCBndWlkZSA9ICJsZWdlbmQiKQ0KYGBgDQoNCiMjIyMjIDcuMi4xNiBNYXAtMzogTm8uIE11cmRlcnMgcGVyIDEwMEsgUG9wdWxhdGlvbg0KYGBge3J9DQojIENyZWF0ZSBhIG5ldyB2YXJpYWJsZSB0aGF0IGlzIHRoZSBudW1iZXIgb2YgbXVyZGVycyBwZXIgMTAwLDAwMCBwb3B1bGF0aW9uOg0KbXVyZGVyTWFwJE11cmRlclJhdGUgPSBtdXJkZXJNYXAkTXVyZGVycyAvIG11cmRlck1hcCRQb3B1bGF0aW9uICogMTAwMDAwDQoNCiMgUmVkbyBvdXIgcGxvdCB3aXRoIG11cmRlciByYXRlOg0KZ2dwbG90KG11cmRlck1hcCwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gTXVyZGVyUmF0ZSkpICsgDQogIGdlb21fcG9seWdvbihjb2xvciA9ICJibGFjayIpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsYWNrIiwgaGlnaCA9ICJyZWQiLCBndWlkZSA9ICJsZWdlbmQiKQ0KYGBgDQoNCiMjIyMjIDcuMi4xNyBNYXAtNDogTm8uIE11cmRlcnMgcGVyIDEwMEsgUG9wdWxhdGlvbiB3aXRoIEZpbHRlcg0KYGBge3J9DQojIFJlZG8gdGhlIHBsb3QsIENhcCB0aGUgTXVyZGVycmF0ZSBhdCAxMDoNCmdncGxvdChtdXJkZXJNYXAsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IE11cmRlclJhdGUpKSArIA0KICBnZW9tX3BvbHlnb24oY29sb3IgPSAiYmxhY2siKSArIA0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAicmVkIiwgDQogICAgICAgICAgICAgICAgICAgICAgZ3VpZGUgPSAibGVnZW5kIiwgbGltaXRzID0gYygwLDEwKSkNCmBgYA0KDQojIyMjIyA3LjIuMTggTWFwLTU6IEd1biBPd25lcnNoaXAgKCUpIGJ5IFN0YXRlcw0KYGBge3J9DQpnZ3Bsb3QobXVyZGVyTWFwLGFlcyh4PWxvbmcseT1sYXQsZ3JvdXA9Z3JvdXAsZmlsbD1HdW5Pd25lcnNoaXApKSArIA0KICBnZW9tX3BvbHlnb24oY29sb3IgPSAiYmxhY2siKSArIA0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJibGFjayIsIGhpZ2ggPSAicmVkIiwgZ3VpZGUgPSAibGVnZW5kIikNCmBgYA0KDQojIyMjIyA3LjIuMTkgR3VuIE93bmVyc2hpcCAoJSkgYnkgU3RhdGVzDQpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD0zLjJ9DQp0YXBwbHkobXVyZGVyTWFwJEd1bk93bmVyc2hpcCwgbXVyZGVyTWFwJHJlZ2lvbiwgbWVhbikgJT4lIHNvcnQgJT4lIA0KICBiYXJwbG90KGxhcz0yLCBjZXgubmFtZXM9MC42LCBtYWluPSJBdmVyZ2UgR3VuT3duZXJTaGlwICglKSIpDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KPGJyPjxicj48YnI+PGJyPjxicj4NCg0KPHN0eWxlPg0KLmNhcHRpb24gew0KICBjb2xvcjogIzc3NzsNCiAgbWFyZ2luLXRvcDogMTBweDsNCn0NCnAgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBpbmhlcml0Ow0KfQ0KcHJlIHsNCiAgd29yZC1icmVhazogbm9ybWFsOw0KICB3b3JkLXdyYXA6IG5vcm1hbDsNCiAgbGluZS1oZWlnaHQ6IDE7DQp9DQpwcmUgY29kZSB7DQogIHdoaXRlLXNwYWNlOiBpbmhlcml0Ow0KfQ0KcCxsaSB7DQogIGZvbnQtZmFtaWx5OiAiVHJlYnVjaGV0IE1TIiwgIuW+rui7n+ato+m7kemrlCIsICJNaWNyb3NvZnQgSmhlbmdIZWkiOw0KfQ0KDQoucnsNCiAgbGluZS1oZWlnaHQ6IDEuMjsNCn0NCg0KdGl0bGV7DQogIGNvbG9yOiAjY2MwMDAwOw0KICBmb250LWZhbWlseTogIlRyZWJ1Y2hldCBNUyIsICLlvq7ou5/mraPpu5Hpq5QiLCAiTWljcm9zb2Z0IEpoZW5nSGVpIjsNCn0NCg0KYm9keXsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmgxLGgyLGgzLGg0LGg1ew0KICBjb2xvcjogIzAwODgwMDsNCiAgZm9udC1mYW1pbHk6ICJUcmVidWNoZXQgTVMiLCAi5b6u6Luf5q2j6buR6auUIiwgIk1pY3Jvc29mdCBKaGVuZ0hlaSI7DQp9DQoNCmgzew0KICBjb2xvcjogI2IzNmIwMDsNCiAgYmFja2dyb3VuZDogI2ZmZTBiMzsNCiAgbGluZS1oZWlnaHQ6IDI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KDQpoNXsNCiAgY29sb3I6ICMwMDYwMDA7DQogIGJhY2tncm91bmQ6ICNmZmZmZTA7DQogIGxpbmUtaGVpZ2h0OiAyOw0KICBmb250LXdlaWdodDogYm9sZDsNCn0NCg0KZW17DQogIGNvbG9yOiAjMDAwMGMwOw0KICBiYWNrZ3JvdW5kOiAjZjBmMGYwOw0KICB9DQo8L3N0eWxlPg0KDQo=