library(tidyverse)
library(sf)
library(tmap)


1 Rudiments

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/Accidentes2006-2010")
Accidents <- st_read("accidentes2006-2010.shp")
Accidents = st_set_crs(Accidents, 32721)

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/afe_estaciones")
Stations <- st_read("afe_estaciones.shp")
Stations <- st_set_crs(Stations, 32721)

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/Vectoriales_2011")
Uruguay <- st_read("ine_depto.shp")
Uruguay <- st_set_crs(Uruguay, 32721)

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/CyclingMontevideoData/v_bi_bicicircuitos")
Bicicircuitos <- st_read("v_bi_bicicircuitos.shp")
tm_shape(Uruguay) + 
  tm_polygons()

Montevideo <- Uruguay %>% filter(NOMBRE=="MONTEVIDEO")
tm_shape(Montevideo) + 
  tm_polygons() +
  tm_shape(Accidents) + tm_bubbles()

MyMap <- tm_shape(Uruguay) + 
  tm_polygons(col = "deepskyblue1") 

st_bbox(Uruguay)
     xmin      ymin      xmax      ymax 
 366582.2 6127918.5  858252.1 6671738.4 
st_bbox(Montevideo)
     xmin      ymin      xmax      ymax 
 551982.7 6133498.9  589227.2 6159810.3 
tm_shape(Uruguay, bbox = st_bbox(Montevideo)) + 
  tm_polygons(col = "deepskyblue1") 

Nort Carolina SIDS data

nc = st_read(system.file("shape/nc.shp", package="sf"))
Reading layer `nc' from data source `/Library/Frameworks/R.framework/Versions/3.5/Resources/library/sf/shape/nc.shp' using driver `ESRI Shapefile'
Simple feature collection with 100 features and 14 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
epsg (SRID):    4267
proj4string:    +proj=longlat +datum=NAD27 +no_defs



2 The road to a map

tm_shape(nc) + tm_polygons(col="BIR79")
tm_shape(nc) + tm_polygons(col="BIR79") + 
  tm_compass() + tm_scale_bar()

2.1 Legends - tm_layout function

tm_shape(nc) + tm_polygons(col="BIR79") + 
    tm_layout(legend.position = c(0.2,0.03),
              scale=0.8,
              #legend.title.size = 1,
              legend.frame = T)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(title = "THI IS MY TITLE",
              legend.position = c(0.01,0.05),
              scale = 0.9,
              legend.frame = T) + 
   tm_add_legend(type = c("fill"),
                labels = c("Some Area","Other Area"), 
                col = c("#66c2a5","#e5c494"),
                title = "Other Areas") +
  tm_add_legend(type = "symbol", 
                labels = c("A point","Other Point"), 
                col = c("#e78ac3","grey"))

2.2 Where is the south?

But coming back to our map, it needs a compass so your audience know where noth and east are.

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass() 

NA
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "8star") 

NA
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3, show.labels = 0) 

2.3 The scale

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar()

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 2, position = c(0.06,0))

In the documentation In the documentation In the documentation

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 5, color.dark = "darkgreen", color.light = "blue")

MyMap <- tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)
MyMap

2.4 Mode: View

tmap_mode("view")
tmap mode set to interactive viewing
MyMap
Compass not supported in view mode.
legend.postion is used for plot mode. Use view.legend.position in tm_view to set the legend position in view mode.
tmap_mode("plot")
tmap mode set to plotting
UruguayMap <- tm_shape(Uruguay) + 
  tm_polygons()
tmap_leaflet(UruguayMap)

2.5 Colors

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "Blues") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

library(RColorBrewer)
display.brewer.all()

library(RColorBrewer)
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "YlGnBu") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "-YlGnBu") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

summary(nc$BIR79)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    319    1336    2636    4224    4889   30757 

Breaks <- c(0, 2000, 4000, 6000, 31000)
Labels <- c("0 - 2000", "2000 - 4000", "4000 - 6000", ">6000")
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "YlGnBu",
                           breaks = Breaks, labels = Labels) + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

MyPalette <- c("#f2f0f7", "#cbc9e2", "#9e9ac8", "#6a51a3")
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = MyPalette,
                           breaks = Breaks, labels = Labels) + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)



3 Auxiliar map

