OnlineJudge/problem/serializers.py

278 lines
10 KiB
Python

import re
from django import forms
from options.options import SysOptions
from utils.api import UsernameSerializer, serializers
from utils.constants import Difficulty
from utils.serializers import LanguageNameMultiChoiceField, SPJLanguageNameChoiceField, LanguageNameChoiceField
from .models import Problem, ProblemRuleType, ProblemTag, ProblemIOMode
from .utils import parse_problem_template
class TestCaseUploadForm(forms.Form):
spj = forms.CharField(max_length=12)
file = forms.FileField()
class CreateSampleSerializer(serializers.Serializer):
input = serializers.CharField(trim_whitespace=False)
output = serializers.CharField(trim_whitespace=False)
class CreateTestCaseScoreSerializer(serializers.Serializer):
input_name = serializers.CharField(max_length=32)
output_name = serializers.CharField(max_length=32)
score = serializers.IntegerField(min_value=0)
class CreateProblemCodeTemplateSerializer(serializers.Serializer):
pass
class ProblemIOModeSerializer(serializers.Serializer):
io_mode = serializers.ChoiceField(choices=ProblemIOMode.choices())
input = serializers.CharField()
output = serializers.CharField()
def validate(self, attrs):
if attrs["input"] == attrs["output"]:
raise serializers.ValidationError("Invalid io mode")
for item in (attrs["input"], attrs["output"]):
if not re.match("^[a-zA-Z0-9.]+$", item):
raise serializers.ValidationError("Invalid io file name format")
return attrs
class CreateOrEditProblemSerializer(serializers.Serializer):
_id = serializers.CharField(max_length=32, allow_blank=True, allow_null=True)
title = serializers.CharField(max_length=1024)
description = serializers.CharField()
input_description = serializers.CharField()
output_description = serializers.CharField()
samples = serializers.ListField(child=CreateSampleSerializer(), allow_empty=False)
test_case_id = serializers.CharField(max_length=32)
test_case_score = serializers.ListField(child=CreateTestCaseScoreSerializer(), allow_empty=True)
time_limit = serializers.IntegerField(min_value=1, max_value=1000 * 60)
memory_limit = serializers.IntegerField(min_value=1, max_value=1024)
languages = LanguageNameMultiChoiceField()
template = serializers.DictField(child=serializers.CharField(min_length=1))
rule_type = serializers.ChoiceField(choices=[ProblemRuleType.ACM, ProblemRuleType.OI])
io_mode = ProblemIOModeSerializer()
spj = serializers.BooleanField()
spj_language = SPJLanguageNameChoiceField(allow_blank=True, allow_null=True)
spj_code = serializers.CharField(allow_blank=True, allow_null=True)
spj_compile_ok = serializers.BooleanField(default=False)
visible = serializers.BooleanField()
difficulty = serializers.ChoiceField(choices=Difficulty.choices())
tags = serializers.ListField(child=serializers.CharField(max_length=32), allow_empty=False)
hint = serializers.CharField(allow_blank=True, allow_null=True)
source = serializers.CharField(max_length=256, allow_blank=True, allow_null=True)
share_submission = serializers.BooleanField()
class CreateProblemSerializer(CreateOrEditProblemSerializer):
pass
class EditProblemSerializer(CreateOrEditProblemSerializer):
id = serializers.IntegerField()
class CreateContestProblemSerializer(CreateOrEditProblemSerializer):
contest_id = serializers.IntegerField()
class EditContestProblemSerializer(CreateOrEditProblemSerializer):
id = serializers.IntegerField()
contest_id = serializers.IntegerField()
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = ProblemTag
fields = "__all__"
class CompileSPJSerializer(serializers.Serializer):
spj_language = SPJLanguageNameChoiceField()
spj_code = serializers.CharField()
class BaseProblemSerializer(serializers.ModelSerializer):
tags = serializers.SlugRelatedField(many=True, slug_field="name", read_only=True)
created_by = UsernameSerializer()
def get_public_template(self, obj):
ret = {}
for lang, code in obj.template.items():
ret[lang] = parse_problem_template(code)["template"]
return ret
class ProblemAdminSerializer(BaseProblemSerializer):
class Meta:
model = Problem
fields = "__all__"
class ProblemSerializer(BaseProblemSerializer):
template = serializers.SerializerMethodField("get_public_template")
class Meta:
model = Problem
exclude = ("test_case_score", "test_case_id", "visible", "is_public",
"spj_code", "spj_version", "spj_compile_ok")
class ProblemSafeSerializer(BaseProblemSerializer):
template = serializers.SerializerMethodField("get_public_template")
class Meta:
model = Problem
exclude = ("test_case_score", "test_case_id", "visible", "is_public",
"spj_code", "spj_version", "spj_compile_ok",
"difficulty", "submission_number", "accepted_number", "statistic_info")
class ContestProblemMakePublicSerializer(serializers.Serializer):
id = serializers.IntegerField()
display_id = serializers.CharField(max_length=32)
class ExportProblemSerializer(serializers.ModelSerializer):
display_id = serializers.SerializerMethodField()
description = serializers.SerializerMethodField()
input_description = serializers.SerializerMethodField()
output_description = serializers.SerializerMethodField()
test_case_score = serializers.SerializerMethodField()
hint = serializers.SerializerMethodField()
spj = serializers.SerializerMethodField()
template = serializers.SerializerMethodField()
source = serializers.SerializerMethodField()
tags = serializers.SlugRelatedField(many=True, slug_field="name", read_only=True)
def get_display_id(self, obj):
return obj._id
def _html_format_value(self, value):
return {"format": "html", "value": value}
def get_description(self, obj):
return self._html_format_value(obj.description)
def get_input_description(self, obj):
return self._html_format_value(obj.input_description)
def get_output_description(self, obj):
return self._html_format_value(obj.output_description)
def get_hint(self, obj):
return self._html_format_value(obj.hint)
def get_test_case_score(self, obj):
return [{"score": item["score"] if obj.rule_type == ProblemRuleType.OI else 100,
"input_name": item["input_name"], "output_name": item["output_name"]}
for item in obj.test_case_score]
def get_spj(self, obj):
return {"code": obj.spj_code,
"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
def get_source(self, obj):
return obj.source or f"{SysOptions.website_name} {SysOptions.website_base_url}"
class Meta:
model = Problem
fields = ("display_id", "title", "description", "tags",
"input_description", "output_description",
"test_case_score", "hint", "time_limit", "memory_limit", "samples",
"template", "spj", "rule_type", "source", "template")
class AddContestProblemSerializer(serializers.Serializer):
contest_id = serializers.IntegerField()
problem_id = serializers.IntegerField()
display_id = serializers.CharField()
class ExportProblemRequestSerialzier(serializers.Serializer):
problem_id = serializers.ListField(child=serializers.IntegerField(), allow_empty=False)
class UploadProblemForm(forms.Form):
file = forms.FileField()
class FormatValueSerializer(serializers.Serializer):
format = serializers.ChoiceField(choices=["html", "markdown"])
value = serializers.CharField(allow_blank=True)
class TestCaseScoreSerializer(serializers.Serializer):
score = serializers.IntegerField(min_value=1)
input_name = serializers.CharField(max_length=32)
output_name = serializers.CharField(max_length=32)
class TemplateSerializer(serializers.Serializer):
prepend = serializers.CharField()
template = serializers.CharField()
append = serializers.CharField()
class SPJSerializer(serializers.Serializer):
code = serializers.CharField()
language = SPJLanguageNameChoiceField()
class AnswerSerializer(serializers.Serializer):
code = serializers.CharField()
language = LanguageNameChoiceField()
class ImportProblemSerializer(serializers.Serializer):
display_id = serializers.CharField(max_length=128)
title = serializers.CharField(max_length=128)
description = FormatValueSerializer()
input_description = FormatValueSerializer()
output_description = FormatValueSerializer()
hint = FormatValueSerializer()
test_case_score = serializers.ListField(child=TestCaseScoreSerializer(), allow_null=True)
time_limit = serializers.IntegerField(min_value=1, max_value=60000)
memory_limit = serializers.IntegerField(min_value=1, max_value=10240)
samples = serializers.ListField(child=CreateSampleSerializer())
template = serializers.DictField(child=TemplateSerializer())
spj = SPJSerializer(allow_null=True)
rule_type = serializers.ChoiceField(choices=ProblemRuleType.choices())
source = serializers.CharField(max_length=200, allow_blank=True, allow_null=True)
answers = serializers.ListField(child=AnswerSerializer())
tags = serializers.ListField(child=serializers.CharField())
class FPSProblemSerializer(serializers.Serializer):
class UnitSerializer(serializers.Serializer):
unit = serializers.ChoiceField(choices=["MB", "s", "ms"])
value = serializers.IntegerField(min_value=1, max_value=60000)
title = serializers.CharField(max_length=128)
description = serializers.CharField()
input = serializers.CharField()
output = serializers.CharField()
hint = serializers.CharField(allow_blank=True, allow_null=True)
time_limit = UnitSerializer()
memory_limit = UnitSerializer()
samples = serializers.ListField(child=CreateSampleSerializer())
source = serializers.CharField(max_length=200, allow_blank=True, allow_null=True)
spj = SPJSerializer(allow_null=True)
template = serializers.ListField(child=serializers.DictField(), allow_empty=True, allow_null=True)
append = serializers.ListField(child=serializers.DictField(), allow_empty=True, allow_null=True)
prepend = serializers.ListField(child=serializers.DictField(), allow_empty=True, allow_null=True)