Convert myway timeliness visualisations to new GTFS feed
Convert myway timeliness visualisations to new GTFS feed

<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
include ('../include/common.inc.php'); include ('../include/common.inc.php');
   
include_header("Busness R&amp;D", "index"); include_header("MyWay Balance and Timeliness Survey Results", "index");
if ($_SESSION['authed'] == true) { if ($_SESSION['authed'] == true) {
echo '<ul data-role="listview" data-theme="e" data-groupingtheme="e"> echo '<ul data-role="listview" data-theme="e" data-groupingtheme="e">
<li data-role="list-divider" > Admin Features </li> <li data-role="list-divider" > Admin Features </li>
<li><a href="myway_timeliness_calculate.php"><h3>myway_timeliness_calculate</h3> <li><a href="myway_timeliness_calculate.php"><h3>myway_timeliness_calculate</h3>
<p>myway_timeliness_calculate</p></a></li> <p>myway_timeliness_calculate</p></a></li>
<li><a href="myway_timeliness_reconcile.php"><h3>myway_timeliness_reconcile</h3> <li><a href="myway_timeliness_reconcile.php"><h3>myway_timeliness_reconcile</h3>
<p>myway_timeliness_reconcile</p></a></li> <p>myway_timeliness_reconcile</p></a></li>
</ul>'; </ul>';
} }
?> ?>
<ul data-role="listview" data-theme="e" data-groupingtheme="e"> <ul data-role="listview" data-theme="e" data-groupingtheme="e">
<li data-role="list-divider" >MyWay Balance </li> <li data-role="list-divider" >MyWay Balance </li>
<li><a href="mywaybalance.php"><h3>Mobile viewer for MyWay balance</h3> <li><a href="mywaybalance.php"><h3>Mobile viewer for MyWay balance</h3>
<p>Warning! No HTTPS security.</p></a></li> <p>Warning! No HTTPS security.</p></a></li>
</ul> </ul>
<ul data-role="listview" data-theme="e" data-groupingtheme="e"> <ul data-role="listview" data-theme="e" data-groupingtheme="e">
   
<li data-role="list-divider" > MyWay Timeliness Graphs </li> <li data-role="list-divider" > MyWay Timeliness Graphs </li>
   
  <li><a href="myway_timeliness_overview.php"><h3>Timeliness Overview</h3>
  <p>Displays statistics on timeliness split by day/time/month/stop etc.</p></a></li>
<li><a href="myway_timeliness.php"><h3>Timeliness over Day</h3> <li><a href="myway_timeliness.php"><h3>Timeliness over Day</h3>
<p>Displays the deviation from the timetable over the day</p></a></li> <p>Displays the deviation from the timetable over the day</p></a></li>
<li><a href="myway_timeliness_freqdist.php"><h3>Frequency Distribution of Time Deviation</h3> <li><a href="myway_timeliness_freqdist.php"><h3>Frequency Distribution of Time Deviation</h3>
<p>Displays spread of time deviations</p></a></li> <p>Displays spread of time deviations</p></a></li>
<li><a href="myway_timeliness_route.php"><h3>Timeliness over Route</h3> <li><a href="myway_timeliness_route.php"><h3>Timeliness over Route</h3>
<p>Displays the deviation from timetable as a specific route progresses</p></a></li> <p>Displays the deviation from timetable as a specific route progresses</p></a></li>
<li><a href="myway_timeliness_stop.php"><h3>Timeliness at Stop</h3> <li><a href="myway_timeliness_stop.php"><h3>Timeliness at Stop</h3>
<p>Displays the deviation from the timetable at a specific stop</p></a></li> <p>Displays the deviation from the timetable at a specific stop</p></a></li>
</ul> </ul>
</div> </div>
<?php <?php
include_footer() include_footer()
?> ?>
   
<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
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>
<center><div id="placeholder" style="width:900px;height:550px"></div></center> <center><div id="placeholder" style="width:900px;height:550px"></div></center>
<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();
   
