Source

nextrain / src / nextrain / controller.clj

Full commit
(ns nextrain.controller
  (:use nextrain.pages
        nextrain.snippets
        nextrain.data.gtfs
        nextrain.utils
        hiccup.core
        ring.util.json-response
        [korma.core :only [select where join fields subselect order]]
        [clojure.data.json :only [json-str]]
        [clojure.pprint :only [pprint cl-format]])
  (:import (java.util Calendar)
           (java.text SimpleDateFormat)))

; 30 minutes in millis
(defonce time-offset (* 30 60 1000))
(defonce calendar-date-format (SimpleDateFormat. "yyyyMMdd"))
(defonce train-time-format    (SimpleDateFormat. "HH:mm:ss"))

(defn nearest-stops [coord]
  (let [[[lat-min lon-min] [lat-max lon-max]] (bounding-box coord 1500)
        result (select stops
                 (where (and {:stop_lat [> lat-min]}
                             {:stop_lon [> lon-min]}
                             {:stop_lat [< lat-max]}
                             {:stop_lon [< lon-max]})))]
    result))

(defn stop-info [stop-id]
  (select stops
    (where {:stop_id stop-id})))

(defn next-train [params]
  (let [timestamp (read-string (:timestamp params))
        client-time (Calendar/getInstance)
        client-future (Calendar/getInstance)
        _ (.setTimeInMillis client-time timestamp)
        _ (.setTimeInMillis client-future (+ timestamp
                                             time-offset))
        time (.format train-time-format (.getTime client-time))
        future (.format train-time-format (.getTime client-future))
        date (.format calendar-date-format (.getTime client-time))
        stop-id (:stop_id params)]
    (select stop_times
      (fields :trip_id :departure_time :trips.trip_headsign :trips.route_id)
      (join trips (= :stop_times.trip_id :trips.trip_id))
      (where (and {:stop_id stop-id}
                  {:departure_time [>= time]}
                  {:departure_time [<  future]}
                  {:trips.direction_id 1} ; outbound
                  {date [in (subselect calendar_dates
                                       (fields :date)
                                       (where {:service_id :trips.service_id}))]}
                  ))
      (order :departure_time)
      )
    ))


;;;
;;; Handlers
;;;
(defn index []
  (layout :body (index-mobile-page)))

(defn stop [stop-id]
  (layout :body (stop-mobile-page (first (stop-info stop-id)))))

(defn next-train-times [params]
  (println "next-train-times:" params)
  (let [times (next-train params)]
    (pprint times)
    (flush)
    (json-response {:times times})))

(defn find-stops [params]
  (let [lat (read-string (:lat params))
        lon (read-string (:lon params))
        stops (nearest-stops [lat lon])]
    (println "find-stops: " lat "," lon)
    (json-response {:stop (map
                           #(assoc % :stop_url (str "/stop/" (:stop_id %)))
                           stops)})))