function [y res avgres] = calcScoreFCSC(path_pred, partition, createGraphs)
%PRE:  path_pred is path to prediction. partition is either 'test' or
%'devel'.
%POST: y is final score (average xcorr over all sequences and dimensions)
%      res is a struct with detailed results and ground truth
%      results are stored in a file in the path_pred directory


    if ~exist('createGraphs', 'var')
        createGraphs = 1;
    end
    pat = regexp(path_pred, '/');
    if length(path_pred) ~= pat(end)
        error('Prediction path must have trailing /');
    end
    y = 0;
    N = 32; % - Nr sessions, equal for test and development partitions
        
    for i = 1:N
        fprintf(1, 'Processing test session %u/%u\n', i, N);
        res(i).truth.arousal = readTruth(i, 'arousal', partition);
        res(i).truth.expectancy = readTruth(i, 'expectancy', partition);
        res(i).truth.power = readTruth(i, 'power', partition);
        res(i).truth.valence = readTruth(i, 'valence', partition);
        
        res(i).pred.arousal = readPred(path_pred, i, 'arousal', partition);
        res(i).pred.expectancy = readPred(path_pred, i, 'expectancy', partition);
        res(i).pred.power = readPred(path_pred, i, 'power', partition);
        res(i).pred.valence = readPred(path_pred, i, 'valence', partition);
        
        res(i) = modifyPredictionToFitTruth(res(i));
        
        fprintf(1, '\tCalculating correlations...');
        res(i).xcorr.arousal = calccorr(res(i).truth.arousal, ...
            res(i).pred.arousal);
        res(i).xcorr.expectancy = calccorr(res(i).truth.expectancy, ...
            res(i).pred.expectancy);
        res(i).xcorr.power = calccorr(res(i).truth.power, ...
            res(i).pred.power);
        res(i).xcorr.valence = calccorr(res(i).truth.valence, ...
            res(i).pred.valence);
        fprintf(1, '[DONE]\n');
        
        fprintf(1, '\tCalculating RMS...');
        res(i).rms.arousal = calcrms(res(i).truth.arousal, ...
            res(i).pred.arousal);
        res(i).rms.expectancy = calcrms(res(i).truth.expectancy, ...
            res(i).pred.expectancy);
        res(i).rms.power = calcrms(res(i).truth.power, ...
            res(i).pred.power);
        res(i).rms.valence = calcrms(res(i).truth.valence, ...
            res(i).pred.valence);
        fprintf(1, '[DONE]\n\n');
        
        y = y + res(i).xcorr.arousal + res(i).xcorr.expectancy + ...
            res(i).xcorr.power + res(i).xcorr.valence;
    end
    y = abs(y/(4*N));
    avgres = calcAverageResultsPerDimension(res);
    fprintf(1, 'Saving results to file...\t');
    saveResults(res, path_pred, partition);
    fprintf(1, '[DONE]\n');
    if createGraphs
        fprintf(1, 'Creating graphs of results, and saving them to file...\t');
        saveGraphics(res, path_pred, partition);
        fprintf(1, '[DONE]\n');
    end
end


function A = calcAverageResultsPerDimension(R)
% -- Calculate the average xcorr and rms per dimension
    n = length(R);
    
    A.arousal.avgxcorr = 0;
    A.expectancy.avgxcorr = 0;
    A.power.avgxcorr = 0;
    A.valence.avgxcorr = 0;
    A.arousal.avgrms = 0;
    A.expectancy.avgrms = 0;
    A.power.avgrms = 0;
    A.valence.avgrms = 0;
    
    for i=1:n
        A.arousal.avgxcorr = A.arousal.avgxcorr + R(i).xcorr.arousal/n;
        A.expectancy.avgxcorr = A.expectancy.avgxcorr + R(i).xcorr.expectancy/n;
        A.power.avgxcorr = A.power.avgxcorr + R(i).xcorr.power/n;
        A.valence.avgxcorr = A.valence.avgxcorr + R(i).xcorr.valence/n;
        A.arousal.avgrms = A.arousal.avgrms + R(i).rms.arousal/n;
        A.expectancy.avgrms = A.expectancy.avgrms + R(i).rms.expectancy/n;
        A.power.avgrms = A.power.avgrms + R(i).rms.power/n;
        A.valence.avgrms = A.valence.avgrms + R(i).rms.valence/n;
    end
    A.arousal.avgxcorr = abs(A.arousal.avgxcorr);
    A.expectancy.avgxcorr = abs(A.expectancy.avgxcorr);
    A.power.avgxcorr = abs(A.power.avgxcorr);
    A.valence.avgxcorr = abs(A.valence.avgxcorr);

