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

Conflicts:
include/common-template.inc.php

file:a/about.php -> file:b/about.php
--- a/about.php
+++ b/about.php
@@ -25,7 +25,7 @@
 All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend, 
 change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site 
 without prior notice. </small>
-<?
+<?php
 include_footer();
 ?>
 

--- a/aws/awsStartup.sh
+++ b/aws/awsStartup.sh
@@ -1,7 +1,8 @@
 #!/bin/bash
 #this script should be run from a fresh git checkout from github
 #ami base must have yum install lighttpd-fastcgi, git, tomcat6 
-#screen php-cli php-gd tomcat6-webapps tomcat6-admin-webapps svn maven2
+#php-cli php-gd tomcat6-webapps tomcat6-admin-webapps svn maven2
+#postgres postgres-server php-pg
 #http://www.how2forge.org/installing-lighttpd-with-php5-and-mysql-support-on-fedora-12
 
 cp /root/aws.php /tmp/
@@ -10,6 +11,8 @@
 chcon -R -h root:object_r:httpd_sys_content_t /var/www/*
 chcon -R -t httpd_sys_content_rw_t /var/www/lib/staticmaplite/cache
 chmod -R 777 /var/www/lib/staticmaplite/cache 
+chcon -R -t httpd_sys_content_rw_t /var/www/labs/tiles
+chmod -R 777 /var/www/labs/tiles
 wget http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \
 -O /var/www/cbrfeed.zip
 

file:b/aws/pg_hba.conf (new)
--- /dev/null
+++ b/aws/pg_hba.conf
@@ -1,1 +1,75 @@
+# PostgreSQL Client Authentication Configuration File
+# ===================================================
+#
+# Refer to the "Client Authentication" section in the
+# PostgreSQL documentation for a complete description
+# of this file.  A short synopsis follows.
+#
+# This file controls: which hosts are allowed to connect, how clients
+# are authenticated, which PostgreSQL user names they can use, which
+# databases they can access.  Records take one of these forms:
+#
+# local      DATABASE  USER  METHOD  [OPTIONS]
+# host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
+# hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
+# hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
+#
+# (The uppercase items must be replaced by actual values.)
+#
+# The first field is the connection type: "local" is a Unix-domain socket,
+# "host" is either a plain or SSL-encrypted TCP/IP socket, "hostssl" is an
+# SSL-encrypted TCP/IP socket, and "hostnossl" is a plain TCP/IP socket.
+#
+# DATABASE can be "all", "sameuser", "samerole", a database name, or
+# a comma-separated list thereof.
+#
+# USER can be "all", a user name, a group name prefixed with "+", or
+# a comma-separated list thereof.  In both the DATABASE and USER fields
+# you can also write a file name prefixed with "@" to include names from
+# a separate file.
+#
+# CIDR-ADDRESS specifies the set of hosts the record matches.
+# It is made up of an IP address and a CIDR mask that is an integer
+# (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that specifies
+# the number of significant bits in the mask.  Alternatively, you can write
+# an IP address and netmask in separate columns to specify the set of hosts.
+#
+# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi", "krb5",
+# "ident", "pam", "ldap" or "cert".  Note that "password" sends passwords
+# in clear text; "md5" is preferred since it sends encrypted passwords.
+#
+# OPTIONS are a set of options for the authentication in the format
+# NAME=VALUE. The available options depend on the different authentication
+# methods - refer to the "Client Authentication" section in the documentation
+# for a list of which options are available for which authentication methods.
+#
+# Database and user names containing spaces, commas, quotes and other special
+# characters must be quoted. Quoting one of the keywords "all", "sameuser" or
+# "samerole" makes the name lose its special character, and just match a
+# database or username with that name.
+#
+# This file is read on server startup and when the postmaster receives
+# a SIGHUP signal.  If you edit the file on a running system, you have
+# to SIGHUP the postmaster for the changes to take effect.  You can use
+# "pg_ctl reload" to do that.
 
+# Put your actual configuration here
+# ----------------------------------
+#
+# If you want to allow non-local connections, you need to add more
+# "host" records. In that case you will also need to make PostgreSQL listen
+# on a non-local interface via the listen_addresses configuration parameter,
+# or via the -i or -h command line switches.
+#
+
+
+
+# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
+
+# "local" is for Unix domain socket connections only
+local   all         all                               trust
+# IPv4 local connections:
+host    all         all         127.0.0.1/32          trust
+# IPv6 local connections:
+host    all         all         ::1/128               trust
+

 Binary files a/css/images/01-refresh.png and /dev/null differ
file:a/css/images/02-redo.png (deleted)
 Binary files a/css/images/02-redo.png and /dev/null differ
 Binary files a/css/images/06-magnify.png and /dev/null differ
 Binary files a/css/images/07-map-marker.png and /dev/null differ
 Binary files a/css/images/101-gameplan.png and /dev/null differ
file:a/css/images/102-walk.png (deleted)
 Binary files a/css/images/102-walk.png and /dev/null differ
file:a/css/images/103-map.png (deleted)
 Binary files a/css/images/103-map.png and /dev/null differ
 Binary files a/css/images/121-landscape.png and /dev/null differ
 Binary files a/css/images/13-target.png and /dev/null differ
 Binary files a/css/images/139-flags.png and /dev/null differ
 Binary files a/css/images/145-persondot.png and /dev/null differ
 Binary files a/css/images/184-warning.png and /dev/null differ
 Binary files a/css/images/193-location-arrow.png and /dev/null differ
file:a/css/images/28-star.png (deleted)
 Binary files a/css/images/28-star.png and /dev/null differ
file:a/css/images/53-house.png (deleted)
 Binary files a/css/images/53-house.png and /dev/null differ
 Binary files a/css/images/55-network.png and /dev/null differ
 Binary files a/css/images/57-download.png and /dev/null differ
 Binary files a/css/images/58-bookmark.png and /dev/null differ
file:a/css/images/59-flag.png (deleted)
 Binary files a/css/images/59-flag.png and /dev/null differ
 Binary files a/css/images/60-signpost.png and /dev/null differ
file:a/css/images/73-radar.png (deleted)
 Binary files a/css/images/73-radar.png and /dev/null differ
 Binary files a/css/images/74-location.png and /dev/null differ
 Binary files a/css/images/83-calendar.png and /dev/null differ
 Binary files /dev/null and b/css/images/91-beaker-2.png differ
--- a/feedback.php
+++ b/feedback.php
@@ -26,7 +26,7 @@
 }
 if (isset($_REQUEST['feedback']) || isset($_REQUEST['newlocation'])){
 	sendEmail("bus.lambda feedback",print_r($_REQUEST,true));
-	echo "<center><h2>Thank you for your feedback!</h2></center>";
+	echo "<h2 style='text-align: center;'>Thank you for your feedback!</h2>";
 } else {
 $stopid = "";
 $stopcode = "";
@@ -48,7 +48,7 @@
 <small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop in one of these boxes </small><br>
 
 Suggested Stop Location (lat/long or words):  <input type="text" name="newlocation"/><br>
-<small> if your device supports javascript, you can pick a location from the map above</small><br>
+<!--<small> if your device supports javascript, you can pick a location from the map above</small><br>-->
 
 <input type="submit" value="Submit!"/>
 </form>

--- a/include/common-db.inc.php
+++ b/include/common-db.inc.php
@@ -1,9 +1,13 @@
 <?php
-  if (isDebugServer()) $conn = pg_connect("dbname=transitdata user=postgres password=snmc");
-  if (php_uname('n') == "actbus-www") $conn = pg_connect("dbname=transitdata user=transitdata password=transitdata host=db.actbus.dotcloud.com port=2242");
+  if (php_uname('n') == "actbus-www") {
+    $conn = pg_connect("dbname=transitdata user=transitdata password=transitdata host=db.actbus.dotcloud.com port=2242");
+  } else if (isDebugServer()) {
+    $conn = pg_connect("dbname=transitdata user=postgres password=snmc");
+  } else {
+    $conn = pg_connect("dbname=transitdata user=transitdata password=transitdata ");
+  }
   if (!$conn) {
-      echo "An error occured.\n";
-      exit;
+      die("A database error occurred.\n");
   }
   
   function databaseError($errMsg) {
@@ -14,3 +18,4 @@
   include('db/trip-dao.inc.php');
   include('db/stop-dao.inc.php');  
   ?>
+

--- a/include/common-geo.inc.php
+++ b/include/common-geo.inc.php
@@ -46,9 +46,9 @@
 		$center = $totalLat / sizeof($mapPoints) . "," . $totalLon / sizeof($mapPoints);
 	}
 	$output = "";
-	if ($collapsible) $output.= '<div data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
-	$output.= '<center><img src="' . curPageURL() . '/lib/staticmaplite/staticmap.php?center=' . $center . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height . '&markers=' . 
-$markers . '" width=' . $width . ' height=' . $height . '></center>';
+	if ($collapsible) $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
+	$output.= '<img class="map" src="' . curPageURL() . '/lib/staticmaplite/staticmap.php?center=' . $center . '&amp;zoom=' . $zoom . '&amp;size=' . $width . 'x' . $height . '&amp;markers=' . 
+$markers . '" width=' . $width . ' height=' . $height . '>';
 	if ($collapsible) $output.= '</div>';
 	return $output;
 }

--- a/include/common-net.inc.php
+++ b/include/common-net.inc.php
@@ -5,7 +5,7 @@
 	$ch = curl_init($url);
 	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 	curl_setopt($ch, CURLOPT_HEADER, 0);
-	curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+	curl_setopt($ch, CURLOPT_TIMEOUT, 45);
 	$page = curl_exec($ch);
 	if (curl_errno($ch)) {
 		echo "<font color=red> Database temporarily unavailable: ";

--- a/include/common-session.inc.php
+++ b/include/common-session.inc.php
@@ -51,6 +51,9 @@
 	session_destroy();
 	session_start();
 }
-debug(print_r($_SESSION, true) , "session");
+//debug(print_r($_SESSION, true) , "session");
 
+function current_time() {
+	return ($_SESSION['time']? $_SESSION['time'] : date("H:i:s"));
+}
 ?>

--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -74,10 +74,14 @@
     .ui-listview-filter {
         margin: 0 !important;
      }
-     .ui-icon-navigation {
+    .ui-icon-navigation {
         background-image: url(css/images/113-navigation.png);
         background-position: 1px 0;
      }
+    .ui-icon-beaker {
+        background-image: url(css/images/91-beaker-2.png);
+        background-position: 1px 0;
+    }
     #footer {
         text-size: 0.75em;
         text-align: center;
@@ -98,6 +102,14 @@
     #extrainfo {
     visibility: hidden;
     display: none;
+    }
+    #servicewarning {
+    padding: 1em;
+    margin-bottom: 0.5em;
+    text-size: 0.2em;
+    background-color: #FF9;
+    -moz-border-radius: 15px;
+border-radius: 15px;
     }
     // source http://webaim.org/techniques/skipnav/
     #skip a, #skip a:hover, #skip a:visited 
@@ -169,12 +181,6 @@
  ';
 	if ($opendiv) {
 		echo '<div data-role="page"> 
- <script>
-$(document).ready(function ()
-{
-    document.title = "' . $pageTitle . '";
-});
-</script>
 	<div data-role="header" data-position="inline">
 	<a href="' . $_SERVER["HTTP_REFERER"] . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a> 
 		<h1>' . $pageTitle . '</h1>
@@ -182,11 +188,22 @@
 	</div><!-- /header -->
         <a name="maincontent" id="maincontent"></a>
         <div data-role="content"> ';
+		$overrides = getServiceOverride();
+		if ($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 
+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>';
+				}
+			}
+		}
 	}
 }
 function include_footer()
 {
-	echo '<div id="footer"><a href="about.php">About/Contact Us</a>&nbsp;<a href="feedback.php">Feedback/Bug Report</a></a>';
+	echo '<div id="footer"><a href="about.php">About/Contact Us</a>&nbsp;<a href="feedback.php">Feedback/Bug Report</a>';
 	echo '</div>';
 	if (isAnalyticsOn()) {
 		echo "<script>  (function() {
@@ -199,7 +216,9 @@
   })();</script>";
 		$googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
 		echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
-	}
+
+	}
+			echo "\n</div></div></body></html>";
 }
 function timePlaceSettings($geolocate = false)
 {
@@ -224,7 +243,7 @@
     		<div data-role="fieldcontain">
 		        <label for="time"> Time: </label>
 		    	<input type="time" name="time" id="time" value="' . (isset($_SESSION['time']) ? $_SESSION['time'] : date("H:i")) . '"/>
-			<a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();' . "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length = 1 ? '0'+ d.getMinutes():  d.getMinutes()));" . '">Current Time?</a>
+			<a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();' . "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length == 1 ? '0'+ d.getMinutes():  d.getMinutes()));" . '">Current Time?</a>
 	        </div>
 		<div data-role="fieldcontain">
 		    <label for="service_period"> Service Period:  </label>
@@ -233,12 +252,12 @@
 		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>
+			<a href="#" style="display:none" name="currentPeriod" id="currentPeriod">Current Period?</a>
 		</div>
 		
 		<input type="submit" value="Update"/>
-                </form>
-            </div></div>';
+                </div></form>
+            </div>';
 }
 function trackEvent($category, $action, $label = "", $value = - 1)
 {

--- a/include/common-transit.inc.php
+++ b/include/common-transit.inc.php
@@ -4,9 +4,26 @@
 	'saturday',
 	'weekday'
 );
+function getServiceOverride() {
+	global $conn;
+	$query = "Select * from calendar_dates where date = '".date("Ymd")."' and exception_type = '1'";
+	 debug($query,"database");
+	$result = pg_query($conn, $query);
+	if (!$result) {
+		databaseError(pg_result_error($result));
+		return Array();
+	}
+	return pg_fetch_assoc($result);
+}
 function service_period()
 {
+	
 	if (isset($_SESSION['service_period'])) return $_SESSION['service_period'];
+	$override = getServiceOverride();
+	if ($override['service_id']){
+		return $override['service_id'];
+	}
+
 	switch (date('w')) {
 	case 0:
 		return 'sunday';
@@ -16,5 +33,24 @@
 		return 'weekday';
 	}
 }
+function midnight_seconds()
+{
+	// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html
+	if (isset($_SESSION['time'])) {
+		$time = strtotime($_SESSION['time']);
+		return (date("G", $time) * 3600) + (date("i", $time) * 60) + date("s", $time);
+	}
+	return (date("G") * 3600) + (date("i") * 60) + date("s");
+}
+function midnight_seconds_to_time($seconds)
+{
+	if ($seconds > 0) {
+		$midnight = mktime(0, 0, 0, date("n") , date("j") , date("Y"));
+		return date("h:ia", $midnight + $seconds);
+	}
+	else {
+		return "";
+	}
+}
+?>
 
-?>

--- a/include/db/route-dao.inc.php
+++ b/include/db/route-dao.inc.php
@@ -1,6 +1,7 @@
 <?php
 
 function getRoute($routeID) {
+		global $conn;
         $query = "Select * from routes where route_id = '$routeID' LIMIT 1";
         debug($query,"database");
 	$result = pg_query($conn, $query);
@@ -40,23 +41,49 @@
 }
 
 function getRouteNextTrip($routeID) {
-    global $conn;
+     global $conn;
     $query = "select * 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 > CURRENT_TIME and routes.route_id = '$routeID' order by
+arrival_time > '".current_time()."' and routes.route_id = '$routeID' order by
 arrival_time limit 1";
         debug($query,"database");
 	$result = pg_query($conn, $query);
-	if (!$result) {
+	if (!$result) {   
 		databaseError(pg_result_error($result));
 		return Array();
 	}
-	return pg_fetch_assoc($result);       
+        $r = pg_fetch_assoc($result);   
+        // past last trip of the day special case
+       if (sizeof($r) == 0) {
+            $query = "select * from routes join trips on trips.route_id = routes.route_id
+join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = '$routeID' order by
+arrival_time DESC limit 1";
+        debug($query,"database");
+	$result = pg_query($conn, $query);
+	if (!$result) {   
+		databaseError(pg_result_error($result));
+		return Array();
+	}
+        $r = pg_fetch_assoc($result); 
+       }
+	return $r;       
   }
+  
+  function getTimeInterpolatedRouteAtStop($routeID, $stop_id)
+{
+    $nextTrip = getRouteNextTrip($routeID);
+    if ($nextTrip['trip_id']){
+    	foreach (getTimeInterpolatedTrip($nextTrip['trip_id']) as $tripStop) {
+		if ($tripStop['stop_id'] == $stop_id) return $tripStop;
+	}
+    }
+	return Array();
+}
+  
 function getRouteTrips($routeID) {
         global $conn;
-    $query = "select * from routes join trips on trips.route_id = routes.route_id
-join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = '$routeID' order by
+    $query = "select routes.route_id,trips.trip_id,service_id,arrival_time, stop_id, stop_sequence from routes join trips on trips.route_id = routes.route_id
+join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = '$routeID' and stop_sequence = '1' order by
 arrival_time ";
         debug($query,"database");
 	$result = pg_query($conn, $query);
@@ -112,7 +139,7 @@
                  if ($service_period == "") $service_period = service_period();
                   if ($limit != "") $limit = " LIMIT $limit "; 
     global $conn;
-        $query = "SELECT service_id,trips.route_id,route_short_name,route_long_name,
+        $query = "SELECT service_id,trips.route_id,route_short_name,route_long_name,min(stops.stop_id) as stop_id,
         min(ST_Distance(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), FALSE)) as distance
 FROM stop_times
 join trips on trips.trip_id = stop_times.trip_id

--- a/include/db/stop-dao.inc.php
+++ b/include/db/stop-dao.inc.php
@@ -84,18 +84,17 @@
 	$afterCondition = "AND arrival_time > '$afterTime'";
 	global $conn;
 	if ($afterTime != "") {
-		$query = " SELECT stop_times.trip_id,stop_times.arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,route_short_name,route_long_name, start_times.arrival_time as start_time
+		$query = " SELECT stop_times.trip_id,stop_times.arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,route_short_name,route_long_name, end_times.arrival_time as end_time
 FROM stop_times
 join trips on trips.trip_id =
 stop_times.trip_id
-join routes on trips.route_id = routes.route_id , (SELECT trip_id,arrival_time from stop_times
-	WHERE stop_times.arrival_time IS NOT NULL
-	AND stop_sequence = '1') as start_times 
+join routes on trips.route_id = routes.route_id , (SELECT trip_id,max(arrival_time) as arrival_time from stop_times
+	WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times 
 WHERE stop_times.stop_id = '$stopID'
-AND stop_times.trip_id = start_times.trip_id
+AND stop_times.trip_id = end_times.trip_id
 AND service_id='$service_period'
-AND start_times.arrival_time > '$afterTime'
-ORDER BY start_time";
+AND end_times.arrival_time > '$afterTime'
+ORDER BY end_time";
 	}
 	else {
 		$query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,route_short_name,route_long_name
@@ -115,15 +114,16 @@
 	}
 	return pg_fetch_all($result);
 }
-function getStopTripsWithTimes($stopID, $time = "", $service_period = "", $time_range = "")
+function getStopTripsWithTimes($stopID, $time = "", $service_period = "", $time_range = "", $limit = "")
 {
 	if ($service_period == "") $service_period = service_period();
 	if ($time_range == "") $time_range = (24 * 60 * 60);
-	if ($time == "") $time = ($_SESSION['time'] ? $_SESSION['time'] : date("H:i:s"));
+	if ($time == "") $time = current_time();
 	if ($limit == "") $limit = 10;
 	$trips = getStopTrips($stopID, $service_period, $time);
 	$timedTrips = Array();
-	foreach ($trips as $trip) {
+	if ($trips && sizeof($trips) > 0) {
+            foreach ($trips as $trip) {
 		if ($trip['arrival_time'] != "") {
 			if (strtotime($trip['arrival_time']) > strtotime($time) and strtotime($trip['arrival_time']) < (strtotime($time) + $time_range)) {
 				$timedTrips[] = $trip;
@@ -138,6 +138,7 @@
 		if (sizeof($timedTrips) > $limit) break;
 	}
 	sktimesort($timedTrips, "arrival_time", true);
+        }
 	return $timedTrips;
 }
 ?>

--- a/include/db/trip-dao.inc.php
+++ b/include/db/trip-dao.inc.php
@@ -49,7 +49,7 @@
 	       points.append((stop.stop_lat, stop.stop_lon))
 	   return points*/
 }
