#!/bin/bash
###############################################################################
# This script is run for each candidate to evaluate it after all
# candidate configurations have been run on a single instance.
#
# Check the examples in examples/
#
# PARAMETERS:
# $1 is the ID of the candidate to be evaluated
# $2 is the instance ID
# $3 is the seed
# $4 is the instance name
# $5 is the total number of candidates
# The rest are the IDs of all candidates run for this instance
#
# RETURN VALUE:
# This script should print a single numerical value
###############################################################################
NORMALIZATION_RANGE="'1 2'"
REFERENCE_POINT="'1.1 1.1'"

# A program that normalizes all _dat files to [0, 1]
# (optional, not included).
NORMALIZE="~/bin/nondominated --verbose -n $NORMALIZATION_RANGE -s '_nor'"
UPDATELIMITS="2>&1 | grep -E 'minimum|maximum'  | sed  's/:/:\n/'"

# A program for computing the hypervolume. Download hypervolume
# code from http://iridia.ulb.ac.be/~manuel/hypervolume
HV="~/bin/hv --quiet -r $REFERENCE_POINT"

CANDIDATE="$1"
INSTANCEID="$2"
SEED="$3"
INSTANCE="$4"
TOTALCANDIDATES="$5"
shift 5 || error "Not enough parameters to $0"
ALLIDS=$*

STDOUT=c${CANDIDATE}-${INSTANCEID}.stdout
STDERR=c${CANDIDATE}-${INSTANCEID}.stderr

# TODO: Use /tmp for all temporary files, i.e., put target-data under /tmp
cd target-data || error "cannot change to directory 'target-data'"

ALLFILES=
for FILENAME in ALLIDS; do
    ALLFILES="$ALLFILES c${FILENAME}-${INSTANCEID}.stdout"
done

calc_measure() {
    LIMITSFILE=limits-${INSTANCEID}.txt
    LIMITSTMP=limits-${INSTANCEID}.tmp
    if [ -s "$LIMITSFILE" ]; then
        $NORMALIZE $LIMITSFILE $ALLFILES $UPDATELIMITS > $LIMITSTMP
        mv $LIMITSTMP $LIMITSFILE
    else
        $NORMALIZE $ALLFILES $UPDATELIMITS > $LIMITSFILE
    fi
}

# First normalize output files, unless they are ready.
while ! ls ${ALLFILES}_nor &> /dev/null ; do
    # Check that all output files are there
    NUM=$(ls -1 ${ALLFILES} 2> /dev/null | wc --lines)
    if [ "$NUM" -ne "$TOTALCANDIDATES" ]; then
        error_sleep "only found $NUM files out of $TOTALCANDIDATES"
        continue
    fi
    # Check every STDERR
    for FILENAME in $ALLFILES; do
        FILESTDERR=${FILENAME/stdout/stderr}
        [ OK = "$(cat ${FILESTDERR})" ] || (error_sleep "${FILESTDERR} is not OK"; continue)
        [ -s "$FILENAME" ] || (error_sleep "$FILENAME is empty"; continue)
    done
    calc_measure
    rm -f error.log
    TODELETE=$(comm -23 <(ls -1 c*-${INSTANCEID}.* | sort) <(ls -1 $ALLFILES))
    # Comment out if you wish to keep all output files around
    echo "rm -f $TODELETE"
done

if [ -s "${STDOUT}_nor" ]; then
    COST=$($HV ${STDOUT}_nor || error "calculating hypervolume failed")
    # Negative because hypervolume is maximised but irace minimises.
    echo "-$COST"
    exit 0
else
    error "${STDOUT}_nor: No such file or directory"
fi

error() {
    echo "`TZ=UTC date`: error: $@"
    if [ -s error.log ]; then
        cat error.log
    fi
    exit 1
}

error_sleep() {
    echo "`TZ=UTC date`: error: $@" >> error.log
    sleep 60
}
