add create contest problem

This commit is contained in:
virusdefender
2017-02-17 20:14:03 +08:00
parent e87c567f55
commit 0fdaab7e88
7 changed files with 201 additions and 16 deletions

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-02-17 08:20
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('contest', '0002_auto_20170209_0845'),
]
operations = [
migrations.AlterUniqueTogether(
name='contestproblem',
unique_together=set([]),
),
migrations.RemoveField(
model_name='contestproblem',
name='contest',
),
migrations.RemoveField(
model_name='contestproblem',
name='created_by',
),
migrations.RemoveField(
model_name='contestproblem',
name='tags',
),
migrations.DeleteModel(
name='ContestProblem',
),
]

View File

@@ -3,7 +3,6 @@ from django.utils.timezone import now
from jsonfield import JSONField from jsonfield import JSONField
from account.models import User from account.models import User
from problem.models import AbstractProblem
from utils.models import RichTextField from utils.models import RichTextField
@@ -61,17 +60,6 @@ class Contest(models.Model):
db_table = "contest" db_table = "contest"
class ContestProblem(AbstractProblem):
_id = models.CharField(max_length=24, db_index=True)
contest = models.ForeignKey(Contest)
# 是否已经公开了题目,防止重复公开
is_public = models.BooleanField(default=False)
class Meta:
db_table = "contest_problem"
unique_together = (("_id", "contest"), )
class ContestRank(models.Model): class ContestRank(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
contest = models.ForeignKey(Contest) contest = models.ForeignKey(Contest)

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-02-17 08:20
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import jsonfield.fields
import utils.models
class Migration(migrations.Migration):
dependencies = [
('contest', '0003_auto_20170217_0820'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('problem', '0002_problem__id'),
]
operations = [
migrations.CreateModel(
name='ContestProblem',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=128)),
('description', utils.models.RichTextField()),
('input_description', utils.models.RichTextField()),
('output_description', utils.models.RichTextField()),
('samples', jsonfield.fields.JSONField()),
('test_case_id', models.CharField(max_length=32)),
('test_case_score', jsonfield.fields.JSONField()),
('hint', utils.models.RichTextField(blank=True, null=True)),
('languages', jsonfield.fields.JSONField()),
('template', jsonfield.fields.JSONField()),
('create_time', models.DateTimeField(auto_now_add=True)),
('last_update_time', models.DateTimeField(blank=True, null=True)),
('time_limit', models.IntegerField()),
('memory_limit', models.IntegerField()),
('spj', models.BooleanField(default=False)),
('spj_language', models.CharField(blank=True, max_length=32, null=True)),
('spj_code', models.TextField(blank=True, null=True)),
('spj_version', models.CharField(blank=True, max_length=32, null=True)),
('rule_type', models.CharField(max_length=32)),
('visible', models.BooleanField(default=True)),
('difficulty', models.CharField(max_length=32)),
('source', models.CharField(blank=True, max_length=200, null=True)),
('total_submit_number', models.IntegerField(default=0)),
('total_accepted_number', models.IntegerField(default=0)),
('_id', models.CharField(db_index=True, max_length=24)),
('is_public', models.BooleanField(default=False)),
('contest', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contest.Contest')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('tags', models.ManyToManyField(to='problem.ProblemTag')),
],
options={
'db_table': 'contest_problem',
},
),
migrations.AlterUniqueTogether(
name='contestproblem',
unique_together=set([('_id', 'contest')]),
),
]

View File

@@ -2,6 +2,7 @@ from django.db import models
from jsonfield import JSONField from jsonfield import JSONField
from account.models import User from account.models import User
from contest.models import Contest
from utils.models import RichTextField from utils.models import RichTextField
@@ -66,3 +67,14 @@ class AbstractProblem(models.Model):
class Problem(AbstractProblem): class Problem(AbstractProblem):
_id = models.CharField(max_length=24, unique=True, db_index=True) _id = models.CharField(max_length=24, unique=True, db_index=True)
class ContestProblem(AbstractProblem):
_id = models.CharField(max_length=24, db_index=True)
contest = models.ForeignKey(Contest)
# 是否已经公开了题目,防止重复公开
is_public = models.BooleanField(default=False)
class Meta:
db_table = "contest_problem"
unique_together = (("_id", "contest"), )

View File

@@ -64,6 +64,10 @@ class EditProblemSerializer(CreateOrEditProblemSerializer):
id = serializers.IntegerField() id = serializers.IntegerField()
class CreateContestProblemSerializer(CreateOrEditProblemSerializer):
contest_id = serializers.IntegerField()
class TagSerializer(serializers.ModelSerializer): class TagSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = ProblemTag model = ProblemTag

View File

