diff --git a/resource/runner/problem/example/README.md b/resource/runner/problem/example/README.md index 39ffa40..d68454a 100644 --- a/resource/runner/problem/example/README.md +++ b/resource/runner/problem/example/README.md @@ -5,7 +5,7 @@ ``` . ├── config.json # 题目配置信息 -├── description.md # (not used) 题目描述必须通过 API 提交给系统 +├── description.md # (optional) 题目描述,必须通过 API 提交,使用 import 脚本时将读取该文件 ├── data # 数据目录 │ ├── input # 输入数据 │ │ ├── (x).input # 第 x 组输入数据 @@ -25,20 +25,21 @@ ```json5 { - "Runtime": { - // 运行时配置 + "Runtime": { + // 运行时配置 "TimeLimit": 1000, // 时间限制 (ms) "MemoryLimit": 16, // 内存限制 (MB) "NProcLimit": 1 // 进(线)程 限制 }, - "Languages": [ + "Languages": [ + // 支持的语言 // c 语言,使用自定义评测脚本,脚本为 ./judge/XYZ.Makefile {"Lang": "c", "Type": "custom", "Script": "XYZ.Makefile", "Cmp": ""}, // c++ 语言,使用默认评测脚本,答案比对方式为 NCMP(testlib) {"Lang": "cpp", "Type": "default", "Script": "", "Cmp": "NCMP"} - ], // 支持的语言 - "Tasks": [ - // 评测点信息 + ], + "Tasks": [ + // 评测点信息 {"Id": 1, "Points": 10}, // 第一个评测点,分值 25 分,使用 ./data/{input,output}/1.{input,output} 为测试数据 {"Id": 2, "Points": 20}, {"Id": 3, "Points": 30}, @@ -51,7 +52,7 @@ 1. 默认评测脚本目前只支持 `c` 语言和 `cpp`,参见 `../../framework/template/default/{c,cpp}.Makefile` 2. 自定义评测脚本参见 `./judge/XYZ.Makefile` -3. `prebuild.Makefile`: 题目初始化脚本,用于编译辅助程序、生成数据等。如果存在改文件,系统会在题目分发到判机后自动执行,否则跳过改步骤 +3. `prebuild.Makefile`: 题目初始化脚本,用于编译辅助程序、生成数据等。如果存在该文件,系统会在题目分发到判机后自动执行,否则跳过该步骤 ## 注意事项 diff --git a/resource/runner/problem/example/judge/XYZ.Makefile b/resource/runner/problem/example/judge/XYZ.Makefile index 1264083..6fcde11 100644 --- a/resource/runner/problem/example/judge/XYZ.Makefile +++ b/resource/runner/problem/example/judge/XYZ.Makefile @@ -2,16 +2,37 @@ include ${TEMPLATE}/c.mk ${TEMPLATE}/Judger.mk # 评测分四个阶段 -# 1. prebuild: 用于提前生成测试数据、评测器、spj等工具,runner 只执行一次 -# 只有 ./data, ./judge 目录可见 -# 2. compile: 用于编译用户提交的程序 -# 只有 ./user/$(USER_PROG).$(LANG) 和 ./judge 目录可见 -# 3. run: 运行用户程序 -# 只有 ./data/input/*.input 和 ./user/$(USER_PROG).out 可见 -# 用户输出存放于 ./user/?.out.usr -# 使用 woj-sandbox 运行,等效于 $(PREFIX)/user/$(USER_PROG).out < $(PREFIX)/data/input/$(TEST_NUM).input > $(PREFIX)/user/$(TEST_NUM).out.usr -# 4. judge: 用于判定输出结果 环境变量 TEST_NUM 表示当前测试点编号 -# 所有目录 ./data ./judge ./user 可见 +# 1. prebuild: 用于提前生成测试数据、评测器、spj等工具,runner 只执行一次 +# 详细信息见 XYZ.Makefile +# 2. compile: 用于编译用户提交的程序 +# 目录映射情况: +# /woj/problem +# ├── judge 映射到题目目录的 ./judge <-- Readonly +# └── user 映射到题目目录的 ./user <-- 用户提交的程序在这里,命名:$(USER_PROG).$(LANG) +# 环境变量: +# USER_PROG=... <-- 一段随机字符串 +# LANG=... <-- 用户提交的程序的语言,如 c, cpp +# 其余通用环境变量,详见 ubuntu-full.Dockerfile +# 执行限制: +# 目前版本硬编码限制:时间 60s,内存 256mb +# 3. run: 运行用户程序 +# 只有 ./data/input/*.input 和 ./user/$(USER_PROG).out 可见 +# 用户输出存放于 ./user/?.out.usr +# 使用 woj-sandbox 运行,等效于 $(PREFIX)/user/$(USER_PROG).out < $(PREFIX)/data/input/$(TEST_NUM).input > $(PREFIX)/user/$(TEST_NUM).out.usr +# 4. judge: 用于判定输出结果 环境变量 TEST_NUM 表示当前测试点编号,每个测试点都会执行一次 +# 目录映射情况: +# /woj/problem +# ├── data 映射到题目目录的 ./data <-- Readonly +# ├── judge 映射到题目目录的 ./judge <-- Readonly +# └── user +# ├── $(TEST_NUM).out.usr <-- 用户程序在 $(TEST_NUM) 上的输出 +# └── $(TEST_NUM).judge <-- 评测结果写在这里,格式要求为 testlib 的 XML 格式 +# 环境变量: +# TEST_NUM=... <-- 当前测试点编号 +# CMP=... <-- 在 config.json 中配置的比较器,如 NCMP +# 其余通用环境变量,详见 ubuntu-full.Dockerfile +# 执行限制: +# 目前版本硬编码限制:时间 60s,内存 256mb compile: $(CC) $(CFLAGS) -o $(PREFIX)/user/$(USER_PROG).out $(PREFIX)/user/$(USER_PROG).$(LANG) $(PREFIX)/judge/gadget.c diff --git a/resource/runner/problem/example/judge/prebuild.Makefile b/resource/runner/problem/example/judge/prebuild.Makefile index c07df39..b10e235 100644 --- a/resource/runner/problem/example/judge/prebuild.Makefile +++ b/resource/runner/problem/example/judge/prebuild.Makefile @@ -2,6 +2,17 @@ include ${TEMPLATE}/c.mk ${TEMPLATE}/Judger.mk # 当题目被下载到 runner 后,会自动执行 prebuild 阶段,判题时不会再次执行 +# prebuild 阶段环境信息 +# 目录映射情况: +# /woj/problem +# ├── data 映射到题目目录的 ./data +# └── judge 映射到题目目录的 ./judge +# 环境变量: +# PREFIX=/woj/problem +# 其余通用环境变量,详见 ubuntu-full.Dockerfile +# 执行限制: +# 目前版本硬编码限制:时间 300s,内存 1g + prebuild: # 生成测试数据生成工具 clang++ -I$(TESTLIB) -Ofast -o $(PREFIX)/judge/gen.out $(PREFIX)/judge/gen.cpp diff --git a/resource/runner/scripts/run_timeout.sh b/resource/runner/scripts/docker_run.sh similarity index 59% rename from resource/runner/scripts/run_timeout.sh rename to resource/runner/scripts/docker_run.sh index 20b64f2..560e573 100755 --- a/resource/runner/scripts/run_timeout.sh +++ b/resource/runner/scripts/docker_run.sh @@ -1,9 +1,12 @@ #!/usr/bin/env bash -. common.sh +SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) +. "$SCRIPT_PATH/common.sh" function docker_run() { local timeout=${TIMEOUT:-10} + local network=${NETWORK:-"none"} + local memory=${MEMORY:-"256m"} local log_file=${LOG_FILE:-"/dev/stderr"} local log_limit=${LOG_LIMIT:-4K} log_info "$DOCKER run with timeout $timeout" @@ -12,7 +15,7 @@ function docker_run() { sleep "$timeout" $DOCKER kill "$CONTAINER_NAME" ) & - $DOCKER run --rm --name "$CONTAINER_NAME" "$@" 2>&1 | head -c "$log_limit" >"$log_file" + $DOCKER run --rm --name "$CONTAINER_NAME" --network "$network" --memory "$memory" "$@" 2>&1 | head -c "$log_limit" >"$log_file" pkill -P $$ $DOCKER kill "$CONTAINER_NAME" >/dev/null 2>&1 return 0 diff --git a/resource/runner/scripts/prepare_images.sh b/resource/runner/scripts/prepare_images.sh index f03c696..2db7ae4 100755 --- a/resource/runner/scripts/prepare_images.sh +++ b/resource/runner/scripts/prepare_images.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash -. common.sh +SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) +. "$SCRIPT_PATH/common.sh" cd "$(dirname "$0")"/../ || exit 1 diff --git a/resource/runner/scripts/problem.sh b/resource/runner/scripts/problem.sh index a9f2754..835499c 100755 --- a/resource/runner/scripts/problem.sh +++ b/resource/runner/scripts/problem.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash -. common.sh +SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) +. "$SCRIPT_PATH/common.sh" # get_problem_info # extract language info and limits diff --git a/resource/runner/scripts/problem_compile.sh b/resource/runner/scripts/problem_compile.sh index a25ccfc..ab06937 100755 --- a/resource/runner/scripts/problem_compile.sh +++ b/resource/runner/scripts/problem_compile.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd) -. "$WORKSPACE"/scripts/run_timeout.sh . "$WORKSPACE"/scripts/common.sh +. "$WORKSPACE"/scripts/docker_run.sh . "$WORKSPACE"/scripts/problem.sh if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then diff --git a/resource/runner/scripts/problem_judge.sh b/resource/runner/scripts/problem_judge.sh index b262d6f..c94f4bb 100755 --- a/resource/runner/scripts/problem_judge.sh +++ b/resource/runner/scripts/problem_judge.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd) -. "$WORKSPACE"/scripts/run_timeout.sh . "$WORKSPACE"/scripts/common.sh +. "$WORKSPACE"/scripts/docker_run.sh . "$WORKSPACE"/scripts/problem.sh if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then diff --git a/resource/runner/scripts/problem_prebuild.sh b/resource/runner/scripts/problem_prebuild.sh index e054688..b79672e 100755 --- a/resource/runner/scripts/problem_prebuild.sh +++ b/resource/runner/scripts/problem_prebuild.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd) -. "$WORKSPACE"/scripts/run_timeout.sh . "$WORKSPACE"/scripts/common.sh +. "$WORKSPACE"/scripts/docker_run.sh if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ]; then log_warn "Usage: $0 " @@ -22,6 +22,7 @@ if [ ! -f "$WORKSPACE/problem/$1/judge/prebuild.Makefile" ]; then fi export TIMEOUT=${2:-300} +export MEMORY="1g" docker_run \ -v "$WORKSPACE/problem/$1/data":/woj/problem/data \ -v "$WORKSPACE/problem/$1/judge":/woj/problem/judge \ diff --git a/resource/runner/scripts/problem_run.sh b/resource/runner/scripts/problem_run.sh index 03da64d..b23ba71 100755 --- a/resource/runner/scripts/problem_run.sh +++ b/resource/runner/scripts/problem_run.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd) -. "$WORKSPACE"/scripts/run_timeout.sh . "$WORKSPACE"/scripts/common.sh +. "$WORKSPACE"/scripts/docker_run.sh . "$WORKSPACE"/scripts/problem.sh if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then