<?php <?php
$query = "select * from myway_timingdeltas where abs(timing_delta) < 2*(select stddev(timing_delta) 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_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(); $labels = Array();
$lastRoute = ""; $lastRoute = "";
foreach ($query->fetchAll() as $delta) { foreach ($query->fetchAll() as $delta) {
$routeName = $delta['route_full_name']; $routeName = $delta['route_name'];
if (strstr($routeName, " 3")) if (preg_match('/z/',$routeName)) {
$routeName = "312-319"; $routeName = "312-319";
else } else {
$routeName = preg_replace('/\D/', '', $routeName); $routeName = preg_replace('/\D/', '', $routeName);
  }
if ($routeName != $lastRoute) { if ($routeName != $lastRoute) {
$i++; $i++;
echo " var d$i = [];"; echo " var d$i = [];";
$lastRoute = $routeName; $lastRoute = $routeName;
$labels[$i] = $routeName; $labels[$i] = $routeName;
} }
echo "d$i.push([ midnight+ (1000*" . midnight_seconds(strtotime($delta['time'])) . "), " . intval($delta['timing_delta']) . "]); \n"; echo "d$i.push([ midnight+ (1000*" . midnight_seconds(strtotime($delta['time'])) . "), " . intval($delta['timing_delta']) . "]); \n";
}; };
?> ?>
   
var placeholder = $("#placeholder"); var placeholder = $("#placeholder");
   
var plot = $.plot(placeholder, [ var plot = $.plot(placeholder, [
<?php <?php
foreach ($labels as $key => $label) { foreach ($labels as $key => $label) {
echo " { echo " {
data: d$key, data: d$key,
points: { show: true }, points: { show: true },
label: '$label' label: '$label'
},"; },";
} }
?> ?>
], ],
{ {
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, labelMargin: 32 }, grid: { hoverable: true, clickable: true, labelMargin: 32 }
}); });
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) {
if (Math.floor(v/60) < -9) return ""; if (Math.floor(v/60) < -9) return "";
return Math.abs(Math.floor(v/60)) + " min " + (v == 0 ? "" : (v >0 ? "early":"late")) return Math.abs(Math.floor(v/60)) + " min " + (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));
$("#y").text(pos.y.toFixed(2)); $("#y").text(pos.y.toFixed(2));
if (item) { if (item) {
if (previousPoint != item.dataIndex) { if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex; previousPoint = item.dataIndex;
$("#tooltip").remove(); $("#tooltip").remove();
var x = item.datapoint[0].toFixed(2), var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2); y = item.datapoint[1].toFixed(2);
var d = new Date(); var d = new Date();
d.setTime(x); d.setTime(x);
var time = d.getUTCHours() +':'+ (d.getUTCMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getUTCMinutes()) var time = d.getUTCHours() +':'+ (d.getUTCMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getUTCMinutes())
   
showTooltip(item.pageX, item.pageY, showTooltip(item.pageX, item.pageY,
item.series.label + " at "+ time +" = " + Math.abs(new Number(y/60).toFixed(2))+" minutes "+(y >0 ? "early":"late")); item.series.label + " at "+ time +" = " + Math.abs(new Number(y/60).toFixed(2))+" minutes "+(y >0 ? "early":"late"));
} }
} }
else { else {
$("#tooltip").remove(); $("#tooltip").remove();
previousPoint = null; previousPoint = null;
} }
}); });
   
</script> </script>
<?php <?php
   
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
include ('../include/common.inc.php'); include ('../include/common.inc.php');
include_header("MyWay Delta Calculate", "mywayDeltaCalc"); include_header("MyWay Delta Calculate", "mywayDeltaCalc");
flush(); flush();
ob_flush(); ob_flush();
   
function abssort($a, $b) { function abssort($a, $b) {
if ($a['timeDiff'] == $b['timeDiff']) { if ($a['timeDiff'] == $b['timeDiff']) {
return 0; return 0;
} }
return (abs($a['timeDiff']) < abs($b['timeDiff'])) ? -1 : 1; return (abs($a['timeDiff']) < abs($b['timeDiff'])) ? -1 : 1;
} }
   
