学院一直是有一个自己的oj的,但是由于最近判题崩了,需要修复一下,拿到判题代码,打开却是一手node.js,让我一个搞Java的着实懵逼,因为以前学过点js,摸清判题逻辑,一步一步console.log来调bug,最后还是太复杂,把心态调崩了。最后想了了想判题就是那个流程,还是自己写一个吧,而且以前的判题只支持python2,现在谁要用python2啊。
好吧,直接开始开发:判题需要几个步骤:
1.在linux搭建编译器环境:gcc g++ java python2 python3 pascal
2.根据源码的类型创建相应的源文件(.c .cpp .java 等)
3.编译对应的源文件
4.运行程序,使用测试用例测试得出时间消耗和内存消耗。
这里最棘手的还是第四步:怎么知道内存和时间消耗?我再网上不断的查资料,后来发现几乎没有,找了很久找到一个前辈有一篇开发oj的博客,纯用python写的。由于自己对于python仅仅是入门语法,纯用python开发对于我来讲确实有点难度。但是思路是可以借鉴的。
里面提到过一个思路:在判题脚本中运行编译之后产生的可执行文件,返回一个pid,使用过linux的小伙伴应该都知道pid(通过这个pid就能找到所运行的那个程序,在top里面就可实时知道这个进程的内存消耗),在python调用linux操作系统的api就可以持续的知道这个进程的内存消耗情况,那么在judge脚本中写个死循环,不断调用操作系统api来获取内存,当时间限制过了之后这个进程还没结束,那么就可以得出结果了(timelimit)。
博客链接:https://www.cnblogs.com/ma6174/archive/2013/05/12/3074034.html
但是后面博主推荐了一个包装这些操作的python模块lorun
。
项目地址:https://github.com/lodevil/Lo-runner
这个使用很简单:
args是一个运行命令;
fd_in是一个输入流,也就是我们判题的测试文件(.in文件);
fd_out是程序的输出流,运行结束需要这个内容来判断程序是否正确的。
timelimit、memorylimit就是我们的时间空间限制啦。
调用lorun模块的run(runcfg)方法就会知道时间空间消耗。
runcfg = {
'args':['./m'],
'fd_in':fin.fileno(),
'fd_out':ftemp.fileno(),
'timelimit':1000, #in MS
'memorylimit':20000, #in KB
}
rst = lorun.run(runcfg)
通过这个模块就解决了我棘手的问题。那么我就可以在java中编写代码来实现创建源代码、编译程序,在python中计算内存和空间消耗。
judge.py
#!/usr/bin/python
# ! -*- coding: utf8 -*-
import os
import sys
import lorun
RESULT_STR = [
'Accepted',
'Presentation Error',
'Time Limit Exceeded',
'Memory Limit Exceeded',
'Wrong Answer',
'Runtime Error',
'Output Limit Exceeded',
'Compile Er