about summary refs log tree commit diff
diff options
context:
space:
mode:
authorArun Isaac2023-10-14 21:08:29 +0100
committerArun Isaac2023-10-14 21:33:57 +0100
commit156dd142883f924cdce11e9ddd41dc11ed604294 (patch)
treeeb2674584ac500f833592e1b3006f25b0b7245c1
parent5550bdf055b8ec9619f5ebfe6c47e13fb4605590 (diff)
downloadrent-in-london-156dd142883f924cdce11e9ddd41dc11ed604294.tar.gz
rent-in-london-156dd142883f924cdce11e9ddd41dc11ed604294.tar.lz
rent-in-london-156dd142883f924cdce11e9ddd41dc11ed604294.zip
Directly query TfL API to find tube lines at station.
Earlier, we were laboriously building a lookup table mapping all tube
lines to the stations they serve, and inverting that lookup table.

* rent.scm (all-tube-lines, stations-on-line): Delete functions.
(lines-at-station): Rewrite to directly query TfL API.
-rw-r--r--rent.scm53
1 files changed, 27 insertions, 26 deletions
diff --git a/rent.scm b/rent.scm
index 9a0857a..d380d1f 100644
--- a/rent.scm
+++ b/rent.scm
@@ -365,34 +365,35 @@ and not distance as the crow flies."
                       "distances" 0 0)
             1000))))))
 
-(define (all-tube-lines)
-  "Return a list of all tube lines in London."
-  (call-with-port (open-bytevector-input-port
-                   (http-get* (string-append %tfl-base-url
-                                             "/Line/Mode/tube")))
-    (lambda (port)
-      (map (lambda (line)
-             (json-ref line "id"))
-           (vector->list (json->scm port))))))
-
-(define (stations-on-line line-id)
-  "Return a list of tube stations on @var{line-id}."
-  (call-with-port (open-bytevector-input-port
-                   (http-get* (string-append %tfl-base-url
-                                             "/Line/" line-id "/StopPoints")))
-    (lambda (port)
-      (map (lambda (station)
-             (let ((station-name (json-ref station "commonName")))
-               (if (string-suffix? " Underground Station" station-name)
-                   (substring station-name 0 (- (string-length station-name)
-                                                (string-length " Underground Station"))))))
-           (vector->list (json->scm port))))))
-
 (define (lines-at-station station-name)
   "Return a list of tube lines serving @var{station-name}."
-  (filter (lambda (line)
-            (member station-name (stations-on-line line)))
-          (all-tube-lines)))
+  (let* ((modes (list "dlr" "elizabeth-line" "tube"))
+         (station-id
+          (call-with-port (open-bytevector-input-port
+                           (http-get* (string-append %tfl-base-url
+                                                     "/StopPoint/Search/"
+                                                     (uri-encode station-name)
+                                                     "?modes="
+                                                     (string-join modes ","))))
+            (lambda (port)
+              ;; Assume the first search result is the station we are
+              ;; looking for.
+              (json-ref (json->scm port)
+                        "matches" 0 "id")))))
+    (call-with-port (open-bytevector-input-port
+                     (http-get* (string-append %tfl-base-url
+                                               "/StopPoint/" station-id)))
+      (lambda (port)
+        (vector->list
+         ;; Assume that we actually find tube lines at this
+         ;; station. This may not be the case if the supplied
+         ;; station-name is not actually a tube station.
+         (json-ref (find (lambda (mode-group)
+                           (member (json-ref mode-group "modeName")
+                                   modes))
+                         (vector->list (json-ref (json->scm port)
+                                                 "lineModeGroups")))
+                   "lineIdentifier"))))))
 
 (define (list-house house)
   "Display details of @var{house} on the current output port."