
package uk.co.wingpath.modbus;

/**
* An implementation of {@link ResponseTimeMonitor} that maintains an
* exponentially-weighted average of response times and an exponentially-
* weighted average of their absolute deviations from the average.
*/
public class ResponseTimeAverager
    implements ResponseTimeMonitor
{
    private long average;
    private long deviation;
    private long weight;
    private long maxWeight;

    /**
    * Constructs an ResponseTimeAverager.
    */
    public ResponseTimeAverager ()
    {
        average = 0;
        deviation = 0;
        weight = 0;
        maxWeight = 20;
    }

    /**
    * Gets the average.
    * @return the average.
    */
    public synchronized long getAverage ()
    {
        return average;
    }

    /**
    * Gets the deviation.
    * @return the deviation.
    */
    public synchronized long getDeviation ()
    {
        return deviation;
    }

    /**
    * Updates the ResponseTimeAverager with another response time.
    * @param responseTime the response time in nanoseconds
    */
    @Override
    public synchronized void inform (long responseTime)
    {
        if (weight == 0)
        {
            average = responseTime;
            deviation = 0;
            weight = 1;
        }
        else
        {
            if (weight < maxWeight)
                ++weight;
            long diff = responseTime - average;
            long devdiff = Math.abs (diff) - deviation;
            average += diff / weight;
            deviation += devdiff / weight;
        }
    }

    /**
    * Resets the average.
    */
    public void reset ()
    {
        average = 0;
        deviation = 0;
        weight = 0;
    }
}

