将编译选项修改为数据库存储

This commit is contained in:
virusdefender 2019-01-05 14:00:59 +08:00
parent 2dc1d0cbce
commit a52f383930
8 changed files with 84 additions and 24 deletions

View File

@ -17,7 +17,6 @@ from account.decorators import super_admin_required
from account.models import User from account.models import User
from contest.models import Contest from contest.models import Contest
from judge.dispatcher import process_pending_task from judge.dispatcher import process_pending_task
from judge.languages import languages, spj_languages
from options.options import SysOptions from options.options import SysOptions
from problem.models import Problem from problem.models import Problem
from submission.models import Submission from submission.models import Submission
@ -166,7 +165,7 @@ class JudgeServerHeartbeatAPI(CSRFExemptAPIView):
class LanguagesAPI(APIView): class LanguagesAPI(APIView):
def get(self, request): def get(self, request):
return self.success({"languages": languages, "spj_languages": spj_languages}) return self.success({"languages": SysOptions.languages, "spj_languages": SysOptions.spj_languages})
class TestCasePruneAPI(APIView): class TestCasePruneAPI(APIView):

View File

@ -10,7 +10,6 @@ from django.db.models import F
from account.models import User from account.models import User
from conf.models import JudgeServer from conf.models import JudgeServer
from contest.models import ContestRuleType, ACMContestRank, OIContestRank, ContestStatus from contest.models import ContestRuleType, ACMContestRank, OIContestRank, ContestStatus
from judge.languages import languages, spj_languages
from options.options import SysOptions from options.options import SysOptions
from problem.models import Problem, ProblemRuleType from problem.models import Problem, ProblemRuleType
from problem.utils import parse_problem_template from problem.utils import parse_problem_template
@ -66,7 +65,7 @@ class DispatcherBase(object):
class SPJCompiler(DispatcherBase): class SPJCompiler(DispatcherBase):
def __init__(self, spj_code, spj_version, spj_language): def __init__(self, spj_code, spj_version, spj_language):
super().__init__() super().__init__()
spj_compile_config = list(filter(lambda config: spj_language == config["name"], spj_languages))[0]["spj"][ spj_compile_config = list(filter(lambda config: spj_language == config["name"], SysOptions.spj_languages))[0]["spj"][
"compile"] "compile"]
self.data = { self.data = {
"src": spj_code, "src": spj_code,
@ -126,10 +125,10 @@ class JudgeDispatcher(DispatcherBase):
return return
language = self.submission.language language = self.submission.language
sub_config = list(filter(lambda item: language == item["name"], languages))[0] sub_config = list(filter(lambda item: language == item["name"], SysOptions.languages))[0]
spj_config = {} spj_config = {}
if self.problem.spj_code: if self.problem.spj_code:
for lang in spj_languages: for lang in SysOptions.spj_languages:
if lang["name"] == self.problem.spj_language: if lang["name"] == self.problem.spj_language:
spj_config = lang["spj"] spj_config = lang["spj"]
break break

View File

@ -179,9 +179,3 @@ languages = [
{"config": _py2_lang_config, "name": "Python2", "description": "Python 2.7", "content_type": "text/x-python"}, {"config": _py2_lang_config, "name": "Python2", "description": "Python 2.7", "content_type": "text/x-python"},
{"config": _py3_lang_config, "name": "Python3", "description": "Python 3.5", "content_type": "text/x-python"}, {"config": _py3_lang_config, "name": "Python3", "description": "Python 3.5", "content_type": "text/x-python"},
] ]
spj_languages = list(filter(lambda item: "spj" in item, languages))
language_names = [item["name"] for item in languages]
spj_language_names = [item["name"] for item in spj_languages]

View File

@ -4,6 +4,7 @@ from django.db import transaction, IntegrityError
from utils.constants import CacheKey from utils.constants import CacheKey
from utils.shortcuts import rand_str from utils.shortcuts import rand_str
from judge.languages import languages
from .models import SysOptions as SysOptionsModel from .models import SysOptions as SysOptionsModel
@ -22,6 +23,7 @@ class OptionKeys:
smtp_config = "smtp_config" smtp_config = "smtp_config"
judge_server_token = "judge_server_token" judge_server_token = "judge_server_token"
throttling = "throttling" throttling = "throttling"
languages = "languages"
class OptionDefaultValue: class OptionDefaultValue:
@ -35,6 +37,7 @@ class OptionDefaultValue:
judge_server_token = default_token judge_server_token = default_token
throttling = {"ip": {"capacity": 100, "fill_rate": 0.1, "default_capacity": 50}, throttling = {"ip": {"capacity": 100, "fill_rate": 0.1, "default_capacity": 50},
"user": {"capacity": 20, "fill_rate": 0.03, "default_capacity": 10}} "user": {"capacity": 20, "fill_rate": 0.03, "default_capacity": 10}}
languages = languages
class _SysOptionsMeta(type): class _SysOptionsMeta(type):
@ -191,6 +194,29 @@ class _SysOptionsMeta(type):
def throttling(cls, value): def throttling(cls, value):
cls._set_option(OptionKeys.throttling, value) cls._set_option(OptionKeys.throttling, value)
@property
def languages(cls):
return cls._get_option(OptionKeys.languages)
@languages.setter
def languages(cls, value):
cls._set_option(OptionKeys.languages, value)
@property
def spj_languages(cls):
return [item for item in cls.languages if "spj" in item]
@property
def language_names(cls):
return [item["name"] for item in languages]
@property
def spj_language_names(cls):
return [item["name"] for item in cls.languages if "spj" in item]
def reset_languages(cls):
cls.languages = languages
class SysOptions(metaclass=_SysOptionsMeta): class SysOptions(metaclass=_SysOptionsMeta):
pass pass

View File

@ -1,9 +1,9 @@
from django import forms from django import forms
from options.options import SysOptions from options.options import SysOptions
from judge.languages import language_names, spj_language_names
from utils.api import UsernameSerializer, serializers from utils.api import UsernameSerializer, serializers
from utils.constants import Difficulty from utils.constants import Difficulty
from utils.serializers import LanguageNameMultiChoiceField, SPJLanguageNameChoiceField, LanguageNameChoiceField
from .models import Problem, ProblemRuleType, ProblemTag from .models import Problem, ProblemRuleType, ProblemTag
from .utils import parse_problem_template from .utils import parse_problem_template
@ -40,11 +40,11 @@ class CreateOrEditProblemSerializer(serializers.Serializer):
test_case_score = serializers.ListField(child=CreateTestCaseScoreSerializer(), allow_empty=True) test_case_score = serializers.ListField(child=CreateTestCaseScoreSerializer(), allow_empty=True)
time_limit = serializers.IntegerField(min_value=1, max_value=1000 * 60) time_limit = serializers.IntegerField(min_value=1, max_value=1000 * 60)
memory_limit = serializers.IntegerField(min_value=1, max_value=1024) memory_limit = serializers.IntegerField(min_value=1, max_value=1024)
languages = serializers.MultipleChoiceField(choices=language_names) languages = LanguageNameMultiChoiceField()
template = serializers.DictField(child=serializers.CharField(min_length=1)) template = serializers.DictField(child=serializers.CharField(min_length=1))
rule_type = serializers.ChoiceField(choices=[ProblemRuleType.ACM, ProblemRuleType.OI]) rule_type = serializers.ChoiceField(choices=[ProblemRuleType.ACM, ProblemRuleType.OI])
spj = serializers.BooleanField() spj = serializers.BooleanField()
spj_language = serializers.ChoiceField(choices=spj_language_names, allow_blank=True, allow_null=True) spj_language = SPJLanguageNameChoiceField(allow_blank=True, allow_null=True)
spj_code = serializers.CharField(allow_blank=True, allow_null=True) spj_code = serializers.CharField(allow_blank=True, allow_null=True)
spj_compile_ok = serializers.BooleanField(default=False) spj_compile_ok = serializers.BooleanField(default=False)
visible = serializers.BooleanField() visible = serializers.BooleanField()
@ -78,7 +78,7 @@ class TagSerializer(serializers.ModelSerializer):
class CompileSPJSerializer(serializers.Serializer): class CompileSPJSerializer(serializers.Serializer):
spj_language = serializers.ChoiceField(choices=spj_language_names) spj_language = SPJLanguageNameChoiceField()
spj_code = serializers.CharField() spj_code = serializers.CharField()
@ -212,12 +212,12 @@ class TemplateSerializer(serializers.Serializer):
class SPJSerializer(serializers.Serializer): class SPJSerializer(serializers.Serializer):
code = serializers.CharField() code = serializers.CharField()
language = serializers.ChoiceField(choices=spj_language_names) language = SPJLanguageNameChoiceField()
class AnswerSerializer(serializers.Serializer): class AnswerSerializer(serializers.Serializer):
code = serializers.CharField() code = serializers.CharField()
language = serializers.ChoiceField(choices=language_names) language = LanguageNameChoiceField()
class ImportProblemSerializer(serializers.Serializer): class ImportProblemSerializer(serializers.Serializer):

View File

@ -15,7 +15,7 @@ from account.decorators import problem_permission_required, ensure_created_by
from contest.models import Contest, ContestStatus from contest.models import Contest, ContestStatus
from fps.parser import FPSHelper, FPSParser from fps.parser import FPSHelper, FPSParser
from judge.dispatcher import SPJCompiler from judge.dispatcher import SPJCompiler
from judge.languages import language_names from options.options import SysOptions
from submission.models import Submission, JudgeStatus from submission.models import Submission, JudgeStatus
from utils.api import APIView, CSRFExemptAPIView, validate_serializer, APIError from utils.api import APIView, CSRFExemptAPIView, validate_serializer, APIError
from utils.constants import Difficulty from utils.constants import Difficulty
@ -578,7 +578,7 @@ class ImportProblemAPI(CSRFExemptAPIView, TestCaseZipProcessor):
else: else:
problem_info = serializer.data problem_info = serializer.data
for item in problem_info["template"].keys(): for item in problem_info["template"].keys():
if item not in language_names: if item not in SysOptions.language_names:
return self.error(f"Unsupported language {item}") return self.error(f"Unsupported language {item}")
problem_info["display_id"] = problem_info["display_id"][:24] problem_info["display_id"] = problem_info["display_id"][:24]
@ -613,7 +613,7 @@ class ImportProblemAPI(CSRFExemptAPIView, TestCaseZipProcessor):
spj_language=problem_info["spj"][ spj_language=problem_info["spj"][
"language"] if spj else None, "language"] if spj else None,
spj_version=rand_str(8) if spj else "", spj_version=rand_str(8) if spj else "",
languages=language_names, languages=SysOptions.language_names,
created_by=request.user, created_by=request.user,
visible=False, visible=False,
difficulty=Difficulty.MID, difficulty=Difficulty.MID,
@ -666,7 +666,7 @@ class FPSProblemImport(CSRFExemptAPIView):
spj_language=problem_data["spj"]["language"] if spj else None, spj_language=problem_data["spj"]["language"] if spj else None,
spj_version=rand_str(8) if spj else "", spj_version=rand_str(8) if spj else "",
visible=False, visible=False,
languages=language_names, languages=SysOptions.language_names,
created_by=creator, created_by=creator,
difficulty=Difficulty.MID, difficulty=Difficulty.MID,
test_case_id=problem_data["test_case_id"]) test_case_id=problem_data["test_case_id"])

