写了OJ判题的东东

于 2011年11月23日 发布在 编程语言 跳到评论

课程设计我们做OJ,具体来说应该是比赛平台。我的主要工作内容是clarification版块,处理用户提交和判题,判题这个东东学长写过,但是不打算用他的,准备自己写个,顺便练习下python。

这个代码参考了两个项目的代码,一个是 ONJ ,另一个是neuoj,ONJ是一个用php写的简单很漂亮的比赛平台,他的代码写的十分工整,推荐想学php和正在学php的读读他的源码,写的非常好,他的判题部分是用python写的,正是因为之前看过这个,所以才敢在课程设计上写。neuoj帮我改进了不少东西,有兴趣的也可以看看。

本来是想直接通过python把判题的结果直接放到数据库里面的,但是还要安装MySqldb库,不方便,就没动。。

只能运行载linux下了,里面的os.sep可以替换成’/’了。。之前是想载win上也能运行。java判题有待添加

?Download runoj.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python
 
"""
coded by fookwood
parameters are passed like this:
$ ./onj 1.cpp 1002 1000 32767
argv[1] : the source code that will be compiled
argv[2] : the problem number
argv[3] : the time limit
argv[4] : the memory limit 
"""
 
import sys, signal, os, subprocess, syslog, time
 
PROBLEMDIR = 'problems'
CODEDIR = 'codes'
 
# Verdicts
verdict = { \
	'ACCEPTED' : 0 ,\
	'WA' : 1,\
	'TLE' : 2,\
	'MLE' : 3,\
	'RE' : 4,\
	'CE' : 5,\
	'OLE' : 6,\
	'ILE' : 7,\
	'PE' : 8 }
 
TIME_LIMIT = int(sys.argv[3])
MEMORY_LIMIT = int(sys.argv[4])
 
def debug(msg):
	print msg
	syslog.syslog(msg)
 
# check if two files are the same
def file_same(a,b):
	fileA = open(a,'r')
	fileB = open(b,'r')
	value = False
	if fileA.readlines() == fileB.readlines():
		value = True
	fileA.close()
	fileB.close()
	return value;
 
# if two files are almost the same	
def compare_files(a,b):
	fileA = open(a,'r')
	fileB = open(b,'r')
	linesA = fileA.read()
	linesB = fileB.read()
	fileA.close()
	fileB.close()
	if linesA.strip() == linesB.strip():
		return True
	return False
 
# Parse commandlines options
sourcefile = sys.argv[1]
problem = sys.argv[2]
path = "."+os.sep+"tmp"
ext = sourcefile.split(".")[1]
runid = sourcefile.split(".")[0]
"""
print sourcefile	1.cpp
print problem		1001
print path			./tmp
print ext			cpp
"""
# check if the code is too long
a = open(CODEDIR+os.sep+sourcefile,"r")
codecode = a.read()
a.close()
if len(codecode) >= 50000:
	debug("ILE")
	sys.exit(verdict["ILE"]);
 
if ext == "cpp":
	compile="g++ -lm %s -o %s 2> /dev/null" % \
			 (CODEDIR+os.sep+sourcefile,path+os.sep+runid)
elif ext  == "c":
	compile="gcc -lm %s -o %s 2> /dev/null" % \
			 (CODEDIR+os.sep+sourcefile,path+os.sep+runid)
 
if os.system(compile):
	debug("CE")
	sys.exit(verdict["CE"])
 
run = path+os.sep+runid
infile = PROBLEMDIR + os.sep + problem + os.sep + problem + ".IN"
outfile= path+os.sep+runid+".OUT"
 
# Run
debug("Running...")
p = subprocess.Popen( run,stdin=open(infile,"r"),stdout=open(outfile,"w"),stderr=open("/dev/null","w"))
start = time.time()
while p.poll() == None:
	s = file("/proc/"+str(p.pid)+'/status','r').read()
	if s.find('RSS') < 0: 		continue 	s=s[s.find('RSS')+6:] 	s=s[:s.find('kB')-1] 	mm = int(s) 	if mm > MEMORY_LIMIT:
		p.kill()
		debug("MLE")
		sys.exit(verdict["MLE"])
	tt = int((time.time()-start)*1000)
	if tt > TIME_LIMIT:
		p.kill()
		debug("TLE")
		sys.exit(verdict["TLE"])
 
print "time cost:"+str(tt)+"ms";	
print "mem  cost:"+str(mm)+"kb"
r = p.returncode
debug("Exit status : %d " % r )
if r != 0:
	debug("RE")
	sys.exit(verdict["RE"])
 
# compare output with expected out
outputProduced = outfile
outputExpected = PROBLEMDIR + os.sep + problem + os.sep + problem + ".OUT"
 
a = open(outfile,'r')
codecode = a.read()
if len(codecode) >= 50000:
	debug( "OLE");
	sys.exit(verdict["OLE"] )
 
timefile= open(path+os.sep+sys.argv[1]+".TIME","w")
memfile = open(path+os.sep+sys.argv[1]+".MEM","w")
timefile.write(str(tt))
memfile.write(str(mm))
timefile.close()
memfile.close()
 
if compare_files(outputProduced,outputExpected) == True:
	if file_same(outputProduced,outputExpected) == True:
		debug("AC")
		sys.exit( verdict["ACCEPTED"] )
	else:
		debug("PE")
		sys.exit( verdict["PE"] )
else:
	debug("WA")
	sys.exit(verdict["WA"])

本文共有 9条评论 | 沙发:文章评论

  1. WilliamKyle说道:

    Linux下的调用就是方便啊~~~~

  2. gb说道:

    有兴趣下个学期合作一个判作弊的东西么?

  3. acmol说道:

    安全性没考虑?还是用其它什么方式实现的?比如system(“reboot”)什么的。
    RE判断有些问题感觉,特别是我偶尔主函数如果写了个return 2了什么的,你似乎判成RE了(不过确实有OJ把主函数返回值不是0特别判断出来,不当AC)?

  4. fookwood说道:

    安全性完全木有考虑。。。
    完全为了应付课程设计,求你的安全问题是怎么处理的?

留下评论!

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)