From 83124f3c866a7657b8120034b6d83e1bb2b37fbc Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sat, 19 Sep 2015 18:46:03 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C=E7=94=A8=E6=88=B7=E4=B8=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E5=AF=BC=E8=87=B4=E7=9A=84=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/serializers.py | 2 +- account/views.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index f60e9cac..c2852a3c 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -7,7 +7,7 @@ from .models import User class UserLoginSerializer(serializers.Serializer): username = serializers.CharField(max_length=30) password = serializers.CharField(max_length=30) - captcha = serializers.CharField(required=False,min_length=4,max_length=4) + captcha = serializers.CharField(required=False, min_length=4, max_length=4) class UsernameCheckSerializer(serializers.Serializer): diff --git a/account/views.py b/account/views.py index 8a3414f3..c482aeae 100644 --- a/account/views.py +++ b/account/views.py @@ -26,17 +26,15 @@ class UserLoginAPIView(APIView): serializer = UserLoginSerializer(data=request.data) if serializer.is_valid(): data = serializer.data - user = User.objects.get(username=data["username"]) - # 只有管理员才适用验证码登录 - if user.admin_type > 0: - if not "captcha" in data: - return error_response(u"请填写验证码!") - captcha = Captcha(request) - if not captcha.check(data["captcha"]): - return error_response(u"验证码错误") user = auth.authenticate(username=data["username"], password=data["password"]) # 用户名或密码错误的话 返回None if user: + if user.admin_type > 0: + if "captcha" not in data: + return error_response(u"请填写验证码!") + captcha = Captcha(request) + if not captcha.check(data["captcha"]): + return error_response(u"验证码错误") auth.login(request, user) return success_response(u"登录成功") else: From 0d6d1a410260d429071a6483cadfcded603bf9bd Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sun, 20 Sep 2015 14:10:38 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=A4=E9=A2=98?= =?UTF-8?q?=E5=B8=AE=E5=8A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/utils/help.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/template/src/utils/help.html b/template/src/utils/help.html index 0b9d605f..3c9a1539 100644 --- a/template/src/utils/help.html +++ b/template/src/utils/help.html @@ -45,7 +45,9 @@ java -cp {exe_path} Main
  • C/C++ 的64位整数类型,请使用 long long 声明,使用 cin/cout%lld 输入输出。 使用__int64会导致编译错误。
  • 程序执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准
  • - +
  • 判题的时候会去除你的输出的最后的换行和空格,然后与去除最后的换行和空格的答案做比较,如果不一致就是 Wrong Answer。 + 其余的行末空格和空行不去除,看清楚题目的要求。没有格式错误。 +
  • From fcafd3444283134bde4960a44d78496d88d6c0ed Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sun, 20 Sep 2015 14:11:03 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=AF=94=E8=B5=9B?= =?UTF-8?q?=E5=80=92=E8=AE=A1=E6=97=B6=E7=9A=84=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/views.py | 21 +++++++++++++++++++++ oj/urls.py | 6 ++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/contest/views.py b/contest/views.py index c1c19580..b38161a5 100644 --- a/contest/views.py +++ b/contest/views.py @@ -7,6 +7,8 @@ from django.db import IntegrityError from django.utils import dateparse from django.db.models import Q, Sum from django.core.paginator import Paginator +from django.utils.timezone import now + from rest_framework.views import APIView from utils.shortcuts import (serializer_invalid_response, error_response, @@ -454,3 +456,22 @@ def contest_rank_page(request, contest_id): "auto_refresh": request.GET.get("auto_refresh", None) == "true", "show_real_name": request.GET.get("show_real_name", None) == "true", "real_time_rank": contest.real_time_rank}) + + +class ContestTimeAPIView(APIView): + """ + 获取比赛开始或者结束的倒计时,返回毫秒数字 + """ + def get(self, request): + t = request.GET.get("type", "start") + contest_id = request.GET.get("contest_id", -1) + try: + contest = Contest.objects.get(id=contest_id) + except Contest.DoesNotExist: + return error_response(u"比赛不存在") + if t == "start": + # 距离开始还有多长时间 + return success_response(int((contest.start_time - now()).total_seconds() * 1000)) + else: + # 距离结束还有多长时间 + return success_response(int((contest.end_time - now()).total_seconds() * 1000)) diff --git a/oj/urls.py b/oj/urls.py index 6d556fc6..6f16acf8 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -8,7 +8,8 @@ from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterA from announcement.views import AnnouncementAdminAPIView -from contest.views import ContestAdminAPIView, ContestProblemAdminAPIView, ContestPasswordVerifyAPIView +from contest.views import (ContestAdminAPIView, ContestProblemAdminAPIView, + ContestPasswordVerifyAPIView, ContestTimeAPIView) from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView, JoinGroupAPIView, JoinGroupRequestAdminAPIView) @@ -25,7 +26,6 @@ from contest_submission.views import contest_problem_my_submissions_list_page urlpatterns = [ - url(r'^install/$', "install.views.install"), url("^$", "account.views.index_page", 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"), @@ -117,4 +117,6 @@ urlpatterns = [ url(r'^captcha/$', "utils.captcha.views.show_captcha", name="show_captcha"), url(r'^api/account_security_check/$', AccountSecurityAPIView.as_view(), name="account_security_check"), + + url(r'^api/contest/time/$', ContestTimeAPIView.as_view(), name="contest_time_api_view"), ] From 899f2768007669268bc0478629bc29195c67852a Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sun, 20 Sep 2015 14:11:17 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A2=98=E7=9B=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=80=92=E8=AE=A1=E6=97=B6=E7=9A=84=20js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/oj/problem/problem.js | 37 ++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/static/src/js/app/oj/problem/problem.js b/static/src/js/app/oj/problem/problem.js index fe51417c..6b31a729 100644 --- a/static/src/js/app/oj/problem/problem.js +++ b/static/src/js/app/oj/problem/problem.js @@ -86,7 +86,7 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert", "ZeroClipboard"], function getResult() { if (counter++ > 10) { hideLoading(); - bsAlert("抱歉,服务器可能出现了故障,请稍后到我的提交列表中查看"); + bsAlert("抱歉,服务器正在紧张判题中,请稍后到我的提交列表中查看"); counter = 0; return; } @@ -130,6 +130,41 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert", "ZeroClipboard"], } } + function getServerTime(){ + var contestId = location.pathname.split("/")[2]; + var time = 0; + $.ajax({ + url: "/api/contest/time/?contest_id=" + contestId + "&type=end", + dataType: "json", + method: "get", + async: false, + success: function(data){ + if(!data.code){ + time = data.data; + } + }, + error: function(){ + time = new Date().getTime(); + } + }); + return time; + } + + if(location.href.indexOf("contest") > -1) { + setInterval(function () { + var time = getServerTime(); + console.log(time); + var minutes = parseInt(time / (1000 * 60)); + console.log(time); + if(minutes == 0){ + bsAlert("比赛即将结束"); + } + else if(minutes > 0 && minutes <= 5){ + bsAlert("比赛还剩" + minutes.toString() + "分钟"); + } + }, 1000 * 5); + } + $("#submit-code-button").click(function () { var code = codeEditor.getValue(); From 3ef7644e9b4332cb269c629043eddba4a03e057b Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sun, 20 Sep 2015 14:41:34 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/oj/problem/problem.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/static/src/js/app/oj/problem/problem.js b/static/src/js/app/oj/problem/problem.js index 6b31a729..b018f523 100644 --- a/static/src/js/app/oj/problem/problem.js +++ b/static/src/js/app/oj/problem/problem.js @@ -153,16 +153,14 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert", "ZeroClipboard"], if(location.href.indexOf("contest") > -1) { setInterval(function () { var time = getServerTime(); - console.log(time); var minutes = parseInt(time / (1000 * 60)); - console.log(time); if(minutes == 0){ bsAlert("比赛即将结束"); } else if(minutes > 0 && minutes <= 5){ bsAlert("比赛还剩" + minutes.toString() + "分钟"); } - }, 1000 * 5); + }, 1000 * 60); } $("#submit-code-button").click(function () { From 43be94cce63e1c396bdbce79eeb98dfc52889145 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 21 Sep 2015 11:06:11 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E6=AF=94=E8=B5=9B=E5=A6=82=E6=9E=9C?= =?UTF-8?q?=E4=B8=8D=E6=98=AF=E6=AD=A3=E5=9C=A8=E8=BF=9B=E8=A1=8C=E7=9A=84?= =?UTF-8?q?=E7=8A=B6=E6=80=81=EF=BC=8C=E5=B0=B1=E4=B8=8D=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=AF=94=E8=B5=9B=E7=9A=84=E5=88=86=E6=95=B0=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=92=8C=E5=A2=9E=E5=8A=A0=E6=AF=94=E8=B5=9B=E9=A2=98=E7=9B=AE?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mq/scripts/mq.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mq/scripts/mq.py b/mq/scripts/mq.py index 567eebb1..b26a46fd 100644 --- a/mq/scripts/mq.py +++ b/mq/scripts/mq.py @@ -57,6 +57,9 @@ class MessageQueue(object): # 能运行到这里的都是比赛题目 try: contest = Contest.objects.get(id=submission.contest_id) + if contest.status != 0: + logger.info("Contest debug mode, id: " + str(contest.id) + ", submission id: " + submission_id) + continue contest_problem = ContestProblem.objects.get(contest=contest, id=submission.problem_id) except Contest.DoesNotExist: logger.warning("Submission contest does not exist, submission_id: " + submission_id) From 041fd2cb602c72299c1e96fb204be7b93d2fdc69 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 21 Sep 2015 11:16:30 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E9=83=A8=E5=88=86=20ma?= =?UTF-8?q?gic=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/decorators.py | 10 +++++----- contest/models.py | 10 +++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/contest/decorators.py b/contest/decorators.py index df73274a..600d98b8 100644 --- a/contest/decorators.py +++ b/contest/decorators.py @@ -3,12 +3,12 @@ from functools import wraps from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render -from django.utils.timezone import now from utils.shortcuts import error_response, error_page from account.models import SUPER_ADMIN -from .models import Contest +from .models import (Contest, PASSWORD_PROTECTED_CONTEST, PUBLIC_CONTEST, GROUP_CONTEST, + CONTEST_ENDED, CONTEST_NOT_START, CONTEST_UNDERWAY) def check_user_contest_permission(func): @@ -55,7 +55,7 @@ def check_user_contest_permission(func): return func(*args, **kwargs) # 有密码的公开赛 - if contest.contest_type == 2: + if contest.contest_type == PASSWORD_PROTECTED_CONTEST: # 没有输入过密码 if contest.id not in request.session.get("contests", []): if request.is_ajax(): @@ -65,7 +65,7 @@ def check_user_contest_permission(func): {"reason": "password_protect", "show_tab": False, "contest": contest}) # 指定小组参加的 - if contest.contest_type == 0: + if contest.contest_type == GROUP_CONTEST: if not contest.groups.filter(id__in=request.user.group_set.all()).exists(): if request.is_ajax(): return error_response(u"只有指定小组的可以参加这场比赛") @@ -74,7 +74,7 @@ def check_user_contest_permission(func): {"reason": "group_limited", "show_tab": False, "contest": contest}) # 比赛没有开始 - if contest.status == 1: + if contest.status == CONTEST_NOT_START: if request.is_ajax(): return error_response(u"比赛还没有开始") else: diff --git a/contest/models.py b/contest/models.py index 7331ec27..e0484555 100644 --- a/contest/models.py +++ b/contest/models.py @@ -10,6 +10,10 @@ GROUP_CONTEST = 0 PUBLIC_CONTEST = 1 PASSWORD_PROTECTED_CONTEST = 2 +CONTEST_NOT_START = 1 +CONTEST_ENDED = -1 +CONTEST_UNDERWAY = 0 + class Contest(models.Model): title = models.CharField(max_length=40, unique=True) @@ -44,13 +48,13 @@ class Contest(models.Model): def status(self): if self.start_time > now(): # 没有开始 返回1 - return 1 + return CONTEST_NOT_START elif self.end_time < now(): # 已经结束 返回0 - return -1 + return CONTEST_ENDED else: # 正在进行 返回0 - return 0 + return CONTEST_UNDERWAY class Meta: db_table = "contest" From 725d950e27f971cf2308049b938ec523b80abd5d Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 21 Sep 2015 12:28:22 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=B8=8D=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E9=AA=8C=E8=AF=81=E7=A0=81=E7=9A=84=E6=97=B6=E5=80=99?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E9=AA=8C=E8=AF=81=E4=BC=9A=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/oj/account/login.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/static/src/js/app/oj/account/login.js b/static/src/js/app/oj/account/login.js index 32343c95..22d47593 100644 --- a/static/src/js/app/oj/account/login.js +++ b/static/src/js/app/oj/account/login.js @@ -33,7 +33,9 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c location.href = "/"; } else { - refresh_captcha(); + if(applied_captcha) { + refresh_captcha(); + } bsAlert(data.data); } } From cb0e7cf9382b94299b2df3b9c00d0e3d68aa98aa Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 21 Sep 2015 12:32:50 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=AC=E5=91=8A?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E4=B8=AD=E7=94=A8=E6=88=B7=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E9=94=99=E8=AF=AF=E7=9A=84=E6=83=85=E5=86=B5?= =?UTF-8?q?=EF=BC=8C=E6=8A=BD=E5=8F=96=E4=BB=A3=E7=A0=81=E4=B8=BA=20decora?= =?UTF-8?q?tor=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- announcement/decorators.py | 43 +++++++++++++++++++++++++ announcement/models.py | 2 +- announcement/views.py | 22 +++---------- utils/templatetags/announcement_list.py | 1 + 4 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 announcement/decorators.py diff --git a/announcement/decorators.py b/announcement/decorators.py new file mode 100644 index 00000000..96df987d --- /dev/null +++ b/announcement/decorators.py @@ -0,0 +1,43 @@ +# coding=utf-8 +from functools import wraps + +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render + +from utils.shortcuts import error_response, error_page + +from account.models import SUPER_ADMIN +from .models import Announcement + + +def check_user_announcement_permission(func): + @wraps(func) + def _check_user_announcement_permission(*args, **kwargs): + """ + 这个函数检测当前用户能否查看这个公告 + """ + # CBV 的情况,第一个参数是self,第二个参数是request + if len(args) == 2: + request = args[-1] + else: + request = args[0] + + if "announcement_id" not in kwargs: + return error_page(request, u"参数错误") + announcement_id = kwargs["announcement_id"] + + try: + announcement = Announcement.objects.get(id=announcement_id, visible=True) + except Announcement.DoesNotExist: + return error_page(request, u"公告不存在") + + # 如果公告是只有部分小组可见的 + if not announcement.is_global: + # 用户必须是登录状态的 + if not request.user.is_authenticated(): + return HttpResponseRedirect("/login/") + if not announcement.groups.filter(id__in=request.user.group_set.all()).exists(): + return error_page(request, u"公告不存在") + return func(*args, **kwargs) + + return _check_user_announcement_permission diff --git a/announcement/models.py b/announcement/models.py index 1dfa6060..c3267f12 100644 --- a/announcement/models.py +++ b/announcement/models.py @@ -18,7 +18,7 @@ class Announcement(models.Model): last_update_time = models.DateTimeField(auto_now=True) # 是否可见 false的话相当于删除 visible = models.BooleanField(default=True) - # 公告可见范围 0是全局可见 1是部分小组可见,需要在下面的字段中存储可见的小组 + # 公告可见范围 True 是全局可见 False 是部分小组可见,需要在下面的字段中存储可见的小组 is_global = models.BooleanField() groups = models.ManyToManyField(Group) diff --git a/announcement/views.py b/announcement/views.py index 6790e8ce..3160d9ef 100644 --- a/announcement/views.py +++ b/announcement/views.py @@ -10,27 +10,13 @@ from group.models import Group from .models import Announcement from .serializers import (CreateAnnouncementSerializer, AnnouncementSerializer, EditAnnouncementSerializer) +from .decorators import check_user_announcement_permission +@check_user_announcement_permission def announcement_page(request, announcement_id): - try: - announcement = Announcement.objects.get(id=announcement_id, visible=True) - except Announcement.DoesNotExist: - return error_page(request, u"公告不存在") - # 公开的公告 - if announcement.is_global == 0: - return render(request, "oj/announcement/announcement.html", {"announcement": announcement}) - else: - if not request.user.is_authenticated(): - return error_page(request, u"公告不存在") - # 判断是不是在组里面 - if request.user.admin_type == SUPER_ADMIN or request.user == announcement.created_by: - return render(request, "oj/announcement/announcement.html", {"announcement": announcement}) - else: - if request.user.groups.filter(id__in=[item.id for item in announcement.groups.all()]).exists(): - return render(request, "oj/announcement/announcement.html", {"announcement": announcement}) - else: - return error_page(request, u"公告不存在") + announcement = Announcement.objects.get(id=announcement_id, visible=True) + return render(request, "oj/announcement/announcement.html", {"announcement": announcement}) class AnnouncementAdminAPIView(APIView): diff --git a/utils/templatetags/announcement_list.py b/utils/templatetags/announcement_list.py index acf38d9f..1b2f331e 100644 --- a/utils/templatetags/announcement_list.py +++ b/utils/templatetags/announcement_list.py @@ -3,6 +3,7 @@ from django import template from announcement.models import Announcement + def public_announcement_list(): return Announcement.objects.filter(is_global=True, visible=True).order_by("-create_time") From 60d727d7b23a07a71d6b8593fb773d22254cf0c5 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 21 Sep 2015 13:41:14 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/admin/admin.js | 3 +-- template/src/admin/admin.html | 39 ----------------------------- template/src/admin/index/index.html | 2 +- 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/static/src/js/app/admin/admin.js b/static/src/js/app/admin/admin.js index 878b9cad..d68dba11 100644 --- a/static/src/js/app/admin/admin.js +++ b/static/src/js/app/admin/admin.js @@ -24,8 +24,7 @@ require(["jquery", "avalon", "bootstrap"], function ($, avalon) { var superAdminNav = [ { name: "首页", children: [{name: "主页", hash: "#index/index"}, - {name: "监控", hash: "#monitor/monitor"}, - {name: "统计", hash: "#statistics/statistics"}] + {name: "监控", hash: "#monitor/monitor"}] }, { name: "通用", diff --git a/template/src/admin/admin.html b/template/src/admin/admin.html index 0e470c6e..7020dae3 100644 --- a/template/src/admin/admin.html +++ b/template/src/admin/admin.html @@ -71,45 +71,6 @@ {{ item.name }} - diff --git a/template/src/admin/index/index.html b/template/src/admin/index/index.html index 61168280..257eab15 100644 --- a/template/src/admin/index/index.html +++ b/template/src/admin/index/index.html @@ -1 +1 @@ -

    Hello world

    \ No newline at end of file +

    Online Judge Admin

    \ No newline at end of file From 5f23bff3c5a9040c4292fdd0a3c231e02eb07a71 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 21 Sep 2015 13:56:54 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=89=8D=E5=8F=B0?= =?UTF-8?q?=E9=A2=98=E7=9B=AE=E7=9A=84=E9=87=8D=E6=96=B0=E5=88=A4=E9=A2=98?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/urls.py | 4 ++- .../js/app/admin/problem/submissionList.js | 14 +++++++++ submission/serializers.py | 4 +++ submission/views.py | 30 ++++++++++++++++++- .../src/admin/problem/submission_list.html | 1 + 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/oj/urls.py b/oj/urls.py index 6f16acf8..5b65e4c0 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -17,7 +17,8 @@ from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView, from admin.views import AdminTemplateView from problem.views import TestCaseUploadAPIView, ProblemTagAdminAPIView, ProblemAdminAPIView -from submission.views import SubmissionAPIView, SubmissionAdminAPIView, SubmissionShareAPIView +from submission.views import (SubmissionAPIView, SubmissionAdminAPIView, + SubmissionShareAPIView, SubmissionRejudgeAdminAPIView) from contest_submission.views import ContestSubmissionAPIView, ContestSubmissionAdminAPIView from monitor.views import QueueLengthMonitorAPIView from utils.views import SimditorImageUploadAPIView @@ -119,4 +120,5 @@ urlpatterns = [ url(r'^api/account_security_check/$', AccountSecurityAPIView.as_view(), name="account_security_check"), url(r'^api/contest/time/$', ContestTimeAPIView.as_view(), name="contest_time_api_view"), + url(r'^api/admin/rejudge/$', SubmissionRejudgeAdminAPIView.as_view(), name="submission_rejudge_api"), ] diff --git a/static/src/js/app/admin/problem/submissionList.js b/static/src/js/app/admin/problem/submissionList.js index 1af2e6ce..e8d00bb0 100644 --- a/static/src/js/app/admin/problem/submissionList.js +++ b/static/src/js/app/admin/problem/submissionList.js @@ -51,6 +51,20 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT }, showProblemListPage: function(){ vm.$fire("up!showProblemListPage"); + }, + rejudge: function(submission_id){ + $.ajax({ + beforeSend: csrfTokenHeader, + url: "/api/admin/rejudge/", + method: "post", + data: {"submission_id": submission_id}, + success: function(data){ + if(!data.code){ + bsAlert("重判任务提交成功"); + } + } + + }) } }); } diff --git a/submission/serializers.py b/submission/serializers.py index 8fd62787..3a5308cd 100644 --- a/submission/serializers.py +++ b/submission/serializers.py @@ -26,3 +26,7 @@ class SubmissionhareSerializer(serializers.Serializer): submission_id = serializers.CharField(max_length=40) +class SubmissionRejudgeSerializer(serializers.Serializer): + submission_id = serializers.CharField(max_length=40) + + diff --git a/submission/views.py b/submission/views.py index 6eb69fae..396cdfe8 100644 --- a/submission/views.py +++ b/submission/views.py @@ -19,7 +19,8 @@ from announcement.models import Announcement from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page, paginate from .models import Submission -from .serializers import CreateSubmissionSerializer, SubmissionSerializer, SubmissionhareSerializer +from .serializers import (CreateSubmissionSerializer, SubmissionSerializer, + SubmissionhareSerializer, SubmissionRejudgeSerializer) logger = logging.getLogger("app_info") @@ -219,3 +220,30 @@ class SubmissionShareAPIView(APIView): return success_response(submission.shared) else: return serializer_invalid_response(serializer) + + +class SubmissionRejudgeAdminAPIView(APIView): + def post(self, request): + serializer = SubmissionRejudgeSerializer(data=request.data) + if serializer.is_valid(): + submission_id = serializer.data["submission_id"] + try: + submission = Submission.objects.get(id=submission_id) + except Submission.DoesNotExist: + return error_response(u"提交不存在") + # 目前只考虑前台公开题目的重新判题 + try: + problem = Problem.objects.get(id=submission.problem_id) + except Problem.DoesNotExist: + return error_response(u"题目不存在") + try: + judge.delay(submission_id, problem.time_limit, problem.memory_limit, problem.test_case_id) + except Exception as e: + logger.error(e) + 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") + else: + return serializer_invalid_response(serializer) \ No newline at end of file diff --git a/template/src/admin/problem/submission_list.html b/template/src/admin/problem/submission_list.html index 28eaebd4..e0880af5 100644 --- a/template/src/admin/problem/submission_list.html +++ b/template/src/admin/problem/submission_list.html @@ -22,6 +22,7 @@ {{ results[el.result] }} 详情 + 重判