Add feeback form/layar API
Add feeback form/layar API

<?php <?php
include('common.inc.php'); include('common.inc.php');
  include_header("About")
?> ?>
<p> <p>
Busness Time - An ACT bus timetable webapp Busness Time - An ACT bus timetable webapp<br />
Based on the maxious-canberra-transit-feed Based on the maxious-canberra-transit-feed (<a href="cbrfeed.zip">download</a>, last updated <?php echo date("F d Y.", @filemtime('cbrfeed.zip')); ?>)<br />
Uses jQuery Mobile, PHP, Ruby, Python, Google Transit Feed Specification tools, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service Source code for the transit feed and this site @ <a href="http://maxious.lambdacomplex.org/git">http://maxious.lambdacomplex.org/git</a><br />
  Uses jQuery Mobile, PHP, Ruby, Python, Google Transit Feed Specification tools, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br />
Feedback encouraged; contact maxious@lambdacomplex.org <br />
  Feedback encouraged; contact maxious@lambdacomplex.org<br />
Some icons by Joseph Wain / glyphish.com <br />
  Some icons by Joseph Wain / glyphish.com<br />
  <br />
Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip. <small>Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip.
Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty, Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty,
express or implied concerning the topicality, correctness, completeness or quality of the information, which is provided express or implied concerning the topicality, correctness, completeness or quality of the information, which is provided
"as is". The Author expressly disclaims all warranties, including but not limited to warranties of fitness for a particular purpose and warranties of merchantability. "as is". The Author expressly disclaims all warranties, including but not limited to warranties of fitness for a particular purpose and warranties of merchantability.
All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend, All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend,
change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site
without prior notice. without prior notice. </small>
<? <?
include_footer(); include_footer();
?> ?>
   
<?php <?php
date_default_timezone_set('Australia/ACT'); date_default_timezone_set('Australia/ACT');
$APIurl = "http://localhost:8765"; $APIurl = "http://localhost:8765";
$cloudmadeAPIkey="daa03470bb8740298d4b10e3f03d63e6"; $cloudmadeAPIkey="daa03470bb8740298d4b10e3f03d63e6";
$googleMapsAPIkey="ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q"; $googleMapsAPIkey="ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q";
$otpAPIurl = 'http://10.1.0.243:5080/opentripplanner-api-webapp/'; $otpAPIurl = 'http://10.1.0.243:5080/opentripplanner-api-webapp/';
if (isDebug()) error_reporting(E_ALL ^ E_NOTICE); if (isDebug()) error_reporting(E_ALL ^ E_NOTICE);
   
// SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',') // SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',')
$suburbs = explode(",","Acton,Ainslie,Amaroo,Aranda,Banks,Barton,Belconnen,Bonner,Bonython,Braddon,Bruce,Calwell,Campbell,Chapman,Charnwood,Chifley,Chisholm,City,Conder,Cook,Curtin,Deakin,Dickson,Downer,Duffy,Dunlop,Evatt,Fadden,Farrer,Fisher,Florey,Flynn,Forrest,Franklin,Fraser,Fyshwick,Garran,Gilmore,Giralang,Gordon,Gowrie,Greenway,Griffith,Gungahlin,Hackett,Hall,Harrison,Hawker,Higgins,Holder,Holt,Hughes,Hume,Isaacs,Isabella Plains,Kaleen,Kambah,Kingston,Latham,Lawson,Lyneham,Lyons,Macarthur,Macgregor,Macquarie,Mawson,McKellar,Melba,Mitchell,Monash,Narrabundah,Ngunnawal,Nicholls,Oaks Estate,O'Connor,O'Malley,Oxley,Page,Palmerston,Parkes,Pearce,Phillip,Pialligo,Red Hill,Reid,Richardson,Rivett,Russell,Scullin,Spence,Stirling,Symonston,Tharwa,Theodore,Torrens,Turner,Wanniassa,Waramanga,Watson,Weetangera,Weston,Yarralumla"); $suburbs = explode(",","Acton,Ainslie,Amaroo,Aranda,Banks,Barton,Belconnen,Bonner,Bonython,Braddon,Bruce,Calwell,Campbell,Chapman,Charnwood,Chifley,Chisholm,City,Conder,Cook,Curtin,Deakin,Dickson,Downer,Duffy,Dunlop,Evatt,Fadden,Farrer,Fisher,Florey,Flynn,Forrest,Franklin,Fraser,Fyshwick,Garran,Gilmore,Giralang,Gordon,Gowrie,Greenway,Griffith,Gungahlin,Hackett,Hall,Harrison,Hawker,Higgins,Holder,Holt,Hughes,Hume,Isaacs,Isabella Plains,Kaleen,Kambah,Kingston,Latham,Lawson,Lyneham,Lyons,Macarthur,Macgregor,Macquarie,Mawson,McKellar,Melba,Mitchell,Monash,Narrabundah,Ngunnawal,Nicholls,Oaks Estate,O'Connor,O'Malley,Oxley,Page,Palmerston,Parkes,Pearce,Phillip,Pialligo,Red Hill,Reid,Richardson,Rivett,Russell,Scullin,Spence,Stirling,Symonston,Tharwa,Theodore,Torrens,Turner,Wanniassa,Waramanga,Watson,Weetangera,Weston,Yarralumla");
   
