-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
95 lines (72 loc) · 3.4 KB
/
server.py
File metadata and controls
95 lines (72 loc) · 3.4 KB
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
import os
import json
import shutil
from sqlalchemy import create_engine
from sqlalchemy.sql import text
from grader.grader import Grader
from grader.config import Configurations, WORKSPACE_PATH, DATABASE_URI, COMPILER_USER_UID, RUN_GROUP_GID
from rq import get_current_job
basedir = os.path.abspath(os.path.dirname(__file__))
engine = create_engine(DATABASE_URI, echo=True)
"""
RESULT_SUCCESS = 0
RESULT_COMPILATION_ERROR = -3
RESULT_PENDING = -2
RESULT_WRONG_ANSWER = -1
RESULT_CPU_TIME_LIMIT_EXCEEDED = 1
RESULT_REAL_TIME_LIMIT_EXCEEDED = 2
RESULT_MEMORY_LIMIT_EXCEEDED = 3
RESULT_RUNTIME_ERROR = 4
RESULT_SYSTEM_ERROR = 5
"""
""" Creates all the necessary directories to compile and execute the submitted code """
class CreateEnvironment(object):
def __init__(self, submission_id):
self.work_dir = os.path.join(WORKSPACE_PATH, str(submission_id))
def __enter__(self):
if os.path.exists(self.work_dir):
shutil.rmtree(self.work_dir)
os.mkdir(self.work_dir)
os.chown(self.work_dir, COMPILER_USER_UID, RUN_GROUP_GID)
os.chmod(self.work_dir, 0o711)
return self.work_dir
def __exit__(self, a, b, c):
shutil.rmtree(self.work_dir)
def evaluate_submission(submission_id, language, code, memory_limit, time_limit, problem_id, registration_id, points):
job = get_current_job()
with CreateEnvironment(str(submission_id)) as path:
config = Configurations.get_config(language)
src = os.path.join(path, config["compile"]["src_name"])
# Saves submitted code to file
with open(src, "w+") as f:
f.write(code)
os.chown(src, COMPILER_USER_UID, 0)
os.chmod(src, 0o400)
grader = Grader(src, config, memory_limit, time_limit, problem_id, path, job)
result = grader.grade_all()
data = {
"submission_id": submission_id,
"progress": f"{grader.max_count}/{grader.max_count}",
"testcases": json.dumps({"data": result})
}
if not any([i["result"] for i in result]):
data["status"] = 0
else:
data["status"] = max([i["result"] for i in result if i["result"] != 0])
with engine.connect() as con:
query = text("""UPDATE submission SET
testcases = :testcases, status = :status, progress = :progress
WHERE submission.id = :submission_id""")
# Update the submission with the final result
con.execute(query, **data)
# Update contest scores if there exists a registration
if data["status"] == 0 and registration_id is not None:
query = text("""UPDATE registration SET
score = score + :points
WHERE registration.id = :registration_id""")
con.execute(query, **{"points": points, "registration_id": registration_id})
# Updating the last submission timestamp
query = text("""UPDATE registration SET
last_submission = (SELECT timestamp FROM submission WHERE submission.id = :submission_id)
WHERE registration.id = :registration_id""")
con.execute(query, **{"submission_id": submission_id, "registration_id": registration_id})