Merge branch 'master' of github.com:maxious/ACTBus-ui
Merge branch 'master' of github.com:maxious/ACTBus-ui

--- a/.gitmodules
+++ b/.gitmodules
@@ -1,7 +1,4 @@
-[submodule "js/flotr2"]
-	path = js/flotr2
-	url = https://github.com/HumbleSoftware/Flotr2.git
-[submodule "js/FlashCanvas"]
-	path = js/FlashCanvas
-	url = https://github.com/timcameronryan/FlashCanvas
+[submodule "lib/amon-php"]
+	path = lib/amon-php
+	url = https://github.com/martinrusev/amon-php.git
 

file:a/about.php -> file:b/about.php
--- a/about.php
+++ b/about.php
@@ -20,8 +20,8 @@
 <p>
     Busness Time - An ACT bus timetable webapp<br />
     Based on the maxious-canberra-transit-feed (<a 
-        href="http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip">download</a>, 
-    last updated <?php echo date("F d Y.", @filemtime('cbrfeed.zip')); ?>)<br />
+        href="http://busresources.lambdacomplex.org/cbrfeed.zip">download</a>, 
+    last updated <?php echo date("F d Y.", @filemtime('../busresources/cbrfeed.zip')); ?>)<br />
     Source code for the <a 
         href="https://github.com/maxious/ACTBus-data">transit 
         feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this 

--- a/aws/busuidb.sh
+++ b/aws/busuidb.sh
@@ -7,10 +7,10 @@
 psql -d transitdata -f /var/www/transitdata.cbrfeed.sql
 #createuser transitdata -SDRP
 #password transitdata
-#psql -d transitdata -c "GRANT SELECT ON TABLE agency,calendar,calendar_dates,routes,stop_times,stops,trips\
-#,servicealerts_alerts,servicealerts_informed TO transitdata;"
-#psql -d transitdata -c "GRANT SELECT,INSERT ON	TABLE myway_observations,myway_routes,myway_stops,myway_timingdeltas TO transitdata;"
-#psql -d transitdata -c	"GRANT SELECT,INSERT,UPDATE ON TABLE myway_routes,myway_stops TO transitdata;"
+#psql -d transitdata -c "GRANT SELECT ON TABLE agency,calendar,calendar_dates,routes,stop_times,stops,trips TO transitdata;"
+#psql -d transitdata -c "GRANT SELECT,INSERT ON TABLE myway_observations,myway_timingdeltas,myway_routes,myway_stops TO transitdata;"
+#psql -d transitdata -c	"GRANT SELECT,INSERT,UPDATE ON TABLE servicealerts_alerts,servicealerts_informed TO transitdata;"
+#psql -d transitdata -c	"GRANT USAGE,SELECT ON SEQUENCE servicealerts_alerts_id_seq TO transitdata;"
 ##psql -d transitdata -c "GRANT SELECT ON ALL TABLES IN SCHEMA public TO transitdata;"
 ## INSERT INTO geometry_columns(f_table_catalog, f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, "type")
 ##SELECT '', 'public', 'shapes', 'shape_pt', ST_CoordDim(shape_pt), ST_SRID(shape_pt), GeometryType(shape_pt)

--- a/css/local.css.php
+++ b/css/local.css.php
@@ -55,7 +55,7 @@
     visibility: hidden;
     display: none;
     }
