Skip to content

Commit 5e8a050

Browse files
committed
copy template files when creating lab instance
1 parent 365fd7a commit 5e8a050

File tree

3 files changed

+81
-25
lines changed

3 files changed

+81
-25
lines changed

judge/languages.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,7 @@
225225
}
226226

227227
languages = [
228-
{"config": _c_lang_config, "spj":
229-
{"compile": _c_lang_spj_compile, "config": _c_lang_spj_config},
228+
{"config": _c_lang_config, "spj": {"compile": _c_lang_spj_compile, "config": _c_lang_spj_config},
230229
"name": "C", "description": "GCC 9.4", "content_type": "text/x-csrc"},
231230
{"config": _cpp_lang_config, "spj": {"compile": _cpp_lang_spj_compile, "config": _cpp_lang_spj_config},
232231
"name": "C++", "description": "G++ 9.4", "content_type": "text/x-c++src"},

judge/testing.py

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import zipfile
23
import os
34
import shutil
@@ -7,22 +8,32 @@
78

89
from onl.settings import DATA_DIR
910
from problem.models import Problem
10-
from submission.models import Submission
11+
from submission.models import JudgeStatus, Submission
1112

1213

1314
PROBLEM_DIR = "problems"
1415
SUBMISSION_DIR = "submissions"
1516
ZIPFILE_DIR = "zips"
1617

18+
TESTCASE_NAME = "testcases.json"
19+
TESTER_NAME = "tester"
20+
21+
def create_new_problem_from_template(new_problem_id: str, old_problem_id: str):
22+
old_path = PathManager.problem_dir(old_problem_id)
23+
new_path = PathManager.problem_dir(new_problem_id)
24+
os.makedirs(new_path, exist_ok=True)
25+
for filename in os.listdir(old_path):
26+
shutil.copyfile(join(old_path, filename), join(new_path, filename))
27+
print(f'create problem instance {new_path}')
1728

1829
class PathManager:
1930
@staticmethod
2031
def problem_dir(problem_id: str) -> str:
2132
return join(DATA_DIR, PROBLEM_DIR, problem_id)
2233

2334
@staticmethod
24-
def submission_dir(submission_id: str) -> str:
25-
return join(DATA_DIR, SUBMISSION_DIR, submission_id)
35+
def submission_dir(user_id: str, submission_id: str) -> str:
36+
return join(DATA_DIR, SUBMISSION_DIR, user_id, submission_id)
2637

2738
@staticmethod
2839
def zipfile_path(problem_id: str, zipfile_name: str) -> str:
@@ -104,15 +115,58 @@ def upload(self) -> bool:
104115

105116

106117
class SubmissionTester:
107-
def __init__(self, submit_id: str, problem_id: str):
108-
self.submit_id = submit_id
109-
self.problem_id = problem_id
110-
self.submission_dir_path = PathManager.submission_dir(submit_id)
111-
if not exists(self.submission_dir_path):
112-
os.makedirs(self.submission_dir_path, exist_ok=True)
118+
def __init__(self, submission: Submission):
119+
self.sub = submission
120+
self.sub_dirpath = PathManager.submission_dir(str(submission.user_id), submission.id)
121+
if not exists(self.sub_dirpath):
122+
os.makedirs(self.sub_dirpath, exist_ok=True)
123+
prob_dir = PathManager.problem_dir(submission.problem._id) # use display id
124+
if not exists(prob_dir):
125+
raise Exception("problem dir {} not exists".format(prob_dir))
126+
for filename in os.listdir(prob_dir):
127+
shutil.copyfile(join(prob_dir, filename), self.sub_dirpath)
113128

114129
def judge(self):
115-
tester = join(self.submission_dir_path, "tester")
116-
if not exists(tester):
117-
raise Exception(f"running submission: tester {tester} not exists")
118-
subprocess.run([tester, '--log', '--json'])
130+
tester_path = join(self.sub_dirpath, TESTER_NAME)
131+
if not exists(tester_path):
132+
raise Exception("running submission: tester {} not exists".format(tester_path))
133+
print(f"running {tester_path}")
134+
subprocess.run([tester_path, '--log', '--json'])
135+
log_path = join(self.sub_dirpath, 'logs')
136+
if not exists(log_path):
137+
raise Exception(f"logs path {log_path} not exists")
138+
failed_info = []
139+
with open(join(log_path, "results.txt")) as fp:
140+
res = json.load(fp)
141+
self.sub.grade = res['grade']
142+
for idx in res['failed']:
143+
log_fp = open(join(log_path, f"testcase{idx}.log"), "r")
144+
testcase_fp = open(join(self.sub_dirpath, TESTCASE_NAME), "r")
145+
testcase_json_data = json.load(testcase_fp)
146+
if "config" in testcase_json_data:
147+
# global config
148+
config = testcase_json_data["config"]
149+
else:
150+
cur_data = testcase_json_data["testcases"][idx]
151+
if "config" in cur_data:
152+
# specific config for testcase
153+
config = ["config"]
154+
else:
155+
# no config
156+
config = None
157+
displayed_test = {
158+
"input": testcase_json_data["testcases"][idx]["input"],
159+
"expected_output":testcase_json_data["testcases"][idx]["output"],
160+
}
161+
# config, "testcase"
162+
failed_info.append({
163+
"config": config,
164+
"testcase_index": idx,
165+
"testcase": displayed_test,
166+
"log": log_fp.read()
167+
})
168+
log_fp.close()
169+
testcase_fp.close()
170+
self.sub.failed_info = failed_info
171+
self.sub.result = JudgeStatus.FINISHED
172+
self.sub.save()

problem/views/admin.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from utils.api import APIView, validate_serializer
1111
from utils.shortcuts import rand_str
1212
from utils.tasks import delete_files
13-
from judge.testing import ZipFileUploader
13+
from judge.testing import ZipFileUploader, create_new_problem_from_template
1414

1515
from ..models import Problem, ProblemTag
1616
from ..serializers import *
@@ -300,7 +300,7 @@ def post(self, request):
300300
data = request.data
301301
try:
302302
contest = Contest.objects.get(id=data["contest_id"])
303-
problem = Problem.objects.get(id=data["problem_id"])
303+
old_problem = Problem.objects.get(id=data["problem_id"])
304304
except (Contest.DoesNotExist, Problem.DoesNotExist):
305305
return self.error("Contest or Problem does not exist")
306306
data["lab_id"] = data.pop("problem_id")
@@ -311,19 +311,22 @@ def post(self, request):
311311
if Problem.objects.filter(contest=contest, _id=data["display_id"]).exists():
312312
return self.error("Duplicate display id in this contest")
313313
if "title" not in data:
314-
data["title"] = problem.title
314+
data["title"] = old_problem.title
315315
if "description" not in data:
316-
data["description"] = problem.description
316+
data["description"] = old_problem.description
317317
data["visible"] = True
318318
data["is_public"] = True
319-
data["code_num"] = problem.code_num
320-
data["code_names"] = problem.code_names
319+
data["code_num"] = old_problem.code_num
320+
data["code_names"] = old_problem.code_names
321321

322-
tags = problem.tags.all()
322+
tags = old_problem.tags.all()
323323
data["_id"] = data.pop("display_id")
324324
data["submission_number"] = data["accepted_number"] = 0
325-
problem = Problem.objects.create(**data)
326-
problem.tags.set(tags)
325+
new_problem = Problem.objects.create(**data)
326+
new_problem.tags.set(tags)
327+
328+
create_new_problem_from_template(new_problem._id, old_problem._id)
329+
327330
return self.success()
328331

329332

@@ -334,7 +337,7 @@ def choose_answers(self, user, problem):
334337
submission = Submission.objects.filter(problem=problem,
335338
user_id=user.id,
336339
language=item,
337-
result=JudgeStatus.ACCEPTED).order_by("-create_time").first()
340+
result=JudgeStatus.FINISHED).order_by("-create_time").first()
338341
if submission:
339342
ret.append({"language": submission.language, "code": submission.code})
340343
return ret

0 commit comments

Comments
 (0)