/*
    Moving Average using a ringbuffer (OOP)
    
    Durchschnittsberechnung der letzten x Werte mit einem Ringbuffer
    https://forum.arduino.cc/t/mittelwert-der-letzten-x-werte/1237432
    https://forum.arduino.cc/t/need-help-with-an-average/1272280/5

    2024-04-19 by noiasca
*/
template <typename T, size_t size>
class Avg {
    T store[size] {0};
    size_t index = 0;
    bool wraparound = false;

  public:

    void add(T in) {
      store[index] = in;
      index++;
      if (index >= size) {
        index = 0;
        wraparound = true;
      }
    }

    T getAvg() {
      T result = 0;
      if (wraparound) {
        for (auto &i : store) result += i;                    // default - Normalbetrieb
        return result / size;
      }
      if (index == 0) return 0;                               // start condition - Anfangsproblem
      for (size_t i = 0; i < index; i++) result += store[i];  // during first iteration - bis zum einmalig Durchlauf aller Werte
      return result / index;
    }
};

// now create an instance of the Avg class and define the variable type and how many values should be stored
Avg <int, 3>average;  // integer storage for 3 variables - Integer Speicher für 3 Variablen

void setup() {
  Serial.begin(115200);
  Serial.println("Average");

  Serial.println(average.getAvg());  // 0  - retrieve current result - Durschnitt abfragen
  average.add(100);                  // add a new value to the internal ring buffer - neuen Wert hinzufügen
  Serial.println(average.getAvg());  // 100
  average.add(200);
  Serial.println(average.getAvg());  // 150
  average.add(300);
  Serial.println(average.getAvg());  // 200
  average.add(400);
  Serial.println(average.getAvg());  // 300
  average.add(400);
  Serial.println(average.getAvg());  // 366
  average.add(400);
  Serial.println(average.getAvg());  // 400
}

void loop() {
  // put your main code here, to run repeatedly:
}