namespace eval slope {} {
  variable tbuffer
  variable vbuffer
}

proc stdConfig::slope {srcnode {omitzero 0}} {
  variable hostport none
  variable name
  variable node
  variable tbuffer
  variable vbuffer
  controller syncedprot

  obj slope upd

  dolater 0 hset $node/node $srcnode

  kids $name {
    node node out -text
    prop check slope::setnode $omitzero
    prop write stdSct::complete

    node unit par 60
    prop help "unit=60: mainunits/minutes, unit=1: mainunits/sec"
    node ref par 0
    node bufperiod par 300
  }
}

proc slope::setnode {omitzero} {
  variable tbuffer
  variable vbuffer

  [sct controller] updatescript [sct target] "slope::update_value [sct parent] $omitzero"
  sct update [sct target]
  set tbuffer([sct parent]) [list]
  set vbuffer([sct parent]) [list]
}

proc slope::update_value {sn omitzero val} {
  variable tbuffer
  variable vbuffer

  if {$val == 0 && $omitzero} {
    return
  }
  # sn: slope node
  set tbuf $tbuffer($sn)
  set vbuf $vbuffer($sn)
  set now [DoubleTime]
  lappend tbuf $now
  lappend vbuf $val
  set b [hvali $sn/bufperiod]
  while {[lindex $tbuf 0] < $now - $b} {
    set tbuf [lrange $tbuf 1 end]
    set vbuf [lrange $vbuf 1 end]
  }
  set tbuffer($sn) $tbuf
  set vbuffer($sn) $vbuf
  set l [llength $tbuf]
  if {$l < 3 || [lindex $tbuf end] - [lindex $tbuf 0] < $b / 4} {
    updateerror $sn "not enough data"
    return
  }
  set nom 0
  set div 0
  set i 0
  for {set i 0} {$i * 2 < $l} {incr i} {
    set j [expr $l - $i - 1]
    set dt [expr [lindex $tbuf $j] - [lindex $tbuf $i]]
    set nom [expr $nom + ([lindex $vbuf $j] - [lindex $vbuf $i]) * $dt]
    set div [expr $div + $dt * $dt]
    incr i
  }
  set slope [expr ($nom / $div) * [hval $sn/unit]]
  updateval $sn $slope
}
