自从去年 12 月,我就接到了沈老师的邀请,得知今年 3 月上海大学要又办 EC Final 了。要我 3 月底空出时间来学校帮忙。
大概是赛前一个月,我得知本次 EC Final 还会办一场华为挑战赛。不过我发现 DOMJudge 并不能支持华为挑战赛的赛制要求。于是就在 @ReiAC 的安利下找到了 Hydro OJ。经过和开发者 @undefined 的交流后,觉得它能够符合华为挑战赛的赛制要求,就决定选用它了。
听沈老师说这次比赛要用新的一批机器,不再用以前那批老的了,于是我打算提前一周去上海大学装系统。在联系计算中心的老师把 ICPC 的 ubuntu 镜像装上去以后我去学校机房试用了一下,并看了一下系统配置,觉得应该还行,跑了两个 VLC (主要是为了能够在比赛的时候抓取选手的屏幕和摄像头时不过多占用系统资源影响选手写代码)。在修复了 vscode 插件不能用并确认修好后不会默认打开 vim 插件、并把我的公钥加到系统后,我便让老师把我修复后的系统下发给了机房里的所有电脑。
受我的邀请,网友 @compute 也会从北京过来帮忙。于是我在他到上海的那天(23号)交完毕业形审材料就去上海大学了。不过由于我们去得太早了,体育馆甚至还有人在打羽毛球,隔壁的舞蹈房(a.k.a 裁判室、气球室)还在上课,完全看不出后面几天像是要比赛的样子。直到晚上 10 点多,红地毯、桌子什么的才到位。于是这一天我们就摆了,直接在酒店里打起了牌。
24 号早上,本以为服务器就能到位了,网和电都能通了,结果却等到了下午 3 点多,中间还回了几次宾馆修改我的论文整改措施。千等万等,服务器和网络终于是到位了。可是好像裁判室的桌子并不在后勤的计划内……。既然网和电都通了,趁着志愿者还在场,就让志愿者把电脑都打开了。这次我配置了 GDM 自动登录账号,所以不需要志愿者手动输入密码了。同时为了方便根据 IP 自动登录 DOMJudge 而不发密码条,这次依然需要给选手机配 IP。不过上次的配置方式是让志愿者手动配置与坐标相同的静态 IP(例如 B11 就是 10.254.130.11
这样),还是需要专业知识的,这样就有一部分志愿者无法完成。所以这次我还是让老师给选手区的网络打开了 DHCP,让机器自动拿到一个租约为 3 天的 IP,然后让志愿者在选手电脑的桌面上新建了一个 seat
的文件,并输入所在的位置。这样扫一遍网段就能拿到座位号与 IP 的对应关系了。
这时,有志愿者发现所有的电脑都没有 DHCP 到 IP,而是在使用机房还原卡上的固定 IP 地址。这可把我给急坏了,后来听计算中心的老师说,我的系统被他们 patch 过的,因为要适配他们的云控系统,所以才会有个固定的 IP(但它甚至还会给我一个默认路由)。最后我只能再让志愿者一个个去编辑 /etc/rc.local
,删掉默认路由,重新 DHCP,才把网的问题解决了(又不是不能用)。中间还意外发现了 /etc/rc.local
的权限位被设置成了 777。
这时候 @小羊
和 @qinmaye
同学也到了,接下来就是装 DOMJudge,配各种外围设施。这套东西大家都比较熟了,所以我是不是不用来了。给 DOMJudge 加上了打印内容的持久化和多打印机调度的扩展(Powered by @小羊
)、测小票机脚本、保证评测机的 chroot
环境与选手端一致(需要使用 java17,但 DOMJudge 默认的那个脚本里用的是 default-{jdk,jre}-headless
,版本并不是 17。当然这里最好的方式并不是去改 dj_make_chroot
里的包,而是直接把选手机镜像的 squashfs
解开后当 chroot
来用)。
装完以后,自然是要给 DOMJudge 上 https。那就用 ecfinal.icpc
好了,于是 @小羊
自签了一个证书,并把根证书发到了选手机上。可是好像 firefox 并不认自签名证书,还需要手动信任。于是我们就找了个选手机,手动信任以后,把 ~/.mozilla
传给了所有选手机。
后面就是 ICPC Tools 那套周围设施和 ICPC Live,基本都是 @compute 在负责,由于赛前我们两个都已经在一些练习赛上试过了,所以基本没遇到什么问题)。
练习赛前志愿者甚至不知道练习赛是要发气球的。在我和他们说了以后,他们更是打了 13 种颜色的气球(气晕……)。
练习赛有同学反映 VSCode 使用的时候会死机,我去亲自试了一下。发现了他们死机的人有着共同的操作特征。新建一个文件,打几个字以后 ctrl + s 保存。这时候后台弹出了一个文件选择框没有看到,造成了假死……实际根本没死机(后来我也是直接把这条加到了选手须知)。
还有同学投诉评测机跑得不稳。也许是我并行数开太多了,正赛实际只开了 16 个评测实例,观测下来没有什么波动。(全场甚至只有最后三份提交是排队了的)
打印机工作也比较正常,除了中间小票机 /dev/usb/lp1
的数字变了一次,导致打丢了几个气球单,不过这个问题不大。
@compute 和我反映直播画面不能播选手的流,但是直接用 vlc/mpv 等播放器都能正常打开,怀疑是浏览器的问题(然而只有我的浏览器能正常播放)。后来经过 @undefined 同学的指导,原来是大部分浏览器的 video 组件都不能播放 ts 视频。最后发邮件询问 icpc-live 的得到了一个 webrtc-proxy,把 ts 转成 webrtc 来播放。不过我们的 @compute 同学没有测试推流效果,直接导致正赛直播卡成了 PPT 。
导入正赛题目就比较轻松了……杜老师他们出的题都是在 polygon 上的,导入 DOMJudge 我也做了好多次了,交接起来非常顺利。
然后就是配了个外榜,由于各种神奇的原因,一直没有从上大这边搞到一个合适的榜单服务器,保险起见先配了一个 https://ecfinal.icpc.hydro.ac 。感谢 Hydro 的同学~
结果没想到,访问量实在是太大了,榜单上的一堆静态资源没有上 CDN,开赛半小时直接被网友打爆了。于是用 sed(1)
紧急修复……
比赛进行到中期,评测机没有遇到什么问题,我就基本上躺平了,打印区有 @qinmaye
一个人负责,他确实牛逼,直接把志愿者教会了,甚至看起了直播。直播室来了很多牛逼网友,甚至裁判都跑去客串了。
不过中间部分选手似乎遇到了问题,有的是没有注意 ulimit
栈深无限,某个数位 DP 题写 dfs 递归爆栈死了好几次机。(老问题了,吃过亏的同学应该都会注意。)还有部分队伍(好像就几个?)的 home 没刷好,导致他们的 VSCode 插件,CLion 授权什么的坏了,具体也不知道清理的时候发生了什么……反应到我这的都手动帮他们修了一下。
比赛结束以后就是整理榜单数据,核对了一下 CDS 和 DOMJudge 的榜单,和老师确定奖牌、各个奖项等。
因为这次闭幕式就在体育馆,滚榜我没有采用之前使用 CDP 离线的方式,而是直接对接 CDS。因为现在 DOMJudge 可以直接支持添加队伍照片、学校 logo 什么的了,基本上只需要用 award 颁个奖就能直接给 resolver 使用。(这 resolver 怎么又吃了 10G 的内存……)
正赛结束后电脑就要全部被收走,进行第二天的挑战赛了。我们一行人吃完回来,发现志愿者把之前的网线都拔到了地方,场地内完全不像第二天能比赛的样子,立刻找人加班放到桌子上,结果没想到早上过来全是坏的。
挑战赛时也遇到了各种问题,首先是赛前发现 DHCP 下发的学校 DNS 是不通的。(其实正赛的时候也是不通的,没有发现是因为 ecfinal.icpc
是给选手机直接写在 /etc/hosts
的,https 也是自签名的,挑战赛则是直接用了 hydro 的子域名,并且使用了 letsencrypt 的证书)紧急联系老师。很多选手在挑战赛前一天用美团外卖购买了老款的 hub,没有测试,牛逼网友下场帮他们修网 。又由于一些原因,中途还重测了一个题,卡了 3000 多个评测。最终榜单忙中出错导出了封榜前的榜单。
最后我负责的一个部分就是闭幕式上的滚榜,总得来说还算比较顺利。解说嘉宾也是之前见过的一位教练。不过由于他也没有提前看过结果,解说中间出现了一些小小的失误,不过也增加了娱乐效果。
比赛算是圆满结束了,感谢这几天前来帮忙的各位同学。特别感谢来自 Hydro 的开发者 @panda 和 @undefined 同学的帮助,让我学到了很多。我也要回学校继续改我的毕业论文了……希望我能按时毕业😭
花絮
- 本次比赛为选手提供了 DOMJudge 的命令行提交的脚本,全场 4842 个提交中有来自 32 个队伍的 465 个提交使用了脚本提交。
- 闭幕式上的回顾短片中的部分素材来自选手机上的前置摄像头捕捉的 reaction 视频。