install.packages(c(tidyverse, sf, tmap, spatstat, maptools, ggplot2, sqldf)) install.packages(“spatstat.geom”, dependencies = TRUE) install.packages(“leaflet.providers”) install.packages(“markdown”, dependencies = TRUE) install.packages(“polyclip”, dependencies = TRUE) install.packages(“ggmap”, dependencies = TRUE)

rdf %>% 
  mutate(birth.year = as.numeric('birth.year')) %>% #THIS CHANGES A STRING INTO A NUMBER
  dplyr::select(-c('birth.year'))  %>%    #THIS DELETES THE OLD COLUMN 
  arrange(birth.year) #THIS SORTS ON BIRTH YEAR
Warning: Problem with `mutate()` column `birth.year`.
ℹ `birth.year = as.numeric("birth.year")`.
ℹ NAs introduced by coercion
Error: arrange() failed at implicit mutate() step. 
* Problem with `mutate()` column `..1`.
ℹ `..1 = birth.year`.
x object 'birth.year' not found
Run `rlang::last_error()` to see where the error occurred.

# Turns it into a gis file
morningStationsGeo <- st_as_sf(morningStations, coords = c("lon", "lat"), dim = "XY", crs = 4326) #crs=coordinate reference system

# Save if you feel like it! # st_write(popularStations, "popularStations.shp", delete_layer = TRUE)

# Look at the map 
tmap_mode('view')
tmap mode set to interactive viewing
tm_shape(morningStationsGeo %>% 
           filter(!is.na(morningtrips)) %>% 
           mutate(morningtrips = as.numeric(morningtrips))) + tm_dots(col = "morningtrips", style="quantile", id = "name")
tm_shape(meStationsGeo %>% 
           filter(!is.na(diff)) %>% 
           mutate(diff = as.numeric(diff))) + tm_dots(col="diff", style="quantile", id = "name")
Variable(s) "diff" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.
######## PART 4 KERNEL DENSITY  ######### 

## Read SF for a file of boroughs
boroughs <- st_read("borough.shp")
Reading layer `borough' from data source 
  `/Users/chaneumpark/OneDrive - Georgia Institute of Technology/2021-Fall/Urban Analytics/R lab session/Assignment2 CitiBike/borough.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 5 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -74.25559 ymin: 40.49612 xmax: -73.70001 ymax: 40.91553
Geodetic CRS:  WGS84(DD)
boroughs_prj <- st_transform(boroughs, crs = 2263)

# Density map (This method doesn't allow us to see the background map)
df.size.proj <- st_transform(morningStationsGeo, crs = 2263)
p.sp <- as(df.size.proj, "Spatial")
p.ppp <- as(p.sp, "ppp")
kernelDensityMorning <- (density(p.ppp, sigma = 1000))

##Plot the two together
plot(kernelDensityMorning, main="Heat Map of Mornign Citibike Origins")
plot(boroughs_prj$geometry, add=TRUE)


##CHALLENGES FOR YOUR DENSITY MAP
##Extra: Clip the raster and clip the vector as well. (only plot the intersection of the two?) 
##Extra: Make the lines white (hint: it is now a polygon!)
##Extra: Add the top 3 (or 5) points and label them.
######## PART 5 GGPLOT EXAMPLE WITH CONTOURS ######### 

# Heatmap in ggplot
library(ggplot2)
library(ggmap)

df.size.degree <- st_transform(morningStationsGeo, crs = 4326) %>% 
  mutate(lat = st_coordinates(.)[,2],
         lon = st_coordinates(.)[,1])

##Get borders
height <- max(st_coordinates(df.size.degree)[,2]) - min(st_coordinates(df.size.degree)[,2])
width <- max(st_coordinates(df.size.degree)[,1]) - min(st_coordinates(df.size.degree)[,1])
  
sac_borders <- c(bottom = min(st_coordinates(df.size.degree)[,2]) - 0.1*height,
                top = max(st_coordinates(df.size.degree)[,2]) + 0.1*height,
                left = min(st_coordinates(df.size.degree)[,1]) - 0.1*width,
                right = max(st_coordinates(df.size.degree)[,1]) + 0.1*width)

