--- a/schedule_viewer.py +++ b/schedule_viewer.py @@ -286,7 +286,7 @@ 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 +294,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 +349,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 +468,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