// you have to open the session to be able to modify or remove it // you have to open the session to be able to modify or remove it
session_start(); session_start();
if (isset($_REQUEST['service_period'])) $_SESSION['service_period'] = filter_var($_REQUEST['service_period'],FILTER_SANITIZE_STRING); if (isset($_REQUEST['service_period'])) $_SESSION['service_period'] = filter_var($_REQUEST['service_period'],FILTER_SANITIZE_STRING);
if (isset($_REQUEST['time'])) $_SESSION['time'] = filter_var($_REQUEST['time'],FILTER_SANITIZE_STRING); if (isset($_REQUEST['time'])) $_SESSION['time'] = filter_var($_REQUEST['time'],FILTER_SANITIZE_STRING);
if (isset($_REQUEST['geolocate'])) { if (isset($_REQUEST['geolocate'])) {
$contents = geocode(var_filter($_REQUEST['geolocate'],FILTER_SANITIZE_URL),true); $contents = geocode(var_filter($_REQUEST['geolocate'],FILTER_SANITIZE_URL),true);
if (isset($contents[0]->centroid)) { if (isset($contents[0]->centroid)) {
$session['lat'] = $contents[0]->centroid->coordinates[0]; $session['lat'] = $contents[0]->centroid->coordinates[0];
$session['lon'] = $contents[0]->centroid->coordinates[1]; $session['lon'] = $contents[0]->centroid->coordinates[1];
} }
else { else {
$session['lat'] = ""; $session['lat'] = "";
$session['lon'] = ""; $session['lon'] = "";
} }
} }
//print_r ($_SESSION); //print_r ($_SESSION);
function isDebug() function isDebug()
{ {
return $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || !$_SERVER['SERVER_NAME']; return $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || !$_SERVER['SERVER_NAME'];
} }
   
function debug($msg) { function debug($msg) {
if (isDebug()) echo "<!-- $msg -->"; if (isDebug()) echo "<!-- $msg -->";
} }
function isFastDevice() { function isFastDevice() {
return true; return true;
} }
   
