+ BOXCMD="$BOXCMD -c$BOXDIR"
+ echo "Sandbox directory: $BOXDIR"
+ echo "Sandbox command: $BOXCMD"
+ box-clean
+ pend "OK"
+}
+
+function box-clean
+{
+ [ -n "$BOXCMD" ] || die "box-init not called"
+ rm -rf $BOXDIR/*
+}
+
+# Initialization of testing directories
+
+function dir-init
+{
+ pstart "Initializing... "
+ HDIR=.
+ PDIR=problems/$PROBLEM
+ SDIR=solutions/$CONTESTANT/$PROBLEM
+ TDIR=testing/$CONTESTANT/$PROBLEM
+ TMPDIR=tmp
+ [ -d $PDIR ] || die "Problem $PROBLEM not known"
+ [ -d $SDIR ] || fatal "Solution of $PROBLEM not found"
+ mkdir -p $TDIR $TMPDIR
+ rm -rf $TDIR $TMPDIR
+ mkdir -p $TDIR $TMPDIR
+ cat >$TDIR/log <<EOF
+Testing solution of $PROBLEM by $CONTESTANT
+Test started at `date`
+Contestant's solution directory: $SDIR
+Problem directory: $PDIR
+Testing directory: $TDIR
+EOF
+ pend "OK"
+}
+
+# Locating source file in SDIR, pass name in SRCN (without path) and extension in SRCEXT
+
+function locate-source
+{
+ pstart "Finding source... "
+ SBASE=${1:-$PROBLEM}
+ for a in $EXTENSIONS ; do
+ if [ -f $SDIR/$SBASE.$a ] ; then
+ [ -z "$SRCN" ] || die "Multiple source files found: $SDIR/$PROBLEM.$a and $SDIR/$SRCN. Please fix."
+ SRCN=$SBASE.$a
+ SRCEXT=$a
+ fi
+ done
+ [ -n "$SRCN" ] || fatal "NOT FOUND"
+ pend $SRCN
+ echo "Found source file: $SDIR/$SRCN"
+}
+
+# Compilation (compile SDIR/SRCN with PDIR/COMP_EXTRAS to EXE=TDIR/PROBLEM)
+
+function compile
+{
+ pstart "Compiling... "
+ cp -a $SDIR/$SRCN $TDIR/$SRCN
+ if [ -n "$COMP_EXTRAS" ] ; then
+ echo "Extras: $COMP_EXTRAS"
+ for a in $COMP_EXTRAS ; do cp $PDIR/$a $TDIR/ ; done
+ fi
+ box-clean
+ for a in $SRCN $COMP_EXTRAS ; do cp $TDIR/$a $BOXDIR/ ; done
+ SRC=$SRCN
+ EXE=$PROBLEM
+ CCMD=COMP_$SRCEXT
+ CCMD=`eval echo ${!CCMD}`
+ COMP_SANDBOX_OPTS=`eval echo $COMP_SANDBOX_OPTS`
+ echo "Compiler command: $CCMD"
+ echo "Compiler sandbox options: $COMP_SANDBOX_OPTS"
+ eval $COMP_SANDBOX_INIT
+
+ echo "Compiler input files:"
+ ls -Al $BOXDIR
+ echo "Compiler output:"
+ if ! $BOXCMD $COMP_SANDBOX_OPTS -- $CCMD 2>$TDIR/compile.out ; then
+ COMPILE_MSG="`cat $TDIR/compile.out`"
+ pend "FAILED: $COMPILE_MSG"
+ echo "$COMPILE_MSG"
+ return 1
+ fi
+ cat $TDIR/compile.out
+ rm $TDIR/compile.out
+ echo "Compiler output files:"
+ ls -Al $BOXDIR
+ if [ ! -f $BOXDIR/$PROBLEM ] ; then
+ pend "FAILED: Missing executable file"
+ echo "Missing executable file"
+ return 1
+ fi
+ EXE=$TDIR/$PROBLEM
+ cp -a $BOXDIR/$PROBLEM $EXE
+ echo "Compiled OK, result copied to $EXE"
+ pend "OK"
+}
+
+# Running of test program according to current task type (returns exit code and TEST_MSG)
+
+function test-run
+{
+ test-run-$TASK_TYPE
+}
+
+function test-result
+{
+ P=$1
+ M=$2
+ if [ -s $TDIR/$TEST.pts ] ; then
+ P=`cat $TDIR/$TEST.pts`
+ rm $TDIR/$TEST.pts
+ fi
+ echo "Verdict: $M"
+ echo "Points: $P"
+ test-verdict $P "$M"
+}
+
+function test-prolog
+{
+ pcont "<init> "
+ box-clean
+ echo "Executable file: $TDIR/$PROBLEM"
+ if [ ! -x $TDIR/$PROBLEM ] ; then
+ test-result 0 "Compile error."
+ fi
+ cp $TDIR/$PROBLEM $BOXDIR/
+ BOX_EXTRAS=
+ IN_TYPE=${IN_TYPE:-$IO_TYPE}
+ OUT_TYPE=${OUT_TYPE:-$IO_TYPE}
+ case $IN_TYPE in
+ file) echo "Input file: $PROBLEM.in (from $PDIR/$TEST.in)"
+ ln $PDIR/$TEST.in $TDIR/$TEST.in
+ cp $PDIR/$TEST.in $BOXDIR/$PROBLEM.in
+ BOX_EXTRAS="$BOX_EXTRAS -i/dev/null"
+ ;;
+ stdio) echo "Input file: <stdin> (from $PDIR/$TEST.in)"
+ ln $PDIR/$TEST.in $TDIR/$TEST.in
+ cp $PDIR/$TEST.in $BOXDIR/.stdin
+ BOX_EXTRAS="$BOX_EXTRAS -i.stdin"
+ ;;
+ none) echo "Input file: <none>"
+ ;;
+ *) die "Unknown IN_TYPE $IN_TYPE"
+ ;;
+ esac
+ case $OUT_TYPE in
+ file) echo "Output file: $PROBLEM.out"
+ BOX_EXTRAS="$BOX_EXTRAS -o/dev/null"
+ ;;
+ stdio) echo "Output file: <stdout>"
+ BOX_EXTRAS="$BOX_EXTRAS -o.stdout"
+ ;;
+ none) echo "Output file: <none>"
+ ;;
+ *) die "Unknown OUT_TYPE $OUT_TYPE"
+ ;;
+ esac
+ echo "Timeout: $TIME_LIMIT s"
+ echo "Memory: $MEM_LIMIT KB"
+ eval $SANDBOX_INIT
+ echo "Sandbox contents before start:"
+ ls -Al $BOXDIR
+}
+
+function test-epilog
+{
+ echo "Sandbox contents after exit:"
+ ls -Al $BOXDIR
+ case ${OUT_TYPE:-$IO_TYPE} in
+ file) [ -f $BOXDIR/$PROBLEM.out ] || test-result 0 "No output file."
+ cp $BOXDIR/$PROBLEM.out $TDIR/$TEST.out
+ ;;
+ stdio) [ -f $BOXDIR/.stdout ] || test-result 0 "No output file."
+ cp $BOXDIR/.stdout $TDIR/$TEST.out
+ ;;
+ esac
+}
+
+# Running of test program with file input/output
+
+function test-run-file
+{
+ test-prolog
+ pcont "<run> "
+ BOXOPTS="`eval echo $TEST_SANDBOX_OPTS`$BOX_EXTRAS"
+ echo "Sandbox options: $BOXOPTS"
+ if ! $BOXCMD $BOXOPTS -- ./$PROBLEM 2>$TMPDIR/exec.out ; then
+ cat $TMPDIR/exec.out
+ MSG=`tail -1 $TMPDIR/exec.out`
+ test-result 0 "$MSG"
+ fi
+ cat $TMPDIR/exec.out
+ test-epilog
+}
+
+# Running of interactive test programs
+
+function test-run-interactive
+{
+ test-prolog
+ pcont "<run> "
+ BOXOPTS="`eval echo $TEST_SANDBOX_OPTS`$BOX_EXTRAS"
+ echo "Sandbox options: $BOXOPTS"
+ ICCMD=`eval echo $IA_CHECK`
+ echo "Interactive checker: $ICCMD"
+ if ! $HDIR/bin/iwrapper $BOXCMD $BOXOPTS -- ./$PROBLEM @@ $ICCMD 2>$TMPDIR/exec.out ; then
+ cat $TMPDIR/exec.out
+ MSG="`tail -1 $TMPDIR/exec.out`"
+ test-result 0 "$MSG"
+ fi
+ cat $TMPDIR/exec.out
+ test-epilog
+}
+
+# Syntax checks
+
+function syntax-check
+{
+ [ -n "$SYNTAX_CHECK" ] || return 0
+ pcont "<syntax> "
+ SCHECK=`eval echo $SYNTAX_CHECK`
+ echo "Syntax check command: $SCHECK"
+ if ! eval $SCHECK 2>$TMPDIR/exec.out ; then
+ cat $TMPDIR/exec.out
+ MSG=`tail -1 $TMPDIR/exec.out`
+ if [ -z "$MSG" ] ; then MSG="Wrong syntax." ; fi
+ test-result 0 "$MSG"
+ fi
+ cat $TMPDIR/exec.out
+}
+
+# Output checks
+
+function output-check
+{
+ [ -n "$OUTPUT_CHECK" ] || return 0
+ pcont "<check> "
+ [ -f $PDIR/$TEST.out ] && ln $PDIR/$TEST.out $TDIR/$TEST.ok
+ OCHECK=`eval echo $OUTPUT_CHECK`
+ echo "Output check command: $OCHECK"
+ if ! eval $OCHECK 2>$TMPDIR/exec.out ; then
+ cat $TMPDIR/exec.out
+ MSG=`tail -1 $TMPDIR/exec.out`
+ if [ -z "$MSG" ] ; then MSG="Wrong answer." ; fi
+ test-result 0 "$MSG"
+ fi
+ cat $TMPDIR/exec.out
+ MSG=`tail -1 $TMPDIR/exec.out`
+ if [ -z "$MSG" ] ; then MSG="OK" ; fi
+ test-result $POINTS_PER_TEST "$MSG"
+}
+
+# Setup of public commands
+
+function public-setup
+{
+ HDIR=$MO_PUBLIC
+ PDIR=$MO_PUBLIC/problems/$PROBLEM
+ SDIR=.
+ TDIR=~/.test
+ TMPDIR=~/.test
+ [ -d $PDIR ] || die "Unknown problem $PROBLEM"
+
+ pstart "Initializing... "
+ mkdir -p $TDIR
+ rm -rf $TDIR/*
+ BOXDIR=~/.box
+ mkdir -p $BOXDIR