//collect all observation not in delta //collect all observation not in delta
$query = "select * from myway_observations INNER JOIN myway_stops $query = "select * from myway_observations INNER JOIN myway_stops
ON myway_observations.myway_stop=myway_stops.myway_stop ON myway_observations.myway_stop=myway_stops.myway_stop
WHERE observation_id NOT IN WHERE observation_id NOT IN
( (
SELECT observation_id SELECT observation_id
FROM myway_timingdeltas FROM myway_timingdeltas
)"; )";
debug($query, "database"); debug($query, "database");
$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();
} }
$uncalcdObservations = $query->fetchAll(); $uncalcdObservations = $query->fetchAll();
//Display count //Display count
echo "<h3>" . sizeof($uncalcdObservations) . " observations not yet processed</h2>"; echo "<h3>" . sizeof($uncalcdObservations) . " observations not yet processed</h2>";
//foreach observation not in delta //foreach observation not in delta
foreach ($uncalcdObservations as $obsv) { foreach ($uncalcdObservations as $obsv) {
//var_dump($obsv); //var_dump($obsv);
echo "<h3>Observation {$obsv['observation_id']}:</h1> echo "<h3>Observation {$obsv['observation_id']}:</h1>
<small>{$obsv['myway_stop']} @ {$obsv['time']} on {$obsv['myway_route']}</small><br>"; <small>{$obsv['myway_stop']} @ {$obsv['time']} on {$obsv['myway_route']}</small><br>";
if ($obsv["stop_id"] == "") { if ($obsv["stop_id"] == "") {
echo "error, stop '{$obsv['myway_stop']}' unknown"; echo "error, stop '{$obsv['myway_stop']}' unknown";
continue; continue;
} }
// convert timestamp into time of day and date // convert timestamp into time of day and date
// timezones from http://www.postgresql.org/docs/8.0/static/datetime-keywords.html // timezones from http://www.postgresql.org/docs/8.0/static/datetime-keywords.html
$time = date("H:i:s", strtotime($obsv['time'])); $time = date("H:i:s", strtotime($obsv['time']));
$time_tz = date("H:i:s", strtotime($obsv['time'])) . " AESST"; $time_tz = date("H:i:s", strtotime($obsv['time'])) . " AESST";
$search_time = date("H:i:s", strtotime($obsv['time']) - (30 * 60)); // 30 minutes margin $search_time = date("H:i:s", strtotime($obsv['time']) - (30 * 60)); // 30 minutes margin
$date = date("c", strtotime($obsv['time'])); $date = date("c", strtotime($obsv['time']));
$timing_period = service_period(strtotime($date)); $timing_period = service_period(strtotime($date));
$potentialStops = Array(getStop($obsv["stop_id"])); $potentialStops = Array(getStop($obsv["stop_id"]));
//:get myway_stops records //:get myway_stops records
//:search by starts with stopcode and starts with street if street is not null //:search by starts with stopcode and starts with street if street is not null
//no result, skip and display error //no result, skip and display error
if (sizeof($potentialStops) < 1) { if (sizeof($potentialStops) < 1) {
echo "error, potential stops for stopid {$obsv["stop_id"]} unknown"; echo "error, potential stops for stopid {$obsv["stop_id"]} unknown";
continue; continue;
} }
//print out stops //print out stops
echo "Matched stops: "; echo "Matched stops: ";
foreach ($potentialStops as $potentialStop) { foreach ($potentialStops as $potentialStop) {
echo $potentialStop['stop_id'] . " " . $potentialStop['stop_name'] . " "; echo $potentialStop['stop_id'] . " " . $potentialStop['stop_name'] . " ";
} }
echo "<br>"; echo "<br>";
//:get myway_route record //:get myway_route record
//no result, skip and display error //no result, skip and display error
//print out route //print out route
$potentialRoutes = getRoutesByShortName(preg_replace("/[A-Z]/", "", $obsv["myway_route"])); $potentialRoutes = getRoutesByShortName(preg_replace("/[A-Z]/", "", $obsv["myway_route"]));
if (sizeof($potentialRoutes) < 1) { if (sizeof($potentialRoutes) < 1) {
echo "error, route '{$obsv["myway_route"]}' unknown"; echo "error, route '{$obsv["myway_route"]}' unknown";
continue; continue;
} }
$timeDeltas = Array(); $timeDeltas = Array();
foreach ($potentialRoutes as $potentialRoute) { foreach ($potentialRoutes as $potentialRoute) {
echo "Matched route: {$potentialRoute['route_id']} {$potentialRoute['route_short_name']}{$potentialRoute['route_long_name']} {$timing_period}<br>"; echo "Matched route: {$potentialRoute['route_id']} {$potentialRoute['route_short_name']}{$potentialRoute['route_long_name']} {$timing_period}<br>";
foreach ($potentialStops as $potentialStop) { foreach ($potentialStops as $potentialStop) {
$stopRoutes = getStopRoutes($potentialStop['stop_id'], $timing_period); $stopRoutes = getStopRoutes($potentialStop['stop_id'], $timing_period);
$foundRoute = Array(); $foundRoute = Array();
foreach ($stopRoutes as $stopRoute) { foreach ($stopRoutes as $stopRoute) {
//Check if this route stops at each stop //Check if this route stops at each stop
if ($stopRoute['route_id'] == $potentialRoute['route_id']) { if ($stopRoute['route_id'] == $potentialRoute['route_id']) {
echo "Matching route {$stopRoute['route_id']} found at stop #{$potentialStop['stop_id']}<br>"; echo "Matching route {$stopRoute['route_id']} found at stop #{$potentialStop['stop_id']}<br>";
$foundRoute = $stopRoute; $foundRoute = $stopRoute;
//if does get tripstoptimes for this route //if does get tripstoptimes for this route
$trips = getStopTrips($potentialStop['stop_id'], $timing_period, $search_time); $trips = getStopTrips($potentialStop['stop_id'], $timing_period, $search_time);
foreach ($trips as $trip) { foreach ($trips as $trip) {
//echo $trip['route_id']." ".$stopRoute['route_id'].";"; //echo $trip['route_id']." ".$stopRoute['route_id'].";";
if ($trip['route_id'] == $stopRoute['route_id']) { if ($trip['route_id'] == $stopRoute['route_id']) {
$timedTrip = getTripAtStop($trip['trip_id'], $trip['stop_sequence']); $timedTrip = getTripAtStop($trip['trip_id'], $trip['stop_sequence']);
$actual_time = strtotime($time); $actual_time = strtotime($time);
$trip_time = strtotime($timedTrip['arrival_time']); $trip_time = strtotime($timedTrip['arrival_time']);
$timeDiff = $actual_time - $trip_time; $timeDiff = $actual_time - $trip_time;
//work out time delta, put into array with index of delta //work out time delta, put into array with index of delta
$timeDeltas[] = Array( $timeDeltas[] = Array(
"timeDiff" => $timeDiff, "timeDiff" => $timeDiff,
"stop_id" => $potentialStop['stop_id'], "stop_id" => $potentialStop['stop_id'],
"stop_sequence" => $trip['stop_sequence'], "stop_sequence" => $trip['stop_sequence'],
  "route_name" => "{$potentialRoute['route_short_name']} {$potentialRoute['route_long_name']}",
"route_id" => $trip['route_id'] "route_id" => $trip['route_id']
); );
echo "Found trip {$trip['trip_id']} at stop {$potentialStop['stop_id']} (#{$potentialStop['stop_name']}, sequence #{$trip['stop_sequence']})<br>"; echo "Found trip {$trip['trip_id']} at stop {$potentialStop['stop_id']} (#{$potentialStop['stop_name']}, sequence #{$trip['stop_sequence']})<br>";
echo "Arriving at {$timedTrip['arrival_time']}, difference of " . round($timeDiff / 60, 2) . " minutes<br>"; echo "Arriving at {$timedTrip['arrival_time']}, difference of " . round($timeDiff / 60, 2) . " minutes<br>";
} }
} }
break; // because have found route break; // because have found route
} }
} }
if (sizeof($foundRoute) < 1) { if (sizeof($foundRoute) < 1) {
//print out that stops/does not stop //print out that stops/does not stop
echo "No matching routes found at {$potentialStop['stop_id']}<br>"; echo "No matching routes found at {$potentialStop['stop_id']}<br>";
//var_dump($stopRoutes); //var_dump($stopRoutes);
flush(); flush();
} }
} }
} }
// lowest delta is recorded delta // lowest delta is recorded delta
usort($timeDeltas, "abssort"); usort($timeDeltas, "abssort");
$lowestDelta = $timeDeltas[0]["timeDiff"]; $lowestDelta = $timeDeltas[0]["timeDiff"];
if (sizeof($timeDeltas) != 0) { if (sizeof($timeDeltas) != 0) {
  if (abs($lowestDelta) > 9999) {
  echo "Difference of " . round($lowestDelta / 60, 2) . " minutes is too high. Will not record this observation<br>";
  } else {
echo "Lowest difference of " . round($lowestDelta / 60, 2) . " minutes will be recorded for this observation<br>"; echo "Lowest difference of " . round($lowestDelta / 60, 2) . " minutes will be recorded for this observation<br>";
$observation_id = $obsv['observation_id']; $observation_id = $obsv['observation_id'];
   
  $route_name = $timeDeltas[0]["route_name"];
$route_id = $timeDeltas[0]["route_id"]; $route_id = $timeDeltas[0]["route_id"];
$stop_id = $timeDeltas[0]["stop_id"]; $stop_id = $timeDeltas[0]["stop_id"];
  $myway_stop = $obsv["myway_stop"];
$stop_sequence = $timeDeltas[0]["stop_sequence"]; $stop_sequence = $timeDeltas[0]["stop_sequence"];
$stmt = $conn->prepare("insert into myway_timingdeltas (observation_id, route_id, stop_id, timing_delta, time, date, timing_period, stop_sequence) $stmt = $conn->prepare("insert into myway_timingdeltas (observation_id, route_id, stop_id, timing_delta, time, date, timing_period, stop_sequence,myway_stop,route_name)
values (:observation_id, :route_id, :stop_id, :timing_delta, :time, :date, :timing_period, :stop_sequence)"); values (:observation_id, :route_id, :stop_id, :timing_delta, :time, :date, :timing_period, :stop_sequence,:myway_stop,:route_name)");
$stmt->bindParam(':observation_id', $observation_id); $stmt->bindParam(':observation_id', $observation_id);
$stmt->bindParam(':route_id', $route_id); $stmt->bindParam(':route_id', $route_id);
  $stmt->bindParam(':route_name', $route_name);
$stmt->bindParam(':stop_id', $stop_id); $stmt->bindParam(':stop_id', $stop_id);
  $stmt->bindParam(':myway_stop', $myway_stop);
$stmt->bindParam(':timing_delta', $lowestDelta); $stmt->bindParam(':timing_delta', $lowestDelta);
$stmt->bindParam(':time', $time_tz); $stmt->bindParam(':time', $time_tz);
$stmt->bindParam(':date', $date); $stmt->bindParam(':date', $date);
$stmt->bindParam(':timing_period', $timing_period); $stmt->bindParam(':timing_period', $timing_period);
$stmt->bindParam(':stop_sequence', $stop_sequence); $stmt->bindParam(':stop_sequence', $stop_sequence);
// insert a record // insert a record
$stmt->execute(); $stmt->execute();
if ($stmt->rowCount() > 0) { if ($stmt->rowCount() > 0) {
echo "Recorded.<br>"; echo "Recorded.<br>";
} }
var_dump($conn->errorInfo()); var_dump($conn->errorInfo());
flush(); flush();
  }
} }
flush(); flush();
} }
   
