Accept Merge Request #128 增加比赛排名的部分逻辑 : (virusdefender-dev -> dev)

Merge Request: 增加比赛排名的部分逻辑
Created By: @virusdefender
Accepted By: @virusdefender
URL: https://coding.net/u/virusdefender/p/qduoj/git/merge/128
This commit is contained in:
virusdefender 2015-08-25 12:50:38 +08:00
commit 4285e94553
40 changed files with 819 additions and 322 deletions

View File

@ -280,7 +280,7 @@ class LoginRequiredDecoratorTest(TestCase):
def test_cbv_without_args(self):
# 没登陆
response = self.client.get("/login_required_test/cbv/1/")
self.assertTemplateUsed(response, "utils/error.html")
self.assertRedirects(response, "/login/")
# 登陆后
self.client.login(username="test", password="test")
@ -353,7 +353,7 @@ class AdminRequiredDecoratorTest(TestCase):
def test_cbv_without_args(self):
# 没登陆
response = self.client.get("/admin_required_test/cbv/1/")
self.assertRedirects(response, "/login/")
self.assertTemplateUsed(response, "utils/error.html")
# 登陆后
self.client.login(username="test", password="test")

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,5 +1,6 @@
# coding=utf-8
import json
from django.test import TestCase, Client
from django.core.urlresolvers import reverse
from django.http import HttpResponse
@ -11,7 +12,7 @@ def middleware_test_func(request):
return HttpResponse(json.dumps({"code": 0}))
class AdminRequiredMidlewareTest(TestCase):
class AdminRequiredMiddlewareTest(TestCase):
urls = "admin.test_urls"
def setUp(self):
@ -53,7 +54,7 @@ class AdminRequiredMidlewareTest(TestCase):
self.assertEqual(json.loads(response.content), {"code": 1, "data": u"请先登录"})
self.client.login(username="test", password="test")
rresponse = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(json.loads(response.content), {"code": 1, "data": u"请先登录"})
self.client.logout()
@ -66,3 +67,21 @@ class AdminRequiredMidlewareTest(TestCase):
response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(json.loads(response.content)["code"], 0)
class AdminTemplateViewTest(TestCase):
def setUp(self):
super_admin_user = User.objects.create(username="test", admin_type=2)
super_admin_user.set_password("test")
super_admin_user.save()
self.client = Client()
self.client.login(username="test", password="test")
def test_file_exists(self):
response = self.client.get("/admin/template/index/index.html")
self.assertEqual(response.status_code, 200)
def test_file_does_not_exist(self):
response = self.client.get("/admin/template/index/index123.html")
self.assertEqual(response.status_code, 200)
self.assertHTMLEqual(response.content, u"模板不存在")

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -74,7 +74,7 @@ def check_user_contest_permission(func):
{"reason": "group_limited", "show_tab": False, "contest": contest})
# 比赛没有开始
if contest.start_time > now():
if contest.status == 1:
if request.is_ajax():
return error_response(u"比赛还没有开始")
else:

View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contest', '0005_contestsubmission'),
('contest', '0005_contestproblem_score'),
]
operations = [
]

View File

@ -1,5 +1,6 @@
# coding=utf-8
from django.db import models
from django.utils.timezone import now
from account.models import User
from problem.models import AbstractProblem
@ -34,6 +35,18 @@ class Contest(models.Model):
# 是否可见 false的话相当于删除
visible = models.BooleanField(default=True)
@property
def status(self):
if self.start_time > now():
# 没有开始 返回1
return 1
elif self.end_time < now():
# 已经结束 返回0
return -1
else:
# 正在进行 返回0
return 0
class Meta:
db_table = "contest"

View File

