Color timeliness graph based on route number
Color timeliness graph based on route number

<?php <?php
// SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',') // SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',')
$suburbs = explode(",", "Acton,Ainslie,Amaroo,Aranda,Banks,Barton,Belconnen,Bonner,Bonython,Braddon,Bruce,Calwell,Campbell,Chapman,Charnwood,Chifley,Chisholm,City,Conder,Cook,Curtin,Deakin,Dickson,Downer,Duffy,Dunlop,Evatt,Fadden,Farrer,Fisher,Florey,Flynn,Forrest,Franklin,Fraser,Fyshwick,Garran,Gilmore,Giralang,Gordon,Gowrie,Greenway,Griffith,Gungahlin,Hackett,Hall,Harrison,Hawker,Higgins,Holder,Holt,Hughes,Hume,Isaacs,Isabella Plains,Kaleen,Kambah,Kingston,Latham,Lawson,Lyneham,Lyons,Macarthur,Macgregor,Macquarie,Mawson,McKellar,Melba,Mitchell,Monash,Narrabundah,Ngunnawal,Nicholls,Oaks Estate,O'Connor,O'Malley,Oxley,Page,Palmerston,Parkes,Pearce,Phillip,Pialligo,Red Hill,Reid,Richardson,Rivett,Russell,Scullin,Spence,Stirling,Symonston,Tharwa,Theodore,Torrens,Turner,Wanniassa,Waramanga,Watson,Weetangera,Weston,Yarralumla"); $suburbs = explode(",", "Acton,Ainslie,Amaroo,Aranda,Banks,Barton,Belconnen,Bonner,Bonython,Braddon,Bruce,Calwell,Campbell,Chapman,Charnwood,Chifley,Chisholm,City,Conder,Cook,Curtin,Deakin,Dickson,Downer,Duffy,Dunlop,Evatt,Fadden,Farrer,Fisher,Florey,Flynn,Forrest,Franklin,Fraser,Fyshwick,Garran,Gilmore,Giralang,Gordon,Gowrie,Greenway,Griffith,Gungahlin,Hackett,Hall,Harrison,Hawker,Higgins,Holder,Holt,Hughes,Hume,Isaacs,Isabella Plains,Kaleen,Kambah,Kingston,Latham,Lawson,Lyneham,Lyons,Macarthur,Macgregor,Macquarie,Mawson,McKellar,Melba,Mitchell,Monash,Narrabundah,Ngunnawal,Nicholls,Oaks Estate,O'Connor,O'Malley,Oxley,Page,Palmerston,Parkes,Pearce,Phillip,Pialligo,Red Hill,Reid,Richardson,Rivett,Russell,Scullin,Spence,Stirling,Symonston,Tharwa,Theodore,Torrens,Turner,Wanniassa,Waramanga,Watson,Weetangera,Weston,Yarralumla");
function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb", $collapsible = true) function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb", $collapsible = true, $twotone = false)
{ {
global $labsPath; global $labsPath;
$width = 300; $width = 300;
$height = 300; $height = 300;
$metersperpixel[9] = 305.492 * $width; $metersperpixel[9] = 305.492 * $width;
$metersperpixel[10] = 152.746 * $width; $metersperpixel[10] = 152.746 * $width;
$metersperpixel[11] = 76.373 * $width; $metersperpixel[11] = 76.373 * $width;
$metersperpixel[12] = 38.187 * $width; $metersperpixel[12] = 38.187 * $width;
$metersperpixel[13] = 19.093 * $width; $metersperpixel[13] = 19.093 * $width;
$metersperpixel[14] = 9.547 * $width; $metersperpixel[14] = 9.547 * $width;
$metersperpixel[15] = 4.773 * $width; $metersperpixel[15] = 4.773 * $width;
//$metersperpixel[16] = 2.387 * $width; //$metersperpixel[16] = 2.387 * $width;
// $metersperpixel[17]=1.193*$width; // $metersperpixel[17]=1.193*$width;
$center = ""; $center = "";
$markers = ""; $markers = "";
$mapwidthinmeters = 50; $mapwidthinmeters = 50;
if (sizeof($mapPoints) < 1) return "map error"; if (sizeof($mapPoints) < 1) return "map error";
if (sizeof($mapPoints) === 1) { if (sizeof($mapPoints) === 1) {
if ($zoom == 0) $zoom = 14; if ($zoom == 0) $zoom = 14;
$markers.= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage"; $markers.= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage";
$center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
} }
else { else {
foreach ($mapPoints as $index => $mapPoint) { foreach ($mapPoints as $index => $mapPoint) {
$markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . $markerImage . ($index + 1); if ($twotone && $index == 0) {
  $markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . "iconr" . ($index + 1);
  $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
  }
  else {
  $markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . $markerImage . ($index + 1);
  }
if ($index + 1 != sizeof($mapPoints)) $markers.= "|"; if ($index + 1 != sizeof($mapPoints)) $markers.= "|";
$dist = distance($mapPoints[0][0], $mapPoint[0][1],$mapPoint[0], $mapPoint[1]); $dist = distance($mapPoints[0][0], $mapPoint[0][1], $mapPoint[0], $mapPoint[1]);
$mapwidthinmeters = ($dist>$mapwidthinmeters ? $dist : $mapwidthinmeters); $mapwidthinmeters = ($dist > $mapwidthinmeters ? $dist : $mapwidthinmeters);
$totalLat+= $mapPoint[0]; $totalLat+= $mapPoint[0];
$totalLon+= $mapPoint[1]; $totalLon+= $mapPoint[1];
} }
if ($zoom == 0) { if ($zoom == 0) {
$mapwidthinmeters = distance($minlat, $minlon, $minlat, $maxlon); $mapwidthinmeters = distance($minlat, $minlon, $minlat, $maxlon);
foreach (array_reverse($metersperpixel, true) as $zoomLevel => $maxdistance) { foreach (array_reverse($metersperpixel, true) as $zoomLevel => $maxdistance) {
if ($zoom == 0 && $mapwidthinmeters*1.5 < ($maxdistance)) $zoom = $zoomLevel; if ($zoom == 0 && $mapwidthinmeters * 1.5 < ($maxdistance)) $zoom = $zoomLevel;
} }
} }
$center = $totalLat / sizeof($mapPoints) . "," . $totalLon / sizeof($mapPoints); $center = $totalLat / sizeof($mapPoints) . "," . $totalLon / sizeof($mapPoints);
} }
$output = ""; $output = "";
if ($collapsible) $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>'; if ($collapsible) $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
$output.= '<img class="map" src="' . curPageURL() . '/'. $labsPath. '/lib/staticmaplite/staticmap.php?center=' . $center . '&amp;zoom=' . $zoom . '&amp;size=' . $width . 'x' . $height . '&amp;markers=' . $output.= '<img class="map" src="' . curPageURL() . '/' . $labsPath . '/lib/staticmaplite/staticmap.php?center=' . $center . '&amp;zoom=' . $zoom . '&amp;size=' . $width . 'x' . $height . '&amp;markers=' . $markers . '" width=' . $width . ' height=' . $height . '>';
$markers . '" width=' . $width . ' height=' . $height . '>';  
if ($collapsible) $output.= '</div>'; if ($collapsible) $output.= '</div>';
return $output; return $output;
} }
function distance($lat1, $lng1, $lat2, $lng2, $roundLargeValues = false) function distance($lat1, $lng1, $lat2, $lng2, $roundLargeValues = false)
{ {
$pi80 = M_PI / 180; $pi80 = M_PI / 180;
$lat1*= $pi80; $lat1*= $pi80;
$lng1*= $pi80; $lng1*= $pi80;
$lat2*= $pi80; $lat2*= $pi80;
$lng2*= $pi80; $lng2*= $pi80;
$r = 6372.797; // mean radius of Earth in km $r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1; $dlat = $lat2 - $lat1;
$dlng = $lng2 - $lng1; $dlng = $lng2 - $lng1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2); $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
$c = 2 * atan2(sqrt($a) , sqrt(1 - $a)); $c = 2 * atan2(sqrt($a) , sqrt(1 - $a));
$km = $r * $c; $km = $r * $c;
if ($roundLargeValues) { if ($roundLargeValues) {
if ($km < 1) return floor($km * 1000); if ($km < 1) return floor($km * 1000);
else return round($km,2)."k"; else return round($km, 2) . "k";
} else return floor($km * 1000); }
  else return floor($km * 1000);
} }
   
