about summary refs log tree commit diff
path: root/fun/amsterdump/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'fun/amsterdump/main.go')
-rw-r--r--fun/amsterdump/main.go108
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)
+	}
+}