@ -2,17 +2,18 @@
import json
import datetime
from functools import wraps
from collections import OrderedDict
from django.utils.timezone import now
from django.shortcuts import render
from django.db import IntegrityError
from django.utils import dateparse
from django.db.models import Q
from django.db.models import Q, Count, Sum
from django.core.paginator import Paginator
from rest_framework.views import APIView
from utils.shortcuts import (serializer_invalid_response, error_response,
success_response, paginate, rand_str, error_page)
from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN
from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN, User
from account.decorators import login_required
from group.models import Group
from announcement.models import Announcement
@ -107,8 +108,6 @@ class ContestAdminAPIView(APIView):
return error_response(u"请至少选择一个小组")
if data["start_time"] >= data["end_time"]:
return error_response(u"比赛的开始时间不能晚于或等于比赛结束的时间")
if request.user.admin_type != SUPER_ADMIN and request.user != contest.created_by:
return error_response(u"你无权修改该比赛!")
contest.title = data["title"]
contest.description = data["description"]
contest.mode = data["mode"]
@ -133,10 +132,7 @@ class ContestAdminAPIView(APIView):
---
response_serializer: ContestSerializer
"""
if request.user.admin_type == SUPER_ADMIN:
contest = Contest.objects.all().order_by("-last_updated_time")
else:
contest = Contest.objects.filter(created_by=request.user).order_by("-last_updated_time")
visible = request.GET.get("visible", None)
if visible:
contest = contest.filter(visible=(visible == "true"))
@ -173,8 +169,7 @@ class ContestProblemAdminAPIView(APIView):
created_by=request.user,
hint=data["hint"],
contest=contest,
sort_index=data["sort_index"],
score=data["score"])
sort_index=data["sort_index"])
return success_response(ContestProblemSerializer(contest_problem).data)
else:
return serializer_invalid_response(serializer)
@ -189,14 +184,10 @@ class ContestProblemAdminAPIView(APIView):
serializer = EditContestProblemSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
try:
contest_problem = ContestProblem.objects.get(id=data["id"])
except ContestProblem.DoesNotExist:
return error_response(u"该比赛题目不存在!")
contest = Contest.objects.get(id=contest_problem.contest_id)
if request.user.admin_type != SUPER_ADMIN and contest.created_by != request.user:
return error_response(u"你无权修改该题目!")
contest_problem.title = data["title"]
contest_problem.description = data["description"]
contest_problem.input_description = data["input_description"]
@ -208,7 +199,6 @@ class ContestProblemAdminAPIView(APIView):
contest_problem.hint = data["hint"]
contest_problem.visible = data["visible"]
contest_problem.sort_index = data["sort_index"]
contest_problem.score = data["score"]
contest_problem.save()
return success_response(ContestProblemSerializer(contest_problem).data)
else:
@ -227,10 +217,7 @@ class ContestProblemAdminAPIView(APIView):
return success_response(ContestProblemSerializer(contest_problem).data)
except ContestProblem.DoesNotExist:
return error_response(u"比赛题目不存在")
if request.user.admin_type == SUPER_ADMIN:
contest_problem = ContestProblem.objects.all().order_by("sort_index")
else:
contest_problem = ContestProblem.objects.filter(created_by=request.user).order_by("sort_index")
visible = request.GET.get("visible", None)
if visible:
contest_problem = contest_problem.filter(visible=(visible == "true"))
@ -238,13 +225,6 @@ class ContestProblemAdminAPIView(APIView):
if keyword:
contest_problem = contest_problem.filter(Q(title__contains=keyword) |
Q(description__contains=keyword))
contest_id = request.GET.get("contest_id", None)
if contest_id:
try:
contest = Contest.objects.get(id=contest_id)
except Contest.DoesNotExist:
return error_response(u"该比赛不存在!")
contest_problem = contest_problem.filter(contest=contest).order_by("sort_index")
return paginate(request, contest_problem, ContestProblemSerializer)
@ -276,6 +256,9 @@ class ContestPasswordVerifyAPIView(APIView):
@check_user_contest_permission
def contest_page(request, contest_id):
"""
单个比赛的详情页
"""
try:
contest = Contest.objects.get(id=contest_id)
except Contest.DoesNotExist:
@ -286,6 +269,9 @@ def contest_page(request, contest_id):
@check_user_contest_permission
def contest_problem_page(request, contest_id, contest_problem_id):
"""
单个比赛题目的详情页
"""
try:
contest = Contest.objects.get(id=contest_id)
except Contest.DoesNotExist:
@ -294,19 +280,28 @@ def contest_problem_page(request, contest_id, contest_problem_id):
contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True)
except ContestProblem.DoesNotExist:
return error_page(request, u"比赛题目不存在")
warning = "您已经提交过本题的正确答案!"
show_warning = False
try:
submission = ContestSubmission.objects.get(user=request.user, contest=contest, problem=contest_problem)
show_warning = submission.ac
except ContestSubmission.DoesNotExist:
pass
return render(request, "oj/contest/contest_problem.html", {"contest_problem": contest_problem,
# 已经结束
if contest.status == -1:
show_warning = True
warning = "比赛已经结束!"
return render(request, "oj/contest/contest_problem.html", {"contest_problem": contest_problem, "contest": contest,
"samples": json.loads(contest_problem.samples),
"show_warning": show_warning})
"show_warning": show_warning, "warning": warning})
@check_user_contest_permission
def contest_problems_list_page(request, contest_id):
"""
比赛所有题目的列表页
"""
try:
contest_problems = ContestProblem.objects.filter(contest=Contest.objects.get(id=contest_id)).order_by("sort_index")
except Contest.DoesNotExist:
@ -319,6 +314,9 @@ def contest_problems_list_page(request, contest_id):
def contest_list_page(request, page=1):
"""
所有比赛的列表页
"""
# 正常情况
contests = Contest.objects.filter(visible=True)
@ -360,3 +358,57 @@ def contest_list_page(request, page=1):
"keyword": keyword, "announcements": announcements,
"join": join})
def _cmp(x, y):
if x["total_ac"] > y["total_ac"]:
return 1
elif x["total_ac"] < y["total_ac"]:
return -1
else:
if x["total_time"] < y["total_time"]:
return 1
else:
return -1
@check_user_contest_permission
def contest_rank_page(request, contest_id):
result = ContestSubmission.objects.values("user_id").annotate(total_submit=Count("user_id"))
for i in range(0, len(result)):
# 这个人所有的提交
submissions = ContestSubmission.objects.filter(user_id=result[i]["user_id"])
result[i]["total_ac"] = submissions.filter(ac=True).count()
result[i]["user"] = User.objects.get(id=result[i]["user_id"])
result[i]["submissions"] = submissions.order_by("problem__sort_index")
result[i]["total_time"] = submissions.filter(ac=True).aggregate(total_time=Sum("total_time"))["total_time"]
print result
return render(request, "oj/contest/contest_rank.html")
#
#
# return
# contest = Contest.objects.get(id=contest_id)
# contest_submissions = ContestSubmission.objects.filter(contest=contest)
# result = {}
# # 先把数据按照用户id 为 key 整理一下
# # {1: {"submissions": [], "total_time": 0, "total_ac": 0}}
# for item in contest_submissions:
# if item.user.id not in contest_submissions:
# result[item.user.id] = {"user": {"id": item.user.id, "username": item.user.username,
# "real_name": item.user.real_name},
# "submissions": [], "total_time": 0, "total_ac": 0}
# result[item.user.id]["submissions"].append(ContestSubmissionSerializer(item).data)
# if item.ac:
# result[item.user.id]["total_time"] += item.total_time
# result[item.user.id]["total_ac"] += 1
# l = []
# for k, v in result.iteritems():
# l.append(v)
# print sorted(l, cmp=_cmp, reverse=True)

View File

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,11 @@
# coding=utf-8
from rest_framework import serializers
from account.models import User
class CreateContestSubmissionSerializer(serializers.Serializer):
contest_id = serializers.IntegerField()
problem_id = serializers.IntegerField()
language = serializers.IntegerField()
code = serializers.CharField(max_length=3000)

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

115
contest_submission/views.py Normal file
View File

@ -0,0 +1,115 @@
# coding=utf-8
import json
import redis
from django.shortcuts import render
from django.core.paginator import Paginator
from rest_framework.views import APIView
from judge.judger_controller.tasks import judge
from judge.judger_controller.settings import redis_config
from account.decorators import login_required
from account.models import SUPER_ADMIN
from contest.decorators import check_user_contest_permission
from problem.models import Problem
from contest.models import Contest, ContestProblem
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page, paginate
from submission.models import Submission
from .serializers import CreateContestSubmissionSerializer
class ContestSubmissionAPIView(APIView):
@check_user_contest_permission
def post(self, request):
"""
创建比赛的提交
---
request_serializer: CreateContestSubmissionSerializer
"""
serializer = CreateContestSubmissionSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
try:
contest = Contest.objects.get(id=data["contest_id"])
except Contest.DoesNotExist:
return error_response(u"比赛不存在")
try:
problem = ContestProblem.objects.get(contest=contest, id=data["problem_id"])
# 更新题目提交计数器
problem.total_submit_number += 1
problem.save()
except Problem.DoesNotExist:
return error_response(u"题目不存在")
submission = Submission.objects.create(user_id=request.user.id, language=int(data["language"]),
contest_id=contest.id, code=data["code"], problem_id=problem.id)
try:
judge.delay(submission.id, problem.time_limit, problem.memory_limit, problem.test_case_id)
except Exception:
return error_response(u"提交判题任务失败")
# 增加redis 中判题队列长度的计数器
r = redis.Redis(host=redis_config["host"], port=redis_config["port"], db=redis_config["db"])
r.incr("judge_queue_length")
return success_response({"submission_id": submission.id})
else:
return serializer_invalid_response(serializer)
@login_required
def contest_problem_my_submissions_list_page(request, contest_id, contest_problem_id):
"""
我比赛单个题目的所有提交列表
"""
try:
Contest.objects.get(id=contest_id)
except Contest.DoesNotExist:
return error_page(request, u"比赛不存在")
try:
contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True)
except Problem.DoesNotExist:
return error_page(request, u"比赛问题不存在")
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=contest_problem.id).order_by("-create_time"). \
values("id", "result", "create_time", "accepted_answer_time", "language")
return render(request, "oj/contest/my_submissions_list.html",
{"submissions": submissions, "problem": contest_problem})
@login_required
def contest_problem_submissions_list_page(request, contest_id, page=1):
"""
单个比赛中的所有提交包含自己和别人自己可查提交结果其他人不可查
"""
try:
contest = Contest.objects.get(id=contest_id)
except Contest.DoesNotExist:
return error_page(request, u"比赛不存在")
# 以下是本场比赛中所有的提交
submissions = Submission.objects.filter(contest_id=contest_id). \
values("id", "result", "create_time", "accepted_answer_time", "language", "user_id").order_by("-create_time")
paginator = Paginator(submissions, 20)
try:
current_page = paginator.page(int(page))
except Exception:
return error_page(request, u"不存在的页码")
previous_page = next_page = None
try:
previous_page = current_page.previous_page_number()
except Exception:
pass
try:
next_page = current_page.next_page_number()
except Exception:
pass
return render(request, "oj/contest/submissions_list.html",
{"submissions": current_page, "page": int(page),
"previous_page": previous_page, "next_page": next_page, "start_id": int(page) * 20 - 20,
"contest": contest})

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -75,10 +75,8 @@ class MessageQueue(object):
except ContestSubmission.DoesNotExist:
# 第一次提交
is_ac = submission.result == result["accepted"]
# 增加题目总提交数计数器
contest_problem.total_submit_number += 1
if is_ac:
total_time = 0
total_time = int((submission.create_time - contest.start_time).total_seconds() / 60)
# 增加题目总的ac数计数器
contest_problem.total_accepted_number += 1
contest_problem.save()

View File

@ -54,6 +54,7 @@ INSTALLED_APPS = (
'submission',
'mq',
'contest',
'contest_submission',
'django_extensions',
'rest_framework',

View File

@ -16,48 +16,44 @@ from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView,
from admin.views import AdminTemplateView
from problem.views import TestCaseUploadAPIView, ProblemTagAdminAPIView, ProblemAdminAPIView
from submission.views import SubmissionAPIView, SubmissionAdminAPIView, ContestSubmissionAPIView
from submission.views import SubmissionAPIView, SubmissionAdminAPIView
from contest_submission.views import ContestSubmissionAPIView
from monitor.views import QueueLengthMonitorAPIView
from contest_submission.views import contest_problem_my_submissions_list_page
urlpatterns = [
url(r'^install/$', "install.views.install"),
url("^$", TemplateView.as_view(template_name="oj/index.html"), name="index_page"),
url(r'^docs/', include('rest_framework_swagger.urls')),
url(r'^admin/$', TemplateView.as_view(template_name="admin/admin.html"), name="admin_spa_page"),
url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"),
name="add_contest_page"),
url(r'^admin/template/(?P<template_dir>\w+)/(?P<template_name>\w+).html$', AdminTemplateView.as_view(),
name="admin_template"),
url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"),
url(r'^register/$', TemplateView.as_view(template_name="oj/account/register.html"),
name="user_register_page"),
url(r'^change_password/$', TemplateView.as_view(template_name="oj/account/change_password.html"),
name="user_change_password_page"),
url(r'^announcement/(?P<announcement_id>\d+)/$', "announcement.views.announcement_page",
name="announcement_page"),
url(r'^api/user/$', UserInfoAPIView.as_view(), name="user_info_api"),
url(r'^api/login/$', UserLoginAPIView.as_view(), name="user_login_api"),
url(r'^api/register/$', UserRegisterAPIView.as_view(), name="user_register_api"),
url(r'^api/change_password/$', UserChangePasswordAPIView.as_view(), name="user_change_password_api"),
url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"),
url(r'^api/email_check/$', EmailCheckAPIView.as_view(), name="email_check_api"),
url(r'^api/contest/password/$', ContestPasswordVerifyAPIView.as_view(), name="contest_password_verify_api"),
url(r'^api/contest/submission/$', ContestSubmissionAPIView.as_view(), name="contest_submission_api"),
url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"),
url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"),
url(r'^api/admin/contest/$', ContestAdminAPIView.as_view(), name="contest_admin_api"),
url(r'^api/admin/user/$', UserAdminAPIView.as_view(), name="user_admin_api"),
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
url(r'^contest/(?P<contest_id>\d+)/problem/(?P<contest_problem_id>\d+)/$', "contest.views.contest_problem_page",
name="contest_problem_page"),
url(r'^contest/(?P<contest_id>\d+)/$', "contest.views.contest_page", name="contest_page"),
url(r'^contest/(?P<contest_id>\d+)/problems/$', "contest.views.contest_problems_list_page",
name="contest_problems_list_page"),
url(r'^announcement/(?P<announcement_id>\d+)/$', "announcement.views.announcement_page",
name="announcement_page"),
url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"),
name="add_contest_page"),
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
url(r'^problems/(?P<page>\d+)/$', "problem.views.problem_list_page", name="problem_list_page"),
url(r'^contests/$', "contest.views.contest_list_page", name="contest_list_page"),
url(r'^contests/(?P<page>\d+)/$', "contest.views.contest_list_page", name="contest_list_page"),
url(r'^admin/template/(?P<template_dir>\w+)/(?P<template_name>\w+).html$', AdminTemplateView.as_view(),
name="admin_template"),
url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"),
url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"),
url(r'^api/admin/group_join/$', JoinGroupAPIView.as_view(), name="group_join_admin_api"),
@ -65,23 +61,44 @@ urlpatterns = [
url(r'^api/admin/contest_problem/$', ContestProblemAdminAPIView.as_view(), name="contest_problem_admin_api"),
url(r'^api/admin/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"),
url(r'^api/admin/tag/$', ProblemTagAdminAPIView.as_view(), name="problem_tag_admin_api"),
url(r'^problem/(?P<problem_id>\d+)/my_submissions/$', "submission.views.problem_my_submissions_list_page",
name="problem_my_submissions_page"),
url(r'^contest/(?P<contest_id>\d+)/problem/(?P<contest_problem_id>\d+)/my_submissions/$',
"submission.views.contest_problem_my_submissions_list_page", name="contest_problem_my_submissions_list_page"),
url(r'^my_submission/(?P<submission_id>\w+)/$', "submission.views.my_submission", name="my_submission_page"),
url(r'^api/admin/join_group_request/$', JoinGroupRequestAdminAPIView.as_view(),
name="join_group_request_admin_api"),
url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"),
url(r'^api/admin/submission/$', SubmissionAdminAPIView.as_view(), name="submission_admin_api_view"),
url(r'^my_submissions/$', "submission.views.my_submission_list_page", name="my_submission_list_page"),
url(r'^my_submissions/(?P<page>\d+)/$', "submission.views.my_submission_list_page", name="my_submission_list_page"),
url(r'^api/admin/monitor/$', QueueLengthMonitorAPIView.as_view(), name="queue_length_monitor_api"),
url(r'^contest/(?P<contest_id>\d+)/problem/(?P<contest_problem_id>\d+)/$', "contest.views.contest_problem_page",
name="contest_problem_page"),
url(r'^contest/(?P<contest_id>\d+)/problem/(?P<contest_problem_id>\d+)/submissions/$',
"contest_submission.views.contest_problem_my_submissions_list_page",
name="contest_problem_my_submissions_list_page"),
url(r'^contest/(?P<contest_id>\d+)/$', "contest.views.contest_page", name="contest_page"),
url(r'^api/contest/password/$', ContestPasswordVerifyAPIView.as_view(), name="contest_password_verify_api"),
url(r'^api/contest/submission/$', ContestSubmissionAPIView.as_view(), name="contest_submission_api"),
url(r'^contest/(?P<contest_id>\d+)/problems/$', "contest.views.contest_problems_list_page",
name="contest_problems_list_page"),
url(r'^contest/(?P<contest_id>\d+)/submissions/$', "contest_submission.views.contest_problem_submissions_list_page",
name="contest_problem_submissions_list_page"),
url(r'^contest/(?P<contest_id>\d+)/submissions/(?P<page>\d+)/$',
"contest_submission.views.contest_problem_submissions_list_page", name="contest_problem_submissions_list_page"),
url(r'^contests/$', "contest.views.contest_list_page", name="contest_list_page"),
url(r'^contests/(?P<page>\d+)/$', "contest.views.contest_list_page", name="contest_list_page"),
url(r'^contest/(?P<contest_id>\d+)/$', "contest.views.contest_page", name="contest_page"),
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
url(r'^problems/(?P<page>\d+)/$', "problem.views.problem_list_page", name="problem_list_page"),
url(r'^problem/(?P<problem_id>\d+)/submissions/$', "submission.views.problem_my_submissions_list_page",
name="problem_my_submissions_page"),
url(r'^submission/(?P<submission_id>\w+)/$', "submission.views.my_submission", name="my_submission_page"),
url(r'^submissions/$', "submission.views.my_submission_list_page", name="my_submission_list_page"),
url(r'^submissions/(?P<page>\d+)/$', "submission.views.my_submission_list_page", name="my_submission_list_page"),
url(r'^contest/(?P<contest_id>\d+)/rank/$', "contest.views.contest_rank_page", name="contest_rank_page")
]

View File

@ -90,5 +90,5 @@ li.list-group-item {
}
.contest-tab{
margin-bottom: 5px;
margin-bottom: 15px;
}

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -22,8 +22,3 @@ class SubmissionSerializer(serializers.ModelSerializer):
return User.objects.get(id=obj.user_id).username
class CreateContestSubmissionSerializer(serializers.Serializer):
contest_id = serializers.IntegerField()
problem_id = serializers.IntegerField()
language = serializers.IntegerField()
code = serializers.CharField(max_length=3000)

View File

@ -1,5 +1,10 @@
# coding=utf-8
import json
from django.test import TestCase
from account.models import User, REGULAR_USER
from django.core.urlresolvers import reverse
from account.models import User, REGULAR_USER, ADMIN, SUPER_ADMIN
from problem.models import Problem
from contest.models import Contest
from submission.models import Submission
from rest_framework.test import APITestCase, APIClient
@ -12,6 +17,7 @@ class SubmissionsListPageTest(TestCase):
self.user2.set_password("666666")
self.user.set_password("666666")
self.user.save()
self.user2.save()
# self.client.login(username="gogoing", password="666666")
self.submission = Submission.objects.create(user_id=self.user.id,
language=1,
@ -20,25 +26,121 @@ class SubmissionsListPageTest(TestCase):
def test_visit_submissionsListPage_successfully(self):
self.client.login(username="gogoing", password="666666")
response = self.client.get('/my_submissions/1/')
response = self.client.get('/submissions/1/')
self.assertEqual(response.status_code, 200)
def test_visit_submissionsListPage_without_page_successfully(self):
self.client.login(username="gogoing", password="666666")
response = self.client.get('/my_submissions/')
response = self.client.get('/submissions/')
self.assertEqual(response.status_code, 200)
def test_submissionsListPage_does_not_exist(self):
self.client.login(username="gogoing", password="666666")
response = self.client.get('/my_submissions/5/')
response = self.client.get('/submissions/5/')
self.assertTemplateUsed(response, "utils/error.html")
def test_submissionsListPage_page_not_exist(self):
self.client.login(username="gogoing", password="666666")
response = self.client.get('/my_submissions/5/')
response = self.client.get('/submissions/5/')
self.assertTemplateUsed(response, "utils/error.html")
def test_submissionsListPage_have_no_submission(self):
self.client.login(username="cool", password="666666")
response = self.client.get('/my_submissions/')
response = self.client.get('/submissions/')
self.assertEqual(response.status_code, 200)
class SubmissionAPITest(APITestCase):
def setUp(self):
self.client = APIClient()
self.url = reverse('submission_api')
self.user1 = User.objects.create(username="test1", admin_type=REGULAR_USER)
self.user1.set_password("testaa")
self.user1.save()
self.user2 = User.objects.create(username="test2", admin_type=SUPER_ADMIN)
self.user2.set_password("testbb")
self.user2.save()
self.problem = Problem.objects.create(title="title1",
description="description1",
input_description="input1_description",
output_description="output1_description",
test_case_id="1",
source="source1",
samples=json.dumps([{"input": "1 1", "output": "2"}]),
time_limit=100,
memory_limit=1000,
difficulty=1,
hint="hint1",
created_by=User.objects.get(username="test2"))
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
end_time="2015-08-15T12:00:00.000Z",
password="aacc", created_by=User.objects.get(username="test2"))
self.submission = Submission.objects.create(user_id=self.user1.id,
language=1,
code='#include "stdio.h"\nint main(){\n\treturn 0;\n}',
problem_id=self.problem.id)
def test_invalid_format(self):
self.client.login(username="test1", password="testaa")
data = {"language": 1}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_problem_does_not_exist(self):
self.client.login(username="test1", password="testaa")
data = {"language": 1, "code": '#include "stdio.h"\nint main(){\n\treturn 0;\n}',
"problem_id": self.problem.id + 10}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"题目不存在"})
def test_submission_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"language": 1, "code": '#include "stdio.h"\nint main(){\n\treturn 0;\n}',
"problem_id": self.problem.id}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 0)
def test_submission_does_not_exist(self):
self.client.login(username="test1", password="testaa")
data = {"submission_id": self.submission.id + "111"}
response = self.client.get(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"提交不存在"})
def test_get_submission_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"submission_id": self.submission.id}
response = self.client.get(self.url, data=data)
self.assertEqual(response.data["code"], 0)
class ContestSubmissionAPITest(APITestCase):
def setUp(self):
self.client = APIClient()
self.url = reverse('contest_submission_api')
self.user1 = User.objects.create(username="test1", admin_type=REGULAR_USER)
self.user1.set_password("testaa")
self.user1.save()
self.user2 = User.objects.create(username="test2", admin_type=SUPER_ADMIN)
self.user2.set_password("testbb")
self.user2.save()
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
end_time="2015-08-15T12:00:00.000Z",
password="aacc", created_by=User.objects.get(username="test2"))
def test_invalid_format(self):
self.client.login(username="test1", password="testaa")
data = {"language": 1}
response = self.client.post(self.url, data=data)
pass

View File

@ -19,7 +19,7 @@ from contest.models import Contest, ContestProblem
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page, paginate
from .models import Submission
from .serializers import CreateSubmissionSerializer, SubmissionSerializer, CreateContestSubmissionSerializer
from .serializers import CreateSubmissionSerializer, SubmissionSerializer
class SubmissionAPIView(APIView):
@ -73,34 +73,24 @@ class SubmissionAPIView(APIView):
@login_required
def problem_my_submissions_list_page(request, problem_id):
"""
我单个题目所有提交的列表页
"""
try:
problem = Problem.objects.get(id=problem_id, visible=True)
except Problem.DoesNotExist:
return error_page(request, u"问题不存在")
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=problem.id).order_by("-create_time"). \
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=problem.id, contest_id__isnull=True).order_by("-create_time"). \
values("id", "result", "create_time", "accepted_answer_time", "language")
return render(request, "oj/problem/my_submissions_list.html",
{"submissions": submissions, "problem": problem})
@login_required
def contest_problem_my_submissions_list_page(request, contest_id, contest_problem_id):
try:
Contest.objects.get(id=contest_id)
except Contest.DoesNotExist:
return error_page(request, u"比赛不存在")
try:
contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True)
except Problem.DoesNotExist:
return error_page(request, u"比赛问题不存在")
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=contest_problem.id).order_by("-create_time"). \
values("id", "result", "create_time", "accepted_answer_time", "language")
return render(request, "oj/contest/my_submissions_list.html",
{"submissions": submissions, "contest_problem": contest_problem})
@login_required
def my_submission(request, submission_id):
"""
单个题目的提交详情页
"""
try:
# 超级管理员可以查看所有的提交
if request.user.admin_type != SUPER_ADMIN:
@ -110,10 +100,18 @@ def my_submission(request, submission_id):
except Submission.DoesNotExist:
return error_page(request, u"提交不存在")
if submission.contest_id:
try:
problem = ContestProblem.objects.get(id=submission.problem_id,
visible=True)
except ContestProblem.DoesNotExist:
return error_page(request, u"提交不存在")
else:
try:
problem = Problem.objects.get(id=submission.problem_id, visible=True)
except Problem.DoesNotExist:
return error_page(request, u"提交不存在")
if submission.info:
try:
info = json.loads(submission.info)
@ -136,6 +134,9 @@ class SubmissionAdminAPIView(APIView):
@login_required
def my_submission_list_page(request, page=1):
"""
我的所有提交的列表页
"""
submissions = Submission.objects.filter(user_id=request.user.id). \
values("id", "result", "create_time", "accepted_answer_time", "language").order_by("-create_time")
paginator = Paginator(submissions, 20)
@ -156,43 +157,3 @@ def my_submission_list_page(request, page=1):
return render(request, "oj/submission/my_submissions_list.html",
{"submissions": current_page, "page": int(page),
"previous_page": previous_page, "next_page": next_page, "start_id": int(page) * 20 - 20})
class ContestSubmissionAPIView(APIView):
@check_user_contest_permission
def post(self, request):
"""
创建比赛的提交
---
request_serializer: CreateContestSubmissionSerializer
"""
serializer = CreateContestSubmissionSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
try:
contest = Contest.objects.get(id=data["contest_id"])
except Contest.DoesNotExist:
return error_response(u"比赛不存在")
try:
problem = ContestProblem.objects.get(contest=contest, id=data["problem_id"])
# 更新题目提交计数器
problem.total_submit_number += 1
problem.save()
except Problem.DoesNotExist:
return error_response(u"题目不存在")
submission = Submission.objects.create(user_id=request.user.id, language=int(data["language"]),
contest_id=contest.id, code=data["code"], problem_id=problem.id)
try:
judge.delay(submission.id, problem.time_limit, problem.memory_limit, problem.test_case_id)
except Exception:
return error_response(u"提交判题任务失败")
# 增加redis 中判题队列长度的计数器
r = redis.Redis(host=redis_config["host"], port=redis_config["port"], db=redis_config["db"])
r.incr("judge_queue_length")
return success_response({"submission_id": submission.id})
else:
return serializer_invalid_response(serializer)

View File

@ -1,4 +1,3 @@
{% extends 'oj_base.html' %}
{% block body %}
@ -6,7 +5,7 @@
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation" class="active">
<a href="/contest/{{ contest_problem.contest.id }}/problem/{{ contest_problem.id }}/">题目</a></li>
<li role="presentation"><a href="/contest/{{ contest_problem.contest.id }}/problem/{{ contest_problem.id }}/my_submissions/">我的提交</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>
@ -15,6 +14,15 @@
内存限制 : {{ contest_problem.memory_limit }}M
</p>
<div>
<div class="problem-section">
<label class="problem-label">描述</label>
<p class="problem-detail">{{ contest_problem.description|safe }}</p>
</div>
<div class="problem-section">
<label class="problem-label">输入</label>
<div>
<div class="problem-section">
<label class="problem-label">描述</label>
@ -60,6 +68,7 @@
</div>
{% endif %}
{% ifequal contest.status 0 %}
<div>
<label>选择语言</label>
@ -89,8 +98,10 @@
<img src="/static/img/loading.gif" id="loading-gif">
</div>
{% endifequal %}
{% if show_warning %}
<div class="alert alert-success" role="alert">您已经提交过本题的正确答案了!</div>
<div class="alert alert-success" role="alert">{{ warning }}</div>
{% endif %}
<div id="result">

View File

@ -21,10 +21,12 @@
<a href="/contest/{{ contest.id }}/rank/">排名</a>
</li>
</ul>
</div>
<div class="col-lg-9">
<div class="col-lg-9">
<div>
<table class="table table-striped">
<thead>
@ -38,9 +40,7 @@
<tbody>
{% for item in contest_problems %}
<tr>
<th>
<span class="glyphicon glyphicon-ok ac-flag"></span>
</th>
<th><span class="glyphicon glyphicon-ok ac-flag"></span></th>
<th scope="row">
<a href="/contest/{{ item.contest.id }}/problem/{{ item.id }}/" target="_blank">{{ item.sort_index }}</a>
</th>
@ -52,27 +52,12 @@
{% endfor %}
</tbody>
</table>
<nav>
<ul class="pager">
{% if previous_page %}
<li class="previous"><a
href="/problems/{{ previous_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">
<span aria-hidden="true">&larr;</span> 上一页</a></li>
{% endif %}
{% if next_page %}
<li class="next"><a
href="/problems/{{ next_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">下一页 <span
aria-hidden="true">&rarr;</span></a></li>
{% endif %}
</ul>
</nav>
</div>
</div>
<div class="col-lg-3">
{% include "oj/announcement/_announcement_panel.html" %}
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,30 @@
{% extends "oj_base.html" %}
{% block body %}
{% load contest %}
<div class="container main">
<div class="col-lg-12 contest-tab">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation" class="active">
<a href="/contest/{{ contest.id }}/">比赛详情</a>
</li>
<li role="presentation">
<a href="/contest/{{ contest.id }}/problems/">题目</a>
</li>
<li role="presentation">
<a href="/contest/{{ contest.id }}/submissions/">提交</a>
</li>
<li role="presentation">
<a href="/contest/{{ contest.id }}/rank/">排名</a>
</li>
</ul>
</div>
<div class="row">
<div class="col-lg-12">
</div>
</div>
</div>
{% endblock %}
{% block js_block %}
{% endblock %}

View File

@ -0,0 +1,71 @@
{% extends 'oj_base.html' %}
{% 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

@ -6,17 +6,13 @@
<div class="container main">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation">
<a href="/contest/{{ contest_problem.contest.id }}/problem/{{ contest_problem.id }}/">题目</a></li>
<a href="/contest/{{ problem.contest.id }}/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation" class="active">
<a href="/contest/{{ contest_problem.contest.id }}/problem/{{ contest_problem.id }}/my_submissions/">
<a href="/contest/{{ problem.contest.id }}/problem/{{ 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>
{% include "oj/problem/_problem_header.html" %}
<table class="table table-bordered">
<thead>
<tr class="" success>
@ -30,7 +26,7 @@
<tbody>
{% for item in submissions %}
<tr class="{{ item.result|translate_result_class }}">
<th scope="row"><a href="/my_submission/{{ item.id }}/">{{ forloop.counter }}</a></th>
<th scope="row"><a href="/submission/{{ item.id }}/">{{ forloop.counter }}</a></th>
<td>{{ item.create_time }}</td>
<td>{{ item.result|translate_result }}</td>
<td>

View File

@ -0,0 +1,84 @@
{% extends 'oj_base.html' %}
{% block body %}
{% load submission %}
{% load user %}
<div class="container main">
<div class="contest-tab">
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation">
<a href="/contest/{{ contest.id }}/">比赛详情</a>
</li>
<li role="presentation">
<a href="/contest/{{ contest.id }}/problems/">题目</a>
</li>
<li role="presentation" class="active">
<a href="/contest/{{ contest.id }}/submissions/">提交</a>
</li>
<li role="presentation">
<a href="/contest/{{ contest.id }}/rank/">排名</a>
</li>
</ul>
</div>
{% if submissions %}
<table class="table table-bordered">
<thead>
<tr class="" success>
<th>#</th>
<td>用户</td>
<th>提交时间</th>
<th>结果</th>
<th>运行时间</th>
<th>语言</th>
</tr>
</thead>
<tbody>
{% for item in submissions %}
<tr class="{{ item.result|translate_result_class }}">
{% ifequal item.user_id request.user.id %}
<th scope="row"><a href="/submission/{{ item.id }}/" id="id_{{ forloop.counter }}">
{{ forloop.counter |add:start_id }}</a></th>
{% else %}
<th scope="row">{{ forloop.counter |add:start_id }}</th>
{% endifequal %}
<td>{{ item.user_id|get_username }}</td>
<td>{{ item.create_time }}</td>
<td>{{ item.result|translate_result }}</td>
<td>
{% if item.accepted_answer_time %}
{{ item.accepted_answer_time }}ms
{% else %}
--
{% endif %}
</td>
<td>
{{ item.language|translate_language }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>你还没有提交记录!</p>
{% endif %}
<nav>
<ul class="pager">
{% if previous_page %}
<li class="previous"><a
href="/contest/{{ contest.id }}/submissions/{{ previous_page }}/">
<span aria-hidden="true">&larr;</span> 上一页</a></li>
{% endif %}
{% if next_page %}
<li class="next">
<a href="/contest/{{ contest.id }}/submissions/{{ next_page }}/">下一页 <span
aria-hidden="true">&rarr;</span></a></li>
{% endif %}
</ul>
</nav>
</div>
{% endblock %}

View File

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

View File

@ -8,13 +8,9 @@
<li role="presentation">
<a href="/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation" class="active">
<a href="/problem/{{ problem.id }}/my_submissions/">我的提交</a></li>
<a href="/problem/{{ problem.id }}/submissions/">我的提交</a></li>
</ul>
<h2 class="text-center">{{ problem.title }}</h2>
<p class="text-muted text-center">发布时间: {{ problem.create_time }}&nbsp;&nbsp;
时间限制: {{ problem.time_limit }}ms&nbsp;&nbsp;
内存限制: {{ problem.memory_limit }}M</p>
{% include "oj/problem/_problem_header.html" %}
<table class="table table-bordered">
<thead>
<tr class="" success>
@ -28,7 +24,7 @@
<tbody>
{% for item in submissions %}
<tr class="{{ item.result|translate_result_class }}">
<th scope="row"><a href="/my_submission/{{ item.id }}/">{{ forloop.counter }}</a></th>
<th scope="row"><a href="/submission/{{ item.id }}/">{{ forloop.counter }}</a></th>
<td>{{ item.create_time }}</td>
<td>{{ item.result|translate_result }}</td>
<td>

View File

@ -5,7 +5,7 @@
<ul class="nav nav-tabs nav-tabs-google">
<li role="presentation" class="active">
<a href="/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation"><a href="/problem/{{ problem.id }}/my_submissions/">我的提交</a></li>
<li role="presentation"><a href="/problem/{{ problem.id }}/submissions/">我的提交</a></li>
</ul>
{% include "oj/problem/_problem_header.html" %}

View File

@ -44,12 +44,12 @@
<ul class="pager">
{% if previous_page %}
<li class="previous"><a
href="/my_submissions/{{ previous_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">
href="/submissions/{{ previous_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">
<span aria-hidden="true">&larr;</span> 上一页</a></li>
{% endif %}
{% if next_page %}
<li class="next"><a
href="/my_submissions/{{ next_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">下一页 <span
href="/submissions/{{ next_page }}/{% if keyword %}?keyword={{ keyword }}{% endif %}{% if tag %}?tag={{ tag }}{% endif %}">下一页 <span
aria-hidden="true">&rarr;</span></a></li>
{% endif %}
</ul>

View File

@ -43,7 +43,7 @@
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/problems/">题目</a></li>
<li><a href="/my_submissions/">提交</a></li>
<li><a href="/submissions/">提交</a></li>
<li><a href="/contests/">比赛</a></li>
<li><a href="/about/">关于</a></li>
</ul>

View File

@ -4,18 +4,22 @@ from django.utils.timezone import now
def get_contest_status(contest):
if contest.start_time > now():
status = contest.status
if status == 1:
return "没有开始"
if contest.end_time < now():
elif status == -1:
return "已经结束"
else:
return "正在进行"
def get_contest_status_color(contest):
if contest.start_time > now():
status = contest.status
if status == 1:
return "info"
if contest.end_time < now():
elif status == -1:
return "warning"
else:
return "success"

View File

@ -0,0 +1,17 @@
# coding=utf-8
import datetime
from account.models import User
def get_username(user_id):
try:
return User.objects.get(id=user_id).username
except User.DoesNotExist:
return ""
from django import template
register = template.Library()
register.filter("get_username", get_username)