end

function saveResults(R, p, part)
% -- Save the results R in a file on path p to email to participants
    pat = regexp(p, '/');
    name = p(pat(end-1)+1:pat(end)-1);
    fn = [p name '_FCSC_' part '.txt'];
    
    A = calcAverageResultsPerDimension(R);
    fid = fopen(fn, 'w');
    
    fprintf(1, 'FCSC results on %s partition for %s\n\n', part, name);
    fprintf(1, '\t\tCorrelation\tRMS\n');
    fprintf(1, 'Arousal\t\t%1.4f\t\t%1.4f\n', A.arousal.avgxcorr, A.arousal.avgrms);
    fprintf(1, 'Expectancy\t%1.4f\t\t%1.4f\n', A.expectancy.avgxcorr, A.expectancy.avgrms);
    fprintf(1, 'Power\t\t%1.4f\t\t%1.4f\n', A.power.avgxcorr, A.power.avgrms);
    fprintf(1, 'Valence\t\t%1.4f\t\t%1.4f\n', A.valence.avgxcorr, A.valence.avgrms);
    fprintf(1, '-------------------------------------------\n');
    fprintf(1, 'Mean\t\t%1.4f\t\t%1.4f\n', mean([A.arousal.avgxcorr, A.expectancy.avgxcorr ...
        A.power.avgxcorr, A.valence.avgxcorr]), mean([A.arousal.avgrms ...
        A.expectancy.avgrms, A.power.avgrms, A.valence.avgrms]));
    
    fprintf(fid, 'FCSC results on %s partition for %s\n\n', part, name);
    fprintf(fid, '\t\tCorrelation\tRMS\n');
    fprintf(fid, 'Arousal\t\t%1.4f\t\t%1.4f\n', A.arousal.avgxcorr, A.arousal.avgrms);
    fprintf(fid, 'Expectancy\t%1.4f\t\t%1.4f\n', A.expectancy.avgxcorr, A.expectancy.avgrms);
    fprintf(fid, 'Power\t\t%1.4f\t\t%1.4f\n', A.power.avgxcorr, A.power.avgrms);
    fprintf(fid, 'Valence\t\t%1.4f\t\t%1.4f\n', A.valence.avgxcorr, A.valence.avgrms);
    fprintf(fid, '------------------------------------------\n');
    fprintf(fid, 'Mean\t\t%1.4f\t\t%1.4f\n', mean([A.arousal.avgxcorr, A.expectancy.avgxcorr ...
        A.power.avgxcorr, A.valence.avgxcorr]), mean([A.arousal.avgrms ...
        A.expectancy.avgrms, A.power.avgrms, A.valence.avgrms]));
    
    fclose(fid);
end

function saveGraphics(R, p, part)
% -- Create graphs. If this is the test partition, these should NOT be
% emailed to the participants
% R is a result struct
% p is the path to save figures in
% part is the partition

    pat = regexp(p, '/');
    name = p(pat(end-1)+1:pat(end)-1);
    %dimensions = {'arousal','expectancy','power','valence'};

    % -- Create appropriate data structures
    
        truth_arousal = seqdata;
        pred_arousal = seqdata;
        
        truth_expectancy = seqdata;
        pred_expectancy = seqdata;
        
        truth_power = seqdata;
        pred_power = seqdata;
        
        truth_valence = seqdata;
        pred_valence = seqdata;
        
        for i = 1:length(R)
            n = numel(R(i).truth.arousal);
            truth_arousal = adddata(truth_arousal, data(zeros(n,1), R(i).truth.arousal));
            pred_arousal = adddata(pred_arousal, data(zeros(n,1), R(i).pred.arousal));
            
            truth_expectancy = adddata(truth_expectancy, data(zeros(n,1), R(i).truth.expectancy));
            pred_expectancy = adddata(pred_expectancy, data(zeros(n,1), R(i).pred.expectancy));
            
            truth_power = adddata(truth_power, data(zeros(n,1), R(i).truth.power));
            pred_power = adddata(pred_power, data(zeros(n,1), R(i).pred.power));
            
            truth_valence = adddata(truth_valence, data(zeros(n,1), R(i).truth.valence));
            pred_valence = adddata(pred_valence, data(zeros(n,1), R(i).pred.valence));
        end
        
        fn_graph = [p name '_FCSC_' 'arousal' '_' part];
        fig = createFcscResultsGraph(truth_arousal, pred_arousal, 1, name, 'arousal', part);
        print('-depsc2', sprintf( '%s.eps',fn_graph));
        fixPSlinestyle(sprintf( '%s.eps',fn_graph), sprintf( '%s_final.eps',fn_graph));
        delete(sprintf( '%s.eps',fn_graph));    % - Delete temporary
        close(fig);
        
        fn_graph = [p name '_FCSC_' 'expectancy' '_' part '.fig'];
        fig = createFcscResultsGraph(truth_expectancy, pred_expectancy, 1, name, 'expectancy', part);
        print('-depsc2', sprintf( '%s.eps',fn_graph));
        fixPSlinestyle(sprintf( '%s.eps',fn_graph), sprintf( '%s_final.eps',fn_graph));
        delete(sprintf( '%s.eps',fn_graph));    % - Delete temporary
        close(fig);
        
        fn_graph = [p name '_FCSC_' 'power' '_' part];
        fig = createFcscResultsGraph(truth_power, pred_power, 1, name, 'power', part);
        print('-depsc2', sprintf( '%s.eps',fn_graph));
        fixPSlinestyle(sprintf( '%s.eps',fn_graph), sprintf( '%s_final.eps',fn_graph));
        delete(sprintf( '%s.eps',fn_graph));    % - Delete temporary
        close(fig);
        
        fn_graph = [p name '_FCSC_' 'valence' '_' part];
        fig = createFcscResultsGraph(truth_valence, pred_valence, 1, name, 'valence', part);
        print('-depsc2', sprintf( '%s.eps',fn_graph));
        fixPSlinestyle(sprintf( '%s.eps',fn_graph), sprintf( '%s_final.eps',fn_graph));
        delete(sprintf( '%s.eps',fn_graph));    % - Delete temporary
        close(fig);
