depot/third_party/tvl/fun/amsterdump/main.go

109 lines
2.6 KiB
Go
Raw Normal View History

// Amsterdump is a small program that populates a BigQuery table with
// a matrix of origin points scattered around Amsterdam and each
// respective points travel time to a given destination.
//
// The two destinations used here are the Schiphol Airport and
// Amsterdam Central station.
//
// To accomplish this the Google Maps Distance Matrix API [1] is
// queried with the points. A visualisation is later done using
// BigQuery GeoViz[2].
//
// [1]: https://developers.google.com/maps/documentation/distance-matrix/start#quotas
// [2]: https://bigquerygeoviz.appspot.com/
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"googlemaps.github.io/maps"
)
func failOn(err error, msg string) {
if err != nil {
log.Fatalln(msg, err)
}
}
type LocationResult struct {
Address string `json:"address"`
URL string `json:"url"`
Schiphol *maps.DistanceMatrixElement `json:"schiphol"`
Centraal *maps.DistanceMatrixElement `json:"centraal"`
}
type Listing struct {
URL string `json:"url"`
Address string `json:"address"`
}
func requestMatrix(ctx context.Context, client *maps.Client, listings []Listing) {
origins := make([]string, len(listings))
for i, l := range listings {
origins[i] = l.Address
}
request := &maps.DistanceMatrixRequest{
Mode: maps.TravelModeTransit,
Units: maps.UnitsMetric,
Origins: origins,
Destinations: []string{
"Schiphol Airport",
"Amsterdam Centraal",
},
}
response, err := client.DistanceMatrix(ctx, request)
failOn(err, "could not retrieve distance matrix:")
for idx, addr := range response.OriginAddresses {
result := LocationResult{
Address: addr,
URL: listings[idx].URL,
Schiphol: response.Rows[idx].Elements[0],
Centraal: response.Rows[idx].Elements[1],
}
j, _ := json.Marshal(result)
fmt.Println(string(j))
}
}
func main() {
var listings []Listing
input, err := ioutil.ReadFile("fun/amsterdump/input.json")
failOn(err, "could not read input file:")
err = json.Unmarshal(input, &listings)
failOn(err, "could not deserialise listings:")
ctx := context.Background()
apiKey := os.Getenv("MAPS_API_KEY")
if apiKey == "" {
log.Fatalln("API key must be supplied via MAPS_API_KEY")
}
client, err := maps.NewClient(maps.WithAPIKey(apiKey))
failOn(err, "could not create Google Maps API client:")
var chunk []Listing
for _, l := range listings {
if len(chunk) == 25 {
requestMatrix(ctx, client, chunk)
chunk = []Listing{}
} else {
chunk = append(chunk, l)
}
}
if len(chunk) > 1 {
requestMatrix(ctx, client, chunk)
}
}