function decodePolylineToArray($encoded) function decodePolylineToArray($encoded)
{ {
// source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 // source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5
$length = strlen($encoded); $length = strlen($encoded);
$index = 0; $index = 0;
$points = array(); $points = array();
$lat = 0; $lat = 0;
$lng = 0; $lng = 0;
while ($index < $length) { while ($index < $length) {
// Temporary variable to hold each ASCII byte. // Temporary variable to hold each ASCII byte.
$b = 0; $b = 0;
// The encoded polyline consists of a latitude value followed by a // The encoded polyline consists of a latitude value followed by a
// longitude value. They should always come in pairs. Read the // longitude value. They should always come in pairs. Read the
// latitude value first. // latitude value first.
$shift = 0; $shift = 0;
$result = 0; $result = 0;
do { do {
// The `ord(substr($encoded, $index++))` statement returns the ASCII // The `ord(substr($encoded, $index++))` statement returns the ASCII
// code for the character at $index. Subtract 63 to get the original // code for the character at $index. Subtract 63 to get the original
// value. (63 was added to ensure proper ASCII characters are displayed // value. (63 was added to ensure proper ASCII characters are displayed
// in the encoded polyline string, which is `human` readable) // in the encoded polyline string, which is `human` readable)
$b = ord(substr($encoded, $index++)) - 63; $b = ord(substr($encoded, $index++)) - 63;
// AND the bits of the byte with 0x1f to get the original 5-bit `chunk. // AND the bits of the byte with 0x1f to get the original 5-bit `chunk.
// Then left shift the bits by the required amount, which increases // Then left shift the bits by the required amount, which increases
// by 5 bits each time. // by 5 bits each time.
// OR the value into $results, which sums up the individual 5-bit chunks // OR the value into $results, which sums up the individual 5-bit chunks
// into the original value. Since the 5-bit chunks were reversed in // into the original value. Since the 5-bit chunks were reversed in
// order during encoding, reading them in this way ensures proper // order during encoding, reading them in this way ensures proper
// summation. // summation.
$result|= ($b & 0x1f) << $shift; $result|= ($b & 0x1f) << $shift;
$shift+= 5; $shift+= 5;
} }
// Continue while the read byte is >= 0x20 since the last `chunk` // Continue while the read byte is >= 0x20 since the last `chunk`
// was not OR'd with 0x20 during the conversion process. (Signals the end) // was not OR'd with 0x20 during the conversion process. (Signals the end)
while ($b >= 0x20); while ($b >= 0x20);
// Check if negative, and convert. (All negative values have the last bit // Check if negative, and convert. (All negative values have the last bit
// set) // set)
$dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1));
// Compute actual latitude since value is offset from previous value. // Compute actual latitude since value is offset from previous value.
$lat+= $dlat; $lat+= $dlat;
// The next values will correspond to the longitude for this point. // The next values will correspond to the longitude for this point.
$shift = 0; $shift = 0;
$result = 0; $result = 0;
do { do {
$b = ord(substr($encoded, $index++)) - 63; $b = ord(substr($encoded, $index++)) - 63;
$result|= ($b & 0x1f) << $shift; $result|= ($b & 0x1f) << $shift;
$shift+= 5; $shift+= 5;
} while ($b >= 0x20); } while ($b >= 0x20);
$dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1));
$lng+= $dlng; $lng+= $dlng;
// The actual latitude and longitude values were multiplied by // The actual latitude and longitude values were multiplied by
// 1e5 before encoding so that they could be converted to a 32-bit // 1e5 before encoding so that they could be converted to a 32-bit
// integer representation. (With a decimal accuracy of 5 places) // integer representation. (With a decimal accuracy of 5 places)
// Convert back to original values. // Convert back to original values.
$points[] = array( $points[] = array(
$lat * 1e-5, $lat * 1e-5,
$lng * 1e-5 $lng * 1e-5
); );
} }
return $points; return $points;
} }
function geocode($query, $giveOptions) function geocode($query, $giveOptions)
{ {
global $cloudmadeAPIkey; 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"; $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)); $contents = json_decode(getPage($url));
if ($giveOptions) return $contents->features; if ($giveOptions) return $contents->features;
elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0] . "," . $contents->features[0]->centroid->coordinates[1]; elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0] . "," . $contents->features[0]->centroid->coordinates[1];
else return ""; else return "";
} }
function reverseGeocode($lat, $lng) function reverseGeocode($lat, $lng)
{ {
global $cloudmadeAPIkey; global $cloudmadeAPIkey;
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=" . $lat . "," . $lng . "&distance=closest&object_type=road"; $url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=" . $lat . "," . $lng . "&distance=closest&object_type=road";
$contents = json_decode(getPage($url)); $contents = json_decode(getPage($url));
return $contents->features[0]->properties->name; return $contents->features[0]->properties->name;
} }
?> ?>
   