-    #servicewarning {
+    .servicewarning {
     padding: 1em;
     margin-bottom: 0.5em;
     text-size: 0.2em;

--- a/feedback.php
+++ b/feedback.php
@@ -67,7 +67,7 @@
   echo "\nServer host/IP: ".php_uname("n");
   echo "\nCurrent date/time: ". date("c");
   echo "\nCurrent code revision: ".exec("git rev-parse --short HEAD");
-  echo "\nCurrent timetables version: ".date("c",@filemtime('cbrfeed.zip'));
+  echo "\nCurrent timetables version: ".date("c",@filemtime('../busresources/cbrfeed.zip'));
   echo "\nDump of session: ".print_r($_SESSION,true);
 ?>
 </textarea>

--- a/include/common-geo.inc.php
+++ b/include/common-geo.inc.php
@@ -58,8 +58,8 @@
     $output = "";
     if ($collapsible)
         $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
-   if (isIOSDevice()) $output.= '<img class="hiresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=2&amp;sensor=true" width=' . $width . ' height=' . $height . '>';
- else $output.= '<img class="lowresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=1&amp;format=jpg&amp;sensor=true" width=' . $width . ' height=' . $height . '>';
+   if (isIOSDevice()) $output.= '<img class="hiresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=2&amp;sensor=true" width=' . $width . ' height=' . $height . ' alt="map of stop location">';
+ else $output.= '<img class="lowresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=1&amp;format=jpg&amp;sensor=true" width=' . $width . ' height=' . $height . ' alt="map of stop location">';
    
     if ($collapsible)
         $output.= '</div>';

--- a/include/common-request.inc.php
+++ b/include/common-request.inc.php
@@ -57,6 +57,12 @@
 if (isset($_REQUEST['stopids'])) {
     $stopids = explode(",", filter_var($_REQUEST['stopids'], FILTER_SANITIZE_STRING));
 }
+if (isset($_REQUEST['filterIncludeRoutes'])) {
+    $filterIncludeRoutes = explode(",", filter_var($_REQUEST['filterIncludeRoutes'], FILTER_SANITIZE_STRING));
+}
+if (isset($_REQUEST['filterHasStop'])) {
+    $filterHasStop = filter_var($_REQUEST['filterHasStop'], FILTER_SANITIZE_STRING);
+}
 if (isset($_REQUEST['tripid'])) {
     $tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_STRING);
 }

--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -42,7 +42,7 @@
 }
 
 function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) {
-    global $basePath, $GTFSREnabled;
+    global $basePath, $GTFSREnabled, $stopid, $routeid;
     echo '
 <!DOCTYPE html> 
 <html lang="en">
@@ -59,14 +59,13 @@
         $jqmcss = $basePath . "css/jquery.mobile-$jqmVersion.css";
         $jqjs = $basePath . "js/jquery-1.6.4.min.js";
         $jqmjs = $basePath . "js/jquery.mobile-$jqmVersion.js";
-        
+
         $jqmcss = $basePath . "css/jquery.mobile-b90eab4935.css";
         $jqmjs = $basePath . "js/jquery.mobile-b90eab4935.js";
     } else {
         $jqmcss = "//code.jquery.com/mobile/$jqmVersion/jquery.mobile-$jqmVersion.min.css";
         $jqjs = "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js";
         $jqmjs = "//code.jquery.com/mobile/$jqmVersion/jquery.mobile-$jqmVersion.min.js";
-
     }
     echo '<link rel="stylesheet"  href="' . $jqmcss . '" />
 	<script src="' . $jqjs . '"></script>
@@ -108,7 +107,7 @@
 }';
     echo '</style>';
     echo '<link rel="stylesheet"  href="' . $basePath . 'css/local.css.php" />';
