Interactive Maps
# Load packages
library(rgdal)
library(dplyr)
library(ggmap)
library(leaflet)
library(RColorBrewer)
# Set working directory
#### Import Data ####
# Options
options(stringsAsFactors = F)
# Geocoded ANC site data
ANC2012 <- read.csv("ANC2012_geocoded.csv")
# Provinces shapefile
provinces_shp <- readOGR("zwe_polbnda_adm1_250k_cso.shp")
Below is a screenshot of a map of HIV prevalence that I found in the 2015 DHS HIV Fact Sheet, a PDF. Let’s make these data map-able by adding the prevalence as a variable in our provinces shapefile’s data frame.
#### Add HIV prevalence data to provinces ####
# First check the ordering of provinces in the shapefile
provinces_shp$PROVINCE
# Now create a list of the HIV prevalence for each province, in the order above
HIVprev <- c(0.18, 0.22, 0.11, 0.12, 0.13, 0.15, 0.14, 0.13, 0.15, 0.14)
# Check that prevalence matches correct province
cbind(provinces_shp@data, HIVprev)
# Assign HIVprev as a new column in the provinces data
provinces_shp@data <- cbind(provinces_shp@data, HIVprev)
provinces_shp@data # See that provinces_shp now has an HIVprev variable
Interactive Points
#### Point Data ####
# Create a Widget of the ANC data on a map
leaflet(ANC2012) %>% addProviderTiles(providers$OpenStreetMap) %>% addMarkers()
# Represent the ANC data as circles
leaflet(ANC2012) %>% addProviderTiles(providers$OpenStreetMap) %>% addCircles(label = ~site)
# Represent the ANC data with Circle Markers
leaflet(ANC2012) %>% addProviderTiles(providers$OpenStreetMap) %>%
addCircleMarkers(radius = ~prevalence,
color = c("red"),
label = ~as.character(prevalence),
popup = ~paste0("<b>", name,"</b>", "<br>",
"ANC HIV Prevalence: ", prevalence, "%"
)
)
Interactive Polygons
Now let’s experiment with the province polygons.
#### Polygon Data ####
# Try out the provinces
leaflet(provinces_shp) %>% addPolygons(color = "blue", label = ~PROVINCE)
# Map of HIV prevalence
leaflet(provinces_shp) %>%
addPolygons(color = c("grey"), weight = 1, smoothFactor = 0.5,
fillColor = ~colorQuantile("YlOrRd", HIVprev)(HIVprev),
opacity = 1.0, fillOpacity = 0.5,
label = ~as.character(HIVprev),
popup = ~PROVINCE
)
# Change to equal interval, format to %, add legend
pal <- colorBin("Reds", provinces_shp$HIVprev*100, bins=4, pretty=F)
leaflet(provinces_shp) %>%
addPolygons(color = c("grey"), weight = 0.5, smoothFactor = 0.5,
fillColor = ~pal(HIVprev*100),
opacity = 1.0, fillOpacity = 0.7,
label = ~paste0(PROVINCE, ": ", HIVprev*100, "%"),
popup = ~paste0("<b>", PROVINCE, "</b>", "<br>",
"HIV Prevalence: ", HIVprev*100, "%"),
highlightOptions = highlightOptions(color = "white",
weight = 2,
bringToFront = TRUE)
) %>%
addLegend("bottomleft", pal = pal, values = ~HIVprev*100, opacity = 0.7,
title = "HIV Prevalence (2015)",
labFormat = labelFormat(suffix = "%")
)
Layers Control
map <- leaflet(ANC2012) %>%
# Base groups
addProviderTiles(providers$CartoDB) %>%
# Overlay groups
addPolygons(data = provinces_shp, color = c("grey"),
weight = 0.5, smoothFactor = 0.5,
fillColor = ~pal(HIVprev*100),
opacity = 1.0, fillOpacity = 0.7,
label = ~paste0(PROVINCE, ": ", HIVprev*100, "%"),
popup = ~paste0("<b>", PROVINCE, "</b>", "<br>",
"HIV Prevalence: ", HIVprev*100, "%"),
highlightOptions = highlightOptions(color = "white",
weight = 2,
bringToFront = F),
group = "Provinces") %>%
addCircleMarkers(~lon, ~lat, radius = ~prevalence,
color = c("black"), stroke = F, fillOpacity = 0.5,
label = ~paste0(site, ": ", prevalence, "%"),
popup = ~paste0("<b>", name, "</b>", "<br>",
"ANC HIV Prevalence: ", prevalence, "%"),
group = "ANC Sites") %>%
# Layers control
addLayersControl(
overlayGroups = c("ANC Sites", "Provinces"),
options = layersControlOptions(collapsed = FALSE)
)
# Render the "map" Widget
map
An Interactive HIV Map
#view the distribution of HIV prevalence for sites and provinces
summary(ANC2012$prevalence)
summary(provinces_shp$HIVprev)
#create a common color palette for sites and provinces
palette <- "OrRd"
range <- range(7.1,26)
cuts <- c(7.10,13,16,19,26)
pal <- colorBin(palette = palette, domain = range, bins = cuts)
# create the map
map <- leaflet(ANC2012) %>%
# Base groups
addProviderTiles(providers$CartoDB, group = "Canvas") %>%
addProviderTiles(providers$OpenStreetMap, group = "Features") %>%
addProviderTiles(providers$Esri.WorldImagery, group = "Satellite") %>%
# Overlay groups
addPolygons(data = provinces_shp, color = "grey", opacity = 1.0,
weight = 0.5, smoothFactor = 0.5,
fillColor = ~pal(HIVprev*100), fillOpacity = 0.8,
label = ~paste0(PROVINCE,": ", HIVprev*100, "%"),
popup = ~paste0("<b>", PROVINCE,"</b>", "<br>",
"HIV Prevalence: ", HIVprev*100, "%"),
highlightOptions = highlightOptions(color = "grey", weight = 2,
bringToFront = F),
group = "HIV Prevalence by Province (DHS, 2015)"
) %>%
addCircleMarkers(~lon, ~lat, radius = ~prevalence, color = "grey", weight = 1.5,
fillColor = ~pal(prevalence), opacity = 1.0, fillOpacity = 0.8,
label = ~paste0(site, ": ", prevalence, "%"),
popup = ~paste0("<b>", name,"</b>", "<br>",
"Setting: ", classification, "<br>",
"<u>", "HIV among ANC clients, 2012", "</u>", "<br>",
"Total women tested: ", tested.total, "<br>",
"Number tested positive: ", tested.positive, "<br>",
"Prevalence: ", prevalence, "% (CI: ",
prev.ci_lower, "-", prev.ci_upper, ")", "<br>",
"<u>", "Residence of ANC clients", "</u>", "<br>",
"Farm: ", res.farm_pct, "%", "<br>",
"Growth point: ", res.growthpt_pct,"%", "<br>",
"Mine: ", res.mine_pct,"%", "<br>",
"Rural: ", res.rural_pct,"%", "<br>",
"Town or City: ", res.urban_pct, "%"
),
group = "HIV Prevalence by ANC Sentinel Site (2012)") %>%
addLegend(position = "bottomleft", pal = pal, values = ~prevalence, opacity = 0.8,
title = "HIV Prevalence", labFormat = labelFormat(suffix = "%")
) %>%
# Layers control
addLayersControl(
overlayGroups = c("HIV Prevalence by ANC Sentinel Site (2012)",
"HIV Prevalence by Province (DHS, 2015)"),
baseGroups = c("Canvas", "Features", "Satellite"),
options = layersControlOptions(collapsed = TRUE)
)
map
View full screen! Click on the sites and provinces to see additional data!
Exporting to HTML
You can export your interactive map as an HTML document that can be opened outside of R. This can be shared with colleagues, for example via email, without being posted on the internet. The file will open in a web browser, but does not require an internet connection. It can only be viewed be people with access to the HTML file on their computer.
# Save as an HTML file for viewing outside R
library(htmlwidgets)
saveWidget(map, file="Zim_HIV_map.html")
If you open your Spatial Workshop folder, you will see the Zim_HIV_map.html
file has been saved there. Double-click on the file to open it in a web browser.
<< Workshop Home
LS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byBNYXBwaW5nIFNwYXRpYWwgRGF0YSBpbiBSIg0Kc3VidGl0bGU6ICJQYXJ0IDU6IEludGVyYWN0aXZlIE1hcHMiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UgDQogICAgdGhlbWU6IGx1bWVuDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UgDQogICAgdGhlbWU6IGx1bWVuDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZSAgDQoNCi0tLQ0KICANCmBgYHtjc3N9DQpjb2RlIHsNCiAgd2hpdGUtc3BhY2U6IHByZSAhaW1wb3J0YW50Ow0KICBvdmVyZmxvdy14OiBzY3JvbGwgIWltcG9ydGFudDsNCiAgd29yZC1icmVhazoga2VlcC1hbGwgIWltcG9ydGFudDsNCiAgd29yZC13cmFwOiBpbml0aWFsICFpbXBvcnRhbnQ7DQp9DQpib2R5eyAvKiBOb3JtYWwgICovDQogICAgICBmb250LXNpemU6IDE2cHg7DQogIH0NCg0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFKQ0Kb3B0aW9ucyh3aWR0aD01MDApDQoNCmBgYA0KDQoNClsqKjw8IFdvcmtzaG9wIEhvbWUqKl0oaHR0cHM6Ly9jYWZhaGV5LmdpdGh1Yi5pby9zcGF0aWFsKQ0KDQoNCg0KIyBJbnRlcmFjdGl2ZSBNYXBzDQoNCmBgYHtyfQ0KIyBMb2FkIHBhY2thZ2VzDQpsaWJyYXJ5KHJnZGFsKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dtYXApDQpsaWJyYXJ5KGxlYWZsZXQpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCg0KIyBTZXQgd29ya2luZyBkaXJlY3RvcnkNCmBgYA0KDQpgYGB7cn0NCiMjIyMgSW1wb3J0IERhdGEgIyMjIw0KDQojIE9wdGlvbnMNCm9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQoNCiMgR2VvY29kZWQgQU5DIHNpdGUgZGF0YQ0KQU5DMjAxMiA8LSByZWFkLmNzdigiQU5DMjAxMl9nZW9jb2RlZC5jc3YiKQ0KDQojIFByb3ZpbmNlcyBzaGFwZWZpbGUNCnByb3ZpbmNlc19zaHAgPC0gcmVhZE9HUigiendlX3BvbGJuZGFfYWRtMV8yNTBrX2Nzby5zaHAiKQ0KYGBgDQoNCkJlbG93IGlzIGEgc2NyZWVuc2hvdCBvZiBhIG1hcCBvZiBISVYgcHJldmFsZW5jZSB0aGF0IEkgZm91bmQgaW4gdGhlIDIwMTUgREhTIEhJViBGYWN0IFNoZWV0LCBhIFBERi4gTGV0J3MgbWFrZSB0aGVzZSBkYXRhIG1hcC1hYmxlIGJ5IGFkZGluZyB0aGUgcHJldmFsZW5jZSBhcyBhIHZhcmlhYmxlIGluIG91ciBwcm92aW5jZXMgc2hhcGVmaWxlJ3MgZGF0YSBmcmFtZS4NCg0KIVtodHRwOi8vZGhzcHJvZ3JhbS5jb20vcHVibGljYXRpb25zL3B1YmxpY2F0aW9uLWhmNTgtaGl2LWZhY3Qtc2hlZXRzLmNmbV0oREhTIDIwMTUgSElWIG1hcC5wbmcpDQoNCg0KYGBge3J9DQojIyMjIEFkZCBISVYgcHJldmFsZW5jZSBkYXRhIHRvIHByb3ZpbmNlcyAjIyMjDQoNCiMgRmlyc3QgY2hlY2sgdGhlIG9yZGVyaW5nIG9mIHByb3ZpbmNlcyBpbiB0aGUgc2hhcGVmaWxlDQpwcm92aW5jZXNfc2hwJFBST1ZJTkNFDQoNCiMgTm93IGNyZWF0ZSBhIGxpc3Qgb2YgdGhlIEhJViBwcmV2YWxlbmNlIGZvciBlYWNoIHByb3ZpbmNlLCBpbiB0aGUgb3JkZXIgYWJvdmUNCkhJVnByZXYgPC0gYygwLjE4LCAwLjIyLCAwLjExLCAwLjEyLCAwLjEzLCAwLjE1LCAwLjE0LCAwLjEzLCAwLjE1LCAwLjE0KQ0KDQojIENoZWNrIHRoYXQgcHJldmFsZW5jZSBtYXRjaGVzIGNvcnJlY3QgcHJvdmluY2UNCmNiaW5kKHByb3ZpbmNlc19zaHBAZGF0YSwgSElWcHJldikNCg0KIyBBc3NpZ24gSElWcHJldiBhcyBhIG5ldyBjb2x1bW4gaW4gdGhlIHByb3ZpbmNlcyBkYXRhDQpwcm92aW5jZXNfc2hwQGRhdGEgPC0gY2JpbmQocHJvdmluY2VzX3NocEBkYXRhLCBISVZwcmV2KQ0KcHJvdmluY2VzX3NocEBkYXRhICMgU2VlIHRoYXQgcHJvdmluY2VzX3NocCBub3cgaGFzIGFuIEhJVnByZXYgdmFyaWFibGUNCmBgYA0KDQoNCiMjTGVhZmxldCBXaWRnZXQNCg0KYGBge3J9DQojIyMjIEludGVyYWN0aXZlIE1hcHMgdXNpbmcgTGVhZmxldCAjIyMjDQoNCiMgUmVhZCB0aGUgUiBEb2N1bWVudGF0aW9uDQo/bGVhZmxldA0KYGBgDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LjQ1fQ0KIyBDcmVhdGUgYSBibGFuayBXaWRnZXQgaW4gdGhlIFZpZXdlciB0YWINCmxlYWZsZXQoKQ0KDQojIENyZWF0ZSBhIFdpZGdldCB3aXRoIGEgbWFwIG9mIHRoZSB3b3JsZA0KbGVhZmxldCgpICU+JSBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRPcGVuU3RyZWV0TWFwKQ0KYGBgDQoNCiMjSW50ZXJhY3RpdmUgUG9pbnRzDQpgYGB7ciwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OC40NX0NCiMjIyMgUG9pbnQgRGF0YSAjIyMjDQoNCiMgQ3JlYXRlIGEgV2lkZ2V0IG9mIHRoZSBBTkMgZGF0YSBvbiBhIG1hcA0KbGVhZmxldChBTkMyMDEyKSAlPiUgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkT3BlblN0cmVldE1hcCkgJT4lIGFkZE1hcmtlcnMoKQ0KDQojIFJlcHJlc2VudCB0aGUgQU5DIGRhdGEgYXMgY2lyY2xlcw0KbGVhZmxldChBTkMyMDEyKSAlPiUgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkT3BlblN0cmVldE1hcCkgJT4lIGFkZENpcmNsZXMobGFiZWwgPSB+c2l0ZSkNCg0KIyBSZXByZXNlbnQgdGhlIEFOQyBkYXRhIHdpdGggQ2lyY2xlIE1hcmtlcnMNCmxlYWZsZXQoQU5DMjAxMikgJT4lIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJE9wZW5TdHJlZXRNYXApICU+JQ0KICBhZGRDaXJjbGVNYXJrZXJzKHJhZGl1cyA9IH5wcmV2YWxlbmNlLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gYygicmVkIiksDQogICAgICAgICAgICAgICAgICAgbGFiZWwgPSB+YXMuY2hhcmFjdGVyKHByZXZhbGVuY2UpLA0KICAgICAgICAgICAgICAgICAgIHBvcHVwID0gfnBhc3RlMCgiPGI+IiwgbmFtZSwiPC9iPiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFOQyBISVYgUHJldmFsZW5jZTogIiwgcHJldmFsZW5jZSwgIiUiDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCiAgICAgICAgICAgICAgICAgICApDQpgYGANCg0KIyNJbnRlcmFjdGl2ZSBQb2x5Z29ucw0KDQpOb3cgbGV0J3MgZXhwZXJpbWVudCB3aXRoIHRoZSBwcm92aW5jZSBwb2x5Z29ucy4NCg0KYGBge3IsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTguNDV9DQoNCiMjIyMgUG9seWdvbiBEYXRhICMjIyMNCg0KIyBUcnkgb3V0IHRoZSBwcm92aW5jZXMNCmxlYWZsZXQocHJvdmluY2VzX3NocCkgJT4lIGFkZFBvbHlnb25zKGNvbG9yID0gImJsdWUiLCBsYWJlbCA9IH5QUk9WSU5DRSkNCg0KIyBNYXAgb2YgSElWIHByZXZhbGVuY2UNCmxlYWZsZXQocHJvdmluY2VzX3NocCkgJT4lDQogIGFkZFBvbHlnb25zKGNvbG9yID0gYygiZ3JleSIpLCB3ZWlnaHQgPSAxLCBzbW9vdGhGYWN0b3IgPSAwLjUsDQogICAgICAgICAgICAgIGZpbGxDb2xvciA9IH5jb2xvclF1YW50aWxlKCJZbE9yUmQiLCBISVZwcmV2KShISVZwcmV2KSwNCiAgICAgICAgICAgICAgb3BhY2l0eSA9IDEuMCwgZmlsbE9wYWNpdHkgPSAwLjUsDQogICAgICAgICAgICAgIGxhYmVsID0gfmFzLmNoYXJhY3RlcihISVZwcmV2KSwNCiAgICAgICAgICAgICAgcG9wdXAgPSB+UFJPVklOQ0UNCiAgICAgICAgICAgICAgKQ0KDQojIENoYW5nZSB0byBlcXVhbCBpbnRlcnZhbCwgZm9ybWF0IHRvICUsIGFkZCBsZWdlbmQNCnBhbCA8LSBjb2xvckJpbigiUmVkcyIsIHByb3ZpbmNlc19zaHAkSElWcHJldioxMDAsIGJpbnM9NCwgcHJldHR5PUYpDQoNCmxlYWZsZXQocHJvdmluY2VzX3NocCkgJT4lDQogIGFkZFBvbHlnb25zKGNvbG9yID0gYygiZ3JleSIpLCB3ZWlnaHQgPSAwLjUsIHNtb290aEZhY3RvciA9IDAuNSwNCiAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbChISVZwcmV2KjEwMCksDQogICAgICAgICAgICAgIG9wYWNpdHkgPSAxLjAsIGZpbGxPcGFjaXR5ID0gMC43LA0KICAgICAgICAgICAgICBsYWJlbCA9IH5wYXN0ZTAoUFJPVklOQ0UsICI6ICIsIEhJVnByZXYqMTAwLCAiJSIpLA0KICAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPiIsIFBST1ZJTkNFLCAiPC9iPiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJISVYgUHJldmFsZW5jZTogIiwgSElWcHJldioxMDAsICIlIiksDQogICAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkNCiAgICAgICAgICAgICAgKSAlPiUNCiAgYWRkTGVnZW5kKCJib3R0b21sZWZ0IiwgcGFsID0gcGFsLCB2YWx1ZXMgPSB+SElWcHJldioxMDAsIG9wYWNpdHkgPSAwLjcsDQogICAgICAgICAgICB0aXRsZSA9ICJISVYgUHJldmFsZW5jZSAoMjAxNSkiLA0KICAgICAgICAgICAgbGFiRm9ybWF0ID0gbGFiZWxGb3JtYXQoc3VmZml4ID0gIiUiKQ0KICAgICAgICAgICAgKQ0KYGBgDQoNCiMjTGF5ZXJzIENvbnRyb2wNCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LjQ1fQ0KbWFwIDwtIGxlYWZsZXQoQU5DMjAxMikgJT4lDQogICMgQmFzZSBncm91cHMNCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQikgJT4lDQogICMgT3ZlcmxheSBncm91cHMNCiAgYWRkUG9seWdvbnMoZGF0YSA9IHByb3ZpbmNlc19zaHAsIGNvbG9yID0gYygiZ3JleSIpLA0KICAgICAgICAgICAgICB3ZWlnaHQgPSAwLjUsIHNtb290aEZhY3RvciA9IDAuNSwNCiAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbChISVZwcmV2KjEwMCksDQogICAgICAgICAgICAgIG9wYWNpdHkgPSAxLjAsIGZpbGxPcGFjaXR5ID0gMC43LA0KICAgICAgICAgICAgICBsYWJlbCA9IH5wYXN0ZTAoUFJPVklOQ0UsICI6ICIsIEhJVnByZXYqMTAwLCAiJSIpLA0KICAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPiIsIFBST1ZJTkNFLCAiPC9iPiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJISVYgUHJldmFsZW5jZTogIiwgSElWcHJldioxMDAsICIlIiksDQogICAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJpbmdUb0Zyb250ID0gRiksDQogICAgICAgICAgICAgIGdyb3VwID0gIlByb3ZpbmNlcyIpICU+JQ0KICBhZGRDaXJjbGVNYXJrZXJzKH5sb24sIH5sYXQsIHJhZGl1cyA9IH5wcmV2YWxlbmNlLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gYygiYmxhY2siKSwgc3Ryb2tlID0gRiwgZmlsbE9wYWNpdHkgPSAwLjUsDQogICAgICAgICAgICAgICAgICAgbGFiZWwgPSB+cGFzdGUwKHNpdGUsICI6ICIsIHByZXZhbGVuY2UsICIlIiksDQogICAgICAgICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUwKCI8Yj4iLCBuYW1lLCAiPC9iPiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFOQyBISVYgUHJldmFsZW5jZTogIiwgcHJldmFsZW5jZSwgIiUiKSwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9ICJBTkMgU2l0ZXMiKSAlPiUNCiAgIyBMYXllcnMgY29udHJvbA0KICBhZGRMYXllcnNDb250cm9sKA0KICAgIG92ZXJsYXlHcm91cHMgPSBjKCJBTkMgU2l0ZXMiLCAiUHJvdmluY2VzIiksDQogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKQ0KICAgICkNCg0KIyBSZW5kZXIgdGhlICJtYXAiIFdpZGdldA0KbWFwDQpgYGANCg0KIyNBbiBJbnRlcmFjdGl2ZSBISVYgTWFwDQpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OC40NX0NCiN2aWV3IHRoZSBkaXN0cmlidXRpb24gb2YgSElWIHByZXZhbGVuY2UgZm9yIHNpdGVzIGFuZCBwcm92aW5jZXMNCnN1bW1hcnkoQU5DMjAxMiRwcmV2YWxlbmNlKQ0Kc3VtbWFyeShwcm92aW5jZXNfc2hwJEhJVnByZXYpDQoNCiNjcmVhdGUgYSBjb21tb24gY29sb3IgcGFsZXR0ZSBmb3Igc2l0ZXMgYW5kIHByb3ZpbmNlcw0KcGFsZXR0ZSA8LSAiT3JSZCINCnJhbmdlIDwtIHJhbmdlKDcuMSwyNikNCmN1dHMgPC0gYyg3LjEwLDEzLDE2LDE5LDI2KQ0KcGFsIDwtIGNvbG9yQmluKHBhbGV0dGUgPSBwYWxldHRlLCBkb21haW4gPSByYW5nZSwgYmlucyA9IGN1dHMpDQoNCiMgY3JlYXRlIHRoZSBtYXANCm1hcCA8LSBsZWFmbGV0KEFOQzIwMTIpICU+JQ0KICAjIEJhc2UgZ3JvdXBzDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIsIGdyb3VwID0gIkNhbnZhcyIpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRPcGVuU3RyZWV0TWFwLCBncm91cCA9ICJGZWF0dXJlcyIpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRFc3JpLldvcmxkSW1hZ2VyeSwgZ3JvdXAgPSAiU2F0ZWxsaXRlIikgJT4lDQogICMgT3ZlcmxheSBncm91cHMNCiAgYWRkUG9seWdvbnMoZGF0YSA9IHByb3ZpbmNlc19zaHAsIGNvbG9yID0gImdyZXkiLCBvcGFjaXR5ID0gMS4wLCAgDQogICAgICAgICAgICAgIHdlaWdodCA9IDAuNSwgc21vb3RoRmFjdG9yID0gMC41LA0KICAgICAgICAgICAgICBmaWxsQ29sb3IgPSB+cGFsKEhJVnByZXYqMTAwKSwgZmlsbE9wYWNpdHkgPSAwLjgsDQogICAgICAgICAgICAgIGxhYmVsID0gfnBhc3RlMChQUk9WSU5DRSwiOiAiLCBISVZwcmV2KjEwMCwgIiUiKSwNCiAgICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUwKCI8Yj4iLCBQUk9WSU5DRSwiPC9iPiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJISVYgUHJldmFsZW5jZTogIiwgSElWcHJldioxMDAsICIlIiksDQogICAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImdyZXkiLCB3ZWlnaHQgPSAyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmluZ1RvRnJvbnQgPSBGKSwNCiAgICAgICAgICAgICAgZ3JvdXAgPSAiSElWIFByZXZhbGVuY2UgYnkgUHJvdmluY2UgKERIUywgMjAxNSkiDQogICkgJT4lDQogIGFkZENpcmNsZU1hcmtlcnMofmxvbiwgfmxhdCwgcmFkaXVzID0gfnByZXZhbGVuY2UsIGNvbG9yID0gImdyZXkiLCB3ZWlnaHQgPSAxLjUsDQogICAgICAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbChwcmV2YWxlbmNlKSwgb3BhY2l0eSA9IDEuMCwgZmlsbE9wYWNpdHkgPSAwLjgsDQogICAgICAgICAgICAgICAgICAgbGFiZWwgPSB+cGFzdGUwKHNpdGUsICI6ICIsIHByZXZhbGVuY2UsICIlIiksDQogICAgICAgICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUwKCI8Yj4iLCBuYW1lLCI8L2I+IiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2V0dGluZzogIiwgY2xhc3NpZmljYXRpb24sICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjx1PiIsICJISVYgYW1vbmcgQU5DIGNsaWVudHMsIDIwMTIiLCAiPC91PiIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRvdGFsIHdvbWVuIHRlc3RlZDogIiwgdGVzdGVkLnRvdGFsLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOdW1iZXIgdGVzdGVkIHBvc2l0aXZlOiAiLCB0ZXN0ZWQucG9zaXRpdmUsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByZXZhbGVuY2U6ICIsIHByZXZhbGVuY2UsICIlIChDSTogIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2LmNpX2xvd2VyLCAiLSIsIHByZXYuY2lfdXBwZXIsICIpIiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPHU+IiwgIlJlc2lkZW5jZSBvZiBBTkMgY2xpZW50cyIsICI8L3U+IiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFybTogIiwgcmVzLmZhcm1fcGN0LCAiJSIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3d0aCBwb2ludDogIiwgcmVzLmdyb3d0aHB0X3BjdCwiJSIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1pbmU6ICIsIHJlcy5taW5lX3BjdCwiJSIsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJ1cmFsOiAiLCByZXMucnVyYWxfcGN0LCIlIiwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVG93biBvciBDaXR5OiAiLCByZXMudXJiYW5fcGN0LCAiJSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9ICJISVYgUHJldmFsZW5jZSBieSBBTkMgU2VudGluZWwgU2l0ZSAoMjAxMikiKSAlPiUNCiAgYWRkTGVnZW5kKHBvc2l0aW9uID0gImJvdHRvbWxlZnQiLCBwYWwgPSBwYWwsIHZhbHVlcyA9IH5wcmV2YWxlbmNlLCBvcGFjaXR5ID0gMC44LA0KICAgICAgICAgICAgdGl0bGUgPSAiSElWIFByZXZhbGVuY2UiLCBsYWJGb3JtYXQgPSBsYWJlbEZvcm1hdChzdWZmaXggPSAiJSIpDQogICAgICAgICAgICApICU+JQ0KIyBMYXllcnMgY29udHJvbA0KICBhZGRMYXllcnNDb250cm9sKA0KICAgIG92ZXJsYXlHcm91cHMgPSBjKCJISVYgUHJldmFsZW5jZSBieSBBTkMgU2VudGluZWwgU2l0ZSAoMjAxMikiLA0KICAgICAgICAgICAgICAgICAgICAgICJISVYgUHJldmFsZW5jZSBieSBQcm92aW5jZSAoREhTLCAyMDE1KSIpLA0KICAgIGJhc2VHcm91cHMgPSBjKCJDYW52YXMiLCAiRmVhdHVyZXMiLCAiU2F0ZWxsaXRlIiksDQogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpDQogICkNCm1hcA0KYGBgDQoNCltWaWV3IGZ1bGwgc2NyZWVuIV0oaHR0cHM6Ly9jYWZhaGV5LmdpdGh1Yi5pby9aaW1fSElWX21hcC5odG1sKQ0KKipDbGljayBvbiB0aGUgc2l0ZXMgYW5kIHByb3ZpbmNlcyB0byBzZWUgYWRkaXRpb25hbCBkYXRhISoqDQoNCiMjRXhwb3J0aW5nICB0byBIVE1MDQpZb3UgY2FuIGV4cG9ydCB5b3VyIGludGVyYWN0aXZlIG1hcCBhcyBhbiBIVE1MIGRvY3VtZW50IHRoYXQgY2FuIGJlIG9wZW5lZCBvdXRzaWRlIG9mIFIuIFRoaXMgY2FuIGJlIHNoYXJlZCB3aXRoIGNvbGxlYWd1ZXMsIGZvciBleGFtcGxlIHZpYSBlbWFpbCwgd2l0aG91dCBiZWluZyBwb3N0ZWQgb24gdGhlIGludGVybmV0LiBUaGUgZmlsZSB3aWxsIG9wZW4gaW4gYSB3ZWIgYnJvd3NlciwgYnV0IGRvZXMgbm90IHJlcXVpcmUgYW4gaW50ZXJuZXQgY29ubmVjdGlvbi4gSXQgY2FuIG9ubHkgYmUgdmlld2VkIGJlIHBlb3BsZSB3aXRoIGFjY2VzcyB0byB0aGUgSFRNTCBmaWxlIG9uIHRoZWlyIGNvbXB1dGVyLg0KDQpgYGB7cn0NCiMgU2F2ZSBhcyBhbiBIVE1MIGZpbGUgZm9yIHZpZXdpbmcgb3V0c2lkZSBSDQpsaWJyYXJ5KGh0bWx3aWRnZXRzKQ0Kc2F2ZVdpZGdldChtYXAsIGZpbGU9IlppbV9ISVZfbWFwLmh0bWwiKQ0KYGBgDQoNCklmIHlvdSBvcGVuIHlvdXIgU3BhdGlhbCBXb3Jrc2hvcCBmb2xkZXIsIHlvdSB3aWxsIHNlZSB0aGUgYFppbV9ISVZfbWFwLmh0bWxgIGZpbGUgaGFzIGJlZW4gc2F2ZWQgdGhlcmUuIERvdWJsZS1jbGljayBvbiB0aGUgZmlsZSB0byBvcGVuIGl0IGluIGEgd2ViIGJyb3dzZXIuDQoNCg0KDQoNClsqKjw8IFdvcmtzaG9wIEhvbWUqKl0oaHR0cHM6Ly9jYWZhaGV5LmdpdGh1Yi5pby9zcGF0aWFsKQ0K