@@ -1,8 +1,9 @@
from django.conf.urls import url from django.conf.urls import url
from ..views.admin import ProblemAPI, TestCaseUploadAPI from ..views.admin import ProblemAPI, TestCaseUploadAPI, ContestProblemAPI
urlpatterns = [ urlpatterns = [
url(r"^test_case/upload$", TestCaseUploadAPI.as_view(), name="test_case_upload_api"), url(r"^test_case/upload$", TestCaseUploadAPI.as_view(), name="test_case_upload_api"),
url(r"^problem$", ProblemAPI.as_view(), name="problem_api") url(r"^problem$", ProblemAPI.as_view(), name="problem_api"),
url(r'contest/problem$', ContestProblemAPI.as_view(), name="contest_problem_api")
] ]

View File

@@ -6,12 +6,13 @@ import zipfile
from django.conf import settings from django.conf import settings
from account.decorators import problem_permission_required from account.decorators import problem_permission_required
from contest.models import Contest
from utils.api import APIView, CSRFExemptAPIView, validate_serializer from utils.api import APIView, CSRFExemptAPIView, validate_serializer
from utils.shortcuts import rand_str from utils.shortcuts import rand_str
from ..models import Problem, ProblemRuleType, ProblemTag from ..models import Problem, ProblemRuleType, ProblemTag, ContestProblem
from ..serializers import (CreateProblemSerializer, EditProblemSerializer, from ..serializers import (CreateProblemSerializer, EditProblemSerializer,
ProblemSerializer, TestCaseUploadForm) ProblemSerializer, TestCaseUploadForm, CreateContestProblemSerializer)
class TestCaseUploadAPI(CSRFExemptAPIView): class TestCaseUploadAPI(CSRFExemptAPIView):
@@ -170,6 +171,9 @@ class ProblemAPI(APIView):
problems = Problem.objects.all().order_by("-create_time") problems = Problem.objects.all().order_by("-create_time")
if not user.can_mgmt_all_problem(): if not user.can_mgmt_all_problem():
problems = problems.filter(created_by=request.user) problems = problems.filter(created_by=request.user)
keyword = request.GET.get("keyword")
if keyword:
problems = problems.filter(title__contains=keyword)
return self.success(self.paginate_data(request, problems, ProblemSerializer)) return self.success(self.paginate_data(request, problems, ProblemSerializer))
@validate_serializer(EditProblemSerializer) @validate_serializer(EditProblemSerializer)
@@ -203,6 +207,7 @@ class ProblemAPI(APIView):
else: else:
data["spj_language"] = None data["spj_language"] = None
data["spj_code"] = None data["spj_code"] = None
if data["rule_type"] == ProblemRuleType.OI: if data["rule_type"] == ProblemRuleType.OI:
for item in data["test_case_score"]: for item in data["test_case_score"]:
if item["score"] <= 0: if item["score"] <= 0:
@@ -223,3 +228,81 @@ class ProblemAPI(APIView):
problem.tags.add(tag) problem.tags.add(tag)
return self.success() return self.success()
class ContestProblemAPI(APIView):
@validate_serializer(CreateContestProblemSerializer)
def post(self, request):
data = request.data
try:
contest = Contest.objects.get(id=data.pop("contest_id"))
if request.user.is_admin() and contest.created_by != request.user:
return self.error("Contest does not exist")
except Contest.DoesNotExist:
return self.error("Contest does not exist")
if data["rule_type"] != contest.rule_type:
return self.error("Invalid rule type")
_id = data["_id"]
if not _id:
return self.error("Display id is required for contest problem")
try:
ContestProblem.objects.get(_id=_id, contest=contest)
return self.error("Duplicate Display id")
except ContestProblem.DoesNotExist:
pass
if data["spj"]:
if not data["spj_language"] or not data["spj_code"]:
return self.error("Invalid spj")
data["spj_version"] = hashlib.md5((data["spj_language"] + ":" + data["spj_code"]).encode("utf-8")).hexdigest()
else:
data["spj_language"] = None
data["spj_code"] = None
if data["rule_type"] == ProblemRuleType.OI:
for item in data["test_case_score"]:
if item["score"] <= 0:
return self.error("Invalid score")
# todo check filename and score info
data["created_by"] = request.user
data["contest"] = contest
tags = data.pop("tags")
data["languages"] = list(data["languages"])
problem = ContestProblem.objects.create(**data)
for item in tags:
try:
tag = ProblemTag.objects.get(name=item)
except ProblemTag.DoesNotExist:
tag = ProblemTag.objects.create(name=item)
problem.tags.add(tag)
return self.success(ProblemSerializer(problem).data)
def get(self, request):
problem_id = request.GET.get("id")
contest_id = request.GET.get("contest_id")
user = request.user
if problem_id:
try:
problem = ContestProblem.objects.get(id=problem_id)
if request.user.is_admin() and problem.contest.created_by != user:
return self.error("Problem does not exist")
except ContestProblem.DoesNotExist:
return self.error("Problem does not exist")
return self.success(ProblemSerializer(problem).data)
if not contest_id:
return self.error("Contest id is required")
problems = ContestProblem.objects.filter(contest_id=contest_id).order_by("-create_time")
if user.is_admin():
problems = problems.filter(contest__created_by=user)
keyword = request.GET.get("keyword")
if keyword:
problems = problems.filter(title__contains=keyword)
return self.success(self.paginate_data(request, problems, ProblemSerializer))