龍 丹,徐 軻,甘 泉
(桂林信息科技學院信息工程學院,桂林 541004)
在線測評系統如今為人類社會提供了關于數據結構、算法和數學的重要服務,在學術界和工業界發揮著重要的作用,特別是在競賽教育方面,使用在線測評系統的用戶的編程和思維能力得到了鍛煉和提升[1]。
為了解決在線提交解決方案代碼的問題,XKOJ 設計了用戶表、題目表、提交表、比賽表和博客表,構建了完整的在線測評系統生態。該系統包含用戶注冊登錄、題目創建和閱讀、代碼提交驗證、比賽創建和運行、以及博客發表和瀏覽功能。該項目運行在云服務器上,使用Django 框架和Redis兩個Docker容器來保證安全性和可移植性。在Django 項目中,提交題目使用異步任務隊列Celery 來避免在線提交解決方案可能發生的沖突。每一個需要測評的程序都通過延時進入函數,作為一個任務加入到隊列中,由隊列中的調度方案來執行任務。通過任務文件中不同的裝飾器找到任務所需執行的函數代碼,對提交代碼進行編譯評測,反饋結果到視圖文件中,并通過數據渲染給前端頁面,讓用戶直觀看到提交結果。
租賃云服務器,本系統所運行的環境為Ubuntu 20.04。在本地創建鏡像后,可以利用鏡像創建Docker容器,并在容器內安裝項目所需的使用工具,例如Python 3、Vim 和Django-admin等。為該容器創建用戶并分配Sudo 權限,然后可以使用服務器端口和賬號密碼直接進行SSH登錄。
Django 默認使用關系型數據庫管理系統。其中SQLite 是默認的數據庫引擎,它是一個輕量級的數據庫,無需獨立的服務器進程,直接存儲在文件中。Django 的對象關系映射提供了一種將對象映射到關系數據庫中的方法,可以將對象轉換為SQL 查詢,從而在數據庫中創建、讀取、更新和刪除數據。
Django 的ORM 基于模型和字段的概念。模型表示數據庫中的一個表,而字段則表示該表中的一列。模型類定義了模型的屬性和行為,其中屬性是模型的字段。模型類還可以通過定義方法來實現模型的邏輯和行為。
XKOJ 為云服務器掛載Docker 中創建的項目,在Docker 中操作項目能簡化項目的部署和隔離管理,提高系統的可擴展性和安全性。系統運用了Python 語言支持的Django 框架來搭建,重點邏輯部分有三塊內容:模型、視圖、數據庫。通過模型定義數據的結構,視圖負責處理用戶的請求并返回響應,數據庫用于存儲應用程序的數據[2]。通過鏈接調用對應的視圖中的函數,來實現后端響應的功能,同時可以通過標識、POST 或GET 方法獲取相應的頁面內容,并在加載的數據庫中找出對應的內容,將處理好的數據集打包傳遞給將要加載的網頁中。
數據庫處理采用Django 自帶的默認關系型數據庫,通過映射的方式創建數據庫表,對在線測評系統所需的用戶、題目、比賽、博客、提交信息進行特征封裝,并在邏輯上需要時將它們相互關聯,保證信息的連通性。在項目完成上,使用了部分Shell 腳本來幫助管理員解決啟用系統文件、代碼文件與編譯文件定量刪除等;在前端頁面上自定義了絕大部分樣式代碼,引入了Ace 代碼編輯器、Markdown、Mathjax 等開源文件增加頁面可讀性;在后端引入Celery異步任務隊列,通過創建任務文件編寫任務邏輯,在視圖中將打包好數據集的任務放入隊列中進行等待,在消息隊列空閑時將會通過自身的調度方式執行一個任務。
通過Docker 將開放端口掛載Redis 緩存數據庫,Celery 使用Redis 作為消息代理,將任務放入Redis 中間件隊列,并從隊列中獲取任務以進行處理。Redis 作為消息代理,具有快速讀取和寫入的能力,可以使得Celery 的任務執行更加高效和快速。此外,Celery 還使用Redis 作為結果存儲,保存任務執行的結果和狀態,以供查詢和分析。
測評機首先要根據提交信息的表單傳入信息,在異常處理模塊下根據聲明的數據庫變量讀取到信息數據集。程序根據使用語言執行對應的編譯指令,在創建的子進程中對提交程序代碼進行編譯,通過返回的編譯文件,在子進程中產生輸出文件并與測試樣例輸出文件進行對比,結合編譯時的信息返回相應結果,包含通過、錯誤、編譯錯誤、超時、超限、程序異常[3]。
對于多組測試用例,則需要產生多組子進程來執行編譯文件產生結果集,將各種情況存放在列表中,按照結果優先級進行反饋。
對于沒有確定結果的題目,需要采取特殊判斷的方式,即按照用戶提交代碼產生的結果信息,根據題目要求邏輯,進行驗證程序的編寫,并將用戶提交代碼的輸出文件輸入到驗證程序中運行,若滿足所有條件,或輸出期望結果,則返回此提交結果正確,否則依舊根據結合編譯時的信息,按照各種情況的優先級進行反饋[4]。