function include_header($pageTitle, $opendiv = true, $geolocate = false) { function include_header($pageTitle, $opendiv = true, $geolocate = false) {
echo ' echo '
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>busness time - '.$pageTitle.'</title> <title>busness time - '.$pageTitle.'</title>
'; ';
if (isDebug()) echo '<link rel="stylesheet" href="css/jquery-mobile-1.0a3.css" /> if (isDebug()) echo '<link rel="stylesheet" href="css/jquery-mobile-1.0a3.css" />
<script type="text/javascript" src="js/jquery-1.5.js"></script> <script type="text/javascript" src="js/jquery-1.5.js"></script>
<script type="text/javascript" src="js/jquery-mobile-1.0a3.js"></script>'; <script type="text/javascript" src="js/jquery-mobile-1.0a3.js"></script>';
else echo '<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.css" /> else echo '<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.js"></script> <script type="text/javascript" src="http://code.jquery.com/jquery-1.5.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.js"></script>'; <script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.js"></script>';
echo ' echo '
<link rel="stylesheet" href="css/jquery.ui.datepicker.mobile.css" /> <link rel="stylesheet" href="css/jquery.ui.datepicker.mobile.css" />
<script> <script>
//reset type=date inputs to text //reset type=date inputs to text
$( document ).bind( "mobileinit", function(){ $( document ).bind( "mobileinit", function(){
$.mobile.page.prototype.options.degradeInputs.date = true; $.mobile.page.prototype.options.degradeInputs.date = true;
}); });
</script> </script>
<script src="js/jQuery.ui.datepicker.js"></script> <script src="js/jQuery.ui.datepicker.js"></script>
<script src="js/jquery.ui.datepicker.mobile.js"></script> <script src="js/jquery.ui.datepicker.mobile.js"></script>
<style type="text/css"> <style type="text/css">
.ui-navbar { .ui-navbar {
width: 100%; width: 100%;
} }
.ui-btn-inner { .ui-btn-inner {
white-space: normal !important; white-space: normal !important;
} }
.ui-li-heading { .ui-li-heading {
white-space: normal !important; white-space: normal !important;
} }
.ui-listview-filter { .ui-listview-filter {
margin: 0 !important; margin: 0 !important;
} }
  #footer {
  text-size: 0.75em;
  text-align: center;
  }
  body {
  background-color: #F0F0F0;
  }
</style> </style>
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-startup-image" href="startup.png" /> <link rel="apple-touch-startup-image" href="startup.png" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; <link rel="apple-touch-icon" href="apple-touch-icon.png" />';
if ($geolocate) { if ($geolocate) {
echo "<script> echo "<script>
   
function success(position) { function success(position) {
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); $('#geolocate').val(position.coords.latitude+','+position.coords.longitude);
// setCookie('geolocate',position.coords.latitude+','+position.coords.longitude,1); // setCookie('geolocate',position.coords.latitude+','+position.coords.longitude,1);
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); $('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;});
$('#here').show(); $('#here').show();
} }
function error(msg) { function error(msg) {
console.log(msg); console.log(msg);
} }
   
if (navigator.geolocation) { if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success, error); navigator.geolocation.getCurrentPosition(success, error);
} }
   
</script> "; </script> ";
} }
echo '</head> echo '</head>
<body> <body>
'; ';
if ($opendiv) { if ($opendiv) {
echo '<div data-role="page"> echo '<div data-role="page">
<div data-role="header"> <div data-role="header">
<h1>'.$pageTitle.'</h1> <h1>'.$pageTitle.'</h1>
</div><!-- /header --> </div><!-- /header -->
<div data-role="content"> '; <div data-role="content"> ';
} }
} }
   
function include_footer() function include_footer()
{ {
if ($geolocate && isset($_SESSION['lat'])) { if ($geolocate && isset($_SESSION['lat'])) {
echo "<script> echo "<script>
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); $('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;});
$('#here').show(); $('#here').show();
</script>"; </script>";
} }
echo '</div>'; echo '<div id="footer"><a href="about.php">About/Contact Us</a>&nbsp;<a href="feedback.php">Feedback/Bug Report</a></a>';
  echo '</div>';
} }
   
$service_periods = Array ('sunday','saturday','weekday'); $service_periods = Array ('sunday','saturday','weekday');
   
function service_period() function service_period()
{ {
if (isset($_SESSION['service_period'])) return $_SESSION['service_period']; if (isset($_SESSION['service_period'])) return $_SESSION['service_period'];
   
switch (date('w')){ switch (date('w')){
   
case 0: case 0:
return 'sunday'; return 'sunday';
case 6: case 6:
return 'saturday'; return 'saturday';
default: default:
return 'weekday'; return 'weekday';
} }
} }
   
function remove_spaces($string) function remove_spaces($string)
{ {
return str_replace(' ','',$string); return str_replace(' ','',$string);
} }
   
function midnight_seconds() function midnight_seconds()
{ {
// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html // from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html
if (isset($_SESSION['time'])) { if (isset($_SESSION['time'])) {
$time = strtotime($_SESSION['time']); $time = strtotime($_SESSION['time']);
return (date("G",$time) * 3600) + (date("i",$time) * 60) + date("s",$time); return (date("G",$time) * 3600) + (date("i",$time) * 60) + date("s",$time);
} }
return (date("G") * 3600) + (date("i") * 60) + date("s"); return (date("G") * 3600) + (date("i") * 60) + date("s");
} }
   
