Domjudge 8.3 Docker 无痛配置

Domjudge 8.3

基于Debian, docker 安装

前置说明

先把docker安装好,然后因为举办该比赛没有用选手机,所以并没有学习选手机如何配置,同时由于设备和规模问题,气球小票机也没有配置,后面有机会再学习了

参考博客Domjudge配置指南 & 校赛踩坑记录 - 知乎

数据库

从docker上pull 数据库的镜像

docker pull dockerpull.org/mariadb

先安装数据库使用mysql

docker run --restart=always -d -it --name dj-mariadb \
-e MYSQL_ROOT_PASSWORD=%1% \
-e MYSQL_USER=domjudge \
-e CONTAINER_TIMEZONE=Asia/Shanghai \
-e MYSQL_PASSWORD=%2% \
-e MYSQL_DATABASE=domjudge -p %3%:3306 \
dockerpull.org/mariadb  --max-connections=1000 --max-allowed-packet=2048000000 --innodb-log-file-size=20480000000

命令中%%部分需要替换成实际值

MYSQL_ROOT_PASSWORD是数据库的root密码建议修改

MYSQL_PASSWORD是数据库的密码建议修改

--max-connections为最大连接数

--max-allowed-packet为你最大测试点大约2倍的值单位B

--innodb-log-file-size为你最大测试点大约10倍的值单位B

映射数据库 /home/Domjudge/db/mysql 修改为本地文件夹

#如果之前没创建过,就不用输这个命令
rm -rf /home/Domjudge/db/mysql
#将数据库的文件夹复制到本地
docker cp dj-mariadb:/etc/mysql /home/Domjudge/db/mysql

然后删除容器

#删除容器
docker rm -f dj-mariadb
#删除容器的卷,之前因为没删除卷导致硬盘一下就满了
docker volume prune

然后重新安装容器

docker run --restart=always -d -it --name dj-mariadb \
-e MYSQL_ROOT_PASSWORD=%1% \
-e MYSQL_USER=domjudge \
-e CONTAINER_TIMEZONE=Asia/Shanghai \
-e MYSQL_PASSWORD=%2% \
-e MYSQL_DATABASE=domjudge -p %3%:3306 \
-v  /home/Domjudge/db/mysql:/etc/mysql \
dockerpull.org/mariadb  --max-connections=1000 --max-allowed-packet=2048000000 --innodb-log-file-size=20480000000

下面的命令,在配置过程中可能会用到

#删除所有卷
docker volume prune
#删除所有容器
docker rm -f $(docker ps -aq)

domserver

拉镜像

docker pull dockerpull.org/domjudge/domserver:8.3.1

创建domserver容器

docker run --restart=always --link dj-mariadb:mariadb -d -it \
-e MYSQL_HOST=mariadb \
-e MYSQL_USER=domjudge \
-e MYSQL_DATABASE=domjudge \
-e CONTAINER_TIMEZONE=Asia/Shanghai \
-e MYSQL_PASSWORD=<数据库的密码> \
-e MYSQL_ROOT_PASSWORD=<数据库root的密码> \
-p <根据需要映射端口>:80 --name domserver dockerpull.org/domjudge/domserver:8.3.1

Domjudge后台管理员的初始密码

docker exec -it domserver cat /opt/domjudge/domserver/etc/initial_admin_password.secret

用这个密码可以用,admin登录web,进入管理员界面

Domjudge的API KEY,配置judgehost需要

docker exec -it domserver cat /opt/domjudge/domserver/etc/restapi.secret

输出大概长这样

Randomly generated on host , Sat Dec  7 17:38:09 CST 2024
Format: '<ID> <API url> <user> <password>'
default http://localhost//api   judgehost       APIKEY

这里就已经可以登录到web端查看了

judgehost

拉镜像

docker pull dockerpull.org/domjudge/judgehost:8.3.1

修改cgroub,文件在/etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1"
#如果你核够用,可以考虑开启守护进程
GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1 isolcpus=2"
#如果你的cgrub版本比较低,或者出现其他的问题,导致容器一直再重启,可以考虑用下面的这句
GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1 isolcpus=2 systemd.unified_cgroup_hierarchy=0"

然后执行

update-grub
reboot

创建judgehost容器

#这里我们创建四个judgehost, 将JUDGEDAEMON_PASSWORD替换成上面查看的APIKEY

docker run -d --restart=always -it --privileged \
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
--name judgehost-0 \
--link domserver:domserver \
--hostname judgedaemon-0 \
-e DAEMON_ID=0 \
-e JUDGEDAEMON_PASSWORD=APIKEY \
-e CONTAINER_TIMEZONE=Asia/Chendu \
dockerpull.org/domjudge/judgehost:8.3.1

