跳转至

基本使用方式

所有基于文本的文件如果含有中文,必须用UTF-8编码。

所有的工具都可以加 -h--help 来显示帮助,例如

1
python -m tuack.gen -h

建立工程

成功安装本工具以后,我们建议你先在一个空的文件夹里进行这些操作。不要在大家共同工作的工程里进行这些操作,直到你熟悉了工具的使用方式。

先将这个文件夹配置为一个“比赛工程”:

1
python -m tuack.gen contest

你会发现工程下面产生了一个文件 conf.yaml。这个文件是这个工程的配置文件,大多数字段都能比较明显地看出含义,之后会需要编辑它。

接下来在这个“比赛工程”下建立三个“比赛日工程”:

1
python -m tuack.gen day day0 day1 day2

此时你会发现生成了名为 day0day1day2 的文件夹,这些文件夹内也分别有一个 conf.yaml

接下来在 day1 中建立 a+ba-b 两道题:

1
2
cd day1
python -m tuack.gen problem add sub
其中 addsub 叫做这两个题目的名称(名称一般用简洁的字母表示,区别于标题,可以较长并且不同的语言可以有不同的标题)。

这时,我们会发现 day1/add 文件夹下也有 conf.yaml

接下来我们手工建立题目 a*b 的文件夹 mul

1
2
3
mkdir mul
cd mul
python -m tuack.gen problem

然后打开 day1/conf.yamlsubdir 一项中添加这个文件夹的名字:

1
subdir: [add, sub, mul]

简单小结一下:tuack.gen 能够用于建立比赛工程、比赛日工程和题目工程。如果不带参数,表示在当前目录下建立相应工程;如果带参数,表示在当前目录的下建立子目录作为相应工程。

此外,当你成为老司机后,你可以用 nde 替代 contestdayproblem。注意它们略有不同,具体请使用 tuack.gen -h 查看。

配置数据和程序

打开一个题目的 data 文件夹,你会看到两个文件:1.in1.ans。我们将其改成样例题目的数据(导出本 wiki 后在目录 /samples/data.zip 中),并且添加一组数据:2.in2.ans。然后编辑这个题目的 conf.yamldata 字段:

1
2
3
data:
- cases: [1]
- cases: [2]

将标准输入输出的标程或其他参考程序放在题目目录下 你的名字/程序名称.{cpp,py,java}。假如你叫 ufozgg,你的程序叫 std.cpp(导出本 wiki 后在目录 /samples/std.cpp 中);你找了一个叫 saffah 的小伙伴帮你写了一个暴力程序叫 baozhi.cpp(导出本 wiki 后在目录 /samples/baozhi.cpp 中)。那么存放路径可以是:

1
2
???/day1/add/ufozgg/std.cpp
???/day1/add/saffah/baozhi.cpp

然后编辑 conf.yamlusers 字段:

1
2
3
4
5
users:
  gugu:
    biaocheng: {expected: == 100, path: ufozgg/std.cpp}
  saffah:
    baoli: {expected: == 30, path: saffah/baozhi.cpp}

接下来在比赛/比赛日/题目目录下运行:

1
python -m tuack.test

输出了一大坨东西之后会自动打开一个测试结果的 csv 文件:

测试结果

csv 文件看上图就能明白。需要留意的是,测试对出题人的数据要求是较为严格的,多余的空格、换行符等都会判为错误。

我们回到命令行中关注这些“友好”的输出:

1
2
3
4
5
6
[I]脚本???/tuack/test.py,工程路径???/day1/add,参数[],开始于????-??-?? ??:??:??.??????。
...
[I]共0组样例,0个预测试点,2个测试点,不是打包评测。
[I]测试程序 add:gugu:biaocheng
[I]测试程序 add:saffah:baoli
[E]未达到预期。预期分数 == 30 ,实际得分 50.00

省略部分的 warning 对于完整造题也很重要,之后需要根据提示进行修复,现在我们先关注最后一个 error。这个暴力程序因为没有开 64 位整数所以只能通过第 1 个测试点,不能通过第 2 个测试点。你肯定猜出可以通过修改 expected 字段来消除这个错误。但如果我们期望两个测试点分值不同,则需要这么设置 conf.yaml 中的 data 字段:

1
2
3
4
5
data:
- cases: [1]
  score: 30
- cases: [2]
  score: 70

之后再运行 tuack.test,这个 error 就消失了,并且测试前的提示也变成了打包评测:

1
[I]共0组样例,0个预测试点,2个测试点,是打包评测(共2个包)。

