|
| 1 | +import json |
1 | 2 | import zipfile
|
2 | 3 | import os
|
3 | 4 | import shutil
|
|
7 | 8 |
|
8 | 9 | from onl.settings import DATA_DIR
|
9 | 10 | from problem.models import Problem
|
10 |
| -from submission.models import Submission |
| 11 | +from submission.models import JudgeStatus, Submission |
11 | 12 |
|
12 | 13 |
|
13 | 14 | PROBLEM_DIR = "problems"
|
14 | 15 | SUBMISSION_DIR = "submissions"
|
15 | 16 | ZIPFILE_DIR = "zips"
|
16 | 17 |
|
| 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}') |
17 | 28 |
|
18 | 29 | class PathManager:
|
19 | 30 | @staticmethod
|
20 | 31 | def problem_dir(problem_id: str) -> str:
|
21 | 32 | return join(DATA_DIR, PROBLEM_DIR, problem_id)
|
22 | 33 |
|
23 | 34 | @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) |
26 | 37 |
|
27 | 38 | @staticmethod
|
28 | 39 | def zipfile_path(problem_id: str, zipfile_name: str) -> str:
|
@@ -104,15 +115,58 @@ def upload(self) -> bool:
|
104 | 115 |
|
105 | 116 |
|
106 | 117 | 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) |
113 | 128 |
|
114 | 129 | 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() |
0 commit comments