Accept Merge Request #233 细节修改&新功能 : (dev-sxw -> dev)
Merge Request: 细节修改&新功能 Created By: @esp Accepted By: @virusdefender URL: https://coding.net/u/virusdefender/p/qduoj/git/merge/233
This commit is contained in:
19
contest/migrations/0009_contestsubmission_first_achieved.py
Normal file
19
contest/migrations/0009_contestsubmission_first_achieved.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contest', '0008_auto_20150912_1912'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='contestsubmission',
|
||||||
|
name='first_achieved',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -89,10 +89,12 @@ class ContestSubmission(models.Model):
|
|||||||
total_submission_number = models.IntegerField(default=1)
|
total_submission_number = models.IntegerField(default=1)
|
||||||
# 这道题是 AC 还是没过
|
# 这道题是 AC 还是没过
|
||||||
ac = models.BooleanField()
|
ac = models.BooleanField()
|
||||||
# ac 用时
|
# ac 用时以秒计
|
||||||
ac_time = models.IntegerField(default=0)
|
ac_time = models.IntegerField(default=0)
|
||||||
# 总的时间,用于acm 类型的,也需要保存罚时
|
# 总的时间,用于acm 类型的,也需要保存罚时
|
||||||
total_time = models.IntegerField(default=0)
|
total_time = models.IntegerField(default=0)
|
||||||
|
# 第一个解出此题目
|
||||||
|
first_achieved = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "contest_submission"
|
db_table = "contest_submission"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class CreateContestSerializer(serializers.Serializer):
|
|||||||
description = serializers.CharField(max_length=5000)
|
description = serializers.CharField(max_length=5000)
|
||||||
mode = serializers.IntegerField()
|
mode = serializers.IntegerField()
|
||||||
contest_type = serializers.IntegerField()
|
contest_type = serializers.IntegerField()
|
||||||
show_rank = serializers.BooleanField()
|
real_time_rank = serializers.BooleanField()
|
||||||
show_user_submission = serializers.BooleanField()
|
show_user_submission = serializers.BooleanField()
|
||||||
password = serializers.CharField(max_length=30, required=False, default=None)
|
password = serializers.CharField(max_length=30, required=False, default=None)
|
||||||
start_time = serializers.DateTimeField()
|
start_time = serializers.DateTimeField()
|
||||||
@@ -47,7 +47,7 @@ class EditContestSerializer(serializers.Serializer):
|
|||||||
description = serializers.CharField(max_length=10000)
|
description = serializers.CharField(max_length=10000)
|
||||||
mode = serializers.IntegerField()
|
mode = serializers.IntegerField()
|
||||||
contest_type = serializers.IntegerField()
|
contest_type = serializers.IntegerField()
|
||||||
show_rank = serializers.BooleanField()
|
real_time_rank = serializers.BooleanField()
|
||||||
show_user_submission = serializers.BooleanField()
|
show_user_submission = serializers.BooleanField()
|
||||||
password = serializers.CharField(max_length=30, required=False, default=None)
|
password = serializers.CharField(max_length=30, required=False, default=None)
|
||||||
start_time = serializers.DateTimeField()
|
start_time = serializers.DateTimeField()
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ from .serializers import (CreateContestSerializer, ContestSerializer, EditContes
|
|||||||
CreateContestProblemSerializer, ContestProblemSerializer,
|
CreateContestProblemSerializer, ContestProblemSerializer,
|
||||||
ContestPasswordVerifySerializer,
|
ContestPasswordVerifySerializer,
|
||||||
EditContestProblemSerializer)
|
EditContestProblemSerializer)
|
||||||
|
from oj.settings import REDIS_CACHE
|
||||||
|
import redis
|
||||||
|
|
||||||
|
|
||||||
class ContestAdminAPIView(APIView):
|
class ContestAdminAPIView(APIView):
|
||||||
@@ -58,7 +60,7 @@ class ContestAdminAPIView(APIView):
|
|||||||
try:
|
try:
|
||||||
contest = Contest.objects.create(title=data["title"], description=data["description"],
|
contest = Contest.objects.create(title=data["title"], description=data["description"],
|
||||||
mode=data["mode"], contest_type=data["contest_type"],
|
mode=data["mode"], contest_type=data["contest_type"],
|
||||||
show_rank=data["show_rank"], password=data["password"],
|
real_time_rank=data["real_time_rank"], password=data["password"],
|
||||||
show_user_submission=data["show_user_submission"],
|
show_user_submission=data["show_user_submission"],
|
||||||
start_time=dateparse.parse_datetime(data["start_time"]),
|
start_time=dateparse.parse_datetime(data["start_time"]),
|
||||||
end_time=dateparse.parse_datetime(data["end_time"]),
|
end_time=dateparse.parse_datetime(data["end_time"]),
|
||||||
@@ -112,7 +114,7 @@ class ContestAdminAPIView(APIView):
|
|||||||
contest.description = data["description"]
|
contest.description = data["description"]
|
||||||
contest.mode = data["mode"]
|
contest.mode = data["mode"]
|
||||||
contest.contest_type = data["contest_type"]
|
contest.contest_type = data["contest_type"]
|
||||||
contest.show_rank = data["show_rank"]
|
contest.real_time_rank = data["real_time_rank"]
|
||||||
contest.show_user_submission = data["show_user_submission"]
|
contest.show_user_submission = data["show_user_submission"]
|
||||||
contest.start_time = dateparse.parse_datetime(data["start_time"])
|
contest.start_time = dateparse.parse_datetime(data["start_time"])
|
||||||
contest.end_time = dateparse.parse_datetime(data["end_time"])
|
contest.end_time = dateparse.parse_datetime(data["end_time"])
|
||||||
@@ -353,7 +355,6 @@ def contest_list_page(request, page=1):
|
|||||||
if request.user.is_authenticated and join:
|
if request.user.is_authenticated and join:
|
||||||
contests = contests.filter(Q(contest_type__in=[1, 2]) | Q(groups__in=request.user.group_set.all())). \
|
contests = contests.filter(Q(contest_type__in=[1, 2]) | Q(groups__in=request.user.group_set.all())). \
|
||||||
filter(end_time__gt=datetime.datetime.now(), start_time__lt=datetime.datetime.now())
|
filter(end_time__gt=datetime.datetime.now(), start_time__lt=datetime.datetime.now())
|
||||||
|
|
||||||
paginator = Paginator(contests, 20)
|
paginator = Paginator(contests, 20)
|
||||||
try:
|
try:
|
||||||
current_page = paginator.page(int(page))
|
current_page = paginator.page(int(page))
|
||||||
@@ -390,23 +391,62 @@ def _cmp(x, y):
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
def get_the_time_format(seconds):
|
||||||
|
if not seconds:
|
||||||
|
return ""
|
||||||
|
result = str(seconds % 60)
|
||||||
|
if seconds % 60 < 10:
|
||||||
|
result = "0" + result
|
||||||
|
result = str((seconds % 3600) / 60) + ":" + result
|
||||||
|
if (seconds % 3600) / 60 < 10:
|
||||||
|
result = "0" + result
|
||||||
|
result = str(seconds / 3600) + ":" + result
|
||||||
|
if seconds / 3600 < 10:
|
||||||
|
result = "0" + result
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@check_user_contest_permission
|
@check_user_contest_permission
|
||||||
def contest_rank_page(request, contest_id):
|
def contest_rank_page(request, contest_id):
|
||||||
contest = Contest.objects.get(id=contest_id)
|
contest = Contest.objects.get(id=contest_id)
|
||||||
contest_problems = ContestProblem.objects.filter(contest=contest).order_by("sort_index")
|
contest_problems = ContestProblem.objects.filter(contest=contest).order_by("sort_index")
|
||||||
|
r = redis.Redis(host=REDIS_CACHE["host"], port=REDIS_CACHE["port"], db=REDIS_CACHE["db"])
|
||||||
|
if contest.real_time_rank:
|
||||||
|
# 更新rank
|
||||||
result = ContestSubmission.objects.filter(contest=contest).values("user_id"). \
|
result = ContestSubmission.objects.filter(contest=contest).values("user_id"). \
|
||||||
annotate(total_submit=Sum("total_submission_number"))
|
annotate(total_submit=Sum("total_submission_number"))
|
||||||
for i in range(0, len(result)):
|
for i in range(0, len(result)):
|
||||||
# 这个人所有的提交
|
# 这个人所有的提交
|
||||||
submissions = ContestSubmission.objects.filter(user_id=result[i]["user_id"], contest_id=contest_id)
|
submissions = ContestSubmission.objects.filter(user_id=result[i]["user_id"], contest_id=contest_id)
|
||||||
result[i]["submissions"] = {}
|
result[i]["submissions"] = {}
|
||||||
for item in submissions:
|
result[i]["problems"] = []
|
||||||
result[i]["submissions"][item.problem_id] = item
|
for problem in contest_problems:
|
||||||
|
try:
|
||||||
|
status = submissions.get(problem=problem)
|
||||||
|
result[i]["problems"].append({
|
||||||
|
"first_achieved": status.first_achieved,
|
||||||
|
"ac": status.ac,
|
||||||
|
"failed_number": status.total_submission_number,
|
||||||
|
"ac_time": get_the_time_format(status.ac_time)})
|
||||||
|
if status.ac:
|
||||||
|
result[i]["problems"][-1]["failed_number"] -= 1
|
||||||
|
except ContestSubmission.DoesNotExist:
|
||||||
|
result[i]["problems"].append({})
|
||||||
result[i]["total_ac"] = submissions.filter(ac=True).count()
|
result[i]["total_ac"] = submissions.filter(ac=True).count()
|
||||||
result[i]["user"] = User.objects.get(id=result[i]["user_id"])
|
result[i]["username"] = User.objects.get(id=result[i]["user_id"]).username
|
||||||
result[i]["total_time"] = submissions.filter(ac=True).aggregate(total_time=Sum("total_time"))["total_time"]
|
result[i]["total_time"] = get_the_time_format(submissions.filter(ac=True).aggregate(total_time=Sum("total_time"))["total_time"])
|
||||||
|
result = sorted(result, cmp=_cmp, reverse=True)
|
||||||
|
r.set("contest_rank_" + contest_id, json.dumps(list(result)))
|
||||||
|
else:
|
||||||
|
# 从缓存读取排名信息
|
||||||
|
result = r.get("contest_rank_" + contest_id)
|
||||||
|
if result:
|
||||||
|
result = json.loads(result)
|
||||||
|
else:
|
||||||
|
result = []
|
||||||
|
|
||||||
return render(request, "oj/contest/contest_rank.html",
|
return render(request, "oj/contest/contest_rank.html",
|
||||||
{"contest": contest, "contest_problems": contest_problems,
|
{"contest": contest, "contest_problems": contest_problems,
|
||||||
"result": sorted(result, cmp=_cmp, reverse=True),
|
"result": result,
|
||||||
"auto_refresh": request.GET.get("auto_refresh", None) == "true"})
|
"auto_refresh": request.GET.get("auto_refresh", None) == "true",
|
||||||
|
"real_time_rank": contest.real_time_rank})
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from judge.judger.result import result
|
|||||||
from submission.models import Submission
|
from submission.models import Submission
|
||||||
from problem.models import Problem
|
from problem.models import Problem
|
||||||
from contest.models import ContestProblem, Contest, ContestSubmission
|
from contest.models import ContestProblem, Contest, ContestSubmission
|
||||||
|
from account.models import User
|
||||||
logger = logging.getLogger("app_info")
|
logger = logging.getLogger("app_info")
|
||||||
|
|
||||||
|
|
||||||
@@ -53,10 +53,8 @@ class MessageQueue(object):
|
|||||||
contest_submission = ContestSubmission.objects.get(user_id=submission.user_id, contest=contest,
|
contest_submission = ContestSubmission.objects.get(user_id=submission.user_id, contest=contest,
|
||||||
problem_id=contest_problem.id)
|
problem_id=contest_problem.id)
|
||||||
# 提交次数加1
|
# 提交次数加1
|
||||||
contest_submission.total_submission_number += 1
|
|
||||||
|
|
||||||
if submission.result == result["accepted"]:
|
if submission.result == result["accepted"]:
|
||||||
|
|
||||||
# 避免这道题已经 ac 了,但是又重新提交了一遍
|
# 避免这道题已经 ac 了,但是又重新提交了一遍
|
||||||
if not contest_submission.ac:
|
if not contest_submission.ac:
|
||||||
# 这种情况是这个题目前处于错误状态,就使用已经存储了的罚时加上这道题的实际用时
|
# 这种情况是这个题目前处于错误状态,就使用已经存储了的罚时加上这道题的实际用时
|
||||||
@@ -64,30 +62,40 @@ class MessageQueue(object):
|
|||||||
# logger.debug(submission.create_time)
|
# logger.debug(submission.create_time)
|
||||||
# logger.debug((submission.create_time - contest.start_time).total_seconds())
|
# logger.debug((submission.create_time - contest.start_time).total_seconds())
|
||||||
# logger.debug(int((submission.create_time - contest.start_time).total_seconds() / 60))
|
# logger.debug(int((submission.create_time - contest.start_time).total_seconds() / 60))
|
||||||
contest_submission.ac_time = int((submission.create_time - contest.start_time).total_seconds() / 60)
|
contest_submission.ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||||
contest_submission.total_time += contest_submission.ac_time
|
contest_submission.total_time += contest_submission.ac_time
|
||||||
|
contest_submission.total_submission_number += 1
|
||||||
# 标记为已经通过
|
# 标记为已经通过
|
||||||
|
if contest_problem.total_accepted_number == 0:
|
||||||
|
contest_submission.first_achieved = True
|
||||||
contest_submission.ac = True
|
contest_submission.ac = True
|
||||||
# contest problem ac 计数器加1
|
# contest problem ac 计数器加1
|
||||||
contest_problem.total_accepted_number += 1
|
contest_problem.total_accepted_number += 1
|
||||||
else:
|
else:
|
||||||
# 如果这个提交是错误的,就罚时20分钟
|
# 如果这个提交是错误的,就罚时20分钟
|
||||||
contest_submission.total_time += 20
|
contest_submission.total_time += 1200
|
||||||
|
contest_submission.total_submission_number += 1
|
||||||
contest_submission.save()
|
contest_submission.save()
|
||||||
contest_problem.save()
|
contest_problem.save()
|
||||||
except ContestSubmission.DoesNotExist:
|
except ContestSubmission.DoesNotExist:
|
||||||
# 第一次提交
|
# 第一次提交
|
||||||
is_ac = submission.result == result["accepted"]
|
is_ac = submission.result == result["accepted"]
|
||||||
|
first_achieved = False
|
||||||
|
ac_time = 0
|
||||||
if is_ac:
|
if is_ac:
|
||||||
total_time = int((submission.create_time - contest.start_time).total_seconds() / 60)
|
ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||||
|
total_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||||
# 增加题目总的ac数计数器
|
# 增加题目总的ac数计数器
|
||||||
|
if contest_problem.total_accepted_number == 0:
|
||||||
|
first_achieved = True
|
||||||
contest_problem.total_accepted_number += 1
|
contest_problem.total_accepted_number += 1
|
||||||
contest_problem.save()
|
contest_problem.save()
|
||||||
else:
|
else:
|
||||||
# 没过罚时20分钟
|
# 没过罚时20分钟
|
||||||
total_time = 20
|
total_time = 1200
|
||||||
ContestSubmission.objects.create(user_id=submission.user_id, contest=contest, problem=contest_problem,
|
ContestSubmission.objects.create(user_id=submission.user_id, contest=contest, problem=contest_problem,
|
||||||
ac=is_ac, total_time=total_time)
|
ac=is_ac, total_time=total_time, first_achieved=first_achieved,
|
||||||
|
ac_time=ac_time)
|
||||||
|
|
||||||
|
|
||||||
logger.debug("Start message queue")
|
logger.debug("Start message queue")
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class CreateProblemSerializer(serializers.Serializer):
|
|||||||
difficulty = serializers.IntegerField()
|
difficulty = serializers.IntegerField()
|
||||||
tags = serializers.ListField(child=serializers.CharField(max_length=10))
|
tags = serializers.ListField(child=serializers.CharField(max_length=10))
|
||||||
hint = serializers.CharField(max_length=3000, allow_blank=True)
|
hint = serializers.CharField(max_length=3000, allow_blank=True)
|
||||||
|
visible = visible = serializers.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
class ProblemTagSerializer(serializers.ModelSerializer):
|
class ProblemTagSerializer(serializers.ModelSerializer):
|
||||||
|
|||||||
@@ -13,13 +13,16 @@ from rest_framework.views import APIView
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
from announcement.models import Announcement
|
from announcement.models import Announcement
|
||||||
from utils.shortcuts import (serializer_invalid_response, error_response,
|
from utils.shortcuts import (serializer_invalid_response, error_response,
|
||||||
success_response, paginate, rand_str, error_page)
|
success_response, paginate, rand_str, error_page)
|
||||||
from .serizalizers import (CreateProblemSerializer, EditProblemSerializer, ProblemSerializer,
|
from .serizalizers import (CreateProblemSerializer, EditProblemSerializer, ProblemSerializer,
|
||||||
ProblemTagSerializer, CreateProblemTagSerializer)
|
ProblemTagSerializer, CreateProblemTagSerializer)
|
||||||
from .models import Problem, ProblemTag
|
from .models import Problem, ProblemTag
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger("app_info")
|
||||||
|
|
||||||
def problem_page(request, problem_id):
|
def problem_page(request, problem_id):
|
||||||
try:
|
try:
|
||||||
@@ -56,7 +59,8 @@ class ProblemAdminAPIView(APIView):
|
|||||||
memory_limit=data["memory_limit"],
|
memory_limit=data["memory_limit"],
|
||||||
difficulty=data["difficulty"],
|
difficulty=data["difficulty"],
|
||||||
created_by=request.user,
|
created_by=request.user,
|
||||||
hint=data["hint"])
|
hint=data["hint"],
|
||||||
|
visible=data["visible"])
|
||||||
for tag in data["tags"]:
|
for tag in data["tags"]:
|
||||||
try:
|
try:
|
||||||
tag = ProblemTag.objects.get(name=tag)
|
tag = ProblemTag.objects.get(name=tag)
|
||||||
@@ -151,8 +155,9 @@ class TestCaseUploadAPIView(APIView):
|
|||||||
with open(tmp_zip, "wb") as test_case_zip:
|
with open(tmp_zip, "wb") as test_case_zip:
|
||||||
for chunk in f:
|
for chunk in f:
|
||||||
test_case_zip.write(chunk)
|
test_case_zip.write(chunk)
|
||||||
except IOError:
|
except IOError as e:
|
||||||
return error_response(u"上传错误,写入临时目录失败")
|
logger.error(e)
|
||||||
|
return error_response(u"上传失败")
|
||||||
|
|
||||||
test_case_file = zipfile.ZipFile(tmp_zip, 'r')
|
test_case_file = zipfile.ZipFile(tmp_zip, 'r')
|
||||||
name_list = test_case_file.namelist()
|
name_list = test_case_file.namelist()
|
||||||
|
|||||||
@@ -108,3 +108,8 @@ li.list-group-item {
|
|||||||
#about-acm-logo{
|
#about-acm-logo{
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rank .first-achieved{
|
||||||
|
background: #33CC99;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
ajaxData.groups = selectedGroups;
|
ajaxData.groups = selectedGroups;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (vm.password) {
|
if (vm.editPassword) {
|
||||||
ajaxData.password = vm.editPassword;
|
ajaxData.password = vm.editPassword;
|
||||||
ajaxData.contest_type = 2;
|
ajaxData.contest_type = 2;
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
allGroups: [],
|
allGroups: [],
|
||||||
showGlobalViewRadio: true,
|
showGlobalViewRadio: true,
|
||||||
|
admin_type: 1,
|
||||||
getNext: function () {
|
getNext: function () {
|
||||||
if (!vm.nextPage)
|
if (!vm.nextPage)
|
||||||
return;
|
return;
|
||||||
@@ -211,6 +211,39 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
if (el)
|
if (el)
|
||||||
problemId = el.id;
|
problemId = el.id;
|
||||||
vm.$fire("up!showContestSubmissionPage", problemId, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
vm.$fire("up!showContestSubmissionPage", problemId, vm.contestList[vm.editingProblemContestIndex - 1].id, vm.editMode);
|
||||||
|
},
|
||||||
|
addToProblemList: function (problem) {
|
||||||
|
var ajaxData = {
|
||||||
|
title: problem.title,
|
||||||
|
description: problem.description,
|
||||||
|
time_limit: problem.time_limit,
|
||||||
|
memory_limit: problem.memory_limit,
|
||||||
|
samples: problem.samples,
|
||||||
|
test_case_id: problem.test_case_id,
|
||||||
|
hint: problem.hint,
|
||||||
|
source: problem.contest.title,
|
||||||
|
visible: false,
|
||||||
|
tags: [],
|
||||||
|
input_description: problem.input_description,
|
||||||
|
output_description: problem.output_description,
|
||||||
|
difficulty: 0
|
||||||
|
};
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
|
url: "/api/admin/problem/",
|
||||||
|
dataType: "json",
|
||||||
|
data: JSON.stringify(ajaxData),
|
||||||
|
method: "post",
|
||||||
|
contentType: "application/json",
|
||||||
|
success: function (data) {
|
||||||
|
if (!data.code) {
|
||||||
|
bsAlert("题目添加成功!题目现在处于隐藏状态,请到题目列表手动修改,并添加分类和难度信息!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
vm.$watch("showVisibleOnly", function () {
|
vm.$watch("showVisibleOnly", function () {
|
||||||
@@ -266,6 +299,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
var admin_type = data.data.admin_type;
|
var admin_type = data.data.admin_type;
|
||||||
|
vm.admin_type = admin_type;
|
||||||
if (data.data.admin_type == 1) {
|
if (data.data.admin_type == 1) {
|
||||||
vm.isGlobal = false;
|
vm.isGlobal = false;
|
||||||
vm.showGlobalViewRadio = false;
|
vm.showGlobalViewRadio = false;
|
||||||
@@ -278,6 +312,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
if (!data.data.length) {
|
if (!data.data.length) {
|
||||||
|
|
||||||
if (admin_type != 2)
|
if (admin_type != 2)
|
||||||
bsAlert("您的用户权限只能创建小组内比赛,但是您还没有创建过小组");
|
bsAlert("您的用户权限只能创建小组内比赛,但是您还没有创建过小组");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -117,11 +117,11 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert", "ZeroClipboard"],
|
|||||||
|
|
||||||
function guessLanguage(code) {
|
function guessLanguage(code) {
|
||||||
//cpp
|
//cpp
|
||||||
if (code.indexOf("using namespace std") > -1) {
|
if (code.indexOf("using namespace std") > -1||code.indexOf("<cstdio>") > -1) {
|
||||||
return "2";
|
return "2";
|
||||||
}
|
}
|
||||||
//c
|
if (code.indexOf("printf"))
|
||||||
if (code.indexOf("printf") > -1) {
|
{
|
||||||
return "1";
|
return "1";
|
||||||
}
|
}
|
||||||
//java
|
//java
|
||||||
@@ -146,6 +146,19 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert", "ZeroClipboard"],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (language < 3) {
|
||||||
|
if (code.indexOf("__int64") > -1) {
|
||||||
|
if (!confirm("您是否在尝试使用'__int64'类型? 这不是 c/c++ 标准并将引发编译错误可以使用 'long long' 代替(详见 关于->帮助),是否仍然提交?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (code.indexOf("%I64d") > -1) {
|
||||||
|
if (!confirm("您是否在尝试将'%I64d'用于long long类型的I/O? 这不被支持,并可能会导致程序输出异常,可以使用 '%lld' 代替(详见 关于->帮助),是否仍然提交?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (location.href.indexOf("contest") > -1) {
|
if (location.href.indexOf("contest") > -1) {
|
||||||
var problemId = location.pathname.split("/")[4];
|
var problemId = location.pathname.split("/")[4];
|
||||||
var contestId = location.pathname.split("/")[2];
|
var contestId = location.pathname.split("/")[2];
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ from .models import Submission
|
|||||||
from .serializers import CreateSubmissionSerializer, SubmissionSerializer, SubmissionhareSerializer
|
from .serializers import CreateSubmissionSerializer, SubmissionSerializer, SubmissionhareSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SubmissionAPIView(APIView):
|
class SubmissionAPIView(APIView):
|
||||||
@login_required
|
@login_required
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
@@ -81,7 +80,8 @@ def problem_my_submissions_list_page(request, problem_id):
|
|||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return error_page(request, u"问题不存在")
|
return error_page(request, u"问题不存在")
|
||||||
|
|
||||||
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=problem.id, contest_id__isnull=True).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")
|
values("id", "result", "create_time", "accepted_answer_time", "language")
|
||||||
|
|
||||||
return render(request, "oj/problem/my_submissions_list.html",
|
return render(request, "oj/problem/my_submissions_list.html",
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="navbar" class="navbar-collapse collapse">
|
<div id="navbar" class="navbar-collapse collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="active"><a href="#">主页</a></li>
|
<li class="active"><a href="/" target="_blank">主页</a></li>
|
||||||
<li><a href="#about">题目</a></li>
|
<li><a href="#problem">题目</a></li>
|
||||||
<li><a href="#contact">提交</a></li>
|
<li><a href="#">提交</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
|||||||
@@ -178,6 +178,8 @@
|
|||||||
ms-click="showProblemEditPage(el)">编辑</a>
|
ms-click="showProblemEditPage(el)">编辑</a>
|
||||||
<a href="javascript:void(0)" class="btn-sm btn-info"
|
<a href="javascript:void(0)" class="btn-sm btn-info"
|
||||||
ms-click="showSubmissionPage(el)">提交</a>
|
ms-click="showSubmissionPage(el)">提交</a>
|
||||||
|
<a href="javascript:void(0)" class="btn-sm btn-info"
|
||||||
|
ms-click="addToProblemList(el)" ms-visible="admin_type=='2'">添加到前台</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{% extends "oj_base.html" %}
|
{% extends "oj_base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% load submission %}
|
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
|
|
||||||
<ul class="nav nav-tabs nav-tabs-google contest-tab">
|
<ul class="nav nav-tabs nav-tabs-google contest-tab">
|
||||||
@@ -19,31 +18,43 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h2 class="text-center">排名(
|
||||||
|
{% if real_time_rank %}
|
||||||
|
实时
|
||||||
|
{% else %}
|
||||||
|
已封榜
|
||||||
|
{% endif %})
|
||||||
|
</h2>
|
||||||
{% if result %}
|
{% if result %}
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered text-center">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
<th>用户名</th>
|
<th class="text-center">用户名</th>
|
||||||
<th>AC / 总提交</th>
|
<th class="text-center">AC / 总提交</th>
|
||||||
<th>用时 + 罚时</th>
|
<th class="text-center">用时 + 罚时</th>
|
||||||
{% for item in contest_problems %}
|
{% for item in contest_problems %}
|
||||||
<th><a href="/contest/{{ contest.id }}/problem/{{ item.id }}/">{{ item.sort_index }}</a>
|
<th class="text-center"><a
|
||||||
|
href="/contest/{{ contest.id }}/problem/{{ item.id }}/">{{ item.sort_index }}</a>
|
||||||
</th>
|
</th>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="rank">
|
||||||
{% for item in result %}
|
{% for item in result %}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ forloop.counter }}</th>
|
<th scope="row">{{ forloop.counter }}</th>
|
||||||
<td>{{ item.user.username }}</td>
|
<td>{{ item.username }}</td>
|
||||||
<td>{{ item.total_ac }} / {{ item.total_submit }}</td>
|
<td>{{ item.total_ac }} / {{ item.total_submit }}</td>
|
||||||
<td>{% if item.total_time %}{{ item.total_time }} min{% else %}--{% endif %}</td>
|
<td>{% if item.total_time %}{{ item.total_time }}{% else %}--{% endif %}</td>
|
||||||
{% for problem in contest_problems %}
|
{% for problem in item.problems %}
|
||||||
<td class="{% submission_problem_result_class problem item.submissions %}">
|
<td class="
|
||||||
{% submission_problem problem item.submissions %}
|
{% if problem %}{% if problem.ac %}{% if problem.first_achieved %}first-achieved{% else %}alert-success{% endif %}{% else %}alert-danger{% endif %}{% endif %}">
|
||||||
|
{% if problem.ac %}{{ problem.ac_time }}{% endif %}
|
||||||
|
{% if problem.failed_number %}
|
||||||
|
(-{{ problem.failed_number }})
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
@@ -59,6 +70,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@
|
|||||||
{{ request.user.username }}
|
{{ request.user.username }}
|
||||||
<span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
|
{% if request.user.admin_type == 2 %}
|
||||||
|
<li><a href="/admin/">后台管理</a></li>
|
||||||
|
{% endif %}
|
||||||
<li><a href="/submissions/">我的提交</a></li>
|
<li><a href="/submissions/">我的提交</a></li>
|
||||||
<li><a href="#">我的资料</a></li>
|
<li><a href="#">我的资料</a></li>
|
||||||
<li role="separator" class="divider"></li>
|
<li role="separator" class="divider"></li>
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{% extends "oj_base.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<div class="container main">
|
||||||
|
<ul class="nav nav-tabs nav-tabs-google">
|
||||||
|
<li role="presentation" class="active">
|
||||||
|
<a href="/help/">帮助</a>
|
||||||
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="/about/">关于</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div>
|
||||||
|
<h2 class="text-center">判题系统</h2>
|
||||||
|
<h4>判题结果</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Accepted: 你的答案符合判题标准</li>
|
||||||
|
<li>Runtime Error: 你的程序运行时出现错误(指针越界,栈溢出,有未处理的异常,主函数返回值非零等)</li>
|
||||||
|
<li>Time Limit Exceeded: 你的程序执行时间超出题目要求</li>
|
||||||
|
<li>Memory Limit Exceeded: 你的程序内存使用超出题目要求</li>
|
||||||
|
<li>Compile Error: 你的程序在编译(包括链接)时出现错误</li>
|
||||||
|
<li>Wrong Answer: 你的程序输出的答案不符合判题标准</li>
|
||||||
|
<li>System Error: 判题系统发生故障,请等待重判</li>
|
||||||
|
<li>Waiting: 你的提交正在等待处理</li>
|
||||||
|
</ul>
|
||||||
|
<h4>支持的语言</h4>
|
||||||
|
<ul>
|
||||||
|
<li>C (GCC 4.8)</li>
|
||||||
|
|
||||||
|
<li>C++ (G++ 4.3)</li>
|
||||||
|
|
||||||
|
<li>Java (Oracle JDK 1.7)</li>
|
||||||
|
</ul>
|
||||||
|
<h4>编译参数</h4>
|
||||||
|
<ul>
|
||||||
|
<li>C</li>
|
||||||
|
<p>gcc -DONLINE_JUDGE -O2 -w -std=c99 {src_path} -lm -o {exe_path}main</p>
|
||||||
|
<li>C++</li>
|
||||||
|
<p>g++ -DONLINE_JUDGE -O2 -w -std=c++11 {src_path} -lm -o {exe_path}main</p>
|
||||||
|
<li>Java</li>
|
||||||
|
<p>javac {src_path} -d {exe_path}</p>
|
||||||
|
<p>java -cp {exe_path} Main</p>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 class="text-center">常见问题</h2>
|
||||||
|
<ul>
|
||||||
|
<li>输入输出</li>
|
||||||
|
<p>无特殊说明,请使用标准输入输出</p>
|
||||||
|
<li>C/C++的64位整数类型</li>
|
||||||
|
<p>请使用long long声明,使用cin/cout或 %lld输入输出</p>
|
||||||
|
<li>判题结果与本地执行结果不一致</li>
|
||||||
|
<p>是否使用了不同版本的编译器(VC和TC并不完全符合C/C++标准)</p>
|
||||||
|
<p>判题时可能使用了与您测试时不同的测试数据(不仅限于样例中展示的数据)</p>
|
||||||
|
<li>程序执行时间和占用的内存如何计算</li>
|
||||||
|
<p>执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</p>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -29,33 +29,7 @@ def translate_result_class(value):
|
|||||||
return "danger"
|
return "danger"
|
||||||
|
|
||||||
|
|
||||||
def get_contest_submission_problem_detail(contest_problem, my_submission):
|
|
||||||
if contest_problem.id in my_submission:
|
|
||||||
submission = my_submission[contest_problem.id]
|
|
||||||
if submission.ac:
|
|
||||||
# 只提交了一次就AC
|
|
||||||
if submission.total_submission_number == 1:
|
|
||||||
return str(submission.ac_time) + " min"
|
|
||||||
else:
|
|
||||||
return "20 min × " + str(submission.total_submission_number - 1) + " WA + " + str(submission.ac_time) + " min"
|
|
||||||
return str(submission.total_submission_number) + " WA"
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def get_submission_problem_result_class(contest_problem, my_submission):
|
|
||||||
if contest_problem.id in my_submission:
|
|
||||||
submission = my_submission[contest_problem.id]
|
|
||||||
if submission.ac:
|
|
||||||
return "success"
|
|
||||||
else:
|
|
||||||
return "danger"
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
register.filter("translate_result", translate_result)
|
register.filter("translate_result", translate_result)
|
||||||
register.filter("translate_language", translate_language)
|
register.filter("translate_language", translate_language)
|
||||||
register.filter("translate_result_class", translate_result_class)
|
register.filter("translate_result_class", translate_result_class)
|
||||||
register.simple_tag(get_contest_submission_problem_detail, name="submission_problem")
|
|
||||||
register.simple_tag(get_submission_problem_result_class, name="submission_problem_result_class")
|
|
||||||
@@ -5,7 +5,9 @@ from rest_framework.response import Response
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from utils.shortcuts import rand_str
|
from utils.shortcuts import rand_str
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger("app_info")
|
||||||
|
|
||||||
class SimditorImageUploadAPIView(APIView):
|
class SimditorImageUploadAPIView(APIView):
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
@@ -22,7 +24,8 @@ class SimditorImageUploadAPIView(APIView):
|
|||||||
with open(image_dir, "wb") as imageFile:
|
with open(image_dir, "wb") as imageFile:
|
||||||
for chunk in img:
|
for chunk in img:
|
||||||
imageFile.write(chunk)
|
imageFile.write(chunk)
|
||||||
except IOError:
|
except IOError as e:
|
||||||
|
logger.error(e)
|
||||||
return Response(data={
|
return Response(data={
|
||||||
"success": True,
|
"success": True,
|
||||||
"msg": "上传错误",
|
"msg": "上传错误",
|
||||||
|
|||||||
Reference in New Issue
Block a user