From 835bbb76a000ebde3c5f629286df98f75d560b67 Mon Sep 17 00:00:00 2001 From: stan Date: Sat, 1 Oct 2005 16:25:21 +0000 Subject: [PATCH] Actual correct file this time! git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@1494 e3e1d417-86f3-4887-817a-d78f3d33393f --- web/zm_html_view_timeline.php | 1177 ++++++++++++++++++++++++++++++--- 1 file changed, 1070 insertions(+), 107 deletions(-) diff --git a/web/zm_html_view_timeline.php b/web/zm_html_view_timeline.php index 95f4250f5..a21cd5943 100644 --- a/web/zm_html_view_timeline.php +++ b/web/zm_html_view_timeline.php @@ -1,6 +1,6 @@ 700, + "height"=>460, + "image" => array( + "width"=>200, + "height"=>200, + "top_offset"=>20, + ), + "image_text" => array( + "width"=>400, + "height"=>30, + "top_offset"=>20, + ), + "graph" => array( + "width"=>600, + "height"=>160, + "top_offset"=>30, + ), + "title" => array( + "top_offset"=>50 + ), + "key" => array( + "top_offset"=>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(); +$monitors_sql = "select * from Monitors order by Id asc"; +if ( !($result = mysql_query( $monitors_sql )) ) + die( mysql_error() ); +srand( 97981 ); +while ( $row = mysql_fetch_assoc( $result ) ) +{ + if ( empty($row['WebColour']) ) + { + $row['WebColour'] = sprintf( "#%02x%02x%02x", rand( 0, 255 ), rand( 0, 255), rand( 0, 255 ) ); + } + $monitors[$row['Id']] = $row; +} + +$range_sql = "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)"; +$events_sql = "select E.Id,E.Name,E.StartTime,E.EndTime,E.Length,E.Frames,E.MaxScore,E.MonitorId from Events as E inner join Monitors as M on (E.MonitorId = M.Id) where not isnull(StartTime)"; + if ( $user['MonitorIds'] ) { - $count_sql .= " M.Id in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; - $events_sql .= " M.Id in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; -} -else -{ - $count_sql .= " 1"; - $events_sql .= " 1"; + $mon_filter_sql = " and M.Id in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; + + $range_sql .= $mon_filter_sql; + $events_sql .= $mon_filter_sql; } -parseSort(); -parseFilter(); - -if ( $filter_sql ) +if ( isset($range) ) { - $count_sql .= $filter_sql; - $events_sql .= $filter_sql; -} -$events_sql .= " order by $sort_column $sort_order"; -if ( $page ) -{ - $limit_start = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); - if ( empty( $limit ) ) + $half_range = (int)($range/2); + if ( isset($mid_time) ) { - $limit_amount = ZM_WEB_EVENTS_PER_PAGE; + $mid_time_t = strtotime($mid_time); + $min_time_t = $mid_time_t-$half_range; + $max_time_t = $mid_time_t+$half_range; + if ( !($range%1) ) + { + $max_time_t--; + } + $min_time = date( "Y-m-d H:i:s", $min_time_t ); + $max_time = date( "Y-m-d H:i:s", $max_time_t ); + } + elseif ( isset($min_time) ) + { + $min_time_t = strtotime($min_time); + $max_time_t = $min_time_t + $range; + $mid_time_t = $min_time_t + $half_range; + $mid_time = date( "Y-m-d H:i:s", $mid_time_t ); + $max_time = date( "Y-m-d H:i:s", $max_time_t ); + } + elseif ( isset($max_time) ) + { + $max_time_t = strtotime($max_time); + $min_time_t = $max_time_t - $range; + $mid_time_t = $min_time_t + $half_range; + $min_time = date( "Y-m-d H:i:s", $min_time_t ); + $mid_time = date( "Y-m-d H:i:s", $mid_time_t ); + } +} +elseif ( isset($min_time) && isset($max_time) ) +{ + $min_time_t = strtotime($min_time); + $max_time_t = strtotime($max_time); + $range = ($max_time_t - $min_time_t) + 1; + $half_range = (int)($range/2); + $mid_time_t = $min_time_t + $half_range; + $mid_time = date( "Y-m-d H:i:s", $mid_time_t ); +} + +if ( !isset($min_time) || !isset($max_time) ) +{ + parseFilter(); + if ( $filter_sql ) + { + $range_sql .= $filter_sql; + $events_sql .= $filter_sql; + } + + // Dynamically determine range + if ( !($result = mysql_query( $range_sql )) ) + die( mysql_error() ); + $row = mysql_fetch_assoc( $result ); + + if ( !isset($min_time) ) + $min_time = $row['MinTime']; + if ( !isset($max_time) ) + $max_time = $row['MaxTime']; + $min_time_t = strtotime($min_time); + $max_time_t = strtotime($max_time); + $range = ($max_time_t - $min_time_t) + 1; + $half_range = (int)($range/2); + $mid_time_t = $min_time_t + $half_range; + $mid_time = date( "Y-m-d H:i:s", $mid_time_t ); +} + +$scales = array( + array( "name"=>"year", "factor"=>60*60*24*365, "align"=>1, "zoomout"=>2, "label"=>"Y" ), + array( "name"=>"month", "factor"=>60*60*24*30, "align"=>1, "zoomout"=>12, "label"=>"M" ), + array( "name"=>"week", "factor"=>60*60*24*7, "align"=>1, "zoomout"=>4.25, "label"=>"j/n", "label_check"=>"W" ), + array( "name"=>"day", "factor"=>60*60*24, "align"=>1, "zoomout"=>7, "label"=>"j" ), + array( "name"=>"hour", "factor"=>60*60, "align"=>1, "zoomout"=>24, "label"=>"H:00", "label_check"=>"H" ), + array( "name"=>"minute10", "factor"=>60, "align"=>10, "zoomout"=>6, "label"=>"H:i", "label_check"=>"i" ), + array( "name"=>"minute", "factor"=>60, "align"=>1, "zoomout"=>10, "label"=>"H:i", "label_check"=>"i" ), + array( "name"=>"second10", "factor"=>1, "align"=>10, "zoomout"=>6, "label"=>"s" ), + array( "name"=>"second", "factor"=>1, "align"=>1, "zoomout"=>10, "label"=>"s" ), +); + +$maj_x_scale = getDateScale( $scales, $range, $chart['grid']['x']['major']['min'], $chart['grid']['x']['major']['max'] ); +//$min_x_scale = getDateScale( $scales, $range, $chart['grid']['x']['minor']['min'], $chart['grid']['x']['minor']['max'] ); +//print_r( $maj_x_scale ); +//print_r( $min_x_scale ); + +// Adjust the range etc for scale +$min_time_t -= $min_time_t%($maj_x_scale['factor']*$maj_x_scale['align']); +$min_time = date( "Y-m-d H:i:s", $min_time_t ); +$max_time_t += (($maj_x_scale['factor']*$maj_x_scale['align'])-$max_time_t%($maj_x_scale['factor']*$maj_x_scale['align']))-1; +if ( $max_time_t > time() ) + $max_time_t = time(); +$max_time = date( "Y-m-d H:i:s", $max_time_t ); +$range = ($max_time_t - $min_time_t) + 1; +$half_range = (int)($range/2); +$mid_time_t = $min_time_t + $half_range; +$mid_time = date( "Y-m-d H:i:s", $mid_time_t ); + +//echo "R:$range
"; +//echo "MnT:$min_time
"; +//echo "MnTt:$min_time_t
"; +//echo "MdT:$mid_time
"; +//echo "MdTt:$mid_time_t
"; +//echo "MxT:$max_time
"; +//echo "MxTt:$max_time_t
"; + +if ( isset($min_time) && isset($max_time) ) +{ + $range_sql .= " and E.EndTime >= '$min_time' and E.StartTime <= '$max_time'"; + $events_sql .= " and E.EndTime >= '$min_time' and E.StartTime <= '$max_time'"; +} +$events_sql .= " order by Id asc"; +//echo "ESQL: $events_sql
"; + +$chart['data'] = array( + "x" => array( + "lo" => strtotime( $min_time ), + "hi" => strtotime( $max_time ), + ), + "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']; + +$mon_event_slots = array(); +$mon_frame_slots = array(); +if ( !($event_result = mysql_query( $events_sql )) ) + die( mysql_error() ); +$monitor_ids = array(); +//echo "YYY:".date( "r" )."
"; flush(); +while( $event = mysql_fetch_assoc( $event_result ) ) +{ + if ( !isset($monitor_ids[$event['MonitorId']]) ) + $monitor_ids[$event['MonitorId']] = true; + + if ( !isset($mon_event_slots[$event['MonitorId']]) ) + $mon_event_slots[$event['MonitorId']] = array(); + if ( !isset($mon_frame_slots[$event['MonitorId']]) ) + $mon_frame_slots[$event['MonitorId']] = array(); + + $curr_event_slots = &$mon_event_slots[$event['MonitorId']]; + $curr_frame_slots = &$mon_frame_slots[$event['MonitorId']]; + + $start_time_t = strtotime($event['StartTime']); + $start_index = $raw_start_index = (int)(($start_time_t - $chart['data']['x']['lo']) / $chart['data']['x']['density']); + if ( $start_index < 0 ) + $start_index = 0; + + if ( isset($event['EndTime']) ) + { + $end_time_t = strtotime($event['EndTime']); } else { - $limit_left = $limit - $limit_start; - $limit_amount = ($limit_left>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limit_left; + $end_time_t = time(); + } + $end_index = $raw_end_index = (int)(($end_time_t - $chart['data']['x']['lo']) / $chart['data']['x']['density']); + if ( $end_index >= $chart['graph']['width'] ) + $end_index = $chart['graph']['width'] - 1; + + for ( $i = $start_index; $i <= $end_index; $i++ ) + { + if ( !isset($curr_event_slots[$i]) ) + { + if ( $raw_start_index == $raw_end_index ) + { + $offset = 1; + } + else + { + $offset = 1+ ($event['Frames']?((int)($event['Frames']*(($i-$raw_start_index)/($raw_end_index-$raw_start_index)))):0); + } + $curr_event_slots[$i] = array( "count"=>0, "width"=>1, "offset"=>$offset, "event"=>$event ); + } + else + { + $curr_event_slots[$i]['count']++; + } + } + if ( $event['MaxScore'] > 0 ) + { + if ( $start_index == $end_index ) + { + $i = $start_index; + if ( !isset($curr_frame_slots[$i]) ) + { + $curr_frame_slots[$i] = array( "count"=>1, "value"=>$event['MaxScore'], "event"=>$event ); + } + else + { + $curr_frame_slots[$i]['count']++; + if ( $event['MaxScore'] > $curr_frame_slots[$i]['value'] ) + { + $curr_frame_slots[$i]['value'] = $event['MaxScore']; + $curr_frame_slots[$i]['event'] = $event; + } + } + if ( $event['MaxScore'] > $chart['data']['y']['hi'] ) + { + $chart['data']['y']['hi'] = $event['MaxScore']; + } + } + else + { + $frames_sql = "select F.FrameId,F.Delta,unix_timestamp(F.TimeStamp) as TimeT,F.Score from Frames as F where F.EventId = '".$event['Id']."' and F.Score > 0"; + if ( !($frame_result = mysql_query( $frames_sql )) ) + die( mysql_error() ); + while( $frame = mysql_fetch_assoc( $frame_result ) ) + { + $frame_time_t = $frame['TimeT']; + $frame_time_t = $start_time_t + $frame['Delta']; + $frame_index = (int)(($frame_time_t - $chart['data']['x']['lo']) / $chart['data']['x']['density']); + if ( $frame_index < 0 ) + continue; + if ( $frame_index >= $chart['graph']['width'] ) + continue; + + if ( !isset($curr_frame_slots[$frame_index]) ) + { + $curr_frame_slots[$frame_index] = array( "count"=>1, "value"=>$frame['Score'], "event"=>$event, "frame"=>$frame ); + } + else + { + $curr_frame_slots[$frame_index]['count']++; + if ( $frame['Score'] > $curr_frame_slots[$frame_index]['value'] ) + { + $curr_frame_slots[$frame_index]['value'] = $frame['Score']; + $curr_frame_slots[$frame_index]['event'] = $event; + $curr_frame_slots[$frame_index]['frame'] = $frame; + } + } + if ( $frame['Score'] > $chart['data']['y']['hi'] ) + { + $chart['data']['y']['hi'] = $frame['Score']; + } + } + } } - $events_sql .= " limit $limit_start, $limit_amount"; } -elseif ( !empty( $limit ) ) + +ksort($monitor_ids,SORT_NUMERIC); +ksort($mon_event_slots,SORT_NUMERIC); +ksort($mon_frame_slots,SORT_NUMERIC); + +//echo "AAA:".date( "r" )."
"; flush(); +// Add on missing frames +$xcount = 0; +foreach( array_keys($mon_frame_slots) as $monitor_id ) { - $events_sql .= " limit 0, $limit"; + unset( $curr_frame_slots ); + $curr_frame_slots = &$mon_frame_slots[$monitor_id]; + for ( $i = 0; $i < $chart['graph']['width']; $i++ ) + { + if ( isset($curr_frame_slots[$i]) ) + { + if ( !isset($curr_frame_slots[$i]['frame']) ) + { + $xcount++; + $frames_sql = "select F.FrameId,F.Score from Frames as F where F.EventId = '".$curr_frame_slots[$i]['event']['Id']."' and F.Score > 0 order by F.FrameId limit 0,1"; + if ( !($frame_result = mysql_query( $frames_sql )) ) + die( mysql_error() ); + $curr_frame_slots[$i]['frame'] = mysql_fetch_assoc( $frame_result ); + } + } + } +} +//echo "Fetched $xcount frames
"; +//echo "BBB:".date( "r" )."
"; flush(); + +$chart['data']['y']['range'] = ($chart['data']['y']['hi'] - $chart['data']['y']['lo']) + 1; +$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['height']; + +$maj_y_scale = getYScale( $chart['data']['y']['range'], $chart['grid']['y']['major']['min'], $chart['grid']['y']['major']['max'] ); +//print_r( $maj_y_scale ); + +$max_width = 0; +$max_height = 0; + +foreach ( array_keys($monitor_ids) as $monitor_id ) +{ + if ( $max_width < $monitors[$monitor_id]['Width'] ) + $max_width = $monitors[$monitor_id]['Width']; + if ( $max_height < $monitors[$monitor_id]['Height'] ) + $max_height = $monitors[$monitor_id]['Height']; +} + +//echo "ZZZ:".date( "r" )."
"; flush(); +// Optimise boxes +foreach( array_keys($mon_event_slots) as $monitor_id ) +{ + unset( $curr_event_slots ); + $curr_event_slots = &$mon_event_slots[$monitor_id]; + for ( $i = 0; $i < $chart['graph']['width']; $i++ ) + { + if ( isset($curr_event_slots[$i]) ) + { + //if ( isset($curr_slot) && (($curr_slot['width'] < $min_event_width) || (($curr_slot['event']['Id'] == $curr_event_slots[$i]['event']['Id']) && ($curr_slot['frame']['FrameId'] == $curr_event_slots[$i]['frame']['FrameId'])) ) ) + //if ( isset($curr_slot) && ($curr_slot['event']['Id'] == $curr_event_slots[$i]['event']['Id']) ) + if ( isset($curr_slot) ) + { + if ( $curr_slot['event']['Id'] == $curr_event_slots[$i]['event']['Id'] ) + { + if ( $curr_slot['width'] < $max_event_width ) + { + // Merge slots for the same long event + $curr_slot['width']++; + unset( $curr_event_slots[$i] ); + continue; + } + elseif ( $curr_slot['offset'] < $curr_event_slots[$i]['offset'] ) + { + // Split very long events + $curr_event_slots[$i]['frame'] = array( 'FrameId'=>$curr_event_slots[$i]['offset'] ); + } + } + elseif ( $curr_slot['width'] < $min_event_width ) + { + // Merge multiple small events + $curr_slot['width']++; + unset( $curr_event_slots[$i] ); + continue; + } + } + $curr_slot = &$curr_event_slots[$i]; + + //if ( isset($curr_slot) && ($curr_slot['width'] < $min_event_width || ($curr_slot['event']['Id'] == $curr_event_slots[$i]['event']['Id']) ) ) + //{ + //$curr_slot['width']++; + //unset( $curr_event_slots[$i] ); + //} + //else + //{ + //$curr_slot = &$curr_event_slots[$i]; + //} + } + else + { + unset( $curr_slot ); + } + } + if ( isset( $curr_slot ) ) + unset( $curr_slot ); +} + +// Stack events +//echo "XXX:".date( "r" )."
"; flush(); +$frame_slots = array(); +$frame_monitor_ids = array_keys($mon_frame_slots); +for ( $i = 0; $i < $chart['graph']['width']; $i++ ) +{ + foreach ( $frame_monitor_ids as $frame_monitor_id ) + { + unset( $curr_frame_slots ); + $curr_frame_slots = &$mon_frame_slots[$frame_monitor_id]; + if ( isset($curr_frame_slots[$i]) ) + { + if ( !isset($frame_slots[$i]) ) + { + $frame_slots[$i] = array(); + $frame_slots[$i][] = &$curr_frame_slots[$i]; + } + else + { + $slot_count = count($frame_slots[$i]); + for ( $j = 0; $j < $slot_count; $j++ ) + { + if ( $curr_frame_slots[$i]['value'] > $frame_slots[$i][$j]['value'] ) + { + for ( $k = $slot_count; $k > $j; $k-- ) + { + $frame_slots[$i][$k] = $frame_slots[$i][$k-1]; + } + $frame_slots[$i][$j] = &$curr_frame_slots[$i]; + break 2; + } + } + $frame_slots[$i][] = &$curr_frame_slots[$i]; + } + } + } +} +//echo "YYY:".date( "r" )."
"; flush(); + +//print_r( $mon_event_slots ); +//print_r( $mon_frame_slots ); +//print_r( $chart ); + +preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $min_time, $start_matches ); +preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $max_time, $end_matches ); + +if ( $start_matches[1] != $end_matches[1] ) +{ + // Different years + $title = date( "M Y", $chart['data']['x']['lo'] )." - ".date( "M Y", $chart['data']['x']['hi'] ); +} +elseif ( $start_matches[2] != $end_matches[2] ) +{ + // Different months + $title = date( "M", $chart['data']['x']['lo'] )." - ".date( "M Y", $chart['data']['x']['hi'] ); +} +elseif ( $start_matches[3] != $end_matches[3] ) +{ + // Different dates + $title = date( "j", $chart['data']['x']['lo'] )." - ".date( "j M Y", $chart['data']['x']['hi'] ); +} +else +{ + // Different times + $title = date( "H:i", $chart['data']['x']['lo'] )." - ".date( "H:i, j M Y", $chart['data']['x']['hi'] ); +} + +function getDateScale( $scales, $range, $min_lines, $max_lines ) +{ + foreach ( $scales as $scale ) + { + $align = isset($scale['align'])?$scale['align']:1; + $scale_range = (int)($range/($scale['factor']*$align)); + //echo "S:".$scale['name'].", A:$align, SR:$scale_range
"; + if ( $scale_range >= $min_lines ) + { + $scale['range'] = $scale_range; + break; + } + } + if ( !isset($scale['range']) ) + { + $scale['range'] = (int)($range/($scale['factor']*$align)); + } + $scale['divisor'] = 1; + while ( ($scale['range']/$scale['divisor']) > $max_lines ) + { + $scale['divisor']++; + } + $scale['lines'] = (int)($scale['range']/$scale['divisor']); + return( $scale ); +} + +function getYScale( $range, $min_lines, $max_lines ) +{ + $scale['range'] = $range; + $scale['divisor'] = 1; + while ( $scale['range']/$scale['divisor'] > $max_lines ) + { + $scale['divisor']++; + } + $scale['lines'] = (int)(($scale['range']-1)/$scale['divisor'])+1; + + return( $scale ); +} + +function drawXGrid( $chart, $scale, $label_class, $tick_class, $grid_class, $zoom_class=0 ) +{ + global $PHP_SELF, $view; + + ob_start(); + $label_count = 0; + $last_tick = 0; + unset( $last_label ); + $label_check = isset($scale['label_check'])?$scale['label_check']:$scale['label']; + for ( $i = 0; $i < $chart['graph']['width']; $i++ ) + { + $x = $i - 1; + $time_offset = (int)($chart['data']['x']['lo'] + ($i * $chart['data']['x']['density'])); + if ( $scale['align'] > 1 ) + { + $label = (int)(date( $label_check, $time_offset )/$scale['align']); + } + else + { + $label = date( $label_check, $time_offset ); + } + if ( !isset($last_label) || ($last_label != $label) ) + { + $label_count++; + } + if ( $label_count >= $scale['divisor'] ) + { + $label_count = 0; + if ( isset($last_label) ) + { + if ( $label_class ) + { +?> +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+".$slot['event']['Name'].(isset($slot['frame'])?("(".$slot['frame']['FrameId'].")"):"")."
".strftime( "%m/%d %H:%M:%S", strtotime($slot['event']['StartTime']) )."
".$slot['event']['Length']."s', '".$PHP_SELF."?view=event&eid=".$slot['event']['Id']."', ".($monitors[$slot['event']['MonitorId']]['Width']+$jws['event']['w']).", ".($monitors[$slot['event']['MonitorId']]['Height']+$jws['event']['h'])." );\"" ); +} + +function getSlotViewEventBehaviour( $slot ) +{ + global $monitors, $jws, $PHP_SELF; + + return( "\"eventWindow( '".$PHP_SELF."?view=event&eid=".$slot['event']['Id']."', 'zmEvent', ".($monitors[$slot['event']['MonitorId']]['Width']+$jws['event']['w']).", ".($monitors[$slot['event']['MonitorId']]['Height']+$jws['event']['h'])." );\"" ); } ?> -<?= ZM_WEB_TITLE_PREFIX ?> - <?= $zmSlangEvents ?> +<?= ZM_WEB_TITLE_PREFIX ?> - <?= $zmSlangTimeline ?> - - + -
-
- - - - - - - +
+
Event Navigator
+
+
+
+
+ <<   + -   + >> +
+
No Event
+
+       + +
+
+
+
+
+ + +
+$slots ) +{ + foreach ( $slots as $slot ) { - $event_array[$i] = 1; + $slot_height = (int)($slot['value']/$chart['data']['y']['density']); + + if ( $slot_height <= 0 ) + continue; + + if ( $mouseover ) + { + $behaviours = array( + "onClick=".getSlotViewEventBehaviour( $slot ), + "onMouseOver=".getSlotLoadImageBehaviour( $slot ), + ); + } + else + { + $behaviours = array( + "onClick=".getSlotLoadImageBehaviour( $slot ), + ); + } +?> +
>
+ - +
+ + +
+ +
>
+ +
+ +
+
+