docker run -d --restart=always -it --privileged \
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
--name judgehost-1 \
--link domserver:domserver \
--hostname judgedaemon-1 \
-e DAEMON_ID=1 \
-e JUDGEDAEMON_PASSWORD=APIKEY \
-e CONTAINER_TIMEZONE=Asia/Chendu \
dockerpull.org/domjudge/judgehost:8.3.1

docker run -d --restart=always -it --privileged \
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
--name judgehost-2 \
--link domserver:domserver \
--hostname judgedaemon-2 \
-e DAEMON_ID=2 \
-e JUDGEDAEMON_PASSWORD=APIKEY \
-e CONTAINER_TIMEZONE=Asia/Chendu \
dockerpull.org/domjudge/judgehost:8.3.1

docker run -d --restart=always -it --privileged \
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
--name judgehost-3 \
--link domserver:domserver \
--hostname judgedaemon-3 \
-e DAEMON_ID=3 \
-e JUDGEDAEMON_PASSWORD=APIKEY \
-e CONTAINER_TIMEZONE=Asia/Chendu \
dockerpull.org/domjudge/judgehost:8.3.1

通过命令进入容器

docker exec -it <Id> /bin/bash
# docker exec -it judgehost-0 /bin/bash

进入chroot

chroot /chroot/domjudge/

通过cat的方式换源

cat > /etc/apt/sources.list << 'EOF'
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware
EOF

更新源

apt update

安装py, java, g++, gcc环境

#java安装需要挂载
mount -t proc none /proc
mkdir -p /usr/share/man/man1

apt-get install -y gcc g++ python3 openjdk-17-jdk

查看环境配置

python3 --version;java -version;gcc --version;g++ --version

导入团队和账户

先准备teams.jsonaccounts.json两个文件
如果用json导入,先把Configuration settings中的External systems中的Data source修改为configuration data external

teams.json比如

[{
  "id": "100", // 队伍唯一id
  "name": "我是A队", // 队伍名字
  "display_name": "我是A队", // 榜单显示名字
  "icpc_id": "formal_100", // 队伍外部id
  "label": "1", // 标签, 座位什么的,需要唯一
  "members": "A B C", // 成员
  "group_ids": ["participants"], // 队伍类型 对应Team Categories 中的external ID
  "organization_id": "school" // 学校 对应Team Affiliations中的external ID
}, {
  "id": "101",
  "name": "我是B队",
  "display_name": "我是B队",
  "icpc_id": "formal_101",
  "label": "2",
  "members": "A B C",
  "group_ids": ["participants"],
  "organization_id": "school"
}
]

accounts.json

[{
  "id": "formal-100", //账户唯一id
  "username": "formal-100", //用户名,唯一
  "password": "",// 密码
  "team_id": "100",// 与teams中id对应, 表示该账户是 id队伍的
  "type": "team", // 类型 team就行
  "name": "A" // 名字, 该用户的名字
}, {
  "id": "formal-101",
  "username": "formal-101",
  "password": "",
  "team_id": "101",
  "type": "team",
  "name": "B"
}
]

如果配置了organization_id,需要保证teams.json中的所有organization_id对应的值已经在存在,可以在web上的Team Affiliations配置里面看到,然后再上传teams.json,再上传accounts.json

创建一场比赛

导入contest.json

{
  
  "id": "formal_contest",
  "formal_name": "formal_contest",
  "name": "正式赛",
  //时间采用绝对时间格式
  "start_time": "2024-12-08T12:00:00+08:00",
  "duration": "5:00:00",
  "penalty_time": 20,
  "activate_time": "2024-12-08T12:00:00+08:00",
  "medals": {
    "gold": 20,
    "silver": 40,
    "bronze": 60
  },
  "scoreboard_freeze_duration": "01:00:00"
}

导入题目

采用以下格式

│  domjudge-problem.ini
│  problem.pdf
│  problem.yaml
│
└─data
    └─sample
            1.ans
            1.in
            2.ans
            2.in
    └─secret
            3.ans
            3.in
            4.ans
            4.in

problem.yaml大概长这样

limits:
  memory: 256
name: 起床别睡啦

domjudge-problem.ini大概长这样

short-name = A
timelimit = 1.0
color = #000000
externalid = a0005

最后打包成.zip文件就行
如果上传失败可以考虑检查数据库的配置是否合理,再看看config cheker是不是有问题
当然如果不知道怎么配置,可以考虑在polygon上出好题后用p2d工具转换
Polygon2DOMjudge/README.cn.md at master · cn-xcpc-tools/Polygon2DOMjudge

导出提交文件

使用这个工具LaiJunBin/domjudge-code-download-tool: Download domjudge contest source code tool.

