重构 problem 和 contest;修改测试和部分模板的结构

This commit is contained in:
virusdefender 2015-10-17 16:49:02 +08:00
parent 28011f9a0e
commit 4dd5aa3eba
20 changed files with 238 additions and 428 deletions

View File

@ -32,7 +32,7 @@ def check_user_contest_permission(func):
else: else:
return HttpResponseRedirect("/login/") return HttpResponseRedirect("/login/")
# kwargs 就包含了url 里面的播或参数 # kwargs 就包含了 url 里面的参数
if "contest_id" in kwargs: if "contest_id" in kwargs:
contest_id = kwargs["contest_id"] contest_id = kwargs["contest_id"]
elif "contest_id" in request.data: elif "contest_id" in request.data:
@ -54,6 +54,13 @@ def check_user_contest_permission(func):
if request.user.admin_type == SUPER_ADMIN or request.user == contest.created_by: if request.user.admin_type == SUPER_ADMIN or request.user == contest.created_by:
return func(*args, **kwargs) return func(*args, **kwargs)
# 管理员可见隐藏的比赛,已经先判断了身份
if not contest.visible:
if request.is_ajax():
return error_response(u"比赛不存在")
else:
return error_page(request, u"比赛不存在")
# 有密码的公开赛 # 有密码的公开赛
if contest.contest_type == PASSWORD_PROTECTED_CONTEST: if contest.contest_type == PASSWORD_PROTECTED_CONTEST:
# 没有输入过密码 # 没有输入过密码

View File

@ -293,7 +293,6 @@ def contest_page(request, contest_id):
单个比赛的详情页 单个比赛的详情页
""" """
contest = Contest.objects.get(id=contest_id) contest = Contest.objects.get(id=contest_id)
return render(request, "oj/contest/contest_index.html", {"contest": contest}) return render(request, "oj/contest/contest_index.html", {"contest": contest})
@ -304,15 +303,17 @@ def contest_problem_page(request, contest_id, contest_problem_id):
""" """
contest = Contest.objects.get(id=contest_id) contest = Contest.objects.get(id=contest_id)
try: try:
contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True) problem = ContestProblem.objects.get(id=contest_problem_id, visible=True)
except ContestProblem.DoesNotExist: except ContestProblem.DoesNotExist:
return error_page(request, u"比赛题目不存在") return error_page(request, u"比赛题目不存在")
warning = u"您已经提交过本题的正确答案,重复提交可能造成时间累计。" warning = u"您已经提交过本题的正确答案,重复提交可能造成时间累计。"
show_warning = False show_warning = False
try: try:
submission = ContestSubmission.objects.get(user=request.user, contest=contest, problem=contest_problem) rank = ContestRank.objects.get(user=request.user, contest=contest)
show_warning = submission.ac # 提示已经 ac 过这道题了
except ContestSubmission.DoesNotExist: show_warning = rank.submission_info.get(str(problem.id), {"is_ac": False})["is_ac"]
except ContestRank.DoesNotExist:
pass pass
# 已经结束 # 已经结束
@ -324,14 +325,16 @@ def contest_problem_page(request, contest_id, contest_problem_id):
warning = u"比赛没有开始,您是管理员,可以提交和测试题目,但是目前的提交不会计入排名。" warning = u"比赛没有开始,您是管理员,可以提交和测试题目,但是目前的提交不会计入排名。"
show_submit_code_area = False show_submit_code_area = False
if contest.status == CONTEST_UNDERWAY: if contest.status == CONTEST_UNDERWAY or \
show_submit_code_area = True request.user.admin_type == SUPER_ADMIN or \
if request.user.admin_type == SUPER_ADMIN or request.user == contest.created_by: request.user == contest.created_by:
show_submit_code_area = True show_submit_code_area = True
return render(request, "oj/contest/contest_problem.html", {"contest_problem": contest_problem, "contest": contest, return render(request, "oj/problem/contest_problem.html", {"problem": problem,
"samples": json.loads(contest_problem.samples), "contest": contest,
"show_warning": show_warning, "warning": warning, "samples": json.loads(problem.samples),
"show_warning": show_warning,
"warning": warning,
"show_submit_code_area": show_submit_code_area}) "show_submit_code_area": show_submit_code_area})

View File

@ -76,7 +76,7 @@ def contest_problem_my_submissions_list_page(request, contest_id, contest_proble
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=contest_problem.id).order_by( submissions = Submission.objects.filter(user_id=request.user.id, problem_id=contest_problem.id).order_by(
"-create_time"). \ "-create_time"). \
values("id", "result", "create_time", "accepted_answer_time", "language") values("id", "result", "create_time", "accepted_answer_time", "language")
return render(request, "oj/contest/my_submissions_list.html", return render(request, "oj/submission/problem_my_submissions_list.html",
{"submissions": submissions, "problem": contest_problem}) {"submissions": submissions, "problem": contest_problem})