function midnight_seconds_to_time($seconds) function midnight_seconds_to_time($seconds)
{ {
if ($seconds > 0) { if ($seconds > 0) {
$midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); $midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y"));
return date("h:ia",$midnight+$seconds); return date("h:ia",$midnight+$seconds);
} else { } else {
return ""; return "";
} }
} }
function getPage($url) function getPage($url)
{ {
debug($url); debug($url);
$ch = curl_init($url); $ch = curl_init($url);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HEADER, 0 ); curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt($ch,CURLOPT_TIMEOUT,30); curl_setopt($ch,CURLOPT_TIMEOUT,30);
$page = curl_exec($ch); $page = curl_exec($ch);
if(curl_errno($ch)) echo "<font color=red> Database temporarily unavailable: ".curl_errno($ch)." ".curl_error($ch)."</font>"; if(curl_errno($ch)) echo "<font color=red> Database temporarily unavailable: ".curl_errno($ch)." ".curl_error($ch)."</font>";
curl_close($ch); curl_close($ch);
return $page; return $page;
} }
function array_flatten($a,$f=array()){ function array_flatten($a,$f=array()){
if(!$a||!is_array($a))return ''; if(!$a||!is_array($a))return '';
foreach($a as $k=>$v){ foreach($a as $k=>$v){
if(is_array($v))$f=array_flatten($v,$f); if(is_array($v))$f=array_flatten($v,$f);
else $f[$k]=$v; else $f[$k]=$v;
} }
return $f; return $f;
} }
   
function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb") function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb")
{ {
$width = 300; $width = 300;
$height = 300; $height = 300;
$metersperpixel[9]=305.492*$width; $metersperpixel[9]=305.492*$width;
$metersperpixel[10]=152.746*$width; $metersperpixel[10]=152.746*$width;
$metersperpixel[11]=76.373*$width; $metersperpixel[11]=76.373*$width;
$metersperpixel[12]=38.187*$width; $metersperpixel[12]=38.187*$width;
$metersperpixel[13]=19.093*$width; $metersperpixel[13]=19.093*$width;
$metersperpixel[14]=9.547*$width; $metersperpixel[14]=9.547*$width;
$metersperpixel[15]=4.773*$width; $metersperpixel[15]=4.773*$width;
$metersperpixel[16]=2.387*$width; $metersperpixel[16]=2.387*$width;
// $metersperpixel[17]=1.193*$width; // $metersperpixel[17]=1.193*$width;
$center = ""; $center = "";
$markers = ""; $markers = "";
$minlat = 999; $minlat = 999;
$minlon = 999; $minlon = 999;
$maxlat = 0; $maxlat = 0;
$maxlon = 0; $maxlon = 0;
   
if (sizeof($mapPoints) < 1) return "map error"; if (sizeof($mapPoints) < 1) return "map error";
if (sizeof($mapPoints) === 1) { if (sizeof($mapPoints) === 1) {
if ($zoom == 0) $zoom = 14; if ($zoom == 0) $zoom = 14;
$markers .= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage"; $markers .= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage";
$center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
} else { } else {
foreach ($mapPoints as $index => $mapPoint) { foreach ($mapPoints as $index => $mapPoint) {
$markers .= $mapPoint[0].",".$mapPoint[1].",".$markerImage.($index+1); $markers .= $mapPoint[0].",".$mapPoint[1].",".$markerImage.($index+1);
if ($index+1 != sizeof($mapPoints)) $markers .= "|"; if ($index+1 != sizeof($mapPoints)) $markers .= "|";
if ($mapPoint[0] < $minlat) $minlat = $mapPoint[0]; if ($mapPoint[0] < $minlat) $minlat = $mapPoint[0];
if ($mapPoint[0] > $maxlat) $maxlat = $mapPoint[0]; if ($mapPoint[0] > $maxlat) $maxlat = $mapPoint[0];
if ($mapPoint[1] < $minlon) $minlon = $mapPoint[1]; if ($mapPoint[1] < $minlon) $minlon = $mapPoint[1];
if ($mapPoint[1] > $maxlon) $maxlon = $mapPoint[1]; if ($mapPoint[1] > $maxlon) $maxlon = $mapPoint[1];
$totalLat += $mapPoint[0]; $totalLat += $mapPoint[0];
$totalLon += $mapPoint[1]; $totalLon += $mapPoint[1];
} }
if ($zoom == 0) { if ($zoom == 0) {
$mapwidthinmeters = distance($minlat,$minlon,$minlat,$maxlon); $mapwidthinmeters = distance($minlat,$minlon,$minlat,$maxlon);
foreach (array_reverse($metersperpixel,true) as $zoomLevel => $maxdistance) foreach (array_reverse($metersperpixel,true) as $zoomLevel => $maxdistance)
{ {
if ($zoom == 0 && $mapwidthinmeters < ($maxdistance + 50)) $zoom = $zoomLevel; if ($zoom == 0 && $mapwidthinmeters < ($maxdistance + 50)) $zoom = $zoomLevel;
} }
} }
$center = $totalLat/sizeof($mapPoints).",".$totalLon/sizeof($mapPoints); $center = $totalLat/sizeof($mapPoints).",".$totalLon/sizeof($mapPoints);
} }
$output = ""; $output = "";
$output .= '<div data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>'; $output .= '<div data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
$output .= '<center><img src="staticmaplite/staticmap.php?center='.$center.'&zoom='.$zoom.'&size='.$width.'x'.$height.'&maptype=mapnik&markers='.$markers.'" width='.$width.' height='.$height.'></center>'; $output .= '<center><img src="staticmaplite/staticmap.php?center='.$center.'&zoom='.$zoom.'&size='.$width.'x'.$height.'&maptype=mapnik&markers='.$markers.'" width='.$width.' height='.$height.'></center>';
$output .= '</div>'; $output .= '</div>';
return $output; return $output;
} }
   
