计划未来几个星期进行线上测试,所以最近就挑了 UOJ (https://github.com/UniversalOJ/UOJ-System )来部署。用 Docker 倒是简单,就是题目数据有些难。虽然之前在其他 OJ 上有过数据和代码,但要逐个导入也是麻烦。目前的方法大概是这样的:1)通过 Docker 的配置把 UOJ 的题库数据目录 (/opt/uoj_data ) 外挂到主机目录;2)执行下面的脚本,根据标程和 input,自动生成 output 和配置problem.conf 。
注:由于我是在 WSL2 通过网络驱动器(SMB)的形式访问题库数据目录。居然默认不支持,需要执行下面的命令手动挂载 WSL2 主机的网络驱动器。
sudo mkdir /mnt/y
sudo mount -t drvfs Y: /mnt/y
下面的是Linux下的Bash脚本代码:
#!/bin/bash
cur_pwd=$PWD
input_name=input
output_name=output
ext_name=txt
problem_conf=problem.conf
uoj_data_dir=/mnt/y/opt-uoj.tpu01yzx.me/uoj_data/upload/
echo "UOJ_DATA_DIR: $uoj_data_dir"
#sudo mkdir /mnt/y
#sudo mount -t drvfs Y: /mnt/y
i=0
while [ true ]; do
i=$(($i + 1));
if [ ! -d "$uoj_data_dir/$i" ]; then
break;
fi;
done;
problem_id=$(($i - 1));
echo "Found Problem ID: $problem_id"
(
cd $uoj_data_dir/$problem_id ;
std_src=$(ls std*.cpp | head -n 1)
if [ ! -e $std_src ]; then
echo "No Standard Source File was Found."
exit;
fi;
exe_name=main_$problem_id
gcc $std_src -Wall -o $exe_name
if [ ! -e "$exe_name" ]; then
echo "Compile Standard Source Failed."
exit;
fi;
for p in "ex_" "" ; do
echo "p: $p"
i=0
while [ true ]; do
i=$(($i + 1));
input_file=${p}${input_name}${i}.${ext_name}
if [ ! -e "$input_file" ]; then
break;
fi;
echo "$input_file is found."
output_file=${p}${output_name}${i}.${ext_name}
./$exe_name < "$input_file" > "$output_file"
if [ ! -e "$output_file" ]; then
echo "$output_file is NOT generated. "
else
echo "$output_file is generated. "
fi;
done;
i=$(($i - 1));
echo "Total $i tests."
conf_key="n_${p}tests"
sed -E 's/'"${conf_key}"'[[:blank:]]+[[:digit:]]+/'"${conf_key} ${i}"'/' $problem_conf > ${problem_conf}.new
rm -f $problem_conf
mv ${problem_conf}.new $problem_conf
done;
rm -f $exe_name
cat $problem_conf
)