-    if (isIOSDevice()){
+    if (isIOSDevice()) {
         echo '<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" />
@@ -174,19 +173,41 @@
         <a name="maincontent" id="maincontent"></a>
         <div data-role="content"> ';
         if ($GTFSREnabled) {
-        $overrides = getServiceOverride();
-        if (isset($overrides['service_id'])) {
-            if ($overrides['service_id'] == "noservice") {
-                echo '<div id="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a 
+            $overrides = getServiceOverride();
+            if (isset($overrides['service_id'])) {
+                if ($overrides['service_id'] == "noservice") {
+                    echo '<div class="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a 
 href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
-            } else {
-                echo '<div id="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
-            }
-        }
-            $serviceAlerts = getServiceAlertsAsArray("agency", "0");
+                } else {
+                    echo '<div class="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
+                }
+            }
+            $serviceAlerts = Array();
+            $globalAlerts = getServiceAlertsAsArray("agency", "0");
+            if ($globalAlerts != null) {
+                // echo "getting alerts due to network wide";
+                $serviceAlerts = array_merge($serviceAlerts, $globalAlerts);
+            }
+            if (isset($stopid)) {
+                $stopAlerts = getServiceAlertsAsArray("stop", $stopid);
+                if ($stopAlerts != null) {
+                    // echo "getting alerts due to stop $stopid";
+                    $serviceAlerts = array_merge($serviceAlerts, $stopAlerts);
+                }
+            }
+            if (isset($routeid)) {
+                $routeAlerts = getServiceAlertsAsArray("route", $routeid);
+                if ($routeAlerts != null) {
+                    //    echo "getting alerts due to route $routeid";
+                    $serviceAlerts = array_merge($serviceAlerts, $routeAlerts);
+                }
+            }
             if (isset($serviceAlerts['entity']) && sizeof($serviceAlerts['entity']) > 0) {
                 foreach ($serviceAlerts['entity'] as $entity) {
-                    echo "<div id='servicewarning'>" . date("F j, g:i a", strtotime($entity['alert']['active_period'][0]['start'])) . " to " . date("F j, g:i a", strtotime($entity['alert']['active_period'][0]['end'])) . "{$entity['alert']['header_text']['translation'][0]['text']}<br>Warning: {$entity['alert']['description_text']['translation'][0]['text']} 
+                    echo "<div class='servicewarning'><b>{$entity['alert']['header_text']['translation'][0]['text']}</b>&nbsp;<small>"
+                    . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['start']) . " to "
+                    . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['end']) . "</small>
+                            <br>Warning: {$entity['alert']['description_text']['translation'][0]['text']} 
                             <br><a href='{$entity['alert']['url']['translation'][0]['text']}'>Source</a>  </div>";
                 }
             }
@@ -208,13 +229,14 @@
 s.parentNode.insertBefore(ga, s);
   })();</script>";
         $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
-        echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
+        echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" alt=""/></noscript>';
     }
     echo "\n</div></div></body></html>";
 }
+
 function timeSettings() {
     global $service_periods;
-echo '<div id="settings" data-role="collapsible" data-collapsed="true">
+    echo '<div id="settings" data-role="collapsible" data-collapsed="true">
 <h3>Change Time (' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3>
         <form action="' . basename($_SERVER['PHP_SELF']) . '" method="GET">
                <input type="hidden" name="suburb" id="suburb" value="' . (isset($_REQUEST['suburb']) ? $_REQUEST['suburb'] : "") . '"/>
@@ -230,10 +252,10 @@
 		<div data-role="fieldcontain">
 		    <label for="service_period"> Service Period:  </label>
 			<select name="service_period" id="service_period">';
-foreach ($service_periods as $service_period) {
-    echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>';
-}
-echo '</select>
+    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>
 		
@@ -241,8 +263,9 @@
                 </div></form>
             </div>';
 }
+
 function placeSettings() {
-    
+
     $geoerror = false;
     $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "";
 
@@ -275,14 +298,15 @@
 
 //stop list collapsing
 function stopCompare($stopName) {
-    return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)),0,9);
-}
-function stopGroupTitle($stopName,$stopdesc) {
-    if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /",$stopName)) {
-        $descParts =  explode("<br>",$stopdesc);
-         return trim(str_replace("Street: ","",$descParts[0]));
+    return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)), 0, 9);
+}
+
+function stopGroupTitle($stopName, $stopdesc) {
+    if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /", $stopName)) {
+        $descParts = explode("<br>", $stopdesc);
+        return trim(str_replace("Street: ", "", $descParts[0]));
     } else {
-        return trim(preg_replace("/\(Platform.*/", "",$stopName));
+        return trim(preg_replace("/\(Platform.*/", "", $stopName));
     }
 }
 