MontevideoMap <- tm_shape(Montevideo) + 
  tm_polygons() +
  tm_shape(Accidents) + tm_bubbles()
UruguayMap <- tm_shape(Uruguay) + 
  tm_polygons()
library(grid)
MontevideoMap
print(UruguayMap, vp = viewport(0.17, 0.8, width = 0.25, height = 0.25))

MontevideoMap <- tm_shape(Montevideo) + 
  tm_polygons(col = "deepskyblue1") 
MontevideoNeigh <- Uruguay %>% filter(NOMBRE %in% c("SAN JOSE", "CANELONES", "MONTEVIDEO"))
AuxMap <- tm_shape(MontevideoNeigh) + tm_polygons(col = "green")
MontevideoMap
print(AuxMap, vp = viewport(0.17, 0.8, width = 0.2, height = 0.2))

Our map needs some context!

MontevideoBox <- st_bbox(Montevideo) %>% st_as_sf()
Error in UseMethod("st_as_sf") : 
  no applicable method for 'st_as_sf' applied to an object of class "bbox"

AuxMap <- tm_shape(MontevideoNeigh) + tm_polygons(col = "green") + 
  tm_shape(MontevideoBox) + tm_polygons(border.col = "red", lwd = 2.5, alpha = 0.3)
  
MontevideoMap
print(AuxMap, vp = viewport(0.17, 0.8, width = 0.2, height = 0.2))



4 Faceted maps

tm_shape(Montevideo) + tm_polygons() +
  tm_shape(Accidents) + tm_dots(alpha = 0.5) + tm_facets(by = "ANIO")

