#!/bin/bash
#
# Skrypt do oceniania rozwiazan
#
# sposb uycia:
#   ocen ZADANIE 
# lub
#   ocen ZADANIE TEST
#
#

DIR=`pwd`
BINDIR=$DIR/bin
INDIR=$DIR/in
OUTDIR=$DIR/out
RUNDIR=$DIR/run

BIN_TIME=/usr/bin/time
BIN_COMPARE=$BINDIR/compare

# domyslne wartosci
TIMELIMIT=30
MEMLIMIT=unlimited   # limit wykorzysztania pamieci przez program (KiB)
SRCLIMIT=100     # limit na rozmiar pliku zrodlowego (KiB)
EXELIMIT=5120   # limit na rozmiar pliku wykonywalnego (KiB) = 5MiB

#if [ -f /etc/oi.conf ] ; then . /etc/oi.conf ; fi
if [ -f "$DIR/oi.conf" ] ; then . "$DIR/oi.conf" ; fi

export EXELIMIT SRCLIMIT

OCENBIN=$0
TASK="$1"
TEST="$2"
OPT="$3"

CHECKER=$BIN_COMPARE

EXIT_NORMAL=0
EXIT_TLIMIT=9

###################################

function help() {
    cat <<EOF
    Ocen4Linux
----------------------

Sposob uzycia:

 ocen ID_ZADANIA 

    by przetestowac rozwiazanie na wszystkich testach dla danego zadania


 ocen ID_ZADANIA NR_TESTU

    by przetestowac na konkretnym tescie

EOF
    exit 0
}

function error() {
    echo "BLAD: $1"
    exit 1
}

function _init() { foo="bar"; }
function _done() { foo="bar"; }
function _tst_before() { foo="bar"; }
function _tst_after() { foo="bar"; }

if [ -f "$HOME/bin/ocen-extra" ] ; then . "$HOME/bin/ocen-extra" ; fi

###################################
# sprawdzanie podanych argumentow
#
function check() {
    if [ -z "$TASK" ] ; then
	help
    fi

    TASK=`echo $TASK | tr A-Z a-z` # zadanie powinno byc pisane malymi literami

    if [ -z "`echo "$TASKS" | grep "$TASK"`" ] ; then
        error "Nieznane zadanie: $TASK"
    fi

    if [ -n "$TEST" ] ; then
        if [ ! -f "$INDIR/${TASK}${TEST}.in" ] ; then
    	    error "Brak pliku: ${TASK}${TEST}.in"
	fi

        if [ ! -f "$OUTDIR/${TASK}${TEST}.out" ] ; then
    	    error "Brak pliku: ${TASK}${TEST}.out"
	fi
    fi

    SOL=""
    for ext in e c cpp pas py ; do
        if [ -f "${TASK}.${ext}" ] ; then
	    ok=0
	    if [ -z "$SOL_EXT" ] ; then
		ok=1
	    else
		if [ "${TASK}.${ext}" -nt "${TASK}.${SOL_EXT}" ] ; then
		    ok=1
		fi
	    fi
	    
	    if [ $ok -eq 0 ] ; then continue; fi
    
    	    SOL=${TASK}.${ext}
    	    SOL_EXT=$ext
        fi
    done

    if [ -z "$SOL" ] ; then
        error "Brak rozwiazania dla zadania: $TASK"
    fi

    if [ "$SOL_EXT" != "e" ] ; then
	# trzeba skompilowac
        if [ "$SOL_EXT" = "py" ]; then
            PYFILE="$SOL"
            GRADER="${DIR}/dlazaw/${TASK}grader.py"
            if [ -f "$GRADER" ]; then
                PYFILE="$GRADER"
            fi
            echo "#!/usr/bin/env python3" |cat - "$PYFILE" > "${TASK}.e"
            chmod a+x "${TASK}.e"
        else
            if ! $BINDIR/compile $SOL ; then
                error "Blad podczas kompilacji: $SOL"
            fi
        fi
        SOL=${TASK}.e
    fi

    if [ -f "$BINDIR/${TASK}chk.e" ] ; then
        CHECKER="$BINDIR/${TASK}chk.e"
    fi
}

####################################

function check_test() {
    _tst_before
    IN="${INDIR}/${TASK}${TEST}.in"
    OUT=${TASK}.out

    # trzeba skopiowac test (juz nie)
    # cp $INDIR/${TASK}${TEST}.in ${TASK}.in || error "Blad podczas kopiowania: ${TASK}${TEST}.in"
    
    # usunac istniejacy out
    rm -f "$OUT"

    ESC="\033"
    printf "$ESC[32mTest %-3s $ESC[0m-- " $TEST

    # uruchomic program
    TMP_FILE="/tmp/tmpfile.$$"
    ( ulimit -t $TIMELIMIT -v $MEMLIMIT ; $BIN_TIME -f "%U" -o $TMP_FILE ./$SOL < $IN > $OUT )
    RUN_RES=$?
    TIME_RES=`tail -n1 "$TMP_FILE"`
    rm -f "$TMP_FILE"

    # wypisac czas
    printf "%5s " "$TIME_RES" 

    TST_RES="???"
    CHK_TXT=""
    if [ $RUN_RES -eq $EXIT_NORMAL ] ; then    

	if [ -f "$OUT" ] ; then 

	    # porownac wyniki

	    if [ "$CHECKER" = "$BIN_COMPARE" ] ; then
		$CHECKER "$OUT" "$OUTDIR/${TASK}${TEST}.out" "$INDIR/${TASK}${TEST}.in" > $TMP_FILE
	    else
		$CHECKER "$OUT" "$OUTDIR/${TASK}${TEST}.out" "$INDIR/${TASK}${TEST}.in" > $TMP_FILE
	    fi

	    CHK_RES=`head -n1 $TMP_FILE`
	    CHK_TXT=`tail -n1 $TMP_FILE`
   	    rm -f "$TMP_FILE"

	    if [ "$CHK_RES" = "OK" ] ; then
	        TST_RES="OK"
	    else
		TST_RES="ZLA ODPOWIEDZ"
	    fi
	else
	    TST_RES="BRAK ODPOWIEDZI"
	fi
    elif [ $RUN_RES -eq $EXIT_TLIMIT ] ; then
    	TST_RES="PRZEKROCZENIE CZASU"
    else
	TST_RES="BLAD WYKONANIA (KOD $RUN_RES)"
    fi

    printf "$TST_RES\n"
    if [ "$OPT" != "quiet" ] ; then
	if [ -n "$CHK_TXT" -a "$TST_RES" != "OK" ] ; then
	    echo "     >> $CHK_TXT"
	fi
    fi

    _tst_after
}

function check_task() {
    echo "Zadanie: $TASK, Rozwiazanie: $SOL"
    echo "---"
    for i in `eval echo '$TESTS_'${TASK}` ; do
	$0 $TASK $i "std"
    done
}

####################################

_init
check
if [ -z "$TEST" ] ; then
    check_task
else
    check_test
fi
_done