<?php <?php
function getServiceOverride($date="") { function getServiceOverride($date="") {
global $conn; global $conn;
$query = "Select * from calendar_dates where date = :date and exception_type = '1' LIMIT 1"; $query = "Select * from calendar_dates where date = :date and exception_type = '1' LIMIT 1";
debug($query,"database"); // debug($query,"database");
$query = $conn->prepare($query); // Create a prepared statement $query = $conn->prepare($query); // Create a prepared statement
$query->bindParam(":date", date("Ymd",($date != "" ? $date : time()))); $query->bindParam(":date", date("Ymd",($date != "" ? $date : time())));
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetch(PDO::FETCH_ASSOC); return $query->fetch(PDO::FETCH_ASSOC);
} }
   
  function getCurrentAlerts() {
  global $conn;
  $query = "SELECT * from servicealerts_alerts";
  //debug($query, "database");
  $query = $conn->prepare($query);
  //if ($stop_sequence != "") $query->bindParam(":stop_sequence", $stop_sequence);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
  function getInformedAlerts($id,$filter_class,$filter_id) {
   
  global $conn;
  $query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id";
   
  if ($filter_class != "" && $filter_id != "") {
  $query .= " AND (informed_class = :informed_class OR informed_class = 'network') AND informed_id = :informed_id";
   
  }
  //debug($query, "database");
  $query = $conn->prepare($query);
  if ($filter_class != "" && $filter_id != "") {
  $query->bindParam(":informed_class", $filter_class);
  $query->bindParam(":informed_id", $filter_id);
  }
  $query->bindParam(":servicealert_id", $id);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
?> ?>
<?php <?php
include ('../include/common.inc.php'); include ('../include/common.inc.php');
include_header("MyWay Deltas", "mywayDelta"); include_header("MyWay Deltas", "mywayDelta");
?> ?>
   
<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="../js/flot/excanvas.min.js"></script><![endif]--> <!--[if lte IE 8]><script language="javascript" type="text/javascript" src="../js/flot/excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="../js/flot/jquery.flot.js"></script> <script language="javascript" type="text/javascript" src="../js/flot/jquery.flot.js"></script>
<div id="placeholder" style="width:800px;height:600px"></div> <div id="placeholder" style="width:1000px;height:600px"></div>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var d = new Date(); var d = new Date();
d.setUTCMinutes(0); d.setUTCMinutes(0);
d.setUTCHours(0); d.setUTCHours(0);
var midnight = d.getTime(); var midnight = d.getTime();
var d1 = [];  
<?php <?php
//$query = "select * from myway_timingdeltas order by time"; //$query = "select * from myway_timingdeltas order by time";
$query = "select * from myway_timingdeltas where abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas) order by time;"; $query = "select * from myway_timingdeltas where abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas) order by route_full_name;";
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
$i = 0; $i = 0;
  $labels = Array();
  $lastRoute = "";
foreach ($query->fetchAll() as $delta) { foreach ($query->fetchAll() as $delta) {
echo "d1.push([ midnight+ (1000*" . midnight_seconds(strtotime($delta['time'])) . "), {$delta['timing_delta']}]); \n"; $routeName = $delta['route_full_name'];
$i++; if (strstr($routeName," 3")) $routeName = "312-319";
  else $routeName = preg_replace('/\D/', '', $routeName);
  if ($routeName != $lastRoute) {
  $i++;
  echo " var d$i = [];";
  $lastRoute = $routeName;
  $labels[$i] = $routeName;
  }
  echo "d$i.push([ midnight+ (1000*" . midnight_seconds(strtotime($delta['time'])) . "), {$delta['timing_delta']}]); \n";
}; };
?> ?>
   
var d2 = [];  
<?php  
//$query = "select * from myway_timingdeltas order by route_full_name";  
$query = "select * from myway_timingdeltas where abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas) order by route_full_name";  
$query = $conn->prepare($query);  
$query->execute();  
if (!$query) {  
databaseError($conn->errorInfo());  
return Array();  
}  
$i = 0;  
foreach ($query->fetchAll() as $delta) {  
// echo "d2.push([$i, {$delta['timing_delta']}]); \n";  
$i++;  
};  
?>  
var placeholder = $("#placeholder"); var placeholder = $("#placeholder");
   
var plot = $.plot(placeholder, [ var plot = $.plot(placeholder, [
{ <?php
data: d1, foreach ($labels as $key => $label) {
points: { show: true } echo " {
}, data: d$key,
{ points: { show: true },
data: d2, label: '$label'
points: { show: true } },";
}, }
  ?>
], ],
{ {
xaxis: { xaxis: {
mode: "time", mode: "time",
min: midnight + (1000*60*60*8), min: midnight + (1000*60*60*8),
max: midnight + (1000*60*60*23.5) max: midnight + (1000*60*60*23.5)
}, },
yaxis: { yaxis: {
tickFormatter: yformatter tickFormatter: yformatter
}, },
grid: { hoverable: true, clickable: true }, grid: { hoverable: true, clickable: true },
}); });
var o; var o;
o = plot.pointOffset({ x: midnight+ (9*60*60*1000), y: -1.2}); o = plot.pointOffset({ x: midnight+ (9*60*60*1000), y: -1.2});
placeholder.append('<div style="position:absolute;left:' + (o.left + 4) + 'px;top:' + o.top + 'px;color:#666;font-size:smaller">9am</div>'); placeholder.append('<div style="position:absolute;left:' + (o.left + 4) + 'px;top:' + o.top + 'px;color:#666;font-size:smaller">9am</div>');
o = plot.pointOffset({ x: midnight+ (16*60*60*1000), y: -1.2}); o = plot.pointOffset({ x: midnight+ (16*60*60*1000), y: -1.2});
placeholder.append('<div style="position:absolute;left:' + (o.left + 4) + 'px;top:' + o.top + 'px;color:#666;font-size:smaller">4pm</div>'); placeholder.append('<div style="position:absolute;left:' + (o.left + 4) + 'px;top:' + o.top + 'px;color:#666;font-size:smaller">4pm</div>');
   
}); });
function yformatter(v) { function yformatter(v) {
return Math.floor(v/60) + " minutes " + (v == 0 ? "" : (v >0 ? "early":"late")) return Math.floor(v/60) + " minutes " + (v == 0 ? "" : (v >0 ? "early":"late"))
} }
function showTooltip(x, y, contents) { function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( { $('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute', position: 'absolute',
display: 'none', display: 'none',
top: y + 5, top: y + 5,
left: x + 5, left: x + 5,
border: '1px solid #fdd', border: '1px solid #fdd',
padding: '2px', padding: '2px',
'background-color': '#fee', 'background-color': '#fee',
opacity: 0.80 opacity: 0.80
}).appendTo("body").fadeIn(200); }).appendTo("body").fadeIn(200);
} }
var previousPoint = null; var previousPoint = null;
$("#placeholder").bind("plothover", function (event, pos, item) { $("#placeholder").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2)); $("#x").text(pos.x.toFixed(2));