From: maxious Date: Mon, 29 Nov 2010 06:15:34 +0000 Subject: Javascript-less navigation using anchor tags on long lists X-Git-Url: https://maxious.lambdacomplex.org/git/?p=bus.git&a=commitdiff&h=cf533fc0b73141ec33a067a36a9b521acd321c89 --- Javascript-less navigation using anchor tags on long lists --- --- /dev/null +++ b/busui/about.php @@ -1,1 +1,9 @@ + +

+Some icons by Joseph Wain / glyphish.com + --- a/busui/common.inc.php +++ b/busui/common.inc.php @@ -8,6 +8,9 @@ return true; } +function debug($msg) { + if (isDebug()) echo ""; +} function isFastDevice() { return true; } @@ -19,22 +22,68 @@ bus.lambdacomplex.org - '.$pageTitle.' - - - - + + + + + - - + '; + if ($geolocate) { +echo " "; + } +echo ' '; if ($opendiv) echo '

'.$pageTitle.'

- Home
'; } @@ -43,6 +92,8 @@ { echo '
'; } + +$service_periods = Array ('sunday','saturday','weekday'); function service_period() { @@ -57,6 +108,11 @@ } } +function remove_spaces($string) +{ + return str_replace(' ','',$string); +} + function midnight_seconds() { // from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html @@ -87,22 +143,179 @@ return $f; } -function staticmap($mapPoints) +function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb") { $width = 300; $height = 300; - if (sizeof($mapPoints) < 1) return ""; - if (sizeof($mapPoints) === 1) $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; - if (sizeof($mapPoints) > 1) $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; //TODO average points - $markers = ""; - foreach ($mapPoints as $index => $mapPoint) { - if (sizeof($mapPoints) === 1) { - $markers .= $mapPoint[0].",".$mapPoint[1].",ol-marker"; - } else { - $markers .= $mapPoint[0].",".$mapPoint[1].",lightblue".($index+1); +$metersperpixel[9]=305.492*$width; +$metersperpixel[10]=152.746*$width; +$metersperpixel[11]=76.373*$width; +$metersperpixel[12]=38.187*$width; +$metersperpixel[13]=19.093*$width; +$metersperpixel[14]=9.547*$width; +$metersperpixel[15]=4.773*$width; +$metersperpixel[16]=2.387*$width; +// $metersperpixel[17]=1.193*$width; +$center = ""; +$markers = ""; +$minlat = 999; +$minlon = 999; +$maxlat = 0; +$maxlon = 0; + + if (sizeof($mapPoints) < 1) return "map error"; + if (sizeof($mapPoints) === 1) { + if ($zoom == 0) $zoom = 14; + $markers .= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage"; + $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; + } else { + foreach ($mapPoints as $index => $mapPoint) { + $markers .= $mapPoint[0].",".$mapPoint[1].",".$markerImage.($index+1); + if ($index+1 != sizeof($mapPoints)) $markers .= "|"; + if ($mapPoint[0] < $minlat) $minlat = $mapPoint[0]; + if ($mapPoint[0] > $maxlat) $maxlat = $mapPoint[0]; + if ($mapPoint[1] < $minlon) $minlon = $mapPoint[1]; + if ($mapPoint[1] > $maxlon) $maxlon = $mapPoint[1]; + $totalLat += $mapPoint[0]; + $totalLon += $mapPoint[1]; } - } - return ''; + if ($zoom == 0) { + $mapwidthinmeters = distance($minlat,$minlon,$minlat,$maxlon); + foreach (array_reverse($metersperpixel,true) as $zoomLevel => $maxdistance) + { + if ($zoom == 0 && $mapwidthinmeters < ($maxdistance + 50)) $zoom = $zoomLevel; + } + } + $center = $totalLat/sizeof($mapPoints).",".$totalLon/sizeof($mapPoints); + } + + return ''; +} + +function distance($lat1, $lng1, $lat2, $lng2) +{ + $pi80 = M_PI / 180; + $lat1 *= $pi80; + $lng1 *= $pi80; + $lat2 *= $pi80; + $lng2 *= $pi80; + + $r = 6372.797; // mean radius of Earth in km + $dlat = $lat2 - $lat1; + $dlng = $lng2 - $lng1; + $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2); + $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); + $km = $r * $c; + + return $km * 1000; +} + +function decodePolylineToArray($encoded) +{ +// source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 + $length = strlen($encoded); + $index = 0; + $points = array(); + $lat = 0; + $lng = 0; + + while ($index < $length) + { + // Temporary variable to hold each ASCII byte. + $b = 0; + + // The encoded polyline consists of a latitude value followed by a + // longitude value. They should always come in pairs. Read the + // latitude value first. + $shift = 0; + $result = 0; + do + { + // The `ord(substr($encoded, $index++))` statement returns the ASCII + // code for the character at $index. Subtract 63 to get the original + // value. (63 was added to ensure proper ASCII characters are displayed + // in the encoded polyline string, which is `human` readable) + $b = ord(substr($encoded, $index++)) - 63; + + // AND the bits of the byte with 0x1f to get the original 5-bit `chunk. + // Then left shift the bits by the required amount, which increases + // by 5 bits each time. + // OR the value into $results, which sums up the individual 5-bit chunks + // into the original value. Since the 5-bit chunks were reversed in + // order during encoding, reading them in this way ensures proper + // summation. + $result |= ($b & 0x1f) << $shift; + $shift += 5; + } + // Continue while the read byte is >= 0x20 since the last `chunk` + // was not OR'd with 0x20 during the conversion process. (Signals the end) + while ($b >= 0x20); + + // Check if negative, and convert. (All negative values have the last bit + // set) + $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); + + // Compute actual latitude since value is offset from previous value. + $lat += $dlat; + + // The next values will correspond to the longitude for this point. + $shift = 0; + $result = 0; + do + { + $b = ord(substr($encoded, $index++)) - 63; + $result |= ($b & 0x1f) << $shift; + $shift += 5; + } + while ($b >= 0x20); + + $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); + $lng += $dlng; + + // The actual latitude and longitude values were multiplied by + // 1e5 before encoding so that they could be converted to a 32-bit + // integer representation. (With a decimal accuracy of 5 places) + // Convert back to original values. + $points[] = array($lat * 1e-5, $lng * 1e-5); + } + + return $points; +} + +function object2array($object) { + if (is_object($object)) { + foreach ($object as $key => $value) { + $array[$key] = $value; + } + } + else { + $array = $object; + } + return $array; +} + +function geocode($query, $giveOptions) { + $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?query=".$query."&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true"; + $contents = json_decode(getPage($url)); + if ($giveOptions) return $contents->features; + elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0].",".$contents->features[0]->centroid->coordinates[1]; + else return ""; +} + +function reverseGeocode($lat,$lng) { + $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".$lat.",".$lng."&distance=closest&object_type=road"; + $contents = json_decode(getPage($url)); + return $contents->features[0]->properties->name; +} + +function startsWith($haystack,$needle,$case=true) { + if($case){return (strcmp(substr($haystack, 0, strlen($needle)),$needle)===0);} + return (strcasecmp(substr($haystack, 0, strlen($needle)),$needle)===0); +} + +function endsWith($haystack,$needle,$case=true) { + if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);} + return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0); } ?> --- a/busui/index.php +++ b/busui/index.php @@ -1,30 +1,53 @@
-

