package ac.essex.gp;

import ac.essex.gp.problems.Problem;
import ac.essex.gp.problems.examples.maths.MathsProblem;
import ac.essex.gp.params.GPParams;
import ac.essex.gp.interfaces.console.ConsoleListener;
import ac.essex.ooechs.imaging.commons.StatisticsSolver;

import java.io.File;

/**
 *
 * <p>
 * Allows you to run the same problem several times so that you can get statistics
 * </p>
 *
 * @author Olly Oechsle, University of Essex, Date: 30-Jan-2007
 * @version 1.1
 */
public class Multirun extends Thread {

    public static int NUM_RUNS = 25;

    // Generations
    //public static final int NUM_GENERATIONS = 100;
    //public static final int MAX_TIME = 300;

    // Time constraints
    //public static final int NUM_GENERATIONS = 1000;
    //public static final int MAX_TIME = 300;

    public static final int NUM_GENERATIONS = 1000;
    public static final int MAX_TIME = 180;

    public static boolean alwaysReloadProblem = true;

    public File directory = null;

    public static void main(String[] args) throws Exception {
        new Multirun().run();
    }

    public Multirun() {
        // empty constructor
    }

    /**
     * Initialises the multirun process with a directory as argument. The console listener
     * is allowed to write some output to files in this directory, allowing further
     * information to be gathered that could be plotted or analysed in a different way.
     */
    public Multirun(File directory) {
        this(directory, NUM_RUNS);
    }

    public Multirun(File directory, int runs) {
        if (directory != null) {
            if (!directory.isDirectory()) {
                throw new RuntimeException("This file is not a directory.");
            }
            this.directory = directory;
        }
        NUM_RUNS = runs;
    }

    public void run() {

        try {

            // Get the problem
            Problem p = null;

            //for (double pXover = 0.6; pXover >= 0; pXover -= 0.1)
            //for (double pMutate = 0.6; pMutate >= 0; pMutate -= 0.1) {

            //System.out.println("XOVER: " + pXover + ", MUTATE: " + pMutate);

            //Vector<ConsoleListener> interfaces = new Vector<ConsoleListener>(NUM_RUNS);

            StatisticsSolver hits = new StatisticsSolver(NUM_RUNS);
            StatisticsSolver inds = new StatisticsSolver(NUM_RUNS);
            StatisticsSolver size = new StatisticsSolver(NUM_RUNS);
            StatisticsSolver time = new StatisticsSolver(NUM_RUNS);

            for (int i = 0; i < NUM_RUNS; i++) {

                if (p == null || alwaysReloadProblem) {
                    p = getProblem();
                }

                if (i == 0) {
                    System.out.println("--------------------------------------------------------------");
                    System.out.println("sxGP EVOLVE MULTIRUN v1.01");
                    System.out.println(p.getName());
                    System.out.println("\nRun, Generation, Fitness, Hits, Size, Inds, Total Time");
                }


                ConsoleListener consoleInterface;

                if (directory == null) {
                    consoleInterface = new ConsoleListener(ConsoleListener.SILENT);
                } else {
                    File f = new File(directory, "Run" + i + ".txt");
                    consoleInterface = new ConsoleListener(ConsoleListener.SILENT, f);
                }

                //interfaces.add(consoleInterface);

                GPParams params = new GPParams();
                params.setGenerations(NUM_GENERATIONS);
                params.setMaxTime(MAX_TIME); // Run for 5 mins
                //params.setCrossoverProbability(pXover);
                //params.setPointMutationProbability(pMutate);

                Evolve e = new Evolve(p, consoleInterface, params);

                e.run();

                hits.addData(consoleInterface.getBestIndividual().getHits());
                inds.addData(consoleInterface.getTotalIndividualsEvaluated());
                size.addData(consoleInterface.getBestIndividual().getTreeSize());
                time.addData(consoleInterface.getTotalTime());

                System.out.print(i);
                System.out.print(", " + consoleInterface.getGeneration());
                System.out.print(", " + consoleInterface.getBestIndividual().getKozaFitness());
                System.out.print(", " + consoleInterface.getBestIndividual().getHits());
                System.out.print(", " + consoleInterface.getBestIndividual().getTreeSize());
                System.out.print(", " + consoleInterface.getTotalIndividualsEvaluated());
                System.out.print(", " + consoleInterface.getTotalTime() + "\n");

                System.gc();

            }

            //System.out.println("\nMULTIRUN RESULTS for problem");

/*
        System.out.println("\nRun, Fitness, Hits, Size, Inds, Total Time");

        for (int i = 0; i < interfaces.size(); i++) {
            ac.essex.gp.interfaces.console.ConsoleListener consoleInterface = interfaces.elementAt(i);
            System.out.print(i);
            System.out.print(", " + consoleInterface.getBestIndividual().getKozaFitness());
            System.out.print(", " + consoleInterface.getBestIndividual().getHits());
            System.out.print(", " + consoleInterface.getBestIndividual().getTreeSize());
            System.out.print(", " + consoleInterface.getTotalIndividualsEvaluated());
            System.out.print(", " + consoleInterface.getTotalTime() + "\n");
        }*/

            /*               DecimalFormat f = new DecimalFormat("0.0");
       //System.out.print(f.format(pXover));
       //System.out.print(", " + f.format(pMutate));
       System.out.println("\nHits Mean, Hits Std Dev, Avg Size, Avg Time");
       System.out.print(f.format(hits.getMean()));
       System.out.print(", " + f.format(hits.getStandardDeviation()));
       System.out.print(", " + f.format(size.getMean()));
       System.out.print(", " + f.format(time.getMean()) + "\n");*/

            //}

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public Problem getProblem() throws Exception {
        //Debugger.NORMALISE_DATA = true;
        //JasmineProject project = JasmineProject.load(new File("/home/ooechs/Desktop/JasmineProjects/Fruit.jasmine"));
        //return new JasmineSegmentationProblem(project);
        return new MathsProblem();
    }


}