-function getTimeInterpolatedTrip($tripID)
+function getTimeInterpolatedTrip($tripID, $range = "")
 {
 	global $conn;
 	$query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_lat,stop_lon,stop_name,stop_code,
@@ -58,7 +58,7 @@
 join trips on trips.trip_id = stop_times.trip_id
 join routes on trips.route_id = routes.route_id
 join stops on stops.stop_id = stop_times.stop_id
-WHERE trips.trip_id = '$tripID' ORDER BY stop_sequence";
+WHERE trips.trip_id = '$tripID' $range ORDER BY stop_sequence";
 	debug($query, "database");
 	$result = pg_query($conn, $query);
 	if (!$result) {
@@ -111,7 +111,18 @@
 }
 function getTimeInterpolatedTripAtStop($tripID, $stop_sequence)
 {
-    	foreach (getTimeInterpolatedTrip($tripID) as $tripStop) {
+    global $conn;
+    // limit interpolation to between nearest actual points.
+    $prevTimePoint = pg_fetch_assoc(pg_query($conn," SELECT trip_id,stop_id,
+	stop_sequence
+FROM stop_times
+WHERE trip_id = '$tripID' and stop_sequence < $stop_sequence and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence DESC LIMIT 1"));
+    $nextTimePoint = pg_fetch_assoc(pg_query($conn," SELECT trip_id,stop_id,
+	stop_sequence
+FROM stop_times
+WHERE trip_id = '$tripID' and stop_sequence > $stop_sequence and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence LIMIT 1"));
+    $range = "AND stop_sequence >= '{$prevTimePoint['stop_sequence']}' AND stop_sequence <= '{$nextTimePoint['stop_sequence']}'";
+    	foreach (getTimeInterpolatedTrip($tripID,$range) as $tripStop) {
 		if ($tripStop['stop_sequence'] == $stop_sequence) return $tripStop;
 	}
 	return Array();
@@ -132,10 +143,26 @@
 	$r = pg_fetch_assoc($result);
 	return $r['arrival_time'];
 }
-function viaPointNames($tripid, $stop_sequence = "")
+function getActiveTrips($time)
+{
+    	global $conn;
+	if ($time == "") $time = current_time();
+	$query = "Select distinct stop_times.trip_id, start_times.arrival_time as start_time, end_times.arrival_time as end_time from stop_times, (SELECT trip_id,arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL
+AND stop_sequence = '1') as start_times, (SELECT trip_id,max(arrival_time) as arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times
+WHERE start_times.trip_id = end_times.trip_id AND stop_times.trip_id = end_times.trip_id AND $time > start_times.arrival_time  AND $time < end_times.arrival_time";
+	debug($query, "database");
+	$result = pg_query($conn, $query);
+	if (!$result) {
+		databaseError(