function distance($lat1, $lng1, $lat2, $lng2) function distance($lat1, $lng1, $lat2, $lng2)
{ {
$pi80 = M_PI / 180; $pi80 = M_PI / 180;
$lat1 *= $pi80; $lat1 *= $pi80;
$lng1 *= $pi80; $lng1 *= $pi80;
$lat2 *= $pi80; $lat2 *= $pi80;
$lng2 *= $pi80; $lng2 *= $pi80;
   
$r = 6372.797; // mean radius of Earth in km $r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1; $dlat = $lat2 - $lat1;
$dlng = $lng2 - $lng1; $dlng = $lng2 - $lng1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2); $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)); $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c; $km = $r * $c;
   
return $km * 1000; return $km * 1000;
} }
   
function decodePolylineToArray($encoded) function decodePolylineToArray($encoded)
{ {
// source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 // source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5
$length = strlen($encoded); $length = strlen($encoded);
$index = 0; $index = 0;
$points = array(); $points = array();
$lat = 0; $lat = 0;
$lng = 0; $lng = 0;
   
while ($index < $length) while ($index < $length)
{ {
// Temporary variable to hold each ASCII byte. // Temporary variable to hold each ASCII byte.
$b = 0; $b = 0;
   
// The encoded polyline consists of a latitude value followed by a // The encoded polyline consists of a latitude value followed by a
// longitude value. They should always come in pairs. Read the // longitude value. They should always come in pairs. Read the
// latitude value first. // latitude value first.
$shift = 0; $shift = 0;
$result = 0; $result = 0;
do do
{ {
// The `ord(substr($encoded, $index++))` statement returns the ASCII // The `ord(substr($encoded, $index++))` statement returns the ASCII
// code for the character at $index. Subtract 63 to get the original // code for the character at $index. Subtract 63 to get the original
// value. (63 was added to ensure proper ASCII characters are displayed // value. (63 was added to ensure proper ASCII characters are displayed
// in the encoded polyline string, which is `human` readable) // in the encoded polyline string, which is `human` readable)
$b = ord(substr($encoded, $index++)) - 63; $b = ord(substr($encoded, $index++)) - 63;
   
// AND the bits of the byte with 0x1f to get the original 5-bit `chunk. // 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 // Then left shift the bits by the required amount, which increases
// by 5 bits each time. // by 5 bits each time.
// OR the value into $results, which sums up the individual 5-bit chunks // 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 // into the original value. Since the 5-bit chunks were reversed in
// order during encoding, reading them in this way ensures proper // order during encoding, reading them in this way ensures proper
// summation. // summation.
$result |= ($b & 0x1f) << $shift; $result |= ($b & 0x1f) << $shift;
$shift += 5; $shift += 5;
} }
// Continue while the read byte is >= 0x20 since the last `chunk` // Continue while the read byte is >= 0x20 since the last `chunk`
// was not OR'd with 0x20 during the conversion process. (Signals the end) // was not OR'd with 0x20 during the conversion process. (Signals the end)
while ($b >= 0x20); while ($b >= 0x20);
   
// Check if negative, and convert. (All negative values have the last bit // Check if negative, and convert. (All negative values have the last bit
// set) // set)
$dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1));
   
// Compute actual latitude since value is offset from previous value. // Compute actual latitude since value is offset from previous value.
$lat += $dlat; $lat += $dlat;
   
// The next values will correspond to the longitude for this point. // The next values will correspond to the longitude for this point.
$shift = 0; $shift = 0;
$result = 0; $result = 0;
do do
{ {
$b = ord(substr($encoded, $index++)) - 63; $b = ord(substr($encoded, $index++)) - 63;
$result |= ($b & 0x1f) << $shift; $result |= ($b & 0x1f) << $shift;
$shift += 5; $shift += 5;
} }
while ($b >= 0x20); while ($b >= 0x20);
   
$dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1));
$lng += $dlng; $lng += $dlng;
   