View File

@ -1,11 +1,11 @@
from .models import Submission from .models import Submission
from utils.api import serializers from utils.api import serializers
from judge.languages import language_names from utils.serializers import LanguageNameChoiceField
class CreateSubmissionSerializer(serializers.Serializer): class CreateSubmissionSerializer(serializers.Serializer):
problem_id = serializers.IntegerField() problem_id = serializers.IntegerField()
language = serializers.ChoiceField(choices=language_names) language = LanguageNameChoiceField()
code = serializers.CharField(max_length=1024 * 1024) code = serializers.CharField(max_length=1024 * 1024)
contest_id = serializers.IntegerField(required=False) contest_id = serializers.IntegerField(required=False)
captcha = serializers.CharField(required=False) captcha = serializers.CharField(required=False)

42
utils/serializers.py Normal file
View File

@ -0,0 +1,42 @@
from rest_framework import serializers
from options.options import SysOptions
class InvalidLanguage(serializers.ValidationError):
def __init__(self, name):
super().__init__(detail=f"{name} is not a valid language")
class LanguageNameChoiceField(serializers.CharField):
def to_internal_value(self, data):
data = super().to_internal_value(data)
if data and data not in SysOptions.language_names:
raise InvalidLanguage(data)
return data
class SPJLanguageNameChoiceField(serializers.CharField):
def to_internal_value(self, data):
data = super().to_internal_value(data)
if data and data not in SysOptions.spj_language_names:
raise InvalidLanguage(data)
return data
class LanguageNameMultiChoiceField(serializers.ListField):
def to_internal_value(self, data):
data = super().to_internal_value(data)
for item in data:
if item not in SysOptions.language_names:
raise InvalidLanguage(item)
return data
class SPJLanguageNameMultiChoiceField(serializers.ListField):
def to_internal_value(self, data):
data = super().to_internal_value(data)
for item in data:
if item not in SysOptions.spj_language_names:
raise InvalidLanguage(item)
return data