merge problem and contest_problem

This commit is contained in:
zema1
2017-09-24 09:48:17 +08:00
parent e9c7344815
commit 51c229a2c5
13 changed files with 263 additions and 97 deletions

View File

@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-09-23 13:18
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('contest', '0005_auto_20170823_0918'),
('problem', '0006_auto_20170823_0918'),
]
operations = [
migrations.AddField(
model_name='contestproblem',
name='total_score',
field=models.IntegerField(blank=True, default=0),
),
migrations.AddField(
model_name='problem',
name='total_score',
field=models.IntegerField(blank=True, default=0),
),
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.AddField(
model_name='problem',
name='contest',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contest.Contest'),
preserve_default=False,
),
migrations.AddField(
model_name='problem',
name='is_public',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='problem',
name='_id',
field=models.CharField(db_index=True, max_length=24),
),
migrations.AlterUniqueTogether(
name='problem',
unique_together=set([('_id', 'contest')]),
),
migrations.DeleteModel(
name='ContestProblem',
),
]

View File

@@ -24,7 +24,12 @@ class ProblemDifficulty(object):
Low = "Low"
class AbstractProblem(models.Model):
class Problem(models.Model):
# display ID
_id = models.CharField(max_length=24, db_index=True)
contest = models.ForeignKey(Contest, null=True, blank=True)
# for contest problem
is_public = models.BooleanField(default=False)
title = models.CharField(max_length=128)
# HTML
description = RichTextField()
@@ -33,6 +38,7 @@ class AbstractProblem(models.Model):
# [{input: "test", output: "123"}, {input: "test123", output: "456"}]
samples = JSONField()
test_case_id = models.CharField(max_length=32)
# [{"input_name": "1.in", "output_name": "1.out", "score": 0}]
test_case_score = JSONField()
hint = RichTextField(blank=True, null=True)
languages = JSONField()
@@ -55,6 +61,8 @@ class AbstractProblem(models.Model):
difficulty = models.CharField(max_length=32)
tags = models.ManyToManyField(ProblemTag)
source = models.CharField(max_length=200, blank=True, null=True)
# for OI mode
total_score = models.IntegerField(default=0, blank=True)
submission_number = models.BigIntegerField(default=0)
accepted_number = models.BigIntegerField(default=0)
# ACM rule_type: {JudgeStatus.ACCEPTED: 3, JudgeStaus.WRONG_ANSWER: 11}, the number means count
@@ -62,7 +70,7 @@ class AbstractProblem(models.Model):
class Meta:
db_table = "problem"
abstract = True
unique_together = (("_id", "contest"),)
def add_submission_number(self):
self.submission_number = models.F("submission_number") + 1
@@ -71,18 +79,3 @@ class AbstractProblem(models.Model):
def add_ac_number(self):
self.accepted_number = models.F("accepted_number") + 1
self.save(update_fields=["accepted_number"])
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

@@ -4,7 +4,6 @@ from judge.languages import language_names, spj_language_names
from utils.api import DateTimeTZField, UsernameSerializer, serializers
from .models import Problem, ProblemRuleType, ProblemTag
from .models import ContestProblem
class TestCaseUploadForm(forms.Form):
@@ -93,16 +92,16 @@ class ProblemAdminSerializer(BaseProblemSerializer):
class ContestProblemAdminSerializer(BaseProblemSerializer):
class Meta:
model = ContestProblem
model = Problem
class ProblemSerializer(BaseProblemSerializer):
class Meta:
model = Problem
exclude = ("test_case_score", "test_case_id", "visible")
exclude = ("contest", "test_case_score", "test_case_id", "visible", "is_public")
class ContestProblemSerializer(BaseProblemSerializer):
class Meta:
model = ContestProblem
model = Problem
exclude = ("test_case_score", "test_case_id", "visible", "is_public")

View File