<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
include ('../include/common.inc.php'); include ('../include/common.inc.php');
include_header("MyWay Deltas", "mywayDelta"); include_header("MyWay Deltas", "mywayDelta");
?> ?>
<table> <table>
<tr><td></td><td>Mean</td><td>Standard<br>Deviation</td><td>Sample Size</td></tr> <tr><td></td><td>Mean</td><td>Standard<br>Deviation</td><td>Sample Size</td></tr>
<th> Overall </th> <th> Overall </th>
<?php <?php
$query = "select '', avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas "; $query = "select '', avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas ";
$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();
} }
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>"; echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>";
}; };
?> ?>
   
   
<th> Hour of Day </th> <th> Hour of Day </th>
<?php <?php
$query = "select extract(hour from time), avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by extract(hour from time) order by extract(hour from time)"; $query = "select extract(hour from time), avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by extract(hour from time) order by extract(hour from time)";
$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();
} }
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>"; echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>";
}; };
?> ?>
   
<th> Day of Week </th> <th> Day of Week </th>
<?php <?php
$query = "select to_char(date, 'Day'), avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by to_char(date, 'Day') order by to_char(date, 'Day')"; $query = "select to_char(date, 'Day'), avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by to_char(date, 'Day') order by to_char(date, 'Day')";
$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();
} }
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>"; echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>";
}; };
?> ?>
<th>Month </th> <th>Month </th>
<?php <?php
$query = "select to_char(date, 'Month'), avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by to_char(date, 'Month') order by to_char(date, 'Month')"; $query = "select to_char(date, 'Month'), avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by to_char(date, 'Month') order by to_char(date, 'Month')";
$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();
} }
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>"; echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>";
}; };
?> ?>
   
