月度归档:2022年11月

UOJ自动配置题目数据

计划未来几个星期进行线上测试,所以最近就挑了 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
)