--- a/include/common-transit.inc.php
+++ b/include/common-transit.inc.php
@@ -149,69 +149,104 @@
           street inform: route inform, trip inform, stop inform
           route patch: trip remove
          */
-        $fm = new transit_realtime\FeedMessage();
-        $fh = new transit_realtime\FeedHeader();
-        $fh->setGtfsRealtimeVersion(1);
-        $fh->setTimestamp(time());
-        $fm->setHeader($fh);
-        foreach (getCurrentAlerts() as $alert) {
-            $fe = new transit_realtime\FeedEntity();
-            $fe->setId($alert['id']);
-            $fe->setIsDeleted(false);
-            $alert = new transit_realtime\Alert();
-            $tr = new transit_realtime\TimeRange();
-            $tr->setStart($alert['start']);
-            $tr->setEnd($alert['end']);
-            $alert->addActivePeriod($tr);
-            $informedEntities = getInformedAlerts($alert['id'], $_REQUEST['filter_class'], $_REQUEST['filter_id']);
-            if (sizeof($informedEntities) > 0) {
-                $informed = Array();
-                $es = new transit_realtime\EntitySelector();
-                if ($informedEntity['informed_class'] == "agency") {
-                    $es->setAgencyId($informedEntity['informed_id']);
-                }
-                if ($informedEntity['informed_class'] == "stop") {
-                    $es->setStopId($informedEntity['informed_id']);
-                }
-                if ($informedEntity['informed_class'] == "route") {
-                    $es->setRouteId($informedEntity['informed_id']);
-                }
-                if ($informedEntity['informed_class'] == "trip") {
-                    $td = new transit_realtime\TripDescriptor();
-                    $td->setTripId($informedEntity['informed_id']);
-                    $es->setTrip($td);
-                }
-                $alert->addInformedEntity($es);
-            }
-            $alert->setCause(constant("transit_realtime\Alert\Cause::" . $alert['cause']));
-            $alert->setEffect(constant("transit_realtime\Alert\Effect::" . $alert['effect']));
-            $tsUrl = new transit_realtime\TranslatedString();
-            $tUrl = new transit_realtime\TranslatedString\Translation();
-            $tUrl->setText($alert['url']);
-            $tUrl->setLanguage("en");
-            $tsUrl->addTranslation($tUrl);
-            $alert->setUrl($tsUrl);
-            $tsHeaderText = new transit_realtime\TranslatedString();
-            $tHeaderText = new transit_realtime\TranslatedString\Translation();
-            $tHeaderText->setText($alert['header']);
-            $tHeaderText->setLanguage("en");
-            $tsHeaderText->addTranslation($tHeaderText);
-            $alert->setHeaderText($tsHeaderText);
-            $tsDescriptionText = new transit_realtime\TranslatedString();
-            $tDescriptionText = new transit_realtime\TranslatedString\Translation();
-            $tDescriptionText->setText($alert['description']);
-            $tDescriptionText->setLanguage("en");
-            $tsDescriptionText->addTranslation($tDescriptionText);
-            $alert->setDescriptionText($tsDescriptionText);
-            $fe->setAlert($alert);
-            $fm->addEntity($fe);
+        $current_alerts = getCurrentAlerts();
+        $informed_count = 0;
+        if (sizeof($current_alerts) > 0) {
+
+            $fm = new transit_realtime\FeedMessage();
+            $fh = new transit_realtime\FeedHeader();
+            $fh->setGtfsRealtimeVersion(1);
+            $fh->setTimestamp(time());
+            $fm->setHeader($fh);
+            foreach ($current_alerts as $current_alert) {
+                $affectsFilteredEntities = false;
+                $fe = new transit_realtime\FeedEntity();
+                $fe->setId($current_alert['id']);
+                $fe->setIsDeleted(false);
+                $alert = new transit_realtime\Alert();
+                $tr = new transit_realtime\TimeRange();
+                $tr->setStart($current_alert['start']);
+                $tr->setEnd($current_alert['end']);
+                $alert->addActivePeriod($tr);
+                $informedEntities = getInformedAlerts($current_alert['id'], $filter_class, $filter_id);
+                if (sizeof($informedEntities) > 0) {
+
+                    $affectsFilteredEntities = true;
+                    foreach ($informedEntities as $informedEntity) {
+	$informed_count++;
+                    $informed = Array();
+                    $es = new transit_realtime\EntitySelector();
+                    if ($informedEntity['informed_class'] == "agency") {
+                        $es->setAgencyId($informedEntity['informed_id']);
+                    }
+                    if ($informedEntity['informed_class'] == "stop") {
+                        $es->setStopId($informedEntity['informed_id']);
+                    }
+                    if ($informedEntity['informed_class'] == "route") {
+                        $es->setRouteId($informedEntity['informed_id']);
+                    }
+                    if ($informedEntity['informed_class'] == "trip") {
+                        $td = new transit_realtime\TripDescriptor();
+                        $td->setTripId($informedEntity['informed_id']);
+                        $es->setTrip($td);
+                    }
+                    $alert->addInformedEntity($es);
+}
+                }
+                if ($current_alert['cause'] != "") {
+                    $alert->setCause(constant("transit_realtime\Alert\Cause::" . $current_alert['cause']));
+                }
+                if ($current_alert['effect'] != "") {
+                    $alert->setEffect(constant("transit_realtime\Alert\Effect::" . $current_alert['effect']));
+                }
+                if ($current_alert['url'] != "") {
+                    $tsUrl = new transit_realtime\TranslatedString();
+                    $tUrl = new transit_realtime\TranslatedString\Translation();
+                    $tUrl->setText($current_alert['url']);
+                    $tUrl->setLanguage("en");
+                    $tsUrl->addTranslation($tUrl);
+                    $alert->setUrl($tsUrl);
+                }
+                if ($current_alert['header'] != "") {
+                    $tsHeaderText = new transit_realtime\TranslatedString();
+                    $tHeaderText = new transit_realtime\TranslatedString\Translation();
+                    $tHeaderText->setText($current_alert['header']);
+                    $tHeaderText->setLanguage("en");
+                    $tsHeaderText->addTranslation($tHeaderText);
+                    $alert->setHeaderText($tsHeaderText);
+                }
+                if ($current_alert['description'] != "") {
+                    $tsDescriptionText = new transit_realtime\TranslatedString();
+                    $tDescriptionText = new transit_realtime\TranslatedString\Translation();
+                    $tDescriptionText->setText(trim($current_alert['description']));
+                    $tDescriptionText->setLanguage("en");
+                    $tsDescriptionText->addTranslation($tDescriptionText);
+                    $alert->setDescriptionText($tsDescriptionText);
+                }
+                $fe->setAlert($alert);
+                if ($affectsFilteredEntities) {
+                    $fm->addEntity($fe);
+                }
+            }
+            if ($informed_count > 0) {
+                return $fm;
+            } else {
+                return null;
+            }
+        } else
+            return null;
+    }
+
+    function getServiceAlertsAsArray($filter_class = "", $filter_id = "") {
+
+        $alerts = getServiceAlerts($filter_class, $filter_id);
+        if ($alerts != null) {
+            $codec = new DrSlump\Protobuf\Codec\PhpArray();
+
+            return $codec->encode($alerts);
+        } else {
+            return null;
         }
-        return $fm;
-    }
-
-    function getServiceAlertsAsArray($filter_class = "", $filter_id = "") {
-        $codec = new DrSlump\Protobuf\Codec\PhpArray();
-        return $codec->encode(getServiceAlerts($filter_class, $filter_id));
     }
 
     function getServiceAlertsAsBinary($filter_class = "", $filter_id = "") {

--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -51,13 +51,20 @@
         || strstr($_SERVER['PHP_SELF'], "lib/")
         || strstr($_SERVER['PHP_SELF'], "geo/")
         || strstr($_SERVER['PHP_SELF'], "include/")
-        || strstr($_SERVER['PHP_SELF'], "servicealerts/"))
+        || strstr($_SERVER['PHP_SELF'], "rtpis/")) {
     $basePath = "../";
+}
 
 function isDebugServer() {
     
     return php_sapi_name() == "cli" || strstr(php_uname('n'),"actbus") || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "azusa" || $_SERVER['SERVER_NAME'] == "vanille"
             || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" ||  $_SERVER['SERVER_NAME'] == "192.168.1.8" || $_SERVER['SERVER_NAME'] == "192.168.178.24");
+}
+
+if (isset($_SERVER['SERVER_NAME'])  && $_SERVER['SERVER_NAME'] == "maxious.xen.prgmr.com") {
+// Set the exception handler
+require $basePath."/lib/amon-php/amon.php";
+Amon::setup_exception_handler();
 }
 
 include_once ("common-geo.inc.php");

