diff options
Diffstat (limited to 'fun/amsterdump/main.go')
-rw-r--r-- | fun/amsterdump/main.go | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/fun/amsterdump/main.go b/fun/amsterdump/main.go new file mode 100644 index 000000000000..77f7392f4b7c --- /dev/null +++ b/fun/amsterdump/main.go @@ -0,0 +1,108 @@ +// 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) + } +} |