From 945ea5e4e04b121f710b5c62b3d912386892e95c Mon Sep 17 00:00:00 2001 From: virusdefender Date: Sun, 26 Nov 2017 13:42:38 +0800 Subject: [PATCH] parse problem code template --- judge/dispatcher.py | 13 +++++++-- problem/serializers.py | 63 +++++++++++++++++++++++++++++++++++++++++- problem/tests.py | 46 +++++++++++++++++++++++++++++- problem/utils.py | 10 +++++++ 4 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 problem/utils.py diff --git a/judge/dispatcher.py b/judge/dispatcher.py index 7c040297..0f5e3cbc 100644 --- a/judge/dispatcher.py +++ b/judge/dispatcher.py @@ -14,6 +14,7 @@ from contest.models import ContestRuleType, ACMContestRank, OIContestRank, Conte from judge.languages import languages, spj_languages from options.options import SysOptions from problem.models import Problem, ProblemRuleType +from problem.utils import parse_problem_template from submission.models import JudgeStatus, Submission from utils.cache import cache from utils.constants import CacheKey @@ -123,16 +124,24 @@ class JudgeDispatcher(DispatcherBase): cache.lpush(CacheKey.waiting_queue, json.dumps(data)) return - sub_config = list(filter(lambda item: self.submission.language == item["name"], languages))[0] + language = self.submission.language + sub_config = list(filter(lambda item: language == item["name"], languages))[0] spj_config = {} if self.problem.spj_code: for lang in spj_languages: if lang["name"] == self.problem.spj_language: spj_config = lang["spj"] break + + if language in self.problem.template: + template = parse_problem_template(self.problem.template[language]) + code = f"{template['prepend']}\n{self.submission.code}\n{template['append']}" + else: + code = self.submission.code + data = { "language_config": sub_config["config"], - "src": self.submission.code, + "src": code, "max_cpu_time": self.problem.time_limit, "max_memory": 1024 * 1024 * self.problem.memory_limit, "test_case_id": self.problem.test_case_id, diff --git a/problem/serializers.py b/problem/serializers.py index 57a034ce..46b2e222 100644 --- a/problem/serializers.py +++ b/problem/serializers.py @@ -4,6 +4,7 @@ from judge.languages import language_names, spj_language_names from utils.api import DateTimeTZField, UsernameSerializer, serializers from .models import Problem, ProblemRuleType, ProblemTag +from .utils import parse_problem_template class TestCaseUploadForm(forms.Form): @@ -110,9 +111,18 @@ class ContestProblemAdminSerializer(BaseProblemSerializer): class ProblemSerializer(BaseProblemSerializer): + template = serializers.SerializerMethodField() + + def get_template(self, obj): + ret = {} + for lang, code in obj.template.items(): + ret[lang] = parse_problem_template(code)["template"] + return ret + class Meta: model = Problem - exclude = ("contest", "test_case_score", "test_case_id", "visible", "is_public") + exclude = ("contest", "test_case_score", "test_case_id", "visible", "is_public", + "template", "spj_code", "spj_version", "spj_compile_ok") class ContestProblemSerializer(BaseProblemSerializer): @@ -131,3 +141,54 @@ class ContestProblemSafeSerializer(BaseProblemSerializer): class ContestProblemMakePublicSerializer(serializers.Serializer): id = serializers.IntegerField() display_id = serializers.CharField(max_length=32) + + +class ExportProblemSerializer(serializers.ModelSerializer): + description = serializers.SerializerMethodField() + input_description = serializers.SerializerMethodField() + output_description = serializers.SerializerMethodField() + test_case_score = serializers.SerializerMethodField() + hint = serializers.SerializerMethodField() + time_limit = serializers.SerializerMethodField() + memory_limit = serializers.SerializerMethodField() + spj = serializers.SerializerMethodField() + template = serializers.SerializerMethodField() + + def get_description(self, obj): + return {"format": "html", "value": obj.description} + + def get_input_description(self, obj): + return {"format": "html", "value": obj.input_description} + + def get_output_description(self, obj): + return {"format": "html", "value": obj.output_description} + + def get_hint(self, obj): + return {"format": "html", "value": obj.hint} + + def get_test_case_score(self, obj): + return obj.test_case_score if obj.rule_type == ProblemRuleType.OI else [] + + def get_time_limit(self, obj): + return {"unit": "ms", "value": obj.time_limit} + + def get_memory_limit(self, obj): + return {"unit": "MB", "value": obj.memory_limit} + + def get_spj(self, obj): + return {"enabled": obj.spj, + "code": obj.spj_code if obj.spj else None, + "language": obj.spj_language if obj.spj else None} + + def get_template(self, obj): + ret = {} + for k, v in obj.template.items(): + ret[k] = parse_problem_template(v) + return ret + + class Meta: + model = Problem + fields = ("_id", "title", "description", + "input_description", "output_description", + "test_case_score", "hint", "time_limit", "memory_limit", "samples", + "template", "spj", "rule_type", "source", "template") diff --git a/problem/tests.py b/problem/tests.py index dbd01b7f..93cd0585 100644 --- a/problem/tests.py +++ b/problem/tests.py @@ -11,10 +11,13 @@ from utils.api.tests import APITestCase from .models import ProblemTag from .models import Problem, ProblemRuleType -from .views.admin import TestCaseAPI from contest.models import Contest from contest.tests import DEFAULT_CONTEST_DATA +from .views.admin import TestCaseAPI +from .utils import parse_problem_template + + DEFAULT_PROBLEM_DATA = {"_id": "A-110", "title": "test", "description": "

test

", "input_description": "test", "output_description": "test", "time_limit": 1000, "memory_limit": 256, "difficulty": "Low", "visible": True, "tags": ["test"], "languages": ["C", "C++", "Java", "Python2"], "template": {}, @@ -257,3 +260,44 @@ class ContestProblemTest(ProblemCreateTestBase): contest.save() resp = self.client.get(self.url + "?contest_id=" + str(self.contest["id"])) self.assertSuccess(resp) + + +class ParseProblemTemplateTest(APITestCase): + def test_parse(self): + template_str = """ +//PREPEND BEGIN +aaa +//PREPEND END + +//TEMPLATE BEGIN +bbb +//TEMPLATE END + +//APPEND BEGIN +ccc +//APPEND END +""" + + ret = parse_problem_template(template_str) + self.assertEqual(ret["prepend"], "aaa\n") + self.assertEqual(ret["template"], "bbb\n") + self.assertEqual(ret["append"], "ccc\n") + + def test_parse1(self): + template_str = """ +//PREPEND BEGIN +aaa +//PREPEND END + +//APPEND BEGIN +ccc +//APPEND END +//APPEND BEGIN +ddd +//APPEND END +""" + + ret = parse_problem_template(template_str) + self.assertEqual(ret["prepend"], "aaa\n") + self.assertEqual(ret["template"], "") + self.assertEqual(ret["append"], "ccc\n") diff --git a/problem/utils.py b/problem/utils.py new file mode 100644 index 00000000..f8243099 --- /dev/null +++ b/problem/utils.py @@ -0,0 +1,10 @@ +import re + + +def parse_problem_template(template_str): + prepend = re.findall("//PREPEND BEGIN\n([\s\S]+?)//PREPEND END", template_str) + template = re.findall("//TEMPLATE BEGIN\n([\s\S]+?)//TEMPLATE END", template_str) + append = re.findall("//APPEND BEGIN\n([\s\S]+?)//APPEND END", template_str) + return {"prepend": prepend[0] if prepend else "", + "template": template[0] if template else "", + "append": append[0] if append else ""}