// The actual latitude and longitude values were multiplied by // The actual latitude and longitude values were multiplied by
// 1e5 before encoding so that they could be converted to a 32-bit // 1e5 before encoding so that they could be converted to a 32-bit
// integer representation. (With a decimal accuracy of 5 places) // integer representation. (With a decimal accuracy of 5 places)
// Convert back to original values. // Convert back to original values.
$points[] = array($lat * 1e-5, $lng * 1e-5); $points[] = array($lat * 1e-5, $lng * 1e-5);
} }
   
return $points; return $points;
} }
   
function object2array($object) { function object2array($object) {
if (is_object($object)) { if (is_object($object)) {
foreach ($object as $key => $value) { foreach ($object as $key => $value) {
$array[$key] = $value; $array[$key] = $value;
} }
} }
else { else {
$array = $object; $array = $object;
} }
return $array; return $array;
} }
   
function geocode($query, $giveOptions) { function geocode($query, $giveOptions) {
global $cloudmadeAPIkey; global $cloudmadeAPIkey;
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?query=".$query."&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true"; $url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/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)); $contents = json_decode(getPage($url));
if ($giveOptions) return $contents->features; if ($giveOptions) return $contents->features;
elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0].",".$contents->features[0]->centroid->coordinates[1]; elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0].",".$contents->features[0]->centroid->coordinates[1];
else return ""; else return "";
} }
   
function reverseGeocode($lat,$lng) { function reverseGeocode($lat,$lng) {
global $cloudmadeAPIkey; global $cloudmadeAPIkey;
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=".$lat.",".$lng."&distance=closest&object_type=road"; $url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=".$lat.",".$lng."&distance=closest&object_type=road";
$contents = json_decode(getPage($url)); $contents = json_decode(getPage($url));
return $contents->features[0]->properties->name; return $contents->features[0]->properties->name;
} }
   
function startsWith($haystack,$needle,$case=true) { function startsWith($haystack,$needle,$case=true) {
if($case){return (strcmp(substr($haystack, 0, strlen($needle)),$needle)===0);} if($case){return (strcmp(substr($haystack, 0, strlen($needle)),$needle)===0);}
return (strcasecmp(substr($haystack, 0, strlen($needle)),$needle)===0); return (strcasecmp(substr($haystack, 0, strlen($needle)),$needle)===0);
} }
   
function endsWith($haystack,$needle,$case=true) { function endsWith($haystack,$needle,$case=true) {
if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);} if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);}
return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0); return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);
} }
function bracketsMeanNewLine($input) { function bracketsMeanNewLine($input) {
return str_replace(")","</small>",str_replace("(","<br><small>",$input)); return str_replace(")","</small>",str_replace("(","<br><small>",$input));
} }
   
function viaPoints($tripid,$stopid, $timingPointsOnly = false) { function viaPoints($tripid,$stopid, $timingPointsOnly = false) {
global $APIurl; global $APIurl;
$url = $APIurl."/json/tripstoptimes?trip=".$tripid; $url = $APIurl."/json/tripstoptimes?trip=".$tripid;
   
$json = json_decode(getPage($url)); $json = json_decode(getPage($url));
debug(print_r($json,true)); debug(print_r($json,true));
$stops = $json[0]; $stops = $json[0];
$times = $json[1]; $times = $json[1];
$foundStop = false; $foundStop = false;
$viaPoints = Array(); $viaPoints = Array();
foreach ($stops as $key => $row) foreach ($stops as $key => $row)
{ {
if ($foundStop) { if ($foundStop) {
if (!$timingPointsOnly || !startsWith($row[5],"Wj") ) { if (!$timingPointsOnly || !startsWith($row[5],"Wj") ) {
$viaPoints[] = Array("id" => $row[0], "name" => $row[1], "time" => $times[$key]); $viaPoints[] = Array("id" => $row[0], "name" => $row[1], "time" => $times[$key]);
} }
} else { } else {
if ($row[0] == $stopid) $foundStop = true; if ($row[0] == $stopid) $foundStop = true;
} }
} }
return $viaPoints; return $viaPoints;
} }
   