但是存在一些bug,我已经修改了,给原作者反馈问题了

可以下载我修改好的

然后运行的话,建议在wsl上运行,实测没有出过问题,在Pycharm和windows上都出过大大小小的bug

导出计分板

可以直接在web后台的contest里面导出

ICPC Tool

The ICPC Tools | Home所有工具的链接,最好下载最新的,而不是下载稳定版本

我是运行在Windows上的,其他操作系统未知.

Contest Data Server

参考博客

关于搭建 domjudge 还有其他一些 ICPC Tool 之类的事 – 赤红幻想

Connecting the ICPC Tools with DOMjudge · DOMjudge/domjudge Wiki

本地配置

CDS 又叫 Contest Data Server,主要用以比赛后台的一些管理服务,得先配置好这个才能用其他 Tools(Resolver 除外)。

然后进入到wlp/usr/servers/cds/config/cdsConfig.xml,将文件内容直接全部修改为

<cds>
    <!-- Set location= to a directory that the user running the CDS can write to -->
    <contest location="/home/cds/contest-data" recordReactions="false">
        <!-- Set the url to the URL of your DOMjudge installation, followed by /api/contests/<cid>, where <cid> is your CID or external ID -->
        <!-- Set the user and password to the user you created in the previous step -->
        <ccs
            url="http://www.domjudge.org/demoweb/api/contests/nwerc18"
            user="cds"
            password="somepassword" />
    </contest>
</cds>

然后修改location为一个用户可以修改的文件目录

然后url 为比赛的api链接,如果你设置了external data source,这里的cid为external ID

http://{ip}//api/v4/contests/{cid}

userpassword分别对应usercdsusercdspwd, 管理员账号也可以

然后配置accounts.yaml

里面的usernametype都不要修改,password建议修改,为了安全

接下来就可以运行(需要装 java jdk 11 或以上)

wlp/bin/server run cds

来启动 CDS 了,关闭的话直接 Ctrl+C 停止服务即可。

然后可以通过server ip为 你本地的任意ip

https://<server ip>:8443/

启动后可以看到以下界面

右上角可以用刚才accounts.yaml文件中的admin用户登录

docker配置

先pull镜像

docker pull ghcr.io/icpctools/cds:2.6.1166

如果你拉取不下来,这里有我已经下载好的cds_docker

docker load -i cds.tar.gz

然后创建容器

docker run --name cds --rm -d  -p 8080:8080 -p 8443:8443 -e CCS_URL=http://<ip:post>/api/v4/contests/<cid> -e CCS_USER=admin -e CCS_PASSWORD=<passwd> ghcr.io/icpctools/cds:2.6.1166

这里的ccs_url建议用http,其中建议使用ip:post

ccs_user需要API reader的角色,和Source code reader

然后进入到cds容器里面

docker exec -it cds /bin/bash
cat /opt/wlp/usr/servers/cds/config/cdsConfig.xml

其配置文件路径为:/opt/wlp/usr/servers/cds/config/cdsConfig.xml

Presentation Admin

这是个屏幕显示后台管理工具,可以管理多个 Client 的屏幕显示。

然后在bash里面运行这个命令

cdsurl为刚才启动的cds页面, user为accounts.yaml中的presAdmin,password同理

presAdmin.bat/sh cdsURL user password [options]
 ./presAdmin.bat <cdsurl> <user> <password>

只要出现这个页面,那么就启动成功了

Presentation Client

用于管理屏幕的

用下面的命令启动即可

./client.bat https://<server ip>:8443/api/contests/<cid> presentation <presentation password> --name <client name>

由于可能存在中文乱码的问题

所以这里有一种解决方式

进入到C:\Windows\Fonts后选择一款字体,然后放到lib/presentations.jar/font

presentations.jar可以用7z或者其他解压工具打开

替换掉原来的字体Helvetica-Plain.ttf

Resolver(滚榜)

awards.bat

有两种方式

RESK是通过CDS地址来拉取,Disk是通过event-feed.json来拉取数据的,

event-feed.json通过下面的链接下载

https://<domjudge url>/api/v4/contests/<cid>/event-feed?stream=false

如果出现这种情况也无所谓,只要能拉到表就行

然后点击Operations下的save event feed.ndjson然后会保存一个event feed.ndjson

#通过cds的链接来启动
.\resolver.bat <cds> admin <passwd> [options]
#通过cdp目录启动,建议这个
.\resolver.bat <contestPackagePath> [options]
#通过eventfeed文件来启动
.\resolver.bat <eventFeedPath> [options]

什么是cdp目录Contest Package Format · CCS Specs

这个目录也很好获取

首先你在本地配置cds后,他会在location你配置的location位置下生成一些下面需要的东西