--- a/include/db/route-dao.inc.php
+++ b/include/db/route-dao.inc.php
@@ -59,7 +59,12 @@
         databaseError($conn->errorInfo());
         return Array();
     }
-    return $query->fetchAll();
+    $results = $query->fetchAll();
+    if (is_array($results)) {
+        return $results;
+    } else {
+        return Array($results);
+    }
 }
 function getRouteDescription($routeID, $directionID) {
     $trip = getRouteNextTrip($routeID, $directionID);
@@ -97,7 +102,7 @@
 function getRoutesByNumberSeries($routeNumberSeries = "") {
     global $conn;
     if (strlen($routeNumberSeries) == 1) {
-        return getRoutesByNumber($routeNumberSeries);
+        return getRoute($routeNumberSeries);
     }
     $seriesMin = substr($routeNumberSeries, 0, -1) . "0";
     $seriesMax = substr($routeNumberSeries, 0, -1) . "9";
@@ -120,7 +125,7 @@
 function getRouteNextTrip($routeID, $directionID) {
     global $conn;
    
-    $query = "select routes.route_id,direction_id,trips.trip_id,trip_headsign,departure_time from routes join trips on trips.route_id = routes.route_id
+    $query = "select routes.route_id,routes.route_url,direction_id,trips.trip_id,trip_headsign,departure_time,service_id from routes join trips on trips.route_id = routes.route_id
 join stop_times on stop_times.trip_id = trips.trip_id where  arrival_time between :currentTime and :futureTime 
 and routes.route_id = :routeID and trips.direction_id = :directionID order by
 arrival_time limit 1";

--- a/include/db/servicealert-dao.inc.php
+++ b/include/db/servicealert-dao.inc.php
@@ -44,17 +44,19 @@
     return $query->fetch(PDO :: FETCH_ASSOC);
 }
 
-function updateServiceAlert($alertID, $start, $end, $header, $description, $url) {
+function updateServiceAlert($alertID, $alert) {
     global $conn;
-    $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url where id = :servicealert_id';
+    $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url, cause=:cause, effect=:effect where id = :servicealert_id';
     debug($query, "database");
     $query = $conn->prepare($query);
-    $query->bindParam(":servicealert_id", $alertID);
-    $query->bindParam(":start", $start);
-    $query->bindParam(":end", $end);
-    $query->bindParam(":header", $header);
-    $query->bindParam(":description", $description);
-    $query->bindParam(":url", $url);
+    $query->bindValue(":servicealert_id", $alertID);
+    $query->bindValue(":start", $alert['startdate']);
+    $query->bindValue(":end", $alert['enddate']);
+    $query->bindValue(":header", $alert['header']);
+    $query->bindValue(":description", $alert['description']);
+    $query->bindValue(":url", $alert['url']);
+    $query->bindValue(":cause", $alert['cause']);
+    $query->bindValue(":effect", $alert['effect']);
     $query->execute();
 
     print_r($conn->errorInfo());
@@ -65,16 +67,19 @@
     return $query->fetch(PDO :: FETCH_ASSOC);
 }
 
-function addServiceAlert($start, $end, $header, $description, $url) {
+function addServiceAlert($alert) {
     global $conn;
-    $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url) VALUES (:start, :end, :header, :description, :url) ';
+    $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url,cause,effect) VALUES (:start, :end, :header, :description, :url,:cause,:effect) ';
     debug($query, "database");
     $query = $conn->prepare($query);
-    $query->bindParam(":start", $start);
-    $query->bindParam(":end", $end);
-    $query->bindParam(":header", $header);
-    $query->bindParam(":description", $description);
-    $query->bindParam(":url", $url);
+    //print_r($alert);
+    $query->bindValue(":start", $alert['startdate']);
+    $query->bindValue(":end", $alert['enddate']);
+    $query->bindValue(":header", $alert['header']);
+    $query->bindValue(":description", $alert['description']);
+    $query->bindValue(":url", $alert['url']);
+    $query->bindValue(":cause", $alert['cause']);
+    $query->bindValue(":effect", $alert['effect']);
     $query->execute();
 
     print_r($conn->errorInfo());
@@ -114,6 +119,7 @@
 function getInformedAlerts($id, $filter_class, $filter_id) {
 
     global $conn;
+    //echo "$id, $filter_class, $filter_id\n";
     $query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id";
 
     if ($filter_class != "") {
@@ -158,12 +164,14 @@
 
 function addInformedAlert($serviceAlertID, $class, $id, $action) {
     global $conn;
-    $query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id) VALUES(:servicealert_id ,:informed_class, :informed_id)';
+    $query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id, informed_action) 
+        VALUES(:servicealert_id ,:informed_class, :informed_id, :informed_action)';
     debug($query, "database");
     $query = $conn->prepare($query);
     $query->bindParam(":servicealert_id", $serviceAlertID);
     $query->bindParam(":informed_class", $class);
     $query->bindParam(":informed_id", $id);
+    $query->bindParam(":informed_action", $action);
     $query->execute();
 
     print_r($conn->errorInfo());

--- a/include/db/stop-dao.inc.php
+++ b/include/db/stop-dao.inc.php
@@ -89,7 +89,7 @@
     $query = "Select * from stops where stop_name LIKE :name;";
     debug($query, "database");
     $query = $conn->prepare($query);
-    $name = "%" . $name . ";%";
+    $name = $name . "%";
     $query->bindParam(":name", $name);
     $query->execute();
     if (!$query) {

--- a/include/db/trip-dao.inc.php
+++ b/include/db/trip-dao.inc.php
@@ -51,6 +51,25 @@
     }
     return $query->fetchAll();
 }
+
+function getTripHasStop($tripID, $stopID) {
+        global $conn;
+    $query = "SELECT stop_id
+FROM stop_times
+join trips on trips.trip_id = stop_times.trip_id
+WHERE trips.trip_id = :tripID and stop_times.stop_id = :stopID";
+    debug($query, "database");
+    $query = $conn->prepare($query);
+    $query->bindParam(":tripID", $tripID);
+    $query->bindParam(":stopID", $stopID);
+    $query->execute();
+    if (!$query) {
+        databaseError($conn->errorInfo());
+        return Array();
+    }
+    return ($query->fetchColumn() > 0);
+}
+
 function getTripShape($tripID) {
     // todo, use shapes table if shape_id specified
     global $conn;

directory:a/js/FlashCanvas (deleted)
--- a/js/FlashCanvas
+++ /dev/null

--- /dev/null
+++ b/js/flot/excanvas.js
@@ -1,1 +1,1428 @@
-
+// Copyright 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "Lic