IMUSTOJ運維——批量自動化生成題目測試資料

凝霜發表於2012-12-01

IMUSTOJ運維——批量自動化生成題目測試資料

By 馬冬亮(凝霜  Loki)

一個人的戰爭(http://blog.csdn.net/MDL13412)

關於IMUSTOJ

我們使用的OJ是基於NOJ修改而成,根據實際需求進行了一些定製,總體功能修改的很少,所以本文提供的指令碼對於使用NOJ的學校也同樣適用。

為什麼要使用指令碼運維

新增題目時,測試資料測生成是一件很麻煩的事情,每道題都需要歷經編寫標程、編寫輸入資料、編譯、連結、執行,直至輸出結果並重定向到檔案中,最後還要按照OJ的資料夾組織形式,將輸入、輸出資料放置到相應資料夾中。如果手工來對每道題進行如上操作,那任務量是非常大的,而且操作及其繁瑣,這時就需要用自動化的指令碼來幫助我們完成以上工作。

本文指令碼實現的功能

  • 給定題目序號範圍,自動生成相應的標程及輸入資料檔案模板,供使用者直接更改,而不用手工建立;
  • 自動編譯、連結標程,而後使用輸入資料執行標程,並將結果重定向到相應目錄結構中;
  • 對於編譯、連結過程中出錯的標程,會有詳細的日誌記錄;

指令碼執行截圖


指令碼實現

首先是自動生成標程和輸入資料的模板指令碼:

@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

上述程式根據STARTINDEX和ENDINDEX作為題目序號的起始及結束,生成以題號命名的XXX.cpp和XXX.in模板,供使用者進行編輯。輸出至SOURCEDIR變數所指定的目錄。由於C語言可以不經修改的使用.cpp字尾進行編譯,所以這裡將所有標程都制定為C++原始檔。

接下來是編譯、連結、執行程式,這裡分為兩個指令碼:maketest.bat和makeeach.bat

其中,maketest.bat使用者列舉標程,而makeeach.bat用於實際處理每個標程。

下面先來檢視maketest.bat的原始碼:

@echo off

set SOURCEDIR=D:\infiles

for /f "delims=" %%I in ('dir /B /ON %SOURCEDIR%') do call makeeach.bat %SOURCEDIR%\%%~nI %%~nI

pause
指令碼列舉SOURCEDIR變數所指定的資料夾中的檔案,將題號提取出來並傳遞給makeeach.bat進行進一步處理。

下面我們來檢視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對應的目錄中即可。

相關文章