<th>Stop </th> <th>Stop </th>
<?php <?php
$query = "select myway_stop, avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas INNER JOIN myway_observations $query = "select myway_stop, avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by myway_stop having count(*) > 1 order by myway_stop";
ON myway_observations.observation_id=myway_timingdeltas.observation_id group by myway_stop having count(*) > 1 order by myway_stop";  
$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();
} }
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>"; echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>";
}; };
?> ?>
<th>Route </th> <th>Route </th>
<?php <?php
$query = "select route_full_name, avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by route_full_name having count(*) > 1 order by route_full_name"; $query = "select route_name, avg(timing_delta), stddev(timing_delta), count(*) from myway_timingdeltas group by route_name having count(*) > 1 order by route_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();
} }
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>"; echo "<tr><td>{$row[0]}</td><td>" . floor($row[1]) . "</td><td>" . floor($row[2]) . "</td><td>{$row[3]}</td></tr>";
}; };
?> ?>
   
   
</table> </table>
   
<?php <?php
include_footer(); include_footer();
?> ?>
   
<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
include ('../include/common.inc.php'); include ('../include/common.inc.php');
header('Content-Type: text/javascript; charset=utf8'); header('Content-Type: text/javascript; charset=utf8');
// header('Access-Control-Allow-Origin: http://bus.lambdacomplex.org/'); // header('Access-Control-Allow-Origin: http://bus.lambdacomplex.org/');
header('Access-Control-Max-Age: 3628800'); header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
?> ?>
{ {
"label": "<?php echo $_REQUEST['routeid']; ?>", "label": "<?php echo $_REQUEST['routeid']; ?>",
"data": <?php "data": <?php
$query = "select * from myway_timingdeltas where route_full_name = :route_full_name AND abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas) order by stop_sequence;"; $query = "select * from myway_timingdeltas where route_name = :route_name AND abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas) order by stop_sequence;";
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(':route_full_name', $_REQUEST['routeid'], PDO::PARAM_STR, 42); $query->bindParam(':route_name', $_REQUEST['routeid'], PDO::PARAM_STR, 42);
   
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
foreach ($query->fetchAll() as $delta) { foreach ($query->fetchAll() as $delta) {
$points[] = "[{$delta['stop_sequence']}, {$delta['timing_delta']}]"; $points[] = "[{$delta['stop_sequence']}, {$delta['timing_delta']}]";
}; };
echo "[" . implode(",", $points) . "]"; echo "[" . implode(",", $points) . "]";
?> ?>
} }
<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
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>
<form method="get" action=""> <form method="get" action="">
<select id="routeid" name="routeid"> <select id="routeid" name="routeid">
<?php <?php
$query = "select distinct route_full_name from myway_routes where myway_route != '' order by route_full_name"; $query = "select distinct route_name from myway_timingdeltas order by route_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();
} }
foreach ($query->fetchAll() as $route) { foreach ($query->fetchAll() as $route) {
echo "<option value=\"{$route['route_full_name']}\">{$route['route_full_name']}</option>"; echo "<option value=\"{$route['route_name']}\">{$route['route_name']}</option>";
}; };
?> </select> ?> </select>
<center><div id="placeholder" style="width:900px;height:550px"></div></center> <center><div id="placeholder" style="width:900px;height:550px"></div></center>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
   
