Fix geolocation
[busui.git] / schedule_viewer.py
blob:a/schedule_viewer.py -> blob:b/schedule_viewer.py
--- a/schedule_viewer.py
+++ b/schedule_viewer.py
@@ -282,11 +282,28 @@
     result.sort(key = lambda x: x[1:3])
     return result
 
+  def handle_json_GET_routesearch(self, params):
+    """Return a list of routes with matching short name."""
+    schedule = self.server.schedule
+    routeshortname = params.get('routeshortname', None)
+    result = []
+    for r in schedule.GetRouteList():
+      if r.route_short_name == routeshortname:
+        servicep = None
+        for t in schedule.GetTripList():
+          if t.route_id == r.route_id:
+            servicep = t.service_period
+            break
+        result.append( (r.route_id, r.route_short_name, r.route_long_name, servicep.service_id) )
+    result.sort(key = lambda x: x[1:3])
+    return result
+
+
   def handle_json_GET_routerow(self, params):
     schedule = self.server.schedule
     route = schedule.GetRoute(params.get('route', None))
     return [transitfeed.Route._FIELD_NAMES, route.GetFieldValuesTuple()]
-    
+  
   def handle_json_GET_routetrips(self, params):
     """ Get a trip for a route_id (preferablly the next one) """
     schedule = self.server.schedule
@@ -294,7 +311,12 @@
     result = []
     for t in schedule.GetTripList():
       if t.route_id == query:
-        result.append ( (t.GetStartTime(), t.trip_id) )
+        try:
+          starttime = t.GetStartTime()  
+        except:
+          print "Error for GetStartTime of trip #" + t.trip_id + sys.exc_info()[0]
+        else:
+            result.append ( (starttime, t.trip_id) )
     return sorted(result, key=lambda trip: trip[0])
   
   def handle_json_GET_triprows(self, params):
@@ -344,14 +366,56 @@
         points.append((stop.stop_lat, stop.stop_lon))
     return points
 
+#
+# GeoPo Encode in Python
+# @author : Shintaro Inagaki
+# @param location (Dictionary) [lat (Float), lng (Float), scale(Int)]
+# @return geopo (String)
+#
+     
   def handle_json_GET_neareststops(self, params):
     """Return a list of the nearest 'limit' stops to 'lat', 'lon'"""
     schedule = self.server.schedule
     lat = float(params.get('lat'))
     lon = float(params.get('lon'))