map <- get_stamenmap(sac_borders, zoom = 12, maptype = "toner-lite")
Source : http://tile.stamen.com/toner-lite/12/1205/1538.png
Source : http://tile.stamen.com/toner-lite/12/1206/1538.png
Source : http://tile.stamen.com/toner-lite/12/1205/1539.png
Source : http://tile.stamen.com/toner-lite/12/1206/1539.png
Source : http://tile.stamen.com/toner-lite/12/1205/1540.png
Source : http://tile.stamen.com/toner-lite/12/1206/1540.png
Source : http://tile.stamen.com/toner-lite/12/1205/1541.png
Source : http://tile.stamen.com/toner-lite/12/1206/1541.png
ggmap(map) +
  geom_density2d(data = df.size.degree, aes(x = lon, y = lat), size = 0.3) +
  stat_density2d(data = df.size.degree, aes(x = lon, y = lat, fill = ..level.., alpha = ..level..), 
                 geom = "polygon", bins = 10) + 
  scale_fill_gradient(low = "green", high = "red") +
  scale_alpha(range = c(0, 0.4), guide = FALSE) #Plot +
Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please use `guide = "none"` instead.

 coord_cartesian(xlim = c(-74.02, -95.7), 
                  ylim = c(29.5, 30.1))
<ggproto object: Class CoordCartesian, Coord, gg>
    aspect: function
    backtransform_range: function
    clip: on
    default: FALSE
    distance: function
    expand: TRUE
    is_free: function
    is_linear: function
    labels: function
    limits: list
    modify_scales: function
    range: function
    render_axis_h: function
    render_axis_v: function
    render_bg: function
    render_fg: function
    setup_data: function
    setup_layout: function
    setup_panel_guides: function
    setup_panel_params: function
    setup_params: function
    train_panel_guides: function
    transform: function
    super:  <ggproto object: Class CoordCartesian, Coord, gg>
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQppbnN0YWxsLnBhY2thZ2VzKGModGlkeXZlcnNlLCBzZiwgdG1hcCwgc3BhdHN0YXQsIG1hcHRvb2xzLCBnZ3Bsb3QyLCBzcWxkZikpCmluc3RhbGwucGFja2FnZXMoInNwYXRzdGF0Lmdlb20iLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQppbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0LnByb3ZpZGVycyIpCmluc3RhbGwucGFja2FnZXMoIm1hcmtkb3duIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkKaW5zdGFsbC5wYWNrYWdlcygicG9seWNsaXAiLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQppbnN0YWxsLnBhY2thZ2VzKCJnZ21hcCIsIGRlcGVuZGVuY2llcyA9IFRSVUUpCgpgYGB7cn0KIyMjIyMjIyMgUEFSVCAxIFNFVCBVUCAjIyMjIyMjIyMgCgpsaWJyYXJ5KHRpZHl2ZXJzZSkgCmxpYnJhcnkoc2YpCmxpYnJhcnkodG1hcCkKbGlicmFyeShzcGF0c3RhdCkKbGlicmFyeShtYXB0b29scykKbGlicmFyeShzcWxkZikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHNwYXRzdGF0Lmdlb20pCmxpYnJhcnkobGVhZmxldC5wcm92aWRlcnMpCmxpYnJhcnkobWFya2Rvd24pCmxpYnJhcnkocG9seWNsaXApCmxpYnJhcnkoZ2dtYXApCgojIEVudmlyb25tZW50IChjaGFuZ2UgdGhpcyBwYXRoIHRvIHlvdXIgZm9sZGVyIHdoZXJlIHlvdSBzdG9yZWQgdGhlIENJVEkgQmlrZSBkYXRhKQpzZXR3ZCgiL1VzZXJzL2NoYW5ldW1wYXJrL09uZURyaXZlIC0gR2VvcmdpYSBJbnN0aXR1dGUgb2YgVGVjaG5vbG9neS8yMDIxLUZhbGwvVXJiYW4gQW5hbHl0aWNzL1IgbGFiIHNlc3Npb24vQXNzaWdubWVudDIgQ2l0aUJpa2UiKQoKIyMgV2UgZG93bmxvYWRlZCB0aGUgZGF0YSBmcm9tIGhlcmU6IGh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS90cmlwZGF0YS9pbmRleC5odG1sCiMjIFNvbWUgY29kZSB0YWtlbiBmcm9tOiBodHRwOi8vbGFiLnJhZHkudWNzZC5lZHUvc2F3dG9vdGgvYnVzaW5lc3NfYW5hbHl0aWNzX2luX3IvbWFwcy5odG1sCiMjIFRoYW5rcyB0byBCb24gV29vIEtvbyBmb3IgaGlzIGhlbHAuCgojIFJlYWQgZGF0YQpyZGYgPC0gcmVhZC5jc3YoIjIwMTMwNi1jaXRpYmlrZS10cmlwZGF0YS5jc3YiKQpyZGYgPC0gc2FtcGxlX24ocmRmMSwoMzM3MTkqMikpCndyaXRlLmNzdihyZGYsICJjaXRpYmlrZV9zbWFsbHNhbXBsZS5jc3YiKQoKIyBUYWtlIGEgbG9vayBieSBiaXJ0aCB5ZWFyIQpyZGYgJT4lIAogIG11dGF0ZShiaXJ0aC55ZWFyID0gYXMubnVtZXJpYygnYmlydGgueWVhcicpKSAlPiUgI1RISVMgQ0hBTkdFUyBBIFNUUklORyBJTlRPIEEgTlVNQkVSCiAgZHBseXI6OnNlbGVjdCgtYygnYmlydGgueWVhcicpKSAgJT4lICAgICNUSElTIERFTEVURVMgVEhFIE9MRCBDT0xVTU4gCiAgYXJyYW5nZShiaXJ0aC55ZWFyKSAjVEhJUyBTT1JUUyBPTiBCSVJUSCBZRUFSCmBgYAoKYGBge3J9CiMjIyMjIyMjIFBBUlQgMiBFWFBMT1JJTkcgVEhFIERBVEEgIyMjIyMjIyMjIAoKIyBTcGxpdCB0aW1lLCBiaXJ0aCB5ZWFyIGFuZCBmaWx0ZXIgYnkgYmlydGggeWVhcgpyZGZDbGVhbiA8LSByZGYgJT4lIAogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShzdGFydHRpbWUpLAogICAgICAgICB0aW1lID0gZm9ybWF0KGFzLlBPU0lYY3Qoc3RhcnR0aW1lKSwgZm9ybWF0ID0gIiVIOiVNOiVTIikpICU+JSAjIyBTUEVDSUFMIEZPUk1BVFRJTkcgVE8gR0VUIEgsTSxTLgogIG11dGF0ZShob3VyID0gc3Vic3RyaW5nKC4kdGltZSwgZmlyc3QgPSAxLCBsYXN0ID0gMikpICU+JSAjIyBUUlVOQ0FURVMgVEhFIFNUUklORwogIG11dGF0ZShnZW5kZXIgPSBhcy5jaGFyYWN0ZXIoZ2VuZGVyKSkgJT4lICAjIyAgQ0hBTkdFUyBOVU1CRVJTIGludG8gU1RSSU5HUwogIGRwbHlyOjpzZWxlY3QoZGF0ZSwgdGltZSwgaG91ciwgZXZlcnl0aGluZygpKSAlPiUgICMjIFJFT1JERVJTIFRIRSBDT0xVTU5TIAogIGZpbHRlcigiYmlydGhfeWVhciIgPiAxOTMwKSAjIyBLRUVQUyBCSVJUSCBZRUFSUyBBRlRFUiAxOTMwCgoKIyBBZ2dyZWdhdGUgYnkgaG91cgp0cmlwc0J5SG91ciA8LSByZGZDbGVhbiAgJT4lCiAgZ3JvdXBfYnkoYGhvdXJgLCBgZ2VuZGVyYCkgJT4lCiAgc3VtbWFyaXNlKHRyaXBzPW4oKSkgJT4lCiAgbXV0YXRlKGhvdXIgPSBhcy5udW1lcmljKGhvdXIpKQoKI290aGVyIHdheSB0byBkbyBpdCAobWF5IG5vdCByZXR1cm4gaG91ciBhcyBpbnQuLi4pCiN0cmlwc0J5SG91ciA8LSBzcWxkZigic2VsZWN0IGhvdXIsIGdlbmRlciwgY291bnQoaG91cikgYXMgdHJpcHMgZnJvbSByZGZDbGVhbiBncm91cCBieSBob3VyLCBnZW5kZXIiKQoKIyBTZWUgdHJpcHMgYnkgaG91ciAodmVyeSBiYXNpYyBwbG90LS0teW91IGNhbiBhbHNvIHVzZSBhbm90aGVyIHBsb3R0aW5nIGNhbGwgZnJvbSBnZ3Bsb3QyIGV0YykKcGxvdCh0cmlwc0J5SG91ciRob3VyLCB0cmlwc0J5SG91ciR0cmlwcywgeGxhYiA9ICJIb3VyIG9mIHRoZSBEYXkiLCB5bGFiID0gIk51bWJlciBvZiBUcmlwcyIpCmBgYCAgCgpgYGB7cn0KIyMgU0FNRSBQTE9UCmdncGxvdCh0cmlwc0J5SG91ciwgYWVzKHg9aG91ciwgeT10cmlwcywgY29sb3VyPWdlbmRlcikpICsgZ2VvbV9saW5lKCkKCmBgYAoKYGBge3J9CiMjIyMjIyMjIFBBUlQgMyBTRUdNRU5UQVRJT04gQU5EIE1BUFBJTkcgIyMjIyMjIyMjIAoKIyBTYW1wbGUgZm9yIGp1c3QgdGhlIG1vcm5pbmcgCm1vcm5pbmcgPC0gcmRmQ2xlYW4gJT4lIGZpbHRlcihob3VyICVpbiUgYygnMDcnLCAnMDgnLCAnMDknKSkKCiMgRmluZCBtb3N0IGltcG9ydGFudCBzdGF0aW9ucwptb3JuaW5nU3RhdGlvbnMgPC0gbW9ybmluZyAgJT4lCiAgZ3JvdXBfYnkoYHN0YXJ0LnN0YXRpb24uaWRgKSAlPiUKICBzdW1tYXJpc2UobGF0PWFzLm51bWVyaWMoYHN0YXJ0LnN0YXRpb24ubGF0aXR1ZGVgWzFdKSwKICAgICAgICAgICAgbG9uPWFzLm51bWVyaWMoYHN0YXJ0LnN0YXRpb24ubG9uZ2l0dWRlYFsxXSksCiAgICAgICAgICAgIG5hbWU9YHN0YXJ0LnN0YXRpb24ubmFtZWBbMV0sCiAgICAgICAgICAgIHRyaXBzPW4oKSkKbW9ybmluZ1N0YXRpb25zPC1yZW5hbWUobW9ybmluZ1N0YXRpb25zLG1vcm5pbmd0cmlwcz10cmlwcykKCiMgU2FtcGxlIGZvciBqdXN0IHRoZSBldmVuaW5nCmV2ZW5pbmcgPC0gcmRmQ2xlYW4gJT4lIGZpbHRlcihob3VyICVpbiUgYygnMTcnLCAnMTgnLCAnMTknKSkKCiMgRmluZCBtb3N0IGltcG9ydGFudCBzdGF0aW9ucwpldmVuaW5nU3RhdGlvbnMgPC0gZXZlbmluZyAgJT4lCiAgZ3JvdXBfYnkoYHN0YXJ0LnN0YXRpb24uaWRgKSAlPiUKICBzdW1tYXJpc2UobGF0PWFzLm51bWVyaWMoYHN0YXJ0LnN0YXRpb24ubGF0aXR1ZGVgWzFdKSwKICAgICAgICAgICAgbG9uPWFzLm51bWVyaWMoYHN0YXJ0LnN0YXRpb24ubG9uZ2l0dWRlYFsxXSksCiAgICAgICAgICAgIG5hbWU9YHN0YXJ0LnN0YXRpb24ubmFtZWBbMV0sCiAgICAgICAgICAgIHRyaXBzPW4oKSkKZXZlbmluZ1N0YXRpb25zPC1yZW5hbWUoZXZlbmluZ1N0YXRpb25zLGV2ZW5pbmd0cmlwcz10cmlwcykKCm1lU3RhdGlvbnM8LW1lcmdlKG1vcm5pbmdTdGF0aW9ucyxldmVuaW5nU3RhdGlvbnMpCm1lU3RhdGlvbnMkZGlmZjwtbWVTdGF0aW9ucyRtb3JuaW5ndHJpcHMtbWVTdGF0aW9ucyRldmVuaW5ndHJpcHMKCm1lU3RhdGlvbnMgJT4lCiAgYXJyYW5nZShkZXNjKG1vcm5pbmd0cmlwcykpCgptZVN0YXRpb25zICU+JQogIGFycmFuZ2UoZGVzYyhldmVuaW5ndHJpcHMpKQoKIyMgVGFrZSBhIGxvb2sKbW9ybmluZ1N0YXRpb25zICU+JQogIGFycmFuZ2UoZGVzYyhtb3JuaW5ndHJpcHMpKQoKZXZlbmluZ1N0YXRpb25zICU+JQogIGFycmFuZ2UoZGVzYyh0cmlwcykpCgptZVN0YXRpb25zICU+JQogIGFycmFuZ2UoZGVzYyhtb3JuaW5ndHJpcHMpKQpgYGAKCmBgYHtyfQojIFR1cm5zIGl0IGludG8gYSBnaXMgZmlsZQptb3JuaW5nU3RhdGlvbnNHZW8gPC0gc3RfYXNfc2YobW9ybmluZ1N0YXRpb25zLCBjb29yZHMgPSBjKCJsb24iLCAibGF0IiksIGRpbSA9ICJYWSIsIGNycyA9IDQzMjYpICNjcnM9Y29vcmRpbmF0ZSByZWZlcmVuY2Ugc3lzdGVtCgojIFNhdmUgaWYgeW91IGZlZWwgbGlrZSBpdCEgIyBzdF93cml0ZShwb3B1bGFyU3RhdGlvbnMsICJwb3B1bGFyU3RhdGlvbnMuc2hwIiwgZGVsZXRlX2xheWVyID0gVFJVRSkKCiMgTG9vayBhdCB0aGUgbWFwIAp0bWFwX21vZGUoJ3ZpZXcnKQp0bV9zaGFwZShtb3JuaW5nU3RhdGlvbnNHZW8gJT4lIAogICAgICAgICAgIGZpbHRlcighaXMubmEobW9ybmluZ3RyaXBzKSkgJT4lIAogICAgICAgICAgIG11dGF0ZShtb3JuaW5ndHJpcHMgPSBhcy5udW1lcmljKG1vcm5pbmd0cmlwcykpKSArIHRtX2RvdHMoY29sID0gIm1vcm5pbmd0cmlwcyIsIHN0eWxlPSJxdWFudGlsZSIsIGlkID0gIm5hbWUiKQpgYGAKCmBgYHtyfQptZVN0YXRpb25zR2VvIDwtIHN0X2FzX3NmKG1lU3RhdGlvbnMsIGNvb3JkcyA9IGMoImxvbiIsICJsYXQiKSwgZGltID0gIlhZIiwgY3JzID0gNDMyNikKCnRtYXBfbW9kZSgndmlldycpCnRtX3NoYXBlKG1lU3RhdGlvbnNHZW8gJT4lIAogICAgICAgICAgIGZpbHRlcighaXMubmEoZGlmZikpICU+JSAKICAgICAgICAgICBtdXRhdGUoZGlmZiA9IGFzLm51bWVyaWMoZGlmZikpKSArIHRtX2RvdHMoY29sPSJkaWZmIiwgc3R5bGU9InF1YW50aWxlIiwgaWQgPSAibmFtZSIpCmBgYAoKCmBgYHtyfQojIyMjIyMjIyBQQVJUIDQgS0VSTkVMIERFTlNJVFkgICMjIyMjIyMjIyAKCiMjIFJlYWQgU0YgZm9yIGEgZmlsZSBvZiBib3JvdWdocwpib3JvdWdocyA8LSBzdF9yZWFkKCJib3JvdWdoLnNocCIpCmJvcm91Z2hzX3ByaiA8LSBzdF90cmFuc2Zvcm0oYm9yb3VnaHMsIGNycyA9IDIyNjMpCgojIERlbnNpdHkgbWFwIChUaGlzIG1ldGhvZCBkb2Vzbid0IGFsbG93IHVzIHRvIHNlZSB0aGUgYmFja2dyb3VuZCBtYXApCmRmLnNpemUucHJvaiA8LSBzdF90cmFuc2Zvcm0obW9ybmluZ1N0YXRpb25zR2VvLCBjcnMgPSAyMjYzKQpwLnNwIDwtIGFzKGRmLnNpemUucHJvaiwgIlNwYXRpYWwiKQpwLnBwcCA8LSBhcyhwLnNwLCAicHBwIikKa2VybmVsRGVuc2l0eU1vcm5pbmcgPC0gKGRlbnNpdHkocC5wcHAsIHNpZ21hID0gMTAwMCkpCgojI1Bsb3QgdGhlIHR3byB0b2dldGhlcgpwbG90KGtlcm5lbERlbnNpdHlNb3JuaW5nLCBtYWluPSJIZWF0IE1hcCBvZiBNb3JuaWduIENpdGliaWtlIE9yaWdpbnMiKQpwbG90KGJvcm91Z2hzX3ByaiRnZW9tZXRyeSwgYWRkPVRSVUUpCgojI0NIQUxMRU5HRVMgRk9SIFlPVVIgREVOU0lUWSBNQVAKIyNFeHRyYTogQ2xpcCB0aGUgcmFzdGVyIGFuZCBjbGlwIHRoZSB2ZWN0b3IgYXMgd2VsbC4gKG9ubHkgcGxvdCB0aGUgaW50ZXJzZWN0aW9uIG9mIHRoZSB0d28/KSAKIyNFeHRyYTogTWFrZSB0aGUgbGluZXMgd2hpdGUgKGhpbnQ6IGl0IGlzIG5vdyBhIHBvbHlnb24hKQojI0V4dHJhOiBBZGQgdGhlIHRvcCAzIChvciA1KSBwb2ludHMgYW5kIGxhYmVsIHRoZW0uCmBgYAoKYGBge3J9CiMjIyMjIyMjIFBBUlQgNSBHR1BMT1QgRVhBTVBMRSBXSVRIIENPTlRPVVJTICMjIyMjIyMjIyAKCiMgSGVhdG1hcCBpbiBnZ3Bsb3QKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnbWFwKQoKZGYuc2l6ZS5kZWdyZWUgPC0gc3RfdHJhbnNmb3JtKG1vcm5pbmdTdGF0aW9uc0dlbywgY3JzID0gNDMyNikgJT4lIAogIG11dGF0ZShsYXQgPSBzdF9jb29yZGluYXRlcyguKVssMl0sCiAgICAgICAgIGxvbiA9IHN0X2Nvb3JkaW5hdGVzKC4pWywxXSkKCiMjR2V0IGJvcmRlcnMKaGVpZ2h0IDwtIG1heChzdF9jb29yZGluYXRlcyhkZi5zaXplLmRlZ3JlZSlbLDJdKSAtIG1pbihzdF9jb29yZGluYXRlcyhkZi5zaXplLmRlZ3JlZSlbLDJdKQp3aWR0aCA8LSBtYXgoc3RfY29vcmRpbmF0ZXMoZGYuc2l6ZS5kZWdyZWUpWywxXSkgLSBtaW4oc3RfY29vcmRpbmF0ZXMoZGYuc2l6ZS5kZWdyZWUpWywxXSkKICAKc2FjX2JvcmRlcnMgPC0gYyhib3R0b20gPSBtaW4oc3RfY29vcmRpbmF0ZXMoZGYuc2l6ZS5kZWdyZWUpWywyXSkgLSAwLjEqaGVpZ2h0LAogICAgICAgICAgICAgICAgdG9wID0gbWF4KHN0X2Nvb3JkaW5hdGVzKGRmLnNpemUuZGVncmVlKVssMl0pICsgMC4xKmhlaWdodCwKICAgICAgICAgICAgICAgIGxlZnQgPSBtaW4oc3RfY29vcmRpbmF0ZXMoZGYuc2l6ZS5kZWdyZWUpWywxXSkgLSAwLjEqd2lkdGgsCiAgICAgICAgICAgICAgICByaWdodCA9IG1heChzdF9jb29yZGluYXRlcyhkZi5zaXplLmRlZ3JlZSlbLDFdKSArIDAuMSp3aWR0aCkKCm1hcCA8LSBnZXRfc3RhbWVubWFwKHNhY19ib3JkZXJzLCB6b29tID0gMTIsIG1hcHR5cGUgPSAidG9uZXItbGl0ZSIpCgpnZ21hcChtYXApICsKICBnZW9tX2RlbnNpdHkyZChkYXRhID0gZGYuc2l6ZS5kZWdyZWUsIGFlcyh4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDAuMykgKwogIHN0YXRfZGVuc2l0eTJkKGRhdGEgPSBkZi5zaXplLmRlZ3JlZSwgYWVzKHggPSBsb24sIHkgPSBsYXQsIGZpbGwgPSAuLmxldmVsLi4sIGFscGhhID0gLi5sZXZlbC4uKSwgCiAgICAgICAgICAgICAgICAgZ2VvbSA9ICJwb2x5Z29uIiwgYmlucyA9IDEwKSArIAogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaCA9ICJyZWQiKSArCiAgc2NhbGVfYWxwaGEocmFuZ2UgPSBjKDAsIDAuNCksIGd1aWRlID0gRkFMU0UpICNQbG90ICsKIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygtNzQuMDIsIC05NS43KSwgCiAgICAgICAgICAgICAgICAgIHlsaW0gPSBjKDI5LjUsIDMwLjEpKQpgYGAK