Limit number of myway transactions now that up to 100 are available
--- a/aws/awsStartup.sh
+++ b/aws/awsStartup.sh
@@ -1,8 +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
-#postgrtes postgres-server php-pg
+#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/
@@ -11,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
Binary files a/css/images/01-refresh.png and /dev/null differ
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
Binary files a/css/images/102-walk.png and /dev/null differ
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
Binary files a/css/images/28-star.png and /dev/null differ
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
Binary files a/css/images/59-flag.png and /dev/null differ
Binary files a/css/images/60-signpost.png and /dev/null differ
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
@@ -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-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,6 +188,17 @@
</div><!-- /header -->
<a name="maincontent" id="maincontent"></a>
<div data-role="content"> ';
+ if (!$_SESSION['service_id']) {
+ $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()
@@ -224,7 +241,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>
--- 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(pg_result_error($result));
+ return Array();
+ }
+ return pg_fetch_all($result);
+}
+
+function viaPoints($tripid, $stop_sequence = "")
{
global $conn;
- $query = "SELECT stop_name
+ $query = "SELECT stops.stop_id, stop_name, arrival_time
FROM stop_times join stops on stops.stop_id = stop_times.stop_id
WHERE stop_times.trip_id = '$tripid'
".($stop_sequence != "" ? "AND stop_sequence > '$stop_sequence'" : "").
@@ -146,7 +173,14 @@
databaseError(pg_result_error($result));
return Array();
}
- $pointNames = pg_fetch_all($result);
- return r_implode(", ", $pointNames);
+ return pg_fetch_all($result);
+}
+function viaPointNames($tripid, $stop_sequence = "")
+{
+ $viaPointNames = Array();
+ foreach(viaPoints($tripid, $stop_sequence) as $point) {
+ $viaPointNames[] = $point['stop_name'];
+ }
+ return r_implode(", ", $viaPointNames);
}
?>
--- a/index.php
+++ b/index.php
@@ -25,6 +25,7 @@
</ul>
<?php
echo timePlaceSettings();
+echo ' <a href="labs/index.php" data-role="button" data-icon="beaker">Busness R&D</a>';
include_footer(true)
?>
--- /dev/null
+++ b/js/flotr/flotr-0.2.0-alpha.js
@@ -1,1 +1,2 @@
-
+//Flotr 0.2.0-alpha Copyright (c) 2009 Bas Wenneker, <http://solutoire.com>, MIT License.
+var Flotr={version:"0.2.0-alpha",author:"Bas Wenneker",website:"http://www.solutoire.com",_registeredTypes:{lines:"drawSeriesLines",points:"drawSeriesPoints",bars:"drawSeriesBars",candles:"drawSeriesCandles",pie:"drawSeriesPie"},register:function(A,B){Flotr._registeredTypes[A]=B+""},draw:function(B,D,A,C){C=C||Flotr.Graph;return new C(B,D,A)},getSeries:function(A){return A.collect(function(C){var B,C=(C.data)?Object.clone(C):{data:C};for(B=C.data.length-1;B>-1;--B){C.data[B][1]=(C.data[B][1]===null?null:parseFloat(C.data[B][1]))}return C})},merge:function(D,B){var A=B||{};for(var C in D){A[C]=(D[C]!=null&&typeof (D[C])=="object"&&!(D[C].constructor==Array||D[C].constructor==RegExp)&&!Object.isElement(D[C]))?Flotr.merge(D[C],B[C]):A[C]=D[C]}return A},getTickSize:function(E,D,A,B){var H=(A-D)/E;var G=Flotr.getMagnitude(H);var C=H/G;var F=10;if(C<1.5){F=1}else{if(C<2.25){F=2}else{if(C<3){F=((B==0)?2:2.5)}else{if(C<7.5){F=5}}}}return F*G},defaultTickFormatter:function(A){return A+""},defaultTrackFormatter:function(A){return"("+A.x+", "+A.y+")"},defaultPieLabelFormatter:function(A){return(A.fraction*100).toFixed(2)+"%"},getMagnitude:function(A){return Math.pow(10,Math.floor(Math.log(A)/Math.LN10))},toPixel:function(A){return Math.floor(A)+0.5},toRad:function(A){return -A*(Math.PI/180)},parseColor:function(D){if(D instanceof Flotr.Color){return D}var A,C=Flotr.Color;if((A=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(D))){return new C(parseInt(A[1]),parseInt(A[2]),parseInt(A[3]))}if((A=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(D))){return new C(parseInt(A[1]),parseInt(A[2]),parseInt(A[3]),parseFloat(A[4]))}if((A=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(D))){return new C(parseFloat(A[1])*2.55,parseFloat(A[2])*2.55,parseFloat(A[3])*2.55)}if((A=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(D))){return new C(parseFloat(A[1])*2.55,parseFloat(A[2])*2.55,parseFloat(A[3])*2.55,parseFloat(A[4]))}if((A=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(D))){return new C(parseInt(A[1],16),parseInt(A[2],16),parseInt(A[3],16))}if((A=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(D))){return new C(parseInt(A[1]+A[1],16),parseInt(A[2]+A[2],16),parseInt(A[3]+A[3],16))}var B=D.strip().toLowerCase();if(B=="transparent"){return new C(255,255,255,0)}return((A=C.lookupColors[B]))?new C(A[0],A[1],A[2]):false},extractColor:function(B){var A;do{A=B.getStyle("background-color").toLowerCase();if(!(A==""||A=="transparent")){break}B=B.up(0)}while(!B.nodeName.match(/^body$/i));return(A=="rgba(0, 0, 0, 0)")?"transparent":A}};Flotr.Graph=Class.create({initialize:function(B,C,A){this.el=$(B);if(!this.el){throw"The target container doesn't exist"}this.data=C;this.series=Flotr.getSeries(C);this.setOptions(A);this.lastMousePos={pageX:null,pageY:null};this.selection={first:{x:-1,y:-1},second:{x:-1,y:-1}};this.prevSelection=null;this.selectionInterval=null;this.ignoreClick=false;this.prevHit=null;this.constructCanvas();this.initEvents();this.findDataRanges();this.calculateTicks(this.axes.x);this.calculateTicks(this.axes.x2);this.calculateTicks(this.axes.y);this.calculateTicks(this.axes.y2);this.calculateSpacing();this.draw();this.insertLegend();if(this.options.spreadsheet.show){this.constructTabs()}},setOptions:function(B){var P={colors:["#00A8F0","#C0D800","#CB4B4B","#4DA74D","#9440ED"],title:null,subtitle:null,legend:{show:true,noColumns:1,labelFormatter:Prototype.K,labelBoxBorderColor:"#CCCCCC",labelBoxWidth:14,labelBoxHeight:10,labelBoxMargin:5,container:null,position:"nw",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{ticks:null,showLabels:true,labelsAngle:0,title:null,titleAngle:0,noTicks:5,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscaleMargin:0,color:null},x2axis:{},yaxis:{ticks:null,showLabels:true,labelsAngle:0,title:null,titleAngle:90,noTicks:5,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscaleMargin:0,color:null},y2axis:{titleAngle:270},points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#FFFFFF",fillOpacity:0.4},lines:{show:false,lineWidth:2,fill:false,fillColor:null,fillOpacity:0.4},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,fillOpacity:0.4,horizontal:false,stacked:false},candles:{show:false,lineWidth:1,wickLineWidth:1,candleWidth:0.6,fill:true,upFillColor:"#00A8F0",downFillColor:"#CB4B4B",fillOpacity:0.5,barcharts:false},pie:{show:false,lineWidth:1,fill:true,fillColor:null,fillOpacity:0.6,explode:6,sizeRatio:0.6,startAngle:Math.PI/4,labelFormatter:Flotr.defaultPieLabelFormatter,pie3D:false,pie3DviewAngle:(Math.PI/2*0.8),pie3DspliceThickness:20},grid:{color:"#545454",backgroundColor:null,tickColor:"#DDDDDD",labelMargin:3,verticalLines:true,horizontalLines:true,outlineWidth:2},selection:{mode:null,color:"#B6D9FF",fps:20},mouse:{track:false,position:"se",relative:false,trackFormatter:Flotr.defaultTrackFormatter,margin:5,lineColor:"#FF3F19",trackDecimals:1,sensibility:2,radius:3},shadowSize:4,defaultType:"lines",HtmlText:true,fontSize:7.5,spreadsheet:{show:false,tabGraphLabel:"Graph",tabDataLabel:"Data",toolbarDownload:"Download CSV",toolbarSelectAll:"Select all"}};P.x2axis=Object.extend(Object.clone(P.xaxis),P.x2axis);P.y2axis=Object.extend(Object.clone(P.yaxis),P.y2axis);this.options=Flotr.merge((B||{}),P);this.axes={x:{options:this.options.xaxis,n:1},x2:{options:this.options.x2axis,n:2},y:{options:this.options.yaxis,n:1},y2:{options:this.options.y2axis,n:2}};var H=[],C=[],K=this.series.length,N=this.series.length,D=this.options.colors,A=[],G=0,M,J,I,O,E;for(J=N-1;J>-1;--J){M=this.series[J].color;if(M!=null){--N;if(Object.isNumber(M)){H.push(M)}else{A.push(Flotr.parseColor(M))}}}for(J=H.length-1;J>-1;--J){N=Math.max(N,H[J]+1)}for(J=0;C.length<N;){M=(D.length==J)?new Flotr.Color(100,100,100):Flotr.parseColor(D[J]);var F=G%2==1?-1:1;var L=1+F*Math.ceil(G/2)*0.2;M.scale(L,L,L);C.push(M);if(++J>=D.length){J=0;++G}}for(J=0,I=0;J<K;++J){O=this.series[J];if(O.color==null){O.color=C[I++].toString()}else{if(Object.isNumber(O.color)){O.color=C[O.color].toString()}}if(!O.xaxis){O.xaxis=this.axes.x}if(O.xaxis==1){O.xaxis=this.axes.x}else{if(O.xaxis==2){O.xaxis=this.axes.x2}}if(!O.yaxis){O.yaxis=this.axes.y}if(O.yaxis==1){O.yaxis=this.axes.y}else{if(O.yaxis==2){O.yaxis=this.axes.y2}}O.lines=Object.extend(Object.clone(this.options.lines),O.lines);O.points=Object.extend(Object.clone(this.options.points),O.points);O.bars=Object.extend(Object.clone(this.options.bars),O.bars);O.candles=Object.extend(Object.clone(this.options.candles),O.candles);O.pie=Object.extend(Object.clone(this.options.pie),O.pie);O.mouse=Object.extend(Object.clone(this.options.mouse),O.mouse);if(O.shadowSize==null){O.shadowSize=this.options.shadowSize}}},constructCanvas:function(){var C=this.el,B,D,A;this.canvas=C.select(".flotr-canvas")[0];this.overlay=C.select(".flotr-overlay")[0];C.childElements().invoke("remove");C.setStyle({position:"relative",cursor:"default"});this.canvasWidth=C.getWidth();this.canvasHeight=C.getHeight();B={width:this.canvasWidth,height:this.canvasHeight};if(this.canvasWidth<=0||this.canvasHeight<=0){throw"Invalid dimensions for plot, width = "+this.canvasWidth+", height = "+this.canvasHeight}if(!this.canvas){D=this.canvas=new Element("canvas",B);D.className="flotr-canvas";D=D.writeAttribute("style","position:absolute;left:0px;top:0px;")}else{D=this.canvas.writeAttribute(B)}C.insert(D);if(Prototype.Browser.IE){D=window.G_vmlCanvasManager.initElement(D)}this.ctx=D.getContext("2d");if(!this.overlay){A=this.overlay=new Element("canvas",B);A.className="flotr-overlay";A=A.writeAttribute("style","position:absolute;left:0px;top:0px;")}else{A=this.overlay.writeAttribute(B)}C.insert(A);if(Prototype.Browser.IE){A=window.G_vmlCanvasManager.initElement(A)}this.octx=A.getContext("2d");if(window.CanvasText){CanvasText.enable(this.ctx);CanvasText.enable(this.octx);this.textEnabled=true}},getTextDimensions:function(F,C,B,D){if(!F){return{width:0,height:0}}if(!this.options.HtmlText&&this.textEnabled){var E=this.ctx.getTextBounds(F,C);return{width:E.width+2,height:E.height+6}}else{var A=this.el.insert('<div style="position:absolute;top:-10000px;'+B+'" class="'+D+' flotr-dummy-div">'+F+"</div>").select(".flotr-dummy-div")[0];dim=A.getDimensions();A.remove();return dim}},loadDataGrid:function(){if(this.seriesData){return this.seriesData}var A=this.series;var B=[];for(i=0;i<A.length;++i){A[i].data.each(function(D){var C=D[0],F=D[1];if(r=B.find(function(G){return G[0]==C})){r[i+1]=F}else{var E=[];E[0]=C;E[i+1]=F;B.push(E)}})}B=B.sortBy(function(C){return C[0]});return this.seriesData=B},showTab:function(B,C){var A="canvas, .flotr-labels, .flotr-legend, .flotr-legend-bg, .flotr-title, .flotr-subtitle";switch(B){case"graph":this.datagrid.up().hide();this.el.select(A).invoke("show");this.tabs.data.removeClassName("selected");this.tabs.graph.addClassName("selected");break;case"data":this.constructDataGrid();this.datagrid.up().show();this.el.select(A).invoke("hide");this.tabs.data.addClassName("selected");this.tabs.graph.removeClassName("selected");break}},constructTabs:function(){var A=new Element("div",{className:"flotr-tabs-group",style:"position:absolute;left:0px;top:"+this.canvasHeight+"px;width:"+this.canvasWidth+"px;"});this.el.insert({bottom:A});this.tabs={graph:new Element("div",{className:"flotr-tab selected",style:"float:left;"}).update(this.options.spreadsheet.tabGraphLabel),data:new Element("div",{className:"flotr-tab",style:"float:left;"}).update(this.options.spreadsheet.tabDataLabel)};A.insert(this.tabs.graph).insert(this.tabs.data);this.el.setStyle({height:this.canvasHeight+this.tabs.data.getHeight()+2+"px"});this.tabs.graph.observe("click",(function(){this.showTab("graph")}).bind(this));this.tabs.data.observe("click",(function(){this.showTab("data")}).bind(this))},constructDataGrid:function(){if(this.datagrid){return this.datagrid}var D,B,L=this.series,J=this.loadDataGrid();var K=this.datagrid=new Element("table",{className:"flotr-datagrid",style:"height:100px;"});var C=["<colgroup><col />"];var F=['<tr class="first-row">'];F.push("<th> </th>");for(D=0;D<L.length;++D){F.push('<th scope="col">'+(L[D].label||String.fromCharCode(65+D))+"</th>");C.push("<col />")}F.push("</tr>");for(B=0;B<J.length;++B){F.push("<tr>");for(D=0;D<L.length+1;++D){var M="td";var G=(J[B][D]!=null?Math.round(J[B][D]*100000)/100000:"");if(D==0){M="th";var I;if(this.options.xaxis.ticks){var E=this.options.xaxis.ticks.find(function(N){return N[0]==J[B][D]});if(E){I=E[1]}}else{I=this.options.xaxis.tickFormatter(G)}if(I){G=I}}F.push("<"+M+(M=="th"?' scope="row"':"")+"&g