function viaPointNames($tripid,$stopid) { function viaPointNames($tripid,$stopid) {
$points = viaPoints($tripid,$stopid,true); $points = viaPoints($tripid,$stopid,true);
$pointNames = Array(); $pointNames = Array();
foreach ($points as $point) { foreach ($points as $point) {
$pointNames[] = $point['name']; $pointNames[] = $point['name'];
} }
return implode(", ",$pointNames); return implode(", ",$pointNames);
} }
   
function timePlaceSettings($geolocate = false) { function timePlaceSettings($geolocate = false) {
global $service_periods; global $service_periods;
$geoerror = false; $geoerror = false;
if ($geolocate == true) { if ($geolocate == true) {
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat'])
|| $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; || $_SESSION['lat'] == "" || $_SESSION['lon'] == "";
} }
if ($geoerror) { if ($geoerror) {
echo '<div class="error">Sorry, but your location could not currently be detected. echo '<div class="error">Sorry, but your location could not currently be detected.
Please allow location permission, wait for your location to be detected, Please allow location permission, wait for your location to be detected,
or enter an address/co-ordinates in the box below.</div>'; or enter an address/co-ordinates in the box below.</div>';
} }
echo '<div data-role="collapsible" data-collapsed="'.!$geoerror.'"> echo '<div data-role="collapsible" data-collapsed="'.!$geoerror.'">
<h3>Change Time/Place...</h3> <h3>Change Time/Place...</h3>
<form action="" method="post"> <form action="" method="post">
<div class="ui-body"> <div class="ui-body">
<div data-role="fieldcontain"> <div data-role="fieldcontain">
<label for="geolocate"> Current Location: </label> <label for="geolocate"> Current Location: </label>
<input type="text" id="geolocate" name="geolocate" value="Enter co-ordinates or address here"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a> <input type="text" id="geolocate" name="geolocate" value="Enter co-ordinates or address here"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a>
</div> </div>
<div data-role="fieldcontain"> <div data-role="fieldcontain">
<label for="time"> Time: </label> <label for="time"> Time: </label>
<input type="time" name="time" id="time" value="'. ($_SESSION['time'] ? $_SESSION['time'] : date("H:m")).'"/> <a href="#" name="currentTime" id="currentTime"/>Current Time?</a> <input type="time" name="time" id="time" value="'. ($_SESSION['time'] ? $_SESSION['time'] : date("H:m")).'"/> <a href="#" name="currentTime" id="currentTime"/>Current Time?</a>
</div> </div>
<div data-role="fieldcontain"> <div data-role="fieldcontain">
<label for="service_period"> Service Period: </label> <label for="service_period"> Service Period: </label>
<select name="service_period">'; <select name="service_period">';
   
foreach ($service_periods as $service_period) { foreach ($service_periods as $service_period) {
echo "<option value=\"$service_period\"".(service_period() === $service_period ? "SELECTED" : "").'>'.ucwords($service_period).'</option>'; echo "<option value=\"$service_period\"".(service_period() === $service_period ? "SELECTED" : "").'>'.ucwords($service_period).'</option>';
} }
echo '</select> echo '</select>
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a> <a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a>
</div> </div>
<input type="submit" value="Update"/> <input type="submit" value="Update"/>
</form> </form>
</div></div>'; </div></div>';
} }
?> ?>
 Binary files /dev/null and b/busui/css/images/ajax-loader.png differ
 Binary files /dev/null and b/busui/css/images/form-check-off.png differ
 Binary files /dev/null and b/busui/css/images/form-check-on.png differ
 Binary files /dev/null and b/busui/css/images/form-radio-off.png differ
 Binary files /dev/null and b/busui/css/images/form-radio-on.png differ
 Binary files /dev/null and b/busui/css/images/icon-search-black.png differ
 Binary files /dev/null and b/busui/css/images/icons-18-black.png differ
 Binary files /dev/null and b/busui/css/images/icons-18-white.png differ
 Binary files /dev/null and b/busui/css/images/icons-36-black.png differ
 Binary files /dev/null and b/busui/css/images/icons-36-white.png differ
  <?php
  include('common.inc.php');
  include_header("Feedback")
  ?>
  <h3>Add/Move/Delete a Bus Stop Location</h3>
  StopID:
  or StopCode:
 
  Suggested Stop Location (lat/long or words):
 
  <h3>Bug Report/Feedback</h3>
  <textarea id="extrainfo">
  Referrer URL
  User Agent
  User host/IP
  Current date/time
  Dump of $_SESSION
  </textarea>