进一步,分数的约定是这样的:

  • 如果 data 字段的元素中设置了 score,那么会被认为是打包评测。应当将总分设置为 100 分。同一个 cases 中所有的数据会被作为一个包整体决定是否得分。特别地,ICPC 风格评测方式应当是只有一个包的打包评测。
  • 如果没有设置 score,将测试点放在同一个 cases 中或是放在不同元素的 cases 中,评分方式都是均分所有得分。但是应当将同一个子任务的数据放在同一个 cases 中,不同子任务的数据放在不同元素的 cases 中(这会影响到其他工具的逻辑)。

样例数据和预测试数据除了字段和存放路径与测试数据不同外,其他都是相同的:

评测数据 样例数据 预测试数据
存放路径 data down pre
字段 data samples pre

最后,我们提供了一些工具帮你生成部分配置文件内容,分别是:

1
2
3
4
5
python -m tuack.gen data
python -m tuack.gen samples
python -m tuack.gen pre
python -m tuack.gen code
python -m tuack.gen auto

最后一条等于前面四条加在一起。

注意:这些工具只能辅助你生成配置文件,不代表它们生成的配置文件是正确的。你应当在运行这些命令后检查配置文件是否满足你的意图和出题的要求。更进一步,大多数可能用到的文件都有规定应该存放的位置和格式,如果你要存放本小节没有提到的文件,请查阅文件的存放和定义中的规定。

警告:如果大家使用 git 合作,并且你的数据比较大(例如单个文件 1 MB 以上或总量 20 MB 以上),那么你应当使用 git-lfs 存放你的数据。否则其他人会吐槽工程无比硕大,工作时需要下载你所有版本的历史数据。具体在相关工具-GIT查询使用方法。

题面

在比赛工程、比赛日工程或题目工程下运行下列命令渲染对应的题面:

1
python -m tuack.ren tuoj

表示生成 tuoj 风格的题面。对于一个现在的工程,你会看到这样的报错:

1
2
3
4
5
6
7
[E]max() arg is an empty sequence
...
  File "???\tmp\problem.md.jinja", line 90, in top-level template code
    输入的第二行包含一个正整数 $m$,保证 $m \le {{ tl.hn(aargs.max('m')) }}$。
  File "???\tuack\tools.py", line 127, in max
    return max(self.get(key, d, True))
ValueError: max() arg is an empty sequence

我们继续修改 conf.yamldata 字段:

1
2
3
4
5
6
7
data:
- cases: [1]
  score: 30
  args: {n: 20, m: 10, bin: true}
- cases: [2]
  score: 70
  args: {n: 30, m: 100000000000, bin: false}

重新运行渲染命令,就能看到一个 markdown 格式的题面了。

到这里,你应该明白这个设计的意图:题目的参数,犹指出题过程中可能需要调整的、不同子任务不同的、未来可能拓展的参数,应当放置在配置文件中,而不是直接放在题面中。这样能够防止修改规模时只改了一个地方忘记改完,也方便进行数据的检验。你的数据生成器 generator、数据格式检查器 validator 也应该从这个配置文件里面读取。

打开 statement/zh-cn.md,进行题面的编辑。大多数内容在样例中都有提示该如何写。有些高级用法这个文件中没有提到,可以参见题面的书写。此外,这个文件是 jinja 造的,正常情况下你也可以使用其他 jinja 语法。

一道题的题面一般要求在格式和语言文字上遵循正式的规范,你可以用这条命令检查部分格式问题:

1
python -m tuack.doc check

这个工具有很多问题检测不出来,还有一些误检。但是将工具正确报出的 error 和 warning 全部修复是较为正式题目的基本要求

题面除了可以渲染成 tuoj 格式,目前支持四类格式:

  • tex:最终会生成成 PDF 格式。需要安装 pandocxelatex。其中 pandoc Windows 下直接到官网下载,Ubuntu 下 apt install pandocxelatex 的安装方式见相关工具-安装和配置XeLaTeX。具体的风格有:tuoitupcnoiccpcccc-tex
  • md:会生成带 html 标签的 markdown。不需要特别安装东西。具体的风格有:tuojccc-mdlojuoj(似乎这个现在有 bug)。
  • html:会生成带$括起来的 MathJAX 公式的 html,需要安装 pandoc。具体的风格有:tsinsen-oj
  • doku:会生成带$括起来的 MathJAX 公式的 DokuWiki,需要安装 pandoc。具体的风格有:thuoj

一般题面应该尽量在不同的环境下都渲染出合适的效果。如果确实没有时间安装所有工具,请咨询题目负责人是否可以排除掉某种特定的格式。

导入和导出

工程造好就可以用 tuack.dump 导出成其他某种格式,格式如下

