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

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 contest.models import Contest
from judge.dispatcher import process_pending_task
from judge.languages import languages, spj_languages
from options.options import SysOptions
from problem.models import Problem
from submission.models import Submission
@ -166,7 +165,7 @@ class JudgeServerHeartbeatAPI(CSRFExemptAPIView):
class LanguagesAPI(APIView):
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):

View File

@ -10,7 +10,6 @@ from django.db.models import F
from account.models import User
from conf.models import JudgeServer
from contest.models import ContestRuleType, ACMContestRank, OIContestRank, ContestStatus
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
@ -66,7 +65,7 @@ class DispatcherBase(object):
class SPJCompiler(DispatcherBase):
def __init__(self, spj_code, spj_version, spj_language):
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"]
self.data = {
"src": spj_code,
@ -126,10 +125,10 @@ class JudgeDispatcher(DispatcherBase):
return
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 = {}
if self.problem.spj_code:
for lang in spj_languages:
for lang in SysOptions.spj_languages:
if lang["name"] == self.problem.spj_language:
spj_config = lang["spj"]
break

View File

@ -179,9 +179,3 @@ languages = [
{"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"},
]
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.shortcuts import rand_str
from judge.languages import languages
from .models import SysOptions as SysOptionsModel
@ -22,6 +23,7 @@ class OptionKeys:
smtp_config = "smtp_config"
judge_server_token = "judge_server_token"
throttling = "throttling"
languages = "languages"
class OptionDefaultValue:
@ -35,6 +37,7 @@ class OptionDefaultValue:
judge_server_token = default_token
throttling = {"ip": {"capacity": 100, "fill_rate": 0.1, "default_capacity": 50},
"user": {"capacity": 20, "fill_rate": 0.03, "default_capacity": 10}}
languages = languages
class _SysOptionsMeta(type):
@ -191,6 +194,29 @@ class _SysOptionsMeta(type):
def throttling(cls, 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):
pass

View File

@ -1,9 +1,9 @@
from django import forms
from options.options import SysOptions
from judge.languages import language_names, spj_language_names
from utils.api import UsernameSerializer, serializers
from utils.constants import Difficulty
from utils.serializers import LanguageNameMultiChoiceField, SPJLanguageNameChoiceField, LanguageNameChoiceField
from .models import Problem, ProblemRuleType, ProblemTag
from .utils import parse_problem_template
@ -40,11 +40,11 @@ class CreateOrEditProblemSerializer(serializers.Serializer):
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 = serializers.MultipleChoiceField(choices=language_names)
languages = LanguageNameMultiChoiceField()
template = serializers.DictField(child=serializers.CharField(min_length=1))
rule_type = serializers.ChoiceField(choices=[ProblemRuleType.ACM, ProblemRuleType.OI])
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_compile_ok = serializers.BooleanField(default=False)
visible = serializers.BooleanField()
@ -78,7 +78,7 @@ class TagSerializer(serializers.ModelSerializer):
class CompileSPJSerializer(serializers.Serializer):
spj_language = serializers.ChoiceField(choices=spj_language_names)
spj_language = SPJLanguageNameChoiceField()
spj_code = serializers.CharField()
@ -212,12 +212,12 @@ class TemplateSerializer(serializers.Serializer):
class SPJSerializer(serializers.Serializer):
code = serializers.CharField()
language = serializers.ChoiceField(choices=spj_language_names)
language = SPJLanguageNameChoiceField()
class AnswerSerializer(serializers.Serializer):
code = serializers.CharField()
language = serializers.ChoiceField(choices=language_names)
language = LanguageNameChoiceField()
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 fps.parser import FPSHelper, FPSParser
from judge.dispatcher import SPJCompiler
from judge.languages import language_names
from options.options import SysOptions
from submission.models import Submission, JudgeStatus
from utils.api import APIView, CSRFExemptAPIView, validate_serializer, APIError
from utils.constants import Difficulty
@ -578,7 +578,7 @@ class ImportProblemAPI(CSRFExemptAPIView, TestCaseZipProcessor):
else:
problem_info = serializer.data
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}")
problem_info["display_id"] = problem_info["display_id"][:24]
@ -613,7 +613,7 @@ class ImportProblemAPI(CSRFExemptAPIView, TestCaseZipProcessor):
spj_language=problem_info["spj"][
"language"] if spj else None,
spj_version=rand_str(8) if spj else "",
languages=language_names,
languages=SysOptions.language_names,
created_by=request.user,
visible=False,
difficulty=Difficulty.MID,
@ -666,7 +666,7 @@ class FPSProblemImport(CSRFExemptAPIView):
spj_language=problem_data["spj"]["language"] if spj else None,
spj_version=rand_str(8) if spj else "",
visible=False,
languages=language_names,
languages=SysOptions.language_names,
created_by=creator,
difficulty=Difficulty.MID,
test_case_id=problem_data["test_case_id"])

View File

@ -1,11 +1,11 @@
from .models import Submission
from utils.api import serializers
from judge.languages import language_names
from utils.serializers import LanguageNameChoiceField
class CreateSubmissionSerializer(serializers.Serializer):
problem_id = serializers.IntegerField()
language = serializers.ChoiceField(choices=language_names)
language = LanguageNameChoiceField()
code = serializers.CharField(max_length=1024 * 1024)
contest_id = serializers.IntegerField(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