<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
include_header("About","about") | include_header("About", "about") |
?> | ?> |
<p> | <p> |
Busness Time - An ACT bus timetable webapp<br /> | Busness Time - An ACT bus timetable webapp<br /> |
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 /> | 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 /> | |
Source code for the transit feed and this site @ <a href="http://maxious.lambdacomplex.org/git">http://maxious.lambdacomplex.org/git</a><br /> | 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 /> | Uses jQuery Mobile, PHP, Ruby, Python, Google Transit Feed Specification tools, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br /> |
<br /> | <br /> |
Feedback encouraged; contact maxious@lambdacomplex.org<br /> | Feedback encouraged; contact maxious@lambdacomplex.org<br /> |
<br /> | <br /> |
Some icons by Joseph Wain / glyphish.com<br /> | Some icons by Joseph Wain / glyphish.com<br /> |
<br /> | <br /> |
<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. | <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. </small> | without prior notice. </small> |
<? | <? |
include_footer(); | include_footer(); |
?> | ?> |
#!/bin/bash | #!/bin/bash |
#this script should be run from a fresh git checkout from http://maxious.lambdacomplex.org | #this script should be run from a fresh git checkout from http://maxious.lambdacomplex.org |
#ami base must have yum install lighttpd-fastcgi, git, tomcat6 | #ami base must have yum install lighttpd-fastcgi, git, tomcat6 |
#screen php-cli php-gd tomcat6-webapps tomcat6-admin-webapps | #screen php-cli php-gd tomcat6-webapps tomcat6-admin-webapps svn maven2 |
#http://www.how2forge.org/installing-lighttpd-with-php5-and-mysql-support-on-fedora-12 | #http://www.how2forge.org/installing-lighttpd-with-php5-and-mysql-support-on-fedora-12 |
cp -rfv /tmp/busui/* /var/www | cp -rfv /tmp/busui/* /var/www |
cp /root/aws.php /tmp/ | cp /root/aws.php /tmp/ |
chcon -h system_u:object_r:httpd_sys_content_t /var/www | chcon -h system_u:object_r:httpd_sys_content_t /var/www |
chcon -R -h root:object_r:httpd_sys_content_t /var/www/* | chcon -R -h root:object_r:httpd_sys_content_t /var/www/* |
chcon -R -t httpd_sys_content_rw_t /var/www/staticmaplite/cache | chcon -R -t httpd_sys_content_rw_t /var/www/staticmaplite/cache |
chmod -R 777 /var/www/staticmaplite/cache | chmod -R 777 /var/www/staticmaplite/cache |
wget http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \ | wget http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \ |
-O /var/www/cbrfeed.zip | -O /var/www/cbrfeed.zip |
easy_install transitfeed | easy_install transitfeed |
easy_install simplejson | easy_install simplejson |
screen -d -m /var/www/view.sh | screen -d -m /var/www/view.sh |
wget http://s3-ap-southeast-1.amazonaws.com/busresources/Graph.obj \ | wget http://s3-ap-southeast-1.amazonaws.com/busresources/Graph.obj \ |
-O /tmp/Graph.obj | -O /tmp/Graph.obj |
rm -rfv /usr/share/tomcat6/webapps/opentripplanner* | rm -rfv /usr/share/tomcat6/webapps/opentripplanner* |
wget http://s3-ap-southeast-1.amazonaws.com/busresources/opentripplanner-webapp.war \ | wget http://s3-ap-southeast-1.amazonaws.com/busresources/opentripplanner-webapp.war \ |
-O /usr/share/tomcat6/webapps/opentripplanner-webapp.war | -O /usr/share/tomcat6/webapps/opentripplanner-webapp.war |
wget http://s3-ap-southeast-1.amazonaws.com/busresources/opentripplanner-api-webapp.war \ | wget http://s3-ap-southeast-1.amazonaws.com/busresources/opentripplanner-api-webapp.war \ |
-O /usr/share/tomcat6/webapps/opentripplanner-api-webapp.war | -O /usr/share/tomcat6/webapps/opentripplanner-api-webapp.war |
/etc/init.d/tomcat6 restart | /etc/init.d/tomcat6 restart |
<?php | |
// 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"); | |
function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb", $collapsible = true) | |
{ | |
$width = 300; | |
$height = 300; | |
$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]; | |
} | |
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); | |
} | |
$output = ""; | |
if ($collapsible) $output.= '<div data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>'; | |
$output.= '<center><img src="' . curPageURL() . 'staticmaplite/staticmap.php?center=' . $center . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height . '&maptype=mapnik&markers=' . $markers . '" width=' . $width . ' height=' . $height . '></center>'; | |
if ($collapsible) $output.= '</div>'; | |
return $output; | |
} | |
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 geocode($query, $giveOptions) | |
{ | |
global $cloudmadeAPIkey; | |
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?query=" . urlencode($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) | |
{ | |
global $cloudmadeAPIkey; | |
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=" . $lat . "," . $lng . "&distance=closest&object_type=road"; | |
$contents = json_decode(getPage($url)); | |
return $contents->features[0]->properties->name; | |
} | |
?> |
<?php | |
function getPage($url) | |
{ | |
debug($url, "json"); | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($ch, CURLOPT_HEADER, 0); | |
curl_setopt($ch, CURLOPT_TIMEOUT, 30); | |
$page = curl_exec($ch); | |
if (curl_errno($ch)) echo "<font color=red> Database temporarily unavailable: " . curl_errno($ch) . " " . curl_error($ch) . "</font><br>"; | |
curl_close($ch); | |
debug(print_r($page,true),"json"); | |
return $page; | |
} | |
function curPageURL() | |
{ | |
$isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); | |
$port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); | |
$port = ($port) ? ':' . $_SERVER["SERVER_PORT"] : ''; | |
$url = ($isHTTPS ? 'https://' : 'http://') . $_SERVER["SERVER_NAME"] . $port . htmlentities(dirname($_SERVER['PHP_SELF']) , ENT_QUOTES) . "/"; | |
return $url; | |
} | |
?> |
<?php | |
function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false) | |
{ | |
echo ' | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>' . $pageTitle . '</title>'; | |
if (isDebugServer()) 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-mobile-1.0a3.js"></script>'; | |
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/mobile/1.0a3/jquery.mobile-1.0a3.js"></script>'; | |
echo ' | |
<link rel="stylesheet" href="css/jquery.ui.datepicker.mobile.css" /> | |
<script> | |
//reset type=date inputs to text | |
$( document ).bind( "mobileinit", function(){ | |
$.mobile.page.prototype.options.degradeInputs.date = true; | |
}); | |
</script> | |
<script src="js/jQuery.ui.datepicker.js"></script> | |
<script src="js/jquery.ui.datepicker.mobile.js"></script> | |
<style type="text/css"> | |
.ui-navbar { | |
width: 100%; | |
} | |
.ui-btn-inner { | |
white-space: normal !important; | |
} | |
.ui-li-heading { | |
white-space: normal !important; | |
} | |
.ui-listview-filter { | |
margin: 0 !important; | |
} | |
.ui-icon-navigation { | |
background-image: url(css/images/113-navigation.png); | |
background-position: 1px 0; | |
} | |
#footer { | |
text-size: 0.75em; | |
text-align: center; | |
} | |
body { | |
background-color: #F0F0F0; | |
} | |
</style> | |
<meta name="apple-mobile-web-app-capable" content="yes" /> | |
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> | |
<link rel="apple-touch-startup-image" href="startup.png" /> | |
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; | |
if ($geolocate) { | |
echo "<script> | |
function success(position) { | |
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); | |
$.ajax({ url: \"common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude }); | |
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); | |
$('#here').show(); | |
} | |
function error(msg) { | |
console.log(msg); | |
} | |
if (navigator.geolocation) { | |
navigator.geolocation.getCurrentPosition(success, error); | |
} | |
</script> "; | |
} | |
echo '</head> | |
<body> | |
'; | |
if (isMetricsOn()) { | |
require_once ('owa/owa_env.php'); | |
require_once (OWA_DIR . 'owa_php.php'); | |
$owa = new owa_php(); | |
global $owaSiteID; | |
$owa->setSiteId($owaSiteID); | |
$owa->setPageTitle($pageTitle); | |
$owa->setPageType($pageType); | |
$owa->trackPageView(); | |
$owa->placeHelperPageTags(); | |
} | |
if ($opendiv) { | |
echo '<div data-role="page"> | |
<script> | |
$(document).ready(function () | |
{ | |
document.title = "' . $pageTitle . '"; | |
}); | |
</script> | |
<div data-role="header"> | |
<h1>' . $pageTitle . '</h1> | |
</div><!-- /header --> | |
<div data-role="content"> '; | |
} | |
} | |
function include_footer() | |
{ | |
if ($geolocate && isset($_SESSION['lat'])) { | |
echo "<script> | |
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); | |
$('#here').show(); | |
</script>"; | |
} | |
echo '<div id="footer"><a href="about.php">About/Contact Us</a> <a href="feedback.php">Feedback/Bug Report</a></a>'; | |
echo '</div>'; | |
} | |
function timePlaceSettings($geolocate = false) | |
{ | |
global $service_periods; | |
$geoerror = false; | |
if ($geolocate == true) { | |
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; | |
} | |
if ($geoerror) { | |
echo '<div class="error">Sorry, but your location could not currently be detected. | |
Please allow location permission, wait for your location to be detected, | |
or enter an address/co-ordinates in the box below.</div>'; | |
} | |
echo '<div data-role="collapsible" data-collapsed="' . !$geoerror . '"> | |
<h3>Change Time/Place (' . (isset($_SESSION['time']) ? $_SESSION['time'] : "Current Time,") . ' '.ucwords(service_period()).')...</h3> | |
<form action="" method="post"> | |
<div class="ui-body"> | |
<div data-role="fieldcontain"> | |
<label for="geolocate"> Current Location: </label> | |
<input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="time"> Time: </label> | |
<input type="time" name="time" id="time" value="' . (isset($_SESSION['time']) ? $_SESSION['time'] : date("H:i")) . '"/> <a href="#" name="currentTime" id="currentTime"/>Current Time?</a> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="service_period"> Service Period: </label> | |
<select name="service_period">'; | |
foreach ($service_periods as $service_period) { | |
echo "<option value=\"$service_period\"" . (service_period() === $service_period ? "SELECTED" : "") . '>' . ucwords($service_period) . '</option>'; | |
} | |
echo '</select> | |
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a> | |
</div> | |
<input type="submit" value="Update"/> | |
</form> | |
</div></div>'; | |
} | |
?> |
<?php | |
$service_periods = Array( | |
'sunday', | |
'saturday', | |
'weekday' | |
); | |
function service_period() | |
{ | |
if (isset($_SESSION['service_period'])) return $_SESSION['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 | |
if (isset($_SESSION['time'])) { | |
$time = strtotime($_SESSION['time']); | |
return (date("G", $time) * 3600) + (date("i", $time) * 60) + date("s", $time); | |
} | |
return (date("G") * 3600) + (date("i") * 60) + date("s"); | |
} | |
function midnight_seconds_to_time($seconds) | |
{ | |
if ($seconds > 0) { | |
$midnight = mktime(0, 0, 0, date("n") , date("j") , date("Y")); | |
return date("h:ia", $midnight + $seconds); | |
} | |
else { | |
return ""; | |
} | |
} | |
function viaPoints($tripid, $stopid, $timingPointsOnly = false) | |
{ | |
global $APIurl; | |
$url = $APIurl . "/json/tripstoptimes?trip=" . $tripid; | |
$json = json_decode(getPage($url)); | |
debug(print_r($json, true)); | |
$stops = $json[0]; | |
$times = $json[1]; | |
$foundStop = false; | |
$viaPoints = Array(); | |
foreach ($stops as $key => $row) { | |
if ($foundStop) { | |
if (!$timingPointsOnly || !startsWith($row[5], "Wj")) { | |
$viaPoints[] = Array( | |
"id" => $row[0], | |
"name" => $row[1], | |
"time" => $times[$key] | |
); | |
} | |
} | |
else { | |
if ($row[0] == $stopid) $foundStop = true; | |
} | |
} | |
return $viaPoints; | |
} | |
function viaPointNames($tripid, $stopid) | |
{ | |
$points = viaPoints($tripid, $stopid, true); | |
$pointNames = Array(); | |
foreach ($points as $point) { | |
$pointNames[] = $point['name']; | |
} | |
return implode(", ", $pointNames); | |
} | |
?> |
<?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://localhost:8080/opentripplanner-api-webapp/'; | $otpAPIurl = 'http://localhost:8080/opentripplanner-api-webapp/'; |
$owaSiteID = 'fe5b819fa8c424a99ff0764d955d23f3'; | $owaSiteID = 'fe5b819fa8c424a99ff0764d955d23f3'; |
//$debugOkay = Array("session","json","phperror","other"); | //$debugOkay = Array("session","json","phperror","other"); |
$debugOkay = Array("session","json","phperror"); | $debugOkay = Array( |
"session", | |
"json", | |
"phperror", | |
"other" | |
); | |
if (isDebug("phperror")) error_reporting(E_ALL ^ E_NOTICE); | if (isDebug("phperror")) error_reporting(E_ALL ^ E_NOTICE); |
include_once ("common-geo.inc.php"); | |
// SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',') | include_once ("common-net.inc.php"); |
$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"); | include_once ("common-template.inc.php"); |
include_once ("common-transit.inc.php"); | |
// 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'])) { | if (isset($_REQUEST['service_period'])) { |
$_SESSION['service_period'] = filter_var($_REQUEST['service_period'],FILTER_SANITIZE_STRING); | $_SESSION['service_period'] = filter_var($_REQUEST['service_period'], FILTER_SANITIZE_STRING); |
} | } |
if (isset($_REQUEST['time'])) { | if (isset($_REQUEST['time'])) { |
$_SESSION['time'] = filter_var($_REQUEST['time'],FILTER_SANITIZE_STRING); | $_SESSION['time'] = filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING); |
} | } |
if (isset($_REQUEST['geolocate'])) { | if (isset($_REQUEST['geolocate'])) { |
$geocoded = false; | |
if (isset($_REQUEST['lat']) && isset($_REQUEST['lon'])) { | $geocoded = false; |
$_SESSION['lat'] = filter_var($_REQUEST['lat'],FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); | if (isset($_REQUEST['lat']) && isset($_REQUEST['lon'])) { |
$_SESSION['lon'] = filter_var($_REQUEST['lon'],FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); | $_SESSION['lat'] = trim(filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)); |
} else { | $_SESSION['lon'] = trim(filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)); |
$contents = geocode(filter_var($_REQUEST['geolocate'],FILTER_SANITIZE_URL),true); | } |
if (isset($contents[0]->centroid)) { | else { |
$geocoded = true; | $geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL); |
$_SESSION['lat'] = $contents[0]->centroid->coordinates[0]; | echo $_REQUEST['geolocate']; |
$_SESSION['lon'] = $contents[0]->centroid->coordinates[1]; | if (startsWith($geolocate, "-")) { |
} | $locateparts = explode(",",$geolocate); |
else { | $_SESSION['lat'] = $locateparts[0]; |
$_SESSION['lat'] = ""; | $_SESSION['lon'] =$locateparts[1]; |
$_SESSION['lon'] = ""; | } else { |
} | $contents = geocode($geolocate, true); |
} | print_r($contents); |
if ($_SESSION['lat'] != "" && isMetricsOn()) { | if (isset($contents[0]->centroid)) { |
// Create a new Instance of the tracker | $geocoded = true; |
$owa = new owa_php($config); | $_SESSION['lat'] = $contents[0]->centroid->coordinates[0]; |
// Set the ID of the site being tracked | $_SESSION['lon'] = $contents[0]->centroid->coordinates[1]; |
$owa->setSiteId($owaSiteID); | } |
// Create a new event object | else { |
$event = $owa->makeEvent(); | $_SESSION['lat'] = ""; |
// Set the Event Type, in this case a "video_play" | $_SESSION['lon'] = ""; |
$event->setEventType('geolocate'); | } |
// Set a property | } |
$event->set('lat',$_SESSION['lat']); | } |
$event->set('lon',$_SESSION['lon']); | if ($_SESSION['lat'] != "" && isMetricsOn()) { |
$event->set('geocoded',$geocoded); | // Create a new Instance of the tracker |
// Track the event | $owa = new owa_php($config); |
$owa->trackEvent($event); | // Set the ID of the site being tracked |
} | $owa->setSiteId($owaSiteID); |
} | // Create a new event object |
debug(print_r($_SESSION,true)); | $event = $owa->makeEvent(); |
// Set the Event Type, in this case a "video_play" | |
$event->setEventType('geolocate'); | |
// Set a property | |
$event->set('lat', $_SESSION['lat']); | |
$event->set('lon', $_SESSION['lon']); | |
$event->set('geocoded', $geocoded); | |
// Track the event | |
$owa->trackEvent($event); | |
} | |
} | |
debug(print_r($_SESSION, true) , "session"); | |
function isDebugServer() | |
{ | |
return $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || !$_SERVER['SERVER_NAME']; | |
} | |
function isDebug($debugReason = "other") | function isDebug($debugReason = "other") |
{ | { |
global $debugOkay; | global $debugOkay; |
return in_array($debugReason,$debugOkay,false) && $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || !$_SERVER['SERVER_NAME']; | return in_array($debugReason, $debugOkay, false) && isDebugServer(); |
} | } |
function isMetricsOn() | function isMetricsOn() |
{ | { |
return !isDebug(); | return !isDebugServer(); |
} | } |
function debug($msg, $debugReason = "other") | |
function debug($msg, $debugReason = "other") { | { |
if (isDebug($debugReason)) echo "\n<!-- ".date(DATE_RFC822)."\n $msg -->\n"; | if (isDebug($debugReason)) echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n"; |
} | } |
function isFastDevice() { | function isFastDevice() |
$ua = $_SERVER['HTTP_USER_AGENT']; | { |
$fastDevices = Array("Mozilla/5.0 (X11;", "Mozilla/5.0 (Windows;", "Mozilla/5.0 (iP", "Mozilla/5.0 (Linux; U; Android", "Mozilla/4.0 (compatible; MSIE"); | $ua = $_SERVER['HTTP_USER_AGENT']; |
$fastDevices = Array( | |
$slowDevices = Array("J2ME","MIDP","Opera/","Mozilla/2.0 (compatible;","Mozilla/3.0 (compatible;"); | "Mozilla/5.0 (X11;", |
return true; | "Mozilla/5.0 (Windows;", |
"Mozilla/5.0 (iP", | |
"Mozilla/5.0 (Linux; U; Android", | |
"Mozilla/4.0 (compatible; MSIE" | |
); | |
$slowDevices = Array( | |
"J2ME", | |
"MIDP", | |
"Opera/", | |
"Mozilla/2.0 (compatible;", | |
"Mozilla/3.0 (compatible;" | |
); | |
return true; | |
} | } |
function array_flatten($a, $f = array()) | |
function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false) { | { |
echo ' | if (!$a || !is_array($a)) return ''; |
<!DOCTYPE html> | foreach ($a as $k => $v) { |
<html> | if (is_array($v)) $f = array_flatten($v, $f); |
<head> | else $f[$k] = $v; |
<title>'.$pageTitle.'</title>'; | } |
if (isDebug()) echo '<link rel="stylesheet" href="css/jquery-mobile-1.0a3.css" /> | return $f; |
<script type="text/javascript" src="js/jquery-1.5.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" /> | |
<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>'; | |
echo ' | |
<link rel="stylesheet" href="css/jquery.ui.datepicker.mobile.css" /> | |
<script> | |
//reset type=date inputs to text | |
$( document ).bind( "mobileinit", function(){ | |
$.mobile.page.prototype.options.degradeInputs.date = true; | |
}); | |
</script> | |
<script src="js/jQuery.ui.datepicker.js"></script> | |
<script src="js/jquery.ui.datepicker.mobile.js"></script> | |
<style type="text/css"> | |
.ui-navbar { | |
width: 100%; | |
} | |
.ui-btn-inner { | |
white-space: normal !important; | |
} | |
.ui-li-heading { | |
white-space: normal !important; | |
} | |
.ui-listview-filter { | |
margin: 0 !important; | |
} | |
#footer { | |
text-size: 0.75em; | |
text-align: center; | |
} | |
body { | |
background-color: #F0F0F0; | |
} | |
</style> | |
<meta name="apple-mobile-web-app-capable" content="yes" /> | |
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> | |
<link rel="apple-touch-startup-image" href="startup.png" /> | |
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; | |
if ($geolocate) { | |
echo "<script> | |
function success(position) { | |
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); | |
$.ajax({ url: \"common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude }); | |
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); | |
$('#here').show(); | |
} | } |
function error(msg) { | |
console.log(msg); | |
} | |
if (navigator.geolocation) { | |
navigator.geolocation.getCurrentPosition(success, error); | |
} | |
</script> "; | |
} | |
echo '</head> | |
<body> | |
'; | |
if (isMetricsOn()) { | |
require_once('owa/owa_env.php'); | |
require_once(OWA_DIR.'owa_php.php'); | |
$owa = new owa_php(); | |
global $owaSiteID; | |
$owa->setSiteId($owaSiteID); | |
$owa->setPageTitle($pageTitle); | |
$owa->setPageType($pageType); | |
$owa->trackPageView(); | |
$owa->placeHelperPageTags(); | |
} | |
if ($opendiv) { | |
echo '<div data-role="page"> | |
<script> | |
$(document).ready(function () | |
{ | |
document.title = "'.$pageTitle.'"; | |
}); | |
</script> | |
<div data-role="header"> | |
<h1>'.$pageTitle.'</h1> | |
</div><!-- /header --> | |
<div data-role="content"> '; | |
} | |
} | |
function include_footer() | |
{ | |
if ($geolocate && isset($_SESSION['lat'])) { | |
echo "<script> | |
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); | |
$('#here').show(); | |
</script>"; | |
} | |
echo '<div id="footer"><a href="about.php">About/Contact Us</a> <a href="feedback.php">Feedback/Bug Report</a></a>'; | |
echo '</div>'; | |
} | |
$service_periods = Array ('sunday','saturday','weekday'); | |
function service_period() | |
{ | |
if (isset($_SESSION['service_period'])) return $_SESSION['service_period']; | |
switch (date('w')){ | |
case 0: | |
return 'sunday'; | |
case 6: | |
return 'saturday'; | |
default: | |
return 'weekday'; | |
} | |
} | |
function remove_spaces($string) | function remove_spaces($string) |
{ | { |
return str_replace(' ','',$string); | return str_replace(' ', '', $string); |
} | } |
function object2array($object) | |
function midnight_seconds() | |
{ | { |
// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html | if (is_object($object)) { |
if (isset($_SESSION['time'])) { | foreach ($object as $key => $value) { |
$time = strtotime($_SESSION['time']); | $array[$key] = $value; |
return (date("G",$time) * 3600) + (date("i",$time) * 60) + date("s",$time); | } |
} | } |
return (date("G") * 3600) + (date("i") * 60) + date("s"); | else { |
$array = $object; | |
} | |
return $array; | |
} | } |
function startsWith($haystack, $needle, $case = true) | |
function midnight_seconds_to_time($seconds) | |
{ | { |
if ($seconds > 0) { | if ($case) { |
$midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); | return (strcmp(substr($haystack, 0, strlen($needle)) , $needle) === 0); |
return date("h:ia",$midnight+$seconds); | } |
} else { | return (strcasecmp(substr($haystack, 0, strlen($needle)) , $needle) === 0); |
return ""; | |
} | } |
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); | |
} | } |
function getPage($url) | function bracketsMeanNewLine($input) |
{ | { |
debug($url); | return str_replace(")", "</small>", str_replace("(", "<br><small>", $input)); |
$ch = curl_init($url); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); | |
curl_setopt( $ch, CURLOPT_HEADER, 0 ); | |
curl_setopt($ch,CURLOPT_TIMEOUT,30); | |
$page = curl_exec($ch); | |
if(curl_errno($ch)) echo "<font color=red> Database temporarily unavailable: ".curl_errno($ch)." ".curl_error($ch)."</font><br>"; | |
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; | |
} | |
function curPageURL() { | |
$isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); | |
$port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); | |
$port = ($port) ? ':'.$_SERVER["SERVER_PORT"] : ''; | |
$url = ($isHTTPS ? 'https://' : 'http://').$_SERVER["SERVER_NAME"].$port.dirname($_SERVER['PHP_SELF'])."/"; | |
return $url; | |
} | |
function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb", $collapsible = true) | |
{ | |
$width = 300; | |
$height = 300; | |
$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]; | |
} | |
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); | |
} | |
$output = ""; | |
if ($collapsible) $output .= '<div data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>'; | |
$output .= '<center><img src="'.curPageURL().'staticmaplite/staticmap.php?center='.$center.'&zoom='.$zoom.'&size='.$width.'x'.$height.'&maptype=mapnik&markers='.$markers.'" width='.$width.' height='.$height.'></center>'; | |
if ($collapsible) $output .= '</div>'; | |
return $output; | |
} | |
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) { | |
global $cloudmadeAPIkey; | |
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?query=".urlencode($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) { | |
global $cloudmadeAPIkey; | |
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/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); | |
} | |
function bracketsMeanNewLine($input) { | |
return str_replace(")","</small>",str_replace("(","<br><small>",$input)); | |
} | |
function viaPoints($tripid,$stopid, $timingPointsOnly = false) { | |
global $APIurl; | |
$url = $APIurl."/json/tripstoptimes?trip=".$tripid; | |
$json = json_decode(getPage($url)); | |
debug(print_r($json,true)); | |
$stops = $json[0]; | |
$times = $json[1]; | |
$foundStop = false; | |
$viaPoints = Array(); | |
foreach ($stops as $key => $row) | |
{ | |
if ($foundStop) { | |
if (!$timingPointsOnly || !startsWith($row[5],"Wj") ) { | |
$viaPoints[] = Array("id" => $row[0], "name" => $row[1], "time" => $times[$key]); | |
} | |
} else { | |
if ($row[0] == $stopid) $foundStop = true; | |
} | |
} | |
return $viaPoints; | |
} | |
function viaPointNames($tripid,$stopid) { | |
$points = viaPoints($tripid,$stopid,true); | |
$pointNames = Array(); | |
foreach ($points as $point) { | |
$pointNames[] = $point['name']; | |
} | |
return implode(", ",$pointNames); | |
} | |
function timePlaceSettings($geolocate = false) { | |
global $service_periods; | |
$geoerror = false; | |
if ($geolocate == true) { | |
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) | |
|| $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; | |
} | |
if ($geoerror) { | |
echo '<div class="error">Sorry, but your location could not currently be detected. | |
Please allow location permission, wait for your location to be detected, | |
or enter an address/co-ordinates in the box below.</div>'; | |
} | |
echo '<div data-role="collapsible" data-collapsed="'.!$geoerror.'"> | |
<h3>Change Time/Place...</h3> | |
<form action="" method="post"> | |
<div class="ui-body"> | |
<div data-role="fieldcontain"> | |
<label for="geolocate"> Current Location: </label> | |
<input type="text" id="geolocate" name="geolocate" value="'. (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] .",". $_SESSION['lon'] :"Enter co-ordinates or address here"). '"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="time"> Time: </label> | |
<input type="time" name="time" id="time" value="'. (isset($_SESSION['time']) ? $_SESSION['time'] : date("H:i")).'"/> <a href="#" name="currentTime" id="currentTime"/>Current Time?</a> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="service_period"> Service Period: </label> | |
<select name="service_period">'; | |
foreach ($service_periods as $service_period) { | |
echo "<option value=\"$service_period\"".(service_period() === $service_period ? "SELECTED" : "").'>'.ucwords($service_period).'</option>'; | |
} | |
echo '</select> | |
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a> | |
</div> | |
<input type="submit" value="Update"/> | |
</form> | |
</div></div>'; | |
} | |
?> | ?> |
Binary files a/css/images/113-navigation.png and b/css/images/113-navigation.png differ
Binary files /dev/null and b/css/images/time.png differ
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
include_header("Feedback","feedback"); | include_header("Feedback", "feedback"); |
function sendEmail($topic, $message) { | function sendEmail($topic, $message) |
$address = "maxious@lambdacomplex.org"; | { |
$address = "maxious@lambdacomplex.org"; | |
if (file_exists("/tmp/aws.php") ) { | if (file_exists("/tmp/aws.php")) { |
include_once('ses.php'); | include_once ('ses.php'); |
include_once("/tmp/aws.php"); | include_once ("/tmp/aws.php"); |
$con=new SimpleEmailService($accessKey,$secretKey); | $con = new SimpleEmailService($accessKey, $secretKey); |
//$con->verifyEmailAddress($address); | //$con->verifyEmailAddress($address); |
//$con->listVerifiedEmailAddresses(); | //$con->listVerifiedEmailAddresses(); |
$m = new SimpleEmailServiceMessage(); | |
$m = new SimpleEmailServiceMessage(); | $m->addTo($address); |
$m->addTo($address); | $m->setFrom($address); |
$m->setFrom($address); | $m->setSubject($topic); |
$m->setSubject($topic); | $m->setMessageFromString($message); |
$m->setMessageFromString($message); | $con->sendEmail($m); |
$con->sendEmail($m); | } |
} else { | else { |
// In case any of our lines are larger than 70 characters, we should use wordwrap() | // In case any of our lines are larger than 70 characters, we should use wordwrap() |
$message = wordwrap($message, 70); | $message = wordwrap($message, 70); |
// Send | |
// Send | mail($address, $topic, $message); |
mail($address, $topic, $message); | } |
} | } |
} | |
?> | ?> |
<h3>Add/Move/Delete a Bus Stop Location</h3> | <h3>Add/Move/Delete a Bus Stop Location</h3> |
StopID: | StopID: |
or StopCode: | or StopCode: |
<small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop <input type="text" name="stoplocation" /> </small> | <small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop <input type="text" name="stoplocation" /> </small> |
Suggested Stop Location (lat/long or words): | Suggested Stop Location (lat/long or words): |
<small> if your device supports javascript, you can pick a location from the map above</small> | <small> if your device supports javascript, you can pick a location from the map above</small> |
Submit! | Submit! |
<h3>Bug Report/Feedback</h3> | <h3>Bug Report/Feedback</h3> |
Please leave feedback about bugs/errors or general suggestions about improvements that could be made to the way the data is presented! | Please leave feedback about bugs/errors or general suggestions about improvements that could be made to the way the data is presented! |
<textarea id="feedback"> | <textarea id="feedback"> |
</textarea> | </textarea> |
<textarea id="extrainfo"> | <textarea id="extrainfo"> |
Referrer URL | Referrer URL |
User Agent | User Agent |
User host/IP | User host/IP |
Server host/IP | Server host/IP |
Current date/time | Current date/time |
Dump of $_SESSION | Dump of $_SESSION |
</textarea> | </textarea> |
Submit! | Submit! |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
include_header("bus.lambdacomplex.org","index",false, true) | include_header("bus.lambdacomplex.org", "index", 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" data-icon="navigation">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 | <?php |
echo timePlaceSettings(); | echo timePlaceSettings(); |
include_footer(true) | include_footer(true) |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
$output = Array(); | $output = Array(); |
$output['hotspots'] = Array(); | $output['hotspots'] = Array(); |
$output['layer'] = "canberrabusstops"; | $output['layer'] = "canberrabusstops"; |
$max_page = 10; | $max_page = 10; |
$max_results = 50; | $max_results = 50; |
$page_start = 0+filter_var($_REQUEST['pageKey'],FILTER_SANITIZE_NUMBER_INT); | $page_start = 0 + filter_var($_REQUEST['pageKey'], FILTER_SANITIZE_NUMBER_INT); |
$page_end = $max_page+filter_var($_REQUEST['pageKey'],FILTER_SANITIZE_NUMBER_INT); | $page_end = $max_page + filter_var($_REQUEST['pageKey'], FILTER_SANITIZE_NUMBER_INT); |
$lat = filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); | |
$lat = filter_var($_REQUEST['lat'],FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); | $lon = filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); |
$lon = filter_var($_REQUEST['lon'],FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); | $url = $APIurl . "/json/neareststops?lat=$lat&lon=$lon&limit=50"; |
if (isset($_REQUEST['radius'])) $radius = filter_var($_REQUEST['radius'],FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); | |
$url = $APIurl."/json/neareststops?lat=$lat&lon=$lon&limit=50"; | |
$contents = json_decode(getPage($url)); | $contents = json_decode(getPage($url)); |
debug(print_r($contents,true)); | debug(print_r($contents, true)); |
$stopNum = 0; | $stopNum = 0; |
foreach ($contents as $row) | foreach ($contents as $row) { |
{ | $stopNum++; |
$stopNum++; | if ($stopNum > $page_start && $stopNum <= $page_end) { |
if ($stopNum > $page_start && $stopNum <= $page_end) { | $hotspot = Array(); |
$hotspot = Array(); | $hotspot['id'] = $row[0]; |
$hotspot['id'] = $row[0]; | $hotspot['title'] = $row[1]; |
$hotspot['title'] = $row[1]; | $hotspot['type'] = 0; |
$hotspot['type'] = 0; | $hotspot['lat'] = floor($row[2] * 1000000); |
$hotspot['lat'] = floor($row[2]*1000000); | $hotspot['lon'] = floor($row[3] * 1000000); |
$hotspot['lon'] = floor($row[3]*1000000); | $hotspot['distance'] = distance($row[2], $row[3], $_REQUEST['lat'], $_REQUEST['lon']); |
$hotspot['distance'] = distance($row[2], $row[3], $_REQUEST['lat'], $_REQUEST['lon']); | $hotspot['actions'] = Array( |
if (!isset($_REQUEST['radius']) || $hotspot['distance'] < $radius) { | Array( |
$hotspot['actions'] = Array(Array("label" => 'View more trips/information', 'uri' => 'http://bus.lambdacomplex.org/'.'stop.php?stopid='.$row[0])); | "label" => 'View more trips/information', |
$url = $APIurl."/json/stoptrips?stop=".$row[0]."&time=".midnight_seconds()."&service_period=".service_period()."&limit=4&time_range=".str(90*60); | 'uri' => 'http://bus.lambdacomplex.org/' . 'stop.php?stopid=' . $row[0] |
$trips = json_decode(getPage($url)); | ) |
debug(print_r($trips,true)); | ); |
foreach ($trips as $key => $row) | $url = $APIurl . "/json/stoptrips?stop=" . $row[0] . "&time=" . midnight_seconds() . "&service_period=" . service_period() . "&limit=4&time_range=" . strval(90 * 60); |
{ | $trips = json_decode(getPage($url)); |
if ($key < 3) { | debug(print_r($trips, true)); |
$hotspot['line'.strval($key+2)]= $row[1][1] .' @ ' .midnight_seconds_to_time($row[0]); | foreach ($trips as $key => $row) { |
} | if ($key < 3) { |
} | $hotspot['line' . strval($key + 2) ] = $row[1][1] . ' @ ' . midnight_seconds_to_time($row[0]); |
if (sizeof($trips) == 0) $hotspot['line2'] = 'No trips in the near future.'; | } |
$output['hotspots'][] = $hotspot; | } |
} | if (sizeof($trips) == 0) $hotspot['line2'] = 'No trips in the near future.'; |
} | $output['hotspots'][] = $hotspot; |
} | |
} | } |
if (sizeof($hotspot) > 0) { | if (sizeof($hotspot) > 0) { |
$output['errorString'] = 'ok'; | $output['errorString'] = 'ok'; |
$output['errorCode'] = 0; | $output['errorCode'] = 0; |
} else { | } |
$output['errorString'] = 'no results, try increasing range'; | else { |
$output['errorCode'] = 21; | $output['errorString'] = 'no results, try increasing range'; |
$output['errorCode'] = 21; | |
} | } |
if ($page_end >= $max_results || sizeof($hotspot) < $max_page) { | if ($page_end >= $max_results || sizeof($hotspot) < $max_page) { |
$output["morePages"] = false; | $output["morePages"] = false; |
$output["nextPageKey"] = null; | $output["nextPageKey"] = null; |
} else { | } |
$output["morePages"] = true; | else { |
$output["nextPageKey"] = $page_end; | $output["morePages"] = true; |
$output["nextPageKey"] = $page_end; | |
} | } |
echo json_encode($output); | echo json_encode($output); |
?> | ?> |
<?php | |
function cleanString($subject) | |
{ | |
$subject = str_replace(" ", " ", $subject); | |
$subject = str_replace("&", "&", $subject); | |
$subject = preg_replace('/[^\r\n\t\x20-\x7E\xA0-\xFF]/', '', $subject); | |
$subject = str_replace(" ", " ", $subject); | |
return trim($subject); | |
} | |
$return = Array(); | |
/*if (file_exists("mywayresponse.txt")) { | |
@$fh = fopen("mywayresponse.txt", 'r'); | |
if ($fh) { | |
$pageHTML = fread($fh, filesize("mywayresponse.txt")); | |
fclose($fh); | |
} | |
}*/ | |
//set POST variables | |
$url = 'https://www.action.act.gov.au/ARTS/use_Funcs.asp'; | |
$field_mapping = Array( | |
"card_number" => "SRNO", | |
"DOBmonth" => "month", | |
"DOBday" => "day", | |
"DOByear" => "year", | |
"secret_answer" => "pwrd", | |
"button" => "button" | |
); | |
foreach (Array( | |
"card_number", | |
"DOBday", | |
"DOBmonth", | |
"DOByear" | |
) as $field_name) { | |
if (isset($_REQUEST[$field_name])) { | |
$fields[$field_name] = filter_var($_REQUEST[$field_name], FILTER_SANITIZE_NUMBER_INT); | |
} | |
else { | |
$return["error"][] = $field_name. " parameter invalid or unspecified"; | |
} | |
} | |
if (isset($_REQUEST['secret_answer'])) { | |
$fields['secret_answer'] = filter_var($_REQUEST['secret_answer'], FILTER_SANITIZE_STRING, Array( | |
FILTER_FLAG_NO_ENCODE_QUOTES, | |
FILTER_FLAG_STRIP_HIGH, | |
FILTER_FLAG_STRIP_LOW | |
)); | |
} | |
else { | |
$return["error"][] = "secret_answer parameter invalid or unspecified"; | |
} | |
$fields['button'] = 'Submit'; | |
$fields_string = ""; | |
//url-ify the data for the POST | |
foreach ($fields as $key => $value) { | |
if (sizeof($value) === 0) $return['error'][] = $key . " parameter invalid or unspecified"; | |
$fields_string.= $field_mapping[$key] . '=' . $value . '&'; | |
} | |
$fields_string = rtrim($fields_string, '&'); | |
if (!isset($return['error'])) { | |
//open connection | |
$ch = curl_init(); | |
//set the url, number of POST vars, POST data | |
curl_setopt($ch, CURLOPT_URL, $url); | |
curl_setopt($ch, CURLOPT_POST, count($fields)); | |
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($ch, CURLOPT_HEADER, 0); | |
curl_setopt($ch, CURLOPT_TIMEOUT, 30); | |
//execute post | |
$pageHTML = curl_exec($ch); | |
if (curl_errno($ch)) $return["error"][] = "Network error " . curl_errno($ch) . " " . curl_error($ch) . " " . $url . $fields_string; | |
//close connection | |
curl_close($ch); | |
} | |
if (!isset($return['error'])) { | |
include_once ('simple_html_dom.php'); | |
$page = str_get_html($pageHTML); | |
$pageAlerts = $page->find(".smartCardAlert"); | |
if (sizeof($pageAlerts) > 0) { | |
$return['error'][] = $pageAlerts[0]->plaintext; | |
} | |
if (!isset($return['error'])) { | |
$tableNum = 0; | |
$tableName = Array( | |
1 => "myway_carddetails", | |
2 => "myway_transactions" | |
); | |
foreach ($page->find("table") as $table) { | |
$tableNum++; | |
$tableColumns = Array(); | |
$tableColumnNum = 0; | |
foreach ($table->find("th") as $th) { | |
$tableColumns[$tableColumnNum] = cleanString($th->plaintext); | |
$tableColumnNum++; | |
} | |
$tableRowNum = 0; | |
foreach ($table->find("tr") as $tr) { | |
$tableColumnNum = 0; | |
foreach ($tr->find("td") as $td) { | |
if ($tableNum == 1) $return[$tableName[$tableNum]][$tableColumns[$tableColumnNum]] = cleanString($td->plaintext); | |
else $return[$tableName[$tableNum]][$tableRowNum][$tableColumns[$tableColumnNum]] = cleanString($td->plaintext); | |
$tableColumnNum++; | |
} | |
$tableRowNum++; | |
} | |
} | |
} | |
} | |
if (sizeof($return) == 0) { | |
$return['error'][] = "No data extracted from MyWay website - API may be out of date"; | |
} | |
header('Content-Type: text/javascript; charset=utf8'); | |
// header('Access-Control-Allow-Origin: http://bus.lambdacomplex.org/'); | |
header('Access-Control-Max-Age: 3628800'); | |
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); | |
if (isset($_GET['callback'])) { | |
$json = '(' . json_encode($return) . ');'; //must wrap in parens and end with semicolon | |
print_r($_GET['callback'] . $json); //callback is prepended for json-p | |
} | |
else echo json_encode($return); | |
?> | |
<?php | |
include ('common.inc.php'); | |
include_header("MyWay Balance", "mywayBalance"); | |
$return = Array(); | |
function printBalance($cardNumber, $date, $pwrd) | |
{ | |
global $return; | |
$return = json_decode(getPage(curPageURL() . "/myway_api.json.php?card_number=$cardNumber&DOBday={$date[0]}&DOBmonth={$date[1]}&DOByear={$date[2]}&secret_answer=$pwrd"), true); | |
if (isset($return['error'])) { | |
echo "<font color=red>" . var_dump($return['error']) . "</font>"; | |
} else { | |
echo "<h2>Balance: " . $return['myway_carddetails']['Card Balance'] . "</h2>"; | |
echo '<ul data-role="listview" data-inset="true"><li data-role="list-divider"> Recent Transactions </li>'; | |
foreach ($return['myway_transactions'] as $transaction) { | |
echo "<li><b>" . $transaction["Date / Time"] . "</b>"; | |
echo "<br><small>" . $transaction["TX Reference No / Type"]. "</small>"; | |
echo '<p class="ui-li-aside">'.$transaction["TX Amount"].'</p>'; | |
echo "</li>"; | |
} | |
echo "</ul>"; | |
} | |
} | |
if (isset($_REQUEST['card_number']) && isset($_REQUEST['date']) && isset($_REQUEST['secret_answer'])) { | |
$cardNumber = $_REQUEST['card_number']; | |
$date = explode("/", $_REQUEST['date']); | |
$pwrd = $_REQUEST['secret_answer']; | |
if ($_REQUEST['remember'] == true) { | |
$_COOKIE['card_number'] = $cardNumber; | |
$_COOKIE['date'] = $date; | |
$_COOKIE['secret_answer'] = $pwrd; | |
} | |
printBalance($cardNumber, $date, $pwrd); | |
} | |
else if (isset($_COOKIE['card_number']) && isset($_COOKIE['date']) && isset($_COOKIE['secret_answer'])) { | |
$cardNumber = $_COOKIE['card_number']; | |
$date = explode("/", $_COOKIE['date']); | |
$pwrd = $_COOKIE['secret_answer']; | |
printBalance($cardNumber, $date, $pwrd); | |
} | |
else { | |
$date = (isset($_REQUEST['date']) ? filter_var($_REQUEST['date'], FILTER_SANITIZE_STRING) : date("m/d/Y")); | |
echo '<form action="" method="post"> | |
<div data-role="fieldcontain"> | |
<label for="card_number">Card number</label> | |
<input type="text" name="card_number" id="card_number" value="' . $card_number . '" /> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="date"> Date of birth </label> | |
<input type="text" name="date" id="date" value="' . $date . '" /> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="secret_answer"> Secret question answer </label> | |
<input type="text" name="secret_answer" id="secret_answer" value="' . $secret_answer . '" /> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="remember"> Remember these details? </label> | |
<input type="checkbox" name="remember" id="remember" checked="yes" /> | |
</div> | |
<input type="submit" value="Go!"></form>'; | |
} | |
include_footer(); | |
?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
include_header("Routes","routeList"); | include_header("Routes", "routeList"); |
echo' | echo ' |
<div data-role="navbar"> | <div data-role="navbar"> |
<ul> | <ul> |
<li><a href="routeList.php">By Final Destination...</a></li> | <li><a href="routeList.php">By Final Destination...</a></li> |
<li><a href="routeList.php?bynumber=yes">By Number... </a></li> | <li><a href="routeList.php?bynumber=yes">By Number... </a></li> |
<li><a href="routeList.php?bysuburb=yes">By Suburb... </a></li> | <li><a href="routeList.php?bysuburb=yes">By Suburb... </a></li> |
<li><a href="routeList.php?nearby=yes">Nearby... </a></li> | <li><a href="routeList.php?nearby=yes">Nearby... </a></li> |
</ul> | </ul> |
</div> | </div> |
'; | '; |
echo ' <ul data-role="listview" data-inset="true">'; | echo ' <ul data-role="listview" data-inset="true">'; |
$url = $APIurl."/json/routes"; | $url = $APIurl . "/json/routes"; |
$contents = json_decode(getPage($url)); | $contents = json_decode(getPage($url)); |
debug(print_r($contents,true)); | function printRoutes($routes) |
{ | |
function printRoutes($routes){ | foreach ($routes as $row) { |
foreach($routes as $row) { | echo '<li>' . $row[1] . ' <a href="trip.php?routeid=' . $row[0] . '">' . $row[2] . " (" . ucwords($row[3]) . ")</a></li>\n"; |
echo '<li>'.$row[1].' <a href="trip.php?routeid='.$row[0].'">'.$row[2]." (".ucwords($row[3]).")</a></li>\n"; | } |
} | |
} | } |
if ($_REQUEST['bynumber']) { | if ($_REQUEST['bynumber']) { |
$routeSeries = Array(); | $routeSeries = Array(); |
$seriesRange = Array(); | $seriesRange = Array(); |
foreach ($contents as $key => $row) { | foreach ($contents as $key => $row) { |
foreach (explode(" ",$row[1]) as $routeNumber ) { | foreach (explode(" ", $row[1]) as $routeNumber) { |
$seriesNum = substr($routeNumber, 0, -1)."0"; | $seriesNum = substr($routeNumber, 0, -1) . "0"; |
if ($seriesNum == "0") $seriesNum = $routeNumber; | if ($seriesNum == "0") $seriesNum = $routeNumber; |
$finalDigit = substr($routeNumber, sizeof($routeNumber)-1, 1); | $finalDigit = substr($routeNumber, sizeof($routeNumber) - 1, 1); |
if (isset($seriesRange[$seriesNum])) { | if (isset($seriesRange[$seriesNum])) { |
if ($finalDigit < $seriesRange[$seriesNum]['max']) | if ($finalDigit < $seriesRange[$seriesNum]['max']) $seriesRange[$seriesNum]['max'] = $routeNumber; |
$seriesRange[$seriesNum]['max'] = $routeNumber; | if ($finalDigit > $seriesRange[$seriesNum]['min']) $seriesRange[$seriesNum]['min'] = $routeNumber; |
if ($finalDigit > $seriesRange[$seriesNum]['min']) | } |
$seriesRange[$seriesNum]['min'] = $routeNumber; | else { |
} else { | |
$seriesRange[$seriesNum]['max'] = $routeNumber; | $seriesRange[$seriesNum]['max'] = $routeNumber; |
$seriesRange[$seriesNum]['min'] = $routeNumber; | $seriesRange[$seriesNum]['min'] = $routeNumber; |
} | } |
$routeSeries[$seriesNum][$seriesNum."-".$row[1]."-".$row[0]] = $row; | $routeSeries[$seriesNum][$seriesNum . "-" . $row[1] . "-" . $row[0]] = $row; |
} | } |
} | } |
ksort($routeSeries); | ksort($routeSeries); |
ksort($seriesRange); | ksort($seriesRange); |
echo '<div class="noscriptnav"> Go to route numbers: '; | echo '<div class="noscriptnav"> Go to route numbers: '; |
foreach ($seriesRange as $series => $range) | foreach ($seriesRange as $series => $range) { |
{ | if ($range['min'] == $range['max']) echo "<a href=\"#$series\">$series</a> "; |
if ($range['min'] == $range['max']) echo "<a href=\"#$series\">$series</a> "; | else echo "<a href=\"#$series\">{$range['min']}-{$range['max']}</a> "; |
else echo "<a href=\"#$series\">{$range['min']}-{$range['max']}</a> "; | } |
} | echo "</div> |
echo "</div> | |
<script> | <script> |
$('.noscriptnav').hide(); | $('.noscriptnav').hide(); |
</script>"; | </script>"; |
foreach ($routeSeries as $series => $routes) | foreach ($routeSeries as $series => $routes) { |
{ | echo '<a name="' . $series . '"></a>'; |
echo '<a name="'.$series.'"></a>'; | if ($series <= 9) echo '<li>' . $series . "<ul>\n"; |
if ($series <= 9) echo '<li>'.$series."<ul>\n"; | |
else echo "<li>{$seriesRange[$series]['min']}-{$seriesRange[$series]['max']}<ul>\n"; | else echo "<li>{$seriesRange[$series]['min']}-{$seriesRange[$series]['max']}<ul>\n"; |
printRoutes($routes); | printRoutes($routes); |
echo "</ul></li>\n"; | echo "</ul></li>\n"; |
} | } |
} else { | } |
else { | |
foreach ($contents as $key => $row) { | foreach ($contents as $key => $row) { |
$routeDestinations[$row[2]][] = $row; | $routeDestinations[$row[2]][] = $row; |
} | } |
echo '<div class="noscriptnav"> Go to Destination: '; | echo '<div class="noscriptnav"> Go to Destination: '; |
foreach(ksort($routeDestinations) as $destination => $routes) | foreach (ksort($routeDestinations) as $destination => $routes) { |
{ | echo "<a href=\"#$destination\">$destination</a> "; |
echo "<a href=\"#$destination\">$destination</a> "; | } |
} | echo "</div> |
echo "</div> | |
<script> | <script> |
$('.noscriptnav').hide(); | $('.noscriptnav').hide(); |
</script>"; | </script>"; |
foreach ($routeDestinations as $destination => $routes) | foreach ($routeDestinations as $destination => $routes) { |
{ | echo '<a name="' . $destination . '"></a>'; |
echo '<a name="'.$destination.'"></a>'; | echo '<li>' . $destination . "... <ul>\n"; |
echo '<li>'.$destination."... <ul>\n"; | |
printRoutes($routes); | printRoutes($routes); |
echo "</ul></li>\n"; | echo "</ul></li>\n"; |
} | } |
} | } |
echo "</ul>\n"; | echo "</ul>\n"; |
include_footer(); | include_footer(); |
?> | ?> |
#!/usr/bin/python2.5 | #!/usr/bin/python2.5 |
# Copyright (C) 2007 Google Inc. | # Copyright (C) 2007 Google Inc. |
# | # |
# Licensed under the Apache License, Version 2.0 (the "License"); | # Licensed under the Apache License, Version 2.0 (the "License"); |
# you may not use this file except in compliance with the License. | # you may not use this file except in compliance with the License. |
# You may obtain a copy of the License at | # You may obtain a copy of the License at |
# | # |
# http://www.apache.org/licenses/LICENSE-2.0 | # http://www.apache.org/licenses/LICENSE-2.0 |
# | # |
# Unless required by applicable law or agreed to in writing, software | # Unless required by applicable law or agreed to in writing, software |
# distributed under the License is distributed on an "AS IS" BASIS, | # distributed under the License is distributed on an "AS IS" BASIS, |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
# See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and |
# limitations under the License. | # limitations under the License. |
""" | """ |
An example application that uses the transitfeed module. | An example application that uses the transitfeed module. |
You must provide a Google Maps API key. | You must provide a Google Maps API key. |
""" | """ |
import BaseHTTPServer, sys, urlparse | import BaseHTTPServer, sys, urlparse |
import bisect | import bisect |
from gtfsscheduleviewer.marey_graph import MareyGraph | from gtfsscheduleviewer.marey_graph import MareyGraph |
import gtfsscheduleviewer | import gtfsscheduleviewer |
import mimetypes | import mimetypes |
import os.path | import os.path |
import re | import re |
import signal | import signal |
import simplejson | import simplejson |
import socket | import socket |
import time | import time |
import datetime | import datetime |
import transitfeed | import transitfeed |
from transitfeed import util | from transitfeed import util |
import urllib | import urllib |
# By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break | # By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break |
# raise a KeyboardInterrupt. | # raise a KeyboardInterrupt. |
if hasattr(signal, 'SIGBREAK'): | if hasattr(signal, 'SIGBREAK'): |
signal.signal(signal.SIGBREAK, signal.default_int_handler) | signal.signal(signal.SIGBREAK, signal.default_int_handler) |
mimetypes.add_type('text/plain', '.vbs') | mimetypes.add_type('text/plain', '.vbs') |
class ResultEncoder(simplejson.JSONEncoder): | class ResultEncoder(simplejson.JSONEncoder): |
def default(self, obj): | def default(self, obj): |
try: | try: |
iterable = iter(obj) | iterable = iter(obj) |
except TypeError: | except TypeError: |
pass | pass |
else: | else: |
return list(iterable) | return list(iterable) |
return simplejson.JSONEncoder.default(self, obj) | return simplejson.JSONEncoder.default(self, obj) |
# Code taken from | # Code taken from |
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt | # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt |
# An alternate approach is shown at | # An alternate approach is shown at |
# http://mail.python.org/pipermail/python-list/2003-July/212751.html | # 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 | # but it requires multiple threads. A sqlite object can only be used from one |
# thread. | # thread. |
class StoppableHTTPServer(BaseHTTPServer.HTTPServer): | class StoppableHTTPServer(BaseHTTPServer.HTTPServer): |
def server_bind(self): | def server_bind(self): |
BaseHTTPServer.HTTPServer.server_bind(self) | BaseHTTPServer.HTTPServer.server_bind(self) |
self.socket.settimeout(1) | self.socket.settimeout(1) |
self._run = True | self._run = True |
def get_request(self): | def get_request(self): |
while self._run: | while self._run: |
try: | try: |
sock, addr = self.socket.accept() | sock, addr = self.socket.accept() |
sock.settimeout(None) | sock.settimeout(None) |
return (sock, addr) | return (sock, addr) |
except socket.timeout: | except socket.timeout: |
pass | pass |
def stop(self): | def stop(self): |
self._run = False | self._run = False |
def serve(self): | def serve(self): |
while self._run: | while self._run: |
self.handle_request() | self.handle_request() |
def StopToTuple(stop): | def StopToTuple(stop): |
"""Return tuple as expected by javascript function addStopMarkerFromList""" | """Return tuple as expected by javascript function addStopMarkerFromList""" |
return (stop.stop_id, stop.stop_name, float(stop.stop_lat), | return (stop.stop_id, stop.stop_name, float(stop.stop_lat), |
float(stop.stop_lon), stop.location_type, stop.stop_code) | float(stop.stop_lon), stop.location_type, stop.stop_code) |
def StopZoneToTuple(stop): | def StopZoneToTuple(stop): |
"""Return tuple as expected by javascript function addStopMarkerFromList""" | """Return tuple as expected by javascript function addStopMarkerFromList""" |
return (stop.stop_id, stop.stop_name, float(stop.stop_lat), | return (stop.stop_id, stop.stop_name, float(stop.stop_lat), |
float(stop.stop_lon), stop.location_type, stop.stop_code, stop.zone_id) | float(stop.stop_lon), stop.location_type, stop.stop_code, stop.zone_id) |
class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
cache = {} | cache = {} |
def do_GET(self): | def do_GET(self): |
scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) | scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) |
parsed_params = {} | parsed_params = {} |
for k in params.split('&'): | for k in params.split('&'): |
k = urllib.unquote(k) | k = urllib.unquote(k) |
if '=' in k: | if '=' in k: |
k, v = k.split('=', 1) | k, v = k.split('=', 1) |
parsed_params[k] = unicode(v, 'utf8') | parsed_params[k] = unicode(v, 'utf8') |
else: | else: |
parsed_params[k] = '' | parsed_params[k] = '' |
if path == '/': | if path == '/': |
return self.handle_GET_home() | return self.handle_GET_home() |
m = re.match(r'/json/([a-z]{1,64})', path) | m = re.match(r'/json/([a-z]{1,64})', path) |
if m: | if m: |
handler_name = 'handle_json_GET_%s' % m.group(1) | handler_name = 'handle_json_GET_%s' % m.group(1) |
handler = getattr(self, handler_name, None) | handler = getattr(self, handler_name, None) |
if callable(handler): | if callable(handler): |
return self.handle_json_wrapper_GET(handler, parsed_params, handler_name) | return self.handle_json_wrapper_GET(handler, parsed_params, handler_name) |
# Restrict allowable file names to prevent relative path attacks etc | # 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) | m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path) |
if m and m.group(1): | if m and m.group(1): |
try: | try: |
f, mime_type = self.OpenFile(m.group(1)) | f, mime_type = self.OpenFile(m.group(1)) |
return self.handle_static_file_GET(f, mime_type) | return self.handle_static_file_GET(f, mime_type) |
except IOError, e: | except IOError, e: |
print "Error: unable to open %s" % m.group(1) | print "Error: unable to open %s" % m.group(1) |
# Ignore and treat as 404 | # Ignore and treat as 404 |
m = re.match(r'/([a-z]{1,64})', path) | m = re.match(r'/([a-z]{1,64})', path) |
if m: | if m: |
handler_name = 'handle_GET_%s' % m.group(1) | handler_name = 'handle_GET_%s' % m.group(1) |
handler = getattr(self, handler_name, None) | handler = getattr(self, handler_name, None) |
if callable(handler): | if callable(handler): |
return handler(parsed_params) | return handler(parsed_params) |
return self.handle_GET_default(parsed_params, path) | return self.handle_GET_default(parsed_params, path) |
def OpenFile(self, filename): | def OpenFile(self, filename): |
"""Try to open filename in the static files directory of this server. | """Try to open filename in the static files directory of this server. |
Return a tuple (file object, string mime_type) or raise an exception.""" | Return a tuple (file object, string mime_type) or raise an exception.""" |
(mime_type, encoding) = mimetypes.guess_type(filename) | (mime_type, encoding) = mimetypes.guess_type(filename) |
assert mime_type | assert mime_type |
# A crude guess of when we should use binary mode. Without it non-unix | # A crude guess of when we should use binary mode. Without it non-unix |
# platforms may corrupt binary files. | # platforms may corrupt binary files. |
if mime_type.startswith('text/'): | if mime_type.startswith('text/'): |
mode = 'r' | mode = 'r' |
else: | else: |
mode = 'rb' | mode = 'rb' |
return open(os.path.join(self.server.file_dir, filename), mode), mime_type | return open(os.path.join(self.server.file_dir, filename), mode), mime_type |
def handle_GET_default(self, parsed_params, path): | def handle_GET_default(self, parsed_params, path): |
self.send_error(404) | self.send_error(404) |
def handle_static_file_GET(self, fh, mime_type): | def handle_static_file_GET(self, fh, mime_type): |
content = fh.read() | content = fh.read() |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', mime_type) | self.send_header('Content-Type', mime_type) |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def AllowEditMode(self): | def AllowEditMode(self): |
return False | return False |
def handle_GET_home(self): | def handle_GET_home(self): |
schedule = self.server.schedule | schedule = self.server.schedule |
(min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() | (min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() |
forbid_editing = ('true', 'false')[self.AllowEditMode()] | forbid_editing = ('true', 'false')[self.AllowEditMode()] |
agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') | agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') |
key = self.server.key | key = self.server.key |
host = self.server.host | host = self.server.host |
# A very simple template system. For a fixed set of values replace [xxx] | # A very simple template system. For a fixed set of values replace [xxx] |
# with the value of local variable xxx | # with the value of local variable xxx |
f, _ = self.OpenFile('index.html') | f, _ = self.OpenFile('index.html') |
content = f.read() | content = f.read() |
for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', | for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', |
'host', 'forbid_editing'): | 'host', 'forbid_editing'): |
content = content.replace('[%s]' % v, str(locals()[v])) | content = content.replace('[%s]' % v, str(locals()[v])) |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', 'text/html') | self.send_header('Content-Type', 'text/html') |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def handle_json_GET_routepatterns(self, params): | def handle_json_GET_routepatterns(self, params): |
"""Given a route_id generate a list of patterns of the route. For each | """Given a route_id generate a list of patterns of the route. For each |
pattern include some basic information and a few sample trips.""" | pattern include some basic information and a few sample trips.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
route = schedule.GetRoute(params.get('route', None)) | route = schedule.GetRoute(params.get('route', None)) |
if not route: | if not route: |
self.send_error(404) | self.send_error(404) |
return | return |
time = int(params.get('time', 0)) | time = int(params.get('time', 0)) |
sample_size = 10 # For each pattern return the start time for this many trips | sample_size = 10 # For each pattern return the start time for this many trips |
pattern_id_trip_dict = route.GetPatternIdTripDict() | pattern_id_trip_dict = route.GetPatternIdTripDict() |
patterns = [] | patterns = [] |
for pattern_id, trips in pattern_id_trip_dict.items(): | for pattern_id, trips in pattern_id_trip_dict.items(): |
time_stops = trips[0].GetTimeStops() | time_stops = trips[0].GetTimeStops() |
if not time_stops: | if not time_stops: |
continue | continue |
has_non_zero_trip_type = False; | has_non_zero_trip_type = False; |
for trip in trips: | for trip in trips: |
if trip['trip_type'] and trip['trip_type'] != '0': | if trip['trip_type'] and trip['trip_type'] != '0': |
has_non_zero_trip_type = True | 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)) | 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) | transitfeed.SortListOfTripByTime(trips) |
num_trips = len(trips) | num_trips = len(trips) |
if num_trips <= sample_size: | if num_trips <= sample_size: |
start_sample_index = 0 | start_sample_index = 0 |
num_after_sample = 0 | num_after_sample = 0 |
else: | else: |
# Will return sample_size trips that start after the 'time' param. | # 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 | # Linear search because I couldn't find a built-in way to do a binary |
# search with a custom key. | # search with a custom key. |
start_sample_index = len(trips) | start_sample_index = len(trips) |
for i, trip in enumerate(trips): | for i, trip in enumerate(trips): |
if trip.GetStartTime() >= time: | if trip.GetStartTime() >= time: |
start_sample_index = i | start_sample_index = i |
break | break |
num_after_sample = num_trips - (start_sample_index + sample_size) | num_after_sample = num_trips - (start_sample_index + sample_size) |
if num_after_sample < 0: | if num_after_sample < 0: |
# Less than sample_size trips start after 'time' so return all the | # Less than sample_size trips start after 'time' so return all the |
# last sample_size trips. | # last sample_size trips. |
num_after_sample = 0 | num_after_sample = 0 |
start_sample_index = num_trips - sample_size | start_sample_index = num_trips - sample_size |
sample = [] | sample = [] |
for t in trips[start_sample_index:start_sample_index + sample_size]: | for t in trips[start_sample_index:start_sample_index + sample_size]: |
sample.append( (t.GetStartTime(), t.trip_id) ) | sample.append( (t.GetStartTime(), t.trip_id) ) |
patterns.append((name, pattern_id, start_sample_index, sample, | patterns.append((name, pattern_id, start_sample_index, sample, |
num_after_sample, (0,1)[has_non_zero_trip_type])) | num_after_sample, (0,1)[has_non_zero_trip_type])) |
patterns.sort() | patterns.sort() |
return patterns | return patterns |
def handle_json_wrapper_GET(self, handler, parsed_params, handler_name): | def handle_json_wrapper_GET(self, handler, parsed_params, handler_name): |
"""Call handler and output the return value in JSON.""" | """Call handler and output the return value in JSON.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
# round times to nearest 100 seconds | # round times to nearest 100 seconds |
if "time" in parsed_params: | if "time" in parsed_params: |
parsed_params['time'] = int(round(float(parsed_params['time']),-2)) | parsed_params['time'] = int(round(float(parsed_params['time']),-2)) |
paramkey = tuple(sorted(parsed_params.items())) | paramkey = tuple(sorted(parsed_params.items())) |
if handler_name in self.cache and paramkey in self.cache[handler_name] : | if handler_name in self.cache and paramkey in self.cache[handler_name] : |
print ("Cache hit for ",handler_name," params ",parsed_params) | print ("Cache hit for ",handler_name," params ",parsed_params) |
else: | else: |
print ("Cache miss for ",handler_name," params ",parsed_params) | print ("Cache miss for ",handler_name," params ",parsed_params) |
result = handler(parsed_params) | result = handler(parsed_params) |
if not handler_name in self.cache: | if not handler_name in self.cache: |
self.cache[handler_name] = {} | self.cache[handler_name] = {} |
self.cache[handler_name][paramkey] = ResultEncoder().encode(result) | self.cache[handler_name][paramkey] = ResultEncoder().encode(result) |
content = self.cache[handler_name][paramkey] | content = self.cache[handler_name][paramkey] |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', 'text/plain') | self.send_header('Content-Type', 'text/plain') |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def handle_json_GET_routes(self, params): | def handle_json_GET_routes(self, params): |
"""Return a list of all routes.""" | """Return a list of all routes.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
result = [] | result = [] |
for r in schedule.GetRouteList(): | for r in schedule.GetRouteList(): |
servicep = None | servicep = None |
for t in schedule.GetTripList(): | for t in schedule.GetTripList(): |
if t.route_id == r.route_id: | if t.route_id == r.route_id: |
servicep = t.service_period | servicep = t.service_period |
break | break |
result.append( (r.route_id, r.route_short_name, r.route_long_name, servicep.service_id) ) | result.append( (r.route_id, r.route_short_name, r.route_long_name, servicep.service_id) ) |
result.sort(key = lambda x: x[1:3]) | result.sort(key = lambda x: x[1:3]) |
return result | return result |
def handle_json_GET_routerow(self, params): | def handle_json_GET_routerow(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
route = schedule.GetRoute(params.get('route', None)) | route = schedule.GetRoute(params.get('route', None)) |
return [transitfeed.Route._FIELD_NAMES, route.GetFieldValuesTuple()] | return [transitfeed.Route._FIELD_NAMES, route.GetFieldValuesTuple()] |
def handle_json_GET_routetrips(self, params): | def handle_json_GET_routetrips(self, params): |
""" Get a trip for a route_id (preferablly the next one) """ | """ Get a trip for a route_id (preferablly the next one) """ |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('route_id', None).lower() | query = params.get('route_id', None).lower() |
result = [] | result = [] |
for t in schedule.GetTripList(): | for t in schedule.GetTripList(): |
if t.route_id == query: | if t.route_id == query: |
result.append ( (t.GetStartTime(), t.trip_id) ) | try: |
starttime = t.GetStartTime() | |
except: | |
print "Error for GetStartTime of trip #" + t.trip_id + sys.exc_info()[0] | |
else: | |
result.append ( (starttime, t.trip_id) ) | |
return sorted(result, key=lambda trip: trip[0]) | return sorted(result, key=lambda trip: trip[0]) |
def handle_json_GET_triprows(self, params): | def handle_json_GET_triprows(self, params): |
"""Return a list of rows from the feed file that are related to this | """Return a list of rows from the feed file that are related to this |
trip.""" | trip.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
try: | try: |
trip = schedule.GetTrip(params.get('trip', None)) | trip = schedule.GetTrip(params.get('trip', None)) |
except KeyError: | except KeyError: |
# if a non-existent trip is searched for, the return nothing | # if a non-existent trip is searched for, the return nothing |
return | return |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
trip_row = dict(trip.iteritems()) | trip_row = dict(trip.iteritems()) |
route_row = dict(route.iteritems()) | route_row = dict(route.iteritems()) |
return [['trips.txt', trip_row], ['routes.txt', route_row]] | return [['trips.txt', trip_row], ['routes.txt', route_row]] |
def handle_json_GET_tripstoptimes(self, params): | def handle_json_GET_tripstoptimes(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
try: | try: |
trip = schedule.GetTrip(params.get('trip')) | trip = schedule.GetTrip(params.get('trip')) |
except KeyError: | except KeyError: |
# if a non-existent trip is searched for, the return nothing | # if a non-existent trip is searched for, the return nothing |
return | return |
time_stops = trip.GetTimeInterpolatedStops() | time_stops = trip.GetTimeInterpolatedStops() |
stops = [] | stops = [] |
times = [] | times = [] |
for arr,ts,is_timingpoint in time_stops: | for arr,ts,is_timingpoint in time_stops: |
stops.append(StopToTuple(ts.stop)) | stops.append(StopToTuple(ts.stop)) |
times.append(arr) | times.append(arr) |
return [stops, times] | return [stops, times] |
def handle_json_GET_tripshape(self, params): | def handle_json_GET_tripshape(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
try: | try: |
trip = schedule.GetTrip(params.get('trip')) | trip = schedule.GetTrip(params.get('trip')) |
except KeyError: | except KeyError: |
# if a non-existent trip is searched for, the return nothing | # if a non-existent trip is searched for, the return nothing |
return | return |
points = [] | points = [] |
if trip.shape_id: | if trip.shape_id: |
shape = schedule.GetShape(trip.shape_id) | shape = schedule.GetShape(trip.shape_id) |
for (lat, lon, dist) in shape.points: | for (lat, lon, dist) in shape.points: |
points.append((lat, lon)) | points.append((lat, lon)) |
else: | else: |
time_stops = trip.GetTimeStops() | time_stops = trip.GetTimeStops() |
for arr,dep,stop in time_stops: | for arr,dep,stop in time_stops: |
points.append((stop.stop_lat, stop.stop_lon)) | points.append((stop.stop_lat, stop.stop_lon)) |
return points | return points |
# | |
# GeoPo Encode in Python | |
# @author : Shintaro Inagaki | |
# @param location (Dictionary) [lat (Float), lng (Float), scale(Int)] | |
# @return geopo (String) | |
# | |
def handle_json_GET_neareststops(self, params): | def handle_json_GET_neareststops(self, params): |
"""Return a list of the nearest 'limit' stops to 'lat', 'lon'""" | """Return a list of the nearest 'limit' stops to 'lat', 'lon'""" |
schedule = self.server.schedule | schedule = self.server.schedule |
lat = float(params.get('lat')) | lat = float(params.get('lat')) |
lon = float(params.get('lon')) | lon = float(params.get('lon')) |
limit = int(params.get('limit')) | limit = int(params.get('limit',5)) |
stops = schedule.GetNearestStops(lat=lat, lon=lon, n=limit) | scale = int(params.get('scale',5)) # 5 = neighbourhood ~ 1km, 4= town 5 by 7km |
return [StopToTuple(s) for s in stops] | stops = [] |
# 64characters (number + big and small letter + hyphen + underscore) | |
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_" | |
geopo = "" | |
# Change a degree measure to a decimal number | |
lat = (lat + 90.0) / 180 * 8 ** 10 # 90.0 is forced FLOAT type when lat is INT | |
lon = (lon + 180.0) / 360 * 8 ** 10 # 180.0 is same | |
# Compute a GeoPo code from head and concatenate | |
for i in range(scale): | |
order = int(lat / (8 ** (9 - i)) % 8) + int(lon / (8 ** (9 - i)) % 8) * 8 | |
geopo = geopo + chars[order] | |
for s in schedule.GetStopList(): | |
if s.stop_code.find(geopo) != -1: | |
stops.append(s) | |
if scale == 5: | |
print stops | |
return [StopToTuple(s) for s in stops] | |
else: | |
dist_stop_list = [] | |
for s in stops: | |
# TODO: Use util.ApproximateDistanceBetweenStops? | |
dist = (s.stop_lat - lat)**2 + (s.stop_lon - lon)**2 | |
if len(dist_stop_list) < limit: | |
bisect.insort(dist_stop_list, (dist, s)) | |
elif dist < dist_stop_list[-1][0]: | |
bisect.insort(dist_stop_list, (dist, s)) | |
dist_stop_list.pop() # Remove stop with greatest distance | |
print dist_stop_list | |
return [StopToTuple(s) for dist, s in dist_stop_list] | |
def handle_json_GET_boundboxstops(self, params): | def handle_json_GET_boundboxstops(self, params): |
"""Return a list of up to 'limit' stops within bounding box with 'n','e' | """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 | and 's','w' in the NE and SW corners. Does not handle boxes crossing |
longitude line 180.""" | longitude line 180.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
n = float(params.get('n')) | n = float(params.get('n')) |
e = float(params.get('e')) | e = float(params.get('e')) |
s = float(params.get('s')) | s = float(params.get('s')) |
w = float(params.get('w')) | w = float(params.get('w')) |
limit = int(params.get('limit')) | limit = int(params.get('limit')) |
stops = schedule.GetStopsInBoundingBox(north=n, east=e, south=s, west=w, n=limit) | stops = schedule.GetStopsInBoundingBox(north=n, east=e, south=s, west=w, n=limit) |
return [StopToTuple(s) for s in stops] | return [StopToTuple(s) for s in stops] |
def handle_json_GET_stops(self, params): | def handle_json_GET_stops(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
return [StopToTuple(s) for s in schedule.GetStopList()] | return [StopToTuple(s) for s in schedule.GetStopList()] |
def handle_json_GET_timingpoints(self, params): | def handle_json_GET_timingpoints(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_code.find("Wj") == -1: | if s.stop_code.find("Wj") == -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stopsearch(self, params): | def handle_json_GET_stopsearch(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('q', None).lower() | query = params.get('q', None).lower() |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_name.lower().find(query) != -1 or s.stop_code.lower().find(query) != -1: | if s.stop_name.lower().find(query) != -1 or s.stop_code.lower().find(query) != -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stopnamesearch(self, params): | def handle_json_GET_stopnamesearch(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('q', None).lower() | query = params.get('q', None).lower() |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_name.lower().find(query) != -1: | if s.stop_name.lower().find(query) != -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stopcodesearch(self, params): | def handle_json_GET_stopcodesearch(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('q', None).lower() | query = params.get('q', None).lower() |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_code.lower().find(query) != -1: | if s.stop_code.lower().find(query) != -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stopzonesearch(self, params): | def handle_json_GET_stopzonesearch(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('q', None).lower() | query = params.get('q', None).lower() |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.zone_id != None and s.zone_id.lower().find(query) != -1: | if s.zone_id != None and s.zone_id.lower().find(query) != -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stop(self, params): | def handle_json_GET_stop(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('stop_id', None).lower() | query = params.get('stop_id', None).lower() |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_id.lower() == query: | if s.stop_id.lower() == query: |
return StopToTuple(s) | return StopToTuple(s) |
return [] | return [] |
def handle_json_GET_stoproutes(self, params): | def handle_json_GET_stoproutes(self, params): |
"""Given a stop_id return all routes to visit the stop.""" | """Given a stop_id return all routes to visit the stop.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
stop = schedule.GetStop(params.get('stop', None)) | stop = schedule.GetStop(params.get('stop', None)) |
service_period = params.get('service_period', None) | service_period = params.get('service_period', None) |
trips = stop.GetTrips(schedule) | trips = stop.GetTrips(schedule) |
result = {} | result = {} |
for trip in trips: | for trip in trips: |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
if not trip.route_id in result: | if not trip.route_short_name+route.route_long_name in result: |
result[trip.route_id] = (route.route_id, route.route_short_name, route.route_long_name, trip.trip_id) | result[trip.route_short_name+route.route_long_name] = (route.route_id, route.route_short_name, route.route_long_name, trip.trip_id) |
return result | return result |
def handle_json_GET_stopalltrips(self, params): | def handle_json_GET_stopalltrips(self, params): |
"""Given a stop_id return all trips to visit the stop.""" | """Given a stop_id return all trips to visit the stop.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
stop = schedule.GetStop(params.get('stop', None)) | stop = schedule.GetStop(params.get('stop', None)) |
service_period = params.get('service_period', None) | service_period = params.get('service_period', None) |
time_trips = stop.GetStopTimeTrips(schedule) | time_trips = stop.GetStopTimeTrips(schedule) |
result = [] | result = [] |
for time, (trip, index), tp in time_trips: | for time, (trip, index), tp in time_trips: |
headsign = None | headsign = None |
# Find the most recent headsign from the StopTime objects | # Find the most recent headsign from the StopTime objects |
for stoptime in trip.GetStopTimes()[index::-1]: | for stoptime in trip.GetStopTimes()[index::-1]: |
if stoptime.stop_headsign: | if stoptime.stop_headsign: |
headsign = stoptime.stop_headsign | headsign = stoptime.stop_headsign |
break | break |
# If stop_headsign isn't found, look for a trip_headsign | # If stop_headsign isn't found, look for a trip_headsign |
if not headsign: | if not headsign: |
headsign = trip.trip_headsign | headsign = trip.trip_headsign |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
trip_name = '' | trip_name = '' |
if route.route_short_name: | if route.route_short_name: |
trip_name += route.route_short_name | trip_name += route.route_short_name |
if route.route_long_name: | if route.route_long_name: |
if len(trip_name): | if len(trip_name): |
trip_name += " - " | trip_name += " - " |
trip_name += route.route_long_name | trip_name += route.route_long_name |
if service_period == None or trip.service_id == service_period: | if service_period == None or trip.service_id == service_period: |
result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) | result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) |
return result | return result |
def handle_json_GET_stoptrips(self, params): | def handle_json_GET_stoptrips(self, params): |
"""Given a stop_id and time in seconds since midnight return the next | """Given a stop_id and time in seconds since midnight return the next |
trips to visit the stop.""" | trips to visit the stop.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
stop = schedule.GetStop(params.get('stop', None)) | stop = schedule.GetStop(params.get('stop', None)) |
requested_time = int(params.get('time', 0)) | requested_time = int(params.get('time', 0)) |
limit = int(params.get('limit', 15)) | limit = int(params.get('limit', 15)) |
service_period = params.get('service_period', None) | service_period = params.get('service_period', None) |
time_range = params.get('time_range', 24*60*60) | time_range = int(params.get('time_range', 24*60*60)) |
filtered_time_trips = [] | filtered_time_trips = [] |
for trip, index in stop._GetTripIndex(schedule): | for trip, index in stop._GetTripIndex(schedule): |
tripstarttime = trip.GetStartTime() | tripstarttime = trip.GetStartTime() |
if tripstarttime > requested_time and tripstarttime < (requested_time + time_range): | if tripstarttime > requested_time and tripstarttime < (requested_time + time_range): |
time, stoptime, tp = trip.GetTimeInterpolatedStops()[index] | time, stoptime, tp = trip.GetTimeInterpolatedStops()[index] |
if time > requested_time and time < (requested_time + time_range): | if time > requested_time and time < (requested_time + time_range): |
bisect.insort(filtered_time_trips, (time, (trip, index), tp)) | bisect.insort(filtered_time_trips, (time, (trip, index), tp)) |
result = [] | result = [] |
for time, (trip, index), tp in filtered_time_trips: | for time, (trip, index), tp in filtered_time_trips: |
if len(result) > limit: | if len(result) > limit: |
break | break |
headsign = None | headsign = None |
# Find the most recent headsign from the StopTime objects | # Find the most recent headsign from the StopTime objects |
for stoptime in trip.GetStopTimes()[index::-1]: | for stoptime in trip.GetStopTimes()[index::-1]: |
if stoptime.stop_headsign: | if stoptime.stop_headsign: |
headsign = stoptime.stop_headsign | headsign = stoptime.stop_headsign |
break | break |
# If stop_headsign isn't found, look for a trip_headsign | # If stop_headsign isn't found, look for a trip_headsign |
if not headsign: | if not headsign: |
headsign = trip.trip_headsign | headsign = trip.trip_headsign |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
trip_name = '' | trip_name = '' |
if route.route_short_name: | if route.route_short_name: |
trip_name += route.route_short_name | trip_name += route.route_short_name |
if route.route_long_name: | if route.route_long_name: |
if len(trip_name): | if len(trip_name): |
trip_name += " - " | trip_name += " - " |
trip_name += route.route_long_name | trip_name += route.route_long_name |
# comment out directions because we already have them in the long name | # comment out directions because we already have them in the long name |
#if headsign: | #if headsign: |
# trip_name += " (Direction: %s)" % headsign | # trip_name += " (Direction: %s)" % headsign |
if service_period == None or trip.service_id == service_period: | if service_period == None or trip.service_id == service_period: |
result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) | result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) |
return result | return result |
def handle_GET_ttablegraph(self,params): | def handle_GET_ttablegraph(self,params): |
"""Draw a Marey graph in SVG for a pattern (collection of trips in a route | """Draw a Marey graph in SVG for a pattern (collection of trips in a route |
that visit the same sequence of stops).""" | that visit the same sequence of stops).""" |
schedule = self.server.schedule | schedule = self.server.schedule |
marey = MareyGraph() | marey = MareyGraph() |
trip = schedule.GetTrip(params.get('trip', None)) | trip = schedule.GetTrip(params.get('trip', None)) |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
height = int(params.get('height', 300)) | height = int(params.get('height', 300)) |
if not route: | if not route: |
print 'no such route' | print 'no such route' |
self.send_error(404) | self.send_error(404) |
return | return |
pattern_id_trip_dict = route.GetPatternIdTripDict() | pattern_id_trip_dict = route.GetPatternIdTripDict() |
pattern_id = trip.pattern_id | pattern_id = trip.pattern_id |
if pattern_id not in pattern_id_trip_dict: | if pattern_id not in pattern_id_trip_dict: |
print 'no pattern %s found in %s' % (pattern_id, pattern_id_trip_dict.keys()) | print 'no pattern %s found in %s' % (pattern_id, pattern_id_trip_dict.keys()) |
self.send_error(404) | self.send_error(404) |
return | return |
triplist = pattern_id_trip_dict[pattern_id] | triplist = pattern_id_trip_dict[pattern_id] |
pattern_start_time = min((t.GetStartTime() for t in triplist)) | pattern_start_time = min((t.GetStartTime() for t in triplist)) |
pattern_end_time = max((t.GetEndTime() for t in triplist)) | pattern_end_time = max((t.GetEndTime() for t in triplist)) |
marey.SetSpan(pattern_start_time,pattern_end_time) | marey.SetSpan(pattern_start_time,pattern_end_time) |
marey.Draw(triplist[0].GetPattern(), triplist, height) | marey.Draw(triplist[0].GetPattern(), triplist, height) |
content = marey.Draw() | content = marey.Draw() |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', 'image/svg+xml') | self.send_header('Content-Type', 'image/svg+xml') |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def FindPy2ExeBase(): | def FindPy2ExeBase(): |
"""If this is running in py2exe return the install directory else return | """If this is running in py2exe return the install directory else return |
None""" | None""" |
# py2exe puts gtfsscheduleviewer in library.zip. For py2exe setup.py is | # py2exe puts gtfsscheduleviewer in library.zip. For py2exe setup.py is |
# configured to put the data next to library.zip. | # configured to put the data next to library.zip. |
windows_ending = gtfsscheduleviewer.__file__.find('\\library.zip\\') | windows_ending = gtfsscheduleviewer.__file__.find('\\library.zip\\') |
if windows_ending != -1: | if windows_ending != -1: |
return transitfeed.__file__[:windows_ending] | return transitfeed.__file__[:windows_ending] |
else: | else: |
return None | return None |
def FindDefaultFileDir(): | def FindDefaultFileDir(): |
"""Return the path of the directory containing the static files. By default | """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 | the directory is called 'files'. The location depends on where setup.py put |
it.""" | it.""" |
base = FindPy2ExeBase() | base = FindPy2ExeBase() |
if base: | if base: |
return os.path.join(base, 'schedule_viewer_files') | return os.path.join(base, 'schedule_viewer_files') |
else: | else: |
# For all other distributions 'files' is in the gtfsscheduleviewer | # For all other distributions 'files' is in the gtfsscheduleviewer |
# directory. | # directory. |
base = os.path.dirname(gtfsscheduleviewer.__file__) # Strip __init__.py | base = os.path.dirname(gtfsscheduleviewer.__file__) # Strip __init__.py |
return os.path.join(base, 'files') | return os.path.join(base, 'files') |
def GetDefaultKeyFilePath(): | def GetDefaultKeyFilePath(): |
"""In py2exe return absolute path of file in the base directory and in all | """In py2exe return absolute path of file in the base directory and in all |
other distributions return relative path 'key.txt'""" | other distributions return relative path 'key.txt'""" |
windows_base = FindPy2ExeBase() | windows_base = FindPy2ExeBase() |
if windows_base: | if windows_base: |
return os.path.join(windows_base, 'key.txt') | return os.path.join(windows_base, 'key.txt') |
else: | else: |
return 'key.txt' | return 'key.txt' |
def main(RequestHandlerClass = ScheduleRequestHandler): | def main(RequestHandlerClass = ScheduleRequestHandler): |
usage = \ | usage = \ |
'''%prog [options] [<input GTFS.zip>] | '''%prog [options] [<input GTFS.zip>] |
Runs a webserver that lets you explore a <input GTFS.zip> in your browser. | Runs a webserver that lets you explore a <input GTFS.zip> in your browser. |
If <input GTFS.zip> is omited the filename is read from the console. Dragging | If <input GTFS.zip> is omited the filename is read from the console. Dragging |
a file into the console may enter the filename. | a file into the console may enter the filename. |
''' | ''' |
parser = util.OptionParserLongError( | parser = util.OptionParserLongError( |
usage=usage, version='%prog '+transitfeed.__version__) | usage=usage, version='%prog '+transitfeed.__version__) |
parser.add_option('--feed_filename', '--feed', dest='feed_filename', | parser.add_option('--feed_filename', '--feed', dest='feed_filename', |
help='file name of feed to load') | help='file name of feed to load') |
parser.add_option('--key', dest='key', | parser.add_option('--key', dest='key', |
help='Google Maps API key or the name ' | help='Google Maps API key or the name ' |
'of a text file that contains an API key') | 'of a text file that contains an API key') |
parser.add_option('--host', dest='host', help='Host name of Google Maps') | parser.add_option('--host', dest='host', help='Host name of Google Maps') |
parser.add_option('--port', dest='port', type='int', | parser.add_option('--port', dest='port', type='int', |
help='port on which to listen') | help='port on which to listen') |
parser.add_option('--file_dir', dest='file_dir', | parser.add_option('--file_dir', dest='file_dir', |
help='directory containing static files') | help='directory containing static files') |
parser.add_option('-n', '--noprompt', action='store_false', | parser.add_option('-n', '--noprompt', action='store_false', |
dest='manual_entry', | dest='manual_entry', |
help='disable interactive prompts') | help='disable interactive prompts') |
parser.set_defaults(port=8765, | parser.set_defaults(port=8765, |
host='maps.google.com', | host='maps.google.com', |
file_dir=FindDefaultFileDir(), | file_dir=FindDefaultFileDir(), |
manual_entry=True) | manual_entry=True) |
(options, args) = parser.parse_args() | (options, args) = parser.parse_args() |
if not os.path.isfile(os.path.join(options.file_dir, 'index.html')): | 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 | print "Can't find index.html with --file_dir=%s" % options.file_dir |
exit(1) | exit(1) |
if not options.feed_filename and len(args) == 1: | if not options.feed_filename and len(args) == 1: |
options.feed_filename = args[0] | options.feed_filename = args[0] |
if not options.feed_filename and options.manual_entry: | if not options.feed_filename and options.manual_entry: |
options.feed_filename = raw_input('Enter Feed Location: ').strip('"') | options.feed_filename = raw_input('Enter Feed Location: ').strip('"') |
default_key_file = GetDefaultKeyFilePath() | default_key_file = GetDefaultKeyFilePath() |
if not options.key and os.path.isfile(default_key_file): | if not options.key and os.path.isfile(default_key_file): |
options.key = open(default_key_file).read().strip() | options.key = open(default_key_file).read().strip() |
if options.key and os.path.isfile(options.key): | if options.key and os.path.isfile(options.key): |
options.key = open(options.key).read().strip() | options.key = open(options.key).read().strip() |
schedule = transitfeed.Schedule(problem_reporter=transitfeed.ProblemReporter()) | schedule = transitfeed.Schedule(problem_reporter=transitfeed.ProblemReporter()) |
print 'Loading data from feed "%s"...' % options.feed_filename | print 'Loading data from feed "%s"...' % options.feed_filename |
print '(this may take a few minutes for larger cities)' | print '(this may take a few minutes for larger cities)' |
t0 = datetime.datetime.now() | t0 = datetime.datetime.now() |
schedule.Load(options.feed_filename) | schedule.Load(options.feed_filename) |
print ("Loaded in", (datetime.datetime.now() - t0).seconds , "seconds") | print ("Loaded in", (datetime.datetime.now() - t0).seconds , "seconds") |
server = StoppableHTTPServer(server_address=('', options.port), | server = StoppableHTTPServer(server_address=('', options.port), |
RequestHandlerClass=RequestHandlerClass) | RequestHandlerClass=RequestHandlerClass) |
server.key = options.key | server.key = options.key |
server.schedule = schedule | server.schedule = schedule |
server.file_dir = options.file_dir | server.file_dir = options.file_dir |
server.host = options.host | server.host = options.host |
server.feed_path = options.feed_filename | server.feed_path = options.feed_filename |
print ("To view, point your browser at http://localhost:%d/" % | print ("To view, point your browser at http://localhost:%d/" % |
(server.server_port)) | (server.server_port)) |
server.serve_forever() | server.serve_forever() |
if __name__ == '__main__': | if __name__ == '__main__': |
main() | main() |
<?php | |
/******************************************************************************* | |
Version: 1.11 ($Rev: 175 $) | |
Website: http://sourceforge.net/projects/simplehtmldom/ | |
Author: S.C. Chen <me578022@gmail.com> | |
Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/) | |
Contributions by: | |
Yousuke Kumakura (Attribute filters) | |
Vadim Voituk (Negative indexes supports of "find" method) | |
Antcs (Constructor with automatically load contents either text or file/url) | |
Licensed under The MIT License | |
Redistributions of files must retain the above copyright notice. | |
*******************************************************************************/ | |
define('HDOM_TYPE_ELEMENT', 1); | |
define('HDOM_TYPE_COMMENT', 2); | |
define('HDOM_TYPE_TEXT', 3); | |
define('HDOM_TYPE_ENDTAG', 4); | |
define('HDOM_TYPE_ROOT', 5); | |
define('HDOM_TYPE_UNKNOWN', 6); | |
define('HDOM_QUOTE_DOUBLE', 0); | |
define('HDOM_QUOTE_SINGLE', 1); | |
define('HDOM_QUOTE_NO', 3); | |
define('HDOM_INFO_BEGIN', 0); | |
define('HDOM_INFO_END', 1); | |
define('HDOM_INFO_QUOTE', 2); | |
define('HDOM_INFO_SPACE', 3); | |
define('HDOM_INFO_TEXT', 4); | |
define('HDOM_INFO_INNER', 5); | |
define('HDOM_INFO_OUTER', 6); | |
define('HDOM_INFO_ENDSPACE',7); | |
// helper functions | |
// ----------------------------------------------------------------------------- | |
// get html dom form file | |
function file_get_html() { | |
$dom = new simple_html_dom; | |
$args = func_get_args(); | |
$dom->load(call_user_func_array('file_get_contents', $args), true); | |
return $dom; | |
} | |
// get html dom form string | |
function str_get_html($str, $lowercase=true) { | |
$dom = new simple_html_dom; | |
$dom->load($str, $lowercase); | |
return $dom; | |
} | |
// dump html dom tree | |
function dump_html_tree($node, $show_attr=true, $deep=0) { | |
$lead = str_repeat(' ', $deep); | |
echo $lead.$node->tag; | |
if ($show_attr && count($node->attr)>0) { | |
echo '('; | |
foreach($node->attr as $k=>$v) | |
echo "[$k]=>\"".$node->$k.'", '; | |
echo ')'; | |
} | |
echo "\n"; | |
foreach($node->nodes as $c) | |
dump_html_tree($c, $show_attr, $deep+1); | |
} | |
// get dom form file (deprecated) | |
function file_get_dom() { | |
$dom = new simple_html_dom; | |
$args = func_get_args(); | |
$dom->load(call_user_func_array('file_get_contents', $args), true); | |
return $dom; | |
} | |
// get dom form string (deprecated) | |
function str_get_dom($str, $lowercase=true) { | |
$dom = new simple_html_dom; | |
$dom->load($str, $lowercase); | |
return $dom; | |
} | |
// simple html dom node | |
// ----------------------------------------------------------------------------- | |
class simple_html_dom_node { | |
public $nodetype = HDOM_TYPE_TEXT; | |
public $tag = 'text'; | |
public $attr = array(); | |
public $children = array(); | |
public $nodes = array(); | |
public $parent = null; | |
public $_ = array(); | |
private $dom = null; | |
function __construct($dom) { | |
$this->dom = $dom; | |
$dom->nodes[] = $this; | |
} | |
function __destruct() { | |
$this->clear(); | |
} | |
function __toString() { | |
return $this->outertext(); | |
} | |
// clean up memory due to php5 circular references memory leak... | |
function clear() { | |
$this->dom = null; | |
$this->nodes = null; | |
$this->parent = null; | |
$this->children = null; | |
} | |
// dump node's tree | |
function dump($show_attr=true) { | |
dump_html_tree($this, $show_attr); | |
} | |
// returns the parent of node | |
function parent() { | |
return $this->parent; | |
} | |
// returns children of node | |
function children($idx=-1) { | |
if ($idx===-1) return $this->children; | |
if (isset($this->children[$idx])) return $this->children[$idx]; | |
return null; | |
} | |
// returns the first child of node | |
function first_child() { | |
if (count($this->children)>0) return $this->children[0]; | |
return null; | |
} | |
// returns the last child of node | |
function last_child() { | |
if (($count=count($this->children))>0) return $this->children[$count-1]; | |
return null; | |
} | |
// returns the next sibling of node | |
function next_sibling() { | |
if ($this->parent===null) return null; | |
$idx = 0; | |
$count = count($this->parent->children); | |
while ($idx<$count && $this!==$this->parent->children[$idx]) | |
++$idx; | |
if (++$idx>=$count) return null; | |
return $this->parent->children[$idx]; | |
} | |
// returns the previous sibling of node | |
function prev_sibling() { | |
if ($this->parent===null) return null; | |
$idx = 0; | |
$count = count($this->parent->children); | |
while ($idx<$count && $this!==$this->parent->children[$idx]) | |
++$idx; | |
if (--$idx<0) return null; | |
return $this->parent->children[$idx]; | |
} | |
// get dom node's inner html | |
function innertext() { | |
if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; | |
if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); | |
$ret = ''; | |
foreach($this->nodes as $n) | |
$ret .= $n->outertext(); | |
return $ret; | |
} | |
// get dom node's outer text (with tag) | |
function outertext() { | |
if ($this->tag==='root') return $this->innertext(); | |
// trigger callback | |
if ($this->dom->callback!==null) | |
call_user_func_array($this->dom->callback, array($this)); | |
if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; | |
if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); | |
// render begin tag | |
$ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); | |
// render inner text | |
if (isset($this->_[HDOM_INFO_INNER])) | |
$ret .= $this->_[HDOM_INFO_INNER]; | |
else { | |
foreach($this->nodes as $n) | |
$ret .= $n->outertext(); | |
} | |
// render end tag | |
if(isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0) | |
$ret .= '</'.$this->tag.'>'; | |
return $ret; | |
} | |
// get dom node's plain text | |
function text() { | |
if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; | |
switch ($this->nodetype) { | |
case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); | |
case HDOM_TYPE_COMMENT: return ''; | |
case HDOM_TYPE_UNKNOWN: return ''; | |
} | |
if (strcasecmp($this->tag, 'script')===0) return ''; | |
if (strcasecmp($this->tag, 'style')===0) return ''; | |
$ret = ''; | |
foreach($this->nodes as $n) | |
$ret .= $n->text(); | |
return $ret; | |
} | |
function xmltext() { | |
$ret = $this->innertext(); | |
$ret = str_ireplace('<![CDATA[', '', $ret); | |
$ret = str_replace(']]>', '', $ret); | |
return $ret; | |
} | |
// build node's text with tag | |
function makeup() { | |
// text, comment, unknown | |
if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); | |
$ret = '<'.$this->tag; | |
$i = -1; | |
foreach($this->attr as $key=>$val) { | |
++$i; | |
// skip removed attribute | |
if ($val===null || $val===false) | |
continue; | |
$ret .= $this->_[HDOM_INFO_SPACE][$i][0]; | |
//no value attr: nowrap, checked selected... | |
if ($val===true) | |
$ret .= $key; | |
else { | |
switch($this->_[HDOM_INFO_QUOTE][$i]) { | |
case HDOM_QUOTE_DOUBLE: $quote = '"'; break; | |
case HDOM_QUOTE_SINGLE: $quote = '\''; break; | |
default: $quote = ''; | |
} | |
$ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; | |
} | |
} | |
$ret = $this->dom->restore_noise($ret); | |
return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; | |
} | |
// find elements by css selector | |
function find($selector, $idx=null) { | |
$selectors = $this->parse_selector($selector); | |
if (($count=count($selectors))===0) return array(); | |
$found_keys = array(); | |
// find each selector | |
for ($c=0; $c<$count; ++$c) { | |
if (($levle=count($selectors[0]))===0) return array(); | |
if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); | |
$head = array($this->_[HDOM_INFO_BEGIN]=>1); | |
// handle descendant selectors, no recursive! | |
for ($l=0; $l<$levle; ++$l) { | |
$ret = array(); | |
foreach($head as $k=>$v) { | |
$n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; | |
$n->seek($selectors[$c][$l], $ret); | |
} | |
$head = $ret; | |
} | |
foreach($head as $k=>$v) { | |
if (!isset($found_keys[$k])) | |
$found_keys[$k] = 1; | |
} | |
} | |
// sort keys | |
ksort($found_keys); | |
$found = array(); | |
foreach($found_keys as $k=>$v) | |
$found[] = $this->dom->nodes[$k]; | |
// return nth-element or array | |
if (is_null($idx)) return $found; | |
else if ($idx<0) $idx = count($found) + $idx; | |
return (isset($found[$idx])) ? $found[$idx] : null; | |
} | |
// seek for given conditions | |
protected function seek($selector, &$ret) { | |
list($tag, $key, $val, $exp, $no_key) = $selector; | |
// xpath index | |
if ($tag && $key && is_numeric($key)) { | |
$count = 0; | |
foreach ($this->children as $c) { | |
if ($tag==='*' || $tag===$c->tag) { | |
if (++$count==$key) { | |
$ret[$c->_[HDOM_INFO_BEGIN]] = 1; | |
return; | |
} | |
} | |
} | |
return; | |
} | |
$end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; | |
if ($end==0) { | |
$parent = $this->parent; | |
while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) { | |
$end -= 1; | |
$parent = $parent->parent; | |
} | |
$end += $parent->_[HDOM_INFO_END]; | |
} | |
for($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { | |
$node = $this->dom->nodes[$i]; | |
$pass = true; | |
if ($tag==='*' && !$key) { | |
if (in_array($node, $this->children, true)) | |
$ret[$i] = 1; | |
continue; | |
} | |
// compare tag | |
if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} | |
// compare key | |
if ($pass && $key) { | |
if ($no_key) { | |
if (isset($node->attr[$key])) $pass=false; | |
} | |
else if (!isset($node->attr[$key])) $pass=false; | |
} | |
// compare value | |
if ($pass && $key && $val && $val!=='*') { | |
$check = $this->match($exp, $val, $node->attr[$key]); | |
// handle multiple class | |
if (!$check && strcasecmp($key, 'class')===0) { | |
foreach(explode(' ',$node->attr[$key]) as $k) { | |
$check = $this->match($exp, $val, $k); | |
if ($check) break; | |
} | |
} | |
if (!$check) $pass = false; | |
} | |
if ($pass) $ret[$i] = 1; | |
unset($node); | |
} | |
} | |
protected function match($exp, $pattern, $value) { | |
switch ($exp) { | |
case '=': | |
return ($value===$pattern); | |
case '!=': | |
return ($value!==$pattern); | |
case '^=': | |
return preg_match("/^".preg_quote($pattern,'/')."/", $value); | |
case '$=': | |
return preg_match("/".preg_quote($pattern,'/')."$/", $value); | |
case '*=': | |
if ($pattern[0]=='/') | |
return preg_match($pattern, $value); | |
return preg_match("/".$pattern."/i", $value); | |
} | |
return false; | |
} | |
protected function parse_selector($selector_string) { | |
// pattern of CSS selectors, modified from mootools | |
$pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; | |
preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER); | |
$selectors = array(); | |
$result = array(); | |
//print_r($matches); | |
foreach ($matches as $m) { | |
$m[0] = trim($m[0]); | |
if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue; | |
// for borwser grnreated xpath | |
if ($m[1]==='tbody') continue; | |
list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); | |
if(!empty($m[2])) {$key='id'; $val=$m[2];} | |
if(!empty($m[3])) {$key='class'; $val=$m[3];} | |
if(!empty($m[4])) {$key=$m[4];} | |
if(!empty($m[5])) {$exp=$m[5];} | |
if(!empty($m[6])) {$val=$m[6];} | |
// convert to lowercase | |
if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);} | |
//elements that do NOT have the specified attribute | |
if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;} | |
$result[] = array($tag, $key, $val, $exp, $no_key); | |
if (trim($m[7])===',') { | |
$selectors[] = $result; | |
$result = array(); | |
} | |
} | |
if (count($result)>0) | |
$selectors[] = $result; | |
return $selectors; | |
} | |
function __get($name) { | |
if (isset($this->attr[$name])) return $this->attr[$name]; | |
switch($name) { | |
case 'outertext': return $this->outertext(); | |
case 'innertext': return $this->innertext(); | |
case 'plaintext': return $this->text(); | |
case 'xmltext': return $this->xmltext(); | |
default: return array_key_exists($name, $this->attr); | |
} | |
} | |
function __set($name, $value) { | |
switch($name) { | |
case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; | |
case 'innertext': | |
if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; | |
return $this->_[HDOM_INFO_INNER] = $value; | |
} | |
if (!isset($this->attr[$name])) { | |
$this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); | |
$this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; | |
} | |
$this->attr[$name] = $value; | |
} | |
function __isset($name) { | |
switch($name) { | |
case 'outertext': return true; | |
case 'innertext': return true; | |
case 'plaintext': return true; | |
} | |
//no value attr: nowrap, checked selected... | |
return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); | |
} | |
function __unset($name) { | |
if (isset($this->attr[$name])) | |
unset($this->attr[$name]); | |
} | |
// camel naming conventions | |
function getAllAttributes() {return $this->attr;} | |
function getAttribute($name) {return $this->__get($name);} | |
function setAttribute($name, $value) {$this->__set($name, $value);} | |
function hasAttribute($name) {return $this->__isset($name);} | |
function removeAttribute($name) {$this->__set($name, null);} | |
function getElementById($id) {return $this->find("#$id", 0);} | |
function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} | |
function getElementByTagName($name) {return $this->find($name, 0);} | |
function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} | |
function parentNode() {return $this->parent();} | |
function childNodes($idx=-1) {return $this->children($idx);} | |
function firstChild() {return $this->first_child();} | |
function lastChild() {return $this->last_child();} | |
function nextSibling() {return $this->next_sibling();} | |
function previousSibling() {return $this->prev_sibling();} | |
} | |
// simple html dom parser | |
// ----------------------------------------------------------------------------- | |
class simple_html_dom { | |
public $root = null; | |
public $nodes = array(); | |
public $callback = null; | |
public $lowercase = false; | |
protected $pos; | |
protected $doc; | |
protected $char; | |
protected $size; | |
protected $cursor; | |
protected $parent; | |
protected $noise = array(); | |
protected $token_blank = " \t\r\n"; | |
protected $token_equal = ' =/>'; | |
protected $token_slash = " />\r\n\t"; | |
protected $token_attr = ' >'; | |
// use isset instead of in_array, performance boost about 30%... | |
protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1); | |
protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1); | |
protected $optional_closing_tags = array( | |
'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1), | |
'th'=>array('th'=>1), | |
'td'=>array('td'=>1), | |
'li'=>array('li'=>1), | |
'dt'=>array('dt'=>1, 'dd'=>1), | |
'dd'=>array('dd'=>1, 'dt'=>1), | |
'dl'=>array('dd'=>1, 'dt'=>1), | |
'p'=>array('p'=>1), | |
'nobr'=>array('nobr'=>1), | |
); | |
function __construct($str=null) { | |
if ($str) { | |
if (preg_match("/^http:\/\//i",$str) || is_file($str)) | |
$this->load_file($str); | |
else | |
$this->load($str); | |
} | |
} | |
function __destruct() { | |
$this->clear(); | |
} | |
// load html from string | |
function load($str, $lowercase=true) { | |
// prepare | |
$this->prepare($str, $lowercase); | |
// strip out comments | |
$this->remove_noise("'<!--(.*?)-->'is"); | |
// strip out cdata | |
$this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true); | |
// strip out <style> tags | |
$this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is"); | |
$this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is"); | |
// strip out <script> tags | |
$this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is"); | |
$this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is"); | |
// strip out preformatted tags | |
$this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is"); | |
// strip out server side scripts | |
$this->remove_noise("'(<\?)(.*?)(\?>)'s", true); | |
// strip smarty scripts | |
$this->remove_noise("'(\{\w)(.*?)(\})'s", true); | |
// parsing | |
while ($this->parse()); | |
// end | |
$this->root->_[HDOM_INFO_END] = $this->cursor; | |
} | |
// load html from file | |
function load_file() { | |
$args = func_get_args(); | |
$this->load(call_user_func_array('file_get_contents', $args), true); | |
} | |
// set callback function | |
function set_callback($function_name) { | |
$this->callback = $function_name; | |
} | |
// remove callback function | |
function remove_callback() { | |
$this->callback = null; | |
} | |
// save dom as string | |
function save($filepath='') { | |
$ret = $this->root->innertext(); | |
if ($filepath!=='') file_put_contents($filepath, $ret); | |
return $ret; | |
} | |
// find dom node by css selector | |
function find($selector, $idx=null) { | |
return $this->root->find($selector, $idx); | |
} | |
// clean up memory due to php5 circular references memory leak... | |
function clear() { | |
foreach($this->nodes as $n) {$n->clear(); $n = null;} | |
if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);} | |
if (isset($this->root)) {$this->root->clear(); unset($this->root);} | |
unset($this->doc); | |
unset($this->noise); | |
} | |
function dump($show_attr=true) { | |
$this->root->dump($show_attr); | |
} | |
// prepare HTML data and init everything | |
protected function prepare($str, $lowercase=true) { | |
$this->clear(); | |
$this->doc = $str; | |
$this->pos = 0; | |
$this->cursor = 1; | |
$this->noise = array(); | |
$this->nodes = array(); | |
$this->lowercase = $lowercase; | |
$this->root = new simple_html_dom_node($this); | |
$this->root->tag = 'root'; | |
$this->root->_[HDOM_INFO_BEGIN] = -1; | |
$this->root->nodetype = HDOM_TYPE_ROOT; | |
$this->parent = $this->root; | |
// set the length of content | |
$this->size = strlen($str); | |
if ($this->size>0) $this->char = $this->doc[0]; | |
} | |
// parse html content | |
protected function parse() { | |
if (($s = $this->copy_until_char('<'))==='') | |
return $this->read_tag(); | |
// text | |
$node = new simple_html_dom_node($this); | |
++$this->cursor; | |
$node->_[HDOM_INFO_TEXT] = $s; | |
$this->link_nodes($node, false); | |
return true; | |
} | |
// read tag info | |
protected function read_tag() { | |
if ($this->char!=='<') { | |
$this->root->_[HDOM_INFO_END] = $this->cursor; | |
return false; | |
} | |
$begin_tag_pos = $this->pos; | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
// end tag | |
if ($this->char==='/') { | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
$this->skip($this->token_blank_t); | |
$tag = $this->copy_until_char('>'); | |
// skip attributes in end tag | |
if (($pos = strpos($tag, ' '))!==false) | |
$tag = substr($tag, 0, $pos); | |
$parent_lower = strtolower($this->parent->tag); | |
$tag_lower = strtolower($tag); | |
if ($parent_lower!==$tag_lower) { | |
if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) { | |
$this->parent->_[HDOM_INFO_END] = 0; | |
$org_parent = $this->parent; | |
while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) | |
$this->parent = $this->parent->parent; | |
if (strtolower($this->parent->tag)!==$tag_lower) { | |
$this->parent = $org_parent; // restore origonal parent | |
if ($this->parent->parent) $this->parent = $this->parent->parent; | |
$this->parent->_[HDOM_INFO_END] = $this->cursor; | |
return $this->as_text_node($tag); | |
} | |
} | |
else if (($this->parent->parent) && isset($this->block_tags[$tag_lower])) { | |
$this->parent->_[HDOM_INFO_END] = 0; | |
$org_parent = $this->parent; | |
while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) | |
$this->parent = $this->parent->parent; | |
if (strtolower($this->parent->tag)!==$tag_lower) { | |
$this->parent = $org_parent; // restore origonal parent | |
$this->parent->_[HDOM_INFO_END] = $this->cursor; | |
return $this->as_text_node($tag); | |
} | |
} | |
else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower) { | |
$this->parent->_[HDOM_INFO_END] = 0; | |
$this->parent = $this->parent->parent; | |
} | |
else | |
return $this->as_text_node($tag); | |
} | |
$this->parent->_[HDOM_INFO_END] = $this->cursor; | |
if ($this->parent->parent) $this->parent = $this->parent->parent; | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
return true; | |
} | |
$node = new simple_html_dom_node($this); | |
$node->_[HDOM_INFO_BEGIN] = $this->cursor; | |
++$this->cursor; | |
$tag = $this->copy_until($this->token_slash); | |
// doctype, cdata & comments... | |
if (isset($tag[0]) && $tag[0]==='!') { | |
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>'); | |
if (isset($tag[2]) && $tag[1]==='-' && $tag[2]==='-') { | |
$node->nodetype = HDOM_TYPE_COMMENT; | |
$node->tag = 'comment'; | |
} else { | |
$node->nodetype = HDOM_TYPE_UNKNOWN; | |
$node->tag = 'unknown'; | |
} | |
if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; | |
$this->link_nodes($node, true); | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
return true; | |
} | |
// text | |
if ($pos=strpos($tag, '<')!==false) { | |
$tag = '<' . substr($tag, 0, -1); | |
$node->_[HDOM_INFO_TEXT] = $tag; | |
$this->link_nodes($node, false); | |
$this->char = $this->doc[--$this->pos]; // prev | |
return true; | |
} | |
if (!preg_match("/^[\w-:]+$/", $tag)) { | |
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>'); | |
if ($this->char==='<') { | |
$this->link_nodes($node, false); | |
return true; | |
} | |
if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; | |
$this->link_nodes($node, false); | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
return true; | |
} | |
// begin tag | |
$node->nodetype = HDOM_TYPE_ELEMENT; | |
$tag_lower = strtolower($tag); | |
$node->tag = ($this->lowercase) ? $tag_lower : $tag; | |
// handle optional closing tags | |
if (isset($this->optional_closing_tags[$tag_lower]) ) { | |
while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) { | |
$this->parent->_[HDOM_INFO_END] = 0; | |
$this->parent = $this->parent->parent; | |
} | |
$node->parent = $this->parent; | |
} | |
$guard = 0; // prevent infinity loop | |
$space = array($this->copy_skip($this->token_blank), '', ''); | |
// attributes | |
do { | |
if ($this->char!==null && $space[0]==='') break; | |
$name = $this->copy_until($this->token_equal); | |
if($guard===$this->pos) { | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
continue; | |
} | |
$guard = $this->pos; | |
// handle endless '<' | |
if($this->pos>=$this->size-1 && $this->char!=='>') { | |
$node->nodetype = HDOM_TYPE_TEXT; | |
$node->_[HDOM_INFO_END] = 0; | |
$node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name; | |
$node->tag = 'text'; | |
$this->link_nodes($node, false); | |
return true; | |
} | |
// handle mismatch '<' | |
if($this->doc[$this->pos-1]=='<') { | |
$node->nodetype = HDOM_TYPE_TEXT; | |
$node->tag = 'text'; | |
$node->attr = array(); | |
$node->_[HDOM_INFO_END] = 0; | |
$node->_[HDOM_INFO_TEXT] = substr($this->doc, $begin_tag_pos, $this->pos-$begin_tag_pos-1); | |
$this->pos -= 2; | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
$this->link_nodes($node, false); | |
return true; | |
} | |
if ($name!=='/' && $name!=='') { | |
$space[1] = $this->copy_skip($this->token_blank); | |
$name = $this->restore_noise($name); | |
if ($this->lowercase) $name = strtolower($name); | |
if ($this->char==='=') { | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
$this->parse_attr($node, $name, $space); | |
} | |
else { | |
//no value attr: nowrap, checked selected... | |
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; | |
$node->attr[$name] = true; | |
if ($this->char!='>') $this->char = $this->doc[--$this->pos]; // prev | |
} | |
$node->_[HDOM_INFO_SPACE][] = $space; | |
$space = array($this->copy_skip($this->token_blank), '', ''); | |
} | |
else | |
break; | |
} while($this->char!=='>' && $this->char!=='/'); | |
$this->link_nodes($node, true); | |
$node->_[HDOM_INFO_ENDSPACE] = $space[0]; | |
// check self closing | |
if ($this->copy_until_char_escape('>')==='/') { | |
$node->_[HDOM_INFO_ENDSPACE] .= '/'; | |
$node->_[HDOM_INFO_END] = 0; | |
} | |
else { | |
// reset parent | |
if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node; | |
} | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
return true; | |
} | |
// parse attributes | |
protected function parse_attr($node, $name, &$space) { | |
$space[2] = $this->copy_skip($this->token_blank); | |
switch($this->char) { | |
case '"': | |
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
$node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"')); | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
break; | |
case '\'': | |
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE; | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
$node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\'')); | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
break; | |
default: | |
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; | |
$node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr)); | |
} | |
} | |
// link node's parent | |
protected function link_nodes(&$node, $is_child) { | |
$node->parent = $this->parent; | |
$this->parent->nodes[] = $node; | |
if ($is_child) | |
$this->parent->children[] = $node; | |
} | |
// as a text node | |
protected function as_text_node($tag) { | |
$node = new simple_html_dom_node($this); | |
++$this->cursor; | |
$node->_[HDOM_INFO_TEXT] = '</' . $tag . '>'; | |
$this->link_nodes($node, false); | |
$this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
return true; | |
} | |
protected function skip($chars) { | |
$this->pos += strspn($this->doc, $chars, $this->pos); | |
$this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
} | |
protected function copy_skip($chars) { | |
$pos = $this->pos; | |
$len = strspn($this->doc, $chars, $pos); | |
$this->pos += $len; | |
$this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
if ($len===0) return ''; | |
return substr($this->doc, $pos, $len); | |
} | |
protected function copy_until($chars) { | |
$pos = $this->pos; | |
$len = strcspn($this->doc, $chars, $pos); | |
$this->pos += $len; | |
$this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next | |
return substr($this->doc, $pos, $len); | |
} | |
protected function copy_until_char($char) { | |
if ($this->char===null) return ''; | |
if (($pos = strpos($this->doc, $char, $this->pos))===false) { | |
$ret = substr($this->doc, $this->pos, $this->size-$this->pos); | |
$this->char = null; | |
$this->pos = $this->size; | |
return $ret; | |
} | |
if ($pos===$this->pos) return ''; | |
$pos_old = $this->pos; | |
$this->char = $this->doc[$pos]; | |
$this->pos = $pos; | |
return substr($this->doc, $pos_old, $pos-$pos_old); | |
} | |
protected function copy_until_char_escape($char) { | |
if ($this->char===null) return ''; | |
$start = $this->pos; | |
while(1) { | |
if (($pos = strpos($this->doc, $char, $start))===false) { | |
$ret = substr($this->doc, $this->pos, $this->size-$this->pos); | |
$this->char = null; | |
$this->pos = $this->size; | |
return $ret; | |
} | |
if ($pos===$this->pos) return ''; | |
if ($this->doc[$pos-1]==='\\') { | |
$start = $pos+1; | |
continue; | |
} | |
$pos_old = $this->pos; | |
$this->char = $this->doc[$pos]; | |
$this->pos = $pos; | |
return substr($this->doc, $pos_old, $pos-$pos_old); | |
} | |
} | |
// remove noise from html content | |
protected function remove_noise($pattern, $remove_tag=false) { | |
$count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); | |
for ($i=$count-1; $i>-1; --$i) { | |
$key = '___noise___'.sprintf('% 3d', count($this->noise)+100); | |
$idx = ($remove_tag) ? 0 : 1; | |
$this->noise[$key] = $matches[$i][$idx][0]; | |
$this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0])); | |
} | |
// reset the length of content | |
$this->size = strlen($this->doc); | |
if ($this->size>0) $this->char = $this->doc[0]; | |
} | |
// restore noise to html content | |
function restore_noise($text) { | |
while(($pos=strpos($text, '___noise___'))!==false) { | |
$key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13]; | |
if (isset($this->noise[$key])) | |
$text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+14); | |
} | |
return $text; | |
} | |
function __toString() { | |
return $this->root->innertext(); | |
} | |
function __get($name) { | |
switch($name) { | |
case 'outertext': return $this->root->innertext(); | |
case 'innertext': return $this->root->innertext(); | |
case 'plaintext': return $this->root->text(); | |
} | |
} | |
// camel naming conventions | |
function childNodes($idx=-1) {return $this->root->childNodes($idx);} | |
function firstChild() {return $this->root->first_child();} | |
function lastChild() {return $this->root->last_child();} | |
function getElementById($id) {return $this->find("#$id", 0);} | |
function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} | |
function getElementByTagName($name) {return $this->find($name, 0);} | |
function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);} | |
function loadFile() {$args = func_get_args();$this->load(call_user_func_array('file_get_contents', $args), true);} | |
} | |
?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
$stopid = filter_var($_REQUEST['stopid'],FILTER_SANITIZE_NUMBER_INT); | $stopid = filter_var($_REQUEST['stopid'], FILTER_SANITIZE_NUMBER_INT); |
$url = $APIurl."/json/stop?stop_id=".$stopid; | $url = $APIurl . "/json/stop?stop_id=" . $stopid; |
$stop = json_decode(getPage($url)); | $stop = json_decode(getPage($url)); |
$html.= '<table><tr><td><br><br> '; | |
$html .= '<div data-role="content" class="ui-content" role="main"><p>'.staticmap(Array(0 => Array($stop[2],$stop[3])), 0,"iconb", false).'</p>'; | $url = $APIurl . "/json/stoproutes?stop=" . $stopid . "&time=" . midnight_seconds() . "&service_period=" . service_period(); |
$html .= ' <ul data-role="listview" data-inset="true">'; | $routes = json_decode(getPage($url)); |
$url = $APIurl."/json/stoptrips?stop=".$stopid."&time=".midnight_seconds()."&service_period=".service_period(); | foreach ($routes as $route) { |
$html.= '<br> <a href="trip.php?routeid=' . $route[0] . '&stopid=' . $stopid . '">' . $route[1] . ' - ' . $route[2] . '</a>'; | |
$viaPoints = viaPointNames($route[3], $stopid); | |
if ($viaPoints != "") $html.= '<br><small>Via: ' . $viaPoints . '</small>'; | |
$html.= "<br>"; | |
} | |
$html.= '</td><td>' . staticmap(Array( | |
0 => Array( | |
$stop[2], | |
$stop[3] | |
) | |
) , 0, "iconb", false) . "</td></tr>"; | |
$url = $APIurl . "/json/stoptrips?stop=" . $stopid . "&time=" . midnight_seconds() . "&service_period=" . service_period(); | |
$trips = json_decode(getPage($url)); | $trips = json_decode(getPage($url)); |
debug(print_r($trips,true)); | $html.= "</table><br><br><table>"; |
foreach ($trips as $row) | $html.= "<thead><tr><th>Route</th><th>Time</th></tr></thead>"; |
debug(print_r($trips, true)); | |
foreach ($trips as $row) { | |
$html.= '<tr><td><a href="trip.php?stopid=' . $stopid . '&tripid=' . $row[1][0] . '">' . $row[1][1] . "</a></td>"; | |
$html.= '<td>' . midnight_seconds_to_time($row[0]) . '</td>'; | |
$html.= '</tr>'; | |
} | |
$html.= '</table>'; | |
if (sizeof($trips) == 0) $html.= "<center>No trips in the near future.</center>"; | |
require_once ('tcpdf/config/lang/eng.php'); | |
require_once ('tcpdf/tcpdf.php'); | |
// create new PDF document | |
class Custom_TCPDF extends TCPDF | |
{ | { |
$html .= '<li>'; | var $QRCodeURL; |
$html .= '<h3><a href="trip.php?stopid='.$stopid.'&tripid='.$row[1][0].'">'.$row[1][1]; | function set_QRCodeURL($url) |
if (isFastDevice()) { | { |
$viaPoints = viaPointNames($row[1][0],$stopid); | $this->QRCodeURL = $url; |
if ($viaPoints != "") $html .= '<br><small>Via: '.$viaPoints.'</small> </a></h3>'; | } |
} | /** |
$html .= '<p class="ui-li-aside"><strong>'.midnight_seconds_to_time($row[0]).'</strong></p>'; | * This method is used to render the page header. |
$html .= '</li>'; | * It is automatically called by AddPage() and could be overwritten in your own inherited class. |
} | * @public |
if (sizeof($trips) == 0) $html .= "<li> <center>No trips in the near future.</center> </li>"; | */ |
$html .= '</ul></div>'; | public function Header() |
require_once('tcpdf/config/lang/eng.php'); | { |
require_once('tcpdf/tcpdf.php'); | if ($this->header_xobjid < 0) { |
// start a new XObject Template | |
// create new PDF document | $this->header_xobjid = $this->startTemplate($this->w, $this->tMargin + 10); |
class Custom_TCPDF extends TCPDF { | $headerfont = $this->getHeaderFont(); |
var $QRCodeURL; | $headerdata = $this->getHeaderData(); |
$this->y = $this->header_margin; | |
function set_QRCodeURL ($url) { | if ($this->rtl) { |
$this->QRCodeURL = $url; | $this->x = $this->w - $this->original_rMargin; |
} | } |
else { | |
/** | $this->x = $this->original_lMargin - 10; |
* This method is used to render the page header. | } |
* It is automatically called by AddPage() and could be overwritten in your own inherited class. | |
* @public | |
*/ | |
public function Header() { | |
if ($this->header_xobjid < 0) { | |
// start a new XObject Template | |
$this->header_xobjid = $this->startTemplate($this->w, $this->tMargin+10); | |
$headerfont = $this->getHeaderFont(); | |
$headerdata = $this->getHeaderData(); | |
$this->y = $this->header_margin; | |
if ($this->rtl) { | |
$this->x = $this->w - $this->original_rMargin; | |
} else { | |
$this->x = $this->original_lMargin-10; | |
} | |
if (isset($this->QRCodeURL)) { | if (isset($this->QRCodeURL)) { |
// QRCODE,H : QR-CODE Best error correction | // QRCODE,H : QR-CODE Best error correction |
$style = array( | $style = array( |
'border' => 1, | 'border' => 1, |
'padding' => 0, | 'padding' => 0, |
'fgcolor' => array(0,0,0), | 'fgcolor' => array( |
'bgcolor' => false, //array(255,255,255) | 0, |
'module_width' => 1, // width of a single module in points | 0, |
'module_height' => 1 // height of a single module in points | 0 |
); | ) , |
$this->write2DBarcode($this->QRCodeURL, 'QRCODE,H', '', '', 25, 25, $style, 'T'); | 'bgcolor' => false, //array(255,255,255) |
$imgy = 50+20; | 'module_width' => 1, // width of a single module in points |
} elseif (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) { | 'module_height' => 1 |
$imgtype = $this->getImageFileType(K_PATH_IMAGES.$headerdata['logo']); | // height of a single module in points |
if (($imgtype == 'eps') OR ($imgtype == 'ai')) { | |
$this->ImageEps(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); | ); |
} elseif ($imgtype == 'svg') { | $this->write2DBarcode($this->QRCodeURL, 'QRCODE,H', '', '', 25, 25, $style, 'T'); |
$this->ImageSVG(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); | $imgy = 50 + 20; |
} else { | } |
$this->Image(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); | elseif (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) { |
} | $imgtype = $this->getImageFileType(K_PATH_IMAGES . $headerdata['logo']); |
$imgy = $this->getImageRBY(); | if (($imgtype == 'eps') OR ($imgtype == 'ai')) { |
} else { | $this->ImageEps(K_PATH_IMAGES . $headerdata['logo'], '', '', $headerdata['logo_width']); |
$imgy = $this->y; | } |
} | elseif ($imgtype == 'svg') { |
$cell_height = round(($this->cell_height_ratio * $headerfont[2]) / $this->k, 2); | $this->ImageSVG(K_PATH_IMAGES . $headerdata['logo'], '', '', $headerdata['logo_width']); |
// set starting margin for text data cell | } |
if ($this->getRTL()) { | else { |
$header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1); | $this->Image(K_PATH_IMAGES . $headerdata['logo'], '', '', $headerdata['logo_width']); |
} else { | } |
$header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1); | $imgy = $this->getImageRBY(); |
} | } |
$cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1); | else { |
$this->SetTextColor(0, 0, 0); | $imgy = $this->y; |
// header title | } |
$this->SetFont($headerfont[0], 'B', $headerfont[2] + 1); | $cell_height = round(($this->cell_height_ratio * $headerfont[2]) / $this->k, 2); |
$this->SetX($header_x); | // set starting margin for text data cell |
$this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0); | if ($this->getRTL()) { |
// header string | $header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1); |
$this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]); | } |
$this->SetX($header_x); | else { |
$this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false); | $header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1); |
// print an ending header line | } |
//$this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); | $cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1); |
//$this->SetY((2.835 / $this->k) + max($imgy, $this->y)); | $this->SetTextColor(0, 0, 0); |
if ($this->rtl) { | // header title |
$this->SetX($this->original_rMargin); | $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1); |
} else { | $this->SetX($header_x); |
$this->SetX($this->original_lMargin); | $this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0); |
} | // header string |
//$this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C'); | $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]); |
$this->endTemplate(); | $this->SetX($header_x); |
} | $this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false); |
// print header template | // print an ending header line |
$x = 0; | //$this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); |
$dx = 0; | //$this->SetY((2.835 / $this->k) + max($imgy, $this->y)); |
if ($this->booklet AND (($this->page % 2) == 0)) { | if ($this->rtl) { |
// adjust margins for booklet mode | $this->SetX($this->original_rMargin); |
$dx = ($this->original_lMargin - $this->original_rMargin); | } |
} | else { |
if ($this->rtl) { | $this->SetX($this->original_lMargin); |
$x = $this->w + $dx; | } |
} else { | //$this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C'); |
$x = 0 + $dx; | $this->endTemplate(); |
} | } |
$this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); | // print header template |
} | $x = 0; |
$dx = 0; | |
if ($this->booklet AND (($this->page % 2) == 0)) { | |
// adjust margins for booklet mode | |
$dx = ($this->original_lMargin - $this->original_rMargin); | |
} | |
if ($this->rtl) { | |
$x = $this->w + $dx; | |
} | |
else { | |
$x = 0 + $dx; | |
} | |
$this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); | |
} | |
} | } |
$pdf = new Custom_TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); | $pdf = new Custom_TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); |
// set document information | // set document information |
$pdf->SetCreator(PDF_CREATOR); | $pdf->SetCreator(PDF_CREATOR); |
$pdf->SetAuthor('bus.lambdacomplex.org'); | $pdf->SetAuthor('bus.lambdacomplex.org'); |
$pdf->SetTitle($stop[1]); | $pdf->SetTitle($stop[1]); |
// set default header data | // set default header data |
$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $stop[1] . " Timetable", "Some description of customization like Weekdays, 9am-10am"); | $pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $stop[1] . " Timetable", "Some description of customization like Weekdays, 9am-10am"); |
$pdf->set_QRCodeURL(curPageURL()."stop.php?stopid=".$_REQUEST['stopid']); | $pdf->set_QRCodeURL(curPageURL() . "stop.php?stopid=" . $_REQUEST['stopid']); |
// set header and footer fonts | // set header and footer fonts |
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN)); | $pdf->setHeaderFont(Array( |
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA)); | PDF_FONT_NAME_MAIN, |
'', | |
PDF_FONT_SIZE_MAIN | |
)); | |
$pdf->setFooterFont(Array( | |
PDF_FONT_NAME_DATA, | |
'', | |
PDF_FONT_SIZE_DATA | |
)); | |
// set default monospaced font | // set default monospaced font |
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); | $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); |
//set margins | //set margins |
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); | $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); |
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER); | $pdf->SetHeaderMargin(PDF_MARGIN_HEADER); |
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER); | $pdf->SetFooterMargin(PDF_MARGIN_FOOTER); |
//set auto page breaks | //set auto page breaks |
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM); | $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM); |
//set image scale factor | //set image scale factor |
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); | $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); |
//set some language-dependent strings | //set some language-dependent strings |
$pdf->setLanguageArray($l); | $pdf->setLanguageArray($l); |
// --------------------------------------------------------- | // --------------------------------------------------------- |
// set default font subsetting mode | // set default font subsetting mode |
$pdf->setFontSubsetting(true); | $pdf->setFontSubsetting(true); |
// Set font | // Set font |
// dejavusans is a UTF-8 Unicode font, if you only need to | // dejavusans is a UTF-8 Unicode font, if you only need to |
// print standard ASCII chars, you can use core fonts like | // print standard ASCII chars, you can use core fonts like |
// helvetica or times to reduce file size. | // helvetica or times to reduce file size. |
$pdf->SetFont('helvetica', '', 14, '', true); | $pdf->SetFont('helvetica', '', 14, '', true); |
// Add a page | // Add a page |
// This method has several options, check the source code documentation for more information. | // This method has several options, check the source code documentation for more information. |
$pdf->AddPage(); | $pdf->AddPage(); |
// Print text using writeHTMLCell() | // Print text using writeHTMLCell() |
$pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=true); | $pdf->writeHTMLCell($w = 0, $h = 0, $x = '', $y = '', $html, $border = 0, $ln = 1, $fill = 0, $reseth = true, $align = '', $autopadding = true); |
// --------------------------------------------------------- | // --------------------------------------------------------- |
// Close and output PDF document | // Close and output PDF document |
// This method has several options, check the source code documentation for more information. | // This method has several options, check the source code documentation for more information. |
$pdf->Output('example_001.pdf', 'I'); | $pdf->Output('example_001.pdf', 'I'); |
//============================================================+ | //============================================================+ |
// END OF FILE | // END OF FILE |
//============================================================+ | //============================================================+ |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
$stopid = filter_var($_REQUEST['stopid'],FILTER_SANITIZE_NUMBER_INT); | $stopid = filter_var($_REQUEST['stopid'], FILTER_SANITIZE_NUMBER_INT); |
$url = $APIurl."/json/stop?stop_id=".$stopid; | $stopcode = filter_var($_REQUEST['stopcode'], FILTER_SANITIZE_STRING); |
$url = $APIurl . "/json/stop?stop_id=" . $stopid; | |
$stop = json_decode(getPage($url)); | $stop = json_decode(getPage($url)); |
if ($stopcode != "" && $stop[5] != $stopcode) { | |
include_header($stop[1],"stop"); | $url = $APIurl . "/json/stopcodesearch?q=" . $stopcode; |
$stopsearch = json_decode(getPage($url)); | |
$stopid = $stopsearch[0][0]; | |
$url = $APIurl . "/json/stop?stop_id=" . $stopid; | |
$stop = json_decode(getPage($url)); | |
} | |
if (!startsWith($stop[5], "Wj") && strpos($stop[1], "Platform") === false) { | |
// expand out to all platforms | |
} | |
$stops = Array(); | |
$stopPositions = Array(); | |
$stopNames = Array(); | |
$tripStopNumbers = Array(); | |
$allStopsTrips = Array(); | |
$stopLinks = ""; | |
if (isset($_REQUEST['stopids'])) { | |
$stopids = explode(",", filter_var($_REQUEST['stopids'], FILTER_SANITIZE_STRING)); | |
foreach ($stopids as $sub_stopid) { | |
$url = $APIurl . "/json/stop?stop_id=" . $sub_stopid; | |
$stop = json_decode(getPage($url)); | |
$stops[] = $stop; | |
} | |
$stop = $stops[0]; | |
$stopid = $stops[0][0]; | |
$stopLinks.= "Individual stop pages: "; | |
foreach ($stops as $key => $sub_stop) { | |
$stopNames[$key] = $sub_stop[1] . ' Stop #' . ($key + 1); | |
$stopLinks.= '<a href="stop.php?stopid=' . $sub_stop[0] . '&stopcode=' . $sub_stop[5] . '">' . $stopNames[$key] . '</a> '; | |
$stopPositions[$key] = Array( | |
$sub_stop[2], | |
$sub_stop[3] | |
); | |
$url = $APIurl . "/json/stoptrips?stop=" . $sub_stop[0] . "&time=" . midnight_seconds() . "&service_period=" . service_period(); | |
$trips = json_decode(getPage($url)); | |
foreach ($trips as $trip) { | |
if (!isset($allStopsTrips[$trip[1][0]])) $allStopsTrips[$trip[1][0]] = $trip; | |
$tripStopNumbers[$trip[1][0]][] = $key; | |
} | |
} | |
} | |
include_header($stop[1], "stop"); | |
if (isMetricsOn()) { | if (isMetricsOn()) { |
// Create a new Instance of the tracker | // Create a new Instance of the tracker |
$owa = new owa_php(); | $owa = new owa_php(); |
// Set the ID of the site being tracked | // Set the ID of the site being tracked |
$owa->setSiteId($owaSiteID); | $owa->setSiteId($owaSiteID); |
// Create a new event object | // Create a new event object |
$event = $owa->makeEvent(); | $event = $owa->makeEvent(); |
// Set the Event Type, in this case a "video_play" | // Set the Event Type, in this case a "video_play" |
$event->setEventType('view_stop'); | $event->setEventType('view_stop'); |
// Set a property | // Set a property |
$event->set('stop_id',$stopid); | $event->set('stop_id', $stopid); |
// Track the event | // Track the event |
$owa->trackEvent($event); | $owa->trackEvent($event); |
} | } |
timePlaceSettings(); | timePlaceSettings(); |
echo '<div data-role="content" class="ui-content" role="main"><p>'.staticmap(Array(0 => Array($stop[2],$stop[3]))).'</p>'; | echo '<div data-role="content" class="ui-content" role="main">'; |
echo $stopLinks; | |
if (sizeof($stops) > 0) { | |
echo '<p>' . staticmap($stopPositions) . '</p>'; | |
} | |
else { | |
echo '<p>' . staticmap(Array( | |
0 => Array( | |
$stop[2], | |
$stop[3] | |
) | |
)) . '</p>'; | |
} | |
echo ' <ul data-role="listview" data-inset="true">'; | echo ' <ul data-role="listview" data-inset="true">'; |
$url = $APIurl."/json/stoptrips?stop=".$stopid."&time=".midnight_seconds()."&service_period=".service_period(); | if (sizeof($allStopsTrips) > 0) { |
$trips = json_decode(getPage($url)); | $trips = $allStopsTrips; |
debug(print_r($trips,true)); | |
foreach ($trips as $row) | |
{ | |
echo '<li>'; | |
echo '<h3><a href="trip.php?stopid='.$stopid.'&tripid='.$row[1][0].'">'.$row[1][1]; | |
if (isFastDevice()) { | |
$viaPoints = viaPointNames($row[1][0],$stopid); | |
if ($viaPoints != "") echo '<br><small>Via: '.$viaPoints.'</small> </a></h3>'; | |
} | } |
echo '<p class="ui-li-aside"><strong>'.midnight_seconds_to_time($row[0]).'</strong></p>'; | else { |
echo '</li>'; | $url = $APIurl . "/json/stoptrips?stop=" . $stopid . "&time=" . midnight_seconds() . "&service_period=" . service_period(); |
$trips = json_decode(getPage($url)); | |
} | |
foreach ($trips as $row) { | |
echo '<li>'; | |
echo '<h3><a href="trip.php?stopid=' . $stopid . '&tripid=' . $row[1][0] . '">' . $row[1][1]; | |
if (isFastDevice()) { | |
$viaPoints = viaPointNames($row[1][0], $stopid); | |
if ($viaPoints != "") echo '<br><small>Via: ' . $viaPoints . '</small>'; | |
} | |
if (sizeof($tripStopNumbers) > 0) { | |
echo '<br><small>Boarding At: '; | |
foreach ($tripStopNumbers[$row[1][0]] as $key) { | |
echo $stopNames[$key] .' '; | |
} | |
echo '</small>'; | |
} | |
echo '</a></h3>'; | |
echo '<p class="ui-li-aside"><strong>' . midnight_seconds_to_time($row[0]) . '</strong></p>'; | |
echo '</li>'; | |
} | } |
if (sizeof($trips) == 0) echo "<li> <center>No trips in the near future.</center> </li>"; | if (sizeof($trips) == 0) echo "<li> <center>No trips in the near future.</center> </li>"; |
echo '</ul></div>'; | echo '</ul></div>'; |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
function filterByFirstLetter($var) { | |
function navbar() { | return $var[1][0] == $_REQUEST['firstLetter']; |
echo' | } |
function navbar() | |
{ | |
echo ' | |
<div data-role="navbar"> | <div data-role="navbar"> |
<ul> | <ul> |
<li><a href="stopList.php">Timing Points</a></li> | <li><a href="stopList.php">Timing Points</a></li> |
<li><a href="stopList.php?suburbs=yes">By Suburb</a></li> | <li><a href="stopList.php?suburbs=yes">By Suburb</a></li> |
<li><a href="stopList.php?nearby=yes">Nearby Stops</a></li> | <li><a href="stopList.php?nearby=yes">Nearby Stops</a></li> |
<li><a href="stopList.php?allstops=yes">All Stops</a></li> | <li><a href="stopList.php?allstops=yes">All Stops</a></li> |
</ul> | </ul> |
</div> | </div> |
'; | '; |
} | } |
// By suburb | // By suburb |
if (isset($_REQUEST['suburbs'])) { | if (isset($_REQUEST['suburbs'])) { |
include_header("Stops by Suburb","stopList"); | include_header("Stops by Suburb", "stopList"); |
navbar(); | navbar(); |
echo ' <ul data-role="listview" data-filter="true" data-inset="true" >'; | echo ' <ul data-role="listview" data-filter="true" data-inset="true" >'; |
foreach ($suburbs as $suburb) { | foreach ($suburbs as $suburb) { |
echo '<li><a href="stopList.php?suburb='.urlencode($suburb).'">'.$suburb.'</a></li>'; | if (!isset($_REQUEST['firstLetter'])) { |
} | foreach (range('A', 'Z') as $letter) { |
echo '</ul>'; | echo "<li><a href=\"stopList.php?firstLetter=$letter&suburbs=yes\">$letter...</a></li>\n"; |
} else { | } |
// Timing Points / All stops | } |
else if (startsWith($suburb, $_REQUEST['firstLetter'])) { | |
if ($_REQUEST['allstops']) { | echo '<li><a href="stopList.php?suburb=' . urlencode($suburb) . '">' . $suburb . '</a></li>'; |
$url = $APIurl."/json/stops"; | } |
include_header("All Stops","stopList"); | } |
navbar(); | echo '</ul>'; |
timePlaceSettings(); | |
} else if ($_REQUEST['nearby']) { | |
$url = $APIurl."/json/neareststops?lat={$_SESSION['lat']}&lon={$_SESSION['lon']}&limit=15"; | |
include_header("Nearby Stops","stopList"); | |
navbar(); | |
timePlaceSettings(true); | |
} else if ($_REQUEST['suburb']) { | |
$suburb = filter_var($_REQUEST['suburb'], FILTER_SANITIZE_STRING); | |
$url = $APIurl."/json/stopzonesearch?q=".$suburb; | |
include_header("Stops in ".ucwords($suburb),"stopList"); | |
if (isMetricsOn()) { | |
// Create a new Instance of the tracker | |
$owa = new owa_php($config); | |
// Set the ID of the site being tracked | |
$owa->setSiteId($owaSiteID); | |
// Create a new event object | |
$event = $owa->makeEvent(); | |
// Set the Event Type, in this case a "video_play" | |
$event->setEventType('view_stop_list_suburb'); | |
// Set a property | |
$event->set('stop_list_suburb',$suburb); | |
// Track the event | |
$owa->trackEvent($event); | |
} | |
navbar(); | |
} else { | |
$url = $APIurl."/json/timingpoints"; | |
include_header("Timing Points / Major Stops","stopList"); | |
navbar(); | |
timePlaceSettings(); | |
} | } |
echo '<div class="noscriptnav"> Go to letter: '; | else { |
foreach(range('A','Z') as $letter) | // Timing Points / All stops |
{ | if ($_REQUEST['allstops']) { |
echo "<a href=\"#$letter\">$letter</a> "; | $listType = 'allstops=yes'; |
} | $url = $APIurl . "/json/stops"; |
echo "</div> | include_header("All Stops", "stopList"); |
<script> | navbar(); |
$('.noscriptnav').hide(); | timePlaceSettings(); |
</script>"; | } |
echo ' <ul data-role="listview" data-filter="true" data-inset="true" >'; | else if ($_REQUEST['nearby']) { |
$contents = json_decode(getPage($url)); | $listType = 'nearby=yes'; |
debug(print_r($contents,true)); | $url = $APIurl . "/json/neareststops?lat={$_SESSION['lat']}&lon={$_SESSION['lon']}&limit=15"; |
foreach ($contents as $key => $row) { | include_header("Nearby Stops", "stopList"); |
$stopName[$key] = $row[1]; | navbar(); |
} | timePlaceSettings(true); |
} | |
// Sort the stops by name | else if ($_REQUEST['suburb']) { |
array_multisort($stopName, SORT_ASC, $contents); | $suburb = filter_var($_REQUEST['suburb'], FILTER_SANITIZE_STRING); |
$listType = "suburb=$suburb"; | |
$firstletter = ""; | $url = $APIurl . "/json/stopzonesearch?q=" . $suburb; |
foreach ($contents as $row) | include_header("Stops in " . ucwords($suburb) , "stopList"); |
{ | if (isMetricsOn()) { |
if (substr($row[1],0,1) != $firstletter){ | // Create a new Instance of the tracker |
echo "<a name=$firstletter></a>"; | $owa = new owa_php($config); |
$firstletter = substr($row[1],0,1); | // Set the ID of the site being tracked |
} | $owa->setSiteId($owaSiteID); |
echo '<li><a href="stop.php?stopid='.$row[0].'">'; | // Create a new event object |
if (isset($_SESSION['lat']) && isset($_SESSION['lon'])){ | $event = $owa->makeEvent(); |
echo '<span class="ui-li-count">'.floor(distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'])).'m away</span>'; | // Set the Event Type, in this case a "video_play" |
} | $event->setEventType('view_stop_list_suburb'); |
echo bracketsMeanNewLine($row[1]); | // Set a property |
echo '</a></li>'; | $event->set('stop_list_suburb', $suburb); |
} | // Track the event |
echo '</ul>'; | $owa->trackEvent($event); |
} | |
navbar(); | |
} | |
else { | |
$url = $APIurl . "/json/timingpoints"; | |
include_header("Timing Points / Major Stops", "stopList"); | |
navbar(); | |
timePlaceSettings(); | |
} | |
echo ' <ul data-role="listview" data-filter="true" data-inset="true" >'; | |
if (!isset($_REQUEST['firstLetter']) && !$_REQUEST['suburb']) { | |
foreach (range('A', 'Z') as $letter) { | |
echo "<li><a href=\"stopList.php?firstLetter=$letter&$listType\">$letter...</a></li>\n"; | |
} | |
} | |
else { | |
$stops = json_decode(getPage($url)); | |
foreach ($stops as $key => $row) { | |
$stopName[$key] = $row[1]; | |
} | |
// Sort the stops by name | |
array_multisort($stopName, SORT_ASC, $stops); | |
if (!isset($_REQUEST['suburb'])){ | |
$stops = array_filter($stops, "filterByFirstLetter"); | |
} | |
$stopsGrouped = Array(); | |
foreach ($stops as $key => $row) { | |
if ((trim(preg_replace("/\(Platform.*/","",$stops[$key][1])) != trim(preg_replace("/\(Platform.*/","",$stops[$key + 1][1]))) || $key + 1 >= sizeof($stops)) { | |
if (sizeof($stopsGrouped) > 0) { | |
// print and empty grouped stops | |
// subsequent duplicates | |
$stopsGrouped["stop_ids"][] = $row[0]; | |
echo '<li>'; | |
if (!startsWith($stopsGrouped['stop_codes'][0], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point" class="ui-li-icon">'; | |
echo '<a href="stop.php?stopids=' . implode(",", $stopsGrouped['stop_ids']) . '">'; | |
if (isset($_SESSION['lat']) && isset($_SESSION['lon'])) { | |
echo '<span class="ui-li-count">' . floor(distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'])) . 'm away</span>'; | |
} | |
echo bracketsMeanNewLine(trim(preg_replace("/\(Platform.*/","",$row[1])) . '(' . sizeof($stopsGrouped["stop_ids"]) . ' stops)'); | |
echo "</a></li>\n"; | |
$stopsGrouped = Array(); | |
} | |
else { | |
// just a normal stop | |
echo '<li>'; | |
if (!startsWith($row[5], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point" class="ui-li-icon">'; | |
echo '<a href="stop.php?stopid=' . $row[0] . (startsWith($row[5], "Wj") ? '&stopcode=' . $row[5] : "") . '">'; | |
if (isset($_SESSION['lat']) && isset($_SESSION['lon'])) { | |
echo '<span class="ui-li-count">' . floor(distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'])) . 'm away</span>'; | |
} | |
echo bracketsMeanNewLine($row[1]); | |
echo "</a></li>\n"; | |
} | |
} else { | |
// this is a duplicated line item | |
if ($key - 1 <= 0 || (trim(preg_replace("/\(Platform.*/","",$stops[$key][1])) != trim(preg_replace("/\(Platform.*/","",$stops[$key - 1][1])))) { | |
// first duplicate | |
$stopsGrouped = Array( | |
"name" => trim(preg_replace("/\(Platform.*/","",$row[1])), | |
"stop_ids" => Array( | |
$row[0] | |
), | |
"stop_codes" => Array( | |
$row[5] | |
) | |
); | |
} | |
else { | |
// subsequent duplicates | |
$stopsGrouped["stop_ids"][] = $row[0]; | |
} | |
} | |
} | |
} | |
echo '</ul>'; | |
var_dump ($stopsGrouped); | |
} | } |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
$tripid = filter_var($_REQUEST['tripid'],FILTER_SANITIZE_NUMBER_INT); | $tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_NUMBER_INT); |
$stopid = filter_var($_REQUEST['stopid'],FILTER_SANITIZE_NUMBER_INT); | $stopid = filter_var($_REQUEST['stopid'], FILTER_SANITIZE_NUMBER_INT); |
$routeid = filter_var($_REQUEST['routeid'],FILTER_SANITIZE_NUMBER_INT); | $routeid = filter_var($_REQUEST['routeid'], FILTER_SANITIZE_NUMBER_INT); |
$routetrips = Array(); | |
if ($_REQUEST['routeid']) { | if ($_REQUEST['routeid']) { |
$url = $APIurl."/json/routetrips?route_id=".$routeid; | $url = $APIurl . "/json/routetrips?route_id=" . $routeid; |
$trips = json_decode(getPage($url)); | $routetrips = json_decode(getPage($url)); |
debug(print_r($trips,true)); | foreach ($routetrips as $trip) { |
foreach ($trips as $trip) | if ($trip[0] < midnight_seconds()) { |
{ | $tripid = $trip[1]; |
if ($trip[0] < midnight_seconds()) { | break; |
$tripid = $trip[1]; | } |
break; | } |
} | if (!($tripid > 0)) $tripid = $routetrip[0][1]; |
} | |
if (!($tripid > 0)) $tripid = $trips[0][1]; | |
} | } |
$url = $APIurl."/json/triprows?trip=".$tripid; | $url = $APIurl . "/json/triprows?trip=" . $tripid; |
$trips = array_flatten(json_decode(getPage($url))); | $trips = array_flatten(json_decode(getPage($url))); |
debug(print_r($trips,true)); | if (sizeof($routetrips) == 0) { |
include_header("Stops on ". $trips[1]->route_short_name . ' '. $trips[1]->route_long_name,"trip"); | $routeid = $trips[1]->route_id; |
$url = $APIurl . "/json/routetrips?route_id=" . $trips[1]->route_id; | |
$routetrips = json_decode(getPage($url)); | |
} | |
include_header("Stops on " . $trips[1]->route_short_name . ' ' . $trips[1]->route_long_name, "trip"); | |
if (isMetricsOn()) { | if (isMetricsOn()) { |
// Create a new Instance of the tracker | // Create a new Instance of the tracker |
$owa = new owa_php(); | $owa = new owa_php(); |
// Set the ID of the site being tracked | // Set the ID of the site being tracked |
$owa->setSiteId($owaSiteID); | $owa->setSiteId($owaSiteID); |
// Create a new event object | // Create a new event object |
$event = $owa->makeEvent(); | $event = $owa->makeEvent(); |
// Set the Event Type, in this case a "video_play" | // Set the Event Type, in this case a "video_play" |
$event->setEventType('view_trip'); | $event->setEventType('view_trip'); |
// Set a property | // Set a property |
$event->set('trip_id',$tripid); | $event->set('trip_id', $tripid); |
$event->set('route_id',$routeid); | $event->set('route_id', $routeid); |
$event->set('stop_id',$stopid); | $event->set('stop_id', $stopid); |
// Track the event | // Track the event |
$owa->trackEvent($event); | $owa->trackEvent($event); |
} | } |
timePlaceSettings(); | timePlaceSettings(); |
echo '<p> Other Trips: '; | |
foreach ($routetrips as $othertrip) { | |
echo '<a href="trip.php?tripid=' . $othertrip[1] . "&routeid=" . $routeid . '">' . midnight_seconds_to_time($othertrip[0]) . '</a> '; | |
} | |
echo '</p> Other directions/timing periods: '; | |
echo ' <ul data-role="listview" data-inset="true">'; | echo ' <ul data-role="listview" data-inset="true">'; |
$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)); | |
$stops = $json[0]; | $stops = $json[0]; |
$times = $json[1]; | $times = $json[1]; |
foreach ($stops as $key => $row) | echo '<li data-role="list-divider">' . midnight_seconds_to_time($times[0]) . '-' . midnight_seconds_to_time($times[sizeof($times) - 1]) . '</li>'; |
{ | $stopsGrouped = Array(); |
echo '<li>'; | foreach ($stops as $key => $row) { |
echo '<h3><a href="stop.php?stopid='.$row[0].'">'.bracketsMeanNewLine($row[1]); | if (($stops[$key][1] != $stops[$key + 1][1]) || $key + 1 >= sizeof($stops)) { |
if ($row[0] == $stopid) echo "<br><small> Current Location</small>"; | echo '<li>'; |
echo '</a></h3>'; | if (!startsWith($row[5], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point" class="ui-li-icon">'; |
echo '<p class="ui-li-aside">'.midnight_seconds_to_time($times[$key]).'</p>'; | if (sizeof($stopsGrouped) > 0) { |
echo '</li>'; | // print and empty grouped stops |
// subsequent duplicates | |
$stopsGrouped["stop_ids"][] = $row[0]; | |
$stopsGrouped["endTime"] = $times[$key]; | |
echo '<a href="stop.php?stopids=' . implode(",",$stopsGrouped['stop_ids']) . '">'; | |
echo '<p class="ui-li-aside">' . midnight_seconds_to_time($stopsGrouped['startTime']) . ' to ' . midnight_seconds_to_time($stopsGrouped['endTime']) . '</p>'; | |
echo bracketsMeanNewLine($row[1]); | |
echo '</a></li>'; | |
$stopsGrouped = Array(); | |
} | |
else { | |
// just a normal stop | |
echo '<a href="stop.php?stopid=' . $row[0] . (startsWith($row[5], "Wj") ? '&stopcode=' . $row[5] : "") . '">'; | |
echo '<p class="ui-li-aside">' . midnight_seconds_to_time($times[$key]) . '</p>'; | |
echo bracketsMeanNewLine($row[1]); | |
echo '</a></li>'; | |
} | |
} | |
else { | |
// this is a duplicated line item | |
if ($key - 1 <= 0 || ($stops[$key][1] != $stops[$key - 1][1])) { | |
// first duplicate | |
$stopsGrouped = Array( | |
"name" => $row[1], | |
"startTime" => $times[$key], | |
"stop_ids" => Array( | |
$row[0] | |
) | |
); | |
} | |
else { | |
// subsequent duplicates | |
$stopsGrouped["stop_ids"][] = $row[0]; | |
$stopsGrouped["endTime"] = $times[$key]; | |
} | |
} | |
} | } |
echo '</ul>'; | echo '</ul>'; |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include ('common.inc.php'); |
include_header("Trip Planner","tripPlanner", true, true); | include_header("Trip Planner", "tripPlanner", true, true); |
$from = (isset($_REQUEST['from']) ? filter_var($_REQUEST['from'],FILTER_SANITIZE_STRING) : "Brigalow"); | $from = (isset($_REQUEST['from']) ? filter_var($_REQUEST['from'], FILTER_SANITIZE_STRING) : "Brigalow"); |
$to = (isset($_REQUEST['to']) ? filter_var($_REQUEST['to'],FILTER_SANITIZE_STRING) : "Barry"); | $to = (isset($_REQUEST['to']) ? filter_var($_REQUEST['to'], FILTER_SANITIZE_STRING) : "Barry"); |
$date = (isset($_REQUEST['date']) ? filter_var($_REQUEST['date'],FILTER_SANITIZE_STRING) : date("m/d/Y")); | $date = (isset($_REQUEST['date']) ? filter_var($_REQUEST['date'], FILTER_SANITIZE_STRING) : date("m/d/Y")); |
$time = (isset($_REQUEST['time']) ? filter_var($_REQUEST['time'],FILTER_SANITIZE_STRING) : date("H:i")); | $time = (isset($_REQUEST['time']) ? filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING) : date("H:i")); |
# todo: convert date from form to h:ia? | // todo: convert date from form to h:ia? |
function tripPlanForm($errorMessage = "") | |
function tripPlanForm($errorMessage = "") | { |
{ | global $date, $time, $from, $to; |
global $date,$time,$from,$to; | echo "<font color=red>$errorMessage</font>"; |
echo "<font color=red>$errorMessage</font>"; | echo '<form action="tripPlanner.php" method="post"> |
echo '<form action="tripPlanner.php" method="post"> | |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="from">I would like to go from</label> | <label for="from">I would like to go from</label> |
<input type="text" name="from" id="from" value="' . $from . '" /> | <input type="text" name="from" id="from" value="' . $from . '" /> |
<a href="#" style="display:none" name="fromHere" id="fromHere"/>Here?</a> | <a href="#" style="display:none" name="fromHere" id="fromHere"/>Here?</a> |
</div> | </div> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="to"> to </label> | <label for="to"> to </label> |
<input type="text" name="to" id="to" value="' . $to . '" /> | <input type="text" name="to" id="to" value="' . $to . '" /> |
<a href="#" style="display:none" name="toHere" id="toHere"/>Here?</a> | <a href="#" style="display:none" name="toHere" id="toHere"/>Here?</a> |
</div> | </div> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="date"> on </label> | <label for="date"> on </label> |
<input type="text" name="date" id="date" value="' . $date . '" /> | <input type="text" name="date" id="date" value="' . $date . '" /> |
</div> | </div> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="time"> at </label> | <label for="time"> at </label> |
<input type="time" name="time" id="time" value="' . $time . '" /> | <input type="time" name="time" id="time" value="' . $time . '" /> |
</div> | </div> |
<input type="submit" value="Go!"></form>'; | <input type="submit" value="Go!"></form>'; |
echo "<script> | echo "<script> |
$('#toHere').click(function(event) { $('#to').val(getCookie('geolocate')); return false;}); | $('#toHere').click(function(event) { $('#to').val(getCookie('geolocate')); return false;}); |
$('#toHere').show(); | $('#toHere').show(); |
$('#fromHere').click(function(event) { $('#from').val(getCookie('geolocate')); return false;}); | $('#fromHere').click(function(event) { $('#from').val(getCookie('geolocate')); return false;}); |
$('#fromHere').show(); | $('#fromHere').show(); |
</script>"; | </script>"; |
} | } |
function processItinerary($itineraryNumber, $itinerary) | |
function processItinerary($itineraryNumber, $itinerary) | { |
{ | echo '<div data-role="collapsible" ' . ($itineraryNumber > 0 ? 'data-collapsed="true"' : "") . '> <h3> Option #' . ($itineraryNumber + 1) . ": " . floor($itinerary->duration / 60000) . " minutes ({$itinerary->startTime} to {$itinerary->endTime})</h3><p>"; |
echo '<div data-role="collapsible" ' . ($itineraryNumber > 0 ? 'data-collapsed="true"' : "") . '> <h3> Option #' . ($itineraryNumber + 1) . ": " . floor($itinerary->duration / 60000) . " minutes ({$itinerary->startTime} to {$itinerary->endTime})</h3><p>"; | echo "Walking time: " . floor($itinerary->walkTime / 60000) . " minutes (" . floor($itinerary->walkDistance) . " meters)<br>\n"; |
echo "Walking time: " . floor($itinerary->walkTime / 60000) . " minutes (" . floor($itinerary->walkDistance) . " meters)<br>\n"; | echo "Transit time: " . floor($itinerary->transitTime / 60000) . " minutes<br>\n"; |
echo "Transit time: " . floor($itinerary->transitTime / 60000) . " minutes<br>\n"; | echo "Waiting time: " . floor($itinerary->waitingTime / 60000) . " minutes<br>\n"; |
echo "Waiting time: " . floor($itinerary->waitingTime / 60000) . " minutes<br>\n"; | if (is_array($itinerary->legs->leg)) { |
$legMarkers = array(); | |
foreach ($itinerary->legs->leg as $legNumber => $leg) { | |
$legMarkers[] = array( | |
if (is_array($itinerary->legs->leg)) { | $leg->from->lat, |
$legMarkers = array(); | $leg->from->lon |
foreach ($itinerary->legs->leg as $legNumber => $leg) { | ); |
$legMarkers[] = array($leg->from->lat, $leg->from->lon); | } |
} | echo '' . staticmap($legMarkers, 0, "iconb", false) . "<br>\n"; |
echo '' . staticmap($legMarkers, 0,"iconb", false) . "<br>\n"; | echo '<ul>'; |
echo '<ul>'; | foreach ($itinerary->legs->leg as $legNumber => $leg) { |
foreach ($itinerary->legs->leg as $legNumber => $leg) { | echo '<li>'; |
echo '<li>'; | processLeg($legNumber, $leg); |
processLeg($legNumber, $leg); | echo "</li>"; |
echo "</li>"; | } |
} | echo "</ul>"; |
echo "</ul>"; | } |
} else { | else { |
echo '' . staticmap(array(array($itinerary->legs->leg->from->lat, $itinerary->legs->leg->from->lon)), 0,"iconb", false) . "<br>\n"; | echo '' . staticmap(array( |
processLeg(0, $itinerary->legs->leg); | array( |
} | $itinerary->legs->leg->from->lat, |
$itinerary->legs->leg->from->lon | |
echo "</p></div>"; | ) |
} | ) , 0, "iconb", false) . "<br>\n"; |
processLeg(0, $itinerary->legs->leg); | |
function processLeg($legNumber, $leg) { | } |
$legArray = object2array($leg); | echo "</p></div>"; |
echo '<h3>Leg #' . ($legNumber + 1) . " ( {$legArray['@mode']} from: {$leg->from->name} to {$leg->to->name}, " . floor($leg->duration / 60000) . " minutes) </h3>\n"; | } |
if ($legArray["@mode"] === "BUS") { | function processLeg($legNumber, $leg) |
echo "Take bus {$legArray['@route']} " . str_replace("To", "towards", $legArray['@headsign']) . "<br>"; | { |
} else { | $legArray = object2array($leg); |
$walkStepMarkers = array(); | echo '<h3>Leg #' . ($legNumber + 1) . " ( {$legArray['@mode']} from: {$leg->from->name} to {$leg->to->name}, " . floor($leg->duration / 60000) . " minutes) </h3>\n"; |
foreach ($leg->steps->walkSteps as $stepNumber => $step) { | if ($legArray["@mode"] === "BUS") { |
$walkStepMarkers[] = array($step->lat, $step->lon); | echo "Take bus {$legArray['@route']} " . str_replace("To", "towards", $legArray['@headsign']) . "<br>"; |
} | } |
echo "" . staticmap($walkStepMarkers, 0,"icong", false) . "<br>\n"; | else { |
foreach ($leg->steps->walkSteps as $stepNumber => $step) { | $walkStepMarkers = array(); |
echo "Walking step " . ($stepNumber + 1) . " $step->absoluteDirection / $step->relativeDirection on $step->streetName for " . floor($step->distance) . " meters<br>\n"; | foreach ($leg->steps->walkSteps as $stepNumber => $step) { |
} | $walkStepMarkers[] = array( |
} | $step->lat, |
} | $step->lon |
); | |
if ($_REQUEST['time']) { | } |
$toPlace = (startsWith($to, "-") ? $to : geocode($to, false)); | echo "" . staticmap($walkStepMarkers, 0, "icong", false) . "<br>\n"; |
$fromPlace = (startsWith($from, "-") ? $from : geocode($from, false)); | foreach ($leg->steps->walkSteps as $stepNumber => $step) { |
if ($toPlace == "" || $fromPlace == "") { | echo "Walking step " . ($stepNumber + 1) . " $step->absoluteDirection / $step->relativeDirection on $step->streetName for " . floor($step->distance) . " meters<br>\n"; |
$errorMessage = ""; | } |
if ($toPlace === "") | } |
$errorMessage .= urlencode($to) . " not found.<br>\n"; | } |
if ($fromPlace === "") | if ($_REQUEST['time']) { |
$errorMessage .= urlencode($from) . " not found.<br>\n"; | $toPlace = (startsWith($to, "-") ? $to : geocode($to, false)); |
tripPlanForm($errorMessage); | $fromPlace = (startsWith($from, "-") ? $from : geocode($from, false)); |
} else { | if ($toPlace == "" || $fromPlace == "") { |
if (isMetricsOn()) { | $errorMessage = ""; |
// Create a new Instance of the tracker | if ($toPlace === "") $errorMessage.= urlencode($to) . " not found.<br>\n"; |
$owa = new owa_php(); | if ($fromPlace === "") $errorMessage.= urlencode($from) . " not found.<br>\n"; |
// Set the ID of the site being tracked | tripPlanForm($errorMessage); |
$owa->setSiteId($owaSiteID); | } |
// Create a new event object | else { |
$event = $owa->makeEvent(); | if (isMetricsOn()) { |
// Set the Event Type, in this case a "video_play" | // Create a new Instance of the tracker |
$event->setEventType('view_trip_plan'); | $owa = new owa_php(); |
// Set a property | // Set the ID of the site being tracked |
$event->set('from',$from); | $owa->setSiteId($owaSiteID); |
$event->set('to',$to); | // Create a new event object |
$event->set('time',$time); | $event = $owa->makeEvent(); |
$event->set('date',$date); | // Set the Event Type, in this case a "video_play" |
// Track the event | $event->setEventType('view_trip_plan'); |
$owa->trackEvent($event); | // Set a property |
} | $event->set('from', $from); |
$url = $otpAPIurl."ws/plan?date=" . urlencode($_REQUEST['date']) . "&time=" . urlencode($_REQUEST['time']) . "&mode=TRANSIT%2CWALK&optimize=QUICK&maxWalkDistance=840&wheelchair=false&toPlace=$toPlace&fromPlace=$fromPlace&intermediatePlaces="; | $event->set('to', $to); |
$ch = curl_init($url); | $event->set('time', $time); |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | $event->set('date', $date); |
curl_setopt($ch, CURLOPT_HEADER, 0); | // Track the event |
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json")); | $owa->trackEvent($event); |
curl_setopt($ch,CURLOPT_TIMEOUT,5); | } |
$page = curl_exec($ch); | $url = $otpAPIurl . "ws/plan?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); | |
if(curl_errno($ch)) { tripPlanForm("Trip planner temporarily unavailable: ".curl_errno($ch)." ".curl_error($ch));} | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
else { | curl_setopt($ch, CURLOPT_HEADER, 0); |
$tripplan = json_decode($page); | curl_setopt($ch, CURLOPT_HTTPHEADER, array( |
debug(print_r($triplan,true)); | "Accept: application/json" |
echo "<h1> From: {$tripplan->plan->from->name} To: {$tripplan->plan->to->name} </h1>"; | )); |
echo "<h1> At: {$tripplan->plan->date} </h1>"; | curl_setopt($ch, CURLOPT_TIMEOUT, 5); |
$page = curl_exec($ch); | |
if (is_array($tripplan->plan->itineraries->itinerary)) { | if (curl_errno($ch)) { |
echo '<div data-role="collapsible-set">'; | tripPlanForm("Trip planner temporarily unavailable: " . curl_errno($ch) . " " . curl_error($ch)); |
foreach ($tripplan->plan->itineraries->itinerary as $itineraryNumber => $itinerary) { | } |
processItinerary($itineraryNumber, $itinerary); | else { |
} | $tripplan = json_decode($page); |
echo "</div>"; | debug(print_r($triplan, true)); |
} else { | echo "<h1> From: {$tripplan->plan->from->name} To: {$tripplan->plan->to->name} </h1>"; |
processItinerary(0, $tripplan->plan->itineraries->itinerary); | echo "<h1> At: {$tripplan->plan->date} </h1>"; |
} | if (is_array($tripplan->plan->itineraries->itinerary)) { |
} | echo '<div data-role="collapsible-set">'; |
curl_close($ch); | foreach ($tripplan->plan->itineraries->itinerary as $itineraryNumber => $itinerary) { |
} | processItinerary($itineraryNumber, $itinerary); |
} else { | } |
tripPlanForm(); | echo "</div>"; |
} | } |
include_footer(); | else { |
processItinerary(0, $tripplan->plan->itineraries->itinerary); | |
} | |
} | |
curl_close($ch); | |
} | |
} | |
else { | |
tripPlanForm(); | |
} | |
include_footer(); | |
?> | ?> |
python schedule_viewer.py --feed=/var/www/cbrfeed.zip \ | #!/bin/sh |
f=`dirname $0` | |
cd $f | |
python schedule_viewer.py --feed=/var/www/cbrfeed.zip \ | |
--key=ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q | --key=ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q |