mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-11-04 14:49:58 +08:00
Merge branch 'virusdefender-dev' into debug
* virusdefender-dev: 增加前台题目的重新判题功能 删除统计功能 修复公告列表中用户权限判断错误的情况,抽取代码为 decorator。 用户不需要验证码的时候刷新验证会导致错误,增加判断 去除部分 magic number 比赛如果不是正在进行的状态,就不创建比赛的分数记录和增加比赛题目计数器 修改刷新时间 增加题目页面倒计时的 js 增加比赛倒计时的 api 增加判题帮助 修复判断验证码是否存在的时候,用户不存在导致的报错
This commit is contained in:
commit
dc9476f585
@ -7,7 +7,7 @@ from .models import User
|
|||||||
class UserLoginSerializer(serializers.Serializer):
|
class UserLoginSerializer(serializers.Serializer):
|
||||||
username = serializers.CharField(max_length=30)
|
username = serializers.CharField(max_length=30)
|
||||||
password = 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):
|
class UsernameCheckSerializer(serializers.Serializer):
|
||||||
|
|||||||
@ -26,17 +26,15 @@ class UserLoginAPIView(APIView):
|
|||||||
serializer = UserLoginSerializer(data=request.data)
|
serializer = UserLoginSerializer(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
data = serializer.data
|
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"])
|
user = auth.authenticate(username=data["username"], password=data["password"])
|
||||||
# 用户名或密码错误的话 返回None
|
# 用户名或密码错误的话 返回None
|
||||||
if user:
|
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)
|
auth.login(request, user)
|
||||||
return success_response(u"登录成功")
|
return success_response(u"登录成功")
|
||||||
else:
|
else:
|
||||||
|
|||||||
43
announcement/decorators.py
Normal file
43
announcement/decorators.py
Normal file
@ -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
|
||||||
@ -18,7 +18,7 @@ class Announcement(models.Model):
|
|||||||
last_update_time = models.DateTimeField(auto_now=True)
|
last_update_time = models.DateTimeField(auto_now=True)
|
||||||
# 是否可见 false的话相当于删除
|
# 是否可见 false的话相当于删除
|
||||||
visible = models.BooleanField(default=True)
|
visible = models.BooleanField(default=True)
|
||||||
# 公告可见范围 0是全局可见 1是部分小组可见,需要在下面的字段中存储可见的小组
|
# 公告可见范围 True 是全局可见 False 是部分小组可见,需要在下面的字段中存储可见的小组
|
||||||
is_global = models.BooleanField()
|
is_global = models.BooleanField()
|
||||||
groups = models.ManyToManyField(Group)
|
groups = models.ManyToManyField(Group)
|
||||||
|
|
||||||
|
|||||||
@ -10,27 +10,13 @@ from group.models import Group
|
|||||||
from .models import Announcement
|
from .models import Announcement
|
||||||
from .serializers import (CreateAnnouncementSerializer, AnnouncementSerializer,
|
from .serializers import (CreateAnnouncementSerializer, AnnouncementSerializer,
|
||||||
EditAnnouncementSerializer)
|
EditAnnouncementSerializer)
|
||||||
|
from .decorators import check_user_announcement_permission
|
||||||
|
|
||||||
|
|
||||||
|
@check_user_announcement_permission
|
||||||
def announcement_page(request, announcement_id):
|
def announcement_page(request, announcement_id):
|
||||||
try:
|
announcement = Announcement.objects.get(id=announcement_id, visible=True)
|
||||||
announcement = Announcement.objects.get(id=announcement_id, visible=True)
|
return render(request, "oj/announcement/announcement.html", {"announcement": announcement})
|
||||||
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"公告不存在")
|
|
||||||
|
|
||||||
|
|
||||||
class AnnouncementAdminAPIView(APIView):
|
class AnnouncementAdminAPIView(APIView):
|
||||||
|
|||||||
@ -3,12 +3,12 @@ from functools import wraps
|
|||||||
|
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.timezone import now
|
|
||||||
|
|
||||||
from utils.shortcuts import error_response, error_page
|
from utils.shortcuts import error_response, error_page
|
||||||
|
|
||||||
from account.models import SUPER_ADMIN
|
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):
|
def check_user_contest_permission(func):
|
||||||
@ -55,7 +55,7 @@ def check_user_contest_permission(func):
|
|||||||
return func(*args, **kwargs)
|
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 contest.id not in request.session.get("contests", []):
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
@ -65,7 +65,7 @@ def check_user_contest_permission(func):
|
|||||||
{"reason": "password_protect", "show_tab": False, "contest": contest})
|
{"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 not contest.groups.filter(id__in=request.user.group_set.all()).exists():
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
return error_response(u"只有指定小组的可以参加这场比赛")
|
return error_response(u"只有指定小组的可以参加这场比赛")
|
||||||
@ -74,7 +74,7 @@ def check_user_contest_permission(func):
|
|||||||
{"reason": "group_limited", "show_tab": False, "contest": contest})
|
{"reason": "group_limited", "show_tab": False, "contest": contest})
|
||||||
|
|
||||||
# 比赛没有开始
|
# 比赛没有开始
|
||||||
if contest.status == 1:
|
if contest.status == CONTEST_NOT_START:
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
return error_response(u"比赛还没有开始")
|
return error_response(u"比赛还没有开始")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -10,6 +10,10 @@ GROUP_CONTEST = 0
|
|||||||
PUBLIC_CONTEST = 1
|
PUBLIC_CONTEST = 1
|
||||||
PASSWORD_PROTECTED_CONTEST = 2
|
PASSWORD_PROTECTED_CONTEST = 2
|
||||||
|
|
||||||
|
CONTEST_NOT_START = 1
|
||||||
|
CONTEST_ENDED = -1
|
||||||
|
CONTEST_UNDERWAY = 0
|
||||||
|
|
||||||
|
|
||||||
class Contest(models.Model):
|
class Contest(models.Model):
|
||||||
title = models.CharField(max_length=40, unique=True)
|
title = models.CharField(max_length=40, unique=True)
|
||||||
@ -44,13 +48,13 @@ class Contest(models.Model):
|
|||||||
def status(self):
|
def status(self):
|
||||||
if self.start_time > now():
|
if self.start_time > now():
|
||||||
# 没有开始 返回1
|
# 没有开始 返回1
|
||||||
return 1
|
return CONTEST_NOT_START
|
||||||
elif self.end_time < now():
|
elif self.end_time < now():
|
||||||
# 已经结束 返回0
|
# 已经结束 返回0
|
||||||
return -1
|
return CONTEST_ENDED
|
||||||
else:
|
else:
|
||||||
# 正在进行 返回0
|
# 正在进行 返回0
|
||||||
return 0
|
return CONTEST_UNDERWAY
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "contest"
|
db_table = "contest"
|
||||||
|
|||||||
@ -7,6 +7,8 @@ from django.db import IntegrityError
|
|||||||
from django.utils import dateparse
|
from django.utils import dateparse
|
||||||
from django.db.models import Q, Sum
|
from django.db.models import Q, Sum
|
||||||
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 rest_framework.views import APIView
|
||||||
|
|
||||||
from utils.shortcuts import (serializer_invalid_response, error_response,
|
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",
|
"auto_refresh": request.GET.get("auto_refresh", None) == "true",
|
||||||
"show_real_name": request.GET.get("show_real_name", None) == "true",
|
"show_real_name": request.GET.get("show_real_name", None) == "true",
|
||||||
"real_time_rank": contest.real_time_rank})
|
"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))
|
||||||
|
|||||||
@ -57,6 +57,9 @@ class MessageQueue(object):
|
|||||||
# 能运行到这里的都是比赛题目
|
# 能运行到这里的都是比赛题目
|
||||||
try:
|
try:
|
||||||
contest = Contest.objects.get(id=submission.contest_id)
|
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)
|
contest_problem = ContestProblem.objects.get(contest=contest, id=submission.problem_id)
|
||||||
except Contest.DoesNotExist:
|
except Contest.DoesNotExist:
|
||||||
logger.warning("Submission contest does not exist, submission_id: " + submission_id)
|
logger.warning("Submission contest does not exist, submission_id: " + submission_id)
|
||||||
|
|||||||
10
oj/urls.py
10
oj/urls.py
@ -8,7 +8,8 @@ from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterA
|
|||||||
|
|
||||||
from announcement.views import AnnouncementAdminAPIView
|
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,
|
from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView,
|
||||||
JoinGroupAPIView, JoinGroupRequestAdminAPIView)
|
JoinGroupAPIView, JoinGroupRequestAdminAPIView)
|
||||||
@ -16,7 +17,8 @@ from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView,
|
|||||||
from admin.views import AdminTemplateView
|
from admin.views import AdminTemplateView
|
||||||
|
|
||||||
from problem.views import TestCaseUploadAPIView, ProblemTagAdminAPIView, ProblemAdminAPIView
|
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 contest_submission.views import ContestSubmissionAPIView, ContestSubmissionAdminAPIView
|
||||||
from monitor.views import QueueLengthMonitorAPIView
|
from monitor.views import QueueLengthMonitorAPIView
|
||||||
from utils.views import SimditorImageUploadAPIView
|
from utils.views import SimditorImageUploadAPIView
|
||||||
@ -25,7 +27,6 @@ from contest_submission.views import contest_problem_my_submissions_list_page
|
|||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^install/$', "install.views.install"),
|
|
||||||
url("^$", "account.views.index_page", name="index_page"),
|
url("^$", "account.views.index_page", name="index_page"),
|
||||||
url(r'^docs/', include('rest_framework_swagger.urls')),
|
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/$', TemplateView.as_view(template_name="admin/admin.html"), name="admin_spa_page"),
|
||||||
@ -117,4 +118,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
url(r'^captcha/$', "utils.captcha.views.show_captcha", name="show_captcha"),
|
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/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"),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -24,8 +24,7 @@ require(["jquery", "avalon", "bootstrap"], function ($, avalon) {
|
|||||||
var superAdminNav = [
|
var superAdminNav = [
|
||||||
{ name: "首页",
|
{ name: "首页",
|
||||||
children: [{name: "主页", hash: "#index/index"},
|
children: [{name: "主页", hash: "#index/index"},
|
||||||
{name: "监控", hash: "#monitor/monitor"},
|
{name: "监控", hash: "#monitor/monitor"}]
|
||||||
{name: "统计", hash: "#statistics/statistics"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "通用",
|
name: "通用",
|
||||||
|
|||||||
@ -51,6 +51,20 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT
|
|||||||
},
|
},
|
||||||
showProblemListPage: function(){
|
showProblemListPage: function(){
|
||||||
vm.$fire("up!showProblemListPage");
|
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("重判任务提交成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,9 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
|
|||||||
location.href = "/";
|
location.href = "/";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
refresh_captcha();
|
if(applied_captcha) {
|
||||||
|
refresh_captcha();
|
||||||
|
}
|
||||||
bsAlert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,7 +86,7 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert", "ZeroClipboard"],
|
|||||||
function getResult() {
|
function getResult() {
|
||||||
if (counter++ > 10) {
|
if (counter++ > 10) {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
bsAlert("抱歉,服务器可能出现了故障,请稍后到我的提交列表中查看");
|
bsAlert("抱歉,服务器正在紧张判题中,请稍后到我的提交列表中查看");
|
||||||
counter = 0;
|
counter = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -130,6 +130,39 @@ 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();
|
||||||
|
var minutes = parseInt(time / (1000 * 60));
|
||||||
|
if(minutes == 0){
|
||||||
|
bsAlert("比赛即将结束");
|
||||||
|
}
|
||||||
|
else if(minutes > 0 && minutes <= 5){
|
||||||
|
bsAlert("比赛还剩" + minutes.toString() + "分钟");
|
||||||
|
}
|
||||||
|
}, 1000 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
$("#submit-code-button").click(function () {
|
$("#submit-code-button").click(function () {
|
||||||
|
|
||||||
var code = codeEditor.getValue();
|
var code = codeEditor.getValue();
|
||||||
|
|||||||
@ -26,3 +26,7 @@ class SubmissionhareSerializer(serializers.Serializer):
|
|||||||
submission_id = serializers.CharField(max_length=40)
|
submission_id = serializers.CharField(max_length=40)
|
||||||
|
|
||||||
|
|
||||||
|
class SubmissionRejudgeSerializer(serializers.Serializer):
|
||||||
|
submission_id = serializers.CharField(max_length=40)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@ from announcement.models import Announcement
|
|||||||
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page, paginate
|
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page, paginate
|
||||||
|
|
||||||
from .models import Submission
|
from .models import Submission
|
||||||
from .serializers import CreateSubmissionSerializer, SubmissionSerializer, SubmissionhareSerializer
|
from .serializers import (CreateSubmissionSerializer, SubmissionSerializer,
|
||||||
|
SubmissionhareSerializer, SubmissionRejudgeSerializer)
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("app_info")
|
logger = logging.getLogger("app_info")
|
||||||
@ -219,3 +220,30 @@ class SubmissionShareAPIView(APIView):
|
|||||||
return success_response(submission.shared)
|
return success_response(submission.shared)
|
||||||
else:
|
else:
|
||||||
return serializer_invalid_response(serializer)
|
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)
|
||||||
@ -71,45 +71,6 @@
|
|||||||
<a ms-attr-href="el.hash">{{ item.name }}</a>
|
<a ms-attr-href="el.hash">{{ item.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
<!--<li class="list-group-header">首页</li>
|
|
||||||
<li class="list-group-item" id="li-index-index">
|
|
||||||
<a href="#index/index">主页</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-item" id="li-monitor-monitor">
|
|
||||||
<a href="#monitor/monitor">监控</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-item" id="li-statistics-statistics">
|
|
||||||
<a href="#statistics/statistics">统计</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-header">通用</li>
|
|
||||||
<li class="list-group-item" id="li-announcement-announcement">
|
|
||||||
<a href="#announcement/announcement">公告管理</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-item" id="li-user-user_list">
|
|
||||||
<a href="#user/user_list">用户管理</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-header">题目管理</li>
|
|
||||||
<li class="list-group-item" id="li-problem-problem_list">
|
|
||||||
<a href="#problem/problem_list">题目列表</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-item" id="li-problem-add_problem">
|
|
||||||
<a href="#problem/add_problem">创建题目</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-header">比赛管理</li>
|
|
||||||
<li class="list-group-item" id="li-contest-contest_list">
|
|
||||||
<a href="#contest/contest_list">比赛列表</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-item" id="li-contest-add_contest">
|
|
||||||
<a href="#contest/add_contest">创建比赛</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="list-group-header">小组管理</li>
|
|
||||||
<li class="list-group-item" id="li-group-group">
|
|
||||||
<a href="#group/group">小组列表</a>
|
|
||||||
</li>
|
|
||||||
<li class="list-group-item" id="li-group-join_group_request_list">
|
|
||||||
<a href="#group/join_group_request_list">加入小组请求</a>
|
|
||||||
</li>-->
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<!-- admin left end -->
|
<!-- admin left end -->
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
<h1>Hello world</h1>
|
<h1>Online Judge Admin</h1>
|
||||||
@ -22,6 +22,7 @@
|
|||||||
<td>{{ results[el.result] }}</td>
|
<td>{{ results[el.result] }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn-info" ms-attr-href="'/submission/' + el.id + '/'" target="_blank">详情</a>
|
<a class="btn btn-info" ms-attr-href="'/submission/' + el.id + '/'" target="_blank">详情</a>
|
||||||
|
<a class="btn btn-primary" ms-click="rejudge(el.id)">重判</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -45,7 +45,9 @@ java -cp {exe_path} Main</pre>
|
|||||||
<li>C/C++ 的64位整数类型,请使用 <code>long long</code> 声明,使用 <code>cin/cout</code> 或 <code>%lld</code> 输入输出。
|
<li>C/C++ 的64位整数类型,请使用 <code>long long</code> 声明,使用 <code>cin/cout</code> 或 <code>%lld</code> 输入输出。
|
||||||
使用<code>__int64</code>会导致编译错误。</li>
|
使用<code>__int64</code>会导致编译错误。</li>
|
||||||
<li>程序执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</li>
|
<li>程序执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</li>
|
||||||
|
<li>判题的时候会去除你的输出的最后的换行和空格,然后与去除最后的换行和空格的答案做比较,如果不一致就是 Wrong Answer。
|
||||||
|
其余的行末空格和空行不去除,看清楚题目的要求。没有格式错误。
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,6 +3,7 @@ from django import template
|
|||||||
|
|
||||||
from announcement.models import Announcement
|
from announcement.models import Announcement
|
||||||
|
|
||||||
|
|
||||||
def public_announcement_list():
|
def public_announcement_list():
|
||||||
return Announcement.objects.filter(is_global=True, visible=True).order_by("-create_time")
|
return Announcement.objects.filter(is_global=True, visible=True).order_by("-create_time")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user