-    limit = int(params.get('limit'))
-    stops = schedule.GetNearestStops(lat=lat, lon=lon, n=limit)
-    return [StopToTuple(s) for s in stops]
+    limit = int(params.get('limit',5))
+    scale = int(params.get('scale',5)) # 5 = neighbourhood ~ 1km, 4= town 5 by 7km
+    stops = []
+    
+    # 64characters (number + big and small letter + hyphen + underscore)
+    chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
+
+    geopo = ""
+
+    # Change a degree measure to a decimal number
+    lat = (lat + 90.0) / 180 * 8 ** 10 # 90.0 is forced FLOAT type when lat is INT
+    lon = (lon + 180.0) / 360 * 8 ** 10 # 180.0 is same
+
+       # Compute a GeoPo code from head and concatenate
+    for i in range(scale):
+            order = int(lat / (8 ** (9 - i)) % 8) + int(lon / (8 ** (9 - i)) % 8) * 8
+            geopo = geopo + chars[order]
+
+    
+    for s in schedule.GetStopList():
+      if s.stop_code.find(geopo) != -1:
+        stops.append(s)
+        
+    if scale == 5:
+      print stops
+      return [StopToTuple(s) for s in stops]
+    else:
+      dist_stop_list = []
+      for s in stops:
+      # TODO: Use util.ApproximateDistanceBetweenStops?
+        dist = (s.stop_lat - lat)**2 + (s.stop_lon - lon)**2
+        if len(dist_stop_list) < limit:
+          bisect.insort(dist_stop_list, (dist, s))
+        elif dist < dist_stop_list[-1][0]:
+          bisect.insort(dist_stop_list, (dist, s))
+          dist_stop_list.pop()  # Remove stop with greatest distance
+      print dist_stop_list
+      return [StopToTuple(s) for dist, s in dist_stop_list]
 
   def handle_json_GET_boundboxstops(self, params):
     """Return a list of up to 'limit' stops within bounding box with 'n','e'
@@ -421,23 +485,69 @@
       if s.stop_id.lower() == query:
         return StopToTuple(s)
     return []
+  def handle_json_GET_stoproutes(self, params):
+    """Given a stop_id return all routes to visit the stop."""
+    schedule = self.server.schedule
+    stop = schedule.GetStop(params.get('stop', None))
+    service_period = params.get('service_period', None)
+    trips = stop.GetTrips(schedule)
+    result = {}
+    for trip in trips:
+      route = schedule.GetRoute(trip.route_id)
+      if not trip.route_short_name+route.route_long_name in result:
+        result[trip.route_short_name+route.route_long_name] = (route.route_id, route.route_short_name, route.route_long_name, trip.trip_id)
+    return result
+    
+  def handle_json_GET_stopalltrips(self, params):
+    """Given a stop_id return all trips to visit the stop."""
+    schedule = self.server.schedule
+    stop = schedule.GetStop(params.get('stop', None))
+    service_period = params.get('service_period', None)
+    time_trips = stop.GetStopTimeTrips(schedule)
+    result = []
+    for time, (trip, index), tp in time_trips:
+      headsign = None
+      # Find the most recent headsign from the StopTime objects
+      for stoptime in trip.GetStopTimes()[index::-1]:
+        if stoptime.stop_headsign:
+          headsign = stoptime.stop_headsign
+          break
+      # If stop_headsign isn't found, look for a trip_headsign
+      if not headsign:
+        headsign = trip.trip_headsign
+      route = schedule.GetRoute(trip.route_id)
+      trip_name = ''
+      if route.route_short_name:
+        trip_name += route.route_short_name
+      if route.route_long_name:
+        if len(trip_name):
+          trip_name += " - "
+        trip_name += route.route_long_name
+      if service_period == None or trip.service_id == service_period:
+        result.append((time, (trip.trip_id, trip_name, trip.service_id), tp))
+    return result
 
   def handle_json_GET_stoptrips(self, params):
     """Given a stop_id and time in seconds since midnight return the next
     trips to visit the stop."""
     schedule = self.server.schedule
     stop = schedule.GetStop(params.get('stop', None))
-    time = int(params.get('time', 0))
+    requested_time = int(params.get('time', 0))
     limit = int(params.get('limit', 15))
     service_period = params.get('service_period', None)
-    time_trips = stop.GetStopTimeTrips(schedule)
-    time_trips.sort()  # OPT: use bisect.insort to make this O(N*ln(N)) -> O(N)
-    # Keep the first 15 after param 'time'.
-    # Need make a tuple to find correct bisect point
-    time_trips = time_trips[bisect.bisect_left(time_trips, (time, 0)):]
-    time_trips = time_trips[:15]
+    time_range = int(params.get('time_range', 24*60*60))
+    
+    
+    filtered_time_trips = []
+    for trip, index in stop._GetTripIndex(schedule):
+      tripstarttime = trip.GetStartTime()
+      if tripstarttime > requested_time and tripstarttime < (requested_time + time_range):
+        time, stoptime, tp = trip.GetTimeInterpolatedStops()[index]
+        if time > requested_time and time < (requested_time + time_range):
+          bisect.insort(filtered_time_trips, (time, (trip, index), tp))
+    
     result = []
-    for time, (trip, index), tp in time_trips:
+    for time, (trip, index), tp in filtered_time_trips:
       if len(result) > limit:
         break
       headsign = None