diff --git a/README.md b/README.md index a7295f4..6bab481 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ Hello. This is a bundle of scripts used to prepare competitive programming problems -File descriptions: +To make a project, while in this directory, call ./makeproject */path/to/where/project/should/be*. -README.md | This readme +Description of a project's structure: + +File name | Description --------- | ----------- problemconfig.sh | A script that sets problem configuration variables (i.e. $problemname, $timelimit) lib.sh | A bash library, used for the scripts in this bundle diff --git a/examples/aorib/buildtests.sh b/examples/aorib/buildtests.sh new file mode 100755 index 0000000..d57de12 --- /dev/null +++ b/examples/aorib/buildtests.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# +# This builds all tests using testmanifest +# Tamio-Vesa Nakajima + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# Make stage (as git deletes it) +mkdir -p stage + +# We will want to remember this: +currtest=0 + +# Loop over lines of +cat testmanifest | while read instr; do + # Parse a line of testmanifest + set $instr + numberoftests=$1 + incf=$2 + totalpoints=$3 + points=$(($totalpoints / $numberoftests)) + + for nr in `seq $currtest $(($currtest + $numberoftests - 1))` ; do + echo $nr + ################# + # Build input: + ################# + + # Build input generator + try "cd ingen && make -s && cd .." "input generator build fail" + + # Copy ingen/ingen.bin and incf/$1 into stage + cp ingen/ingen.bin stage/$problemname.bin + try "cp incf/$incf stage/$problemname.cf" "incf/$incf doesn't exist" + + # Build input + try "cd stage && ./$problemname.bin > ../tests/$problemname-$nr.in && cd .." "input generation fail" + + # Clean stage + rm stage/* + + ################### + # Build ok + ################### + + # Build ok generator + try "cd okgen && make -s && cd .." "ok generator build fil" + + # Copy ok generator and input into stage + cp okgen/okgen.bin stage/$problemname.bin + cp tests/$problemname-$nr.in stage/$problemname.in + + # Indicate the number of points in the stage + echo $points > stage/$problemname.points + + # Build ok + try "cd stage && ./$problemname.bin && cd .." "ok generation fail" + + # Copy ok from stage into tests + cp stage/$problemname.ok tests/$problemname-$nr.ok + + # Clean stage + rm stage/* + done + + #update currtest + currtest=$(($currtest + $numberoftests)) + +done diff --git a/examples/aorib/eval/eval.bin b/examples/aorib/eval/eval.bin new file mode 100755 index 0000000..d03e57d Binary files /dev/null and b/examples/aorib/eval/eval.bin differ diff --git a/examples/aorib/eval/eval.cpp b/examples/aorib/eval/eval.cpp new file mode 100644 index 0000000..eb52b30 --- /dev/null +++ b/examples/aorib/eval/eval.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +using namespace std; + +int main(){ + ifstream fout("aorib.out"); + ifstream fok("aorib.ok"); + + int points = 0; + fok >> points; + + string s1, s2; + while(fok >> s1){ + if(!bool(fout >> s2) || s1 != s2){ + cerr << "WA" << endl; + cout << 0 << endl; + return 0; } } + + cerr << "OK" << endl; + cout << points << endl; + return 0; } diff --git a/examples/aorib/eval/makefile b/examples/aorib/eval/makefile new file mode 100644 index 0000000..2abe5c6 --- /dev/null +++ b/examples/aorib/eval/makefile @@ -0,0 +1,2 @@ +../eval/eval.bin: + g++ eval.cpp -std=c++11 -o ../eval/eval.bin diff --git a/examples/aorib/incf/fixed b/examples/aorib/incf/fixed new file mode 100644 index 0000000..722ff38 --- /dev/null +++ b/examples/aorib/incf/fixed @@ -0,0 +1 @@ +1 0 1 diff --git a/examples/aorib/incf/makefile b/examples/aorib/incf/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/incf/random b/examples/aorib/incf/random new file mode 100644 index 0000000..a5c7b77 --- /dev/null +++ b/examples/aorib/incf/random @@ -0,0 +1 @@ +0 0 0 diff --git a/examples/aorib/ingen/ingen.bin b/examples/aorib/ingen/ingen.bin new file mode 100755 index 0000000..078734f Binary files /dev/null and b/examples/aorib/ingen/ingen.bin differ diff --git a/examples/aorib/ingen/ingen.cpp b/examples/aorib/ingen/ingen.cpp new file mode 100644 index 0000000..b59f1f5 --- /dev/null +++ b/examples/aorib/ingen/ingen.cpp @@ -0,0 +1,16 @@ +#include +#include +using namespace std; + +int main(){ + ifstream f("aorib.cf"); + ofstream g("aorib.in"); + bool fixed; + int x, y; + f >> fixed >> x >> y; + + if(fixed) g << x << ' ' << y << endl; + else{ + srand(time(nullptr)); + g << rand() << ' ' << rand() << endl; } + return 0; } diff --git a/examples/aorib/ingen/makefile b/examples/aorib/ingen/makefile new file mode 100644 index 0000000..ae4ea9c --- /dev/null +++ b/examples/aorib/ingen/makefile @@ -0,0 +1,2 @@ +../ingen/ingen.bin: + g++ ingen.cpp -std=c++11 -o ../ingen/ingen.bin diff --git a/examples/aorib/lib.sh b/examples/aorib/lib.sh new file mode 100644 index 0000000..cfee486 --- /dev/null +++ b/examples/aorib/lib.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# +# Bash library for this project +# Tamio-Vesa Nakajima + +# Tries to execute $1 ; if this succeeds, do nothing +# otherwise, output $2 +try () { + if eval $1 ; then + : + else + echo $2 + exit 1 + fi +} + +# Tries to copy $1 to $2 ; if $1 doesn't exist, creates an empty $2 +maybecp () { + if [ -f $1 ] ; then + cp $1 $2 + else + touch $2 + fi +} + +# Evaluates the binary $1 with test $2, returning the message in $message, the time used in $timeUsed and the points in $points +evaluate_src_test () { + binary=$1 + testname=$2 + + # Get an appropriate timeout command + timeoutCommand=timeout + + if [[ "$OSTYPE" == "darwin"* ]] ; then + timeoutCommand=gtimeout + fi + + # Fetch the problem configuration + source problemconfig.sh + + # clear any previous messages + echo -en " \r" + + # Output an appropriate messgae + echo -en "Doing $testname\r" + + # Clean the stage + rm stage/* + + # Copy the binary into the stage + cp $binary stage/$problemname.bin + + # Copy the input into the stage + cp tests/$testname.in stage/$problemname.in + + # Get the problem config + source problemconfig.sh + + # This string runs the competitor's executable + runExec="./$problemname.bin > /dev/null 2> /dev/null" + + # This string runs the competitors executable with an appropriate timeout + runExecWithTimeout="$timeoutCommand $timelimit $runExec" + + # Run the competitors executable with a timeout, and store the time used in timeUsed + timeUsed=$(cd stage && { time $runExecWithTimeout ; } 2>&1 >/dev/null \ + | tail -3 \ + | head -1 \ + | awk -F ' ' '{print $2}' \ + | awk -F 'm' '{print $2}' \ + | awk -F 's' '{print $1}' && cd ..) + + if (( $(echo "$timeUsed > $timelimit" | bc -l))) ; then + # Set the return values + # timeUsed is already set + message=TLE + points=0 + else + # Make the evaluator + try "cd eval && make -s && cd .." "evaluator build fail" + + # Copy the evaluator into the stage + cp eval/eval.bin stage/eval.bin + + # Copy the ok file into the stage + cp tests/$testname.ok stage/$problemname.ok + + # Create temporary files to hold the points and the eval message + pointsFile=`mktemp` + messageFile=`mktemp` + + # Enter the stage and evaluate, storing the results in $pointsFile and $messageFile + try "cd stage && ./eval.bin > $pointsFile 2> $messageFile && cd .." "eval error" + + # Set the return values + # timeUsed is already set + points=`cat $pointsFile` + message=`cat $messageFile` + fi +} diff --git a/examples/aorib/okgen/makefile b/examples/aorib/okgen/makefile new file mode 100644 index 0000000..0bc29f0 --- /dev/null +++ b/examples/aorib/okgen/makefile @@ -0,0 +1,2 @@ +../okgen/okgen.bin: + g++ okgen.cpp -std=c++11 -o ../okgen/okgen.bin diff --git a/examples/aorib/okgen/okgen.bin b/examples/aorib/okgen/okgen.bin new file mode 100755 index 0000000..c5e0513 Binary files /dev/null and b/examples/aorib/okgen/okgen.bin differ diff --git a/examples/aorib/okgen/okgen.cpp b/examples/aorib/okgen/okgen.cpp new file mode 100644 index 0000000..9d7d3cb --- /dev/null +++ b/examples/aorib/okgen/okgen.cpp @@ -0,0 +1,14 @@ +#include +using namespace std; + +int main(){ + ifstream points("aorib.points"); + ifstream f("aorib.in"); + ofstream g("aorib.ok"); + + long long p, x, y; + f >> x >> y; + points >> p; + g << p << endl; + g << x*y << endl; + return 0; } diff --git a/examples/aorib/problemconfig.sh b/examples/aorib/problemconfig.sh new file mode 100644 index 0000000..eb06f31 --- /dev/null +++ b/examples/aorib/problemconfig.sh @@ -0,0 +1,2 @@ +problemname=aorib +timelimit=0.1 diff --git a/examples/aorib/run.sh b/examples/aorib/run.sh new file mode 100755 index 0000000..c5067cf --- /dev/null +++ b/examples/aorib/run.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Runs sources on tests +# Tamio-Vesa Nakajima +# +# Use cases: +# ./run.sh -> runs all sources on all tests +# ./run.sh -s "a.cpp b.cpp" -s c.cpp -> runs a,b,c.cpp on all tests +# ./run.sh -t "00 01 02" -> runs all sources on tests 00, 01, 02 +# ./run.sh -s a.cpp -t 00 -> runs a.cpp on 00 + +########################## +# GENERAL SETUP +######################### + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# make stage (as git deletes it) +mkdir -p stage + +############################ +# ARGUMENT PARSING +############################# + +# default values for used sources and used tests + +srcs="" +tests="" + +while getopts "hs:t:" opt; do + case $opt in + h) + echo "Usage: ./run.sh -s [source] -t [test]" + exit 0 + ;; + s) + for x in $OPTARG ; do + srcs="$srcs $x" + done + ;; + t) + for x in $OPTARG ; do + tests="$tests $problemname-$x" + done + ;; + esac +done + +if [ -z "$srcs" ] ; then + srcs=`ls -1 src | grep .cpp` +fi + +if [ -z "$tests" ] ; then + tests=`ls -1 tests | grep .in | awk -F '.' '{print $1}'` +fi + +tests=`echo $tests | sort -t '-' -k 1 -n` + + +########################### +# EVALUATING +########################## + +for src in $srcs ; do + # Copy the source into the stage + try "cp src/$src stage/$problemname.cpp" "source file missing" + + # Create a temporary file to hold the problem binary + binary=`mktemp` + + # Build the source + try "g++ stage/$problemname.cpp -std=c++11 -o $binary -O2" "Compile error" + + # Make a temporary file to hold the table: + table=`mktemp` + + # $table holds the score table + echo $src > $table + echo Test Message Time Points >> $table + + # For all tests + for testname in $tests ; do + # evaluate $binary on $testname, setting $message, $timeUsed, $points + evaluate_src_test $binary $testname + echo $testname.in $message $timeUsed $points >> $table + done + + # Clear "Doing test ..." + echo -en " \r" + + # Output the table + column -t $table + + # Calculate the score + echo SCORE: `awk -F ' ' '$1 != "Test" {sum += 0 $4} END {print sum}' $table` + + # Clear the temporary files + rm $table + rm $binary + + # And the stage + rm stage/* +done diff --git a/examples/aorib/src/makefile b/examples/aorib/src/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/src/ok.cpp b/examples/aorib/src/ok.cpp new file mode 100644 index 0000000..f62ffa8 --- /dev/null +++ b/examples/aorib/src/ok.cpp @@ -0,0 +1,10 @@ +#include +using namespace std; + +int main(){ + ifstream f("aorib.in"); + ofstream g("aorib.out"); + long long x, y; + f >> x >> y; + g << x*y << endl; + return 0; } diff --git a/src/tle.cpp b/examples/aorib/src/tle.cpp similarity index 100% rename from src/tle.cpp rename to examples/aorib/src/tle.cpp diff --git a/src/wa.cpp b/examples/aorib/src/wa.cpp similarity index 100% rename from src/wa.cpp rename to examples/aorib/src/wa.cpp diff --git a/examples/aorib/stage/aorib.bin b/examples/aorib/stage/aorib.bin new file mode 100755 index 0000000..c5d63c9 Binary files /dev/null and b/examples/aorib/stage/aorib.bin differ diff --git a/examples/aorib/stage/aorib.in b/examples/aorib/stage/aorib.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/testmanifest b/examples/aorib/testmanifest new file mode 100644 index 0000000..83d2d86 --- /dev/null +++ b/examples/aorib/testmanifest @@ -0,0 +1,2 @@ +1 fixed 10 +18 random 90 diff --git a/examples/aorib/tests/aorib-0.in b/examples/aorib/tests/aorib-0.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-0.ok b/examples/aorib/tests/aorib-0.ok new file mode 100644 index 0000000..937bac7 --- /dev/null +++ b/examples/aorib/tests/aorib-0.ok @@ -0,0 +1,2 @@ +10 +0 diff --git a/examples/aorib/tests/aorib-1.in b/examples/aorib/tests/aorib-1.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-1.ok b/examples/aorib/tests/aorib-1.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-1.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-10.in b/examples/aorib/tests/aorib-10.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-10.ok b/examples/aorib/tests/aorib-10.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-10.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-11.in b/examples/aorib/tests/aorib-11.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-11.ok b/examples/aorib/tests/aorib-11.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-11.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-12.in b/examples/aorib/tests/aorib-12.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-12.ok b/examples/aorib/tests/aorib-12.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-12.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-13.in b/examples/aorib/tests/aorib-13.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-13.ok b/examples/aorib/tests/aorib-13.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-13.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-14.in b/examples/aorib/tests/aorib-14.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-14.ok b/examples/aorib/tests/aorib-14.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-14.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-15.in b/examples/aorib/tests/aorib-15.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-15.ok b/examples/aorib/tests/aorib-15.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-15.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-16.in b/examples/aorib/tests/aorib-16.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-16.ok b/examples/aorib/tests/aorib-16.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-16.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-17.in b/examples/aorib/tests/aorib-17.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-17.ok b/examples/aorib/tests/aorib-17.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-17.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-18.in b/examples/aorib/tests/aorib-18.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-18.ok b/examples/aorib/tests/aorib-18.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-18.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-2.in b/examples/aorib/tests/aorib-2.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-2.ok b/examples/aorib/tests/aorib-2.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-2.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-3.in b/examples/aorib/tests/aorib-3.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-3.ok b/examples/aorib/tests/aorib-3.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-3.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-4.in b/examples/aorib/tests/aorib-4.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-4.ok b/examples/aorib/tests/aorib-4.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-4.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-5.in b/examples/aorib/tests/aorib-5.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-5.ok b/examples/aorib/tests/aorib-5.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-5.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-6.in b/examples/aorib/tests/aorib-6.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-6.ok b/examples/aorib/tests/aorib-6.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-6.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-7.in b/examples/aorib/tests/aorib-7.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-7.ok b/examples/aorib/tests/aorib-7.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-7.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-8.in b/examples/aorib/tests/aorib-8.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-8.ok b/examples/aorib/tests/aorib-8.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-8.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aorib/tests/aorib-9.in b/examples/aorib/tests/aorib-9.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aorib/tests/aorib-9.ok b/examples/aorib/tests/aorib-9.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aorib/tests/aorib-9.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/buildtests.sh b/examples/aplusb/buildtests.sh new file mode 100755 index 0000000..d57de12 --- /dev/null +++ b/examples/aplusb/buildtests.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# +# This builds all tests using testmanifest +# Tamio-Vesa Nakajima + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# Make stage (as git deletes it) +mkdir -p stage + +# We will want to remember this: +currtest=0 + +# Loop over lines of +cat testmanifest | while read instr; do + # Parse a line of testmanifest + set $instr + numberoftests=$1 + incf=$2 + totalpoints=$3 + points=$(($totalpoints / $numberoftests)) + + for nr in `seq $currtest $(($currtest + $numberoftests - 1))` ; do + echo $nr + ################# + # Build input: + ################# + + # Build input generator + try "cd ingen && make -s && cd .." "input generator build fail" + + # Copy ingen/ingen.bin and incf/$1 into stage + cp ingen/ingen.bin stage/$problemname.bin + try "cp incf/$incf stage/$problemname.cf" "incf/$incf doesn't exist" + + # Build input + try "cd stage && ./$problemname.bin > ../tests/$problemname-$nr.in && cd .." "input generation fail" + + # Clean stage + rm stage/* + + ################### + # Build ok + ################### + + # Build ok generator + try "cd okgen && make -s && cd .." "ok generator build fil" + + # Copy ok generator and input into stage + cp okgen/okgen.bin stage/$problemname.bin + cp tests/$problemname-$nr.in stage/$problemname.in + + # Indicate the number of points in the stage + echo $points > stage/$problemname.points + + # Build ok + try "cd stage && ./$problemname.bin && cd .." "ok generation fail" + + # Copy ok from stage into tests + cp stage/$problemname.ok tests/$problemname-$nr.ok + + # Clean stage + rm stage/* + done + + #update currtest + currtest=$(($currtest + $numberoftests)) + +done diff --git a/examples/aplusb/eval/eval.bin b/examples/aplusb/eval/eval.bin new file mode 100755 index 0000000..c3c63e4 Binary files /dev/null and b/examples/aplusb/eval/eval.bin differ diff --git a/examples/aplusb/eval/eval.cpp b/examples/aplusb/eval/eval.cpp new file mode 100644 index 0000000..04f428b --- /dev/null +++ b/examples/aplusb/eval/eval.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +using namespace std; + +int main(){ + ifstream fout("aplusb.out"); + ifstream fok("aplusb.ok"); + + int points = 0; + fok >> points; + + string s1, s2; + while(fok >> s1){ + if(!bool(fout >> s2) || s1 != s2){ + cerr << "WA" << endl; + cout << 0 << endl; + return 0; } } + + cerr << "OK" << endl; + cout << points << endl; + return 0; } diff --git a/examples/aplusb/eval/makefile b/examples/aplusb/eval/makefile new file mode 100644 index 0000000..2abe5c6 --- /dev/null +++ b/examples/aplusb/eval/makefile @@ -0,0 +1,2 @@ +../eval/eval.bin: + g++ eval.cpp -std=c++11 -o ../eval/eval.bin diff --git a/examples/aplusb/incf/fixed b/examples/aplusb/incf/fixed new file mode 100644 index 0000000..722ff38 --- /dev/null +++ b/examples/aplusb/incf/fixed @@ -0,0 +1 @@ +1 0 1 diff --git a/examples/aplusb/incf/random b/examples/aplusb/incf/random new file mode 100644 index 0000000..a5c7b77 --- /dev/null +++ b/examples/aplusb/incf/random @@ -0,0 +1 @@ +0 0 0 diff --git a/examples/aplusb/ingen/ingen.bin b/examples/aplusb/ingen/ingen.bin new file mode 100755 index 0000000..531eddb Binary files /dev/null and b/examples/aplusb/ingen/ingen.bin differ diff --git a/examples/aplusb/ingen/ingen.cpp b/examples/aplusb/ingen/ingen.cpp new file mode 100644 index 0000000..0d04686 --- /dev/null +++ b/examples/aplusb/ingen/ingen.cpp @@ -0,0 +1,16 @@ +#include +#include +using namespace std; + +int main(){ + ifstream f("aplusb.cf"); + ofstream g("aplusb.in"); + bool fixed; + int x, y; + f >> fixed >> x >> y; + + if(fixed) g << x << ' ' << y << endl; + else{ + srand(time(nullptr)); + g << rand() << ' ' << rand() << endl; } + return 0; } diff --git a/examples/aplusb/ingen/makefile b/examples/aplusb/ingen/makefile new file mode 100644 index 0000000..ae4ea9c --- /dev/null +++ b/examples/aplusb/ingen/makefile @@ -0,0 +1,2 @@ +../ingen/ingen.bin: + g++ ingen.cpp -std=c++11 -o ../ingen/ingen.bin diff --git a/examples/aplusb/lib.sh b/examples/aplusb/lib.sh new file mode 100644 index 0000000..cfee486 --- /dev/null +++ b/examples/aplusb/lib.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# +# Bash library for this project +# Tamio-Vesa Nakajima + +# Tries to execute $1 ; if this succeeds, do nothing +# otherwise, output $2 +try () { + if eval $1 ; then + : + else + echo $2 + exit 1 + fi +} + +# Tries to copy $1 to $2 ; if $1 doesn't exist, creates an empty $2 +maybecp () { + if [ -f $1 ] ; then + cp $1 $2 + else + touch $2 + fi +} + +# Evaluates the binary $1 with test $2, returning the message in $message, the time used in $timeUsed and the points in $points +evaluate_src_test () { + binary=$1 + testname=$2 + + # Get an appropriate timeout command + timeoutCommand=timeout + + if [[ "$OSTYPE" == "darwin"* ]] ; then + timeoutCommand=gtimeout + fi + + # Fetch the problem configuration + source problemconfig.sh + + # clear any previous messages + echo -en " \r" + + # Output an appropriate messgae + echo -en "Doing $testname\r" + + # Clean the stage + rm stage/* + + # Copy the binary into the stage + cp $binary stage/$problemname.bin + + # Copy the input into the stage + cp tests/$testname.in stage/$problemname.in + + # Get the problem config + source problemconfig.sh + + # This string runs the competitor's executable + runExec="./$problemname.bin > /dev/null 2> /dev/null" + + # This string runs the competitors executable with an appropriate timeout + runExecWithTimeout="$timeoutCommand $timelimit $runExec" + + # Run the competitors executable with a timeout, and store the time used in timeUsed + timeUsed=$(cd stage && { time $runExecWithTimeout ; } 2>&1 >/dev/null \ + | tail -3 \ + | head -1 \ + | awk -F ' ' '{print $2}' \ + | awk -F 'm' '{print $2}' \ + | awk -F 's' '{print $1}' && cd ..) + + if (( $(echo "$timeUsed > $timelimit" | bc -l))) ; then + # Set the return values + # timeUsed is already set + message=TLE + points=0 + else + # Make the evaluator + try "cd eval && make -s && cd .." "evaluator build fail" + + # Copy the evaluator into the stage + cp eval/eval.bin stage/eval.bin + + # Copy the ok file into the stage + cp tests/$testname.ok stage/$problemname.ok + + # Create temporary files to hold the points and the eval message + pointsFile=`mktemp` + messageFile=`mktemp` + + # Enter the stage and evaluate, storing the results in $pointsFile and $messageFile + try "cd stage && ./eval.bin > $pointsFile 2> $messageFile && cd .." "eval error" + + # Set the return values + # timeUsed is already set + points=`cat $pointsFile` + message=`cat $messageFile` + fi +} diff --git a/examples/aplusb/okgen/makefile b/examples/aplusb/okgen/makefile new file mode 100644 index 0000000..0bc29f0 --- /dev/null +++ b/examples/aplusb/okgen/makefile @@ -0,0 +1,2 @@ +../okgen/okgen.bin: + g++ okgen.cpp -std=c++11 -o ../okgen/okgen.bin diff --git a/examples/aplusb/okgen/okgen.bin b/examples/aplusb/okgen/okgen.bin new file mode 100755 index 0000000..0b4dca0 Binary files /dev/null and b/examples/aplusb/okgen/okgen.bin differ diff --git a/examples/aplusb/okgen/okgen.cpp b/examples/aplusb/okgen/okgen.cpp new file mode 100644 index 0000000..186e0e0 --- /dev/null +++ b/examples/aplusb/okgen/okgen.cpp @@ -0,0 +1,14 @@ +#include +using namespace std; + +int main(){ + ifstream points("aplusb.points"); + ifstream f("aplusb.in"); + ofstream g("aplusb.ok"); + + long long p, x, y; + f >> x >> y; + points >> p; + g << p << endl; + g << x+y << endl; + return 0; } diff --git a/examples/aplusb/problemconfig.sh b/examples/aplusb/problemconfig.sh new file mode 100644 index 0000000..6cfe193 --- /dev/null +++ b/examples/aplusb/problemconfig.sh @@ -0,0 +1,2 @@ +problemname=aplusb +timelimit=0.1 diff --git a/examples/aplusb/run.sh b/examples/aplusb/run.sh new file mode 100755 index 0000000..c5067cf --- /dev/null +++ b/examples/aplusb/run.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Runs sources on tests +# Tamio-Vesa Nakajima +# +# Use cases: +# ./run.sh -> runs all sources on all tests +# ./run.sh -s "a.cpp b.cpp" -s c.cpp -> runs a,b,c.cpp on all tests +# ./run.sh -t "00 01 02" -> runs all sources on tests 00, 01, 02 +# ./run.sh -s a.cpp -t 00 -> runs a.cpp on 00 + +########################## +# GENERAL SETUP +######################### + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# make stage (as git deletes it) +mkdir -p stage + +############################ +# ARGUMENT PARSING +############################# + +# default values for used sources and used tests + +srcs="" +tests="" + +while getopts "hs:t:" opt; do + case $opt in + h) + echo "Usage: ./run.sh -s [source] -t [test]" + exit 0 + ;; + s) + for x in $OPTARG ; do + srcs="$srcs $x" + done + ;; + t) + for x in $OPTARG ; do + tests="$tests $problemname-$x" + done + ;; + esac +done + +if [ -z "$srcs" ] ; then + srcs=`ls -1 src | grep .cpp` +fi + +if [ -z "$tests" ] ; then + tests=`ls -1 tests | grep .in | awk -F '.' '{print $1}'` +fi + +tests=`echo $tests | sort -t '-' -k 1 -n` + + +########################### +# EVALUATING +########################## + +for src in $srcs ; do + # Copy the source into the stage + try "cp src/$src stage/$problemname.cpp" "source file missing" + + # Create a temporary file to hold the problem binary + binary=`mktemp` + + # Build the source + try "g++ stage/$problemname.cpp -std=c++11 -o $binary -O2" "Compile error" + + # Make a temporary file to hold the table: + table=`mktemp` + + # $table holds the score table + echo $src > $table + echo Test Message Time Points >> $table + + # For all tests + for testname in $tests ; do + # evaluate $binary on $testname, setting $message, $timeUsed, $points + evaluate_src_test $binary $testname + echo $testname.in $message $timeUsed $points >> $table + done + + # Clear "Doing test ..." + echo -en " \r" + + # Output the table + column -t $table + + # Calculate the score + echo SCORE: `awk -F ' ' '$1 != "Test" {sum += 0 $4} END {print sum}' $table` + + # Clear the temporary files + rm $table + rm $binary + + # And the stage + rm stage/* +done diff --git a/src/ok.cpp b/examples/aplusb/src/ok.cpp similarity index 100% rename from src/ok.cpp rename to examples/aplusb/src/ok.cpp diff --git a/examples/aplusb/src/tle.cpp b/examples/aplusb/src/tle.cpp new file mode 100644 index 0000000..c55d503 --- /dev/null +++ b/examples/aplusb/src/tle.cpp @@ -0,0 +1,2 @@ +int main(){ + while(true){} } diff --git a/examples/aplusb/src/wa.cpp b/examples/aplusb/src/wa.cpp new file mode 100644 index 0000000..59c52f1 --- /dev/null +++ b/examples/aplusb/src/wa.cpp @@ -0,0 +1,4 @@ +#include +using namespace std; + +int main(){} diff --git a/examples/aplusb/testmanifest b/examples/aplusb/testmanifest new file mode 100644 index 0000000..83d2d86 --- /dev/null +++ b/examples/aplusb/testmanifest @@ -0,0 +1,2 @@ +1 fixed 10 +18 random 90 diff --git a/examples/aplusb/tests/aplusb-0.in b/examples/aplusb/tests/aplusb-0.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-0.ok b/examples/aplusb/tests/aplusb-0.ok new file mode 100644 index 0000000..937bac7 --- /dev/null +++ b/examples/aplusb/tests/aplusb-0.ok @@ -0,0 +1,2 @@ +10 +0 diff --git a/examples/aplusb/tests/aplusb-1.in b/examples/aplusb/tests/aplusb-1.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-1.ok b/examples/aplusb/tests/aplusb-1.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-1.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-10.in b/examples/aplusb/tests/aplusb-10.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-10.ok b/examples/aplusb/tests/aplusb-10.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-10.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-11.in b/examples/aplusb/tests/aplusb-11.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-11.ok b/examples/aplusb/tests/aplusb-11.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-11.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-12.in b/examples/aplusb/tests/aplusb-12.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-12.ok b/examples/aplusb/tests/aplusb-12.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-12.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-13.in b/examples/aplusb/tests/aplusb-13.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-13.ok b/examples/aplusb/tests/aplusb-13.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-13.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-14.in b/examples/aplusb/tests/aplusb-14.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-14.ok b/examples/aplusb/tests/aplusb-14.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-14.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-15.in b/examples/aplusb/tests/aplusb-15.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-15.ok b/examples/aplusb/tests/aplusb-15.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-15.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-16.in b/examples/aplusb/tests/aplusb-16.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-16.ok b/examples/aplusb/tests/aplusb-16.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-16.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-17.in b/examples/aplusb/tests/aplusb-17.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-17.ok b/examples/aplusb/tests/aplusb-17.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-17.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-18.in b/examples/aplusb/tests/aplusb-18.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-18.ok b/examples/aplusb/tests/aplusb-18.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-18.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-2.in b/examples/aplusb/tests/aplusb-2.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-2.ok b/examples/aplusb/tests/aplusb-2.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-2.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-3.in b/examples/aplusb/tests/aplusb-3.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-3.ok b/examples/aplusb/tests/aplusb-3.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-3.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-4.in b/examples/aplusb/tests/aplusb-4.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-4.ok b/examples/aplusb/tests/aplusb-4.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-4.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-5.in b/examples/aplusb/tests/aplusb-5.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-5.ok b/examples/aplusb/tests/aplusb-5.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-5.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-6.in b/examples/aplusb/tests/aplusb-6.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-6.ok b/examples/aplusb/tests/aplusb-6.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-6.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-7.in b/examples/aplusb/tests/aplusb-7.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-7.ok b/examples/aplusb/tests/aplusb-7.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-7.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-8.in b/examples/aplusb/tests/aplusb-8.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-8.ok b/examples/aplusb/tests/aplusb-8.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-8.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/aplusb/tests/aplusb-9.in b/examples/aplusb/tests/aplusb-9.in new file mode 100644 index 0000000..e69de29 diff --git a/examples/aplusb/tests/aplusb-9.ok b/examples/aplusb/tests/aplusb-9.ok new file mode 100644 index 0000000..cb6e5ed --- /dev/null +++ b/examples/aplusb/tests/aplusb-9.ok @@ -0,0 +1,2 @@ +5 +0 diff --git a/examples/tmp/buildtests.sh b/examples/tmp/buildtests.sh new file mode 100755 index 0000000..d57de12 --- /dev/null +++ b/examples/tmp/buildtests.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# +# This builds all tests using testmanifest +# Tamio-Vesa Nakajima + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# Make stage (as git deletes it) +mkdir -p stage + +# We will want to remember this: +currtest=0 + +# Loop over lines of +cat testmanifest | while read instr; do + # Parse a line of testmanifest + set $instr + numberoftests=$1 + incf=$2 + totalpoints=$3 + points=$(($totalpoints / $numberoftests)) + + for nr in `seq $currtest $(($currtest + $numberoftests - 1))` ; do + echo $nr + ################# + # Build input: + ################# + + # Build input generator + try "cd ingen && make -s && cd .." "input generator build fail" + + # Copy ingen/ingen.bin and incf/$1 into stage + cp ingen/ingen.bin stage/$problemname.bin + try "cp incf/$incf stage/$problemname.cf" "incf/$incf doesn't exist" + + # Build input + try "cd stage && ./$problemname.bin > ../tests/$problemname-$nr.in && cd .." "input generation fail" + + # Clean stage + rm stage/* + + ################### + # Build ok + ################### + + # Build ok generator + try "cd okgen && make -s && cd .." "ok generator build fil" + + # Copy ok generator and input into stage + cp okgen/okgen.bin stage/$problemname.bin + cp tests/$problemname-$nr.in stage/$problemname.in + + # Indicate the number of points in the stage + echo $points > stage/$problemname.points + + # Build ok + try "cd stage && ./$problemname.bin && cd .." "ok generation fail" + + # Copy ok from stage into tests + cp stage/$problemname.ok tests/$problemname-$nr.ok + + # Clean stage + rm stage/* + done + + #update currtest + currtest=$(($currtest + $numberoftests)) + +done diff --git a/examples/tmp/eval/makefile b/examples/tmp/eval/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/tmp/incf/makefile b/examples/tmp/incf/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/tmp/ingen/makefile b/examples/tmp/ingen/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/tmp/lib.sh b/examples/tmp/lib.sh new file mode 100644 index 0000000..cfee486 --- /dev/null +++ b/examples/tmp/lib.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# +# Bash library for this project +# Tamio-Vesa Nakajima + +# Tries to execute $1 ; if this succeeds, do nothing +# otherwise, output $2 +try () { + if eval $1 ; then + : + else + echo $2 + exit 1 + fi +} + +# Tries to copy $1 to $2 ; if $1 doesn't exist, creates an empty $2 +maybecp () { + if [ -f $1 ] ; then + cp $1 $2 + else + touch $2 + fi +} + +# Evaluates the binary $1 with test $2, returning the message in $message, the time used in $timeUsed and the points in $points +evaluate_src_test () { + binary=$1 + testname=$2 + + # Get an appropriate timeout command + timeoutCommand=timeout + + if [[ "$OSTYPE" == "darwin"* ]] ; then + timeoutCommand=gtimeout + fi + + # Fetch the problem configuration + source problemconfig.sh + + # clear any previous messages + echo -en " \r" + + # Output an appropriate messgae + echo -en "Doing $testname\r" + + # Clean the stage + rm stage/* + + # Copy the binary into the stage + cp $binary stage/$problemname.bin + + # Copy the input into the stage + cp tests/$testname.in stage/$problemname.in + + # Get the problem config + source problemconfig.sh + + # This string runs the competitor's executable + runExec="./$problemname.bin > /dev/null 2> /dev/null" + + # This string runs the competitors executable with an appropriate timeout + runExecWithTimeout="$timeoutCommand $timelimit $runExec" + + # Run the competitors executable with a timeout, and store the time used in timeUsed + timeUsed=$(cd stage && { time $runExecWithTimeout ; } 2>&1 >/dev/null \ + | tail -3 \ + | head -1 \ + | awk -F ' ' '{print $2}' \ + | awk -F 'm' '{print $2}' \ + | awk -F 's' '{print $1}' && cd ..) + + if (( $(echo "$timeUsed > $timelimit" | bc -l))) ; then + # Set the return values + # timeUsed is already set + message=TLE + points=0 + else + # Make the evaluator + try "cd eval && make -s && cd .." "evaluator build fail" + + # Copy the evaluator into the stage + cp eval/eval.bin stage/eval.bin + + # Copy the ok file into the stage + cp tests/$testname.ok stage/$problemname.ok + + # Create temporary files to hold the points and the eval message + pointsFile=`mktemp` + messageFile=`mktemp` + + # Enter the stage and evaluate, storing the results in $pointsFile and $messageFile + try "cd stage && ./eval.bin > $pointsFile 2> $messageFile && cd .." "eval error" + + # Set the return values + # timeUsed is already set + points=`cat $pointsFile` + message=`cat $messageFile` + fi +} diff --git a/examples/tmp/okgen/makefile b/examples/tmp/okgen/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/tmp/problemconfig.sh b/examples/tmp/problemconfig.sh new file mode 100644 index 0000000..262bab5 --- /dev/null +++ b/examples/tmp/problemconfig.sh @@ -0,0 +1,2 @@ +problemname=tmp +timelimit=22 diff --git a/examples/tmp/run.sh b/examples/tmp/run.sh new file mode 100755 index 0000000..c5067cf --- /dev/null +++ b/examples/tmp/run.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Runs sources on tests +# Tamio-Vesa Nakajima +# +# Use cases: +# ./run.sh -> runs all sources on all tests +# ./run.sh -s "a.cpp b.cpp" -s c.cpp -> runs a,b,c.cpp on all tests +# ./run.sh -t "00 01 02" -> runs all sources on tests 00, 01, 02 +# ./run.sh -s a.cpp -t 00 -> runs a.cpp on 00 + +########################## +# GENERAL SETUP +######################### + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# make stage (as git deletes it) +mkdir -p stage + +############################ +# ARGUMENT PARSING +############################# + +# default values for used sources and used tests + +srcs="" +tests="" + +while getopts "hs:t:" opt; do + case $opt in + h) + echo "Usage: ./run.sh -s [source] -t [test]" + exit 0 + ;; + s) + for x in $OPTARG ; do + srcs="$srcs $x" + done + ;; + t) + for x in $OPTARG ; do + tests="$tests $problemname-$x" + done + ;; + esac +done + +if [ -z "$srcs" ] ; then + srcs=`ls -1 src | grep .cpp` +fi + +if [ -z "$tests" ] ; then + tests=`ls -1 tests | grep .in | awk -F '.' '{print $1}'` +fi + +tests=`echo $tests | sort -t '-' -k 1 -n` + + +########################### +# EVALUATING +########################## + +for src in $srcs ; do + # Copy the source into the stage + try "cp src/$src stage/$problemname.cpp" "source file missing" + + # Create a temporary file to hold the problem binary + binary=`mktemp` + + # Build the source + try "g++ stage/$problemname.cpp -std=c++11 -o $binary -O2" "Compile error" + + # Make a temporary file to hold the table: + table=`mktemp` + + # $table holds the score table + echo $src > $table + echo Test Message Time Points >> $table + + # For all tests + for testname in $tests ; do + # evaluate $binary on $testname, setting $message, $timeUsed, $points + evaluate_src_test $binary $testname + echo $testname.in $message $timeUsed $points >> $table + done + + # Clear "Doing test ..." + echo -en " \r" + + # Output the table + column -t $table + + # Calculate the score + echo SCORE: `awk -F ' ' '$1 != "Test" {sum += 0 $4} END {print sum}' $table` + + # Clear the temporary files + rm $table + rm $binary + + # And the stage + rm stage/* +done diff --git a/examples/tmp/src/makefile b/examples/tmp/src/makefile new file mode 100644 index 0000000..e69de29 diff --git a/examples/tmp/testmanifest b/examples/tmp/testmanifest new file mode 100644 index 0000000..e69de29 diff --git a/examples/tmp/todo b/examples/tmp/todo new file mode 100644 index 0000000..8f8b63e --- /dev/null +++ b/examples/tmp/todo @@ -0,0 +1,9 @@ +TODO: + +- make an evaluator (should read from $problemname.out and $problemname.ok, write the evaluation message to stderr and the # of points to cout +- make an input generator (should read configuration from $problemname.cf and write the input to $problemname.in) +- make an ok generator (should read the # of points from $problemname.points, the input from $problemname.in, and write to ok to $problemname.ok) +- make a testmanifest (each line should contain a group of tests, described by the # of tests, the configuration file, and the # of points for that group) +- call ./buildtests.sh +- add source files to src +- call ./run.sh diff --git a/makeproject.sh b/makeproject.sh new file mode 100755 index 0000000..994c959 --- /dev/null +++ b/makeproject.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Makes a project in $1 + +# Get problem configuration +read -p "Problem name name: " problemname +read -p "Time limit: " timelimit + +# Make project directory +mkdir $1/$problemname + +# Make project structure +mkdir $1/$problemname/eval +mkdir $1/$problemname/incf +mkdir $1/$problemname/ingen +mkdir $1/$problemname/okgen +mkdir $1/$problemname/src +mkdir $1/$problemname/stage +mkdir $1/$problemname/tests + +touch $1/$problemname/eval/makefile +touch $1/$problemname/incf/makefile +touch $1/$problemname/ingen/makefile +touch $1/$problemname/okgen/makefile +touch $1/$problemname/src/makefile + +cp src/buildtests.sh $1/$problemname/buildtests.sh +cp src/lib.sh $1/$problemname/lib.sh +cp src/run.sh $1/$problemname/run.sh + +touch $1/$problemname/testmanifest + +echo "problemname=$problemname" > $1/$problemname/problemconfig.sh +echo "timelimit=$timelimit" >> $1/$problemname/problemconfig.sh + +cp src/todo $1/$problemname/todo diff --git a/src/buildtests.sh b/src/buildtests.sh new file mode 100755 index 0000000..d57de12 --- /dev/null +++ b/src/buildtests.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# +# This builds all tests using testmanifest +# Tamio-Vesa Nakajima + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# Make stage (as git deletes it) +mkdir -p stage + +# We will want to remember this: +currtest=0 + +# Loop over lines of +cat testmanifest | while read instr; do + # Parse a line of testmanifest + set $instr + numberoftests=$1 + incf=$2 + totalpoints=$3 + points=$(($totalpoints / $numberoftests)) + + for nr in `seq $currtest $(($currtest + $numberoftests - 1))` ; do + echo $nr + ################# + # Build input: + ################# + + # Build input generator + try "cd ingen && make -s && cd .." "input generator build fail" + + # Copy ingen/ingen.bin and incf/$1 into stage + cp ingen/ingen.bin stage/$problemname.bin + try "cp incf/$incf stage/$problemname.cf" "incf/$incf doesn't exist" + + # Build input + try "cd stage && ./$problemname.bin > ../tests/$problemname-$nr.in && cd .." "input generation fail" + + # Clean stage + rm stage/* + + ################### + # Build ok + ################### + + # Build ok generator + try "cd okgen && make -s && cd .." "ok generator build fil" + + # Copy ok generator and input into stage + cp okgen/okgen.bin stage/$problemname.bin + cp tests/$problemname-$nr.in stage/$problemname.in + + # Indicate the number of points in the stage + echo $points > stage/$problemname.points + + # Build ok + try "cd stage && ./$problemname.bin && cd .." "ok generation fail" + + # Copy ok from stage into tests + cp stage/$problemname.ok tests/$problemname-$nr.ok + + # Clean stage + rm stage/* + done + + #update currtest + currtest=$(($currtest + $numberoftests)) + +done diff --git a/src/lib.sh b/src/lib.sh new file mode 100644 index 0000000..cfee486 --- /dev/null +++ b/src/lib.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# +# Bash library for this project +# Tamio-Vesa Nakajima + +# Tries to execute $1 ; if this succeeds, do nothing +# otherwise, output $2 +try () { + if eval $1 ; then + : + else + echo $2 + exit 1 + fi +} + +# Tries to copy $1 to $2 ; if $1 doesn't exist, creates an empty $2 +maybecp () { + if [ -f $1 ] ; then + cp $1 $2 + else + touch $2 + fi +} + +# Evaluates the binary $1 with test $2, returning the message in $message, the time used in $timeUsed and the points in $points +evaluate_src_test () { + binary=$1 + testname=$2 + + # Get an appropriate timeout command + timeoutCommand=timeout + + if [[ "$OSTYPE" == "darwin"* ]] ; then + timeoutCommand=gtimeout + fi + + # Fetch the problem configuration + source problemconfig.sh + + # clear any previous messages + echo -en " \r" + + # Output an appropriate messgae + echo -en "Doing $testname\r" + + # Clean the stage + rm stage/* + + # Copy the binary into the stage + cp $binary stage/$problemname.bin + + # Copy the input into the stage + cp tests/$testname.in stage/$problemname.in + + # Get the problem config + source problemconfig.sh + + # This string runs the competitor's executable + runExec="./$problemname.bin > /dev/null 2> /dev/null" + + # This string runs the competitors executable with an appropriate timeout + runExecWithTimeout="$timeoutCommand $timelimit $runExec" + + # Run the competitors executable with a timeout, and store the time used in timeUsed + timeUsed=$(cd stage && { time $runExecWithTimeout ; } 2>&1 >/dev/null \ + | tail -3 \ + | head -1 \ + | awk -F ' ' '{print $2}' \ + | awk -F 'm' '{print $2}' \ + | awk -F 's' '{print $1}' && cd ..) + + if (( $(echo "$timeUsed > $timelimit" | bc -l))) ; then + # Set the return values + # timeUsed is already set + message=TLE + points=0 + else + # Make the evaluator + try "cd eval && make -s && cd .." "evaluator build fail" + + # Copy the evaluator into the stage + cp eval/eval.bin stage/eval.bin + + # Copy the ok file into the stage + cp tests/$testname.ok stage/$problemname.ok + + # Create temporary files to hold the points and the eval message + pointsFile=`mktemp` + messageFile=`mktemp` + + # Enter the stage and evaluate, storing the results in $pointsFile and $messageFile + try "cd stage && ./eval.bin > $pointsFile 2> $messageFile && cd .." "eval error" + + # Set the return values + # timeUsed is already set + points=`cat $pointsFile` + message=`cat $messageFile` + fi +} diff --git a/src/run.sh b/src/run.sh new file mode 100755 index 0000000..c5067cf --- /dev/null +++ b/src/run.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Runs sources on tests +# Tamio-Vesa Nakajima +# +# Use cases: +# ./run.sh -> runs all sources on all tests +# ./run.sh -s "a.cpp b.cpp" -s c.cpp -> runs a,b,c.cpp on all tests +# ./run.sh -t "00 01 02" -> runs all sources on tests 00, 01, 02 +# ./run.sh -s a.cpp -t 00 -> runs a.cpp on 00 + +########################## +# GENERAL SETUP +######################### + +# include the library +source lib.sh + +# include the configuration +source problemconfig.sh + +# make stage (as git deletes it) +mkdir -p stage + +############################ +# ARGUMENT PARSING +############################# + +# default values for used sources and used tests + +srcs="" +tests="" + +while getopts "hs:t:" opt; do + case $opt in + h) + echo "Usage: ./run.sh -s [source] -t [test]" + exit 0 + ;; + s) + for x in $OPTARG ; do + srcs="$srcs $x" + done + ;; + t) + for x in $OPTARG ; do + tests="$tests $problemname-$x" + done + ;; + esac +done + +if [ -z "$srcs" ] ; then + srcs=`ls -1 src | grep .cpp` +fi + +if [ -z "$tests" ] ; then + tests=`ls -1 tests | grep .in | awk -F '.' '{print $1}'` +fi + +tests=`echo $tests | sort -t '-' -k 1 -n` + + +########################### +# EVALUATING +########################## + +for src in $srcs ; do + # Copy the source into the stage + try "cp src/$src stage/$problemname.cpp" "source file missing" + + # Create a temporary file to hold the problem binary + binary=`mktemp` + + # Build the source + try "g++ stage/$problemname.cpp -std=c++11 -o $binary -O2" "Compile error" + + # Make a temporary file to hold the table: + table=`mktemp` + + # $table holds the score table + echo $src > $table + echo Test Message Time Points >> $table + + # For all tests + for testname in $tests ; do + # evaluate $binary on $testname, setting $message, $timeUsed, $points + evaluate_src_test $binary $testname + echo $testname.in $message $timeUsed $points >> $table + done + + # Clear "Doing test ..." + echo -en " \r" + + # Output the table + column -t $table + + # Calculate the score + echo SCORE: `awk -F ' ' '$1 != "Test" {sum += 0 $4} END {print sum}' $table` + + # Clear the temporary files + rm $table + rm $binary + + # And the stage + rm stage/* +done diff --git a/src/todo b/src/todo new file mode 100644 index 0000000..8f8b63e --- /dev/null +++ b/src/todo @@ -0,0 +1,9 @@ +TODO: + +- make an evaluator (should read from $problemname.out and $problemname.ok, write the evaluation message to stderr and the # of points to cout +- make an input generator (should read configuration from $problemname.cf and write the input to $problemname.in) +- make an ok generator (should read the # of points from $problemname.points, the input from $problemname.in, and write to ok to $problemname.ok) +- make a testmanifest (each line should contain a group of tests, described by the # of tests, the configuration file, and the # of points for that group) +- call ./buildtests.sh +- add source files to src +- call ./run.sh