---
title: "Looking for a home"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Looking for a home}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = nzchar(Sys.getenv("CLOSECITY_KEY"))
)
library(closecity)
library(sf)
close <- closecity::close_client(api_key = Sys.getenv("CLOSECITY_KEY"))
```

Say you are moving to a new city and want to live near the amenities that are
important to you. In this tutorial, we find the blocks that are within a 10-minute
walk of a supermarket, a 5-minute walk of a restaurant, and a 20-minute walk of a
frequent-transit stop. Then, we narrow those blocks to the overlap of two commutes.
The example city is Somerville, Massachusetts.

*Running this tutorial uses about 2,600 tokens.*

## Set up

Build a client, then read the pieces you need from the free catalog instead of
memorising codes.

```r
library(closecity)
library(sf)
close <- closecity::close_client(api_key = "ck_live_your_key")   # use your own key here
```

```{r}
# The catalog lists every category with its numeric id. Pull the ids you need.
amenity_types <- close$destination_types()
ids <- setNames(amenity_types$dest_type_id, amenity_types$label)

supermarket_dest_id <- ids[["grocery_stores"]]
restaurant_dest_id <- ids[["restaurants"]]
freq_transit_stop_dest_id <- ids[["frequent_transit"]]

# Turn the city name into a GEOID and pull its boundary for context.
city <- close$places(q = "Somerville")[1, ]
city_boundary <- close$place_boundary(geoid = city$geoid)
```

## See what is around

Look at the raw ingredients first: every supermarket, restaurant, and frequent-transit
stop **within Somerville**, from `$place_pois()`. The city boundary, not a guessed
radius, is the edge. Give each category a colour and map them together.

```{r}
supermarkets <- close$place_pois(geoid = city$geoid, type = supermarket_dest_id)
restaurants <- close$place_pois(geoid = city$geoid, type = restaurant_dest_id)
stops <- close$place_pois(geoid = city$geoid, type = freq_transit_stop_dest_id)

supermarkets$kind <- "Supermarket"
restaurants$kind <- "Restaurant"
stops$kind <- "Transit stop"
around <- rbind(supermarkets, restaurants, stops)

palette <- c(Supermarket = "#058040", Restaurant = "#c6cbe0", `Transit stop` = "#f36e21")
closecity::close_map(
  x = around,
  color = palette[around$kind],
  label = "kind",
  boundary = city_boundary
)
```

## Find the blocks that qualify

Somerville is a census place, so one call by place GEOID pulls the per-block walk
times for every block in the city. `$place_blocks()` reads every page and returns
one sf row per (block, category); block boundaries come from `tigris`, downloaded
once and cached. (To search an arbitrary area instead, use `$blocks_query()` with a
centre and radius or a polygon. We do that with a radius in the other tutorials
only to keep their token cost low; a place GEOID pulls the whole city.)

```{r}
blocks <- close$place_blocks(
  geoid = city$geoid,
  mode = "walk",
  type = c(supermarket_dest_id, restaurant_dest_id, freq_transit_stop_dest_id)
)
```

Reshape to one row per block, with a walk-time column for each amenity, so a block
carries all three times at once (and the hover on the map shows them). Then flag the
blocks that pass every rule.

```{r}
city_blocks <- blocks[!duplicated(blocks$geoid), "geoid"]
time_to <- function(type_id) {
  sub <- blocks[blocks$dest_type_id == type_id, ]
  setNames(sub$travel_time, sub$geoid)[city_blocks$geoid]
}
city_blocks$supermarket_min <- time_to(supermarket_dest_id)
city_blocks$restaurant_min <- time_to(restaurant_dest_id)
city_blocks$transit_min <- time_to(freq_transit_stop_dest_id)

city_blocks$qualifies <- (city_blocks$supermarket_min <= 10 &
                          city_blocks$restaurant_min <= 5 &
                          city_blocks$transit_min <= 20)
city_blocks$qualifies[is.na(city_blocks$qualifies)] <- FALSE
```

Show every block in the city, highlight the ones that qualify, and hover any block
to read its walk time to each amenity.

```{r}
closecity::close_map(
  x = city_blocks,
  highlight = "qualifies",
  color = "#f36e21",
  boundary = city_boundary
)
```

## Narrow to a shared commute

Suppose two of you work in different places. A transit isochrone from each workplace
shows how far each commute reaches; drawn together, half-transparent, you can see
both at once.

```{r}
work_a <- close$isochrone(
  lon = -71.0865,
  lat = 42.3625,
  mode = "transit",
  direction = "from",
  minutes = 20,
  format = "geojson"
)
work_b <- close$isochrone(
  lon = -71.0589,
  lat = 42.3555,
  mode = "transit",
  direction = "from",
  minutes = 20,
  format = "geojson"
)

closecity::close_map(
  x = work_a,
  color = "#058040",
  opacity = 0.5,
  background = work_b,
  background_color = "#f36e21",
  background_opacity = 0.5
)
```

Keep the qualifying blocks that also sit inside both commutes. The final map shows
those winning blocks, with the shortlist (inside both commutes) highlighted, over
the two commute walksheds.

```{r}
both_commutes <- sf::st_intersection(sf::st_union(work_a), sf::st_union(work_b))
winners <- city_blocks[city_blocks$qualifies, ]
winners$shortlist <- sf::st_intersects(winners, both_commutes, sparse = FALSE)[, 1]

closecity::close_map(
  x = winners,
  highlight = "shortlist",
  color = "#1f78b4",
  boundary = city_boundary,
  background = list(work_a, work_b),
  background_color = c("#058040", "#f36e21"),
  background_fill = FALSE
)
```
