# -*- Tcl -*-
# 
# Display running status of NS2 simulator.
# Copyright (c) 2005, Hiroyuki Ohsaki.
# All rights reserved.
# 
# $Id: runmonitor.tcl,v 1.10 2005/12/06 02:25:49 oosaki Exp $
# 

# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY.  No author or distributor
# accepts responsibility to anyone for the consequences of using it
# or for whether it serves any particular purpose or works at all,
# unless he says so in writing.  Refer to the GNU Emacs General Public
# License for full details.

# Everyone is granted permission to copy, modify and redistribute
# this code, but only under the conditions described in the
# GNU Emacs General Public License.   A copy of this license is
# supposed to have been given to you along with GNU Emacs so you
# can know your rights and responsibilities.  It should be in a
# file named COPYING.  Among other things, the copyright notice
# and this notice must be preserved on all copies.

# Usage:
# source runmonitor.tcl
# $ns init-runmonitor end-time

# FIXME: must not taint global namespace
proc _sec2str { sec } {
  # 86399 sec = 23:59:59
  if { $sec > 86399 } {
    set sec 86399
  }
  set ss [expr int($sec) % 60]
  set mm [expr (int($sec) / 60) % 60]
  set hh [expr (int($sec) / 3600) % 60]
  return [format "%02d:%02d:%02d" $hh $mm $ss]
}

Simulator instproc init-runmonitor {tmax {interval 0.5}} {
  $self instvar rmstart_ rmtmax_ rmintv_

  set rmstart_ [clock seconds]
  set rmtmax_ $tmax
  set rmintv_ $interval

  # schedule first invocation
  $self at 0 "$self show-runmonitor"
  $self at [expr $tmax - 0.000001] "$self flush-runmonitor"
}

Simulator instproc show-runmonitor {} {
  $self instvar rmstart_ rmtmax_ rmintv_ rmrate_
  
  set now [$self now]
  # elapsed time since simulation invocation
  set elapsed [expr 0.0 + [clock seconds] - $rmstart_]
  # simulator processing rate (= simulation time/wallclock time)
  if { $now > 0 && $elapsed > 0 } {
    set rate [expr 0.0 + $now / $elapsed]
  } else {
    set rate 1.0
  }
  # estimated remaining time in seconds
  set eta [expr 0.0 + ($rmtmax_ - $now) / ($rate + 1e-16)]

  # display stats in standard error
  puts -nonewline stderr \
    [format "Time: %7.3f \[%7.3f\], Elapsed: %s \[%s\] @ %7.2f%% \r" \
       $now [expr 0.0 + $rmtmax_ - $now] \
       [_sec2str $elapsed] [_sec2str $eta] [expr 0.0 + $rate * 100.0]]

  # schedule next invocation after (approximately) $rmintv_ wallclock seconds
  # NOTE: for preventing lockups, advance at least 1ms
  $self after [expr 0.0 + $rmintv_ * $rate + 0.001] "$self show-runmonitor"
}

Simulator instproc flush-runmonitor {} {
  $self show-runmonitor
  puts stderr ""
}

