From: maxious Date: Sun, 27 Feb 2011 05:49:00 +0000 Subject: Merge branch 'master' of ssh://apples.lambdacomplex.org/git/bus X-Git-Url: https://maxious.lambdacomplex.org/git/?p=bus.git&a=commitdiff&h=bfaff533125ca5691ec33564982725011c3b3613 --- Merge branch 'master' of ssh://apples.lambdacomplex.org/git/bus --- --- /dev/null +++ b/betweenpoint.add.php @@ -1,1 +1,50 @@ +"); + $sql = "INSERT INTO stops (geohash,lat,lng) VALUES ('$geoPo', '$nodelat', '$nodelon')"; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } else { + echo "Inserted new point at $geoPo
"; + } + } + flush(); +?> --- /dev/null +++ b/betweenpoint.delete.php @@ -1,1 +1,33 @@ - +\n"); + } else { + echo "Deleted {$_REQUEST['oldgeopo']}
"; + $updatedroutes = 0; + $result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'"); + while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) { + $newpoints = str_replace($_REQUEST['oldgeopo'].';', '', $outdatedroute['points']); + $sql = "UPDATE between_stops set points='$newpoints' where fromlocation = '{$outdatedroute['fromlocation']}' AND tolocation = '{$outdatedroute['tolocation']}' "; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } + echo "updated ".$outdatedroute['fromlocation']."->".$outdatedroute['tolocation']."
"; + + $updatedroutes++; + } + echo "updated $updatedroutes routes
"; + } + } + flush(); +?> --- /dev/null +++ b/betweenpoint.move.php @@ -1,1 +1,95 @@ - +"); + $sql = "UPDATE stops SET geohash='$geoPo', lat='$nodelat', lng='$nodelon', name=null, suburb=null WHERE geohash = '{$_REQUEST['oldgeopo']}'"; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } else if (pg_affected_rows($result) == 0) { + echo ("Error 0 points moved, please refresh page and try again"); + } else { + echo $_REQUEST['oldgeopo'] . " replaced with $geoPo
"; + $updatedroutes = 0; + $result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'"); + while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) { + $newpoints = str_replace($_REQUEST['oldgeopo'], $geoPo, $outdatedroute['points']); + $sql = "UPDATE between_stops set points='$newpoints' where + fromlocation = '".pg_escape_string($outdatedroute['fromlocation']). + "' AND tolocation = '".pg_escape_string($outdatedroute['tolocation'])."' "; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } + echo "updated ".$outdatedroute['fromlocation']."->".$outdatedroute['tolocation']."
"; + $updatedroutes++; + } + echo "updated $updatedroutes routes
"; + } + } + flush(); +?> --- a/betweenpoint.php +++ b/betweenpoint.php @@ -10,11 +10,46 @@ // create the ol map object var map = new OpenLayers.Map('map'); - var osmtiles = new OpenLayers.Layer.OSM("local", "http://127.0.0.1/tiles/${z}/${x}/${y}.png") + var osmtiles = new OpenLayers.Layer.OSM("local", "/tiles/${z}/${x}/${y}.png") // use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles markers = new OpenLayers.Layer.Markers("Between Stop Markers"); - + //hanlde mousedown on regions that are not points by reporting latlng +OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, { + defaultHandlerOptions: { + 'single': true, + 'double': false, + 'pixelTolerance': 0, + 'stopSingle': false, + 'stopDouble': false + }, + + initialize: function(options) { + this.handlerOptions = OpenLayers.Util.extend( + {}, this.defaultHandlerOptions + ); + OpenLayers.Control.prototype.initialize.apply( + this, arguments + ); + this.handler = new OpenLayers.Handler.Click( + this, { + 'click': this.trigger + }, this.handlerOptions + ); + }, + + trigger: function(e) { + var lonlat = map.getLonLatFromViewPortPx(e.xy).transform( + new OpenLayers.Projection("EPSG:900913"), + new OpenLayers.Projection("EPSG:4326") + ); + $('form input[name="newlatlng"]').val(lonlat.lat + ";" + lonlat.lon ); + } + + }); + var click = new OpenLayers.Control.Click(); + map.addControl(click); + click.activate(); -var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32)); +var timeicon = new OpenLayers.Icon("icong.png",new OpenLayers.Size(16,16)); var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon }); map.addLayers([osmtiles, markers,timepoints]); @@ -51,11 +88,31 @@ function submitBetween () { $.post("betweenpoint.submit.php", $("#inputform").serialize(), function(html){ $("#response").html(html); - //clearForms(); - return false; - }); -}; - + clearForms(); + return false; + }); +}; +function submitMove () { + $.post("betweenpoint.move.php", $("#moveform").serialize(), function(html){ + $("#response").html(html); + clearForms(); + return false; + }); +}; +function submitDelete () { + $.post("betweenpoint.delete.php", $("#moveform").serialize(), function(html){ + $("#response").html(html); + clearForms(); + return false; + }); +}; +function submitAdd () { + $.post("betweenpoint.add.php", $("#moveform").serialize(), function(html){ + $("#response").html(html); + clearForms(); + return false; + }); +}; function OnChange(dropdown) { var myindex = dropdown.selectedIndex @@ -129,7 +186,9 @@ // Strip off individual platforms because it usually doesn't matter for routes $timetable["time_points"] = preg_replace("/\(Platform.*/","",$timetable["time_points"]); for ($i = 0; $i < sizeof($timetable["time_points"]) - 1; $i++) { - @$paths[trim($timetable["time_points"][$i]) . "->" . trim($timetable["time_points"][$i + 1])] .= $timetable["short_name"] . ";"; + $key = trim($timetable["time_points"][$i]) . "->" . trim($timetable["time_points"][$i + 1]); + if (strstr($paths[$key],";" . $timetable["short_name"] . ";") === false) + @$paths[$key] .= $timetable["short_name"] . ";"; } } } @@ -139,28 +198,35 @@ $completedPaths = array(); $result_betweenstops = pg_query($conn, "Select * FROM between_stops"); while ($path = pg_fetch_assoc($result_betweenstops)) { - $completedPaths[trim($path['fromlocation']) . "->" . trim($path['tolocation'])] .= trim($path['routes']); - } - + $key = trim($path['fromlocation']) . "->" . trim($path['tolocation']); + $completedPaths[$key].= trim($path['routes']); + + } + + $processed = 0; foreach ($paths as $path => $routes) { if (!in_array($path, array_keys($completedPaths))) { - echo "\n"; + echo "\n"; + $processed++; } else { $completedRoutes = explode(";", $completedPaths[$path]); $incompleteRoutes = ""; foreach (explode(";", $routes) as $route) { - if (!in_array($route,$completedRoutes)) { + if (!in_array($route,$completedRoutes) && strstr($incompleteRoutes,';'.$route.';') === false) { $incompleteRoutes .= $route.';'; } } - if ($incompleteRoutes != "") echo "\n"; + if ($incompleteRoutes != "") { + echo "\n"; + $processed++; + } } } + echo "$processed"; ?> - from to
@@ -171,6 +237,13 @@
+
+oldgeopo +newlatlng + + + +
--- a/betweenpoint.submit.php +++ b/betweenpoint.submit.php @@ -5,9 +5,9 @@ exit; } print_r($_REQUEST); -$reverse=$_REQUEST["reverse"]; -$from=$_REQUEST["from"]; -$to=$_REQUEST["to"]; +$reverse=(isset($_REQUEST["reverse"]) ? $_REQUEST["reverse"] : "off"); +$from=pg_escape_string($_REQUEST["from"]); +$to=pg_escape_string($_REQUEST["to"]); $routes=$_REQUEST["routes"] ; $points=$_REQUEST["between_points"]; $sql = "INSERT INTO between_stops (fromLocation, toLocation, points, routes) VALUES('$from','$to','$points','$routes')"; @@ -16,9 +16,11 @@ echo("Error in SQL query: " . pg_last_error() ."
\n"); } if ($reverse === "on") { - $p = implode(";",array_reverse(explode(";",$points))).";"; - $points = str_replace(";","",$p,1); -$sql = "INSERT INTO between_stops ( toLocation, fromLocation, points, routes) VALUES('$from','$to','$points','$routes')"; + $ep = explode(";",$points); + $epr = array_reverse($ep); + $p = implode(";",$epr).";"; + $pointsString = substr($p,1); +$sql = "INSERT INTO between_stops ( toLocation, fromLocation, points, routes) VALUES('$from','$to','$pointsString','$routes')"; $result = pg_query($conn, $sql); if (!$result) { echo("Error in SQL query: " . pg_last_error() ."
\n"); --- a/busui/common.inc.php +++ /dev/null @@ -1,90 +1,1 @@ - - - - bus.lambdacomplex.org - '.$pageTitle.' - - - - - - - - - - -
- -
-

'.$pageTitle.'

-
-
'; -} - -function include_footer() -{ - echo '
'; -} - -function service_period() -{ -switch (date('w')){ - -case 0: - return 'sunday'; -case 6: - return 'saturday'; -default: - return 'weekday'; -} -} - -function midnight_seconds() -{ -// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html - $secs = (date("G") * 3600) + (date("i") * 60) + date("s"); - return $secs; -} - -function midnight_seconds_to_time($seconds) -{ - $midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); - return date("h:ia",$midnight+$seconds); -} -function getPage($url) -{ - $ch = curl_init($url); -curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); -curl_setopt( $ch, CURLOPT_HEADER, 0 ); -$page = curl_exec($ch); -curl_close($ch); -return $page; -} -function array_flatten($a,$f=array()){ - if(!$a||!is_array($a))return ''; - foreach($a as $k=>$v){ - if(is_array($v))$f=array_flatten($v,$f); - else $f[$k]=$v; - } - return $f; -} -?> - - --- a/busui/index.php +++ /dev/null @@ -1,66 +1,1 @@ - - - - - - bus.lambdacomplex.org - - - - - - - - -
-
-

bus.lambdacomplex.org

-
-
- - -
-

- Time:
- Service Period: -
-
-
- - --- a/busui/readme.txt +++ /dev/null @@ -1,23 +1,1 @@ -# input location (via GPS or favourites or search) and destination (via searchable list, optional) -# http://10.0.1.153:8765/json/boundboxstops?n=-35.27568499917103&e=149.1346514225006&s=-35.279495003493516 -&w=149.12622928619385&limit=50 -# http://10.0.1.153:8765/json/stoptrips?stop=43&time=64440 # recursively call to show all services nearby, sort by distance, need to filter by service period -# Hey, can pick destination again from a list filtered to places these stops go if you're curious! -# http://10.0.1.153:8765/json/tripstoptimes?trip=2139 # Can recursively call and parse based on intended destination to show ETA -# http://10.0.1.153:8765/json/triprows?trip=2139 # For pretty maps -have to do -/usr/sbin/setsebool -P httpd_can_network_connect=1 -on fedora - -might need http://forum.jquery.com/topic/google-maps-inside-jquery-mobile - -some extras -/json/routes = all routes -/json/neareststops?lat/lng/number -TODO -Destinations -Favourites -OOP stops/routes -Stop sorting/search-filter - --- a/busui/route.php +++ /dev/null --- a/busui/routeList.php +++ /dev/null @@ -1,34 +1,1 @@ -'; -echo "";*/ -echo ' \n"; -/* -
-
- -
-*/ -include_footer(); -?> - --- a/busui/schedule_viewer.py +++ /dev/null @@ -1,545 +1,1 @@ -#!/usr/bin/python2.5 -# Copyright (C) 2007 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -An example application that uses the transitfeed module. - -You must provide a Google Maps API key. -""" - - -import BaseHTTPServer, sys, urlparse -import bisect -from gtfsscheduleviewer.marey_graph import MareyGraph -import gtfsscheduleviewer -import mimetypes -import os.path -import re -import signal -import simplejson -import socket -import time -import transitfeed -from transitfeed import util -import urllib - - -# By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break -# raise a KeyboardInterrupt. -if hasattr(signal, 'SIGBREAK'): - signal.signal(signal.SIGBREAK, signal.default_int_handler) - - -mimetypes.add_type('text/plain', '.vbs') - - -class ResultEncoder(simplejson.JSONEncoder): - def default(self, obj): - try: - iterable = iter(obj) - except TypeError: - pass - else: - return list(iterable) - return simplejson.JSONEncoder.default(self, obj) - -# Code taken from -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt -# An alternate approach is shown at -# http://mail.python.org/pipermail/python-list/2003-July/212751.html -# but it requires multiple threads. A sqlite object can only be used from one -# thread. -class StoppableHTTPServer(BaseHTTPServer.HTTPServer): - def server_bind(self): - BaseHTTPServer.HTTPServer.server_bind(self) - self.socket.settimeout(1) - self._run = True - - def get_request(self): - while self._run: - try: - sock, addr = self.socket.accept() - sock.settimeout(None) - return (sock, addr) - except socket.timeout: - pass - - def stop(self): - self._run = False - - def serve(self): - while self._run: - self.handle_request() - - -def StopToTuple(stop): - """Return tuple as expected by javascript function addStopMarkerFromList""" - return (stop.stop_id, stop.stop_name, float(stop.stop_lat), - float(stop.stop_lon), stop.location_type) - - -class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def do_GET(self): - scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) - parsed_params = {} - for k in params.split('&'): - k = urllib.unquote(k) - if '=' in k: - k, v = k.split('=', 1) - parsed_params[k] = unicode(v, 'utf8') - else: - parsed_params[k] = '' - - if path == '/': - return self.handle_GET_home() - - m = re.match(r'/json/([a-z]{1,64})', path) - if m: - handler_name = 'handle_json_GET_%s' % m.group(1) - handler = getattr(self, handler_name, None) - if callable(handler): - return self.handle_json_wrapper_GET(handler, parsed_params) - - # Restrict allowable file names to prevent relative path attacks etc - m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path) - if m and m.group(1): - try: - f, mime_type = self.OpenFile(m.group(1)) - return self.handle_static_file_GET(f, mime_type) - except IOError, e: - print "Error: unable to open %s" % m.group(1) - # Ignore and treat as 404 - - m = re.match(r'/([a-z]{1,64})', path) - if m: - handler_name = 'handle_GET_%s' % m.group(1) - handler = getattr(self, handler_name, None) - if callable(handler): - return handler(parsed_params) - - return self.handle_GET_default(parsed_params, path) - - def OpenFile(self, filename): - """Try to open filename in the static files directory of this server. - Return a tuple (file object, string mime_type) or raise an exception.""" - (mime_type, encoding) = mimetypes.guess_type(filename) - assert mime_type - # A crude guess of when we should use binary mode. Without it non-unix - # platforms may corrupt binary files. - if mime_type.startswith('text/'): - mode = 'r' - else: - mode = 'rb' - return open(os.path.join(self.server.file_dir, filename), mode), mime_type - - def handle_GET_default(self, parsed_params, path): - self.send_error(404) - - def handle_static_file_GET(self, fh, mime_type): - content = fh.read() - self.send_response(200) - self.send_header('Content-Type', mime_type) - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - def AllowEditMode(self): - return False - - def handle_GET_home(self): - schedule = self.server.schedule - (min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() - forbid_editing = ('true', 'false')[self.AllowEditMode()] - - agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') - - key = self.server.key - host = self.server.host - - # A very simple template system. For a fixed set of values replace [xxx] - # with the value of local variable xxx - f, _ = self.OpenFile('index.html') - content = f.read() - for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', - 'host', 'forbid_editing'): - content = content.replace('[%s]' % v, str(locals()[v])) - - self.send_response(200) - self.send_header('Content-Type', 'text/html') - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - def handle_json_GET_routepatterns(self, params): - """Given a route_id generate a list of patterns of the route. For each - pattern include some basic information and a few sample trips.""" - schedule = self.server.schedule - route = schedule.GetRoute(params.get('route', None)) - if not route: - self.send_error(404) - return - time = int(params.get('time', 0)) - sample_size = 10 # For each pattern return the start time for this many trips - - pattern_id_trip_dict = route.GetPatternIdTripDict() - patterns = [] - - for pattern_id, trips in pattern_id_trip_dict.items(): - time_stops = trips[0].GetTimeStops() - if not time_stops: - continue - has_non_zero_trip_type = False; - for trip in trips: - if trip['trip_type'] and trip['trip_type'] != '0': - has_non_zero_trip_type = True - name = u'%s to %s, %d stops' % (time_stops[0][2].stop_name, time_stops[-1][2].stop_name, len(time_stops)) - transitfeed.SortListOfTripByTime(trips) - - num_trips = len(trips) - if num_trips <= sample_size: - start_sample_index = 0 - num_after_sample = 0 - else: - # Will return sample_size trips that start after the 'time' param. - - # Linear search because I couldn't find a built-in way to do a binary - # search with a custom key. - start_sample_index = len(trips) - for i, trip in enumerate(trips): - if trip.GetStartTime() >= time: - start_sample_index = i - break - - num_after_sample = num_trips - (start_sample_index + sample_size) - if num_after_sample < 0: - # Less than sample_size trips start after 'time' so return all the - # last sample_size trips. - num_after_sample = 0 - start_sample_index = num_trips - sample_size - - sample = [] - for t in trips[start_sample_index:start_sample_index + sample_size]: - sample.append( (t.GetStartTime(), t.trip_id) ) - - patterns.append((name, pattern_id, start_sample_index, sample, - num_after_sample, (0,1)[has_non_zero_trip_type])) - - patterns.sort() - return patterns - - def handle_json_wrapper_GET(self, handler, parsed_params): - """Call handler and output the return value in JSON.""" - schedule = self.server.schedule - result = handler(parsed_params) - content = ResultEncoder().encode(result) - self.send_response(200) - self.send_header('Content-Type', 'text/plain') - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - def handle_json_GET_routes(self, params): - """Return a list of all routes.""" - schedule = self.server.schedule - result = [] - for r in schedule.GetRouteList(): - result.append( (r.route_id, r.route_short_name, r.route_long_name) ) - 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_triprows(self, params): - """Return a list of rows from the feed file that are related to this - trip.""" - schedule = self.server.schedule - try: - trip = schedule.GetTrip(params.get('trip', None)) - except KeyError: - # if a non-existent trip is searched for, the return nothing - return - route = schedule.GetRoute(trip.route_id) - trip_row = dict(trip.iteritems()) - route_row = dict(route.iteritems()) - return [['trips.txt', trip_row], ['routes.txt', route_row]] - - def handle_json_GET_tripstoptimes(self, params): - schedule = self.server.schedule - try: - trip = schedule.GetTrip(params.get('trip')) - except KeyError: - # if a non-existent trip is searched for, the return nothing - return - time_stops = trip.GetTimeStops() - stops = [] - times = [] - for arr,dep,stop in time_stops: - stops.append(StopToTuple(stop)) - times.append(arr) - return [stops, times] - - def handle_json_GET_tripshape(self, params): - schedule = self.server.schedule - try: - trip = schedule.GetTrip(params.get('trip')) - except KeyError: - # if a non-existent trip is searched for, the return nothing - return - points = [] - if trip.shape_id: - shape = schedule.GetShape(trip.shape_id) - for (lat, lon, dist) in shape.points: - points.append((lat, lon)) - else: - time_stops = trip.GetTimeStops() - for arr,dep,stop in time_stops: - points.append((stop.stop_lat, stop.stop_lon)) - return points - - 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] - - def handle_json_GET_boundboxstops(self, params): - """Return a list of up to 'limit' stops within bounding box with 'n','e' - and 's','w' in the NE and SW corners. Does not handle boxes crossing - longitude line 180.""" - schedule = self.server.schedule - n = float(params.get('n')) - e = float(params.get('e')) - s = float(params.get('s')) - w = float(params.get('w')) - limit = int(params.get('limit')) - stops = schedule.GetStopsInBoundingBox(north=n, east=e, south=s, west=w, n=limit) - return [StopToTuple(s) for s in stops] - - def handle_json_GET_stops(self, params): - schedule = self.server.schedule - return [StopToTuple(s) for s in schedule.GetStopList()] - - def handle_json_GET_timingpoints(self, params): - schedule = self.server.schedule - matches = [] - for s in schedule.GetStopList(): - if s.stop_code.find("Wj") == -1: - matches.append(StopToTuple(s)) - return matches - - def handle_json_GET_stopsearch(self, params): - schedule = self.server.schedule - query = params.get('q', None).lower() - matches = [] - for s in schedule.GetStopList(): - if s.stop_id.lower().find(query) != -1 or s.stop_name.lower().find(query) != -1: - matches.append(StopToTuple(s)) - return matches - - def handle_json_GET_stop(self, params): - schedule = self.server.schedule - query = params.get('stop_id', None).lower() - for s in schedule.GetStopList(): - if s.stop_id.lower() == query: - return StopToTuple(s) - return [] - - 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)) - 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] - # TODO: combine times for a route to show next 2 departure times - 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 headsign: - trip_name += " (Direction: %s)" % headsign - 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_GET_ttablegraph(self,params): - """Draw a Marey graph in SVG for a pattern (collection of trips in a route - that visit the same sequence of stops).""" - schedule = self.server.schedule - marey = MareyGraph() - trip = schedule.GetTrip(params.get('trip', None)) - route = schedule.GetRoute(trip.route_id) - height = int(params.get('height', 300)) - - if not route: - print 'no such route' - self.send_error(404) - return - - pattern_id_trip_dict = route.GetPatternIdTripDict() - pattern_id = trip.pattern_id - if pattern_id not in pattern_id_trip_dict: - print 'no pattern %s found in %s' % (pattern_id, pattern_id_trip_dict.keys()) - self.send_error(404) - return - triplist = pattern_id_trip_dict[pattern_id] - - pattern_start_time = min((t.GetStartTime() for t in triplist)) - pattern_end_time = max((t.GetEndTime() for t in triplist)) - - marey.SetSpan(pattern_start_time,pattern_end_time) - marey.Draw(triplist[0].GetPattern(), triplist, height) - - content = marey.Draw() - - self.send_response(200) - self.send_header('Content-Type', 'image/svg+xml') - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - -def FindPy2ExeBase(): - """If this is running in py2exe return the install directory else return - None""" - # py2exe puts gtfsscheduleviewer in library.zip. For py2exe setup.py is - # configured to put the data next to library.zip. - windows_ending = gtfsscheduleviewer.__file__.find('\\library.zip\\') - if windows_ending != -1: - return transitfeed.__file__[:windows_ending] - else: - return None - - -def FindDefaultFileDir(): - """Return the path of the directory containing the static files. By default - the directory is called 'files'. The location depends on where setup.py put - it.""" - base = FindPy2ExeBase() - if base: - return os.path.join(base, 'schedule_viewer_files') - else: - # For all other distributions 'files' is in the gtfsscheduleviewer - # directory. - base = os.path.dirname(gtfsscheduleviewer.__file__) # Strip __init__.py - return os.path.join(base, 'files') - - -def GetDefaultKeyFilePath(): - """In py2exe return absolute path of file in the base directory and in all - other distributions return relative path 'key.txt'""" - windows_base = FindPy2ExeBase() - if windows_base: - return os.path.join(windows_base, 'key.txt') - else: - return 'key.txt' - - -def main(RequestHandlerClass = ScheduleRequestHandler): - usage = \ -'''%prog [options] [] - -Runs a webserver that lets you explore a in your browser. - -If is omited the filename is read from the console. Dragging -a file into the console may enter the filename. -''' - parser = util.OptionParserLongError( - usage=usage, version='%prog '+transitfeed.__version__) - parser.add_option('--feed_filename', '--feed', dest='feed_filename', - help='file name of feed to load') - parser.add_option('--key', dest='key', - help='Google Maps API key or the name ' - 'of a text file that contains an API key') - parser.add_option('--host', dest='host', help='Host name of Google Maps') - parser.add_option('--port', dest='port', type='int', - help='port on which to listen') - parser.add_option('--file_dir', dest='file_dir', - help='directory containing static files') - parser.add_option('-n', '--noprompt', action='store_false', - dest='manual_entry', - help='disable interactive prompts') - parser.set_defaults(port=8765, - host='maps.google.com', - file_dir=FindDefaultFileDir(), - manual_entry=True) - (options, args) = parser.parse_args() - - if not os.path.isfile(os.path.join(options.file_dir, 'index.html')): - print "Can't find index.html with --file_dir=%s" % options.file_dir - exit(1) - - if not options.feed_filename and len(args) == 1: - options.feed_filename = args[0] - - if not options.feed_filename and options.manual_entry: - options.feed_filename = raw_input('Enter Feed Location: ').strip('"') - - default_key_file = GetDefaultKeyFilePath() - if not options.key and os.path.isfile(default_key_file): - options.key = open(default_key_file).read().strip() - - if options.key and os.path.isfile(options.key): - options.key = open(options.key).read().strip() - - schedule = transitfeed.Schedule(problem_reporter=transitfeed.ProblemReporter()) - print 'Loading data from feed "%s"...' % options.feed_filename - print '(this may take a few minutes for larger cities)' - schedule.Load(options.feed_filename) - - server = StoppableHTTPServer(server_address=('', options.port), - RequestHandlerClass=RequestHandlerClass) - server.key = options.key - server.schedule = schedule - server.file_dir = options.file_dir - server.host = options.host - server.feed_path = options.feed_filename - - print ("To view, point your browser at http://localhost:%d/" % - (server.server_port)) - server.serve_forever() - - -if __name__ == '__main__': - main() - --- a/busui/stop.php +++ /dev/null @@ -1,18 +1,1 @@ -'; -$url = $APIurl."/json/stoptrips?stop=".$_REQUEST['stopid']."&time=".midnight_seconds()."&service_period=".service_period(); -$page = getPage($url); -echo $page; -foreach (json_decode($page) as $row) -{ -echo '
  • '.midnight_seconds_to_time($row[0]).' '.$row[1][1].'
  • '; -} -echo ''; -include_footer(); -?> - --- a/busui/stopList.php +++ /dev/null @@ -1,34 +1,1 @@ -'; -$url = $APIurl."/json/timingpoints"; -if ($_REQUEST['allstops']) $url = $APIurl."/json/stops"; -if ($_REQUEST['lat'] && $_REQUEST['lon']) $url = $APIurl."/json/neareststops?lat={$_REQUEST['lat']}&lon={$_REQUEST['lon']}&limit=15"; -$contents = json_decode(getPage($url)); -foreach ($contents as $key => $row) { - $stopName[$key] = $row[1]; -} -// Sort the data with volume descending, edition ascending -// Add $data as the last parameter, to sort by the common key -array_multisort($stopName, SORT_ASC, $contents); - -foreach ($contents as $row) -{ - - echo '
  • '.$row[1].'
  • '; - } -echo ''; -echo' -
    -
    - - '; -include_footer(); -?> - - --- a/busui/trip.php +++ /dev/null @@ -1,25 +1,1 @@ -route_short_name . ' '. $trips[1]->route_long_name); -echo '
      '; - - - - -$url = $APIurl."/json/tripstoptimes?trip=".$_REQUEST['tripid']; - -$json = json_decode(getPage($url)); -$stops = $json[0]; -$times = $json[1]; -foreach ($stops as $key => $row) -{ -echo '
    • '.midnight_seconds_to_time($times[$key]).' '.$row[1].'
    • '; -} -echo '
    '; -include_footer(); -?> - --- a/busui/view.sh +++ /dev/null @@ -1,8 +1,1 @@ -# input location (via GPS or favourites or search) and destination (via searchable list, optional) -# http://10.0.1.153:8765/json/boundboxstops?n=-35.27568499917103&e=149.1346514225006&s=-35.279495003493516&w=149.12622928619385&limit=50 -# http://10.0.1.153:8765/json/stoptrips?stop=43&time=64440 # recursively call to show all services nearby, sort by distance, need to filter by service period -# Hey, can pick destination again from a list filtered to places these stops go if you're curious! -# http://10.0.1.153:8765/json/tripstoptimes?trip=2139 # Can recursively call and parse based on intended destination to show ETA -# http://10.0.1.153:8765/json/triprows?trip=2139 # For pretty maps -python schedule_viewer.py --feed=../maxious-canberra-transit-feed/cbrfeed.zip --key=ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q --- a/display.php +++ b/display.php @@ -18,7 +18,7 @@ // create the ol map object var map = new OpenLayers.Map('map', options); -var osmtiles = new OpenLayers.Layer.OSM("local", "http://10.0.1.153/tiles/${z}/${x}/${y}.png"); +var osmtiles = new OpenLayers.Layer.OSM("local", "http://10.0.1.154/tiles/${z}/${x}/${y}.png"); // use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles var graphic = new OpenLayers.Layer.Image( 'Weekday Bus Map', --- a/displaytimepoints.georss.php +++ b/displaytimepoints.georss.php @@ -17,7 +17,7 @@ echo ""; echo "".htmlspecialchars ($timepoint['name']).""; echo "".htmlspecialchars($timepoint['name']).""; -echo " ".($timepoint['lat']/10000000)." ".($timepoint['lng']/10000000).""; +echo " ".($timepoint['lat']/10000001)." ".($timepoint['lng']/10000000).""; echo "\n"; } --- a/maxious-canberra-transit-feed/01-extracttimes.rb +++ b/maxious-canberra-transit-feed/01-extracttimes.rb @@ -14,10 +14,15 @@ timetable = {"between_stops" => [], "short_name" => short_name} time_points = table.xpath('tr[1]//th').map do |tp| if tp.content != "\302\240" && tp.content != "" && tp.content != "
    " - timing_point = tp.content.squeeze(" ").gsub("Bus Station"," Bus Station ").gsub(" Platform"," (Platform").gsub(" - "," - ").gsub("\n"," ").gsub("\r"," ").gsub("\t"," ").gsub("\\"," / ").gsub("/"," / ").gsub(","," ").gsub("\302\240","").squeeze(" ").strip + timing_point = tp.content.squeeze(" ").gsub("Shops"," ").gsub("Bus Station"," Bus Station ").gsub("Interchange"," Bus Station ").gsub(" Platform"," (Platform") + timing_point = timing_point.gsub("Machonochie","Maconochie").gsub("Hume"," ").gsub("Market Place","Marketplace").gsub("Terminus Fyshwick","Terminus") + timing_point = timing_point.gsub(" - "," - ").gsub("\n"," ").gsub("\r"," ").gsub("\t"," ").gsub("\\"," / ").gsub("/"," / ").gsub(","," ").gsub("\302\240","").squeeze(" ").strip + if (short_name == "923" or short_name == "924" or short_name == "938") and timing_point == "Pearce" + timing_point = "Canberra Hospital" + end if (tp.content.match('Platform')) timing_point.concat(")") - end; + end if tp.to_s.match(/[0-9][0-9][0-9]/) or tp.to_s.include? "Wheelchair" timing_point = nil end @@ -79,7 +84,9 @@ timetables << makeTimetable(table, "stop_times", short_name) end doc.xpath('//table[preceding::text()="This timetable is effective from Monday 15th November 2010."]').each do |table| - timetables << makeTimetable(table, "stop_times", short_name) + if short_name[0].chr != "9" or short_name.size == 1 + timetables << makeTimetable(table, "stop_times", short_name) + end end #all tables are weekdays on some really malformatted timetables if short_name == "170" --- a/maxious-canberra-transit-feed/02-tidytimepoints.rb +++ b/maxious-canberra-transit-feed/02-tidytimepoints.rb @@ -32,9 +32,9 @@ "Bridbabella GardensNursing Home"=> "Brindabella Gardens Nursing Home", "BrindabellaBusiness Park"=> "Brindabella Business Park", "NarrabundahTerminus"=>"Narrabundah Terminus", + "Narrabundah"=>"Narrabundah Terminus", "Railway StationKingston"=>"Railway Station Kingston", "Saint AndrewsVillage Hughes"=>"Saint Andrews Village Hughes", - "Dickson ShopsAntill Street"=>"Dickson Shops", "Cohen St Bus Station (Platform 3)" => "Cohen Street Bus Station (Platform 3)", "Cohen St Bus Station (Platform 6)" => "Cohen Street Bus Station (Platform 6)", "Newcastle Streetafter Isa Street" => "Newcastle Street after Isa Street", @@ -52,8 +52,9 @@ "Flemington Road / Nullabor Ave"=>"Flemington Rd / Nullabor Ave", "Flemington Road / Sandford St"=>"Flemington Rd / Sandford St", "Heagney Cres Clift Cres Richardson"=> "Heagney / Clift Richardson", - "Charnwood Shops (Tillyard Drive)"=> "Charnwood Shops", - "charnwood Shops"=> "Charnwood Shops", + "Charnwood (Tillyard Drive)"=> "Charnwood", + "Charnwood Tillyard Dr"=> "Charnwood", + "charnwood"=> "Charnwood", "Black Moutain- Telstra Tower"=>"Black Mountain Telstra Tower", "Bonython Primary"=> "Bonython Primary School", "Athllon Drive / Sulwood Dr Kambah"=>"Athllon / Sulwood Kambah", @@ -61,31 +62,40 @@ "Alexander Maconochie Centre Hume"=>"Alexander Maconochie Centre", "Anthony Rolfe Ave / Moonight Ave" =>"Anthony Rolfe Av / Moonlight Av", "Australian National Botanic Gardens"=>"Botanic Gardens", - "Calwell shops"=> "Calwell Shops", + "Calwell shops"=> "Calwell", "Chuculba / William Slim Drive"=>"Chuculba / William Slim Dr", "Fyshwick direct Factory Outlet"=>"Fyshwick Direct Factory Outlet", - "Kaleen Village / Maibrynong"=>"Kaleen Village / Marybrynong", - "Kaleen Village / Marybrynong Ave"=>"Kaleen Village / Marybrynong", + "Kaleen Village / Maibrynong"=>"Kaleen Village / Maribrynong", + "Kaleen Village / Marybrynong Ave"=>"Kaleen Village / Maribrynong", "National Aquarium"=>"National Zoo and Aquarium", - "chisholm Shops"=>"Chisholm Shops", - "O'connor Shops"=>"O'Connor Shops", - "Mckellar Shops"=>"McKellar Shops", - "Melba shops"=> "Melba Shops", + "chisholm"=>"Chisholm", + "O'connor"=>"O'Connor", + "Mckellar"=>"McKellar", "William Web / Ginninderra Drive"=>"William Webb / Ginninderra Drive", "Procor / Mead"=>"Proctor / Mead", "Fyshwick DirectFactory Outlet"=>"Fyshwick Direct Factory Outlet", - "Yarrulumla Shops"=>"Yarralumla Shops", - "Tharwa Dr / Pocket Ave"=>"Tharwa Dr / Pockett Ave", + "Yarrulumla"=>"Yarralumla", "Paul Coe / Mirrebei Dr"=>"Paul Coe / Mirrabei Dr", "Mirrebei Drive / Dam Wall"=>"Mirrabei Drive / Dam Wall", - "Tharwa / Knoke" => "Tharwa Drive / Knoke Ave", - "Tharwa / Pocket" => "Tharwa Dr / Pockett Ave", + "Tharwa / Knoke" => "Tharwa Drive / Pockett Ave", + "Tharwa Drive / Knoke Ave" => "Tharwa Drive / Pockett Ave", + "Tharwa / Pocket" => "Tharwa Drive / Pockett Ave", + 'Tharwa Dr / Pockett Ave' => "Tharwa Drive / Pockett Ave", + "Tharwa Dr / Pocket Ave"=>"Tharwa Dr / Pockett Ave", "Outrim / Duggan" => "Outtrim / Duggan", "ANU Burton and Garran Hall Daley Rd" => "Burton and Garran Hall Daley Road", "Farrer Primary"=>"Farrer Primary School", "St Thomas More Campbell"=>"St Thomas More's Campbell", - "Lyneham Shops"=>"Lyneham Shops Wattle Street", - + "Lyneham"=>"Lyneham / Wattle St", + "Lyneham Wattle Street"=>"Lyneham / Wattle St", + "Dickson" => "Dickson / Cowper St", + 'Dickson Antill Street' => 'Dickson / Antill St', + "DicksonAntill Street"=> 'Dickson / Antill St', + "Livingston / Kambah" => "Kambah / Livingston St", + 'Melba shops' => 'Melba', + 'St Clare of Assisi' => 'St Clare of Assisi Primary', + 'War Memorial Limestone Ave' => 'War Memorial / Limestone Ave', + 'Flynn' => 'Kingsford Smith / Companion' } time_point_corrections.each do |wrong, right| --- a/maxious-canberra-transit-feed/03-locatetimepoints.rb +++ b/maxious-canberra-transit-feed/03-locatetimepoints.rb @@ -38,6 +38,7 @@ $time_points = [] $time_points_sources = Hash.new([]) Dir.glob("*.yml") { |file| + pp file timetable = YAML::load_file(file) $time_points = $time_points | timetable["time_points"] timetable["time_points"].each do |timepoint| --- a/maxious-canberra-transit-feed/04-generateymlinclude.rb +++ b/maxious-canberra-transit-feed/04-generateymlinclude.rb @@ -27,7 +27,6 @@ time_points.each do |time_point| #pp time_point # 0 = name - # 1 = lat*100000 # 2 = lng*100000 #pp time_point[0] @@ -45,8 +44,9 @@ # 1 = lat*100000 # 2 = lng*100000 # 3 = name + # 4 = suburb(s) #pp time_point[0] - f2.puts " - { name: #{stop[3]},stop_code: #{stop[0]}, lat: #{Float(stop[1])/10000000}, lng: #{Float(stop[2])/10000000}}" + f2.puts " - { name: #{stop[3]},stop_code: #{stop[0]}, lat: #{Float(stop[1])/10000000}, lng: #{Float(stop[2])/10000000}, zone_id: #{stop[4]} }" end f2.puts "routes:\n"; end --- a/maxious-canberra-transit-feed/04-locatebetweenpoints.osm.xml.php +++ b/maxious-canberra-transit-feed/04-locatebetweenpoints.osm.xml.php @@ -2,7 +2,7 @@ header('Content-Type: application/xml'); echo " "; $conn = pg_connect("dbname=openstreetmap user=postgres password=snmc"); --- a/maxious-canberra-transit-feed/04-locatebetweenpoints.reversegeocode.php +++ b/maxious-canberra-transit-feed/04-locatebetweenpoints.reversegeocode.php @@ -15,20 +15,40 @@ echo "An error occured.\n"; exit; } -$sql = "Select * from stops where name is null"; +$sql = "Select * from stops where name is null or suburb is null"; $result_stops = pg_query($conn, $sql); if (!$result_stops) { - cho("Error in SQL query: " . pg_last_error() ."
    \n"); + echo("Error in SQL query: " . pg_last_error() ."
    \n"); } while ($stop = pg_fetch_assoc($result_stops)) { - echo "Processing ".$stop['geohash'] . " ... "; + if ($stop['name'] == "") { + echo "Processing ".$stop['geohash'] . " streetname ... "; $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".($stop['lat']/10000000).",".($stop['lng']/10000000)."&distance=closest&object_type=road"; $contents = json_decode(getPage($url)); + //print_r($contents); $name = $contents->features[0]->properties->name; echo "Saving $name !
    " ; $result_save = pg_query($conn, "UPDATE stops set name = '".pg_escape_string($name)."' where geohash = '{$stop['geohash']}' "); if (!$result_save) { echo("Error in SQL query: " . pg_last_error() ."
    \n"); + } + } + if ($stop['suburb'] == "") { + echo "Processing ".$stop['geohash'] . " suburb ... "; + $sql = "select * from suburbs where the_geom @> 'POINT(".($stop['lng']/10000000)." ".($stop['lat']/10000000).")'::geometry"; + $result_suburbs = pg_query($conn, $sql); + if (!$result_suburbs) { + echo("Error in SQL query: " . pg_last_error() ."
    \n"); + } + $suburbs = ""; + while ($suburb = pg_fetch_assoc($result_suburbs)) { + $suburbs .= $suburb['name_2006'].";"; + } + echo "Saving $suburbs !
    " ; + $result_save = pg_query($conn, "UPDATE stops set suburb = '".pg_escape_string($suburbs)."' where geohash = '{$stop['geohash']}' "); + if (!$result_save) { + echo("Error in SQL query: " . pg_last_error() ."
    \n"); + } } flush(); } --- a/maxious-canberra-transit-feed/05-addbetweenpointstotimetables.rb +++ b/maxious-canberra-transit-feed/05-addbetweenpointstotimetables.rb @@ -36,7 +36,7 @@ #conn.close() if conn end between_points.each do |between_point_row| - points = between_point_row['points'].split(";") + points = between_point_row['points'].strip.split(";") points.delete("") timetable["between_stops"][timetable["time_points"][i] + '-' +timetable["time_points"][i+1]] = points; end --- a/maxious-canberra-transit-feed/cbrtable.yml +++ b/maxious-canberra-transit-feed/cbrtable.yml @@ -1,7 +1,7 @@ options: - start_date: 20090525 - end_date: 20101001 - remove_date: 20101001 + start_date: 20101115 + end_date: 20111231 + remove_date: 20111231 agency_name: ACT Internal Omnibus Network (ACTION) agency_url: http://www.action.act.gov.au/ agency_timezone: Australia/Sydney @@ -11,39 +11,29 @@ - { name: ACTEW AGL House,stop_code: ACTEW AGL House, lat: -35.282374, lng: 149.132047} - { name: ADFA,stop_code: ADFA, lat: -35.2937972, lng: 149.1643403} - { name: Ainslie,stop_code: Ainslie, lat: -35.2620105, lng: 149.1443302} - - { name: Ainslie Shops,stop_code: Ainslie Shops, lat: -35.26198, lng: 149.14535} - { name: Alexander Maconochie Centre,stop_code: Alexander Maconochie Centre, lat: -35.3720651, lng: 149.1696618} - - { name: Alpen & Clifford St,stop_code: Alpen & Clifford St, lat: -35.20562, lng: 149.06259} - { name: Anthony Rolfe Av / Moonlight Av,stop_code: Anthony Rolfe Av / Moonlight Av, lat: -35.1856021, lng: 149.1543639} - { name: Aranda,stop_code: Aranda, lat: -35.257534, lng: 149.0762963} - - { name: Aranda Shops,stop_code: Aranda Shops, lat: -35.25753, lng: 149.0763} - { name: Athllon / Sulwood Kambah,stop_code: Athllon / Sulwood Kambah, lat: -35.38442, lng: 149.09328} - { name: Australian Institute of Sport,stop_code: Australian Institute of Sport, lat: -35.246351, lng: 149.101478} - - { name: Belconnen Community Bus Station,stop_code: Belconnen Community Bus Station, lat: -35.23987, lng: 149.0619} + - { name: Belconnen Community Bus Station,stop_code: Belconnen Community Bus Station, lat: -35.2398858, lng: 149.0690795} - { name: Belconnen Community Bus Station (Platform 1),stop_code: Belconnen Community Bus Station (Platform 1), lat: -35.23982, lng: 149.06978} - { name: Belconnen Community Bus Station (Platform 2),stop_code: Belconnen Community Bus Station (Platform 2), lat: -35.23982, lng: 149.06926} - { name: Belconnen Community Bus Station (Platform 3),stop_code: Belconnen Community Bus Station (Platform 3), lat: -35.23986, lng: 149.06847} - { name: Belconnen Community Bus Station (Platform 4),stop_code: Belconnen Community Bus Station (Platform 4), lat: -35.23994, lng: 149.06887} - { name: Belconnen Community Bus Station (Platform 5),stop_code: Belconnen Community Bus Station (Platform 5), lat: -35.23994, lng: 149.06928} - { name: Belconnen Community Bus Station (Platform 6),stop_code: Belconnen Community Bus Station (Platform 6), lat: -35.23994, lng: 149.0698} - - { name: Belconnen Way,stop_code: Belconnen Way, lat: -35.24809, lng: 149.06765} + - { name: Belconnen Way,stop_code: Belconnen Way, lat: -35.2410162, lng: 149.0409512} - { name: Bimberi Centre,stop_code: Bimberi Centre, lat: -35.2219941, lng: 149.1546928} - { name: Black Mountain Telstra Tower,stop_code: Black Mountain Telstra Tower, lat: -35.2748058, lng: 149.0972461} - - { name: Bonython,stop_code: Bonython, lat: -35.4297416, lng: 149.0814517} - - { name: Bonython Primary School,stop_code: Bonython Primary School, lat: -35.431019, lng: 149.0831217} + - { name: Bonython Primary School,stop_code: Bonython Primary School, lat: -35.4297416, lng: 149.0814517} - { name: Botanic Gardens,stop_code: Botanic Gardens, lat: -35.278643, lng: 149.1093237} - { name: Brindabella Business Park,stop_code: Brindabella Business Park, lat: -35.314496, lng: 149.189145} - { name: Brindabella Gardens Nursing Home,stop_code: Brindabella Gardens Nursing Home, lat: -35.3294459, lng: 149.0806116} - - { name: Bugden Sternberg,stop_code: Bugden Sternberg, lat: -35.4017223, lng: 149.0992172} + - { name: Bugden Sternberg,stop_code: Bugden Sternberg, lat: -35.403233, lng: 149.1073117} - { name: Burton and Garran Hall Daley Road,stop_code: Burton and Garran Hall Daley Road, lat: -35.2753671, lng: 149.1172822} - { name: Calvary Hospital,stop_code: Calvary Hospital, lat: -35.25212, lng: 149.09088} - - { name: Calwell Shops,stop_code: Calwell Shops, lat: -35.43524, lng: 149.113942} - - { name: Cameron Ave Bus Station,stop_code: Cameron Ave Bus Station, lat: -35.2410195, lng: 149.0722506} - - { name: Cameron Ave Bus Station (Platform 1),stop_code: Cameron Ave Bus Station (Platform 1), lat: -35.2410195, lng: 149.0722506} - - { name: Cameron Ave Bus Station (Platform 2),stop_code: Cameron Ave Bus Station (Platform 2), lat: -35.2410108, lng: 149.0717142} - - { name: Cameron Ave Bus Station (Platform 3),stop_code: Cameron Ave Bus Station (Platform 3), lat: -35.2410064, lng: 149.0710758} - - { name: Cameron Ave Bus Station (Platform 4),stop_code: Cameron Ave Bus Station (Platform 4), lat: -35.2411773, lng: 149.0709793} - - { name: Cameron Ave Bus Station (Platform 5),stop_code: Cameron Ave Bus Station (Platform 5), lat: -35.241186, lng: 149.0720789} + - { name: Calwell,stop_code: Calwell, lat: -35.43524, lng: 149.113942} - { name: Campbell Park Offices,stop_code: Campbell Park Offices, lat: -35.28368, lng: 149.17045} - { name: Canberra College Weston Campus,stop_code: Canberra College Weston Campus, lat: -35.3490278, lng: 149.0486277} - { name: Canberra Hospital,stop_code: Canberra Hospital, lat: -35.3459462, lng: 149.1012001} @@ -52,13 +42,9 @@ - { name: Causeway,stop_code: Causeway, lat: -35.31615, lng: 149.15058} - { name: Centrelink Tuggeranong,stop_code: Centrelink Tuggeranong, lat: -35.4207496, lng: 149.0700973} - { name: Chapman,stop_code: Chapman, lat: -35.3557877, lng: 149.0408111} - - { name: Chapman Shops,stop_code: Chapman Shops, lat: -35.35579, lng: 149.04082} - { name: Charnwood,stop_code: Charnwood, lat: -35.2052138, lng: 149.0337266} - - { name: Charnwood Shops,stop_code: Charnwood Shops, lat: -35.20472, lng: 149.03336} - - { name: Charnwood Tillyard Dr,stop_code: Charnwood Tillyard Dr, lat: -35.20295, lng: 149.04027} - - { name: Chifley,stop_code: Chifley, lat: -35.350985, lng: 149.077319} - - { name: Chifley Shops,stop_code: Chifley Shops, lat: -35.35099, lng: 149.07732} - - { name: Chisholm Shops,stop_code: Chisholm Shops, lat: -35.41341, lng: 149.12833} + - { name: Chifley,stop_code: Chifley, lat: -35.3529713, lng: 149.0759413} + - { name: Chisholm,stop_code: Chisholm, lat: -35.41341, lng: 149.1308079} - { name: Chuculba / William Slim Dr,stop_code: Chuculba / William Slim Dr, lat: -35.208931, lng: 149.088499} - { name: CIT Weston,stop_code: CIT Weston, lat: -35.330234, lng: 149.058632} - { name: City Bus Station,stop_code: City Bus Station, lat: -35.2794346, lng: 149.1305879} @@ -73,8 +59,6 @@ - { name: City Bus Station (Platform 8),stop_code: City Bus Station (Platform 8), lat: -35.2778798, lng: 149.1305995} - { name: City Bus Station (Platform 9),stop_code: City Bus Station (Platform 9), lat: -35.2783224, lng: 149.130726} - { name: City West,stop_code: City West, lat: -35.2788605, lng: 149.1257969} - - { name: Cnr Kerrigan/Lhotsky,stop_code: Cnr Kerrigan/Lhotsky, lat: -35.1995716, lng: 149.0285277} - - { name: Cnr Tillyard Dr & Spalding St,stop_code: Cnr Tillyard Dr & Spalding St, lat: -35.2040477, lng: 149.0393052} - { name: Cohen Street Bus Station,stop_code: Cohen Street Bus Station, lat: -35.2394775, lng: 149.0602031} - { name: Cohen Street Bus Station (Platform 1),stop_code: Cohen Street Bus Station (Platform 1), lat: -35.2394775, lng: 149.0602031} - { name: Cohen Street Bus Station (Platform 2),stop_code: Cohen Street Bus Station (Platform 2), lat: -35.2396467, lng: 149.0602152} @@ -84,110 +68,75 @@ - { name: Cohen Street Bus Station (Platform 6),stop_code: Cohen Street Bus Station (Platform 6), lat: -35.2400028, lng: 149.060315} - { name: Conder Primary,stop_code: Conder Primary, lat: -35.4643475, lng: 149.0986908} - { name: Cook,stop_code: Cook, lat: -35.2596, lng: 149.0638} - - { name: Cook Shops,stop_code: Cook Shops, lat: -35.25898, lng: 149.06343} - { name: Cooleman Court,stop_code: Cooleman Court, lat: -35.34147, lng: 149.05338} - { name: Copland College,stop_code: Copland College, lat: -35.2127018, lng: 149.0596387} - - { name: Curtin,stop_code: Curtin, lat: -35.3248779, lng: 149.081441} - - { name: Curtin Shops,stop_code: Curtin Shops, lat: -35.32515, lng: 149.08224} - - { name: Deakin,stop_code: Deakin, lat: -35.3158608, lng: 149.1084563} - - { name: Deakin Shops,stop_code: Deakin Shops, lat: -35.31473, lng: 149.10