import java.util.ArrayList;
import java.util.List;

public class MathUtils {
    private static List<Double> weights;
    private static final double freq = 50.0;
    private static final int steps = 360;
    private static final double PI = 3.141592653589793238;

    public static void main(String[] args) {
        int ret = train();
        // Do something with the return value if needed
    }

    public static int train() {
        final double w = 2.0 * PI * freq;
        final double P = 1.0 / freq;
        double time;

        weights = new ArrayList<>(steps);

        for (int i = 0; i <= steps / 4; ++i) {
            time = P * (double) i / steps;
            double x = w * time;
            weights.add(x);
            // Uncomment the following code block if you need to print the values
            /*
            #ifdef TEST_BUILD
            System.out.printf("i: %d time: %f weights: %f trueValue: %f%n", i, time, weights.get(i), Math.sin(x));
            #endif
            */
        }

        for (int i = steps / 4; i < steps / 2; ++i) {
            weights.add(weights.get(steps / 2 - i));
        }

        for (int i = steps / 2; i < steps; ++i) {
            weights.add(-weights.get(i - steps / 2));
        }

        return errorAnalysis();
    }

    public static int errorAnalysis() {
        double stdDev = 0.0;
        final double TOLERANCE = 0.001;
        int retVal = 0;
        final double w = 2.0 * PI * freq;
        final double P = 1.0 / freq;
        double diffSum = 0.0;

        for (int i = 0; i < steps; ++i) {
            double time = P * (double) i / steps;
            double trueValue = Math.sin(w * time);
            diffSum += (weights.get(i) - trueValue) * (weights.get(i) - trueValue);
        }

        stdDev = Math.sqrt(diffSum / (steps - 1));

        if (stdDev > TOLERANCE) {
            System.out.println();
            System.out.println("stdDev: " + stdDev);
            System.out.println("ERROR: The training model is inaccurate!");
            System.out.println();
            retVal = -1;
        } else {
            System.out.println("The training model is accurate.");
            System.out.println();
        }

        return retVal;
    }
}
