IMUSTOJ运维——批量自动化生成题目测试数据
By 马冬亮(凝霜 Loki)
一个人的战争(http://blog.csdn.net/MDL13412)
关于IMUSTOJ
我们使用的OJ是基于NOJ修改而成,根据实际需求进行了一些定制,总体功能修改的很少,所以本文提供的脚本对于使用NOJ的学校也同样适用。
为什么要使用脚本运维
添加题目时,测试数据测生成是一件很麻烦的事情,每道题都需要历经编写标程、编写输入数据、编译、链接、运行,直至输出结果并重定向到文件中,最后还要按照OJ的文件夹组织形式,将输入、输出数据放置到相应文件夹中。如果手工来对每道题进行如上操作,那任务量是非常大的,而且操作及其繁琐,这时就需要用自动化的脚本来帮助我们完成以上工作。
本文脚本实现的功能
- 给定题目序号范围,自动生成相应的标程及输入数据文件模板,供用户直接更改,而不用手工创建;
- 自动编译、链接标程,而后使用输入数据运行标程,并将结果重定向到相应目录结构中;
- 对于编译、链接过程中出错的标程,会有详细的日志记录;
脚本运行截图
脚本实现
首先是自动生成标程和输入数据的模板脚本:
上述程序根据STARTINDEX和ENDINDEX作为题目序号的起始及结束,生成以题号命名的XXX.cpp和XXX.in模板,供用户进行编辑。输出至SOURCEDIR变量所指定的目录。由于C语言可以不经修改的使用.cpp后缀进行编译,所以这里将所有标程都制定为C++源文件。@echo off set STARTINDEX=1100 set ENDINDEX=1120 set STEPINDEX=1 set SOURCEDIR=D:\infiles if exist %SOURCEDIR% goto direxist >nul 2>nul mkdir %SOURCEDIR% >nul 2>nul :direxist FOR /L %%i IN (%STARTINDEX%,%STEPINDEX%,%ENDINDEX%) DO echo TODO > %SOURCEDIR%\%%i.cpp && echo TODO > %SOURCEDIR%\%%i.in pause
接下来是编译、链接、运行程序,这里分为两个脚本:maketest.bat和makeeach.bat
其中,maketest.bat用户枚举标程,而makeeach.bat用于实际处理每个标程。
下面先来查看maketest.bat的源码:
脚本枚举SOURCEDIR变量所指定的文件夹中的文件,将题号提取出来并传递给makeeach.bat进行进一步处理。@echo off set SOURCEDIR=D:\infiles for /f "delims=" %%I in ('dir /B /ON %SOURCEDIR%') do call makeeach.bat %SOURCEDIR%\%%~nI %%~nI pause
下面我们来查看makeeach.bat的源码:
这个脚本是三个脚本中最重要的一个脚本,其中:@echo off set GPPPATH=E:\IMUSTJudge\AcmJudge\bin\gcc\bin\g++.exe set OUTPUTBIN=D:\outfiles\%2.exe set LOGFILE=D:\maketest.log set OUTPUTDIR=D:\outfiles set SOURCEFILE=%1.cpp set INFILE=%1.in set OUTFILE=%OUTPUTDIR%\%2\output\%2.out if exist %OUTPUTDIR% goto direxist >nul 2>nul mkdir %OUTPUTDIR% >nul 2>nul :direxist del /f /q /s %OUTPUTBIN% >nul 2>nul %GPPPATH% %SOURCEFILE% -o %OUTPUTBIN% >nul 2>nul set err=%errorlevel% if "%err%"=="0" goto success goto failure :success mkdir %OUTPUTDIR%\%2\output >nul 2>nul %OUTPUTBIN% < %INFILE% > %OUTFILE% set COPYINFILEPATH=%OUTPUTDIR%\%2\input mkdir %OUTPUTDIR%\%2\input >nul 2>nul copy /Y %INFILE% /A %COPYINFILEPATH% /A >nul 2>nul goto end :failure echo compile %SOURCEFILE% failed echo compile %SOURCEFILE% failed >> %LOGFILE% :end
- GPPPATH指定了g++编译器的路径;
- OUTPUTBIN指定了最终编译好的程序存放路径,其命名是“题号.exe”形式;
- LOGFILE指定了错误日志的存放位置及名称;
- OUTPUTDIR指定了最终生成的输入和输出文件存放位置,会自动在此文件夹下创建以题号明明的文件夹,并在其中创建inout和output文件夹,同时将输入和输出数据拷贝至相应文件夹;
- SOURCEFILE指定了标程名称;
- IINFILE指定了输入数据文件名称;
- OUTPUTFILE指定了输出文件的路径及名称;
对于涉及到的文件夹,要先判断其是否存在,都则在复制、编译文件的时候会发生错误。
编译标程的代码很简单,如下所示:判断编译是否成功需要对命令的返回值做判断,如下所示:%GPPPATH% %SOURCEFILE% -o %OUTPUTBIN% >nul 2>nul
编译成功则运行程序,生成输出数据,并将相应文件拷贝至指定目录结构中,如下所示:set err=%errorlevel% if "%err%"=="0" goto success goto failure
若编译失败,则记录错误日志,如下所示::success mkdir %OUTPUTDIR%\%2\output >nul 2>nul %OUTPUTBIN% < %INFILE% > %OUTFILE% set COPYINFILEPATH=%OUTPUTDIR%\%2\input mkdir %OUTPUTDIR%\%2\input >nul 2>nul copy /Y %INFILE% /A %COPYINFILEPATH% /A >nul 2>nul goto end
:failure echo compile %SOURCEFILE% failed echo compile %SOURCEFILE% failed >> %LOGFILE%
脚本用法
在配置好参数后,首先运行makesourcefile.bat生成标程及输入数据模板,然后完成相应模板;
完成上述操作后,运行maketest.bat,程序将自动完成所有的相关操作,如果出错,将打印错误日志,并记录到文件中,方便用户查看;
最后,将生成的题目文件夹拷贝到OJ对应的目录中即可。