jQuery Mobile Framework +

logo
bus.lambdacomplex.org

-
+
+ Launch Trip Planner... -
-

- Time:
- Service Period: +
+

Time/Place Settings

+
+ + +
+
+ + "/> +
+
+ + + +
+ +
+
--- a/busui/routeList.php +++ b/busui/routeList.php @@ -1,55 +1,90 @@ '; -echo "";*/ +echo' +
+ +
+ '; echo '
    '; $url = $APIurl."/json/routes"; +$contents = json_decode(getPage($url)); +debug(print_r($contents,true)); -$contents = json_decode(getPage($url)); +function printRoutes($routes){ + foreach($routes as $row) { + echo '
  • '.$row[1].' '.$row[2]." (".ucwords($row[3]).")
  • \n"; + } +} + if ($_REQUEST['bynumber']) { $routeSeries = Array(); + $seriesRange = Array(); foreach ($contents as $key => $row) { foreach (explode(" ",$row[1]) as $routeNumber ) { $seriesNum = substr($routeNumber, 0, -1)."0"; if ($seriesNum == "0") $seriesNum = $routeNumber; + $finalDigit = substr($routeNumber, sizeof($routeNumber)-1, 1); + if (isset($seriesRange[$seriesNum])) { + if ($finalDigit < $seriesRange[$seriesNum]['max']) + $seriesRange[$seriesNum]['max'] = $routeNumber; + if ($finalDigit > $seriesRange[$seriesNum]['min']) + $seriesRange[$seriesNum]['min'] = $routeNumber; + } else { + $seriesRange[$seriesNum]['max'] = $routeNumber; + $seriesRange[$seriesNum]['min'] = $routeNumber; + } $routeSeries[$seriesNum][$seriesNum."-".$row[1]."-".$row[0]] = $row; - - } } ksort($routeSeries); + ksort($seriesRange); + echo '
    Go to route numbers: '; + foreach ($seriesRange as $series => $range) + { + if ($range['min'] == $range['max']) echo "$series "; + else echo "{$range['min']}-{$range['max']} "; + } + echo "
    + "; foreach ($routeSeries as $series => $routes) { - echo '
  • '.$series."...
      \n"; - foreach($routes as $row) { - echo '
    • '.$row[1].' '.$row[2]."
    • \n"; - } + echo ''; + if ($series <= 9) echo '
    • '.$series."
        \n"; + else echo "
      • {$seriesRange[$series]['min']}-{$seriesRange[$series]['max']}
          \n"; + printRoutes($routes); echo "
      • \n"; } } else { foreach ($contents as $key => $row) { $routeDestinations[$row[2]][] = $row; } + echo '
        Go to Destination: '; + foreach($routeDestinations as $destination => $routes) + { + echo "$destination "; + } + echo "
        + "; foreach ($routeDestinations as $destination => $routes) { + echo ''; echo '
      • '.$destination."...
          \n"; - foreach($routes as $row) { - echo '
        • '.$row[1].' '.$row[2]."
        • \n"; - } + printRoutes($routes); echo "
      • \n"; } } echo "
      \n"; -echo' -
      -
      - - '; + + include_footer(); ?> --- a/busui/schedule_viewer.py +++ b/busui/schedule_viewer.py @@ -256,7 +256,12 @@ schedule = self.server.schedule result = [] for r in schedule.GetRouteList(): - result.append( (r.route_id, r.route_short_name, r.route_long_name) ) + 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 @@ -273,8 +278,6 @@ for t in schedule.GetTripList(): if t.route_id == query: result.append ( (t.GetStartTime(), t.trip_id) ) - """ UGH fails for 300s """ - """return result""" return sorted(result, key=lambda trip: trip[0]) def handle_json_GET_triprows(self, params): --- /dev/null +++ b/busui/staticmaplite/.gitignore @@ -1,1 +1,3 @@ +cache/tiles +cache/map --- /dev/null +++ b/busui/staticmaplite/images/markers/GPlotter - Make Google Maps Easily.URL @@ -1,1 +1,3 @@ +[InternetShortcut] +URL=http://gplotter.offwhite.net/ --- /dev/null +++ b/busui/staticmaplite/images/markers/Google Maps Icons, Free!.URL @@ -1,1 +1,3 @@ +[InternetShortcut] +URL=http://brennan.offwhite.net/blog/2005/07/23/new-google-maps-icons-free/ --- /dev/null +++ b/busui/staticmaplite/index.html @@ -1,1 +1,122 @@ + + + + + + staticMapLite + + + +
      + +
      + +
      +

      + staticMapLite - simple map for your website +

      +

      +

      +

      + This image was created using the following simple <img> tag: +

      <img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" />
      +

      +
      +
      +
      +

      + Place Markers +

      + +

      + +

      Add markers by appending them to the image URL: +

      markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3
      +

      +
      +
      +
      +

      + Use Different Map Styles (Tile Sources) +

      + +

      +

      + +
      maptype=mapnik
      +
      +
      + +
      maptype=osmarenderer
      +
      +
      + +
      maptype=cycle
      +
      +
      +

      +
      + +
      + +
      + + --- /dev/null +++ b/busui/staticmaplite/selinux-fix.sh @@ -1,1 +1,3 @@ +chcon -R -t httpd_sys_content_rw_t cache + --- /dev/null +++ b/busui/staticmaplite/staticmap.php @@ -1,1 +1,273 @@ - + + * + * USAGE: + * + * staticmap.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=mapnik&markers=40.702147,-74.015794,blues|40.711614,-74.012318,greeng|40.718217,-73.998284,redc + * + */ + +error_reporting(0); +ini_set('display_errors','off'); + +Class staticMapLite { + + protected $tileSize = 256; + protected $tileSrcUrl = array( 'mapnik' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png', + 'osmarenderer' => 'http://c.tah.openstreetmap.org/Tiles/tile/{Z}/{X}/{Y}.png', + 'cycle' => 'http://c.andy.sandbox.cloudmade.com/tiles/cycle/{Z}/{X}/{Y}.png' + ); + + protected $tileDefaultSrc = 'mapnik'; + protected $markerBaseDir = 'images/markers'; + protected $osmLogo = 'images/osm_logo.png'; + + protected $useTileCache = true; + protected $tileCacheBaseDir = './cache/tiles'; + + protected $useMapCache = true; + protected $mapCacheBaseDir = './cache/maps'; + protected $mapCacheID = ''; + protected $mapCacheFile = ''; + protected $mapCacheExtension = 'png'; + + protected $zoom, $lat, $lon, $width, $height, $markers, $image, $maptype; + protected $centerX, $centerY, $offsetX, $offsetY; + + public function __construct(){ + $this->zoom = 0; + $this->lat = 0; + $this->lon = 0; + $this->width = 500; + $this->height = 350; + $this->markers = array(); + $this->maptype = $this->tileDefaultSrc; + } + + public function parseParams(){ + global $_GET; + + // get zoom from GET paramter + $this->zoom = $_GET['zoom']?intval($_GET['zoom']):0; + if($this->zoom>18)$this->zoom = 18; + + // get lat and lon from GET paramter + list($this->lat,$this->lon) = split(',',$_GET['center']); + $this->lat = floatval($this->lat); + $this->lon = floatval($this->lon); + + // get zoom from GET paramter + if($_GET['size']){ + list($this->width, $this->height) = split('x',$_GET['size']); + $this->width = intval($this->width); + $this->height = intval($this->height); + } + if($_GET['markers']){ + $markers = split('%7C|\|',$_GET['markers']); + foreach($markers as $marker){ + list($markerLat, $markerLon, $markerImage) = split(',',$marker); + $markerLat = floatval($markerLat); + $markerLon = floatval($markerLon); + $markerImage = basename($markerImage); + $this->markers[] = array('lat'=>$markerLat, 'lon'=>$markerLon, 'image'=>$markerImage); + } + + } + if($_GET['maptype']){ + if(array_key_exists($_GET['maptype'],$this->tileSrcUrl)) $this->maptype = $_GET['maptype']; + } + } + + public function lonToTile($long, $zoom){ + return (($long + 180) / 360) * pow(2, $zoom); + } + + public function latToTile($lat, $zoom){ + return (1 - log(tan($lat * pi()/180) + 1 / cos($lat* pi()/180)) / pi()) /2 * pow(2, $zoom); + } + + public function initCoords(){ + $this->centerX = $this->lonToTile($this->lon, $this->zoom); + $this->centerY = $this->latToTile($this->lat, $this->zoom); + $this->offsetX = floor((floor($this->centerX)-$this->centerX)*$this->tileSize); + $this->offsetY = floor((floor($this->centerY)-$this->centerY)*$this->tileSize); + } + + public function createBaseMap(){ + $this->image = imagecreatetruecolor($this->width, $this->height); + $startX = floor($this->centerX-($this->width/$this->tileSize)/2); + $startY = floor($this->centerY-($this->height/$this->tileSize)/2); + $endX = ceil($this->centerX+($this->width/$this->tileSize)/2); + $endY = ceil($this->centerY+($this->height/$this->tileSize)/2); + $this->offsetX = -floor(($this->centerX-floor($this->centerX))*$this->tileSize); + $this->offsetY = -floor(($this->centerY-floor($this->centerY))*$this->tileSize); + $this->offsetX += floor($this->width/2); + $this->offsetY += floor($this->height/2); + $this->offsetX += floor($startX-floor($this->centerX))*$this->tileSize; + $this->offsetY += floor($startY-floor($this->centerY))*$this->tileSize; + + for($x=$startX; $x<=$endX; $x++){ + for($y=$startY; $y<=$endY; $y++){ + $url = str_replace(array('{Z}','{X}','{Y}'),array($this->zoom, $x, $y), $this->tileSrcUrl[$this->maptype]); + $tileImage = imagecreatefromstring($this->fetchTile($url)); + $destX = ($x-$startX)*$this->tileSize+$this->offsetX; + $destY = ($y-$startY)*$this->tileSize+$this->offsetY; + imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize); + } + } + } + + + public function placeMarkers(){ + foreach($this->markers as $marker){ + $markerLat = $marker['lat']; + $markerLon = $marker['lon']; + $markerImage = $marker['image']; + $markerIndex++; + $markerFilename = $markerImage?(file_exists($this->markerBaseDir.'/'.$markerImage.".png")?$markerImage:'lightblue'.$markerIndex):'lightblue'.$markerIndex; + if(file_exists($this->markerBaseDir.'/'.$markerFilename.".png")){ + $markerImg = imagecreatefrompng($this->markerBaseDir.'/'.$markerFilename.".png"); + } else { + $markerImg = imagecreatefrompng($this->markerBaseDir.'/lightblue1.png'); + } + $destX = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($markerLon, $this->zoom))); + $destY = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($markerLat, $this->zoom))); + $destY = $destY - imagesy($markerImg); + + imagecopy($this->image, $markerImg, $destX, $destY, 0, 0, imagesx($markerImg), imagesy($markerImg)); + + }; +} + + + + public function tileUrlToFilename($url){ + return $this->tileCacheBaseDir."/".str_replace(array('http://'),'',$url); + } + + public function checkTileCache($url){ + $filename = $this->tileUrlToFilename($url); + if(file_exists($filename)){ + return file_get_contents($filename); + } + } + + public function checkMapCache(){ + $this->mapCacheID = md5($this->serializeParams()); + $filename = $this->mapCacheIDToFilename(); + if(file_exists($filename)) return true; + } + + public function serializeParams(){ + return join("&",array($this->zoom,$this->lat,$this->lon,$this->width,$this->height, serialize($this->markers),$this->maptype)); + } + + public function mapCacheIDToFilename(){ + if(!$this->mapCacheFile){ + $this->mapCacheFile = $this->mapCacheBaseDir."/".substr($this->mapCacheID,0,2)."/".substr($this->mapCacheID,2,2)."/".substr($this->mapCacheID,4); + } + return $this->mapCacheFile.".".$this->mapCacheExtension; + } + + + + public function mkdir_recursive($pathname, $mode){ + return mkdir($pathname, $mode, true); + } + public function writeTileToCache($url, $data){ + $filename = $this->tileUrlToFilename($url); + $this->mkdir_recursive(dirname($filename),0777); + file_put_contents($filename, $data); + } + + public function fetchTile($url){ + if($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0"); + curl_setopt($ch, CURLOPT_URL, $url); + $tile = curl_exec($ch); + curl_close($ch); + if($this->useTileCache){ + $this->writeTileToCache($url,$tile); + } + return $tile; + + } + + public function copyrightNotice(){ + $logoImg = imagecreatefrompng($this->osmLogo); + imagecopy($this->image, $logoImg, imagesx($this->image)-imagesx($logoImg), imagesy($this->image)-imagesy($logoImg), 0, 0, imagesx($logoImg), imagesy($logoImg)); + + } + + public function sendHeader(){ + header('Content-Type: image/png'); + $expires = 60*60*24*14; + header("Pragma: public"); + header("Cache-Control: maxage=".$expires); + header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); + } + + public function makeMap(){ + $this->initCoords(); + $this->createBaseMap(); + if(count($this->markers))$this->placeMarkers(); + if($this->osmLogo) $this->copyrightNotice(); + } + + public function showMap(){ + $this->parseParams(); + if($this->useMapCache){ + // use map cache, so check cache for map + if(!$this->checkMapCache()){ + // map is not in cache, needs to be build + $this->makeMap(); + $this->mkdir_recursive(dirname($this->mapCacheIDToFilename()),0777); + imagepng($this->image,$this->mapCacheIDToFilename(),9); + $this->sendHeader(); + if(file_exists($this->mapCacheIDToFilename())){ + return file_get_contents($this->mapCacheIDToFilename()); + } else { + return imagepng($this->image); + } + } else { + // map is in cache + $this->sendHeader(); + return file_get_contents($this->mapCacheIDToFilename()); + } + + } else { + // no cache, make map, send headers and deliver png + $this->makeMap(); + $this->sendHeader(); + return imagepng($this->image); + + } + } + +} + +$map = new staticMapLite(); +print $map->showMap(); + +?> + --- a/busui/stop.php +++ b/busui/stop.php @@ -8,6 +8,7 @@ echo '
        '; $url = $APIurl."/json/stoptrips?stop=".$_REQUEST['stopid']."&time=".midnight_seconds()."&service_period=".service_period(); $trips = json_decode(getPage($url)); +debug(print_r($trips,true)); foreach ($trips as $row) { echo '
      • '; --- a/busui/stopList.php +++ b/busui/stopList.php @@ -1,33 +1,48 @@ '; +echo' + + '; + + echo '
        Go to letter: '; +foreach(range('A','Z') as $letter) +{ + echo "$letter "; +} +echo "
        + "; +echo '
          '; $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)); +debug(print_r($contents,true)); 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 +// Sort the stops by name array_multisort($stopName, SORT_ASC, $contents); +$firstletter = ""; foreach ($contents as $row) { - + if (substr($row[1],0,1) != $firstletter){ + echo ""; + $firstletter = substr($row[1],0,1); + } echo '
        • '.$row[1].'
        • '; } echo '
        '; -echo' -
        -
        - - '; + include_footer(); ?> --- a/busui/trip.php +++ b/busui/trip.php @@ -4,6 +4,7 @@ if ($_REQUEST['routeid']) { $url = $APIurl."/json/routetrips?route_id=".$_REQUEST['routeid']; $trips = json_decode(getPage($url)); +debug(print_r($trips,true)); foreach ($trips as $trip) { if ($trip[0] < midnight_seconds()) { @@ -15,7 +16,7 @@ } $url = $APIurl."/json/triprows?trip=".$tripid; $trips = array_flatten(json_decode(getPage($url))); - +debug(print_r($trips,true)); include_header("Stops on ". $trips[1]->route_short_name . ' '. $trips[1]->route_long_name); echo '
          '; @@ -23,6 +24,7 @@ $url = $APIurl."/json/tripstoptimes?trip=".$tripid; $json = json_decode(getPage($url)); +debug(print_r($json,true)); $stops = $json[0]; $times = $json[1]; foreach ($stops as $key => $row) --- /dev/null +++ b/busui/tripPlanner.php @@ -1,1 +1,125 @@ +$errorMessage"; + echo '
          +
          + + + +
          +
          + + + +
          +
          + + +
          +
          + + +
          +
          '; + echo ""; + } + + function processItinerary($itineraryNumber, $itinerary) + { + echo '
          0 ? 'data-collapsed="true"' : "") . '>

          Option #' . ($itineraryNumber + 1) . ": " . floor($itinerary->duration / 60000) . " minutes ({$itinerary->startTime} to {$itinerary->endTime})

          "; + echo "Walking time: " . floor($itinerary->walkTime / 60000) . " minutes (" . floor($itinerary->walkDistance) . " meters)
          \n"; + echo "Transit time: " . floor($itinerary->transitTime / 60000) . " minutes
          \n"; + echo "Waiting time: " . floor($itinerary->waitingTime / 60000) . " minutes
          \n"; + + + + if (is_array($itinerary->legs->leg)) { + $legMarkers = array(); + foreach ($itinerary->legs->leg as $legNumber => $leg) { + $legMarkers[] = array($leg->from->lat, $leg->from->lon); + } + echo '' . staticmap($legMarkers) . "
          \n"; + echo '

            '; + foreach ($itinerary->legs->leg as $legNumber => $leg) { + echo '
          • '; + processLeg($legNumber, $leg); + echo "
          • "; + } + echo "
          "; + } else { + echo '' . staticmap(array(array($itinerary->legs->leg->from->lat, $itinerary->legs->leg->from->lon))) . "
          \n"; + processLeg(0, $itinerary->legs->leg); + } + + echo "

          "; + } + + function processLeg($legNumber, $leg) { + $legArray = object2array($leg); + echo '

          Leg #' . ($legNumber + 1) . " ( {$legArray['@mode']} from: {$leg->from->name} to {$leg->to->name}, " . floor($leg->duration / 60000) . " minutes)

          \n"; + if ($legArray["@mode"] === "BUS") { + echo "Take bus {$legArray['@route']} " . str_replace("To", "towards", $legArray['@headsign']) . "
          "; + } else { + $walkStepMarkers = array(); + foreach ($leg->steps->walkSteps as $stepNumber => $step) { + $walkStepMarkers[] = array($step->lat, $step->lon); + } + echo "" . staticmap($walkStepMarkers, "icong") . "
          \n"; + foreach ($leg->steps->walkSteps as $stepNumber => $step) { + echo "Walking step " . ($stepNumber + 1) . " $step->absoluteDirection / $step->relativeDirection on $step->streetName for " . floor($step->distance) . " meters
          \n"; + } + } + } + + if ($_REQUEST['time']) { + $toPlace = (startsWith($_REQUEST['to'], "-") ? $_REQUEST['to'] : geocode(urlencode($_REQUEST['to']), false)); + $fromPlace = (startsWith($_REQUEST['from'], "-") ? $_REQUEST['from'] : geocode(urlencode($_REQUEST['from']), false)); + if ($toPlace == "" || $fromPlace == "") { + $errorMessage = ""; + if ($toPlace === "") + $errorMessage .= urlencode($_REQUEST['to']) . " not found.
          \n"; + if ($fromPlace === "") + $errorMessage .= urlencode($_REQUEST['from']) . " not found.
          \n"; + tripPlanForm($errorMessage); + } else { + $url = "http://localhost:8080/opentripplanner-api-webapp/ws/plan?_dc=1290254798856&arriveBy=false&date=" . urlencode($_REQUEST['date']) . "&time=" . urlencode($_REQUEST['time']) . "&mode=TRANSIT%2CWALK&optimize=QUICK&maxWalkDistance=840&wheelchair=false&toPlace=$toPlace&fromPlace=$fromPlace&intermediatePlaces="; + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json")); + $page = curl_exec($ch); + curl_close($ch); + $tripplan = json_decode($page); + debug(print_r($triplan,true)); + echo "

          From: {$tripplan->plan->from->name} To: {$tripplan->plan->to->name}

          "; + echo "

          At: {$tripplan->plan->date}

          "; + + if (is_array($tripplan->plan->itineraries->itinerary)) { + echo '
          '; + foreach ($tripplan->plan->itineraries->itinerary as $itineraryNumber => $itinerary) { + processItinerary($itineraryNumber, $itinerary); + } + echo "
          "; + } else { + processItinerary(0, $tripplan->plan->itineraries->itinerary); + } + + } + } else { + tripPlanForm(); + } + include_footer(); +?> --- a/maxious-canberra-transit-feed/01-extracttimes.rb +++ b/maxious-canberra-transit-feed/01-extracttimes.rb @@ -14,7 +14,7 @@ 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(" Platform"," (Platform").gsub(" - "," - ").gsub("\n"," ").gsub("\r"," ").gsub("\t"," ").gsub("\\"," / ").gsub("/"," / ").gsub(","," ").gsub("\302\240","").squeeze(" ").strip if (tp.content.match('Platform')) timing_point.concat(")") end; @@ -79,7 +79,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 @@ -34,7 +34,7 @@ "NarrabundahTerminus"=>"Narrabundah Terminus", "Railway StationKingston"=>"Railway Station Kingston", "Saint AndrewsVillage Hughes"=>"Saint Andrews Village Hughes", - "Dickson ShopsAntill Street"=>"Dickson Shops", + "DicksonAntill Street"=>"Dickson", "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,8 @@ "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"=> "Charnwood", "Black Moutain- Telstra Tower"=>"Black Mountain Telstra Tower", "Bonython Primary"=> "Bonython Primary School", "Athllon Drive / Sulwood Dr Kambah"=>"Athllon / Sulwood Kambah", @@ -61,31 +61,37 @@ "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", "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", + "Yarrulumla"=>"Yarralumla", "Tharwa Dr / Pocket Ave"=>"Tharwa Dr / Pockett Ave", "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 / Pocket" => "Tharwa Drive / Pockett Ave", + 'Tharwa Dr / Pockett Ave' => "Tharwa Drive / 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 Wattle Street"=>"Lyneham / Wattle St", + "Dickson" => "Dickson / Antill St", + 'Dickson Antill 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' + } 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/cbrtable.yml +++ b/maxious-canberra-transit-feed/cbrtable.yml @@ -11,12 +11,10 @@ - { 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} @@ -37,7 +35,7 @@ - { name: Bugden Sternberg,stop_code: Bugden Sternberg, lat: -35.4017223, lng: 149.0992172} - { 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: Calwell,stop_code: Calwell, 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} @@ -52,13 +50,10 @@ - { 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: Chisholm,stop_code: Chisholm, lat: -35.41341, lng: 149.12833} - { 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} @@ -84,19 +79,14 @@ - { 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.10771} - { name: Deamer / Clift Richardson,stop_code: Deamer / Clift Richardson, lat: -35.4319597, lng: 149.1187876} - - { name: Dickson,stop_code: Dickson, lat: -35.2498434, lng: 149.1391218} + - { name: Dickson / Antill St,stop_code: Dickson / Antill St, lat: -35.2489, lng: 149.14012} - { name: Dickson College,stop_code: Dickson College, lat: -35.24923, lng: 149.15315} - - { name: Dickson Cowper St,stop_code: Dickson Cowper St, lat: -35.250297, lng: 149.141336} - - { name: Dickson Shops,stop_code: Dickson Shops, lat: -35.25045, lng: 149.14044} - - { name: Dickson Shops/Antill St,stop_code: Dickson Shops/Antill St, lat: -35.2251335, lng: 149.1658895} + - { name: Dickson / Cowper St,stop_code: Dickson / Cowper St, lat: -35.250297, lng: 149.141336} - { name: Duffy,stop_code: Duffy, lat: -35.3366908, lng: 149.0324311} - { name: Duffy Primary,stop_code: Duffy Primary, lat: -35.334219, lng: 149.033656} - { name: Dunlop,stop_code: Dunlop, lat: -35.1942693, lng: 149.0206702} @@ -104,59 +94,47 @@ - { name: Erindale Dr / Charleston St Monash,stop_code: Erindale Dr / Charleston St Monash, lat: -35.414616, lng: 149.07888} - { name: Erindale / Sternberg Cres,stop_code: Erindale / Sternberg Cres, lat: -35.4014472, lng: 149.0956545} - { name: Evatt,stop_code: Evatt, lat: -35.2091093, lng: 149.0735343} - - { name: Evatt Shops,stop_code: Evatt Shops, lat: -35.21203, lng: 149.06505} - { name: Eye Hospital,stop_code: Eye Hospital, lat: -35.3341884, lng: 149.1656213} - { name: Fairbairn Park,stop_code: Fairbairn Park, lat: -35.3001773, lng: 149.2041185} - { name: Farrer Primary School,stop_code: Farrer Primary School, lat: -35.37887, lng: 149.10641} - { name: Farrer Terminus,stop_code: Farrer Terminus, lat: -35.3771794, lng: 149.1046948} - { name: Federation Square,stop_code: Federation Square, lat: -35.1908726, lng: 149.0848153} - { name: Fisher,stop_code: Fisher, lat: -35.3605627, lng: 149.0576481} - - { name: Fisher Shops,stop_code: Fisher Shops, lat: -35.36056, lng: 149.05765} - { name: Flemington Rd,stop_code: Flemington Rd, lat: -35.20756, lng: 149.14778} - { name: Flemington Rd / Nullabor Ave,stop_code: Flemington Rd / Nullabor Ave, lat: -35.2008585, lng: 149.1493407} - { name: Flemington Rd / Sandford St,stop_code: Flemington Rd / Sandford St, lat: -35.221231, lng: 149.144645} - - { name: Florey Shops,stop_code: Florey Shops, lat: -35.2258544, lng: 149.0546214} + - { name: Florey,stop_code: Florey, lat: -35.2258544, lng: 149.0546214} - { name: Flynn,stop_code: Flynn, lat: -35.2019283, lng: 149.0478356} - { name: Fraser,stop_code: Fraser, lat: -35.1896539, lng: 149.0435012} - { name: Fraser East Terminus,stop_code: Fraser East Terminus, lat: -35.1896539, lng: 149.0435012} - - { name: Fraser Shops,stop_code: Fraser Shops, lat: -35.18966, lng: 149.0435} - { name: Fraser West Terminus,stop_code: Fraser West Terminus, lat: -35.191513, lng: 149.038006} - { name: Fyshwick Direct Factory Outlet,stop_code: Fyshwick Direct Factory Outlet, lat: -35.3359862, lng: 149.1796322} - { name: Fyshwick Terminus,stop_code: Fyshwick Terminus, lat: -35.3285202, lng: 149.1785592} - { name: Garran,stop_code: Garran, lat: -35.3423286, lng: 149.10811} - - { name: Garran Shops,stop_code: Garran Shops, lat: -35.34236, lng: 149.1082} - { name: Geoscience Australia,stop_code: Geoscience Australia, lat: -35.3429702, lng: 149.1583893} - { name: Giralang,stop_code: Giralang, lat: -35.2115608, lng: 149.0960692} - - { name: Giralang Shops,stop_code: Giralang Shops, lat: -35.2115608, lng: 149.0960692} - { name: Gordon Primary,stop_code: Gordon Primary, lat: -35.455517, lng: 149.086978} - { name: Gowrie,stop_code: Gowrie, lat: -35.4120264, lng: 149.1110804} - - { name: Gowrie Shops,stop_code: Gowrie Shops, lat: -35.4120264, lng: 149.1110804} - { name: Gungahlin Marketplace,stop_code: Gungahlin Marketplace, lat: -35.1769532, lng: 149.1319017} - { name: Gwydir Square Kaleen,stop_code: Gwydir Square Kaleen, lat: -35.2338677, lng: 149.1031998} - { name: Hackett,stop_code: Hackett, lat: -35.2481617, lng: 149.1626094} - - { name: Hackett Shops,stop_code: Hackett Shops, lat: -35.24825, lng: 149.16271} - { name: Hawker,stop_code: Hawker, lat: -35.2437386, lng: 149.0432804} - { name: Hawker College,stop_code: Hawker College, lat: -35.2454598, lng: 149.0324251} - - { name: Hawker Shops,stop_code: Hawker Shops, lat: -35.24398, lng: 149.04361} - { name: Heagney / Clift Richardson,stop_code: Heagney / Clift Richardson, lat: -35.4251299, lng: 149.11375} - { name: Hibberson / Kate Crace,stop_code: Hibberson / Kate Crace, lat: -35.1861642, lng: 149.1391756} - { name: Higgins,stop_code: Higgins, lat: -35.2313901, lng: 149.0271811} - - { name: Higgins Shops,stop_code: Higgins Shops, lat: -35.23136, lng: 149.02611} - { name: Holder,stop_code: Holder, lat: -35.3378123, lng: 149.0449433} - - { name: Holder Shops,stop_code: Holder Shops, lat: -35.33781, lng: 149.04494} - { name: Holt,stop_code: Holt, lat: -35.223099, lng: 149.0126269} - - { name: Holt Shops,stop_code: Holt Shops, lat: -35.2231, lng: 149.01263} - { name: Hoskins Street / Oodgeroo Ave,stop_code: Hoskins Street / Oodgeroo Ave, lat: -35.201095, lng: 149.139941} - { name: Hospice / Menindee Dr,stop_code: Hospice / Menindee Dr, lat: -35.303557, lng: 149.151627} - { name: Hughes,stop_code: Hughes, lat: -35.3339223, lng: 149.093854} - - { name: Hughes Shops,stop_code: Hughes Shops, lat: -35.3335, lng: 149.09392} - { name: Isaacs,stop_code: Isaacs, lat: -35.3669823, lng: 149.1119217} - - { name: Isaacs Shops,stop_code: Isaacs Shops, lat: -35.36698, lng: 149.11192} - - { name: Isabella Shops,stop_code: Isabella Shops, lat: -35.4285703, lng: 149.0916837} + - { name: Isabella,stop_code: Isabella, lat: -35.4285703, lng: 149.0916837} - { name: Jamison Centre,stop_code: Jamison Centre, lat: -35.2527268, lng: 149.0713712} - { name: John James Hospital,stop_code: John James Hospital, lat: -35.3200295, lng: 149.0955996} - { name: Kaleen Village / Marybrynong,stop_code: Kaleen Village / Marybrynong, lat: -35.2274031, lng: 149.1075421} - { name: Kambah High,stop_code: Kambah High, lat: -35.3847749, lng: 149.0720245} + - { name: Kambah / Livingston St,stop_code: Kambah / Livingston St, lat: -35.3883359, lng: 149.0811471} - { name: Kambah Village,stop_code: Kambah Village, lat: -35.3800314, lng: 149.0576581} - { name: Katherine Ave / Horse Park Drive,stop_code: Katherine Ave / Horse Park Drive, lat: -35.1680901, lng: 149.1321801} - { name: Kerrigan / Lhotsky,stop_code: Kerrigan / Lhotsky, lat: -35.193801, lng: 149.035689} @@ -166,8 +144,8 @@ - { name: Kippax Centre,stop_code: Kippax Centre, lat: -35.22172, lng: 149.01995} - { name: Kosciuszko / Everard,stop_code: Kosciuszko / Everard, lat: -35.188901, lng: 149.1216937} - { name: Lanyon Market Place,stop_code: Lanyon Market Place, lat: -35.4573, lng: 149.09199} + - { name: Latham,stop_code: Latham, lat: -35.21848, lng: 149.03214} - { name: Latham Post Office,stop_code: Latham Post Office, lat: -35.21906, lng: 149.03223} - - { name: Latham Shops,stop_code: Latham Shops, lat: -35.21848, lng: 149.03214} - { name: Lathlain St Bus Station,stop_code: Lathlain St Bus Station, lat: -35.2396657, lng: 149.0633993} - { name: Lathlain St Bus Station (Platform 1),stop_code: Lathlain St Bus Station (Platform 1), lat: -35.2408973, lng: 149.0639887} - { name: Lathlain St Bus Station (Platform 2),stop_code: Lathlain St Bus Station (Platform 2), lat: -35.2406038, lng: 149.0638922} @@ -177,17 +155,13 @@ - { name: Lathlain St Bus Station (Platform 6),stop_code: Lathlain St Bus Station (Platform 6), lat: -35.2410486, lng: 149.0638326} - { name: Lewis Luxton/Woodcock Dr,stop_code: Lewis Luxton/Woodcock Dr, lat: -35.4422566, lng: 149.0854375} - { name: Lithgow St Terminus Fyshwick,stop_code: Lithgow St Terminus Fyshwick, lat: -35.3296912, lng: 149.1668153} - - { name: Livingston Shops Kambah,stop_code: Livingston Shops Kambah, lat: -35.3883359, lng: 149.0811471} - - { name: Livingston Shops / Kambah,stop_code: Livingston Shops / Kambah, lat: -35.390246, lng: 149.07822} - { name: Lyneham,stop_code: Lyneham, lat: -35.2523304, lng: 149.1246184} - { name: Lyneham High,stop_code: Lyneham High, lat: -35.2524016, lng: 149.130254} - - { name: Lyneham Shops Wattle Street,stop_code: Lyneham Shops Wattle Street, lat: -35.25205, lng: 149.12524} + - { name: Lyneham / Wattle St,stop_code: Lyneham / Wattle St, lat: -35.25205, lng: 149.12524} - { name: Lyons,stop_code: Lyons, lat: -35.3415779, lng: 149.0765703} - - { name: Lyons Shops,stop_code: Lyons Shops, lat: -35.34019, lng: 149.0771} - { name: Macarthur / Miller O'Connor,stop_code: Macarthur / Miller O'Connor, lat: -35.2587584, lng: 149.1153561} - { name: Macarthur / Northbourne Ave,stop_code: Macarthur / Northbourne Ave, lat: -35.26051, lng: 149.13224} - { name: Macgregor,stop_code: Macgregor, lat: -35.2100645, lng: 149.0122952} - - { name: Macgregor Shops,stop_code: Macgregor Shops, lat: -35.2100645, lng: 149.0122952} - { name: MacKillop College Isabella Campus,stop_code: MacKillop College Isabella Campus, lat: -35.42597, lng: 149.09172} - { name: MacKillop College Wanniassa Campus,stop_code: MacKillop College Wanniassa Campus, lat: -35.4056, lng: 149.089774} - { name: Macquarie,stop_code: Macquarie, lat: -35.2483414, lng: 149.0600666} @@ -196,9 +170,7 @@ - { name: Manuka,stop_code: Manuka, lat: -35.3200096, lng: 149.1341344} - { name: Manuka / Captain Cook Cres,stop_code: Manuka / Captain Cook Cres, lat: -35.3217, lng: 149.13445} - { name: McKellar,stop_code: McKellar, lat: -35.2174267, lng: 149.0742108} - - { name: McKellar Shops,stop_code: McKellar Shops, lat: -35.2182, lng: 149.07555} - { name: Melba,stop_code: Melba, lat: -35.2083104, lng: 149.0485366} - - { name: Melba Shops,stop_code: Melba Shops, lat: -35.21004, lng: 149.05302} - { name: Mentone View / Tharwa Drive,stop_code: Mentone View / Tharwa Drive, lat: -35.45144, lng: 149.0919} - { name: Merici College,stop_code: Merici College, lat: -35.266525, lng: 149.137037} - { name: Mirrabei Drive / Dam Wall,stop_code: Mirrabei Drive / Dam Wall, lat: -35.177453, lng: 149.124291} @@ -219,32 +191,26 @@ - { name: Northbourne Avenue / Antill St,stop_code: Northbourne Avenue / Antill St, lat: -35.248287, lng: 149.134241} - { name: North Lyneham,stop_code: North Lyneham, lat: -35.2385618, lng: 149.1221188} - { name: O'Connor,stop_code: O'Connor, lat: -35.2640376, lng: 149.1226107} - - { name: O'Connor Shops,stop_code: O'Connor Shops, lat: -35.2640376, lng: 149.1226107} - { name: Olims Hotel,stop_code: Olims Hotel, lat: -35.27597, lng: 149.1428} - { name: Outtrim / Duggan,stop_code: Outtrim / Duggan, lat: -35.435871, lng: 149.097692} - - { name: Page Shops,stop_code: Page Shops, lat: -35.2360695, lng: 149.0536554} + - { name: Page,stop_code: Page, lat: -35.2360695, lng: 149.0536554} - { name: Parliament House,stop_code: Parliament House, lat: -35.3081571, lng: 149.1244592} - { name: Paul Coe / Mirrabei Dr,stop_code: Paul Coe / Mirrabei Dr, lat: -35.17467, lng: 149.12005} - { name: Pearce,stop_code: Pearce, lat: -35.3625413, lng: 149.0815935} - - { name: Pearce Shops,stop_code: Pearce Shops, lat: -35.3625413, lng: 149.0815935} - { name: Police College Weston,stop_code: Police College Weston, lat: -35.33018, lng: 149.05458} - { name: Proctor / Mead,stop_code: Proctor / Mead, lat: -35.415305, lng: 149.127204} - { name: Railway Station Kingston,stop_code: Railway Station Kingston, lat: -35.319602, lng: 149.149083} - { name: Red Hill,stop_code: Red Hill, lat: -35.336505, lng: 149.131645} - - { name: Red Hill Shops,stop_code: Red Hill Shops, lat: -35.336505, lng: 149.131645} - { name: Rivett,stop_code: Rivett, lat: -35.3473758, lng: 149.036543