1
python -m tuack.dump 类型1,类型2,...

目前支持的类型有:lemonarbiter(=arbiter-down+arbiter-main)(这两个暂时不支持 special judge),tsinsen-ojloj

例如,导出 tsinsen-oj 格式后,你会在目录下看到一个 tsinsen-oj.txt 文件。在清橙 OJ→我的清橙→我来出题→新建→上传,选择该文件即可将这道题发布到清橙。

loj 格式需要“登录”,且仅支持有管理题目权限的人传题,因此需要到 tuack 配置目录(对 Windows 是 tuack 的安装目录,对其他是 ~/.tuack)下的 conf.json加入下列内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  ...
  "loj": {
    "default": {
      "cookies": {
        "connect.sid": "在浏览器中找到cookie的相应字段",
        "login": "在浏览器中找到cookie的相应字段"
      },
      "main": "http://loj.ac"
    }
  }
}

成功上传以后,本地题目目录的 conf.yaml 文件会记录题号,因此如果任何东西有改动只需要再次 dump 即可。目前导出 loj 格式还不支持将配置文件解析为 data.yml,题面也没有分栏(将会把所有内容都塞到“题目描述”一栏),但 chk 已经可以使用了。

因为 loj 已经有较大改版,这个功能目前只能支持自己部署的 syzoj 的自动上传。

一个工程还可以用 tuack.load 导入某个其他格式的题目、比赛或数据包。

1
python -m tuack.load 类型 来源路径

其中 来源路径 是存放原始工程的路径。目前支持的类型有 tsinsen-ojlojdata。其中 loj 需要提供类 SYZOJ 的 url,另外的需要提供本地的路径或压缩包。另外 loj 暂时不支持解析 data.yml 和 spj。

尽管完整的导入功能还有待开发,但是题目的很多组件已经支持导入。例如数据可以放在 data 文件夹下然后使用 tuack.gen data 导入。题面使用如下方式导入:

1
python -m tuack.doc load 题面路径

这个方式可以导入很多格式,例如 docxmarkdownhtml 等,功能还算稳定,但注意会覆盖 statement/zh-cn.md。对于一个使用纯 markdown 书写的 zh-cn.md,可以用如下方式转化成更接近本工具建议的格式(例如从文本中提取样例):

1
python -m tuack.doc format

警告:这个操作有一定可能性会在写回 zh-cn.md 时挂掉,建议运行前进行备份。

警告:已经使用本工具格式的题面(非纯 markdown)不要使用 tuack.doc format 转化。

注意:导入的工程、数据和题面不等于符合题目规范。如果是正式考试使用,导入成功后还应当按规范进行编辑。

一些常用命令

帮助文档

所有的工具都可以加 -h--help 来显示帮助。例如:

1
python -m tuack.gen -h

不自动打开

对于运行结束会自动打开结果文件的脚本,使用 -s 可以不打开。例如:

1
python -m tuack.test -s

不完全运行

对于会迭代执行目录下所有比赛日/题目/用户/程序的脚本,使用 -p 可以指定只运行其中的一部分而不是全部:

1
2
3
4
python -m tuack.dump arbiter -p day1,day2
python -m tuack.test -p day1/excellent,day2/drink
python -m tuack.test -p day1/excellent/saffah
python -m tuack.test -p day1/excellent/saffah/std

这个开关可以在比赛/比赛日/题目的文件夹中使用,其中用户和程序是使用 conf.yaml 中的名称而不是路径名称。并且结尾不能有多余的斜杠 /,windows 下也不使用反斜杠 \

Checker

如果需要用到 checker(或称作 special judge),在题目工程下使用下列命令:

1
python -m tuack.gen chk

请尽量基于这份相对通用的 chk 代码编写你的 chk,而不要只针对特定比赛编写。在此基础上你可使用 testlib(当然也可以不使用)。

评测系统差异

这几个工具都可以指定考试/评测时的操作系统,使用命令如 -o Windows 。操作系统的名称与 python 的 platform.system() 调用结果一致(WindowsLinuxDarwin)。默认是当前操作系统。

对于 tuack.test,将会把所有数据转成指定操作系统的换行符进行测试;对于 tuack.ren,会按指定的操作系统习惯输出题面;对于 tuack.dump,会进行换行符转换。

注意:这里的指定操作系统主要是为了处理换行符、不同操作系统题面差异等小问题,不涉及交叉编译(跨平台编译)。例如编译的 chk 等只跟运行环境的操作系统有关,不能指定操作系统。

题面中的注意事项

如果要在印刷版的题面中添加“注意事项”,使用下列语法:

1
python -m tuack.gen prec