Skip to content
lanrongqi edited this page Feb 7, 2021 · 13 revisions

Deer Executor

一个基于Go语言实现的代码评测工具

✨ 特性

  • 以CLI方式运行,不需要OJ平台;
  • 支持多种编程语言程序的判定,你可以自行扩展更多的语言;
  • 支持将题目配置和数据打包,随处都能一行命令运行评测;
  • 支持评测结果压缩打包,便于OJ存档和回放;
  • 支持使用Testlib作为出题工具;
  • 基于Linux和Mac OS平台。

🖥️ 环境准备

请先自行安装相关语言的编译器。

其中,Go语言编译器和GCC编译器是必须的,Go编译器请升级到至少1.14版本。

如果需要在docker中运行,请通过工程目录下的Dockerfile编译。

警告:判题机本身暂时没有任何沙箱功能,如果你不希望被恶意代码攻击,生产环境请务必借用docker容器来充当沙箱,并设置好相关的目录权限、网络权限等。

⚙️ 安装和编译

开箱即用:

$ go get github.com/LanceLRQ/deer-executor/v2
$ deer-executor

此时,因为没有lib文件夹,部分功能可能无法使用。可以访问Releases页面下载编译好的二进制包。

二次开发:

请先确定当前环境为Linux或Mac OS环境,并且安装好golang(1.13+)gccg++。假设当前用户目录为/Users/lancelrq/github

$ cd ~/github
$ git clone https://github.com/LanceLRQ/deer-executor.git
$ cd deer-executor
$ go get
$ go run main.go

deer-common依赖用于存放一些公共的定义和工具函数。如果需要修改,请先从github把它克隆下来,然后做软链接到./pkg

$ cd ~/github
$ git clone git@github.com:LanceLRQ/deer-common.git
$ ln -s ~/github/deer-common ~/github/deer-executor/pkg/deer-common

然后在go.mod文件里增加替换指令replace github.com/LanceLRQ/deer-common@版本 => ./pkg/deer-common。注意版本二字需要替换成当前go.mod文件内描述的版本,然后再返回deer-executor目录下运行或者编译程序吧。

🎈 运行“A+B”问题

  1. 运行一次简单的评测

    $ go run main.go run ./data/problems/APlusB/problem.json ./data/codes/APlusB/ac.c

    ./data/codes/APlusB目录下提供了各种情况的测试代码,你可以测试判题机的工作状态和判题的准确性。

    *默认的数据工作目录以配置文件所在的目录为准,本例中./data/codes/APlusB会被视作工作目录。配置中的文件名均为相对路径,如0.in会被解析成./data/codes/APlusB/0.in../0.in会被解析成./data/codes/0.in等。你可以使用--workdir指定工作目录,详情请通过目录查看各个功能的描述。

    **最终所有文件路径都会被解析成绝对路径,故特判程序收到的运行参数中所有地址均为绝对路径的地址,这个和特殊评测有关

    运行结束后,控制台会输出结果数据,内容不会包含测试数据详情,如果需要打印完整内容请加上--detail参数。未来,如果是OJ使用,请直接读取持久化文件,读取方法后续会补充相关的sdk和说明。

  2. 运行评测并持久化到文件

    $ go run main.go run --persistence ./result ./data/problems/APlusB/problem.json ./data/codes/APlusB/ac.c
  3. 运行评测并持久化到文件(带签名和数字校验)

    $ go run main.go run --persistence ./result --sign --key YOUR_GPG_KEY_FILE ./data/problems/APlusB/problem.json ./data/codes/APlusB/ac.c

    *此步骤会在控制台提示GPG密钥文件保护密码(passpharse),你可以通过--passphrase参数直接传入,但不建议。

📦 构建“A+B问题”的数据包

$ go run main.go pack --sign --key YOUR_GPG_KEY_FILE ./data/problems/APlusB/problem.json ./a+b.problem 

*此步骤会在控制台提示GPG密钥文件保护密码(passpharse)

**如果不需要对数据包进行签名,去掉--sign参数和--key参数即可,程序默认会给数据包做简单的SHA-256校验

⛳ 通过“A+B问题”的数据包,运行评测

$ go run main.go run ./a+b.problem ./data/codes/APlusB/ac.c
或者
$ go run main.go run --work-dir /tmp/a+b ./a+b.problem ./data/codes/APlusB/ac.c

运行评测时,--config参数支持识别是否为题目数据包文件。通过--work-dir参数设定数据包释放的工作目录,目录下相同的内容将被覆盖;如果不设置,默认使用/tmp/<uuid4()>作为工作目录,并在工作完成后删除该目录。

*此功能的设计初衷是希望用户能够更轻松通过CLI运行判题,题目数据包可以由OJ按照对应的格式导出,便于分发。

**如果将判题机用于OJ,则不建议使用数据包的方式运行题目,因为同一个题目重复的解包过程会带来更多资源开销。建议OJ自己管理题目数据(类似./data/problems目录一样),然后通过problem.json

💡 Testlib判题支持

  1. 编辑配置文件(参考./data/problems/APlusB2/problem.json),启用testlib设置,配置generator、validator和checker等。 注意每个testcase的input、output都要命名!如果你想要生成

  2. 使用go run main.go problem build ./data/problems/APlusB2/problem.json命令,编译构建对应的二进制程序。

    • (可选) 使用go run main.go problem validate ./data/problems/APlusB2/problem.json命令,运行validator对测试数据、 手打数据(validator_cases)进行校验。其中,测试数据如果启用了generator,会运行generator生成数据,否则会使用Input文件中的数据。

    • (可选) 使用go run main.go problem checker ./data/problems/APlusB2/problem.json命令,运行checker对checker_cases的数据进行验证。

  3. 使用go run main.go problem generate ./data/problems/APlusB2/problem.json命令,生成完整的评测数据输入文件。 如果带上--with-answer参数,则会运行答案代码,覆盖对应的输出文件。

  4. 执行正常的判题命令即可。