Fix use of onclick and onchange. Fix bulk frame lookup. Make scanning events more efficient

This commit is contained in:
Isaac Connor 2019-06-10 15:59:19 -04:00
parent 265e49fe45
commit 1eadb814e2
3 changed files with 171 additions and 110 deletions

View File

@ -45,51 +45,81 @@ function evaluateLoadTimes() {
$('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + ".";
} // end evaluateLoadTimes()
function getFrame( monId, time ) {
function getFrame(monId, time, last_Frame=null) {
if ( last_Frame ) {
if (
(last_Frame.TimeStampSecs <= time)
&&
(last_Frame.EndTimeStampSecs >= time)
) {
return last_Frame;
}
}
var events_for_monitor = events_by_monitor_id[monId];
if ( ! events_for_monitor ) {
console.log("No events for monitor " + monId);
return;
}
var Frame = null;
for ( var event_id in events ) {
for ( var i = 0; i < events_for_monitor.length; i++ ) {
//for ( var event_id_idx in events_for_monitor ) {
var event_id = events_for_monitor[i];
// Search for the event matching this time. Would be more efficient if we had events indexed by monitor
Event = events[event_id];
if ( Event.MonitorId != monId || Event.StartTimeSecs > time || Event.EndTimeSecs < time ) {
e = events[event_id];
if ( !e ) {
console.log("No event found for " + event_id);
break;
}
if ( e.MonitorId != monId || e.StartTimeSecs > time || e.EndTimeSecs < time ) {
//console.log("Event not for " + time);
continue;
}
var duration = Event.EndTimeSecs - Event.StartTimeSecs;
if ( ! Event.FramesById ) {
if ( !e.FramesById ) {
console.log("No FramesById for event " + event_id);
return;
}
var frame = parseInt((time - Event.StartTimeSecs)/(duration)*Object.keys(Event.FramesById).length)+1;
// Need to get frame by time, not some fun calc that assumes frames have the same mlength.
// Frames are not sorted.
for ( var frame_id in Event.FramesById ) {
var duration = e.EndTimeSecs - e.StartTimeSecs;
// I think this is an estimate to jump near the desired frame.
var frame = parseInt((time - e.StartTimeSecs)/(duration)*Object.keys(e.FramesById).length)+1;
//console.log("frame_id for " + time + " is " + frame);
// Need to get frame by time, not some fun calc that assumes frames have the same length.
// Frames are sorted in descreasing order (or not sorted).
// This is likely not efficient. Would be better to start at the last frame viewed, see if it is still relevant
// Then move forward or backwards as appropriate
for ( var frame_id in e.FramesById ) {
if ( 0 ) {
if ( frame == 0 ) {
console.log("Found frame for time " + time );
console.log("Found frame for time " + time);
console.log(Frame);
Frame = Event.FramesById[frame_id];
Frame = e.FramesById[frame_id];
break;
}
frame --;
continue;
}
if (
Event.FramesById[frame_id].TimeStampSecs == time
e.FramesById[frame_id].TimeStampSecs == time
|| (
Event.FramesById[frame_id].TimeStampSecs < time
e.FramesById[frame_id].TimeStampSecs < time
&& (
(!Event.FramesById[frame_id].NextTimeStampSecs)
(!e.FramesById[frame_id].NextTimeStampSecs) // only if event.EndTime is null
||
(Event.FramesById[frame_id].NextTimeStampSecs > time)
(e.FramesById[frame_id].NextTimeStampSecs > time)
)
)
) {
Frame = Event.FramesById[frame_id];
Frame = e.FramesById[frame_id];
break;
}
} // end foreach frame in the event.
if ( ! Frame ) {
console.log("Didn't find frame for " + time );
if ( !Frame ) {
console.log("Didn't find frame for " + time);
return null;
}
} // end foreach event
@ -97,11 +127,11 @@ function getFrame( monId, time ) {
}
// time is seconds since epoch
function getImageSource( monId, time ) {
function getImageSource(monId, time) {
if ( liveMode == 1 ) {
var new_url = monitorImageObject[monId].src.replace(
/rand=\d+/i,
'rand='+Math.floor((Math.random() * 1000000) )
'rand='+Math.floor(Math.random() * 1000000)
);
if ( auth_hash ) {
// update auth hash
@ -109,20 +139,31 @@ function getImageSource( monId, time ) {
}
return new_url;
}
var frame_id;
var Frame = getFrame(monId, time);
if ( Frame ) {
// Adjust for bulk frames
if ( Frame.NextFrameId ) {
var duration = Frame.NextTimeStampSecs - Frame.TimeStampSecs;
frame_id = Frame.FrameId + parseInt( (Frame.NextFrameId-Frame.FrameId) * ( time-Frame.TimeStampSecs )/duration );
//console.log("Have NextFrame: duration: " + duration + " frame_id = " + frame_id + " from " + Frame.NextFrameId + ' - ' + Frame.FrameId + " time: " + (time-Frame.TimeStampSecs) );
//} else {
//console.log("No NextFrame");
var e = events[Frame.EventId];
var NextFrame = e.FramesById[Frame.NextFrameId];
if ( !NextFrame ) {
console.log("No next frame for " + Frame.NextFrameId);
} else if ( NextFrame.Type == 'Bulk' ) {
// There is time between this frame and a bulk frame
var duration = Frame.NextTimeStampSecs - Frame.TimeStampSecs;
frame_id = Frame.FrameId + parseInt( (NextFrame.FrameId-Frame.FrameId) * ( time-Frame.TimeStampSecs )/duration );
//console.log("Have NextFrame: duration: " + duration + " frame_id = " + frame_id + " from " + NextFrame.FrameId + ' - ' + Frame.FrameId + " time: " + (time-Frame.TimeStampSecs) );
}
} else {
frame_id = Frame['Id'];
console.log("No NextFrame");
}
Event = events[Frame.EventId];
var storage = Storage[Event.StorageId];
if ( ! storage ) {
if ( !storage ) {
// Storage[0] is guaranteed to exist as we make sure it is there in montagereview.js.php
console.log("No storage area for id " + Event.StorageId);
storage = Storage[0];
@ -130,7 +171,7 @@ function getImageSource( monId, time ) {
// monitorServerId may be 0, which gives us the default Server entry
var server = storage.ServerId ? Servers[storage.ServerId] : Servers[monitorServerId[monId]];
return server.PathToIndex +
'?view=image&eid=' + Frame.EventId + '&fid='+Frame.FrameId +
'?view=image&eid=' + Frame.EventId + '&fid='+frame_id +
"&width=" + monitorCanvasObj[monId].width +
"&height=" + monitorCanvasObj[monId].height;
} // end found Frame
@ -818,16 +859,16 @@ function showOneMonitor(monId) {
// We know the monitor, need to determine the event based on current time
var url;
if ( liveMode != 0 ) {
url="?view=watch&mid=" + monId.toString();
createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId] );
url = '?view=watch&mid=' + monId.toString();
createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId]);
} else {
var Frame = getFrame( monId, currentTimeSecs );
if ( Frame ) {
url="?view=event&eid=" + Frame.EventId + '&fid=' +Frame.FrameId;
url = '?view=event&eid=' + Frame.EventId + '&fid=' + Frame.FrameId;
createPopup(url, 'zmEvent', 'event', monitorWidth[monId], monitorHeight[monId]);
} else {
url="?view=watch&mid=" + monId.toString();
createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId] );
url = '?view=watch&mid=' + monId.toString();
createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId]);
}
} // end if live/events
}
@ -960,11 +1001,19 @@ function initPage() {
maxDate: +0,
constrainInput: false,
onClose: function(newDate, oldData) {
if (newDate !== oldData.lastVal) {
if ( newDate !== oldData.lastVal ) {
changeDateTime();
}
}
});
$j('#scaleslider').bind('change', function() { setScale(this.value); });
$j('#scaleslider').bind('input', function() { showScale(this.value); });
$j('#speedslider').bind('change', function() { setSpeed(this.value); });
$j('#speedslider').bind('input', function() { showSpeed(this.value); });
$j('#liveButton').bind('click', function() { setLive(1-liveMode); });
$j('#fit').bind('click', function() { setFit(1-fitMode); });
$j('#archive_status').bind('change', function() { console.log('submitting'); this.form.submit(); });
}
window.addEventListener("resize", redrawScreen, {passive: true});
// Kick everything off

View File

@ -55,23 +55,26 @@ if ( !$liveMode ) {
if ( $result = dbQuery($framesSql) ) {
$next_frame = null;
while( $frame = $result->fetch(PDO::FETCH_ASSOC) ) {
while ( $frame = $result->fetch(PDO::FETCH_ASSOC) ) {
$event_id = $frame['EventId'];
$event = &$EventsById[$event_id];
$frame['TimeStampSecs'] = $event['StartTimeSecs'] + $frame['Delta'];
if ( !isset($event['FramesById']) ) {
// Please note that this is the last frame as we sort DESC
$event['FramesById'] = array();
$frame['NextTimeStampSecs'] = 0;
$frame['NextTimeStampSecs'] = $event['EndTime'];
} else {
$frame['NextTimeStampSecs'] = $next_frames[$frame['EventId']]['TimeStampSecs'];
$frame['NextFrameId'] = $next_frames[$frame['EventId']]['FrameId'];
$frame['NextFrameId'] = $next_frames[$frame['EventId']]['Id'];
}
$event['FramesById'] += array( $frame['Id']=>$frame );
$event['FramesById'] += array($frame['Id']=>$frame);
$next_frames[$frame['EventId']] = $frame;
}
}
$events_by_monitor_id = array();
echo "var events = {\n";
foreach ( $EventsById as $event_id=>$event ) {
@ -82,7 +85,7 @@ if ( !$liveMode ) {
if ( !$minTimeSecs or $minTimeSecs > $StartTimeSecs ) $minTimeSecs = $StartTimeSecs;
if ( !$maxTimeSecs or $maxTimeSecs < $EndTimeSecs ) $maxTimeSecs = $EndTimeSecs;
$event_json = json_encode($event, JSON_PRETTY_PRINT);
$event_json = json_encode($event, JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK);
echo " $event_id : $event_json,\n";
$index = $index + 1;
@ -91,8 +94,19 @@ if ( !$liveMode ) {
$maxScore = $event['MaxScore'];
$anyAlarms = true;
}
if ( !isset($events_by_monitor_id[$event['MonitorId']]) )
$events_by_monitor_id[$event['MonitorId']] = array();
array_push($events_by_monitor_id[$event['MonitorId']], $event_id);
} # end foreach Event
echo " };
var events_by_monitor_id = {
\n";
foreach ( $events_by_monitor_id as $monitor_id=>$event_ids ) {
echo "$monitor_id : ".json_encode($event_ids, JSON_NUMERIC_CHECK) . "\n";
}
echo " };\n";
echo " };\n";
// if there is no data set the min/max to the passed in values
if ( $index == 0 ) {

View File

@ -64,7 +64,7 @@ if ( isset($_REQUEST['filter']) ) {
$filter = $_REQUEST['filter'];
} else {
if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($displayMonitors) != 0) {
if ( isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && (count($displayMonitors) != 0) ) {
$filter = array(
'Query' => array(
'terms' => array(
@ -77,10 +77,10 @@ if ( isset($_REQUEST['filter']) ) {
$filter['Query']['terms'][] = (array('attr' => 'MonitorId', 'op' => 'IN', 'val' => implode(',',$selected_monitor_ids), 'cnj' => 'and'));
} else if ( ( $group_id != 0 || isset($_SESSION['ServerFilter']) || isset($_SESSION['StorageFilter']) || isset($_SESSION['StatusFilter']) ) ) {
# this should be redundant
for ($i=0; $i < count($displayMonitors); $i++) {
if ($i == '0') {
for ( $i = 0; $i < count($displayMonitors); $i++ ) {
if ( $i == '0' ) {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'and', 'obr' => '1');
} else if ($i == (count($displayMonitors)-1)) {
} else if ( $i == (count($displayMonitors)-1) ) {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or', 'cbr' => '1');
} else {
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or');
@ -118,7 +118,7 @@ $eventsSql = 'SELECT
// Note that the delta value seems more accurate than the time stamp for some reason.
$framesSql = '
SELECT Id, FrameId, EventId, TimeStamp, UNIX_TIMESTAMP(TimeStamp) AS TimeStampSecs, Score, Delta
SELECT Id, FrameId, EventId, TimeStamp, UNIX_TIMESTAMP(TimeStamp) AS TimeStampSecs, Score, Delta, Type
FROM Frames
WHERE EventId IN (SELECT E.Id FROM Events AS E WHERE 1>0
';
@ -126,9 +126,9 @@ $framesSql = '
// This program only calls itself with the time range involved -- it does all monitors (the user can see, in the called group) all the time
$monitor_ids_sql = '';
if ( ! empty($user['MonitorIds']) ) {
if ( !empty($user['MonitorIds']) ) {
$eventsSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
$framesSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
$framesSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
}
if ( count($selected_monitor_ids) ) {
$monitor_ids_sql = ' IN (' . implode(',',$selected_monitor_ids).')';
@ -173,7 +173,7 @@ if ( (strtotime($maxTime) - strtotime($minTime))/(365*24*3600) > 30 ) {
}
$fitMode = 1;
if (isset($_REQUEST['fit']) && $_REQUEST['fit']=='0' )
if ( isset($_REQUEST['fit']) && ($_REQUEST['fit'] == '0') )
$fitMode = 0;
if ( isset($_REQUEST['scale']) )
@ -200,7 +200,7 @@ if ( isset($_REQUEST['current']) )
$defaultCurrentTime = validHtmlStr($_REQUEST['current']);
$liveMode = 1; // default to live
if ( isset($_REQUEST['live']) && $_REQUEST['live']=='0' )
if ( isset($_REQUEST['live']) && ($_REQUEST['live'] == '0') )
$liveMode = 0;
$initialDisplayInterval = 1000;
@ -236,82 +236,80 @@ foreach( $displayMonitors as $row ) {
// These are zoom ranges per visible monitor
xhtmlHeaders(__FILE__, translate('MontageReview') );
getBodyTopHTML();
?>
<body>
<div id="page">
<div id="page">
<?php echo getNavBarHTML() ?>
<form id="montagereview_form" action="?" method="get">
<input type="hidden" name="view" value="montagereview"/>
<div id="header">&nbsp;&nbsp;
<a href="#"><span id="hdrbutton" class="glyphicon glyphicon-menu-up pull-right"></span></a>
<div id="flipMontageHeader">
<?php echo $filter_bar ?>
<div id="DateTimeDiv">
<input type="text" name="minTime" id="minTime" value="<?php echo preg_replace('/T/', ' ', $minTime ) ?>"/> to
<input type="text" name="maxTime" id="maxTime" value="<?php echo preg_replace('/T/', ' ', $maxTime ) ?>"/>
</div>
<div id="ScaleDiv">
<label for="scaleslider"><?php echo translate('Scale')?></label>
<input id="scaleslider" type="range" min="0.1" max="1.0" value="<?php echo $defaultScale ?>" step="0.10" onchange="setScale(this.value);" oninput="showScale(this.value);"/>
<span id="scaleslideroutput"><?php echo number_format((float)$defaultScale,2,'.','')?> x</span>
</div>
<div id="SpeedDiv">
<label for="speedslider"><?php echo translate('Speed') ?></label>
<input id="speedslider" type="range" min="0" max="<?php echo count($speeds)-1?>" value="<?php echo $speedIndex ?>" step="1" onchange="setSpeed(this.value);" oninput="showSpeed(this.value);"/>
<span id="speedslideroutput"><?php echo $speeds[$speedIndex] ?> fps</span>
</div>
<div id="ButtonsDiv">
<button type="button" id="panleft" data-on-click="click_panleft" >&lt; <?php echo translate('Pan') ?></button>
<button type="button" id="zoomin" data-on-click="click_zoomin" ><?php echo translate('In +') ?></button>
<button type="button" id="zoomout" data-on-click="click_zoomout" ><?php echo translate('Out -') ?></button>
<button type="button" id="lasteight" data-on-click="click_lastEight" ><?php echo translate('8 Hour') ?></button>
<button type="button" id="lasthour" data-on-click="click_lastHour" ><?php echo translate('1 Hour') ?></button>
<button type="button" id="allof" data-on-click="click_all_events" ><?php echo translate('All Events') ?></button>
<button type="button" id="liveButton" onclick="setLive(1-liveMode); console.log('live');return false;"><?php echo translate('Live') ?></button>
<button type="button" id="fit" onclick="setFit(1-fitMode);" ><?php echo translate('Fit') ?></button>
<button type="button" id="panright" data-on-click="click_panright" ><?php echo translate('Pan') ?> &gt;</button>
<a href="#"><span id="hdrbutton" class="glyphicon glyphicon-menu-up pull-right"></span></a>
<div id="flipMontageHeader">
<?php echo $filter_bar ?>
<div id="DateTimeDiv">
<input type="text" name="minTime" id="minTime" value="<?php echo preg_replace('/T/', ' ', $minTime ) ?>"/> to
<input type="text" name="maxTime" id="maxTime" value="<?php echo preg_replace('/T/', ' ', $maxTime ) ?>"/>
</div>
<div id="ScaleDiv">
<label for="scaleslider"><?php echo translate('Scale')?></label>
<input id="scaleslider" type="range" min="0.1" max="1.0" value="<?php echo $defaultScale ?>" step="0.10"/>
<span id="scaleslideroutput"><?php echo number_format((float)$defaultScale,2,'.','')?> x</span>
</div>
<div id="SpeedDiv">
<label for="speedslider"><?php echo translate('Speed') ?></label>
<input id="speedslider" type="range" min="0" max="<?php echo count($speeds)-1?>" value="<?php echo $speedIndex ?>" step="1"/>
<span id="speedslideroutput"><?php echo $speeds[$speedIndex] ?> fps</span>
</div>
<div id="ButtonsDiv">
<button type="button" id="panleft" data-on-click="click_panleft" >&lt; <?php echo translate('Pan') ?></button>
<button type="button" id="zoomin" data-on-click="click_zoomin" ><?php echo translate('In +') ?></button>
<button type="button" id="zoomout" data-on-click="click_zoomout" ><?php echo translate('Out -') ?></button>
<button type="button" id="lasteight" data-on-click="click_lastEight" ><?php echo translate('8 Hour') ?></button>
<button type="button" id="lasthour" data-on-click="click_lastHour" ><?php echo translate('1 Hour') ?></button>
<button type="button" id="allof" data-on-click="click_all_events" ><?php echo translate('All Events') ?></button>
<button type="button" id="liveButton"><?php echo translate('Live') ?></button>
<button type="button" id="fit" ><?php echo translate('Fit') ?></button>
<button type="button" id="panright" data-on-click="click_panright" ><?php echo translate('Pan') ?> &gt;</button>
<?php
if ( (!$liveMode) and (count($displayMonitors) != 0) ) {
if ( (!$liveMode) and (count($displayMonitors) != 0) ) {
?>
<button type="button" id="downloadVideo" data-on-click="click_download"><?php echo translate('Download Video') ?></button>
<button type="button" id="downloadVideo" data-on-click="click_download"><?php echo translate('Download Video') ?></button>
<?php
}
}
?>
</div>
</div>
<?php if ( !$liveMode ) { ?>
<div id="eventfilterdiv" class="input-group">
<label>Archive Status
<?php echo htmlSelect(
'archive_status',
array(
'' => translate('All'),
'Archived' => translate('Archived'),
'Unarchived' => translate('UnArchived'),
),
( isset($_SESSION['archive_status']) ? $_SESSION['archive_status'] : ''),
array('onchange'=>'this.form.submit();')
);
?>
</label>
</div>
<div id="eventfilterdiv" class="input-group">
<label>Archive Status
<?php echo htmlSelect(
'archive_status',
array(
'' => translate('All'),
'Archived' => translate('Archived'),
'Unarchived' => translate('UnArchived'),
),
( isset($_SESSION['archive_status']) ? $_SESSION['archive_status'] : '')
); ?>
</label>
</div>
<?php } // end if !live ?>
<div id="timelinediv">
<canvas id="timeline"></canvas>
<span id="scrubleft"></span>
<span id="scrubright"></span>
<span id="scruboutput"></span>
</div>
</div>
</div>
<input type="hidden" name="fit" value="<?php echo $fitMode ?>"/>
<input type="hidden" name="live" value="<?php echo $liveMode ?>"/>
</div>
</form>
<div id="timelinediv">
<canvas id="timeline"></canvas>
<span id="scrubleft"></span>
<span id="scrubright"></span>
<span id="scruboutput"></span>
</div>
</div><!--flipMontageHeader-->
<input type="hidden" name="fit" value="<?php echo $fitMode ?>"/>
<input type="hidden" name="live" value="<?php echo $liveMode ?>"/>
</div><!--header-->
</form>
<div id="monitors">
<?php
// Monitor images - these had to be loaded after the monitors used were determined (after loading events)
foreach ( $monitors as $m ) {
echo '<canvas title="'.$m->Id().' ' .$m->Name().'" width="' . $m->Width() * $defaultScale . '" height="' . $m->Height() * $defaultScale . '" id="Monitor' . $m->Id() . '" style="border:1px solid ' . $m->WebColour() . '" monitor_id="'.$m->Id().'">No Canvas Support!!</canvas>';
echo '<canvas title="'.$m->Id().' ' .$m->Name().'" width="' . $m->Width() * $defaultScale . '" height="' . $m->Height() * $defaultScale . '" id="Monitor' . $m->Id() . '" style="border:1px solid ' . $m->WebColour() . '" monitor_id="'.$m->Id().'">No Canvas Support!!</canvas>
';
}
?>
</div>