View File

@ -17,12 +17,16 @@ def check_user_problem_permission(func):
request = args[0] request = args[0]
# 这是在后台使用的url middleware 已经确保用户是登录状态的了 # 这是在后台使用的url middleware 已经确保用户是登录状态的了
if request.user.admin_type == SUPER_ADMIN:
return func(*args, **kwargs)
try: try:
Problem.objects.get(id=request.data.get("problem_id", -1), created_by=request.user) problem = Problem.objects.get(id=request.data.get("id", -1))
except Problem.DoesNotExist: except Problem.DoesNotExist:
return error_response(u"问题不存在") return error_response(u"问题不存在")
return func(*args, **kwargs)
if request.user.admin_type == SUPER_ADMIN:
return func(*args, **kwargs)
else:
if problem.created_by != request.user:
return error_response(u"问题不存在")
return func(*args, **kwargs)
return check return check

View File

@ -25,13 +25,13 @@ class CreateProblemSerializer(serializers.Serializer):
# [{"input": "1 1", "output": "2"}] # [{"input": "1 1", "output": "2"}]
samples = ProblemSampleSerializer() samples = ProblemSampleSerializer()
test_case_id = serializers.CharField(max_length=40) test_case_id = serializers.CharField(max_length=40)
source = serializers.CharField(max_length=30, required=False, default=None)
time_limit = serializers.IntegerField(min_value=1) time_limit = serializers.IntegerField(min_value=1)
memory_limit = serializers.IntegerField(min_value=1) memory_limit = serializers.IntegerField(min_value=1)
difficulty = serializers.IntegerField() difficulty = serializers.IntegerField()
tags = serializers.ListField(child=serializers.CharField(max_length=10)) tags = serializers.ListField(child=serializers.CharField(max_length=10))
hint = serializers.CharField(max_length=3000, allow_blank=True) hint = serializers.CharField(max_length=3000, allow_blank=True)
visible = visible = serializers.BooleanField() source = serializers.CharField(max_length=100, required=False, default=None)
visible = serializers.BooleanField()
class ProblemTagSerializer(serializers.ModelSerializer): class ProblemTagSerializer(serializers.ModelSerializer):
@ -61,7 +61,7 @@ class EditProblemSerializer(serializers.Serializer):
input_description = serializers.CharField(max_length=10000) input_description = serializers.CharField(max_length=10000)
output_description = serializers.CharField(max_length=10000) output_description = serializers.CharField(max_length=10000)
test_case_id = serializers.CharField(max_length=40) test_case_id = serializers.CharField(max_length=40)
source = serializers.CharField(max_length=30) source = serializers.CharField(max_length=100)
time_limit = serializers.IntegerField(min_value=1) time_limit = serializers.IntegerField(min_value=1)
memory_limit = serializers.IntegerField(min_value=1) memory_limit = serializers.IntegerField(min_value=1)
difficulty = serializers.IntegerField() difficulty = serializers.IntegerField()
@ -69,7 +69,3 @@ class EditProblemSerializer(serializers.Serializer):
samples = ProblemSampleSerializer() samples = ProblemSampleSerializer()
hint = serializers.CharField(max_length=3000, allow_blank=True) hint = serializers.CharField(max_length=3000, allow_blank=True)
visible = serializers.BooleanField() visible = serializers.BooleanField()
class CreateProblemTagSerializer(serializers.Serializer):
name = serializers.CharField(max_length=10)

View File