@@ -10,11 +10,10 @@ from contest.models import Contest
from utils.api import APIView, CSRFExemptAPIView, validate_serializer
from utils.shortcuts import rand_str
from ..models import ContestProblem, Problem, ProblemRuleType, ProblemTag
from ..serializers import (CreateContestProblemSerializer,
from ..models import Problem, ProblemRuleType, ProblemTag
from ..serializers import (CreateContestProblemSerializer, ContestProblemAdminSerializer,
CreateProblemSerializer, EditProblemSerializer,
ProblemAdminSerializer, TestCaseUploadForm,
ContestProblemAdminSerializer)
ProblemAdminSerializer, TestCaseUploadForm)
class TestCaseUploadAPI(CSRFExemptAPIView):
@@ -134,9 +133,13 @@ class ProblemAPI(APIView):
data["spj_language"] = None
data["spj_code"] = None
if data["rule_type"] == ProblemRuleType.OI:
total_score = 0
for item in data["test_case_score"]:
if item["score"] <= 0:
return self.error("Invalid score")
else:
total_score += item["score"]
data["total_score"] = total_score
# todo check filename and score info
data["created_by"] = request.user
tags = data.pop("tags")
@@ -211,9 +214,13 @@ class ProblemAPI(APIView):
data["spj_code"] = None
if data["rule_type"] == ProblemRuleType.OI:
total_score = 0
for item in data["test_case_score"]:
if item["score"] <= 0:
return self.error("Invalid score")
else:
total_score += item["score"]
data["total_score"] = total_score
# todo check filename and score info
tags = data.pop("tags")
@@ -250,11 +257,9 @@ class ContestProblemAPI(APIView):
_id = data["_id"]
if not _id:
return self.error("Display id is required for contest problem")
try:
ContestProblem.objects.get(_id=_id, contest=contest)
if Problem.objects.filter(_id=_id, contest=contest).exists():
return self.error("Duplicate Display id")
except ContestProblem.DoesNotExist:
pass
if data["spj"]:
if not data["spj_language"] or not data["spj_code"]:
@@ -275,7 +280,7 @@ class ContestProblemAPI(APIView):
tags = data.pop("tags")
data["languages"] = list(data["languages"])
problem = ContestProblem.objects.create(**data)
problem = Problem.objects.create(**data)
for item in tags:
try:
@@ -291,17 +296,17 @@ class ContestProblemAPI(APIView):
user = request.user
if problem_id:
try:
problem = ContestProblem.objects.get(id=problem_id)
problem = Problem.objects.get(id=problem_id)
if user.is_admin() and problem.contest.created_by != user:
return self.error("Problem does not exist")
except ContestProblem.DoesNotExist:
except Problem.DoesNotExist:
return self.error("Problem does not exist")
return self.success(ProblemAdminSerializer(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")
problems = Problem.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")

View File

@@ -1,7 +1,7 @@
from django.db.models import Q
from utils.api import APIView
from account.decorators import check_contest_permission
from ..models import ProblemTag, Problem, ContestProblem, ProblemRuleType
from ..models import ProblemTag, Problem, ProblemRuleType
from ..serializers import ProblemSerializer, TagSerializer
from ..serializers import ContestProblemSerializer
from contest.models import ContestRuleType
@@ -66,14 +66,14 @@ class ContestProblemAPI(APIView):
problem_id = request.GET.get("problem_id")
if problem_id:
try:
problem = ContestProblem.objects.select_related("created_by").get(_id=problem_id, contest=self.contest,
visible=True)
except ContestProblem.DoesNotExist:
problem = Problem.objects.select_related("created_by").get(_id=problem_id,
contest=self.contest,
visible=True)
except Problem.DoesNotExist:
return self.error("Problem does not exist.")
return self.success(ContestProblemSerializer(problem).data)
contest_problems = ContestProblem.objects.select_related("created_by").filter(contest=self.contest,
visible=True)
contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True)
# 根据profile 为做过的题目添加标记
data = ContestProblemSerializer(contest_problems, many=True).data
if request.user.id: