package presenter.evaluation;

import model.Line;
import presenter.algorithms.util.FastElementSelector;

import java.util.ArrayList;
import java.util.LinkedList;

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


    private ArrayList<Double> sampsonError;
    private ArrayList<Double> naivSampsonError;
    private ArrayList<Double> scaledError;

    public ScaledErrorBasedMeasure(final LinkedList<Line> lines, Double m, Double b, Double naivSlope, Double naivInterception) {

        this.sampsonError = new ArrayList<>();
        this.naivSampsonError = new ArrayList<>();
        this.scaledError = new ArrayList<>();


        for (Line line : lines) {
            Double e = Math.pow(naivSlope * line.getM() - line.getB() + naivInterception, 2) / (Math.pow(naivSlope, 2) + 1);
            naivSampsonError.add(e);
        }

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

        for (int i=0;i<sampsonError.size();i++){
            scaledError.add(sampsonError.get(i) / naivSampsonError.get(i));
        }


    }

    /* Skalierungs Abhängige Approximationsgüten */
    //unterschiedliche Alg.- auf einem Datensatz
    public Double mse() {
        double error = 0;
        for (Double d : scaledError) {
            error += Math.pow(d, 2);
        }
        error /= scaledError.size();
        return error;
    }

    public Double rmse() {
        return Math.sqrt(mse());
    }

    public Double mae() {
        double error = 0;
        for (Double d : scaledError) {
            error += Math.abs(d);
        }
        error /= scaledError.size();
        return error;
    }

    public Double mdae() {
        return FastElementSelector
                .randomizedSelect(scaledError, scaledError.size() * 0.5);
    }

}
