mirror of
https://github.com/QingdaoU/OpenVJ.git
synced 2025-01-16 01:13:36 +00:00
127 lines
6.1 KiB
Python
127 lines
6.1 KiB
Python
# coding=utf-8
|
|
import re
|
|
import html
|
|
from .robot import Robot
|
|
from .exceptions import AuthFailed,RequestFailed, RegexError, SubmitProblemFailed
|
|
from .utils import Language, Result
|
|
|
|
|
|
class ZOJRobot(Robot):
|
|
def save(self):
|
|
return {"cookies": self.cookies}
|
|
|
|
def check_url(self, url):
|
|
regex = r"^http://acm.zju.edu.cn/onlinejudge/showProblem.do\?problemCode=(\d{4})$"
|
|
return re.compile(regex).match(url) is not None
|
|
|
|
def login(self, username, password):
|
|
url = r"http://acm.zju.edu.cn/onlinejudge/login.do"
|
|
data = {
|
|
"handle": username,
|
|
"password": password,
|
|
"rememberMe": "on"
|
|
}
|
|
headers = {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Referer": "http://acm.zju.edu.cn/onlinejudge/login.do"
|
|
}
|
|
r = self.post(url, data, headers)
|
|
|
|
if r.status_code != 302:
|
|
raise AuthFailed("Failed to login ZOJ!")
|
|
self.cookies = dict(r.cookies)
|
|
|
|
@property
|
|
def is_logged_in(self):
|
|
r = self.get("http://acm.zju.edu.cn/onlinejudge/editProfile.do", cookies = self.cookies)
|
|
return r'<td align="right">Confirm Password</td>' in r.text
|
|
|
|
def get_problem(self, url):
|
|
if not self.check_url(url):
|
|
raise RequestFailed("Invalid ZOJ URL!")
|
|
regex = {
|
|
"title": r"<center><span\s*class=\"bigProblemTitle\">(.*)</span></center>",
|
|
"time_Limit": r"<font\s*color=\"green\">Time\s*Limit:\s*</font>\s*(\d+)\s*(?:Seconds|Second)",
|
|
"memory_limit": r"<font\s*color=\"green\">Memory\s*Limit:\s*</font>\s*(\d+)\s*KB",
|
|
"description": r"</center>\s*<hr>[\s\S]*?<p>\s*([\s\S]*?)\s*(?:<b>|<h4>)Input",
|
|
"input_description": r"(?:<h4>|<b>|<strong>)Input(?:</h4>|</b>|</strong>)\s*([\s\S]*?)\s*(?:<h4>|<b>|<strong>)Output(?:</h4>|</b>|</strong>)",
|
|
"output_description": r"(?:<h4>|<b>|<strong>)Output(?:</h4>|</b>|</strong>)\s*([\s\S]*?)\s*(?:<h4>|<b>|<strong>)Sample Input",
|
|
"samples": r"(?:<h4>|<b>|<strong>)Sample\sInput(?:</h4>|</b>|</strong>)\s*<pre>\s*([\s\S]*?)</pre>\s*(?:<h4>|<strong>|<b>)Sample Output(?:</b>|</strong>|</h4>)\s*<pre>([\s\S]*?)</pre>",
|
|
"hint": r'(?:<h4>|<b>|<strong>)Hint(?:</h4>|</b>|</strong>)\s*<p>[\s\S]*<hr>'
|
|
}
|
|
data = self._regex_page(url, regex)
|
|
data["id"] = re.compile(r"^http://acm.zju.edu.cn/onlinejudge/showProblem.do\?problemCode=(\d{4})$").findall(url)[0]
|
|
data["memory_limit"] = int(data["memory_limit"]) // 1024
|
|
data["time_limit"] = int(data["time_limit"])
|
|
return data
|
|
|
|
def _regex_page(self, url, regex):
|
|
r = self.get(url)
|
|
self.check_status_code(r)
|
|
data = {}
|
|
for k, v in regex.items():
|
|
items = re.compile(v).findall(r.text)
|
|
if not items:
|
|
raise RegexError("NO such data!")
|
|
if k != "samples":
|
|
data[k] = self._clean_html(items[0])
|
|
else:
|
|
data[k] = {items[0][0]: items[0][1]}
|
|
return data
|
|
|
|
def submit(self, submit_url, language, code, origin_id):
|
|
if language == Language.C:
|
|
compiler_id = "1"
|
|
elif language == Language.CPP:
|
|
compiler_id = "2"
|
|
else:
|
|
compiler_id = "4"
|
|
r = self.post(submit_url,
|
|
data={"problemId": str(int(origin_id) - 1000), "languageId": compiler_id, "source": code},
|
|
cookies=self.cookies,
|
|
headers={"Referer": "http://acm.zju.edu.cn/",
|
|
"Content-Type": "application/x-www-form-urlencoded"})
|
|
if r.status_code != 200:
|
|
raise SubmitProblemFailed("Failed to submit problem, url: %s, status code: %d" % (submit_url, r.status_code))
|
|
return re.compile(r"<p>Your source has been submitted. The submission id is <font color='red'>(\d+)</font>").findall(r.text)[0]
|
|
|
|
def get_result(self, submission_id, username):
|
|
url = r"http://acm.zju.edu.cn/onlinejudge/showRuns.do?contestId=1&search=true&firstId=-1&lastId=-1&problemCode=&handle=&idStart=" + \
|
|
submission_id + r"&idEnd=" + submission_id
|
|
r = self.get(url, headers={r"Referer": r"http://acm.zju.edu.cn/"}, cookies=self.cookies)
|
|
res = {"info": {"error": None}, "cpu_time": None, "memory": None}
|
|
|
|
compile_list = re.compile(r'<a href="/onlinejudge/showJudgeComment\.do\?submissionId=(\d+)">Compilation Error</a>').findall(r.text)
|
|
if compile_list:
|
|
res["result"] = Result.compile_error
|
|
compile_id = compile_list[0]
|
|
res["info"]["error"] = self.get(r"http://acm.zju.edu.cn/onlinejudge/showJudgeComment.do?submissionId=" + compile_id,
|
|
headers={r"Referer": r"http://acm.zju.edu.cn/"}, cookies=self.cookies).text
|
|
elif r"No submission available." in r.text:
|
|
res["result"] = Result.waiting
|
|
else:
|
|
regex = {
|
|
"result": r'<span class="judgeReply(?:AC|Other)">\s*([\s\S]*?)\s*</span></td>',
|
|
"cpu_time": r'<td class="runTime">(\d+)</td>',
|
|
"memory": r'<td class="runMemory">(\d+)</td>',
|
|
}
|
|
result_str = re.compile(regex["result"]).findall(r.text)[0]
|
|
|
|
result_mapping = {
|
|
"Accepted": Result.accepted,
|
|
"Time Limit Exceeded": Result.time_limit_exceeded,
|
|
"Memory Limit Exceeded": Result.memory_limit_exceeded,
|
|
"Compilation Error": Result.compile_error,
|
|
"Presentation Error": Result.format_error,
|
|
"Wrong Answer": Result.wrong_answer,
|
|
"Segmentation Fault": Result.runtime_error,
|
|
"Non-zero Exit Code": Result.runtime_error,
|
|
"Floating Point Error": Result.runtime_error,
|
|
"Output Limit Exceeded": Result.runtime_error,
|
|
}
|
|
|
|
res["result"] = result_mapping[result_str]
|
|
res["cpu_time"] = int(re.compile(regex["cpu_time"]).findall(r.text)[0])
|
|
res["memory"] = int(re.compile(regex["memory"]).findall(r.text)[0])
|
|
return res
|