var placeholder = $("#placeholder"); var placeholder = $("#placeholder");
var data = []; var data = [];
var options = { var options = {
xaxis: { xaxis: {
}, },
yaxis: { yaxis: {
tickFormatter: yformatter tickFormatter: yformatter
}, },
grid: { hoverable: true, clickable: true, labelMargin: 32 }, grid: { hoverable: true, clickable: true, labelMargin: 32 },
series: { series: {
lines: { show: false }, lines: { show: false },
points: { show: true } points: { show: true }
} }
}; };
var plot = $.plot(placeholder, data, options); var plot = $.plot(placeholder, data, options);
// fetch one series, adding to what we got // fetch one series, adding to what we got
var alreadyFetched = {}; var alreadyFetched = {};
$("#routeid").change(function () { $("#routeid").change(function () {
var select = $(this); var select = $(this);
// find the URL in the link right next to us // find the URL in the link right next to us
// var dataurl = button.siblings('a').attr('href'); // var dataurl = button.siblings('a').attr('href');
var dataurl = "myway_timeliness_route.json.php?routeid=" + select.val(); var dataurl = "myway_timeliness_route.json.php?routeid=" + select.val();
// then fetch the data with jQuery // then fetch the data with jQuery
function onDataReceived(series) { function onDataReceived(series) {
// extract the first coordinate pair so you can see that // extract the first coordinate pair so you can see that
// data is now an ordinary Javascript object // data is now an ordinary Javascript object
var firstcoordinate = '(' + series.data[0][0] + ', ' + series.data[0][1] + ')'; var firstcoordinate = '(' + series.data[0][0] + ', ' + series.data[0][1] + ')';
// let's add it to our current data // let's add it to our current data
if (!alreadyFetched[series.label]) { if (!alreadyFetched[series.label]) {
alreadyFetched[series.label] = true; alreadyFetched[series.label] = true;
data.push(series); data.push(series);
} }
// and plot all we got // and plot all we got
$.plot(placeholder, data, options); $.plot(placeholder, data, options);
} }
$.ajax({ $.ajax({
url: dataurl, url: dataurl,
method: 'GET', method: 'GET',
dataType: 'json', dataType: 'json',
success: onDataReceived success: onDataReceived
}); });
}); });
   
}); });
   
   
   