@ -7,16 +7,15 @@ from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase, APIClient from rest_framework.test import APITestCase, APIClient
from account.models import User, SUPER_ADMIN from account.models import User, SUPER_ADMIN
from account.tests import create_user
from problem.models import Problem, ProblemTag from problem.models import Problem, ProblemTag
class ProblemPageTest(TestCase): class ProblemPageTest(TestCase):
def setUp(self): def setUp(self):
self.client = APIClient() self.client = APIClient()
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN) self.user = create_user()
self.user.set_password("testaa") self.client.login(username="test", password="111111")
self.user.save()
self.client.login(username="test", password="testaa")
self.problem = Problem.objects.create(title="title1", self.problem = Problem.objects.create(title="title1",
description="description1", description="description1",
input_description="input1_description", input_description="input1_description",
@ -31,11 +30,11 @@ class ProblemPageTest(TestCase):
created_by=User.objects.get(username="test")) created_by=User.objects.get(username="test"))
def test_visit_problem_successfully(self): def test_visit_problem_successfully(self):
response = self.client.get('/problem/1/') response = self.client.get('/problem/' + str(self.problem.id) + "/")
self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "oj/problem/problem.html")
def test_problem_does_not_exist(self): def test_problem_does_not_exist(self):
response = self.client.get('/problem/3/') response = self.client.get('/problem/3000/')
self.assertTemplateUsed(response, "utils/error.html") self.assertTemplateUsed(response, "utils/error.html")
@ -60,10 +59,8 @@ class ProblemAdminTest(APITestCase):
def setUp(self): def setUp(self):
self.client = APIClient() self.client = APIClient()
self.url = reverse("problem_admin_api") self.url = reverse("problem_admin_api")
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN) self.user = create_user(admin_type=SUPER_ADMIN)
self.user.set_password("testaa") self.client.login(username="test", password="111111")
self.user.save()
self.client.login(username="test", password="testaa")
ProblemTag.objects.create(name="tag1") ProblemTag.objects.create(name="tag1")
ProblemTag.objects.create(name="tag2") ProblemTag.objects.create(name="tag2")
self.problem = Problem.objects.create(title="title1", self.problem = Problem.objects.create(title="title1",
@ -77,15 +74,9 @@ class ProblemAdminTest(APITestCase):
memory_limit=1000, memory_limit=1000,
difficulty=1, difficulty=1,
hint="hint1", hint="hint1",
created_by=User.objects.get(username="test")) created_by=self.user)
# 以下是发布题目的测试 def test_create_problem_successfully(self):
def test_invalid_format(self):
data = {"title": "test1"}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_release_problem_successfully(self):
data = {"title": "title2", data = {"title": "title2",
"description": "description2", "description": "description2",
"input_description": "input_description2", "input_description": "input_description2",
@ -97,30 +88,15 @@ class ProblemAdminTest(APITestCase):
"memory_limit": "1000", "memory_limit": "1000",
"difficulty": "1", "difficulty": "1",
"hint": "hint1", "hint": "hint1",
"visible": True,
"tags": [1]} "tags": [1]}
response = self.client.post(self.url, data=json.dumps(data), content_type="application/json") response = self.client.post(self.url, data=json.dumps(data), content_type="application/json")
self.assertEqual(response.data["code"], 0) self.assertEqual(response.data["code"], 0)
# 以下是编辑题目的测试
def test_invalid_data(self):
data = {"title": "test0"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_problem_does_not_exist(self):
tags = ProblemTag.objects.filter(id__in=[1])
self.problem.tags.add(*tags)
data = self._create_data(2, False, [1])
response = self.client.put(self.url, data=json.dumps(data), content_type="application/json")
self.assertEqual(response.data, {"code": 1, "data": u"该题目不存在!"})
def test_edit_problem_successfully(self): def test_edit_problem_successfully(self):
tags = ProblemTag.objects.filter(id__in=[1]) tags = ProblemTag.objects.filter(id__in=[1])
self.problem.tags.add(*tags) self.problem.tags.add(*tags)
data = self._create_data(1, True, [1, 2]) data = self._create_data(self.problem.id, True, [1, 2])
problem = Problem.objects.get(id=data["id"])
problem.tags.remove(*problem.tags.all())
problem.tags.add(*ProblemTag.objects.filter(id__in=data["tags"]))
response = self.client.put(self.url, data=json.dumps(data), content_type="application/json") response = self.client.put(self.url, data=json.dumps(data), content_type="application/json")
self.assertEqual(response.data["code"], 0) self.assertEqual(response.data["code"], 0)
@ -139,11 +115,11 @@ class ProblemAdminTest(APITestCase):
self.assertEqual(item["visible"], True) self.assertEqual(item["visible"], True)
def test_query_problem_does_not_exist(self): def test_query_problem_does_not_exist(self):
data = {"problem_id": 2} data = {"problem_id": 200}
response = self.client.get(self.url, data=data) response = self.client.get(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"题目不存在"}) self.assertEqual(response.data, {"code": 1, "data": u"题目不存在"})
def test_query_problem_exists(self): def test_query_existed_problem(self):
data = {"problem_id": self.problem.id} data = {"problem_id": self.problem.id}
response = self.client.get(self.url, data=data) response = self.client.get(self.url, data=data)
self.assertEqual(response.data["code"], 0) self.assertEqual(response.data["code"], 0)
@ -153,10 +129,8 @@ class ProblemTagAdminAPITest(APITestCase):
def setUp(self): def setUp(self):
self.client = APIClient() self.client = APIClient()
self.url = reverse('problem_tag_admin_api') self.url = reverse('problem_tag_admin_api')
self.user = User.objects.create(username="testx", admin_type=SUPER_ADMIN) self.user = create_user(admin_type=SUPER_ADMIN)
self.user.set_password("testxx") self.client.login(username="test", password="111111")
self.user.save()
self.client.login(username="testx", password="testxx")
ProblemTag.objects.create(name="tag1") ProblemTag.objects.create(name="tag1")
# 以下是返回所有的问题的标签 # 以下是返回所有的问题的标签
@ -168,10 +142,8 @@ class ProblemListPageTest(TestCase):
def setUp(self): def setUp(self):
self.client = Client() self.client = Client()
self.url = reverse('problem_list_page', kwargs={"page": 1}) self.url = reverse('problem_list_page', kwargs={"page": 1})
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN) self.user = create_user(admin_type=SUPER_ADMIN)
self.user.set_password("testaa") self.client.login(username="test", password="111111")
self.user.save()
self.client.login(username="test", password="testaa")
ProblemTag.objects.create(name="tag1") ProblemTag.objects.create(name="tag1")
ProblemTag.objects.create(name="tag2") ProblemTag.objects.create(name="tag2")
self.problem = Problem.objects.create(title="title1", self.problem = Problem.objects.create(title="title1",
@ -185,7 +157,7 @@ class ProblemListPageTest(TestCase):
memory_limit=1000, memory_limit=1000,
difficulty=1, difficulty=1,
hint="hint1", hint="hint1",
created_by=User.objects.get(username="test")) created_by=self.user)
def test_problemListPage_not_exist(self): def test_problemListPage_not_exist(self):
response = self.client.get('/problems/999/') response = self.client.get('/problems/999/')

