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 account.models import User
from problem.models import AbstractProblem
from utils.models import RichTextField
@ -61,17 +60,6 @@ class Contest(models.Model):
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):
user = models.ForeignKey(User)
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 account.models import User
from contest.models import Contest
from utils.models import RichTextField
@ -66,3 +67,14 @@ class AbstractProblem(models.Model):
class Problem(AbstractProblem):
_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()
class CreateContestProblemSerializer(CreateOrEditProblemSerializer):
contest_id = serializers.IntegerField()
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = ProblemTag

View File

@ -1,8 +1,9 @@
from django.conf.urls import url
from ..views.admin import ProblemAPI, TestCaseUploadAPI
from ..views.admin import ProblemAPI, TestCaseUploadAPI, ContestProblemAPI
urlpatterns = [
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 account.decorators import problem_permission_required
from contest.models import Contest
from utils.api import APIView, CSRFExemptAPIView, validate_serializer
from utils.shortcuts import rand_str
from ..models import Problem, ProblemRuleType, ProblemTag
from ..models import Problem, ProblemRuleType, ProblemTag, ContestProblem
from ..serializers import (CreateProblemSerializer, EditProblemSerializer,
ProblemSerializer, TestCaseUploadForm)
ProblemSerializer, TestCaseUploadForm, CreateContestProblemSerializer)
class TestCaseUploadAPI(CSRFExemptAPIView):
@ -170,6 +171,9 @@ class ProblemAPI(APIView):
problems = Problem.objects.all().order_by("-create_time")
if not user.can_mgmt_all_problem():
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))
@validate_serializer(EditProblemSerializer)
@ -203,6 +207,7 @@ class ProblemAPI(APIView):
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:
@ -223,3 +228,81 @@ class ProblemAPI(APIView):
problem.tags.add(tag)
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))