function yformatter(v) { function yformatter(v) {
if (Math.floor(v/60) < -9) return ""; if (Math.floor(v/60) < -9) return "";
return Math.abs(Math.floor(v/60)) + " min " + (v == 0 ? "" : (v >0 ? "early":"late")) return Math.abs(Math.floor(v/60)) + " min " + (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));
$("#y").text(pos.y.toFixed(2)); $("#y").text(pos.y.toFixed(2));
if (item) { if (item) {
if (previousPoint != item.dataIndex) { if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex; previousPoint = item.dataIndex;
$("#tooltip").remove(); $("#tooltip").remove();
var x = item.datapoint[0], var x = item.datapoint[0],
y = item.datapoint[1].toFixed(2); y = item.datapoint[1].toFixed(2);
showTooltip(item.pageX, item.pageY, showTooltip(item.pageX, item.pageY,
item.series.label + " at stop_sequence "+ x +" = " + Math.abs(new Number(y/60).toFixed(2))+" minutes "+(y >0 ? "early":"late")); item.series.label + " at stop_sequence "+ x +" = " + Math.abs(new Number(y/60).toFixed(2))+" minutes "+(y >0 ? "early":"late"));
} }
} }
else { else {
$("#tooltip").remove(); $("#tooltip").remove();
previousPoint = null; previousPoint = null;
} }
}); });
   
</script> </script>
   
<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
include ('../include/common.inc.php'); include ('../include/common.inc.php');
header('Content-Type: text/javascript; charset=utf8'); header('Content-Type: text/javascript; charset=utf8');
// header('Access-Control-Allow-Origin: http://bus.lambdacomplex.org/'); // header('Access-Control-Allow-Origin: http://bus.lambdacomplex.org/');
header('Access-Control-Max-Age: 3628800'); header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
?> ?>
{ {
"label": "<?php echo $_REQUEST['stopid']; ?>", "label": "<?php echo $_REQUEST['stopid']; ?>",
"data": <?php "data": <?php
$query = "select * from myway_timingdeltas INNER JOIN myway_observations $query = "select * from myway_timingdeltas
ON myway_observations.observation_id=myway_timingdeltas.observation_id  
where myway_stop = :myway_stop where myway_stop = :myway_stop
AND abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas) AND abs(timing_delta) < 2*(select stddev(timing_delta) from myway_timingdeltas)
order by myway_timingdeltas.time;"; order by time;";
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(':myway_stop', $_REQUEST['stopid'], PDO::PARAM_STR, 42); $query->bindParam(':myway_stop', $_REQUEST['stopid'], PDO::PARAM_STR, 42);
   
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
foreach ($query->fetchAll() as $delta) { foreach ($query->fetchAll() as $delta) {
$points[] = "[" . ((strtotime("00:00Z") + midnight_seconds(strtotime($delta['time']))) * 1000) . ", {$delta['timing_delta']}]"; $points[] = "[" . ((strtotime("00:00Z") + midnight_seconds(strtotime($delta['time']))) * 1000) . ", {$delta['timing_delta']}]";
}; };
if (count($points) == 0) { if (count($points) == 0) {
echo "[]"; echo "[]";
} }
else else
echo "[" . implode(",", $points) . "]"; echo "[" . implode(",", $points) . "]";
?> ?>
} }
   
