package ac.essex.ooechs.facedetection.util;

import ac.essex.gp.problems.Problem;
import ac.essex.gp.problems.DataStack;
import ac.essex.gp.individuals.Individual;
import ac.essex.gp.Evolve;
import ac.essex.ooechs.facedetection.util.IntegralTrainingImage;
import ac.essex.ooechs.facedetection.util.DataSet;
import ac.essex.ooechs.facedetection.singlestage.nodes.FeatureUtils;

import java.util.Vector;

/**
 * Common stuff for the detection experiments. Saves repetition,
 *
 * @author Olly Oechsle, University of Essex, Date: 20-Jun-2008
 * @version 1.0
 */
public abstract class AbstractDetectionProblem extends Problem {

    public static int generations = 150;
    
    public Vector<IntegralTrainingImage> trainingData, testingData;

    public AbstractDetectionProblem(DataSet training, DataSet testing) {
        trainingData = training.getData();
        if (testing != null) {
            testingData = testing.getData();
        }        
    }

    public String test(Individual individual) {

        StringBuffer buffer = new StringBuffer();

        test(buffer, individual, trainingData, false);

        if (testingData != null) {
            buffer.append(", ");
            test(buffer, individual, testingData, true);
        }

        buffer.append("\n");

        return buffer.toString();

    }

    protected void test(StringBuffer buffer, Individual ind, Vector<IntegralTrainingImage> testData, boolean clearCaches) {

        DataStack dataStack = new DataStack();

        int totalTP = 0;
        int totalTN = 0;

        int TP = 0;
        int TN = 0;

        int mistakes = 0;

        for (int i = 0; i < testData.size(); i++) {
            IntegralTrainingImage integralTrainingImage = testData.elementAt(i);

            dataStack.setIntegralImage(integralTrainingImage.getImage());

            double raw = ind.execute(dataStack);

            int result;

            if (ind.getPCM() != null) {
                result = ind.getPCM().getClassFromOutput(raw);
            } else {
                result = raw > 0 ? DataSet.TRUE : DataSet.FALSE;
            }

            if (result == integralTrainingImage.classID) {
                if (integralTrainingImage.classID == DataSet.TRUE) TP++;
                if (integralTrainingImage.classID == DataSet.FALSE) TN++;
            } else {
                mistakes++;
            }

            if (integralTrainingImage.classID == DataSet.TRUE) {
                totalTP++;
            } else {
                totalTN++;
            }

            if (clearCaches) {
                integralTrainingImage.clearImage();
            }

        }

        buffer.append(TP / (double) totalTP);
        buffer.append("," + TN / (double) totalTN);
        buffer.append("," + (mistakes / (double) testData.size()));
        buffer.append(", " + ind.getTreeSize());

    }

}
