FileDocCategorySizeDatePackage
Average.javaAPI DocAzureus 3.0.3.46832Fri Jun 29 13:28:42 BST 2007org.gudy.azureus2.core3.util

Average

public class Average extends Object
This class is used to compute average (mostly for speed transfer).
author
Olivier

Fields Summary
private int
refreshRate
It uses a simple array of longs to store values in a cycling way. The array has 2 more elements than really needed to compute the average. One is the next one to be filled, and its value is always 0, and the other one is the one currently filled, which value is not taken into account for the average.
private int
period
private int
nbElements
private long
lastUpdate
private long[]
values
Constructors Summary
protected Average(int _refreshRate, int _period)
Private constructor for an Average

param
_refreshRate the refresh rate in ms
param
_period the period in s

    this.refreshRate = _refreshRate;
    this.period = _period;

    this.nbElements = (_period * 1000) / _refreshRate + 2;
    this.lastUpdate = getEffectiveTime() / _refreshRate;
    this.values = new long[this.nbElements];
  
Methods Summary
public voidaddValue(long value)
Public method to add a value to the average, the time it is added is the time this method is called.

param
value the value to be added to the Average

    //We get the current time factor.
    long timeFactor = getEffectiveTime() / refreshRate;
    //We first update the buffer.
    update(timeFactor);
    //And then we add our value to current element
    values[(int) (timeFactor % nbElements)] += value;
  
public longgetAverage()
This method can be called to get the current average value.

return
the current Average computed.

	  return( getSum() / period );
  
public longgetAverage(int average_period)

	  int	slots = average_period<=0?(nbElements - 2):(average_period / refreshRate);
	  
	  if ( slots <= 0 ){
		  
		  slots = 1;
		  
	  }else if ( slots > nbElements - 2 ){
		  
		  slots = nbElements - 2;
	  }
	 
	  if ( slots == 1 ){
		 
		  return( getPointValue());
	  }
	  
	  long res = getSum(slots) / ( period * slots / ( nbElements - 2 ));
	  
	  return( res );
  
public doublegetDoubleAverage()

	  return( (double)getSum() / period );
  
public java.lang.StringgetDoubleAverageAsString(int precision)

	  return( DisplayFormatters.formatDecimal( getDoubleAverage(), precision ));
  
protected longgetEffectiveTime()

	  return( SystemTime.getCurrentTime());
  
public static org.gudy.azureus2.core3.util.AveragegetInstance(int refreshRate, int period)
The way to get a new Average Object, it does some parameter checking. refreshRate must be greater than 100, and period*1000 must be greater than refreshRate

param
refreshRate in ms
param
period in s
return
the newlly created Average, or null if parameters are wrong

    if (refreshRate < 100)
      return null;
    if ((period * 1000) < refreshRate)
      return null;
    return new Average(refreshRate, period);
  
public longgetPointValue()

	  long timeFactor = getEffectiveTime() / refreshRate;
	  //We first update the buffer
	  update(timeFactor);

	  return(values[(int)((timeFactor-1)% nbElements)]);
  
protected final longgetSum()

    //We get the current timeFactor
    long timeFactor = getEffectiveTime() / refreshRate;
    //We first update the buffer
    update(timeFactor);

    //The sum of all elements used for the average.
    long sum = 0;

    //Starting on oldest one (the one after the next one)
    //Ending on last one fully updated (the one previous current one)
    for (long i = timeFactor + 2; i < timeFactor + nbElements; i++) {
      //Simple addition
      sum += values[(int) (i % nbElements)];
    }

    //We return the sum divided by the period
    return(sum);
  
protected final longgetSum(int slots)

	    //We get the current timeFactor
	    long timeFactor = getEffectiveTime() / refreshRate;
	    //We first update the buffer
	    update(timeFactor);

	    //The sum of all elements used for the average.
	    long sum = 0;
	    
	    if ( slots < 1 ){
	    	
	    	slots = 1;
	    	
	    }else if ( slots > nbElements-2 ){
	    	
	    	slots = nbElements-2;
	    }
	    
	    //Starting on oldest one (the one after the next one)
	    //Ending on last one fully updated (the one previous current one)
	    
	    long end_slot 	= timeFactor + nbElements;
	    long start_slot = end_slot - slots;
	    
	    for (long i = start_slot; i< end_slot;i++ ){
	      sum += values[(int) (i % nbElements)];
	    }

	    //We return the sum divided by the period
	    return(sum);
	  
private synchronized voidupdate(long timeFactor)
This method is used to update the buffer tha stores the values, in fact it mostly does clean-up over this buffer, erasing all values that have not been updated.

param
timeFactor which is the currentTime divided by the refresh Rate

    //If we have a really OLD lastUpdate, we could erase the buffer a 
    //huge number of time, so if it's really old, we change it so we'll only
    //erase the buffer once.
    if (lastUpdate < timeFactor - nbElements)
      lastUpdate = timeFactor - nbElements - 1;

    //For all values between lastUpdate + 1 (next value than last updated)
    //and timeFactor (which is the new value insertion position) 
    for (long i = lastUpdate + 1; i <= timeFactor; i++) {
      //We set the value to 0.
      values[(int) (i % nbElements)] = 0;
    }
    //We also clear the next value to be inserted (so on next time change...)
    values[(int) ((timeFactor + 1) % nbElements)] = 0;

    //And we update lastUpdate.
    lastUpdate = timeFactor;