圖1 測評機處理任務流程
在XKOJ中,訓練模式對應標題單,比賽模式對應比賽。在查看題目之后的所有操作都相同,但是會調用不同的測評機,傳遞不同的比賽信息。在XKOJ中,視圖會根據不同的比賽ID將提交結果保存在不同比賽外鍵的表中,在后續查看比賽排名與提交信息時,能夠清晰地顯示當前比賽中的各種信息。但如果是在題單中提交代碼,則不會將其添加到任何比賽中,而是會保存在無比賽外鍵的表中,為用戶提供狀態查看與代碼查看。

圖2 練習、比賽共用題庫模塊需求
系統功能總體分為四個類別:設置、題目、博客、比賽。
在每個類別下,需要編寫對應的視圖函數實現需求。
設置:登錄、登出、注冊、查看用戶信息。
題目:查看題目列表、查看題目內容、提交解決方案、查看提交結果。
博客:查看文章列表、編寫博客、查看文章內容、點贊、評論。
比賽:創建比賽、報名、查看比賽列表、查看比賽排名、查看提交狀態。
實現不同的視圖函數,需要建立對應的數據表,用來支持系統完成相應的操作。

圖3 XKOJ主要數據表結構系統重點視圖函數與數據庫表
用戶是在線測評系統一個重要的組成部分,系統需要具體實現:注冊、登錄、填寫、顯示和修改個人信息功能,并保證用戶提交題目或者比賽會產生相應的練習數據與比賽數據,并能進行查詢。
一個在線測評系統需要驗證用戶根據題目要求編寫的代碼是否正確,即需要設計一個滿足評測需求的測評機。測評機需要識別語言和代碼信息,并編譯運行程序,判斷程序是否符合要求,將結果數據打包返回。
對于處理多用戶多提交解決方案代碼的實際情況,首先應保證測評機能穩定有序地返回評測結果,其次應盡可能優化測評機的評測水平以提高其性能??紤]到安全性,防止提交代碼內包含惡意攻擊代碼,應盡可能使用子進程去驗證并執行子任務。

