700,
"height"=>460,
"image" => array(
"width"=>264,
"height"=>220,
"topOffset"=>20,
),
"imageText" => array(
"width"=>400,
"height"=>30,
"topOffset"=>20,
),
"graph" => array(
"width"=>600,
"height"=>160,
"topOffset"=>30,
),
"title" => array(
"topOffset"=>50
),
"key" => array(
"topOffset"=>50
),
"axes" => array(
"x" => array(
"height" => 20,
),
"y" => array(
"width" => 30,
),
),
"grid" => array(
"x" => array(
"major" => array(
"max" => 12,
"min" => 4,
),
"minor" => array(
"max" => 48,
"min" => 12,
),
),
"y" => array(
"major" => array(
"max" => 8,
"min" => 1,
),
"minor" => array(
"max" => 0,
"min" => 0,
),
),
),
);
$monitors = array();
$monitorsSql = "select * from Monitors order by Sequence asc";
//srand( 97981 );
foreach( dbFetchAll( $monitorsSql ) as $row )
{
//if ( empty($row['WebColour']) )
//{
//$row['WebColour'] = sprintf( "#%02x%02x%02x", rand( 0, 255 ), rand( 0, 255), rand( 0, 255 ) );
//}
$monitors[$row['Id']] = $row;
}
$rangeSql = "select min(E.StartTime) as MinTime, max(E.EndTime) as MaxTime from Events as E inner join Monitors as M on (E.MonitorId = M.Id) where not isnull(E.StartTime) and not isnull(E.EndTime)";
$eventsSql = "select E.Id,E.Name,E.StartTime,E.EndTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId from Events as E inner join Monitors as M on (E.MonitorId = M.Id) where not isnull(StartTime)";
if ( !empty($user['MonitorIds']) )
{
$monFilterSql = ' AND M.Id IN ('.$user['MonitorIds'].')';
$rangeSql .= $monFilterSql;
$eventsSql .= $monFilterSql;
}
if ( isset($_REQUEST['filter']) )
$tree = parseFilterToTree( $_REQUEST['filter'] );
else
$tree = false;
if ( isset($_REQUEST['range']) )
$range = validHtmlStr($_REQUEST['range']);
if ( isset($_REQUEST['minTime']) )
$minTime = validHtmlStr($_REQUEST['minTime']);
if ( isset($_REQUEST['midTime']) )
$midTime = validHtmlStr($_REQUEST['midTime']);
if ( isset($_REQUEST['maxTime']) )
$maxTime = validHtmlStr($_REQUEST['maxTime']);
if ( isset($range) )
{
$halfRange = (int)($range/2);
if ( isset($midTime) )
{
$midTimeT = strtotime($midTime);
$minTimeT = $midTimeT-$halfRange;
$maxTimeT = $midTimeT+$halfRange;
if ( !($range%1) )
{
$maxTimeT--;
}
$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT );
$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT );
}
elseif ( isset($minTime) )
{
$minTimeT = strtotime($minTime);
$maxTimeT = $minTimeT + $range;
$midTimeT = $minTimeT + $halfRange;
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT );
}
elseif ( isset($maxTime) )
{
$maxTimeT = strtotime($maxTime);
$minTimeT = $maxTimeT - $range;
$midTimeT = $minTimeT + $halfRange;
$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT );
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
}
}
elseif ( isset($minTime) && isset($maxTime) )
{
$minTimeT = strtotime($minTime);
$maxTimeT = strtotime($maxTime);
$range = ($maxTimeT - $minTimeT) + 1;
$halfRange = (int)($range/2);
$midTimeT = $minTimeT + $halfRange;
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
}
if ( isset($minTime) && isset($maxTime) )
{
$tempMinTime = $tempMaxTime = $tempExpandable = false;
extractDatetimeRange( $tree, $tempMinTime, $tempMaxTime, $tempExpandable );
$filterSql = parseTreeToSQL( $tree );
if ( $filterSql )
{
$filterSql = " and $filterSql";
$eventsSql .= $filterSql;
}
}
else
{
$filterSql = parseTreeToSQL( $tree );
$tempMinTime = $tempMaxTime = $tempExpandable = false;
extractDatetimeRange( $tree, $tempMinTime, $tempMaxTime, $tempExpandable );
if ( $filterSql )
{
$filterSql = " and $filterSql";
$rangeSql .= $filterSql;
$eventsSql .= $filterSql;
}
if ( !isset($minTime) || !isset($maxTime) )
{
// Dynamically determine range
$row = dbFetchOne( $rangeSql );
if ( !isset($minTime) )
$minTime = $row['MinTime'];
if ( !isset($maxTime) )
$maxTime = $row['MaxTime'];
}
if ( empty($minTime) )
$minTime = $tempMinTime;
if ( empty($maxTime) )
$maxTime = $tempMaxTime;
if ( empty($maxTime) )
$maxTime = "now";
$minTimeT = strtotime($minTime);
$maxTimeT = strtotime($maxTime);
$range = ($maxTimeT - $minTimeT) + 1;
$halfRange = (int)($range/2);
$midTimeT = $minTimeT + $halfRange;
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
}
//echo "MnT: $tempMinTime, MxT: $tempMaxTime, ExP: $tempExpandable
";
if ( $tree )
{
appendDatetimeRange( $tree, $minTime, $maxTime );
$filterQuery = parseTreeToQuery( $tree );
}
else
{
$filterQuery = false;
}
$scales = array(
array( "name"=>"year", "factor"=>60*60*24*365, "align"=>1, "zoomout"=>2, "label"=>STRF_TL_AXIS_LABEL_YEAR ),
array( "name"=>"month", "factor"=>60*60*24*30, "align"=>1, "zoomout"=>12, "label"=>STRF_TL_AXIS_LABEL_MONTH ),
array( "name"=>"week", "factor"=>60*60*24*7, "align"=>1, "zoomout"=>4.25, "label"=>STRF_TL_AXIS_LABEL_WEEK, "labelCheck"=>"%W" ),
array( "name"=>"day", "factor"=>60*60*24, "align"=>1, "zoomout"=>7, "label"=>STRF_TL_AXIS_LABEL_DAY ),
array( "name"=>"hour4", "factor"=>60*60, "align"=>4, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_4HOUR, "labelCheck"=>"%H" ),
array( "name"=>"hour", "factor"=>60*60, "align"=>1, "zoomout"=>4, "label"=>STRF_TL_AXIS_LABEL_HOUR, "labelCheck"=>"%H" ),
array( "name"=>"minute10", "factor"=>60, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10MINUTE, "labelCheck"=>"%M" ),
array( "name"=>"minute", "factor"=>60, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_MINUTE, "labelCheck"=>"%M" ),
array( "name"=>"second10", "factor"=>1, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10SECOND ),
array( "name"=>"second", "factor"=>1, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_SECOND ),
);
$majXScale = getDateScale( $scales, $range, $chart['grid']['x']['major']['min'], $chart['grid']['x']['major']['max'] );
// Adjust the range etc for scale
$minTimeT -= $minTimeT%($majXScale['factor']*$majXScale['align']);
$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT );
$maxTimeT += (($majXScale['factor']*$majXScale['align'])-$maxTimeT%($majXScale['factor']*$majXScale['align']))-1;
if ( $maxTimeT > time() )
$maxTimeT = time();
$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT );
$range = ($maxTimeT - $minTimeT) + 1;
$halfRange = (int)($range/2);
$midTimeT = $minTimeT + $halfRange;
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
//echo "R:$range
";
//echo "MnT:$minTime
";
//echo "MnTt:$minTimeT
";
//echo "MdT:$midTime
";
//echo "MdTt:$midTimeT
";
//echo "MxT:$maxTime
";
//echo "MxTt:$maxTimeT
";
if ( isset($minTime) && isset($maxTime) )
{
$eventsSql .= " and E.EndTime >= '$minTime' and E.StartTime <= '$maxTime'";
}
$eventsSql .= " order by Id asc";
//echo "ESQL: $eventsSql
";
$chart['data'] = array(
"x" => array(
"lo" => strtotime( $minTime ),
"hi" => strtotime( $maxTime ),
),
"y" => array(
"lo" => 0,
"hi" => 0,
)
);
$chart['data']['x']['range'] = ($chart['data']['x']['hi'] - $chart['data']['x']['lo']) + 1;
$chart['data']['x']['density'] = $chart['data']['x']['range']/$chart['graph']['width'];
$monEventSlots = array();
$monFrameSlots = array();
$monitorIds = array();
foreach( dbFetchAll( $eventsSql ) as $event )
{
if ( !isset($monitorIds[$event['MonitorId']]) )
$monitorIds[$event['MonitorId']] = true;
if ( !isset($monEventSlots[$event['MonitorId']]) )
$monEventSlots[$event['MonitorId']] = array();
if ( !isset($monFrameSlots[$event['MonitorId']]) )
$monFrameSlots[$event['MonitorId']] = array();
$currEventSlots = &$monEventSlots[$event['MonitorId']];
$currFrameSlots = &$monFrameSlots[$event['MonitorId']];
$startTimeT = strtotime($event['StartTime']);
$startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
if ( $startIndex < 0 )
$startIndex = 0;
if ( isset($event['EndTime']) )
$endTimeT = strtotime($event['EndTime']);
else
$endTimeT = time();
$endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
if ( $endIndex >= $chart['graph']['width'] )
$endIndex = $chart['graph']['width'] - 1;
for ( $i = $startIndex; $i <= $endIndex; $i++ )
{
if ( !isset($currEventSlots[$i]) )
{
if ( $rawStartIndex == $rawEndIndex )
{
$offset = 1;
}
else
{
$offset = 1 + ($event['Frames']?((int)(($event['Frames']-1)*(($i-$rawStartIndex)/($rawEndIndex-$rawStartIndex)))):0);
}
$currEventSlots[$i] = array( "count"=>0, "width"=>1, "offset"=>$offset, "event"=>$event );
}
else
{
$currEventSlots[$i]['count']++;
}
}
if ( $event['MaxScore'] > 0 )
{
if ( $startIndex == $endIndex )
{
$framesSql = "select FrameId,Score from Frames where EventId = ? and Score > 0 order by Score desc limit 1";
$frame = dbFetchOne( $framesSql, NULL, array($event['Id']) );
$i = $startIndex;
if ( !isset($currFrameSlots[$i]) )
{
$currFrameSlots[$i] = array( "count"=>1, "value"=>$event['MaxScore'], "event"=>$event, "frame"=>$frame );
}
else
{
$currFrameSlots[$i]['count']++;
if ( $event['MaxScore'] > $currFrameSlots[$i]['value'] )
{
$currFrameSlots[$i]['value'] = $event['MaxScore'];
$currFrameSlots[$i]['event'] = $event;
$currFrameSlots[$i]['frame'] = $frame;
}
}
if ( $event['MaxScore'] > $chart['data']['y']['hi'] )
{
$chart['data']['y']['hi'] = $event['MaxScore'];
}
}
else
{
$framesSql = "select FrameId,Delta,unix_timestamp(TimeStamp) as TimeT,Score from Frames where EventId = ? and Score > 0";
$result = dbQuery( $framesSql, array( $event['Id'] ) );
while( $frame = dbFetchNext( $result ) )
{
if ( $frame['Score'] == 0 )
continue;
$frameTimeT = $frame['TimeT'];
$frameTimeT = $startTimeT + $frame['Delta'];
$frameIndex = (int)(($frameTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
if ( $frameIndex < 0 )
continue;
if ( $frameIndex >= $chart['graph']['width'] )
continue;
if ( !isset($currFrameSlots[$frameIndex]) )
{
$currFrameSlots[$frameIndex] = array( "count"=>1, "value"=>$frame['Score'], "event"=>$event, "frame"=>$frame );
}
else
{
$currFrameSlots[$frameIndex]['count']++;
if ( $frame['Score'] > $currFrameSlots[$frameIndex]['value'] )
{
$currFrameSlots[$frameIndex]['value'] = $frame['Score'];
$currFrameSlots[$frameIndex]['event'] = $event;
$currFrameSlots[$frameIndex]['frame'] = $frame;
}
}
if ( $frame['Score'] > $chart['data']['y']['hi'] )
{
$chart['data']['y']['hi'] = $frame['Score'];
}
}
}
}
}
ksort( $monitorIds, SORT_NUMERIC );
ksort( $monEventSlots, SORT_NUMERIC );
ksort( $monFrameSlots, SORT_NUMERIC );
// No longer needed?
if ( false )
{
// Add on missing frames
foreach( array_keys($monFrameSlots) as $monitorId )
{
unset( $currFrameSlots );
$currFrameSlots = &$monFrameSlots[$monitorId];
for ( $i = 0; $i < $chart['graph']['width']; $i++ )
{
if ( isset($currFrameSlots[$i]) )
{
if ( !isset($currFrameSlots[$i]['frame']) )
{
$framesSql = "select FrameId,Score from Frames where EventId = ? and Score > 0 order by FrameId limit 1";
$currFrameSlots[$i]['frame'] = dbFetchOne( $framesSql, NULL, array( $currFrameSlots[$i]['event']['Id'] ) );
}
}
}
}
}
$chart['data']['y']['range'] = ($chart['data']['y']['hi'] - $chart['data']['y']['lo']) + 1;
$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['height'];
$majYScale = getYScale( $chart['data']['y']['range'], $chart['grid']['y']['major']['min'], $chart['grid']['y']['major']['max'] );
$maxWidth = 0;
$maxHeight = 0;
foreach ( array_keys($monitorIds) as $monitorId )
{
if ( $maxWidth < $monitors[$monitorId]['Width'] )
$maxWidth = $monitors[$monitorId]['Width'];
if ( $maxHeight < $monitors[$monitorId]['Height'] )
$maxHeight = $monitors[$monitorId]['Height'];
}
//print_r( $monEventSlots );
// Optimise boxes
foreach( array_keys($monEventSlots) as $monitorId )
{
unset( $currEventSlots );
$currEventSlots = &$monEventSlots[$monitorId];
for ( $i = 0; $i < $chart['graph']['width']; $i++ )
{
if ( isset($currEventSlots[$i]) )
{
if ( isset($currSlot) )
{
if ( $currSlot['event']['Id'] == $currEventSlots[$i]['event']['Id'] )
{
if ( $currSlot['width'] < $maxEventWidth )
{
// Merge slots for the same long event
$currSlot['width']++;
unset( $currEventSlots[$i] );
continue;
}
elseif ( $currSlot['offset'] < $currEventSlots[$i]['offset'] )
{
// Split very long events
$currEventSlots[$i]['frame'] = array( 'FrameId'=>$currEventSlots[$i]['offset'] );
}
}
elseif ( $currSlot['width'] < $minEventWidth )
{
// Merge multiple small events
$currSlot['width']++;
unset( $currEventSlots[$i] );
continue;
}
}
$currSlot = &$currEventSlots[$i];
}
else
{
unset( $currSlot );
}
}
if ( isset( $currSlot ) )
unset( $currSlot );
}
//print_r( $monEventSlots );
// Stack events
$frameSlots = array();
$frameMonitorIds = array_keys($monFrameSlots);
for ( $i = 0; $i < $chart['graph']['width']; $i++ )
{
foreach ( $frameMonitorIds as $frameMonitorId )
{
unset( $currFrameSlots );
$currFrameSlots = &$monFrameSlots[$frameMonitorId];
if ( isset($currFrameSlots[$i]) )
{
if ( !isset($frameSlots[$i]) )
{
$frameSlots[$i] = array();
$frameSlots[$i][] = &$currFrameSlots[$i];
}
else
{
$slotCount = count($frameSlots[$i]);
for ( $j = 0; $j < $slotCount; $j++ )
{
if ( $currFrameSlots[$i]['value'] > $frameSlots[$i][$j]['value'] )
{
for ( $k = $slotCount; $k > $j; $k-- )
{
$frameSlots[$i][$k] = $frameSlots[$i][$k-1];
}
$frameSlots[$i][$j] = &$currFrameSlots[$i];
break 2;
}
}
$frameSlots[$i][] = &$currFrameSlots[$i];
}
}
}
}
//print_r( $monEventSlots );
//print_r( $monFrameSlots );
//print_r( $chart );
$graphHeight = $chart['graph']['height'];
if ( $mode == "overlay" )
{
$minEventBarHeight = 10;
$maxEventBarHeight = 40;
if ( count($monitorIds) )
{
$chart['graph']['eventBarHeight'] = $minEventBarHeight;
while ( ($chart['graph']['eventsHeight'] = (($chart['graph']['eventBarHeight'] * count($monitorIds)) + (count($monitorIds)-1))) < $maxEventBarHeight )
{
$chart['graph']['eventBarHeight']++;
}
}
else
{
$chart['graph']['eventBarHeight'] = $maxEventBarHeight;
$chart['graph']['eventsHeight'] = $maxEventBarHeight;
}
$chart['graph']['activityHeight'] = ($graphHeight - $chart['graph']['eventsHeight']);
$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['activityHeight'];
$chart['eventBars'] = array();
$top = $chart['graph']['activityHeight'];
foreach ( array_keys($monitorIds) as $monitorId )
{
$chart['eventBars'][$monitorId] = array( 'top' => $top );
$top += $chart['graph']['eventBarHeight']+1;
}
}
elseif ( $mode == "split" )
{
$minActivityBarHeight = 30;
$minEventBarHeight = 10;
$maxEventBarHeight = 40;
if ( count($monitorIds) )
{
$chart['graph']['eventBarHeight'] = $minEventBarHeight;
$chart['graph']['activityBarHeight'] = $minActivityBarHeight;
while ( ((($chart['graph']['eventBarHeight']+$chart['graph']['activityBarHeight']) * count($monitorIds)) + ((2*count($monitorIds))-1)) < $graphHeight )
{
$chart['graph']['activityBarHeight']++;
if ( $chart['graph']['eventBarHeight'] < $maxEventBarHeight )
{
$chart['graph']['eventBarHeight']++;
}
}
}
else
{
$chart['graph']['eventBarHeight'] = $maxEventBarHeight;
$chart['graph']['activityBarHeight'] = $graphHeight - $chart['graph']['eventBarHeight'];
}
$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['activityBarHeight'];
?>
$top );
$chart['eventBars'][$monitorId] = array( 'top' => $top+$chart['graph']['activityBarHeight']+1 );
$top += $chart['graph']['activityBarHeight']+1+$chart['graph']['eventBarHeight']+1;
}
}
preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $minTime, $startMatches );
preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $maxTime, $endMatches );
if ( $startMatches[1] != $endMatches[1] )
{
// Different years
$title = strftime( STRF_TL_AXIS_RANGE_YEAR1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_YEAR2, $chart['data']['x']['hi'] );
}
elseif ( $startMatches[2] != $endMatches[2] )
{
// Different months
$title = strftime( STRF_TL_AXIS_RANGE_MONTH1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_MONTH2, $chart['data']['x']['hi'] );
}
elseif ( $startMatches[3] != $endMatches[3] )
{
// Different dates
$title = strftime( STRF_TL_AXIS_RANGE_DAY1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_DAY2, $chart['data']['x']['hi'] );
}
else
{
// Different times
$title = strftime( STRF_TL_AXIS_RANGE_TIME1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_TIME2, $chart['data']['x']['hi'] );
}
function drawXGrid( $chart, $scale, $labelClass, $tickClass, $gridClass, $zoomClass=false )
{
ob_start();
$labelCount = 0;
$lastTick = 0;
unset( $lastLabel );
$labelCheck = isset($scale['labelCheck'])?$scale['labelCheck']:$scale['label'];
?>