View File

@ -9,21 +9,19 @@ import logging
from django.shortcuts import render from django.shortcuts import render
from django.db.models import Q, Count from django.db.models import Q, Count
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.utils.timezone import now
from rest_framework.views import APIView
from django.conf import settings from django.conf import settings
from rest_framework.views import APIView
from account.models import SUPER_ADMIN from account.models import SUPER_ADMIN
from account.decorators import super_admin_required from account.decorators import super_admin_required
from utils.shortcuts import (serializer_invalid_response, error_response, from utils.shortcuts import (serializer_invalid_response, error_response,
success_response, paginate, rand_str, error_page) success_response, paginate, rand_str, error_page)
from .serizalizers import (CreateProblemSerializer, EditProblemSerializer, ProblemSerializer, from .serizalizers import (CreateProblemSerializer, EditProblemSerializer, ProblemSerializer,
ProblemTagSerializer, CreateProblemTagSerializer) ProblemTagSerializer)
from .models import Problem, ProblemTag from .models import Problem, ProblemTag
from .decorators import check_user_problem_permission from .decorators import check_user_problem_permission
logger = logging.getLogger("app_info") logger = logging.getLogger("app_info")
@ -59,7 +57,7 @@ class ProblemAdminAPIView(APIView):
if serializer.is_valid(): if serializer.is_valid():
data = serializer.data data = serializer.data
try: try:
Problem.objects.get(title=data["title"], description=data["description"]) Problem.objects.get(title=data["title"])
return error_response(u"添加失败,存在重复的题目") return error_response(u"添加失败,存在重复的题目")
except Problem.DoesNotExist: except Problem.DoesNotExist:
pass pass
@ -110,6 +108,7 @@ class ProblemAdminAPIView(APIView):
problem.samples = json.dumps(data["samples"]) problem.samples = json.dumps(data["samples"])
problem.hint = data["hint"] problem.hint = data["hint"]
problem.visible = data["visible"] problem.visible = data["visible"]
problem.last_update_time = now()
# 删除原有的标签的对应关系 # 删除原有的标签的对应关系
problem.tags.remove(*problem.tags.all()) problem.tags.remove(*problem.tags.all())
@ -155,7 +154,7 @@ class ProblemAdminAPIView(APIView):
keyword = request.GET.get("keyword", None) keyword = request.GET.get("keyword", None)
if keyword: if keyword:
problems = problems.filter(Q(title__contains=keyword) | problems = problems.filter(Q(title__contains=keyword) |
Q(description__contains=keyword)) Q(description__contains=keyword))
return paginate(request, problems, ProblemSerializer) return paginate(request, problems, ProblemSerializer)
@ -164,6 +163,7 @@ class TestCaseUploadAPIView(APIView):
""" """
上传题目的测试用例 上传题目的测试用例
""" """
def _is_legal_test_case_file_name(self, file_name): def _is_legal_test_case_file_name(self, file_name):
# 正整数开头的 .in 或者.out 结尾的 # 正整数开头的 .in 或者.out 结尾的
regex = r"^[1-9]\d*\.(in|out)$" regex = r"^[1-9]\d*\.(in|out)$"
@ -190,10 +190,7 @@ class TestCaseUploadAPIView(APIView):
l = [] l = []
# 如果文件是直接打包的那么name_list 就是["1.in", "1.out"]这样的 # 如果文件是直接打包的那么name_list 就是["1.in", "1.out"]这样的
# 如果文件还有一层文件夹test_case那么name_list就是["test_case/", "test_case/1.in", "test_case/1.out"]
# 现在暂时只支持第一种,先判断一下是什么格式的
# 第一种格式的
if "1.in" in name_list and "1.out" in name_list: if "1.in" in name_list and "1.out" in name_list:
for file_name in name_list: for file_name in name_list:
if self._is_legal_test_case_file_name(file_name): if self._is_legal_test_case_file_name(file_name):
@ -251,7 +248,8 @@ class TestCaseUploadAPIView(APIView):
"striped_output_md5": striped_md5.hexdigest(), "striped_output_md5": striped_md5.hexdigest(),
"output_size": os.path.getsize(test_case_dir + str(i + 1) + ".out")} "output_size": os.path.getsize(test_case_dir + str(i + 1) + ".out")}
# 写入配置文件 # 写入配置文件
open(test_case_dir + "info", "w").write(json.dumps(file_info)) with open(test_case_dir + "info", "w") as f:
f.write(json.dumps(file_info))
return success_response({"test_case_id": problem_test_dir, return success_response({"test_case_id": problem_test_dir,
"file_list": {"input": l[0::2], "file_list": {"input": l[0::2],
@ -311,7 +309,8 @@ def problem_list_page(request, page=1):
pass pass
# 右侧标签列表 按照关联的题目的数量排序 排除题目数量为0的 # 右侧标签列表 按照关联的题目的数量排序 排除题目数量为0的
tags = ProblemTag.objects.annotate(problem_number=Count("problem")).filter(problem_number__gt=0).order_by("-problem_number") tags = ProblemTag.objects.annotate(problem_number=Count("problem")).filter(problem_number__gt=0).order_by(
"-problem_number")
return render(request, "oj/problem/problem_list.html", return render(request, "oj/problem/problem_list.html",
{"problems": current_page, "page": int(page), {"problems": current_page, "page": int(page),

View File

@ -85,6 +85,9 @@
{ {
name: "bootstrap", name: "bootstrap",
}, },
{
name: "codeMirror"
},
{ {
name: "announcement_0_pack" name: "announcement_0_pack"
}, },

View File

@ -85,7 +85,7 @@ def problem_my_submissions_list_page(request, problem_id):
contest_id__isnull=True).order_by("-create_time"). \ contest_id__isnull=True).order_by("-create_time"). \
values("id", "result", "create_time", "accepted_answer_time", "language") values("id", "result", "create_time", "accepted_answer_time", "language")
return render(request, "oj/problem/my_submissions_list.html", return render(request, "oj/submission/problem_my_submissions_list.html",
{"submissions": submissions, "problem": problem}) {"submissions": submissions, "problem": problem})
@ -139,7 +139,7 @@ def my_submission(request, submission_id):
else: else:
info = None info = None
user = User.objects.get(id=submission.user_id) user = User.objects.get(id=submission.user_id)
return render(request, "oj/problem/my_submission.html", return render(request, "oj/submission/my_submission.html",
{"submission": submission, "problem": problem, "info": info, {"submission": submission, "problem": problem, "info": info,
"user": user, "can_share": result["can_share"]}) "user": user, "can_share": result["can_share"]})

View File

@ -1,103 +0,0 @@
{% extends 'oj_base.html' %}
{% block title %}
{{ contest_problem.title }}
{% endblock %}
{% block body %}
<div class="container main">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation">
<a href="/contest/{{ contest_problem.contest.id }}/problems/">题目列表</a>
</li>
<li role="presentation" class="active">
<a href="/contest/{{ contest_problem.contest.id }}/problem/{{ contest_problem.id }}/">题目
{{ contest_problem.sort_index }}</a>
</li>
<li role="presentation">
<a href="/contest/{{ contest_problem.contest.id }}/problem/{{ contest_problem.id }}/submissions/">我的提交</a>
</li>
</ul>
<h2 class="text-center">{{ contest_problem.title }}</h2>
<p class="text-muted text-center">发布时间 : {{ contest_problem.create_time }}&nbsp;&nbsp;
时间限制 : {{ contest_problem.time_limit }}ms&nbsp;&nbsp;
内存限制 : {{ contest_problem.memory_limit }}M
</p>
<div>
<div class="problem-section">
<label class="problem-label">描述</label>
<div class="problem-detail">{{ contest_problem.description|safe }}</div>
</div>
<div class="problem-section">
<label class="problem-label">输入</label>
<p class="problem-detail">{{ contest_problem.input_description }}</p>
<div>
<div class="problem-section">
<label class="problem-label">输出</label>
<p class="problem-detail">{{ contest_problem.output_description }}</p>
</div>
{% for item in samples %}
<div class="problem-section">
<label class="problem-label">样例输入{{ forloop.counter }}</label>
<a href="javascript:void(0)" class="copy-sample"
data-clipboard-text="{{ item.input }}">复制</a>
<pre>{{ item.input }}</pre>
</div>
<div class="problem-section">
<label class="problem-label">样例输出{{ forloop.counter }}</label>
<pre>{{ item.output }}</pre>
</div>
{% endfor %}
{% if contest_problem.hint %}
<div class="problem-section">
<label class="problem-label">提示</label>
<div class="problem-detail">{{ contest_problem.hint|safe }}</div>
</div>
{% endif %}
{% if show_submit_code_area %}
<div>
<label>选择语言</label>
<div>
<label class="radio-inline">
<input type="radio" name="language" value="1" checked> C (GCC 4.8)
</label>
<label class="radio-inline">
<input type="radio" name="language" value="2"> C++ (G++ 4.3)
</label>
<label class="radio-inline">
<input type="radio" name="language" value="3"> Java (Oracle JDK 1.7)
</label>
</div>
</div>
<div id="code-field">
<label class="problem-label">提交代码</label>
<textarea id="code-editor"></textarea>
</div>
<hr>
<div id="submit-code">
<button type="button" class="btn btn-primary" id="submit-code-button">
提交代码
</button>
<img src="/static/img/loading.gif" id="loading-gif">
</div>
{% endif %}
{% if show_warning %}
<div class="alert alert-success" role="alert">{{ warning }}</div>
{% endif %}
<div id="result">
</div>
<hr>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js_block %}
<script src="/static/js/app/oj/problem/problem.js"></script>
{% endblock %}

View File

@ -3,66 +3,66 @@
比赛题目列表 比赛题目列表
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{% load problem %} {% load problem %}
<div class="container main"> <div class="container main">
<div class="row"> <div class="row">
<div class="col-lg-12 contest-tab"> <div class="col-lg-12 contest-tab">
<ul class="nav nav-tabs nav-tabs-google"> <ul class="nav nav-tabs nav-tabs-google">
<li role="presentation"> <li role="presentation">
<a href="/contest/{{ contest.id }}/">比赛详情</a> <a href="/contest/{{ contest.id }}/">比赛详情</a>
</li> </li>
<li role="presentation" class="active"> <li role="presentation" class="active">
<a href="/contest/{{ contest.id }}/problems/">题目列表</a> <a href="/contest/{{ contest.id }}/problems/">题目列表</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="/contest/{{ contest.id }}/submissions/">提交</a> <a href="/contest/{{ contest.id }}/submissions/">提交</a>
</li> </li>
<li role="presentation"> <li role="presentation">
<a href="/contest/{{ contest.id }}/rank/?paging=true&page=1&page_size=40">排名</a> <a href="/contest/{{ contest.id }}/rank/?paging=true&page=1&page_size=40">排名</a>
</li> </li>
</ul> </ul>
</div>
<div class="col-md-12 col-lg-12">
<div>
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th>#</th>
<th>题目</th>
<th>通过率</th>
</tr>
</thead>
<tbody>
{% for item in contest_problems %}
<tr>
<th>
<span class="{% get_problem_status request.user.problems_status.contest_problems item.id %}"></span>
</th>
<th scope="row">
<a href="/contest/{{ item.contest.id }}/problem/{{ item.id }}/">{{ item.sort_index }}</a>
</th>
<td>
<a href="/contest/{{ item.contest.id }}/problem/{{ item.id }}/">{{ item.title }}</a>
</td>
<td>{{ item|accepted_radio }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
</div>
<div class="col-md-12 col-lg-12">
<div>
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th>#</th>
<th>题目</th>
<th>通过率</th>
</tr>
</thead>
<tbody>
{% for item in contest_problems %}
<tr>
<th>
<span class="{% get_problem_status request.user.problems_status.contest_problems item.id %}"></span>
</th>
<th scope="row">
<a href="/contest/{{ item.contest.id }}/problem/{{ item.id }}/">{{ item.sort_index }}</a>
</th>
<td>
<a href="/contest/{{ item.contest.id }}/problem/{{ item.id }}/">{{ item.title }}</a>
</td>
<td>{{ item|accepted_radio }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block js_block %} {% block js_block %}

View File

@ -1,74 +0,0 @@
{% extends 'oj_base.html' %}
{% block title %}
我的提交详情
{% endblock %}
{% block css_block %}
<style>
.CodeMirror {
height: auto;
}
</style>
{% endblock %}
{% block body %}
{% load submission %}
<div class="container main">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation" class="active">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/submissions/">
我的提交</a>
</li>
</ul>
{% include "oj/problem/_problem_header.html" %}
<div class="panel panel-default">
<div class="panel-body">
<h4>运行结果 : <span class="text-{{ submission.result|translate_result_class }}">
{{ submission.result|translate_result }}
</span>
</h4>
{% ifequal submission.result 0 %}
<p>时间 : {{ submission.accepted_answer_time }}ms 语言 :
{{ submission.language|translate_language }}
</p>
{% endifequal %}
{% ifequal submission.result 4 %}
<p>{{ submission.info }}</p>
{% endifequal %}
<p>提交时间 : {{ submission.create_time }}</p>
</div>
</div>
{% ifequal request.user.admin_type 2 %}
<p>本调试信息仅超级管理员可见</p>
{% ifequal submission.result 7 %}
<pre>System Error: {{ submission.info }}</pre>
{% else %}
<pre>{{ info }}</pre>
{% endifequal %}
{% endifequal %}
<div id="code-field">
<textarea id="code-editor">{{ submission.code }}</textarea>
</div>
</div>
{% endblock %}
{% block js_block %}
<script>
require(["jquery", "codeMirror"], function ($, codeMirror) {
{% ifequal submission.language 1 %}
var language = "text/x-csrc";
{% else %}
{% ifequal submission.language 2 %}
var language = "text/x-c++src";
{% else %}
var language = "text/x-java";
{% endifequal %}
{% endifequal %}
var codeEditor = codeMirror($("#code-editor")[0], language);
codeEditor.setOption("readOnly", true);
});
</script>
{% endblock %}

View File

@ -1,52 +0,0 @@
{% extends 'oj_base.html' %}
{% block title %}
我的提交列表
{% endblock %}
{% block body %}
{% load submission %}
<div class="container main">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation" class="active">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/submissions/">
我的提交</a>
</li>
</ul>
{% include "oj/problem/_problem_header.html" %}
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>提交时间</th>
<th>语言</th>
<th>运行时间</th>
<th>结果</th>
</tr>
</thead>
<tbody>
{% for item in submissions %}
<tr>
<th scope="row"><a href="/submission/{{ item.id }}/">{{ forloop.counter }}</a></th>
<td>{{ item.create_time }}</td>
<td>
{{ item.language|translate_language }}
</td>
<td>
{% if item.accepted_answer_time %}
{{ item.accepted_answer_time }}ms
{% else %}
--
{% endif %}
</td>
<td class="alert-{{ item.result|translate_result_class }}">
<strong>{{ item.result|translate_result }}</strong>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -1,6 +1,8 @@
<h2 class="text-center">{{ problem.title }}</h2> <h2 class="text-center">{{ problem.title }}</h2>
<p class="text-muted text-center">发布时间 : {{ problem.create_time }}&nbsp;&nbsp; <p class="text-muted text-center">
时间限制 : {{ problem.time_limit }}ms&nbsp;&nbsp; 发布时间: {{ problem.create_time }}&nbsp;&nbsp;
内存限制 : {{ problem.memory_limit }}M {% if problem.last_update_time %}最后更新: {{ problem.last_update_time }}&nbsp;&nbsp;{% endif %}
时间限制: {{ problem.time_limit }}ms&nbsp;&nbsp;
内存限制: {{ problem.memory_limit }}M
</p> </p>

View File

@ -0,0 +1,29 @@
<div class="problem-section">
<label class="problem-label">描述</label>
<div class="problem-detail">{{ problem.description|safe }}</div>
</div>
<div class="problem-section">
<label class="problem-label">输入</label>
<p class="problem-detail">{{ problem.input_description }}</p>
</div>
<div class="problem-section">
<label class="problem-label">输出</label>
<p class="problem-detail">{{ problem.output_description }}</p>
</div>
{% for item in samples %}
<div class="problem-section">
<label class="problem-label">样例输入{{ forloop.counter }}</label>
<a href="javascript:void(0)" class="copy-sample" data-clipboard-text="{{ item.input }}">复制</a>
<pre>
{{ item.input }}</pre>
</div>
<div class="problem-section">
<label class="problem-label">样例输出{{ forloop.counter }}</label>
<pre>
{{ item.output }}</pre>
</div>
{% endfor %}

View File

@ -0,0 +1,25 @@
<div>
<label>选择语言</label>
<div>
<label class="radio-inline">
<input type="radio" name="language" value="1" checked> C (GCC 4.8)
</label>
<label class="radio-inline">
<input type="radio" name="language" value="2"> C++ (G++ 4.3)
</label>
<label class="radio-inline">
<input type="radio" name="language" value="3"> Java (Oracle JDK 1.7)
</label>
</div>
</div>
<div id="code-field">
<label class="problem-label">提交代码</label>
<textarea id="code-editor"></textarea>
</div>
<hr>
<div id="submit-code">
<button type="button" class="btn btn-primary" id="submit-code-button">
提交代码
</button>
<img src="/static/img/loading.gif" id="loading-gif">
</div>

View File

@ -0,0 +1,42 @@
{% extends 'oj_base.html' %}
{% block title %}
{{ problem.title }}
{% endblock %}
{% block body %}
<div class="container main">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation">
<a href="/contest/{{ problem.contest.id }}/problems/">题目列表</a>
</li>
<li role="presentation" class="active">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/">题目{{ problem.sort_index }}</a>
</li>
<li role="presentation">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/submissions/">我的提交</a>
</li>
</ul>
{% include "oj/problem/_problem_header.html" %}
<div>
{% include "oj/problem/_problem_main_info.html" %}
{% if problem.hint %}
<div class="problem-section">
<label class="problem-label">提示</label>
<div class="problem-detail">{{ problem.hint|safe }}</div>
</div>
{% endif %}
{% if show_submit_code_area %}
{% include "oj/problem/_submit_problem.html" %}
{% endif %}
{% if show_warning %}
<div class="alert alert-success" role="alert">{{ warning }}</div>
{% endif %}
<div id="result">
</div>
<hr>
</div>
</div>
{% endblock %}
{% block js_block %}
<script src="/static/js/app/oj/problem/problem.js"></script>
{% endblock %}

View File

@ -15,35 +15,7 @@
{% include "oj/problem/_problem_header.html" %} {% include "oj/problem/_problem_header.html" %}
<div> <div>
<div class="problem-section"> {% include "oj/problem/_problem_main_info.html" %}
<label class="problem-label">描述</label>
<div class="problem-detail">{{ problem.description|safe }}</div>
</div>
<div class="problem-section">
<label class="problem-label">输入</label>
<p class="problem-detail">{{ problem.input_description }}</p>
</div>
<div class="problem-section">
<label class="problem-label">输出</label>
<p class="problem-detail">{{ problem.output_description }}</p>
</div>
{% for item in samples %}
<div class="problem-section">
<label class="problem-label">样例输入{{ forloop.counter }}</label>
<a href="javascript:void(0)" class="copy-sample" data-clipboard-text="{{ item.input }}">复制</a>
<pre>
{{ item.input }}</pre>
</div>
<div class="problem-section">
<label class="problem-label">样例输出{{ forloop.counter }}</label>
<pre>
{{ item.output }}</pre>
</div>
{% endfor %}
<div> <div>
<button type="button" id="show-more-btn" class="btn btn-default btn-sm">查看隐藏信息</button> <button type="button" id="show-more-btn" class="btn btn-default btn-sm">查看隐藏信息</button>
</div> </div>
@ -67,31 +39,7 @@
<div class="problem-detail">{{ problem.source }}</div> <div class="problem-detail">{{ problem.source }}</div>
</div> </div>
{% endif %} {% endif %}
<div> {% include "oj/problem/submit_problem.html" %}
<label>选择语言</label>
<div>
<label class="radio-inline">
<input type="radio" name="language" value="1" checked> C (GCC 4.8)
</label>
<label class="radio-inline">
<input type="radio" name="language" value="2"> C++ (G++ 4.3)
</label>
<label class="radio-inline">
<input type="radio" name="language" value="3"> Java (Oracle JDK 1.7)
</label>
</div>
</div>
<div id="code-field">
<label class="problem-label">提交代码</label>
<textarea id="code-editor"></textarea>
</div>
<hr>
<div id="submit-code">
<button type="button" class="btn btn-primary" id="submit-code-button">
提交代码
</button>
<img src="/static/img/loading.gif" id="loading-gif">
</div>
<div id="result"> <div id="result">
</div> </div>
<hr> <hr>

View File

@ -7,10 +7,19 @@
{% load submission %} {% load submission %}
<div class="container main"> <div class="container main">
<ul class="nav nav-tabs nav-tabs-google"> <ul class="nav nav-tabs nav-tabs-google">
<li role="presentation"> {% if problem.contest_id %}
<a href="/problem/{{ problem.id }}/">题目</a></li> <li role="presentation">
<li role="presentation" class="active"> <a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/">题目</a></li>
<a href="/problem/{{ problem.id }}/submissions/">我的提交</a></li> <li role="presentation" class="active">
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/submissions/">我的提交</a>
</li>
{% else %}
<li role="presentation">
<a href="/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation" class="active">
<a href="/problem/{{ problem.id }}/submissions/">我的提交</a>
</li>
{% endif %}
</ul> </ul>
{% include "oj/problem/_problem_header.html" %} {% include "oj/problem/_problem_header.html" %}
{% if submissions %} {% if submissions %}