#!/usr/bin/env python
import time

class rate:
    """This class is useful for keeping track of an incremented
    counter, displaying the overall average as well as the recent
    'period' average"""

    histarr = None      # historical data ([time,...],[val,...])
    avgperiods = None   # number of periods of historical data
    count = None
    totcount = None     # total 'complete' count
    tstart = None       # start time
    tcurr = None        # current time
    
    def __init__(self, avgperiods=10, totcount=None):
        self.tstart = time.time()
        self.tcurr = self.tstart
        
        self.histarr = [[],[]]
        self.count = 0
        self.avgperiods = avgperiods
        self.totcount = totcount
        # initialize the local average histogram
        self.pushhist()
        
    def __str__( self):
        "print a formatted rate query"
        
        if self.count == 0: return "No rate data"
        
        (telapsed, avgcps, pavgcps) = self.queryrate()

        m = "s: %7d, cnt: %9d   avg cnt/s: %6.2f, period cnt/s: %6.2f"
        mout = m % (telapsed, self.count, avgcps, pavgcps)
        
        if self.totcount:
            mout += "    s left: %9d"
            mout = mout % self.remaining( avgcps)
        return mout

    def cps( self, dts, dcnt):
        "count per second"

        if dts==0: return -1.0
        return (float(dcnt) / dts)

    def remaining(self, avgcps):
        "seconds remaining"

        return ((self.totcount - self.count) / avgcps)
        
    def pushhist( self):
        "store historical data of the past 'avgperiod' queries"

        # append the current time and count
        self.histarr[0].append( self.tcurr)
        self.histarr[1].append( self.count)

        # trim the length (from the first element) if necessary
        if len(self.histarr[0]) >= self.avgperiods:
            self.histarr[0] = self.histarr[0][-self.avgperiods:]
            self.histarr[1] = self.histarr[1][-self.avgperiods:]
        return

    def queryrate( self):
        "query, prompting a history iteration"

        self.tcurr = time.time()
        telapsed = self.tcurr - self.tstart

        # overall rate
        avgcps = self.cps( telapsed, self.count)

        # rate of last periods
        self.pushhist()
        pavgcps = self.cps( self.histarr[0][-1] - self.histarr[0][0],
                            self.histarr[1][-1] - self.histarr[1][0])

        return (telapsed, avgcps, pavgcps)

    
    def increment( self, cnt=1):
        "increment the count"
        self.count += cnt
        
