支持选取已有题目作为比赛题目

This commit is contained in:
zema1 2017-12-03 18:52:32 +08:00
parent 4c2db34b9d
commit 0f9f34df65
7 changed files with 75 additions and 8 deletions

View File

@ -73,7 +73,7 @@ def check_contest_permission(check_type="details"):
else:
contest_id = request.GET.get("contest_id")
if not contest_id:
return self.error("Parameter contest_id doesn't exist.")
return self.error("Parameter error, contest_id is required")
try:
# use self.contest to avoid query contest again in view.

View File

@ -10,7 +10,7 @@ from ..models import Contest, ContestAnnouncement, ACMContestRank
from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer,
CreateConetestSeriaizer, CreateContestAnnouncementSerializer,
EditConetestSeriaizer, EditContestAnnouncementSerializer,
ACMContesHelperSerializer)
ACMContesHelperSerializer, )
class ContestAPI(APIView):

View File

@ -4,6 +4,7 @@ from utils.models import JSONField
from account.models import User
from contest.models import Contest
from utils.models import RichTextField
from utils.constants import Choices
class ProblemTag(models.Model):
@ -13,7 +14,7 @@ class ProblemTag(models.Model):
db_table = "problem_tag"
class ProblemRuleType(object):
class ProblemRuleType(Choices):
ACM = "ACM"
OI = "OI"

View File

@ -174,3 +174,9 @@ class ExportProblemSerializer(serializers.ModelSerializer):
"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()

View File

@ -17,7 +17,6 @@ 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": "<p>test</p>", "input_description": "test",
"output_description": "test", "time_limit": 1000, "memory_limit": 256, "difficulty": "Low",
"visible": True, "tags": ["test"], "languages": ["C", "C++", "Java", "Python2"], "template": {},
@ -259,6 +258,29 @@ class ContestProblemTest(ProblemCreateTestBase):
self.assertSuccess(resp)
class AddProblemFromPublicProblemAPITest(ProblemCreateTestBase):
def setUp(self):
admin = self.create_admin()
url = self.reverse("contest_admin_api")
contest_data = copy.deepcopy(DEFAULT_CONTEST_DATA)
contest_data["password"] = ""
contest_data["start_time"] = contest_data["start_time"] + timedelta(hours=1)
self.contest = self.client.post(url, data=contest_data).data["data"]
self.problem = self.add_problem(DEFAULT_PROBLEM_DATA, admin)
self.url = self.reverse("add_contest_problem_from_public_api")
self.data = {
"display_id": "1000",
"contest_id": self.contest["id"],
"problem_id": self.problem.id
}
def test_add_contest_problem(self):
resp = self.client.post(self.url, data=self.data)
self.assertSuccess(resp)
self.assertTrue(Problem.objects.all().exists())
self.assertTrue(Problem.objects.filter(contest_id=self.contest["id"]).exists())
class ParseProblemTemplateTest(APITestCase):
def test_parse(self):
template_str = """

View File

@ -1,7 +1,7 @@
from django.conf.urls import url
from ..views.admin import ContestProblemAPI, ProblemAPI, TestCaseAPI, MakeContestProblemPublicAPIView
from ..views.admin import CompileSPJAPI
from ..views.admin import CompileSPJAPI, AddContestProblemAPI
urlpatterns = [
url(r"^test_case/?$", TestCaseAPI.as_view(), name="test_case_api"),
@ -9,4 +9,5 @@ urlpatterns = [
url(r"^problem/?$", ProblemAPI.as_view(), name="problem_admin_api"),
url(r"^contest/problem/?$", ContestProblemAPI.as_view(), name="contest_problem_admin_api"),
url(r"^contest_problem/make_public/?$", MakeContestProblemPublicAPIView.as_view(), name="make_public_api"),
url(r"^contest/add_problem_from_public/?$", AddContestProblemAPI.as_view(), name="add_contest_problem_from_public_api"),
]

View File

@ -10,7 +10,7 @@ from django.http import StreamingHttpResponse, HttpResponse
from account.decorators import problem_permission_required
from judge.dispatcher import SPJCompiler
from contest.models import Contest
from contest.models import Contest, ContestStatus
from submission.models import Submission
from utils.api import APIView, CSRFExemptAPIView, validate_serializer
from utils.shortcuts import rand_str, natural_sort_key
@ -18,7 +18,8 @@ from utils.shortcuts import rand_str, natural_sort_key
from ..models import Problem, ProblemRuleType, ProblemTag
from ..serializers import (CreateContestProblemSerializer, CompileSPJSerializer,
CreateProblemSerializer, EditProblemSerializer, EditContestProblemSerializer,
ProblemAdminSerializer, TestCaseUploadForm, ContestProblemMakePublicSerializer)
ProblemAdminSerializer, TestCaseUploadForm, ContestProblemMakePublicSerializer,
AddContestProblemSerializer)
class TestCaseAPI(CSRFExemptAPIView):
@ -71,7 +72,8 @@ class TestCaseAPI(CSRFExemptAPIView):
response = HttpResponse()
response["X-Accel-Redirect"] = file_name
else:
response = StreamingHttpResponse(FileWrapper(open(file_name, "rb")), content_type="application/octet-stream")
response = StreamingHttpResponse(FileWrapper(open(file_name, "rb")),
content_type="application/octet-stream")
response["Content-Disposition"] = f"attachment; filename=problem_{problem.id}_test_cases.zip"
response["Content-Length"] = os.path.getsize(file_name)
@ -229,6 +231,7 @@ class ProblemAPI(ProblemBase):
@problem_permission_required
def get(self, request):
problem_id = request.GET.get("id")
rule_type = request.GET.get("rule_type")
user = request.user
if problem_id:
try:
@ -240,6 +243,12 @@ class ProblemAPI(ProblemBase):
return self.error("Problem does not exist")
problems = Problem.objects.filter(contest_id__isnull=True).order_by("-create_time")
if rule_type:
if rule_type not in ProblemRuleType.choices():
return self.error("Invalid rule_type")
else:
problems = problems.filter(rule_type=rule_type)
if not user.can_mgmt_all_problem():
problems = problems.filter(created_by=user)
keyword = request.GET.get("keyword")
@ -433,3 +442,31 @@ class MakeContestProblemPublicAPIView(APIView):
problem.save()
problem.tags.set(tags)
return self.success()
class AddContestProblemAPI(APIView):
@validate_serializer(AddContestProblemSerializer)
def post(self, request):
data = request.data
try:
contest = Contest.objects.get(id=data["contest_id"])
problem = Problem.objects.get(id=data["problem_id"])
except (Contest.DoesNotExist, Problem.DoesNotExist):
return self.error("Contest or Problem does not exist")
if contest.status == ContestStatus.CONTEST_ENDED:
return self.error("Contest has ended")
if Problem.objects.filter(contest=contest, _id=data["display_id"]).exists():
return self.error("Duplicate display id in this contest")
tags = problem.tags.all()
problem.pk = None
problem.contest = contest
problem.is_public = True
problem.visible = True
problem._id = request.data["display_id"]
problem.submission_number = problem.accepted_number = 0
problem.statistic_info = {}
problem.save()
problem.tags.set(tags)
return self.success()