From e50def381ce512f58135fc599f4198c4d8098b37 Mon Sep 17 00:00:00 2001 From: ZsgsDesign Date: Wed, 2 Mar 2022 20:11:00 +0800 Subject: [PATCH] add SPJ docs and migration guide --- README.md | 42 +++++++++++++++++++++++++++++++++++++----- server/judge_client.py | 4 ++-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 380a938..fcf9757 100644 --- a/README.md +++ b/README.md @@ -85,23 +85,55 @@ NOJ JudgeServer is driven by Babel Extension NOJ, see [Babel Extension NOJ](http Starting from NOJ `v0.18.0` and NOJ JudgeServer `v0.3.0`, NOJ JudgeServer provides a SPJ library called **testlib**, it contains some useful constants and definitions and it would be bundled as a optional SPJ library of `C++`. -Right now **testlib** would be the only two SPJ libraries but we are planning to support more SPJ libraries in the future. +Right now **testlib** would be the only SPJ library available but we are planning to support more SPJ libraries in the future. ### SPJ Checker Languages -NOJ JudgeServer provides SPJ support for `C` only prior to `v0.3.0`. +NOJ JudgeServer provides SPJ support for `C` language only prior to `v0.3.0`. -Starting from NOJ `v0.18.0` and NOJ JudgeServer `v0.3.0`, NOJ JudgeServer provides support for `C++`, `PHP` and `Python3`. +Starting from NOJ `v0.18.0` and NOJ JudgeServer `v0.3.0`, NOJ JudgeServer provides additional support for `C++` and `PHP`. |Language|Compiler|Additional SPJ Libraries| |--------|--------|------------------------| |C|gcc (C99)|-| |C++|g++ (C++11)|testlib| |PHP|php (7.3-cli)|-| -|Python3|python3.7|testlib| + +### Migration from version prior to v0.3.0 + +Older versions of NOJ JudgeServer SPJs are feeded with testcase input and user output only. While in latest version of `v0.3.0`, It becomes testcase input, testcase output and user output. The changes not only grants testcase output access to SPJs, but also alters the given order. Thus all legacy version of SPJ need to: + +1. Alter accepted `argc` to 4 and accepts testcase input as first, testcase output as second and user output as third; +2. Re-bundle testcases archive file to include .out files, then use NOJ v0.18.0 Admin Portal to re-upload the testcases, the `.out` files, if not needed, can be blank or simply the same as input. ### SPJ sample code +#### SPJ Cheatsheet + +Here lists all valid exit code for SPJ: + +|Verdict|Exit Codes| +|--------|--------| +|Accepted|0| +|Wrong Answer|1, 2, 4, 8| +|System Error|3, 7, 255| + +All unlisted exit codes would be viewed as **System Error**. + +> Since Linux only accepts last 8 bits of exit code, you can practically use `-1` for **System Error** for it actually converts to `255`. You can also use `-255` (`1`) for **Wrong Answer** or `-253` (`3`) for **System Error**, etc. + +For C++ with testlib support, you can use testlib `quitf` function and macro defined `_wa`, `_ok` and so on without any conversion except `Points` and `Partically Accepted` status. NOJ Judge Server would recognize them properly and auto-convert them to NOJ JudgeServer standard. + +|NOJ Verdict|Testlib Verdict| +|--------|--------| +|Accepted|`_ok`| +|Wrong Answer|`_wa`, `_pe`, `_dirt`, `_unexpected_eof`| +|System Error|`_fail`, `_points`, `_partically`, `_pc`| + +For `Points` and `Partically Accepted` status, NOJ would verdict them all **System Error** no matter what score this SPJ actually nailed. For NOJ does not support single testcase with divided score. + +> We may support single-testcase-wide partically accepted status in the future. + #### Clang without any libraries Here is a simple SPJ checker written in `Clang`, this checker checks if the integer user outputs equals the given testcase: @@ -245,7 +277,7 @@ class Judge return Judge::WRONG_ANSWER; } - public function getVerdict() + public function getVerdict(): int { return $this->verdict ?? $this->judge(); } diff --git a/server/judge_client.py b/server/judge_client.py index abed6e5..54f80ad 100644 --- a/server/judge_client.py +++ b/server/judge_client.py @@ -24,9 +24,9 @@ TESTLIB_UNEXPECTED_EOF = 8 # TESTLIB_PC_BASE = 50 -SPJ_WA = [NOJSPJ_WA, TESTLIB_PE, TESTLIB_POINTS, TESTLIB_UNEXPECTED_EOF] +SPJ_WA = [NOJSPJ_WA, TESTLIB_PE, TESTLIB_DIRT, TESTLIB_UNEXPECTED_EOF] SPJ_AC = [NOJSPJ_AC] -SPJ_ERROR = [NOJSPJ_ERROR, TESTLIB_FAIL, TESTLIB_DIRT] +SPJ_ERROR = [NOJSPJ_ERROR, TESTLIB_FAIL, TESTLIB_POINTS] # SPJ_PC_THRESHOLD = TESTLIB_PC_BASE def _run(instance, test_case_file_id):