Commits

Marco Yuen  committed 2c75b4c

Display the nearest stops.

Using a gtfs database and the current location, it will display
the closest stops.

  • Participants
  • Parent commits e68110b

Comments (0)

Files changed (9)

   :plugins      [[lein-ring  "0.7.1"]
                  [lein-swank "1.4.4"]
                  [lein-midje "1.0.10"]]
-  :dependencies [[org.clojure/clojure     "1.3.0"]
-                 [org.clojure/tools.trace "0.7.3"]
-                 [org.xerial/sqlite-jdbc  "3.7.2"]
-                 [compojure               "1.1.0"]
-                 [hiccup                  "1.0.0"]
-                 [ring-json-response      "0.2.0"]
-                 [useful                  "0.8.3-alpha2"]
-                 [korma                   "0.3.0-beta10"]
-                 [lobos                   "1.0.0-SNAPSHOT"]]
+  :dependencies [[org.clojure/clojure        "1.3.0"]
+                 [org.clojure/tools.trace    "0.7.3"]
+                 [org.clojure/data.json      "0.1.3"]
+                 [org.xerial/sqlite-jdbc     "3.7.2"]
+                 [mysql/mysql-connector-java "5.1.20"]
+                 [compojure                  "1.1.0"]
+                 [hiccup                     "1.0.0"]
+                 [ring-json-response         "0.2.0"]
+                 [useful                     "0.8.3-alpha2"]
+                 [korma                      "0.3.0-beta10"]
+                 [lobos                      "1.0.0-SNAPSHOT"]]
   :dev-dependencies [[clojure-source "1.3.0"]
                      [midje          "1.4.0"]
                      [ring-serve     "0.1.2"]

File resources/public/js/location.coffee

+$(document).bind('pageinit', -> )
+
 $ ->
     success = (position) ->
         console.log(position)
         $('#lat').html(position.coords.latitude)
-        $('#lng').html(position.coords.longitude)
-        true
+        $('#lon').html(position.coords.longitude)
+        $.post('/findstops',
+               {lat: position.coords.latitude, lon: position.coords.longitude},
+               (data, status, jqxhr) ->
+                 directive = {'li': {
+                               'stop<-stops': {
+                                 '.': 'stop' }}}
+                 $('#stops-list-template').render(data, directive)
+                 console.log(data))
 
     errorhandler = (error) ->
         console.log("Cannot acquire location.")
             when error.TIMEOUT then alert "Retrieving position timed out"
             else alert "Unknown error"
 
-
     if navigator.geolocation
-        navigator.geolocation.getCurrentPosition(success, errorhandler
+        navigator.geolocation.getCurrentPosition(success, errorhandler,
                                                  {enableHighAccuracy: true})
     else
         alert("Cannot determine your location.")

File resources/public/js/location.js

 // Generated by CoffeeScript 1.3.3
 
+$(document).bind('pageinit', function() {});
+
 $(function() {
   var errorhandler, success;
   success = function(position) {
     console.log(position);
     $('#lat').html(position.coords.latitude);
-    $('#lng').html(position.coords.longitude);
-    return true;
+    $('#lon').html(position.coords.longitude);
+    return $.post('/findstops', {
+      lat: position.coords.latitude,
+      lon: position.coords.longitude
+    }, function(data, status, jqxhr) {
+      var directive;
+      directive = {
+        'li': {
+          'stop<-stops': {
+            '.': 'stop'
+          }
+        }
+      };
+      $('#stops-list-template').render(data, directive);
+      return console.log(data);
+    });
   };
   errorhandler = function(error) {
     console.log("Cannot acquire location.");

File src/nextrain/controller.clj

+(ns nextrain.controller
+  (:use nextrain.pages
+        nextrain.snippets
+        nextrain.data.gtfs
+        nextrain.utils
+        hiccup.core
+        ring.util.json-response
+        [korma.core :only [select where]]
+        [clojure.data.json :only [json-str]]))
+
+(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]})))]
+    (map :stop_name result)))
+
+;;;
+;;; Handlers
+;;;
+(defn index []
+  (layout :body (index-mobile-page)))
+
+(defn find-stops [params]
+  (let [lat (read-string (:lat params))
+        lon (read-string (:lon params))
+        stops (nearest-stops [lat lon])]
+    (json-response {:stops stops})))
+

