001package de.hdm_stuttgart.mi.sd1.store;
002
003import java.util.Arrays;
004
005/**
006 * A container holding a fixed
007 *  number of integer values.
008 *
009 */
010public class IntegerStore {
011  
012  final static int defaultCapacity = 4;
013  private int[] values ;         // Array containing our values
014  private int numValues = 0;     // Number of values present in the container so far.
015  
016  /**
017   * Create a new store being able to
018   * hold integer values.
019   * 
020   */
021  public IntegerStore() {
022    values = new int[defaultCapacity];
023  }
024  /**
025   * Create a new store being able to
026   * hold integer values.
027   * 
028   * @param capacity The store's initial capacity. If more values
029   * are being added via {@link #addValue(int)} the capacity
030   * will be increased dynamically.
031   * 
032   */
033  public IntegerStore(int capacity) {
034    values = new int[capacity];
035  }
036
037  /**
038   * Initializing from a given array of integers.
039   * 
040   * @param values These presumably  unsorted values will be sorted
041   *     when being added to this store.
042   */
043  public IntegerStore(final int[] values) {
044
045    this.values = new int[values.length];
046    for (final int value: values) {
047      addValue(value);
048    }   
049  }
050
051  
052  /**
053   * @return The number of elements the store may
054   * hold, see {@link #IntegerStore(int)}.
055   */
056  public int getCapacity() {
057    return values.length;
058  }
059  
060  /**
061   * @return The number of values being contained.
062   */
063  public int getNumValues() { 
064    return numValues;
065  }
066  
067  /**
068   * Insert a new value into our container
069   * 
070   * @param value The value to be inserted. This will increment
071   * {@link #getNumValues()} by one.
072   * 
073   */
074  public void addValue(int value) {
075    if (values.length <= numValues) { // Insufficient capacity available to add a new value?
076      final int[] currentArray = values; // Save the current array variable
077      values = new int[2 * currentArray.length]; // Double the current array's size.
078      for (int i = 0; i < currentArray.length; i++) { // Copy old values to new array
079        values[i] = currentArray[i];
080      }
081    } 
082    int insertIndex;
083    // Find the index of the first existing element
084    // being larger or equal to the new element to be inserted
085    for (insertIndex= 0; insertIndex < numValues && values[insertIndex] < value; insertIndex++);
086    
087    /*
088     * Example insert value == 3; Finding the right position
089     * and shift some values accordingly to create a "free"
090     * position
091     *  Index values     | 0| 1| 2| 3| 4| 5| ...
092     *  -----------------+--+--+--+--+-----+ ...
093     *  values oldArray  | 1| 2| 7| 9|  |  |  
094     *  -----------------+--+--+--+--+-----+ ...
095     *  shift right one index starting from value "7" and fill in value 3
096     *  -----------------+--+--+--+--+-----+ ...
097     *  values newArray  | 1| 2| 3| 7| 9|  | ...
098     */
099    
100    for (int i = numValues; insertIndex <  i; i--) { // Shift values if necessary
101      values[i] = values[i - 1];
102    }
103    values[insertIndex] = value;
104    numValues++;
105  }
106
107  /**
108   * Access the value at a given index
109   * 
110   * @param index The desired value's index
111   * @return The desired value.
112   * <dl>
113      <dt><b>Precondition:</b></dt>
114       <dd>index &lt; {@link #getNumValues()}</dd>
115     </dl>
116   * 
117   */
118  public int getValue(int index) {
119    return values[index];
120  }
121  
122  /**
123   * @return The array of values entered so far
124   */
125  public int[] getValues() {
126    return Arrays.copyOfRange(values, 0, numValues);
127  }
128  
129  /**
130   * Empty the current set of values and set the store
131   * to its initial state.
132   */
133  public void clear() {
134    numValues = 0;
135  }
136  
137  /**
138   * @return The sample's average value.
139   */
140  public double getAverage() {
141    double sum = 0;
142    for (int i = 0; i < numValues; i++) {
143      sum += values[i];
144    }
145    return sum / numValues;
146  }
147  /**
148   *<dl>
149      <dt><b>Precondition:</b></dt>
150       <dd>There must be at least one element.</dd>
151     </dl>
152   * 
153   * @return The sample's median.
154   */
155  public double getMedian() {
156    final int upperMiddleIndex = numValues / 2;
157    if (0 == numValues % 2) { // Even number of values
158      return (values[upperMiddleIndex] +    // Choose mean of both
159          values[upperMiddleIndex -1]) / 2.;// center values
160    } else {  // Odd number of values
161      return values[upperMiddleIndex]; 
162    }
163  } 
164}