<?php <?php
include('common.inc.php'); include('common.inc.php');
include_header("bus.lambdacomplex.org",false, true) include_header("bus.lambdacomplex.org",false, true)
?> ?>
<div data-role="page"> <div data-role="page">
<div data-role="content"> <div data-role="content">
<div id="jqm-homeheader"> <div id="jqm-homeheader">
<center><h3>busness time</h3><br><small>Canberra Bus Timetables and Trip Planner</small></center> <center><h3>busness time</h3><br><small>Canberra Bus Timetables and Trip Planner</small></center>
</div> </div>
<a href="tripPlanner.php" data-role="button">Launch Trip Planner...</a> <a href="tripPlanner.php" data-role="button">Launch Trip Planner...</a>
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
<li data-role="list-divider">Timetables - Stops</li> <li data-role="list-divider">Timetables - Stops</li>
<li><a href="stopList.php">Major (Timing Point) Stops</a></li> <li><a href="stopList.php">Major (Timing Point) Stops</a></li>
<li><a href="stopList.php">All Stops</a></li> <li><a href="stopList.php">All Stops</a></li>
<li><a href="stopList.php?suburbs=yes">Stops By Suburb</a></li> <li><a href="stopList.php?suburbs=yes">Stops By Suburb</a></li>
<li><a class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li> <li><a class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li>
</ul> </ul>
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
<li data-role="list-divider">Timetables - Routes</li> <li data-role="list-divider">Timetables - Routes</li>
<li><a href="routeList.php">Routes By Final Destination</a></li> <li><a href="routeList.php">Routes By Final Destination</a></li>
<li><a href="routeList.php?bynumber=yes">Routes By Number</a></li> <li><a href="routeList.php?bynumber=yes">Routes By Number</a></li>
<li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li> <li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li>
</ul> </ul>
<?php echo timePlaceSettings();?> <?php
  echo timePlaceSettings();
  include_footer(true)
  ?>
</div>  
</body>  
</html>  
   
  <?php
  include('common.inc.php');
  $output = Array();
  $output['hotspots'] = Array();
  $output['layer'] = "canberrabusstops";
 
  $url = $APIurl."/json/neareststops?lat={$_REQUEST['lat']}&lon={$_REQUEST['lon']}&limit=5";
  $contents = json_decode(getPage($url));
  debug(print_r($contents,true));
  foreach ($contents as $row)
  {
  $hotspot = Array();
  $hotspot['id'] = $row[0];
  $hotspot['title'] = $row[1];
  $hotspot['type'] = 0;
  $hotspot['lat'] = floor($row[2]*1000000);
  $hotspot['lon'] = floor($row[3]*1000000);
  $hotspot['distance'] = distance($row[2], $row[3], $_REQUEST['lat'], $_REQUEST['lon']);
  if (!isset($_REQUEST['radius']) || $hotspot['distance'] < $_REQUEST['radius']) {
  $hotspot['actions'] = Array(Array("label" => 'Visit Webpage', 'uri' => 'http://bus.lambdacomplex.org/'.'stop.php?stopid='.$row[0]));
  $url = $APIurl."/json/stoptrips?stop=".$row[0]."&time=".midnight_seconds()."&service_period=".service_period();
  $trips = json_decode(getPage($url));
  debug(print_r($trips,true));
  foreach ($trips as $key => $row)
  {
  if ($key > 3) {
  $hotspot['line'.$key+2]= $row[1][1] .' @ ' .midnight_seconds_to_time($row[0]);
  }
  }
  if (sizeof($trips) == 0) $hotspot['line2'] = 'No trips in the near future.';
  $hotspot['imageURL'] = null;
  $output['hotspots'][] = $hotspot;
  }
  }
  if (sizeof($hotspot) > 0) {
  $output['errorString'] = 'ok';
  $output['errorCode'] = 0;
  } else {
  $output['errorString'] = 'no results, try increasing range';
  $output['errorCode'] = 21;
  }
  echo json_encode($output);
  ?>