Accidents2006 <- Accidents %>% filter(ANIO == "2006")
Accidents2010 <- Accidents %>% filter(ANIO == "2010")
Complements <- tm_compass() + tm_scale_bar()
Map2006 <- tm_shape(Accidents2006) + tm_dots() + Complements
Map2010 <- tm_shape(Accidents2010) + tm_dots() + Complements
tmap_arrange(Map2006, Map2010)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKYXV0aG9yOiAiT3JsYW5kbyBTYWJvZ2FsIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdGhlbWU6IHlldGkKICAgIHRvYzogeWVzCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHRtYXApCmBgYAoKPGJyLz4KPGhyLz4KCiNSdWRpbWVudHMKCmBgYHtyfQpzZXR3ZCgifi9Ecm9wYm94L1RlYWNoaW5nL1NwYXRpYWxBbmFseXNpcy1Nb250ZXZpZGVvV29ya3Nob3AyMDE5L05vdGVib29rcy9Nb250ZXZpZGVvX0RhdGEvQWNjaWRlbnRlczIwMDYtMjAxMCIpCkFjY2lkZW50cyA8LSBzdF9yZWFkKCJhY2NpZGVudGVzMjAwNi0yMDEwLnNocCIpCkFjY2lkZW50cyA9IHN0X3NldF9jcnMoQWNjaWRlbnRzLCAzMjcyMSkKCnNldHdkKCJ+L0Ryb3Bib3gvVGVhY2hpbmcvU3BhdGlhbEFuYWx5c2lzLU1vbnRldmlkZW9Xb3Jrc2hvcDIwMTkvTm90ZWJvb2tzL01vbnRldmlkZW9fRGF0YS9hZmVfZXN0YWNpb25lcyIpClN0YXRpb25zIDwtIHN0X3JlYWQoImFmZV9lc3RhY2lvbmVzLnNocCIpClN0YXRpb25zIDwtIHN0X3NldF9jcnMoU3RhdGlvbnMsIDMyNzIxKQoKc2V0d2QoIn4vRHJvcGJveC9UZWFjaGluZy9TcGF0aWFsQW5hbHlzaXMtTW9udGV2aWRlb1dvcmtzaG9wMjAxOS9Ob3RlYm9va3MvTW9udGV2aWRlb19EYXRhL1ZlY3RvcmlhbGVzXzIwMTEiKQpVcnVndWF5IDwtIHN0X3JlYWQoImluZV9kZXB0by5zaHAiKQpVcnVndWF5IDwtIHN0X3NldF9jcnMoVXJ1Z3VheSwgMzI3MjEpCgpzZXR3ZCgifi9Ecm9wYm94L1RlYWNoaW5nL1NwYXRpYWxBbmFseXNpcy1Nb250ZXZpZGVvV29ya3Nob3AyMDE5L05vdGVib29rcy9Nb250ZXZpZGVvX0RhdGEvQ3ljbGluZ01vbnRldmlkZW9EYXRhL3ZfYmlfYmljaWNpcmN1aXRvcyIpCkJpY2ljaXJjdWl0b3MgPC0gc3RfcmVhZCgidl9iaV9iaWNpY2lyY3VpdG9zLnNocCIpCgpgYGAKCmBgYHtyfQp0bV9zaGFwZShVcnVndWF5KSArIAogIHRtX3BvbHlnb25zKCkKYGBgCgpgYGB7cn0KTW9udGV2aWRlbyA8LSBVcnVndWF5ICU+JSBmaWx0ZXIoTk9NQlJFPT0iTU9OVEVWSURFTyIpCmBgYAoKCmBgYHtyfQp0bV9zaGFwZShNb250ZXZpZGVvKSArIAogIHRtX3BvbHlnb25zKCkgKwogIHRtX3NoYXBlKEFjY2lkZW50cykgKyB0bV9idWJibGVzKCkKYGBgCgpgYGB7cn0KTXlNYXAgPC0gdG1fc2hhcGUoVXJ1Z3VheSkgKyAKICB0bV9wb2x5Z29ucyhjb2wgPSAiZGVlcHNreWJsdWUxIikgCmBgYAoKYGBge3J9Ck15TWFwCmBgYAoKCmBgYHtyfQpzdF9iYm94KFVydWd1YXkpCnN0X2Jib3goTW9udGV2aWRlbykKYGBgCgoKYGBge3J9CnRtX3NoYXBlKFVydWd1YXksIGJib3ggPSBzdF9iYm94KE1vbnRldmlkZW8pKSArIAogIHRtX3BvbHlnb25zKGNvbCA9ICJkZWVwc2t5Ymx1ZTEiKSAKYGBgCgoKW05vcnQgQ2Fyb2xpbmEgU0lEUyBkYXRhXShodHRwczovL25vd29zYWQuZ2l0aHViLmlvL3NwRGF0YS9yZWZlcmVuY2UvbmMuc2lkcy5odG1sKQoKYGBge3J9Cm5jID0gc3RfcmVhZChzeXN0ZW0uZmlsZSgic2hhcGUvbmMuc2hwIiwgcGFja2FnZT0ic2YiKSkKYGBgCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIpCmBgYAoKPGJyLz4KPGhyLz4KCiNUaGUgcm9hZCB0byBhIG1hcAoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiKQpgYGAKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IikgKyAKICB0bV9jb21wYXNzKCkgKyB0bV9zY2FsZV9iYXIoKQpgYGAKCiMjIExlZ2VuZHMgLSB0bV9sYXlvdXQgZnVuY3Rpb24KCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMiwwLjAzKSwKICAgICAgICAgICAgICBzY2FsZT0wLjgsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkKYGBgCgoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBUKQpgYGAKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQodGl0bGUgPSAiVEhJIElTIE1ZIFRJVExFIiwKICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC4wNSksCiAgICAgICAgICAgICAgc2NhbGUgPSAwLjksCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkgKyAKICAgdG1fYWRkX2xlZ2VuZCh0eXBlID0gYygiZmlsbCIpLAogICAgICAgICAgICAgICAgbGFiZWxzID0gYygiU29tZSBBcmVhIiwiT3RoZXIgQXJlYSIpLCAKICAgICAgICAgICAgICAgIGNvbCA9IGMoIiM2NmMyYTUiLCIjZTVjNDk0IiksCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJPdGhlciBBcmVhcyIpICsKICB0bV9hZGRfbGVnZW5kKHR5cGUgPSAic3ltYm9sIiwgCiAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJBIHBvaW50IiwiT3RoZXIgUG9pbnQiKSwgCiAgICAgICAgICAgICAgICBjb2wgPSBjKCIjZTc4YWMzIiwiZ3JleSIpKQpgYGAKCgojI1doZXJlIGlzIHRoZSBzb3V0aD8KCkJ1dCBjb21pbmcgYmFjayB0byBvdXIgbWFwLCBpdCBuZWVkcyBhIGNvbXBhc3Mgc28geW91ciBhdWRpZW5jZSBrbm93IHdoZXJlIG5vdGggYW5kIGVhc3QgYXJlLgoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBUKSArIAogICAgdG1fY29tcGFzcygpIAogIApgYGAKCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiKSArIAogICAgdG1fbGF5b3V0KGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wMSwwLjY1KSwKICAgICAgICAgICAgICBzY2FsZT0wLjY1LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQpICsgCiAgICB0bV9jb21wYXNzKHNpemUgPSA1LCB0eXBlID0gIjhzdGFyIikgCiAgCmBgYAoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBUKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMywgc2hvdy5sYWJlbHMgPSAwKSAKYGBgCgoKIyNUaGUgc2NhbGUKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMpICsgCiAgICB0bV9zY2FsZV9iYXIoKQpgYGAKCgoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBUKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAyLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSkKYGBgCgoKCkluIHRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3RtYXAvdmVyc2lvbnMvMi4yL3RvcGljcy90bV9sYXlvdXQpCkluIHRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3RtYXAvdmVyc2lvbnMvMi4yL3RvcGljcy90bV9jb21wYXNzKQpJbiB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy90bWFwL3ZlcnNpb25zLzIuMi90b3BpY3MvdG1fc2NhbGVfYmFyKQoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBUKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAxLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSwKICAgICAgICAgICAgICAgICBsd2QgPSA1LCBjb2xvci5kYXJrID0gImRhcmtncmVlbiIsIGNvbG9yLmxpZ2h0ID0gImJsdWUiKQpgYGAKCmBgYHtyfQpNeU1hcCA8LSB0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCwKICAgICAgICAgICAgICBiZy5jb2xvciA9ICJsaWdodGJsdWUiKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAxLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSwKICAgICAgICAgICAgICAgICBsd2QgPSAzKQoKYGBgCgpgYGB7cn0KTXlNYXAKYGBgCgojI01vZGU6IFZpZXcKCmBgYHtyfQp0bWFwX21vZGUoInZpZXciKQpNeU1hcApgYGAKCgpgYGB7cn0KdG1hcF9tb2RlKCJwbG90IikKYGBgCgoKYGBge3J9ClVydWd1YXlNYXAgPC0gdG1fc2hhcGUoVXJ1Z3VheSkgKyAKICB0bV9wb2x5Z29ucygpCgp0bWFwX2xlYWZsZXQoVXJ1Z3VheU1hcCkKYGBgCgojI0NvbG9ycwoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IiwgcGFsZXR0ZSA9ICJCbHVlcyIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCwKICAgICAgICAgICAgICBiZy5jb2xvciA9ICJsaWdodGJsdWUiKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAxLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSwKICAgICAgICAgICAgICAgICBsd2QgPSAzKQoKYGBgCgpgYGB7cn0KbGlicmFyeShSQ29sb3JCcmV3ZXIpCmRpc3BsYXkuYnJld2VyLmFsbCgpCmBgYAoKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIsIHBhbGV0dGUgPSAiWWxHbkJ1IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBULAogICAgICAgICAgICAgIGJnLmNvbG9yID0gImxpZ2h0Ymx1ZSIpICsgCiAgICB0bV9jb21wYXNzKHNpemUgPSA1LCB0eXBlID0gInJvc2UiLCBsd2QgPSAzKSArIAogICAgdG1fc2NhbGVfYmFyKGJyZWFrcyA9IGMoMCw1MCwxMDAsMTUwLDIwMCksc2l6ZSA9IDEsIHBvc2l0aW9uID0gYygwLjA2LDApLAogICAgICAgICAgICAgICAgIGx3ZCA9IDMpCmBgYAoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IiwgcGFsZXR0ZSA9ICItWWxHbkJ1IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBULAogICAgICAgICAgICAgIGJnLmNvbG9yID0gImxpZ2h0Ymx1ZSIpICsgCiAgICB0bV9jb21wYXNzKHNpemUgPSA1LCB0eXBlID0gInJvc2UiLCBsd2QgPSAzKSArIAogICAgdG1fc2NhbGVfYmFyKGJyZWFrcyA9IGMoMCw1MCwxMDAsMTUwLDIwMCksc2l6ZSA9IDEsIHBvc2l0aW9uID0gYygwLjA2LDApLAogICAgICAgICAgICAgICAgIGx3ZCA9IDMpCmBgYAoKCmBgYHtyfQpzdW1tYXJ5KG5jJEJJUjc5KQpgYGAKCgpgYGB7cn0KbmMgJT4lIGdncGxvdChhZXMoeD1CSVI3OSkpICsgZ2VvbV9oaXN0b2dyYW0oKQpgYGAKCgoKYGBge3J9CkJyZWFrcyA8LSBjKDAsIDIwMDAsIDQwMDAsIDYwMDAsIDMxMDAwKQpMYWJlbHMgPC0gYygiMCAtIDIwMDAiLCAiMjAwMCAtIDQwMDAiLCAiNDAwMCAtIDYwMDAiLCAiPjYwMDAiKQpgYGAKCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiLCBwYWxldHRlID0gIllsR25CdSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IEJyZWFrcywgbGFiZWxzID0gTGFiZWxzKSArIAogICAgdG1fbGF5b3V0KGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wMSwwLjY1KSwKICAgICAgICAgICAgICBzY2FsZT0wLjY1LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQsCiAgICAgICAgICAgICAgYmcuY29sb3IgPSAibGlnaHRibHVlIikgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMpICsgCiAgICB0bV9zY2FsZV9iYXIoYnJlYWtzID0gYygwLDUwLDEwMCwxNTAsMjAwKSxzaXplID0gMSwgcG9zaXRpb24gPSBjKDAuMDYsMCksCiAgICAgICAgICAgICAgICAgbHdkID0gMykKYGBgCgpgYGB7cn0KTXlQYWxldHRlIDwtIGMoIiNmMmYwZjciLCAiI2NiYzllMiIsICIjOWU5YWM4IiwgIiM2YTUxYTMiKQpgYGAKCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiLCBwYWxldHRlID0gTXlQYWxldHRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBCcmVha3MsIGxhYmVscyA9IExhYmVscykgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBULAogICAgICAgICAgICAgIGJnLmNvbG9yID0gImxpZ2h0Ymx1ZSIpICsgCiAgICB0bV9jb21wYXNzKHNpemUgPSA1LCB0eXBlID0gInJvc2UiLCBsd2QgPSAzKSArIAogICAgdG1fc2NhbGVfYmFyKGJyZWFrcyA9IGMoMCw1MCwxMDAsMTUwLDIwMCksc2l6ZSA9IDEsIHBvc2l0aW9uID0gYygwLjA2LDApLAogICAgICAgICAgICAgICAgIGx3ZCA9IDMpCmBgYAoKPGJyLz4KPGhyLz4KCiNBdXhpbGlhciBtYXAKCmBgYHtyfQpNb250ZXZpZGVvTWFwIDwtIHRtX3NoYXBlKE1vbnRldmlkZW8pICsgCiAgdG1fcG9seWdvbnMoKSArCiAgdG1fc2hhcGUoQWNjaWRlbnRzKSArIHRtX2J1YmJsZXMoKQoKVXJ1Z3VheU1hcCA8LSB0bV9zaGFwZShVcnVndWF5KSArIAogIHRtX3BvbHlnb25zKCkKYGBgCgpgYGB7cn0KbGlicmFyeShncmlkKQpgYGAKCgpgYGB7cn0KTW9udGV2aWRlb01hcApwcmludChVcnVndWF5TWFwLCB2cCA9IHZpZXdwb3J0KDAuMTcsIDAuOCwgd2lkdGggPSAwLjI1LCBoZWlnaHQgPSAwLjI1KSkKYGBgCgpgYGB7cn0KTW9udGV2aWRlb01hcCA8LSB0bV9zaGFwZShNb250ZXZpZGVvKSArIAogIHRtX3BvbHlnb25zKGNvbCA9ICJkZWVwc2t5Ymx1ZTEiKSAKCgpNb250ZXZpZGVvTmVpZ2ggPC0gVXJ1Z3VheSAlPiUgZmlsdGVyKE5PTUJSRSAlaW4lIGMoIlNBTiBKT1NFIiwgIkNBTkVMT05FUyIsICJNT05URVZJREVPIikpCgpBdXhNYXAgPC0gdG1fc2hhcGUoTW9udGV2aWRlb05laWdoKSArIHRtX3BvbHlnb25zKGNvbCA9ICJncmVlbiIpCmBgYAoKYGBge3J9Ck1vbnRldmlkZW9NYXAKcHJpbnQoQXV4TWFwLCB2cCA9IHZpZXdwb3J0KDAuMTcsIDAuOCwgd2lkdGggPSAwLjIsIGhlaWdodCA9IDAuMikpCmBgYAoKCk91ciBtYXAgbmVlZHMgc29tZSBjb250ZXh0IQoKYGBge3J9Ck1vbnRldmlkZW9Cb3ggPC0gc3RfYmJveChNb250ZXZpZGVvKSAlPiUgc3RfYXNfc2ZjKCkgI1doeSBub3Qgc3RfYXNfc2Y/CmBgYAoKYGBge3J9CnRtX3NoYXBlKE1vbnRldmlkZW9Cb3gpICsgdG1fcG9seWdvbnMoY29sID0gIndoaXRlIiwgYm9yZGVyLmNvbCA9ICJibHVlIiwgbHdkID0gNCkKI3Bsb3Qoc3RfZ2VvbWV0cnkoTW9udGV2aWRlb0JveCkpCmBgYAoKCmBgYHtyfQoKQXV4TWFwIDwtIHRtX3NoYXBlKE1vbnRldmlkZW9OZWlnaCkgKyB0bV9wb2x5Z29ucyhjb2wgPSAiZ3JlZW4iKSArIAogIHRtX3NoYXBlKE1vbnRldmlkZW9Cb3gpICsgdG1fcG9seWdvbnMoYm9yZGVyLmNvbCA9ICJyZWQiLCBsd2QgPSAyLjUsIGFscGhhID0gMC4zKQogIAoKTW9udGV2aWRlb01hcApwcmludChBdXhNYXAsIHZwID0gdmlld3BvcnQoMC4xNywgMC44LCB3aWR0aCA9IDAuMiwgaGVpZ2h0ID0gMC4yKSkKYGBgCgo8YnIvPgo8aHIvPgoKI0ZhY2V0ZWQgbWFwcwoKYGBge3J9CnRtX3NoYXBlKE1vbnRldmlkZW8pICsgdG1fcG9seWdvbnMoKSArCiAgdG1fc2hhcGUoQWNjaWRlbnRzKSArIHRtX2RvdHMoYWxwaGEgPSAwLjUpICsgdG1fZmFjZXRzKGJ5ID0gIkFOSU8iKQpgYGAKCmBgYHtyfQp0bV9zaGFwZShNb250ZXZpZGVvKSArIHRtX3BvbHlnb25zKCkgKwogIHRtX3NoYXBlKEFjY2lkZW50cykgKyB0bV9kb3RzKGFscGhhID0gMC41KSArIHRtX2ZhY2V0cyhieSA9ICJBTklPIiwgbnJvdyA9IDEpCmBgYAoKYGBge3J9CnRtX3NoYXBlKE1vbnRldmlkZW8pICsgdG1fcG9seWdvbnMoKSArCiAgdG1fc2hhcGUoQWNjaWRlbnRzKSArIHRtX2RvdHMoYWxwaGEgPSAwLjUpICsgdG1fZmFjZXRzKGJ5ID0gIkFOSU8iLCBuY29sID0gMSkKYGBgCgpgYGB7cn0KQWNjaWRlbnRzMjAwNiA8LSBBY2NpZGVudHMgJT4lIGZpbHRlcihBTklPID09ICIyMDA2IikKQWNjaWRlbnRzMjAxMCA8LSBBY2NpZGVudHMgJT4lIGZpbHRlcihBTklPID09ICIyMDEwIikKCkNvbXBsZW1lbnRzIDwtIHRtX2NvbXBhc3MoKSArIHRtX3NjYWxlX2JhcigpCgpNYXAyMDA2IDwtIHRtX3NoYXBlKEFjY2lkZW50czIwMDYpICsgdG1fZG90cygpICsgQ29tcGxlbWVudHMKTWFwMjAxMCA8LSB0bV9zaGFwZShBY2NpZGVudHMyMDEwKSArIHRtX2RvdHMoKSArIENvbXBsZW1lbnRzCmBgYAoKYGBge3J9CnRtYXBfYXJyYW5nZShNYXAyMDA2LCBNYXAyMDEwKQpgYGAK