圖4 測評機功能分析
題庫是在線測評系統的核心,有了階梯難度分布的廣泛題庫,才能更好地鍛煉用戶的代碼水平[5]。
解決問題的代碼編寫需要在限定的時間和空間復雜度內考察用戶的算法能力,并對數據范圍有敏感的認知。通過各表間的相互聯系,共同實現在線測評系統的一整套流程。
博客是在線測評系統的重要組成部分,用戶可以通過編寫博客的方式進行輸出,分享解決問題或積累的知識,還可以通過博客內的各類知識與題解提高自己的學識。博客查閱需要舒適的閱讀體驗,可以通過封裝Markdown 提高內容的可讀性。
比賽是一個封裝的功能,需要保證每場比賽之間的獨立性。同時,在邏輯上,XKOJ 將題單作為沒有開始與結束時間的比賽放在比賽頁面中。用戶點擊比賽時,將跳轉到報名信息界面進行報名。如果用戶未報名,則返回報名成功;如果已報名,則進入具體比賽界面。通過不同表單之間的聯系,匹配用戶、題目、比賽三元組的信息,在比賽期間實時更新排名。在提交表中加入用戶提交本題的錯誤次數、正確標識和正確時間;在排名表中加入用戶的總通過數和總花費時間,作為特征依據“通過數量多者優先,通過數量相同者花費時間小者優先”的規則,對每位參加比賽的用戶進行排序。
對于提交狀態,只需要在比賽內的測評機內不斷更新任務隊列中已處理的任務信息即可。同時,根據自定義需求,在網頁上顯示部分特征。
關于比賽題目查閱問題,本系統采用通過超鏈接傳遞比賽ID 的方式,讓題目在提交時首先判斷是通過練習題單提交還是通過比賽提交,并調用不同的測評機進行評測。這樣能夠很好地將提交信息封裝到每場不同的比賽中,保證數據清晰。
Celery是一種基于Python 的異步任務隊列消息代理,它提供了分布式任務調度和處理的功能。它可以與多種后端存儲集成,支持任務的異步執行,可靠性高、可擴展性強。

測評環境為阿里云服務器2 核2 GB,測試內容為使用Celery 作為任務隊列來實現一個測評機任務隊列,Redis 作為支持AMQP 的消息代理傳遞消息。通常情況下,Celery支持處理數以萬計的任務,但是任務隊列的吞吐量會受到消息代理的限制、任務處理時間的約束。
本次測試通過程序編寫,模擬用戶提交解決方案,并發提交5000 個任務到任務隊列中,并記錄完成這些任務所需要的時間。為了測試測評機的吞吐量,測試了使用1 個測評機和4 個測評機的情況完成所有任務所需的時間,并計算出每秒可以測評的任務數量。
進行兩組測試,一組測試需要計算兩個數的和;另一組測試題目為圖論經典題目最大流,需要在有向圖中找到一條從原點到匯點的路徑,使得路徑上的最小邊權最大。

表1 測評機吞吐量測試
經過表格內的測試結果,在任務量很大時測評機依舊可以保持不錯的狀態,使用4個測評機時效率大概為單測評機的四倍。這說明,在處理較大的任務量時,使用Celery 可以顯著提高任務處理的效率,減少任務完成的時間,提高系統的性能。因此,在本系統的使用需求下,采用Celery實現任務隊列是不錯的選擇。
近年來,在線評測系統已經被廣泛應用于各個領域。隨著計算機科學技術的不斷發展,在線評測系統也在不斷進步和完善。未來,這些系統將引入更多的智能技術,如機器學習和深度學習,以提高評測的準確性和效率[6]。同時,為了保證比賽評判的公正性,將會為比賽參賽者提供更高效的代碼查重機制,并引入更加公正和客觀的評判機制。這些系統將根據不同用戶的需求和特點,提供更加個性化的學習內容和評測體驗。未來,在線評測系統將會不斷更新題庫,覆蓋更多的算法和數據結構等知識,同時添加更多實際應用場景下的編程題目,以幫助程序員更好地解決現實生活中遇到的問題。
此外,未來的在線評測系統將建立更加開放的社區生態,注重社區的建設和發展,為用戶提供更豐富的交流和互動機會,促進用戶之間的交流和學習。同時,這些系統將提供更加高效的測試和調試工具,幫助程序員更快地發現和解決程序中的問題。它們還將為新出現的編程語言提供機會和平臺,以便它們傳播、交流和發展。不僅如此,這些系統還將為不同需求的群體提供一個計算機科學技術交流的平臺,促進計算機科學技術的發展。