<contest location="/home/cds/contest-data" recordReactions="false">

在自己添加一个config文件夹就可以了,然后把award生成的event-feed.ndjson放到这里就行

.
├── config              // 非必需
│   ├── contest.yaml    // 从domjudge Import/export页面导出即可
│   ├── groups.tsv      // 从domjudge Import/export页面导出即可
│   ├── problemset.yaml
│   └── teams.tsv       // 从domjudge Import/export页面导出即可
├── contest
│   ├── banner.png      // resolver无用,但在cds放置于此就可显示banner
│   └── logo.png        // resolver主页面的图片&无照片队伍的默认照片
├── event-feed.ndjson   // 滚榜数据
├── groups              // Categories照片,但在resolver似乎没起到作用
│   └── 3               // Categories的id
│       └── logo.png
├── organizations       // Affiliations照片,只要某Affiliations的队伍有logo,其他同Affiliations的队伍就都是该logo
│   ├── 3000            // 该Affiliations所对应的任一队伍的icpc id
│   │   └── logo.png
│   ├── 3001
│   │   └── logo.png
│   ├── 3012
│   │   └── logo.png
│   ├── 3017
│   │   ├── country_flag.png    // 照源码里是这样放置的,但在resolver似乎没起到作用
│   │   └── logo.png
│   └── 3187
│       └── logo.png
└── teams               // 队伍照片
    ├── 3000            // 队伍的icpc id
    │   └── photo.png   // 照片名字固定是photo
    ├── 3001
    │   └── photo.png
    ├── 3009
    │   └── photo.png
    └── 3010
        └── photo.png

然后就可以直接

.\resolver.bat cpd路径 --singleStep 999

--pause 一般调试用,表示按num下

--speed 解析速度

--light 主题改为light

--display 指定在全屏独占模式下使用的桌面显示。主显示器为1号,次显示器为2号,依此类推。如果未指定此选项,则默认为主显示。

--singleStep 前numRow排名的强制单步解析

相关操作

Ctrl-Q 退出

space 或者 f 前进一步

r 或者 b 退后一步

0 重新开始

2 快进一步(没有延迟)

1快退一步(没有延迟)

+ 或者 =加快解析速度

- 或者 _降低解析速度

其他问题

如何在颁奖界面显示队伍名字

两种方式

第一种,我们给每个队伍有奖的队伍放一张他们的图片,图片放在teams下面

第二种,我们给每个队伍颁一个奖,奖项的名字叫他们团队的名字

在award里面是这样写的

我们可以写写脚本生成,直接对应event-feed.ndjson里面

//格式
{
    "type":"awards", //事件类型 这里写奖项
    "id":"id_formal_contest_100", //奖项id
    "data":{
        "id":"id_formal_contest_100", //奖项id
        "team_ids":["formal_contest_100"],// 获奖的队伍id
        "citation":"队伍名称", //屏幕上显示什么
        "display_mode":"pause", //滚榜模式
        "parameters":{}
    },
    "token":"cd233722" // 事件id 一般接着上面的写连续就行
}

{"type":"awards","id":"observer-bronze-medal","data":{"id":"observer-bronze-medal","team_ids":["formal_contest_337","formal_contest_373"],"citation":"等同铜奖","parameters":{}},"token":"cd233721"}

{"type":"awards","id":"id_formal_contest_100","data":{"id":"id_formal_contest_100","team_ids":["formal_contest_100"],"citation":"我是名字","display_mode":"pause","parameters":{}},"token":"cd233722"}

两个注意点,type对应的字段是awards,id需要唯一,如果是给队伍显示名字,"display_mode":"pause"需要加上这个字段,然后token需要和上面的连续team_ids是一个数组,包含哪些队伍获得该奖项citation是奖项名字

Configuration settingsDisplay中关掉Show flags打开Show affiliation logos

logo获取可以取这个网站看看555所大学校徽 - 中国大学矢量校徽大全

参考

关于搭建 domjudge 还有其他一些 ICPC Tool 之类的事 – 赤红幻想

Domjudge配置指南 & 校赛踩坑记录 - 知乎

Polygon2DOMjudge/README.cn.md at master · cn-xcpc-tools/Polygon2DOMjudge

Connecting the ICPC Tools with DOMjudge · DOMjudge/domjudge Wiki

Connecting the ICPC Tools with DOMjudge · DOMjudge/domjudge Wiki

Contest Package Format · CCS Specs

cn-xcpc-docs/domserver.md at master · cn-xcpc-tools/cn-xcpc-docs

使用icpc tool进行滚榜操作_icpc tools-CSDN博客

DOMjudge 中文文档

posted @ 2024-12-10 17:45  叽莜玖  阅读(572)  评论(0)    收藏  举报