end


function y = readTruth(i, dim, partition)
    fprintf(1, '\tLoading ground truth for %s...', dim);
    ddir = '/Users/mfv/Documents/data/AVEC2012/';  % - Partiticipants will have different base directory
    if strcmp(partition, 'test')
        tdir = [ddir 'private/FCSC/labels/test/']; % - FCSC test labels, participants won't have this
    else
        tdir = [ddir 'public/FCSC/labels/devel/']; % - FCSC test labels
    end
    fn = sprintf('%slabels_continuous_%s%.3u_%s.dat', tdir, partition, i, dim);
    y = load(fn, '-ASCII');
    fprintf(1, '[DONE]\n');
end

function y = readPred(p, i, dim, partition)
    fprintf(1, '\tLoading predictions for %s...', dim);
    
    % -- Hardcoded Laurens emulator :/
    if ~isempty(regexp(p, 'delft', 'once')) && strcmp(dim, 'expectancy')
        if isempty(regexp(p, 'Final', 'once'))
            dim = 'expectation';
        end
    end
    
    fn = sprintf('%slabels_continuous_%s%.3u_%s.dat', p,  partition, i, dim);
    % -- Give AVEC2011 style filenaming a chance...
    if ~exist(fn, 'file')
        fn = sprintf('%slabels_continuous_%ss%.3u_%s.dat', p,  partition, i, dim);
    end
    if ~exist(fn, 'file')
        error('Participant using incorrect filenaming: %s\n', fn);
    end
    
    y = load(fn, '-ASCII');
    fprintf(1, '[DONE]\n');
end

function R = modifyPredictionToFitTruth(R)
    n_t = numel(R.truth.arousal);
    n_p = numel(R.pred.arousal);
    
    if n_t > n_p
        dif = n_t - n_p;
        fprintf(1, 'Prediction has %u fewer instances than ground truth, appending last prediction to fix this\n', dif);
        R.pred.arousal(end+1:end+dif) = R.pred.arousal(end);
        R.pred.expectancy(end+1:end+dif) = R.pred.expectancy(end);
        R.pred.power(end+1:end+dif) = R.pred.power(end);
        R.pred.valence(end+1:end+dif) = R.pred.valence(end);
    else
        if n_p > n_t
            dif = n_p - n_t;
            fprintf(1, 'Prediction has %u more instances than ground truth, removing rear block of predictions to fix this\n', dif);
            R.pred.arousal = R.pred.arousal(1:n_t);
            R.pred.expectancy = R.pred.expectancy(1:n_t);
            R.pred.power = R.pred.power(1:n_t);
            R.pred.valence = R.pred.valence(1:n_t);
        end
    end
end

function c = calccorr(x, y)
    C = corrcoef(x, y);
    c = C(1,2);
    if isnan(c)
        warning('NaN score while calculating correlation!\n');
        c = 0;
    end
end

function r = calcrms(x, y)
    r = sqrt(sum((x-y).^2));
    if isnan(r)
        warning('NaN score while calculating RMS score!\n');
        r = 0;
    end
end