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)