summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Makefile5
-rw-r--r--config.example.json39
-rw-r--r--distances.py114
-rw-r--r--shell.nix7
5 files changed, 170 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3f70185
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
1/config.json
2/outputs/
3*.dat
4*.gnuplot
5*.json
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..71ec2f9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
1NIX_PATH=nixpkgs=https://releases.nixos.org/nixos/19.09/nixos-19.09.840.8bf142e001b/nixexprs.tar.xz
2.PHONY: build
3
4build:
5 NIX_PATH=$(NIX_PATH) nix-shell --pure --run "python distances.py"
diff --git a/config.example.json b/config.example.json
new file mode 100644
index 0000000..fec6b23
--- /dev/null
+++ b/config.example.json
@@ -0,0 +1,39 @@
1{
2 "api_key": "your-api-key see https://developers.google.com/maps/documentation/distance-matrix/start",
3 "locations": {
4 "home": "6 Rue Ribotti, 06300 Nice, France",
5 "work": "43.586337,6.939781"
6 },
7 "plots": {
8 "home-work": {
9 "days": ["monday","tuesday","wednesday","thursday","friday"],
10 "name": "Home -> Work",
11 "times": [
12 "6:30", "7:00", "7:30", "8:00", "8:30",
13 "9:00", "9:30", "10:00"
14 ],
15 "origin": "home",
16 "destination": "work"
17 },
18 "work-home": {
19 "days": ["monday","tuesday","wednesday","thursday","friday"],
20 "name": "Work -> Home",
21 "times": [
22 "16:00", "16:30", "17:00", "17:30", "18:00",
23 "18:30", "19:00", "19:30", "20:00"
24 ],
25 "origin": "work",
26 "destination": "home"
27 },
28 "work-gym": {
29 "days": ["monday"],
30 "name": "Work -> Monday’s gym",
31 "times": [
32 "11:00", "11:15", "11:30", "11:45",
33 "12:00", "12:15"
34 ],
35 "origin": "work",
36 "destination": "330 Rue Henri Laugier, 06600 Antibes, France"
37 }
38 }
39}
diff --git a/distances.py b/distances.py
new file mode 100644
index 0000000..e28caf7
--- /dev/null
+++ b/distances.py
@@ -0,0 +1,114 @@
1#!/usr/bin/env python
2import requests
3from datetime import datetime, timedelta
4from collections import defaultdict
5import json
6import os, sys
7import pytz
8import argparse
9
10URL= "https://maps.googleapis.com/maps/api/distancematrix/json"
11
12parser = argparse.ArgumentParser(description='Plot traffic information for various origin-destinations')
13parser.add_argument('-c', '--config', type=str, default='config.json', help='Config file to load (default config.jsonà')
14parser.add_argument('-n', '--dry-run', action='store_true', help='Run in dry-run mode (don’t make any api call)')
15parser.add_argument('-d', '--date', type=str, default='now', help='date (%%Y-%%m-%%d) for which to generate the plots')
16parser.add_argument('-s', '--stats', action='store_true', help='only print number of weekly calls for the config')
17args = parser.parse_args()
18
19WEEKDAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
20SETTINGS = json.load(open(args.config, "r"))
21
22if args.date == "now":
23 date = datetime.now(tz=pytz.timezone("Europe/Paris"))
24else:
25 date = datetime.strptime(args.date, "%Y-%m-%d").replace(tzinfo=pytz.timezone("Europe/Paris"))
26
27def parse_plot(info):
28 def condition(d):
29 return "days" not in info or WEEKDAYS[d.weekday()] in info["days"]
30 return {
31 "name": info["name"],
32 "origin": SETTINGS.get("locations", {}).get(info["origin"], info["origin"]),
33 "destination": SETTINGS.get("locations", {}).get(info["destination"], info["destination"]),
34 "condition": condition,
35 "times": [t.split(":") for t in info["times"]],
36 }
37
38plots = {}
39for name,info in SETTINGS["plots"].items():
40 plots[name] = parse_plot(info)
41
42def to_time(date, hour, minute):
43 return date.replace(date.year, date.month, date.day, int(hour), int(minute), 0, 0)
44
45def get(time, origin, destination):
46 keys = {
47 "origins": origin,
48 "destinations": destination,
49 "departure_time": int(time.timestamp()),
50 "key": SETTINGS["api_key"],
51 }
52 return requests.get(URL, params=keys)
53
54def stats():
55 total_calls_per_week = 0
56 for k, infos in plots.items():
57 calls_per_week = 0
58 for i in range(0, 7):
59 if infos["condition"](date + timedelta(i)):
60 calls_per_week += 1
61 total_calls_per_week += calls_per_week * len(infos["times"])
62 print("{} calls per week to api".format(total_calls_per_week))
63if args.stats:
64 stats()
65 sys.exit(0)
66
67gnuplot = """
68reset
69set terminal png size 1024,768 enhanced font "Helvetica"
70set output 'outputs/{fname}.png'
71set datafile separator "\\t"
72set xlabel "Time"
73set ylabel "Duration"
74
75set xdata time
76set timefmt "%H:%M"
77set format x "%H:%M"
78set title "{date} {name}"
79plot '{fname}.dat' using 1:2 with linespoints pointtype 5 title ""
80"""
81
82def get_times(name, infos, date, dry_run=False):
83 result = {}
84 if "condition" in infos and not infos["condition"](date):
85 return result
86 for time in infos["times"]:
87 t = to_time(date, time[0], time[1])
88 try:
89 if dry_run:
90 v = 42
91 else:
92 v = get(t, infos["origin"], infos["destination"]).json()
93 v = int(v["rows"][0]["elements"][0]["duration_in_traffic"]["value"] / 60)
94 except:
95 continue
96 result[t.strftime("%H:%M")] = v
97 with open(date.strftime("%Y-%m-%d_{}.json".format(name)), "w") as f:
98 f.write(json.dumps(result, indent=True))
99
100 fname = date.strftime("%Y-%m-%d_{}".format(name))
101 with open("{}.dat".format(fname), "w") as f:
102 for time, duration in result.items():
103 f.write('{}\t{}\n'.format(time, duration))
104 with open("{}.gnuplot".format(fname), "w") as f:
105 f.write(gnuplot.format(**{
106 "fname": fname,
107 "name": infos["name"],
108 "date": date.strftime("%Y-%m-%d")
109 }))
110 os.system("gnuplot -c {}.gnuplot".format(fname))
111 return result
112
113for name, infos in plots.items():
114 get_times(name, infos, date, dry_run=args.dry_run)
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..cdf128c
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,7 @@
1{ pkgs ? import <nixpkgs> {} }:
2pkgs.mkShell {
3 buildInputs = [
4 pkgs.gnuplot
5 (pkgs.python3.withPackages (p: [p.requests p.pytz]))
6 ];
7}