File src/nextrain/core.clj

 (ns nextrain.core
   (:use compojure.core
-        nextrain.pages
+        nextrain.controller
         ring.adapter.jetty)
   (:require [compojure.route :as route]
             [compojure.handler :as handler]))
      :session (assoc session :n 1)}))
 
 (defroutes main-routes
-  (GET "/" [] (index-page))
+  (GET "/" [] (index))
+  (POST "/findstops" {params :params} (find-stops params))
   (GET "/ses" {params :params
                session :session} (testsession params session))
   (route/resources "/")
   (route/not-found "Page not found"))
 
 ;(def app
-;  (-> #'main-routes
-;      handler/site))
+;  (-> #'main-routes handler/site))
 (def app (handler/site main-routes))
 
 (defn -main [& args]

File src/nextrain/data/gtfs.clj

+(ns nextrain.data.gtfs
+  (:use [clojure.java.jdbc :only [create-table]]
+        [korma.core :only [select defentity table entity-fields database]]
+        [korma.db :only [defdb sqlite3 mysql]])
+  (:require [clojure.java.jdbc :as sql]))
+
+;; TODO load from configuration
+(defdb gtfsdb (sqlite3 {:db "transit.db"}))
+
+(defn get-tables []
+  (into [] (sql/resultset-seq
+            (-> (sql/connection)
+                (.getMetaData)
+                (.getTables nil nil nil nil)))))
+
+(defn table-exists? [tblname]
+  (contains? (set (map :table_name (get-tables)))
+             tblname))
+
+(defmacro deftable
+  [db tblname & specs]
+  (let [field-names (map first specs)]
+    `(do
+       (defn ~(symbol (str "create-tbl-" tblname)) []
+         (when-not (table-exists? ~(str tblname))
+           (create-table ~(keyword tblname) ~@specs)))
+       (defentity ~tblname
+         (table ~(keyword tblname))
+         (entity-fields ~@field-names)
+         (database ~db)))))
+
+(deftable gtfsdb stops
+  [:stop_id "varchar(16)"]
+  [:stop_code "varchar(24)"]
+  [:stop_name "varchar(256)"]
+  [:stop_desc :text]
+  [:stop_lat :real]
+  [:stop_lon :real]
+  [:zone_id :integer])
+
+(deftable gtfsdb stop_times
+  [:trip_id :integer]
+  [:arrival_time "varchar(128)"]
+  [:departure_time "varchar(128)"]
+  [:stop_id "varchar(16)"]
+  [:stop_sequence :integer]
+  [:pickup_type :integer]
+  [:drop_off_type :integer]
+  [:shape_dist_traveled :real])
+
+(deftable gtfsdb calendar_dates
+  [:service_id :integer]
+  [:date "varchar(128)"]
+  [:exception_type :integer])
+
+(deftable gtfsdb trips
+  [:route_id :integer]
+  [:service_id :integer]
+  [:trip_id :integer]
+  [:trip_headsign "varchar(512)"]
+  [:direction_id :integer]
+  [:block_id :integer]
+  [:shape_id :integer])
+
+(deftable gtfsdb routes
+  [:route_id :integer]
+  [:agency_id :integer]
+  [:route_short_name "varchar(128)"]
+  [:route_long_name "varchar(512)"]
+  [:route_type :integer]
+  [:route_url "varchar(512)"]
+  [:route_color "varchar(128)"])
+
+(deftable gtfsdb agency
+  [:agency_id :integer]
+  [:agency_name "varchar(512)"]
+  [:agency_url "varchar(512)"]
+  [:agency_timezone "varchar(128)"]
+  [:agency_lang"varchar(8)"]
+  [:agency_phone "varchar(24)"])

File src/nextrain/pages.clj

 (ns nextrain.pages
   (:use [hiccup.page :only (html5 include-css include-js)]
-        [hiccup.element :only (javascript-tag)]))
+        [hiccup.element :only (javascript-tag)]
+        hiccup.core))
 
-(defn index-page []
+(defn layout [& {:keys [body] :as params}]
   (html5
     [:head
       [:title "NexTrain"]
       (include-css "http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css")
       (include-js "https://www.google.com/jsapi"
                   "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"
+                  "http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"
+                  "https://raw.github.com/pure/pure/master/libs/pure_min.js"
                   "/js/location.js"
-                  "http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js")]
-    [:body
-      [:div {:data-rote "page"}
-        [:div#lat "latitude"]
-        [:div#lng "longitude"]]]))
+                  )]
+    [:body body]))
 

File src/nextrain/snippets.clj

+(ns nextrain.snippets
+  (:use hiccup.core))
+
+(defn mobile-page
+  [& {:as params}]
+  (html [:div {:data-role "page"}
+         [:div {:data-role "header"}
+           (:header params)]
+         [:div {:data-role "content"}
+           (:content params)]]))
+
+(defn default-lat-lon []
+  (html [:div {:data-role "page"}
+         [:div {:data-role "header"}
+           [:h1 "Your Location"]]
+         [:div {:data-role "content"}
+           [:div#lat "latitude"]
+           [:div#lon "longitude"]]]))
+
+(defn index-mobile-page []
+  (mobile-page :header (html [:h1 "Nearest Stops"])
+               :content (html [:div#stops-list-template
+                                [:ul {:data-role "listview"}
+                                  [:li]]])))

File src/nextrain/utils.clj

 (ns nextrain.utils)
 
-(def origin  [40.7599573, -73.9921683])
-(def ny_penn [40.750046, -73.992358])
-(def pton    [40.343398, -74.659872])
+(defonce origin  [40.7599573, -73.9921683])
+(defonce ny_penn [40.750046, -73.992358])
+(defonce pton    [40.343398, -74.659872])
 
-(def ^Double earth-radius 6371.01)
-(def cos    #(Math/cos %))
-(def acos   #(Math/acos %))
-(def sin    #(Math/sin %))
-(def radian #(Math/toRadians %))
-(def degree #(Math/toDegrees %))
-(def sqrt   #(Math/sqrt %))
-(def atan2  #(Math/atan2 % %2))
-(def pow    #(Math/pow % %2))
+(defonce ^Double earth-radius 6371.01)
+(defonce cos    #(Math/cos %))
+(defonce acos   #(Math/acos %))
+(defonce sin    #(Math/sin %))
+(defonce radian #(Math/toRadians %))
+(defonce degree #(Math/toDegrees %))
+(defonce sqrt   #(Math/sqrt %))
+(defonce atan2  #(Math/atan2 % %2))
+(defonce pow    #(Math/pow % %2))
 
 (defn haversine-dist
   [[src-lat src-lon] [dest-lat dest-lon]]