package de.wwwu.awolf.presenter.evaluation.measures;

import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.util.FastElementSelector;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
 *
 * @Author: Armin Wolf
 * @Email: a_wolf28@uni-muenster.de
 * @Date: 07.09.2017.
 */
public class ScaleDependentMeasure {

    private Set<Double> errorValues;

    /**
     * Konstruktor
     *
     * @param lines Liste des Geraden
     * @param m     Steigung
     * @param b     y-Achsenabschnitt
     */
    public ScaleDependentMeasure(final Set<Line> lines, Double m, Double b) {
        //Liste mit den Fehler zu jedem Punkt
        errorValues = new HashSet<>();

        //Sampson-Fehler Berechnung
        for (Line line : lines) {
            Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1);
            errorValues.add(e);
        }
    }

    /* Skalierungs Abhängige Approximationsgüten */
    //unterschiedliche Alg.- auf einem Datensatz

    /**
     * Mean Square Error:
     *
     * @return Ergebnis
     */
    public Double mse() {
        double error = 0;

        for (Double d : errorValues) {
            error += Math.pow(d, 2);
        }

        error /= errorValues.size();

        return error;
    }

    /**
     * Root Mean Square Error
     *
     * @return Ergebnis
     */
    public Double rmse() {
        return Math.sqrt(mse());
    }

    /**
     * Mean Absolute Error
     *
     * @return Ergebnis
     */
    public Double mae() {
        double error = 0;
        for (Double d : errorValues) {
            error += Math.abs(d);
        }
        error /= errorValues.size();
        return error;
    }

    /**
     * Median Absolute Error
     *
     * @return Ergebnis
     */
    public Double mdae() {
        return FastElementSelector
                .randomizedSelect(new ArrayList<>(errorValues), errorValues.size() * 0.5);
    }
}
