package simulate;

/**
 * Meter for recording and averaging a simple scalar of type double.
 * Subclasses of this abstract class need only to define the currentValue method
 * to calculate the desired property.  All averaging and error analysis is handled automatically by 
 * the methods defined by the MeterAbstract class.
 * The default condition of a Meter is "active", meaning that it increments sums for averages upon
 * receiving sufficient interval events from the integrator.
 */
public abstract class Meter extends MeterAbstract
{
    MeterAbstract.Accumulator accumulator = new MeterAbstract.Accumulator();

	public Meter() {
	    super();
	    setActive(true);  //default is to have meter do averages after some number of integrationIntervalEvents
	}
	
	/**
	 * Defined by the subclass to specify what property is measured by the meter.
	 * The method is called by the updateSums method to add the current value to the accumulator.
	 * This method may be called directly by any object to obtain the current value of the measured
	 * property.  As an example, a energy meter is present in each phase for the purpose of providing
	 * a value for the potential energy via a call to this method.  A call to currentValue does nothing
	 * to the sums kept for averages.  To obtain the current value and increment the sums at the same time,
	 * call updateSums() and then mostRecent().
	 */
	public abstract double currentValue();
 
    /**
     * Method to update running sums for averages and error statistics
     * Called by integrationIntervalAction every updateInterval times an integration event is received
     */
	public void updateSums() {accumulator.add(currentValue());}
	
    /**
     * Returns the current value of the average
     */
	public double average() {return accumulator.average();}
	
	/**
	 * Returns the current value of the error bar (67% confidence limit)
	 */
	public double error() {return accumulator.error();}
	
	/**
	 * Returns the value passed most recently obtained via an integrator intervalEvent
	 * (does not give the value last returned by any direct call to currentValue
	 *  i.e. by a call to currentValue that was not made in response to an interval event)
	 */
	public double mostRecent() {return accumulator.mostRecent();}
	
	/**
	 * Zeros all sums used for averages
	 */
	public void reset() {accumulator.reset();}
}	 
