mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 00:13:18 +00:00
add create problem api
This commit is contained in:
parent
ffc85e9587
commit
8ce6040a5b
82
contest/migrations/0003_auto_20170202_0826.py
Normal file
82
contest/migrations/0003_auto_20170202_0826.py
Normal file
@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.12 on 2017-02-02 08:26
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import jsonfield.fields
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('problem', '0002_auto_20170202_0826'),
|
||||
('contest', '0002_contestannouncement_created_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='contestproblem',
|
||||
name='difficulty',
|
||||
field=models.CharField(default='LOW', max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contestproblem',
|
||||
name='languages',
|
||||
field=jsonfield.fields.JSONField(default=[]),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contestproblem',
|
||||
name='rule_type',
|
||||
field=models.CharField(default='ACM', max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contestproblem',
|
||||
name='source',
|
||||
field=models.CharField(blank=True, max_length=200, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contestproblem',
|
||||
name='tags',
|
||||
field=models.ManyToManyField(to='problem.ProblemTag'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contestproblem',
|
||||
name='test_case_score',
|
||||
field=jsonfield.fields.JSONField(default={}),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contestproblem',
|
||||
name='input_description',
|
||||
field=utils.models.RichTextField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contestproblem',
|
||||
name='output_description',
|
||||
field=utils.models.RichTextField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contestproblem',
|
||||
name='samples',
|
||||
field=jsonfield.fields.JSONField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contestproblem',
|
||||
name='spj_language',
|
||||
field=models.CharField(blank=True, max_length=32, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contestproblem',
|
||||
name='test_case_id',
|
||||
field=models.CharField(max_length=32),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contestproblem',
|
||||
name='title',
|
||||
field=models.CharField(max_length=128),
|
||||
),
|
||||
]
|
@ -89,7 +89,7 @@ _py2_lang_config = {
|
||||
},
|
||||
"run": {
|
||||
"command": "/usr/bin/python {exe_path}",
|
||||
"seccomp_rule": None,
|
||||
"seccomp_rule": "general",
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,3 +103,7 @@ languages = [
|
||||
]
|
||||
|
||||
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]
|
||||
|
78
problem/migrations/0001_initial.py
Normal file
78
problem/migrations/0001_initial.py
Normal file
@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.12 on 2017-01-31 09:35
|
||||
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):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Problem',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=50)),
|
||||
('description', utils.models.RichTextField()),
|
||||
('input_description', models.CharField(max_length=10000)),
|
||||
('output_description', models.CharField(max_length=10000)),
|
||||
('samples', models.TextField(blank=True)),
|
||||
('test_case_id', models.CharField(max_length=40)),
|
||||
('hint', utils.models.RichTextField(blank=True, null=True)),
|
||||
('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.IntegerField(blank=True, null=True)),
|
||||
('spj_code', models.TextField(blank=True, null=True)),
|
||||
('spj_version', models.CharField(blank=True, max_length=32, null=True)),
|
||||
('visible', models.BooleanField(default=True)),
|
||||
('total_submit_number', models.IntegerField(default=0)),
|
||||
('total_accepted_number', models.IntegerField(default=0)),
|
||||
('difficulty', models.IntegerField()),
|
||||
('source', models.CharField(blank=True, max_length=200, null=True)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'db_table': 'problem',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProblemTag',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=30)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'problem_tag',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TestCaseScore',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('test_case_id', models.CharField(max_length=32)),
|
||||
('score', jsonfield.fields.JSONField()),
|
||||
],
|
||||
options={
|
||||
'db_table': 'test_case_score',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='problem',
|
||||
name='tags',
|
||||
field=models.ManyToManyField(to='problem.ProblemTag'),
|
||||
),
|
||||
]
|
73
problem/migrations/0002_auto_20170202_0826.py
Normal file
73
problem/migrations/0002_auto_20170202_0826.py
Normal file
@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.12 on 2017-02-02 08:26
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import jsonfield.fields
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('problem', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='TestCaseScore',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='problem',
|
||||
name='languages',
|
||||
field=jsonfield.fields.JSONField(default=[]),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='problem',
|
||||
name='rule_type',
|
||||
field=models.CharField(default='ACM', max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='problem',
|
||||
name='test_case_score',
|
||||
field=jsonfield.fields.JSONField(default={}),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='difficulty',
|
||||
field=models.CharField(max_length=32),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='input_description',
|
||||
field=utils.models.RichTextField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='output_description',
|
||||
field=utils.models.RichTextField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='samples',
|
||||
field=jsonfield.fields.JSONField(),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='spj_language',
|
||||
field=models.CharField(blank=True, max_length=32, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='test_case_id',
|
||||
field=models.CharField(max_length=32),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='title',
|
||||
field=models.CharField(max_length=128),
|
||||
),
|
||||
]
|
0
problem/migrations/__init__.py
Normal file
0
problem/migrations/__init__.py
Normal file
@ -12,16 +12,23 @@ class ProblemTag(models.Model):
|
||||
db_table = "problem_tag"
|
||||
|
||||
|
||||
class ProblemRuleType(object):
|
||||
ACM = "ACM"
|
||||
OI = "OI"
|
||||
|
||||
|
||||
class AbstractProblem(models.Model):
|
||||
title = models.CharField(max_length=50)
|
||||
title = models.CharField(max_length=128)
|
||||
# HTML
|
||||
description = RichTextField()
|
||||
input_description = models.CharField(max_length=10000)
|
||||
output_description = models.CharField(max_length=10000)
|
||||
input_description = RichTextField()
|
||||
output_description = RichTextField()
|
||||
# [{input: "test", output: "123"}, {input: "test123", output: "456"}]
|
||||
samples = models.TextField(blank=True)
|
||||
test_case_id = models.CharField(max_length=40)
|
||||
samples = JSONField()
|
||||
test_case_id = models.CharField(max_length=32)
|
||||
test_case_score = JSONField()
|
||||
hint = RichTextField(blank=True, null=True)
|
||||
languages = JSONField()
|
||||
create_time = models.DateTimeField(auto_now_add=True)
|
||||
# we can not use auto_now here
|
||||
last_update_time = models.DateTimeField(blank=True, null=True)
|
||||
@ -32,10 +39,14 @@ class AbstractProblem(models.Model):
|
||||
memory_limit = models.IntegerField()
|
||||
# special judge related
|
||||
spj = models.BooleanField(default=False)
|
||||
spj_language = models.IntegerField(blank=True, null=True)
|
||||
spj_language = models.CharField(max_length=32, blank=True, null=True)
|
||||
spj_code = models.TextField(blank=True, null=True)
|
||||
spj_version = models.CharField(max_length=32, blank=True, null=True)
|
||||
rule_type = models.CharField(max_length=32)
|
||||
visible = models.BooleanField(default=True)
|
||||
difficulty = models.CharField(max_length=32)
|
||||
tags = models.ManyToManyField(ProblemTag)
|
||||
source = models.CharField(max_length=200, blank=True, null=True)
|
||||
total_submit_number = models.IntegerField(default=0)
|
||||
total_accepted_number = models.IntegerField(default=0)
|
||||
|
||||
@ -53,14 +64,4 @@ class AbstractProblem(models.Model):
|
||||
|
||||
|
||||
class Problem(AbstractProblem):
|
||||
difficulty = models.IntegerField()
|
||||
tags = models.ManyToManyField(ProblemTag)
|
||||
source = models.CharField(max_length=200, blank=True, null=True)
|
||||
|
||||
|
||||
class TestCaseScore(models.Model):
|
||||
test_case_id = models.CharField(max_length=32)
|
||||
score = JSONField()
|
||||
|
||||
class Meta:
|
||||
db_table = "test_case_score"
|
||||
pass
|
||||
|
@ -1,6 +1,67 @@
|
||||
from django import forms
|
||||
|
||||
from judge.languages import language_names, spj_language_names
|
||||
from utils.api import DateTimeTZField, UsernameSerializer, serializers
|
||||
|
||||
from .models import Problem, ProblemRuleType, ProblemTag
|
||||
|
||||
|
||||
class TestCaseUploadForm(forms.Form):
|
||||
spj = forms.CharField(max_length=12)
|
||||
file = forms.FileField()
|
||||
|
||||
|
||||
class CreateSampleSerializer(serializers.Serializer):
|
||||
input = serializers.CharField()
|
||||
output = serializers.CharField()
|
||||
|
||||
|
||||
class CreateTestCaseScoreSerializer(serializers.Serializer):
|
||||
input_name = serializers.CharField(max_length=32)
|
||||
score = serializers.IntegerField(min_value=0)
|
||||
|
||||
|
||||
class Difficulty(object):
|
||||
LOW = "Low"
|
||||
MID = "Mid"
|
||||
HIGH = "High"
|
||||
|
||||
|
||||
class CreateProblemSerializer(serializers.Serializer):
|
||||
title = serializers.CharField(max_length=128)
|
||||
description = serializers.CharField()
|
||||
input_description = serializers.CharField()
|
||||
output_description = serializers.CharField()
|
||||
samples = serializers.ListField(child=CreateSampleSerializer())
|
||||
test_case_id = serializers.CharField(max_length=32)
|
||||
test_case_score = serializers.ListField(child=CreateTestCaseScoreSerializer())
|
||||
hint = serializers.CharField(allow_blank=True)
|
||||
time_limit = serializers.IntegerField(min_value=1, max_value=1000 * 60)
|
||||
memory_limit = serializers.IntegerField(min_value=1, max_value=1024)
|
||||
languages = serializers.ListField(child=serializers.ChoiceField(choices=language_names))
|
||||
rule_type = serializers.ChoiceField(choices=[ProblemRuleType.ACM, ProblemRuleType.OI])
|
||||
spj = serializers.BooleanField()
|
||||
spj_language = serializers.ChoiceField(choices=spj_language_names, allow_blank=True)
|
||||
spj_code = serializers.CharField(allow_blank=True)
|
||||
visible = serializers.BooleanField()
|
||||
difficulty = serializers.ChoiceField(choices=[Difficulty.LOW, Difficulty.MID, Difficulty.HIGH])
|
||||
tags = serializers.ListField(child=serializers.CharField(max_length=32))
|
||||
source = serializers.CharField(max_length=256, allow_blank=True)
|
||||
|
||||
|
||||
class TagSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProblemTag
|
||||
|
||||
|
||||
class ProblemSerializer(serializers.ModelSerializer):
|
||||
samples = serializers.JSONField()
|
||||
test_case_score = serializers.JSONField()
|
||||
languages = serializers.JSONField()
|
||||
tags = TagSerializer(many=True)
|
||||
create_time = DateTimeTZField()
|
||||
last_update_time = DateTimeTZField()
|
||||
created_by = UsernameSerializer()
|
||||
|
||||
class Meta:
|
||||
model = Problem
|
||||
|
@ -1,7 +1,8 @@
|
||||
from django.conf.urls import url
|
||||
|
||||
from ..views.admin import TestCaseUploadAPI
|
||||
from ..views.admin import ProblemAPI, TestCaseUploadAPI
|
||||
|
||||
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")
|
||||
]
|
||||
|
@ -3,5 +3,5 @@ from django.conf.urls import url
|
||||
from ..views.oj import ProblemTagAPI
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^tags$", ProblemTagAPI.as_view(), name="problem_tag_list_api")
|
||||
url(r"^problem/tags$", ProblemTagAPI.as_view(), name="problem_tag_list_api")
|
||||
]
|
||||
|
@ -6,10 +6,12 @@ import zipfile
|
||||
from django.conf import settings
|
||||
|
||||
from account.decorators import admin_required
|
||||
from utils.api import CSRFExemptAPIView
|
||||
from utils.api import APIView, CSRFExemptAPIView, validate_serializer
|
||||
from utils.shortcuts import rand_str
|
||||
|
||||
from ..serializers import TestCaseUploadForm
|
||||
from ..models import Problem, ProblemRuleType, ProblemTag
|
||||
from ..serializers import (CreateProblemSerializer, ProblemSerializer,
|
||||
TestCaseUploadForm)
|
||||
|
||||
|
||||
class TestCaseUploadAPI(CSRFExemptAPIView):
|
||||
@ -103,3 +105,47 @@ class TestCaseUploadAPI(CSRFExemptAPIView):
|
||||
with open(os.path.join(test_case_dir, "info"), "w", encoding="utf-8") as f:
|
||||
f.write(json.dumps(test_case_info, indent=4))
|
||||
return self.success({"id": test_case_id, "info": ret, "hint": hint, "spj": spj})
|
||||
|
||||
|
||||
class ProblemAPI(APIView):
|
||||
@validate_serializer(CreateProblemSerializer)
|
||||
def post(self, request):
|
||||
data = request.data
|
||||
if not data["languages"]:
|
||||
return self.error("Invalid languages")
|
||||
if not data["samples"]:
|
||||
return self.error("Invalid samples")
|
||||
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:
|
||||
if not data["test_case_score"]:
|
||||
return self.error("Test case score is required")
|
||||
for item in data["test_case_score"]:
|
||||
if item["score"] <= 0:
|
||||
return self.error("Invalid score")
|
||||
# todo check filename
|
||||
else:
|
||||
data["test_case_score"] = {}
|
||||
data["created_by"] = request.user
|
||||
tags = data.pop("tags")
|
||||
if not tags:
|
||||
return self.error("Tags is required")
|
||||
problem = Problem.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()
|
||||
|
||||
def get(self, request):
|
||||
problems = Problem.objects.all().order_by("-create_time")
|
||||
if request.user.is_admin_role():
|
||||
problems = problems.filter(created_by=request.user)
|
||||
return self.success(self.paginate_data(request, problems, ProblemSerializer))
|
||||
|
@ -1,14 +1,7 @@
|
||||
import json
|
||||
|
||||
from django.utils import timezone
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class JSONField(serializers.Field):
|
||||
def to_representation(self, value):
|
||||
return json.loads(value)
|
||||
|
||||
|
||||
class DateTimeTZField(serializers.DateTimeField):
|
||||
def to_representation(self, value):
|
||||
self.format = "%Y-%-m-%d %H:%M:%S %Z"
|
||||
|
@ -1,6 +1,7 @@
|
||||
import functools
|
||||
import json
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.http import HttpResponse, QueryDict
|
||||
from django.utils.decorators import method_decorator
|
||||
@ -80,12 +81,21 @@ class APIView(View):
|
||||
def error(self, msg, err="error"):
|
||||
return self.response({"error": err, "data": msg})
|
||||
|
||||
def _serializer_error_to_str(self, errors):
|
||||
for k, v in errors.items():
|
||||
if isinstance(v, list):
|
||||
return k, v[0]
|
||||
elif isinstance(v, OrderedDict):
|
||||
for _k, _v in v.items():
|
||||
return self._serializer_error_to_str({_k: _v})
|
||||
|
||||
def invalid_serializer(self, serializer):
|
||||
for k, v in serializer.errors.items():
|
||||
print(serializer.errors)
|
||||
k, v = self._serializer_error_to_str(serializer.errors)
|
||||
if k != "non_field_errors":
|
||||
return self.error(err="invalid-" + k, msg=k + ": " + v[0])
|
||||
return self.error(err="invalid-" + k, msg=k + ": " + v)
|
||||
else:
|
||||
return self.error(err="invalid-field", msg=k[0])
|
||||
return self.error(err="invalid-field", msg=v)
|
||||
|
||||
def server_error(self):
|
||||
return self.error(err="server-error", msg="server error")
|
||||
|
Loading…
Reference in New Issue
Block a user