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(); # The as E, and joining with Monitors is required for the filterSQL filters. $rangeSql = 'SELECT min(E.StartDateTime) AS MinTime, max(E.EndDateTime) AS MaxTime FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(E.StartDateTime) AND NOT isnull(E.EndDateTime)'; $eventsSql = 'SELECT E.* FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartDateTime)'; $eventIdsSql = 'SELECT E.Id FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartDateTime)'; $eventsValues = array(); if ( !empty($user['MonitorIds']) ) { $monFilterSql = ' AND MonitorId IN ('.$user['MonitorIds'].')'; $rangeSql .= $monFilterSql; $eventsSql .= $monFilterSql; $eventIdsSql .= $monFilterSql; } $tree = false; if ( isset($_REQUEST['filter']) ) { $filter = ZM\Filter::parse($_REQUEST['filter']); $tree = $filter->tree(); ZM\Debug('Parse tree: ' . print_r($tree,true)); } 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) and validInt($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; $eventIdsSql .= $filterSql; } } else { $filterSql = parseTreeToSQL($tree); $tempMinTime = $tempMaxTime = $tempExpandable = false; extractDatetimeRange($tree, $tempMinTime, $tempMaxTime, $tempExpandable); if ( $filterSql ) { $filterSql = " AND $filterSql"; $rangeSql .= $filterSql; $eventsSql .= $filterSql; $eventIdsSql .= $filterSql; } if ( !isset($minTime) || !isset($maxTime) ) { // Dynamically determine range $row = dbFetchOne($rangeSql); if ( $row ) { if ( !isset($minTime) ) $minTime = $row['MinTime']; if ( !isset($maxTime) ) $maxTime = $row['MaxTime']; } else { # Errors will be reported by db functions } } 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); if ( isset($minTime) && isset($maxTime) ) { $eventsSql .= " AND EndDateTime >= '$minTime' AND StartDateTime <= '$maxTime'"; $eventIdsSql .= " AND EndDateTime >= '$minTime' AND StartDateTime <= '$maxTime'"; } if ( 0 ) { $framesByEventId = array(); $eventsSql .= ' ORDER BY E.Id ASC'; $framesSql = "SELECT EventId,FrameId,Delta,Score FROM Frames WHERE EventId IN($eventIdsSql) AND Score > 0 ORDER BY Score DESC"; $frames_result = dbQuery($framesSql); while ( $row = $frames_result->fetch(PDO::FETCH_ASSOC) ) { if ( !isset($framesByEventId[$row['EventId']]) ) { $framesByEventId[$row['EventId']] = array(); } $framesByEventId[$row['EventId']][] = $row; } } $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(); $events_result = dbQuery($eventsSql); if ( !$events_result ) { ZM\Fatal('SQL-ERR'); return; } $max_aspect_ratio = 0; while( $event = $events_result->fetch(PDO::FETCH_ASSOC) ) { if ( !isset($monitors[$event['MonitorId']]) ) { $monitor = $monitors[$event['MonitorId']] = ZM\Monitor::find_one(array('Id'=>$event['MonitorId'])); $monEventSlots[$event['MonitorId']] = array(); $monFrameSlots[$event['MonitorId']] = array(); $aspect_ratio = round($monitor->Width() / $monitor->Height(), 2); if ( $aspect_ratio > $max_aspect_ratio ) $max_aspect_ratio = $aspect_ratio; } $currEventSlots = &$monEventSlots[$event['MonitorId']]; $currFrameSlots = &$monFrameSlots[$event['MonitorId']]; $startTimeT = strtotime($event['StartDateTime']); $startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']); if ( $startIndex < 0 ) $startIndex = 0; if ( isset($event['EndDateTime']) ) $endTimeT = strtotime($event['EndDateTime']); 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 ) { # Only fills 1 slot, so just get the max Score $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 { # Fills multiple Slots, so need multiple scores to generate the graph over multiple slots. $framesSql = 'SELECT FrameId,Delta,Score FROM Frames WHERE EventId = ? AND Score > 0'; $result = dbQuery($framesSql, array($event['Id'])); while ( $frame = dbFetchNext($result) ) { #foreach ( $framesByEventId[$event['Id']] as $frame ) { $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']; } } // end foreach frame } } // end if MaxScore > 0 } // end foreach event //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']); // 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; } else if ( $currSlot['offset'] < $currEventSlots[$i]['offset'] ) { // Split very long events $currEventSlots[$i]['frame'] = array( 'FrameId'=>$currEventSlots[$i]['offset'] ); } } else if ( $currSlot['width'] < $minEventWidth ) { // Merge multiple small events $currSlot['width']++; unset( $currEventSlots[$i] ); continue; } } $currSlot = &$currEventSlots[$i]; } else { unset($currSlot); } } # end foreach x unset($currSlot); } // end foreach Event Monitors //print_r( $monEventSlots ); // Stack events $frameSlots = array(); $frameMonitorIds = array_keys($monFrameSlots); for ( $i = 0; $i < $chart['graph']['width']; $i++ ) { foreach ( $frameMonitorIds as $frameMonitorId ) { $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]; } } unset($currFrameSlots); } # end foreach MonitorId } # end foreach x //ZM\Debug(print_r( $monEventSlots,true )); //print_r( $monFrameSlots ); //print_r( $chart ); $graphHeight = $chart['graph']['height']; if ( $mode == 'overlay' ) { $minEventBarHeight = 10; $maxEventBarHeight = 40; if ( count($monitors) ) { $chart['graph']['eventBarHeight'] = $minEventBarHeight; while ( ($chart['graph']['eventsHeight'] = (($chart['graph']['eventBarHeight'] * count($monitors)) + (count($monitors)-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($monitors) as $monitorId ) { $chart['eventBars'][$monitorId] = array( 'top' => $top ); $top += $chart['graph']['eventBarHeight']+1; } } else if ( $mode == 'split' ) { $minActivityBarHeight = 30; $minEventBarHeight = 10; $maxEventBarHeight = 40; if ( count($monitors) ) { $chart['graph']['eventBarHeight'] = $minEventBarHeight; $chart['graph']['activityBarHeight'] = $minActivityBarHeight; while ( ((($chart['graph']['eventBarHeight']+$chart['graph']['activityBarHeight']) * count($monitors)) + ((2*count($monitors))-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']; $chart['activityBars'] = array(); $chart['eventBars'] = array(); $top = 0; $barCount = 1; foreach ( array_keys($monitors) as $monitorId ) { $chart['eventBars'][$monitorId] = array( 'top' => $top ); $chart['eventBars'][$monitorId] = array( 'top' => $top+$chart['graph']['activityBarHeight']+1 ); $top += $chart['graph']['activityBarHeight']+1+$chart['graph']['eventBarHeight']+1; } } else { ZM\Warning("No mode $mode"); } 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'] ); } else if ( $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'] ); } else if ( $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 ) { $html = ''; ob_start(); $labelCount = 0; $lastTick = 0; unset( $lastLabel ); $labelCheck = isset($scale['labelCheck'])?$scale['labelCheck']:$scale['label']; echo '
'; for ( $i = 0; $i < $chart['graph']['width']; $i++ ) { $x = round(100*(($i)/$chart['graph']['width']),1); $timeOffset = (int)($chart['data']['x']['lo'] + ($i * $chart['data']['x']['density'])); if ( $scale['align'] > 1 ) { $label = (int)(strftime( $labelCheck, $timeOffset )/$scale['align']); } else { $label = strftime( $labelCheck, $timeOffset ); } if ( !isset($lastLabel) || ($lastLabel != $label) ) { $labelCount++; } if ( $labelCount >= $scale['divisor'] ) { $labelCount = 0; if ( isset($lastLabel) ) { if ( $labelClass ) { ?>

<?php echo translate('ViewEvent') ?>

'; } if ( $mode == 'overlay' ) { echo drawYGrid( $chart, $majYScale, 'majLabelY', 'majTickY', 'majGridY graphWidth' ); } echo drawXGrid( $chart, $majXScale, 'majLabelX', 'majTickX', 'majGridX graphHeight', 'zoom graphHeight' ); if ( $mode == 'overlay' ) { ?>
$slots ) { foreach ( $slots as $slot ) { echo drawSlot($slot, $index); } } ?>
$slot ) { echo drawSlot($slot, $index); } # end foreach $currFrameSlots unset($currFrameSlots); ?>
'; unset( $slot ); } # end if isset($currEventSlots[$i]) } # end foreach width segment unset ($currEventSlots); ?>
Name() ?>