<?php <?php
/* /*
* Copyright 2010,2011 Alexander Sadleir * Copyright 2010,2011 Alexander Sadleir
   
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.
*/ */
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>
<form method="get" action=""> <form method="get" action="">
<select id="stopid" name="stopid"> <select id="stopid" name="stopid">
<?php <?php
$query = "select distinct myway_stop from myway_stops where myway_stop != '' order by myway_stop"; $query = "select distinct myway_stop from myway_timingdeltas where myway_stop != '' order by myway_stop";
$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();
} }
foreach ($query->fetchAll() as $stop) { foreach ($query->fetchAll() as $stop) {
echo "<option value=\"{$stop['myway_stop']}\">{$stop['myway_stop']}</option>"; echo "<option value=\"{$stop['myway_stop']}\">{$stop['myway_stop']}</option>";
}; };
?> </select> <center><div id="placeholder" style="width:900px;height:550px"></div></center> ?> </select> <center><div id="placeholder" style="width:900px;height:550px"></div></center>
<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 placeholder = $("#placeholder"); var placeholder = $("#placeholder");
var data = []; var data = [];
var options = { var options = {
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, labelMargin: 32 }, grid: { hoverable: true, clickable: true, labelMargin: 32 },
series: { series: {
lines: { show: false }, lines: { show: false },
points: { show: true } points: { show: true }
} }
}; };
   
var plot = $.plot(placeholder, data, options); var plot = $.plot(placeholder, data, options);
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>');
// fetch one series, adding to what we got // fetch one series, adding to what we got
var alreadyFetched = {}; var alreadyFetched = {};
$("#stopid").change(function () { $("#stopid").change(function () {
var select = $(this); var select = $(this);
// find the URL in the link right next to us // find the URL in the link right next to us
// var dataurl = button.siblings('a').attr('href'); // var dataurl = button.siblings('a').attr('href');
var dataurl = "myway_timeliness_stop.json.php?stopid=" + select.val(); var dataurl = "myway_timeliness_stop.json.php?stopid=" + select.val();
// then fetch the data with jQuery // then fetch the data with jQuery
function onDataReceived(series) { function onDataReceived(series) {
// extract the first coordinate pair so you can see that // extract the first coordinate pair so you can see that
// data is now an ordinary Javascript object // data is now an ordinary Javascript object
var firstcoordinate = '(' + series.data[0][0] + ', ' + series.data[0][1] + ')'; var firstcoordinate = '(' + series.data[0][0] + ', ' + series.data[0][1] + ')';
// let's add it to our current data // let's add it to our current data
if (!alreadyFetched[series.label]) { if (!alreadyFetched[series.label]) {
alreadyFetched[series.label] = true; alreadyFetched[series.label] = true;
data.push(series); data.push(series);
} }
// and plot all we got // and plot all we got
$.plot(placeholder, data, options); $.plot(placeholder, data, options);
} }
$.ajax({ $.ajax({
url: dataurl, url: dataurl,
method: 'GET', method: 'GET',
dataType: 'json', dataType: 'json',
success: onDataReceived success: onDataReceived
}); });
}); });
   
}); });
function yformatter(v) { function yformatter(v) {
if (Math.floor(v/60) < -9) return ""; if (Math.floor(v/60) < -9) return "";
return Math.abs(Math.floor(v/60)) + " min " + (v == 0 ? "" : (v >0 ? "early":"late")) return Math.abs(Math.floor(v/60)) + " min " + (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));
$("#y").text(pos.y.toFixed(2)); $("#y").text(pos.y.toFixed(2));
if (item) { if (item) {
if (previousPoint != item.dataIndex) { if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex; previousPoint = item.dataIndex;
$("#tooltip").remove(); $("#tooltip").remove();
var x = item.datapoint[0].toFixed(2), var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2); y = item.datapoint[1].toFixed(2);
var d = new Date(); var d = new Date();
d.setTime(x); d.setTime(x);
var time = d.getUTCHours() +':'+ (d.getUTCMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getUTCMinutes()) var time = d.getUTCHours() +':'+ (d.getUTCMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getUTCMinutes())
   
showTooltip(item.pageX, item.pageY, showTooltip(item.pageX, item.pageY,
item.series.label + " at "+ time +" = " + Math.abs(new Number(y/60).toFixed(2))+" minutes "+(y >0 ? "early":"late")); item.series.label + " at "+ time +" = " + Math.abs(new Number(y/60).toFixed(2))+" minutes "+(y >0 ? "early":"late"));
} }
} }
else { else {
$("#tooltip").remove(); $("#tooltip").remove();
previousPoint = null; previousPoint = null;
} }
}); });
   
</script> </script>