Merge branch 'dev' into hohoTT-dev
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -62,3 +62,4 @@ static/src/upload_image/*
|
||||
build.txt
|
||||
tmp/
|
||||
test_case/
|
||||
release/
|
||||
@@ -1 +0,0 @@
|
||||
__author__ = 'root'
|
||||
@@ -1,74 +0,0 @@
|
||||
import django
|
||||
from contest.models import *
|
||||
from problem.models import *
|
||||
from submission.models import Submission
|
||||
|
||||
import redis
|
||||
|
||||
from judge.judger_controller.tasks import judge
|
||||
from judge.judger_controller.settings import redis_config
|
||||
|
||||
django.setup()
|
||||
|
||||
|
||||
def rejudge(submission):
|
||||
# for submission in submission:
|
||||
# submission_id = submission.id
|
||||
# try:
|
||||
# command = "%s run -t -i --privileged --rm=true " \
|
||||
# "-v %s:/var/judger/test_case/ " \
|
||||
# "-v %s:/var/judger/code/ " \
|
||||
# "%s " \
|
||||
# "python judge/judger/run.py " \
|
||||
# "--solution_id %s --time_limit %s --memory_limit %s --test_case_id %s" % \
|
||||
# (docker_config["docker_path"],
|
||||
# test_case_dir,
|
||||
# source_code_dir,
|
||||
# docker_config["image_name"],
|
||||
# submission_id, str(time_limit), str(memory_limit), test_case_id)
|
||||
# subprocess.call(command, shell=docker_config["shell"])
|
||||
# except Exception as e:
|
||||
# print e
|
||||
return
|
||||
|
||||
|
||||
def easy_rejudge(submissions, map_table, user_id, contest_id=None):
|
||||
try:
|
||||
user = User.objects.get(pk=user_id)
|
||||
except User.DoesNotExist:
|
||||
print "User.DoesNotExist!"
|
||||
return
|
||||
problemDict = {}
|
||||
for oldSubmission in submission:
|
||||
problem_id = map_table[oldSubmission.problem_id]
|
||||
|
||||
if problem_id in problemDict:
|
||||
problem = problemDict[problem_id]
|
||||
else:
|
||||
try:
|
||||
p = Problem.objects.get(pk=problem_id)
|
||||
except Problem.DoesNotExist:
|
||||
print " Problem.DoesNotExist!" + str(problem_id)
|
||||
continue
|
||||
problem = p
|
||||
problemDict[problem_id] = p
|
||||
|
||||
submission = Submission.objects.create(
|
||||
user_id=user_id,
|
||||
language=oldSubmission.language,
|
||||
code=oldSubmission.code,
|
||||
contest_id=contest_id,
|
||||
problem_id=problem_id,
|
||||
originResult=oldSubmission.result
|
||||
)
|
||||
try:
|
||||
judge.delay(submission.id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||
except Exception:
|
||||
print "error!"
|
||||
continue
|
||||
|
||||
r = redis.Redis(host=redis_config["host"], port=redis_config["port"], db=redis_config["db"])
|
||||
r.incr("judge_queue_length")
|
||||
|
||||
return
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import django
|
||||
from contest.models import *
|
||||
from problem.models import *
|
||||
django.setup()
|
||||
def add_exist_problem_to_contest(problems, contest_id):
|
||||
try:
|
||||
contest = Contest.objects.get(pk=contest_id)
|
||||
except Contest.DoesNotExist:
|
||||
print "Contest Doesn't Exist!"
|
||||
return
|
||||
i = 1
|
||||
for problem in problems:
|
||||
print "Add the problem:"
|
||||
print problem.title
|
||||
print "The sort Index is" + str(i) + " You Can modify it latter as you like~"
|
||||
ContestProblem.objects.create(contest=contest, sort_index=str(i),
|
||||
title=problem.title, description=problem.description,
|
||||
input_description=problem.input_description,
|
||||
output_description=problem.output_description,
|
||||
samples=problem.samples,
|
||||
test_case_id=problem.test_case_id,
|
||||
hint=problem.hint,
|
||||
created_by=problem.created_by,
|
||||
time_limit=problem.time_limit,
|
||||
memory_limit=problem.memory_limit)
|
||||
i += 1
|
||||
return
|
||||
def add_contest_problem_to_problem(contest_id):
|
||||
try:
|
||||
contest = Contest.objects.get(pk=contest_id)
|
||||
except Contest.DoesNotExist:
|
||||
print "Contest Doesn't Exist!"
|
||||
return
|
||||
#Get all problems in this contest
|
||||
problems = ContestProblem.objects.filter(contest=contest)
|
||||
|
||||
#get a tag
|
||||
try:
|
||||
tag = ProblemTag.objects.get(name=contest.title)
|
||||
except ProblemTag.DoesNotExist:
|
||||
tag = ProblemTag.objects.create(name=contest.title)
|
||||
|
||||
#for each problem
|
||||
for problem in problems:
|
||||
print "Add problem to problem list:"
|
||||
print problem.title
|
||||
p = Problem.objects.create(title=problem.title,
|
||||
description=problem.description,
|
||||
input_description=problem.input_description,
|
||||
output_description=problem.output_description,
|
||||
samples=problem.samples,
|
||||
test_case_id=problem.test_case_id,
|
||||
hint=problem.hint,
|
||||
created_by=problem.created_by,
|
||||
time_limit=problem.time_limit,
|
||||
memory_limit=problem.memory_limit,
|
||||
visible = False,
|
||||
difficulty = 0,
|
||||
source = contest.title)
|
||||
p.tags.add(tag)
|
||||
return
|
||||
@@ -16,8 +16,21 @@ def announcement_page(request, announcement_id):
|
||||
try:
|
||||
announcement = Announcement.objects.get(id=announcement_id, visible=True)
|
||||
except Announcement.DoesNotExist:
|
||||
return error_page(request, u"模板不存在")
|
||||
return render(request, "oj/announcement/announcement.html", {"announcement": announcement})
|
||||
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):
|
||||
|
||||
@@ -6,10 +6,9 @@ from account.models import User
|
||||
from problem.models import AbstractProblem
|
||||
from group.models import Group
|
||||
|
||||
|
||||
GROUP_CONTEST = 0
|
||||
PUBLIC_CONTEST = 1
|
||||
PASSWORD_PUBLIC_CONTEST = 2
|
||||
PASSWORD_PROTECTED_CONTEST = 2
|
||||
|
||||
|
||||
class Contest(models.Model):
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
# coding=utf-8
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase, Client
|
||||
from django.http import HttpResponse
|
||||
|
||||
from rest_framework.test import APITestCase, APIClient
|
||||
|
||||
from account.models import User
|
||||
from group.models import Group
|
||||
from contest.models import Contest, ContestProblem
|
||||
from .models import ContestSubmission
|
||||
from .models import GROUP_CONTEST, PUBLIC_CONTEST, PASSWORD_PUBLIC_CONTEST
|
||||
from announcement.models import Announcement
|
||||
from .models import GROUP_CONTEST, PASSWORD_PROTECTED_CONTEST
|
||||
from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN
|
||||
from decorators import check_user_contest_permission
|
||||
|
||||
|
||||
class ContestAdminAPITest(APITestCase):
|
||||
@@ -36,13 +33,13 @@ class ContestAdminAPITest(APITestCase):
|
||||
join_group_setting=0, visible=True,
|
||||
admin=user1)
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, 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="test1"))
|
||||
self.group_contest = Contest.objects.create(title="titley", description="descriptiony", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
@@ -57,7 +54,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
|
||||
def test_global_contest_does_not_has_privileges(self):
|
||||
self.client.login(username="test2", password="testbb")
|
||||
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": PASSWORD_PUBLIC_CONTEST,
|
||||
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": PASSWORD_PROTECTED_CONTEST,
|
||||
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
|
||||
"end_time": "2015-08-15T12:00:00.000Z", "password": "aabb", "visible": True}
|
||||
response = self.client.post(self.url, data=data)
|
||||
@@ -65,7 +62,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
|
||||
def test_global_contest_password_exists(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": PASSWORD_PUBLIC_CONTEST,
|
||||
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": PASSWORD_PROTECTED_CONTEST,
|
||||
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
|
||||
"end_time": "2015-08-15T12:00:00.000Z", "visible": True}
|
||||
response = self.client.post(self.url, data=data)
|
||||
@@ -81,7 +78,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
|
||||
def test_global_contest_successfully(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"title": "title1", "description": "description1", "mode": 1, "contest_type": PASSWORD_PUBLIC_CONTEST,
|
||||
data = {"title": "title1", "description": "description1", "mode": 1, "contest_type": PASSWORD_PROTECTED_CONTEST,
|
||||
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
|
||||
"end_time": "2015-08-15T12:00:00.000Z", "password": "aabb", "visible": True}
|
||||
response = self.client.post(self.url, data=data)
|
||||
@@ -105,7 +102,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
|
||||
def test_time_error(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"title": "title2", "description": "description2", "mode": 1, "contest_type": PASSWORD_PUBLIC_CONTEST,
|
||||
data = {"title": "title2", "description": "description2", "mode": 1, "contest_type": PASSWORD_PROTECTED_CONTEST,
|
||||
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T12:00:00.000Z",
|
||||
"end_time": "2015-08-15T10:00:00.000Z", "password": "aabb", "visible": True}
|
||||
response = self.client.post(self.url, data=data)
|
||||
@@ -113,7 +110,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
|
||||
def test_contest_has_exists(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"title": "titlex", "description": "descriptionx", "mode": 1, "contest_type": PASSWORD_PUBLIC_CONTEST,
|
||||
data = {"title": "titlex", "description": "descriptionx", "mode": 1, "contest_type": PASSWORD_PROTECTED_CONTEST,
|
||||
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
|
||||
"end_time": "2015-08-15T12:00:00.000Z", "password": "aabb", "visible": True}
|
||||
response = self.client.post(self.url, data=data)
|
||||
@@ -129,7 +126,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
def test_contest_does_not_exist(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"id": self.global_contest.id + 10, "title": "title2", "description": "description2", "mode": 1,
|
||||
"contest_type": PASSWORD_PUBLIC_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"contest_type": PASSWORD_PROTECTED_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T12:00:00.000Z", "password": "aabb",
|
||||
"visible": True}
|
||||
response = self.client.put(self.url, data=data)
|
||||
@@ -138,7 +135,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
def test_edit_global_contest_successfully(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"id": self.global_contest.id, "title": "titlez", "description": "descriptionz", "mode": 1,
|
||||
"contest_type": PASSWORD_PUBLIC_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"contest_type": PASSWORD_PROTECTED_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T13:00:00.000Z", "password": "aabb",
|
||||
"visible": True}
|
||||
response = self.client.put(self.url, data=data)
|
||||
@@ -178,7 +175,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
def test_edit_contest_has_exists(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"id": self.global_contest.id, "title": "titley", "description": "descriptiony", "mode": 1,
|
||||
"contest_type": PASSWORD_PUBLIC_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"contest_type": PASSWORD_PROTECTED_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T12:00:00.000Z", "password": "aabb",
|
||||
"visible": True}
|
||||
response = self.client.put(self.url, data=data)
|
||||
@@ -187,7 +184,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
def test_edit_global_contest_does_not_has_privileges(self):
|
||||
self.client.login(username="test2", password="testbb")
|
||||
data = {"id": self.global_contest.id, "title": "titlexxxxxxxxx", "description": "descriptionxxxxxx", "mode": 1,
|
||||
"contest_type": PASSWORD_PUBLIC_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"contest_type": PASSWORD_PROTECTED_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T12:00:00.000Z", "password": "aabb",
|
||||
"visible": True}
|
||||
response = self.client.put(self.url, data=data)
|
||||
@@ -196,7 +193,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
def test_edit_global_contest_password_exists(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"id": self.global_contest.id, "title": "title0", "description": "description0", "mode": 1,
|
||||
"contest_type": PASSWORD_PUBLIC_CONTEST, "show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
|
||||
"contest_type": PASSWORD_PROTECTED_CONTEST, "show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
|
||||
"end_time": "2015-08-15T12:00:00.000Z", "visible": True}
|
||||
response = self.client.put(self.url, data=data)
|
||||
self.assertEqual(response.data, {"code": 1, "data": u"此比赛为有密码的公开赛,密码不可为空"})
|
||||
@@ -204,7 +201,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
def test_edit_time_error(self):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
data = {"id": self.global_contest.id, "title": "titleaaaa", "description": "descriptionaaaaa", "mode": 1,
|
||||
"contest_type": PASSWORD_PUBLIC_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"contest_type": PASSWORD_PROTECTED_CONTEST, "show_rank": True, "show_user_submission": True,
|
||||
"start_time": "2015-08-15T12:00:00.000Z", "end_time": "2015-08-15T10:00:00.000Z", "password": "aabb",
|
||||
"visible": True}
|
||||
response = self.client.put(self.url, data=data)
|
||||
@@ -247,7 +244,7 @@ class ContestProblemAdminAPItEST(APITestCase):
|
||||
self.user3.save()
|
||||
self.client.login(username="test1", password="testaa")
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
@@ -417,7 +414,7 @@ class ContestPasswordVerifyAPITest(APITestCase):
|
||||
self.user2.save()
|
||||
self.client.login(username="test1", password="testaa")
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
@@ -457,7 +454,7 @@ class ContestPageTest(TestCase):
|
||||
self.user1.save()
|
||||
self.client.login(username="test1", password="testaa")
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
@@ -481,7 +478,7 @@ class ContestProblemPageTest(TestCase):
|
||||
self.user1.save()
|
||||
self.client.login(username="test1", password="testaa")
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
@@ -525,7 +522,7 @@ class ContestProblemListPageTest(TestCase):
|
||||
self.user1.save()
|
||||
self.client.login(username="test1", password="testaa")
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
@@ -562,7 +559,7 @@ class ContestListPageTest(TestCase):
|
||||
self.url = reverse('contest_list_page')
|
||||
self.client.login(username="test1", password="testaa")
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
# coding=utf-8
|
||||
import json
|
||||
import datetime
|
||||
from functools import wraps
|
||||
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, Count, Sum
|
||||
from django.db.models import Q, 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, User
|
||||
from utils.shortcuts import (serializer_invalid_response, error_response,
|
||||
success_response, paginate, error_page)
|
||||
from account.models import SUPER_ADMIN, User
|
||||
from account.decorators import login_required
|
||||
from group.models import Group
|
||||
from announcement.models import Announcement
|
||||
|
||||
from .models import Contest, ContestProblem, ContestSubmission
|
||||
from .models import GROUP_CONTEST, PUBLIC_CONTEST, PASSWORD_PUBLIC_CONTEST
|
||||
from .models import GROUP_CONTEST, PUBLIC_CONTEST, PASSWORD_PROTECTED_CONTEST
|
||||
from .decorators import check_user_contest_permission
|
||||
from .serializers import (CreateContestSerializer, ContestSerializer, EditContestSerializer,
|
||||
CreateContestProblemSerializer, ContestProblemSerializer,
|
||||
EditContestProblemSerializer, ContestPasswordVerifySerializer,
|
||||
ContestPasswordVerifySerializer,
|
||||
EditContestProblemSerializer)
|
||||
|
||||
|
||||
@@ -41,10 +38,10 @@ class ContestAdminAPIView(APIView):
|
||||
# 首先判断比赛的类型: 0 即为是小组赛(GROUP_CONTEST),1 即为是无密码的公开赛(PUBLIC_CONTEST),
|
||||
# 2 即为是有密码的公开赛(PASSWORD_PUBLIC_CONTEST)
|
||||
# 此时为有密码的公开赛,并且此时只能超级管理员才有权限此创建比赛
|
||||
if data["contest_type"] in [PUBLIC_CONTEST, PASSWORD_PUBLIC_CONTEST]:
|
||||
if data["contest_type"] in [PUBLIC_CONTEST, PASSWORD_PROTECTED_CONTEST]:
|
||||
if request.user.admin_type != SUPER_ADMIN:
|
||||
return error_response(u"只有超级管理员才可创建公开赛")
|
||||
if data["contest_type"] == PASSWORD_PUBLIC_CONTEST:
|
||||
if data["contest_type"] == PASSWORD_PROTECTED_CONTEST:
|
||||
if not data["password"]:
|
||||
return error_response(u"此比赛为有密码的公开赛,密码不可为空")
|
||||
|
||||
@@ -94,10 +91,10 @@ class ContestAdminAPIView(APIView):
|
||||
return error_response(u"该比赛名称已经存在")
|
||||
except Contest.DoesNotExist:
|
||||
pass
|
||||
if data["contest_type"] in [PUBLIC_CONTEST, PASSWORD_PUBLIC_CONTEST]:
|
||||
if data["contest_type"] in [PUBLIC_CONTEST, PASSWORD_PROTECTED_CONTEST]:
|
||||
if request.user.admin_type != SUPER_ADMIN:
|
||||
return error_response(u"只有超级管理员才可创建公开赛")
|
||||
if data["contest_type"] == PASSWORD_PUBLIC_CONTEST:
|
||||
if data["contest_type"] == PASSWORD_PROTECTED_CONTEST:
|
||||
if not data["password"]:
|
||||
return error_response(u"此比赛为有密码的公开赛,密码不可为空")
|
||||
elif data["contest_type"] == GROUP_CONTEST:
|
||||
@@ -258,7 +255,7 @@ class ContestPasswordVerifyAPIView(APIView):
|
||||
if serializer.is_valid():
|
||||
data = request.data
|
||||
try:
|
||||
contest = Contest.objects.get(id=data["contest_id"], contest_type=PASSWORD_PUBLIC_CONTEST)
|
||||
contest = Contest.objects.get(id=data["contest_id"], contest_type=PASSWORD_PROTECTED_CONTEST)
|
||||
except Contest.DoesNotExist:
|
||||
return error_response(u"比赛不存在")
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# coding=utf-8
|
||||
import json
|
||||
|
||||
from django.test import TestCase, Client
|
||||
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, ContestProblem
|
||||
from contest.models import GROUP_CONTEST, PUBLIC_CONTEST, PASSWORD_PUBLIC_CONTEST
|
||||
from submission.models import Submission
|
||||
from rest_framework.test import APITestCase, APIClient
|
||||
|
||||
from account.models import User, REGULAR_USER, ADMIN, SUPER_ADMIN
|
||||
from contest.models import Contest, ContestProblem
|
||||
from contest.models import PUBLIC_CONTEST, PASSWORD_PROTECTED_CONTEST
|
||||
from submission.models import Submission
|
||||
|
||||
|
||||
class ContestSubmissionAPITest(APITestCase):
|
||||
def setUp(self):
|
||||
@@ -107,7 +108,7 @@ class SubmissionAPITest(APITestCase):
|
||||
self.userS.set_password("testbb")
|
||||
self.userS.save()
|
||||
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
|
||||
contest_type=PASSWORD_PUBLIC_CONTEST, show_rank=True,
|
||||
contest_type=PASSWORD_PROTECTED_CONTEST, show_rank=True,
|
||||
show_user_submission=True,
|
||||
start_time="2015-08-15T10:00:00.000Z",
|
||||
end_time="2015-08-15T12:00:00.000Z",
|
||||
|
||||
@@ -120,12 +120,13 @@ def contest_problem_submissions_list_page(request, contest_id, page=1):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 如果该用户是超级管理员那么他可以查看所有的提交记录详情
|
||||
if request.user.admin_type > 1:
|
||||
return render(request, "oj/contest/submissions_list_admin.html",
|
||||
{"submissions": current_page, "page": int(page),
|
||||
"previous_page": previous_page, "next_page": next_page, "start_id": int(page) * 20 - 20,
|
||||
"contest": contest})
|
||||
for item in current_page:
|
||||
# 自己提交的 管理员和创建比赛的可以看到所有的提交链接
|
||||
if item["user_id"] == request.user.id or request.user.admin_type == SUPER_ADMIN or \
|
||||
request.user == contest.created_by:
|
||||
item["show_link"] = True
|
||||
else:
|
||||
item["show_link"] = False
|
||||
|
||||
return render(request, "oj/contest/submissions_list.html",
|
||||
{"submissions": current_page, "page": int(page),
|
||||
|
||||
@@ -34,7 +34,7 @@ REDIS_CACHE = {
|
||||
DEBUG = True
|
||||
|
||||
# 同理 这是 web 服务器的上传路径
|
||||
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/')
|
||||
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/')
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Created by virusdefender on 8/25/15.
|
||||
*/
|
||||
|
||||
fis.match('*.{js,css,png,gif}', {
|
||||
useHash: true // 开启 md5 戳
|
||||
});
|
||||
|
||||
fis.config.set(
|
||||
'roadmap.path',
|
||||
[{reg:'*.html',isHtmlLike : true}
|
||||
])
|
||||
;
|
||||
@@ -1,4 +1,4 @@
|
||||
define("admin", ["jquery", "avalon"], function ($, avalon) {
|
||||
require(["jquery", "avalon", "bootstrap"], function ($, avalon) {
|
||||
|
||||
avalon.ready(function () {
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
require(["jquery", "avalon"], function($, avalon){
|
||||
var vm = avalon.define({
|
||||
$id: "problem_list",
|
||||
problem_list: []
|
||||
})
|
||||
});
|
||||
@@ -1,10 +1,9 @@
|
||||
({
|
||||
// RequireJS 通过一个相对的路径 baseUrl来加载所有代码。baseUrl通常被设置成data-main属性指定脚本的同级目录。
|
||||
baseUrl: "/static/js/",
|
||||
baseUrl: "./js",
|
||||
// 第三方脚本模块的别名,jquery比libs/jquery-1.11.1.min.js简洁明了;
|
||||
paths: {
|
||||
|
||||
jquery: "lib/jquery/jquery",
|
||||
jquery: "empty:",
|
||||
avalon: "lib/avalon/avalon",
|
||||
editor: "utils/editor",
|
||||
uploader: "utils/uploader",
|
||||
@@ -19,9 +18,9 @@
|
||||
tagEditor: "lib/tagEditor/jquery.tag-editor.min",
|
||||
jqueryUI: "lib/jqueryUI/jquery-ui",
|
||||
bootstrap: "lib/bootstrap/bootstrap",
|
||||
datetimePicker: "lib/datetime_picker/bootstrap-datetimepicker.zh-CN",
|
||||
datetimePicker: "lib/datetime_picker/bootstrap-datetimepicker",
|
||||
validator: "lib/validator/validator",
|
||||
|
||||
ZeroClipboard: "lib/ZeroClipboard/ZeroClipboard",
|
||||
|
||||
// ------ 下面写的都不要直接用,而是使用上面的封装版本 ------
|
||||
//富文本编辑器simditor -> editor
|
||||
@@ -34,35 +33,47 @@
|
||||
_codeMirror: "lib/codeMirror/codemirror",
|
||||
codeMirrorClang: "lib/codeMirror/language/clike",
|
||||
|
||||
// bootstrap组件
|
||||
modal: "lib/bootstrap/modal",
|
||||
dropdown: "lib/bootstrap/dropdown",
|
||||
transition: "lib/bootstrap/transition",
|
||||
|
||||
//百度webuploader -> uploader
|
||||
webUploader: "lib/webuploader/webuploader",
|
||||
|
||||
"_datetimePicker": "lib/datetime_picker/bootstrap-datetimepicker"
|
||||
},
|
||||
shim: {
|
||||
bootstrap: {deps: ["jquery"]},
|
||||
_datetimePicker: {dep: ["jquery"]},
|
||||
datetimePicker: {deps: ["_datetimePicker"]},
|
||||
validator: ["jquery"]
|
||||
//"_datetimePicker": "lib/datetime_picker/bootstrap-datetimepicker",
|
||||
|
||||
//以下都是页面 script 标签引用的js
|
||||
addProblem_0_pack: "app/admin/problem/addProblem",
|
||||
addContest_1_pack: "app/admin/contest/addContest",
|
||||
problem_2_pack: "app/admin/problem/problem",
|
||||
register_3_pack: "app/oj/account/register",
|
||||
contestList_4_pack: "app/admin/contest/contestList",
|
||||
group_5_pack: "app/oj/group/group",
|
||||
editProblem_6_pack: "app/admin/problem/editProblem",
|
||||
announcement_7_pack: "app/admin/announcement/announcement",
|
||||
monitor_8_pack: "app/admin/monitor/monitor",
|
||||
groupDetail_9_pack: "app/admin/group/groupDetail",
|
||||
admin_10_pack: "app/admin/admin",
|
||||
problem_11_pack: "app/oj/problem/problem",
|
||||
submissionList_12_pack: "app/admin/problem/submissionList",
|
||||
editProblem_13_pack: "app/admin/contest/editProblem",
|
||||
joinGroupRequestList_14_pack: "app/admin/group/joinGroupRequestList",
|
||||
changePassword_15_pack: "app/oj/account/changePassword",
|
||||
group_16_pack: "app/admin/group/group",
|
||||
submissionList_17_pack: "app/admin/contest/submissionList",
|
||||
login_18_pack: "app/oj/account/login",
|
||||
contestPassword_19_pack: "app/oj/contest/contestPassword",
|
||||
userList_20_pack: "app/admin/user/userList"
|
||||
},
|
||||
findNestedDependencies: true,
|
||||
appDir: "../",
|
||||
dir: "../../release/",
|
||||
modules: [
|
||||
|
||||
{
|
||||
name: "submit_code"
|
||||
},
|
||||
{
|
||||
name: "validation"
|
||||
},
|
||||
{
|
||||
name: "editor"
|
||||
},
|
||||
{
|
||||
name: "code_mirror"
|
||||
},
|
||||
{
|
||||
name: "datetimepicker"
|
||||
name: "addContest_1_pack"
|
||||
}
|
||||
]
|
||||
],
|
||||
optimizeCss: "standard",
|
||||
})
|
||||
@@ -2,7 +2,6 @@ var require = {
|
||||
// RequireJS 通过一个相对的路径 baseUrl来加载所有代码。baseUrl通常被设置成data-main属性指定脚本的同级目录。
|
||||
baseUrl: "/static/js/",
|
||||
paths: {
|
||||
|
||||
jquery: "lib/jquery/jquery",
|
||||
avalon: "lib/avalon/avalon",
|
||||
editor: "utils/editor",
|
||||
@@ -18,7 +17,7 @@ var require = {
|
||||
tagEditor: "lib/tagEditor/jquery.tag-editor.min",
|
||||
jqueryUI: "lib/jqueryUI/jquery-ui",
|
||||
bootstrap: "lib/bootstrap/bootstrap",
|
||||
datetimePicker: "lib/datetime_picker/bootstrap-datetimepicker.zh-CN",
|
||||
datetimePicker: "lib/datetime_picker/bootstrap-datetimepicker",
|
||||
validator: "lib/validator/validator",
|
||||
ZeroClipboard: "lib/ZeroClipboard/ZeroClipboard",
|
||||
|
||||
@@ -34,15 +33,37 @@ var require = {
|
||||
_codeMirror: "lib/codeMirror/codemirror",
|
||||
codeMirrorClang: "lib/codeMirror/language/clike",
|
||||
|
||||
// bootstrap组件
|
||||
modal: "lib/bootstrap/modal",
|
||||
dropdown: "lib/bootstrap/dropdown",
|
||||
transition: "lib/bootstrap/transition",
|
||||
|
||||
//百度webuploader -> uploader
|
||||
webUploader: "lib/webuploader/webuploader",
|
||||
|
||||
"_datetimePicker": "lib/datetime_picker/bootstrap-datetimepicker"
|
||||
},
|
||||
shim: {
|
||||
bootstrap: {deps: ["jquery"]},
|
||||
_datetimePicker: {dep: ["jquery"]},
|
||||
datetimePicker: {deps: ["_datetimePicker"]},
|
||||
validator: ["jquery"]
|
||||
// "_datetimePicker": "lib/datetime_picker/bootstrap-datetimepicker",
|
||||
|
||||
//以下都是页面 script 标签引用的js
|
||||
addProblem_0_pack: "app/admin/problem/addProblem",
|
||||
addContest_1_pack: "app/admin/contest/addContest",
|
||||
problem_2_pack: "app/admin/problem/problem",
|
||||
register_3_pack: "app/oj/account/register",
|
||||
contestList_4_pack: "app/admin/contest/contestList",
|
||||
group_5_pack: "app/oj/group/group",
|
||||
editProblem_6_pack: "app/admin/problem/editProblem",
|
||||
announcement_7_pack: "app/admin/announcement/announcement",
|
||||
monitor_8_pack: "app/admin/monitor/monitor",
|
||||
groupDetail_9_pack: "app/admin/group/groupDetail",
|
||||
admin_10_pack: "app/admin/admin",
|
||||
problem_11_pack: "app/oj/problem/problem",
|
||||
submissionList_12_pack: "app/admin/problem/submissionList",
|
||||
editProblem_13_pack: "app/admin/contest/editProblem",
|
||||
joinGroupRequestList_14_pack: "app/admin/group/joinGroupRequestList",
|
||||
changePassword_15_pack: "app/oj/account/changePassword",
|
||||
group_16_pack: "app/admin/group/group",
|
||||
submissionList_17_pack: "app/admin/contest/submissionList",
|
||||
login_18_pack: "app/oj/account/login",
|
||||
contestPassword_19_pack: "app/oj/contest/contestPassword",
|
||||
userList_20_pack: "app/admin/user/userList"
|
||||
}
|
||||
};
|
||||
2364
static/src/js/lib/bootstrap/bootstrap.js
vendored
2364
static/src/js/lib/bootstrap/bootstrap.js
vendored
File diff suppressed because it is too large
Load Diff
168
static/src/js/lib/bootstrap/dropdown.js
Normal file
168
static/src/js/lib/bootstrap/dropdown.js
Normal file
@@ -0,0 +1,168 @@
|
||||
define([ 'jquery', 'transition' ], function ( jQuery ) {
|
||||
/* ========================================================================
|
||||
* Bootstrap: dropdown.js v3.3.5
|
||||
* http://getbootstrap.com/javascript/#dropdowns
|
||||
* ========================================================================
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// DROPDOWN CLASS DEFINITION
|
||||
// =========================
|
||||
|
||||
var backdrop = '.dropdown-backdrop'
|
||||
var toggle = '[data-toggle="dropdown"]'
|
||||
var Dropdown = function (element) {
|
||||
$(element).on('click.bs.dropdown', this.toggle)
|
||||
}
|
||||
|
||||
Dropdown.VERSION = '3.3.5'
|
||||
|
||||
function getParent($this) {
|
||||
var selector = $this.attr('data-target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
var $parent = selector && $(selector)
|
||||
|
||||
return $parent && $parent.length ? $parent : $this.parent()
|
||||
}
|
||||
|
||||
function clearMenus(e) {
|
||||
if (e && e.which === 3) return
|
||||
$(backdrop).remove()
|
||||
$(toggle).each(function () {
|
||||
var $this = $(this)
|
||||
var $parent = getParent($this)
|
||||
var relatedTarget = { relatedTarget: this }
|
||||
|
||||
if (!$parent.hasClass('open')) return
|
||||
|
||||
if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
|
||||
|
||||
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$this.attr('aria-expanded', 'false')
|
||||
$parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
|
||||
})
|
||||
}
|
||||
|
||||
Dropdown.prototype.toggle = function (e) {
|
||||
var $this = $(this)
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return
|
||||
|
||||
var $parent = getParent($this)
|
||||
var isActive = $parent.hasClass('open')
|
||||
|
||||
clearMenus()
|
||||
|
||||
if (!isActive) {
|
||||
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
|
||||
// if mobile we use a backdrop because click events don't delegate
|
||||
$(document.createElement('div'))
|
||||
.addClass('dropdown-backdrop')
|
||||
.insertAfter($(this))
|
||||
.on('click', clearMenus)
|
||||
}
|
||||
|
||||
var relatedTarget = { relatedTarget: this }
|
||||
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$this
|
||||
.trigger('focus')
|
||||
.attr('aria-expanded', 'true')
|
||||
|
||||
$parent
|
||||
.toggleClass('open')
|
||||
.trigger($.Event('shown.bs.dropdown', relatedTarget))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Dropdown.prototype.keydown = function (e) {
|
||||
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
|
||||
|
||||
var $this = $(this)
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return
|
||||
|
||||
var $parent = getParent($this)
|
||||
var isActive = $parent.hasClass('open')
|
||||
|
||||
if (!isActive && e.which != 27 || isActive && e.which == 27) {
|
||||
if (e.which == 27) $parent.find(toggle).trigger('focus')
|
||||
return $this.trigger('click')
|
||||
}
|
||||
|
||||
var desc = ' li:not(.disabled):visible a'
|
||||
var $items = $parent.find('.dropdown-menu' + desc)
|
||||
|
||||
if (!$items.length) return
|
||||
|
||||
var index = $items.index(e.target)
|
||||
|
||||
if (e.which == 38 && index > 0) index-- // up
|
||||
if (e.which == 40 && index < $items.length - 1) index++ // down
|
||||
if (!~index) index = 0
|
||||
|
||||
$items.eq(index).trigger('focus')
|
||||
}
|
||||
|
||||
|
||||
// DROPDOWN PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.dropdown')
|
||||
|
||||
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.dropdown
|
||||
|
||||
$.fn.dropdown = Plugin
|
||||
$.fn.dropdown.Constructor = Dropdown
|
||||
|
||||
|
||||
// DROPDOWN NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.dropdown.noConflict = function () {
|
||||
$.fn.dropdown = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// APPLY TO STANDARD DROPDOWN ELEMENTS
|
||||
// ===================================
|
||||
|
||||
$(document)
|
||||
.on('click.bs.dropdown.data-api', clearMenus)
|
||||
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
|
||||
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
||||
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
|
||||
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
|
||||
|
||||
}(jQuery);
|
||||
|
||||
});
|
||||
340
static/src/js/lib/bootstrap/modal.js
Normal file
340
static/src/js/lib/bootstrap/modal.js
Normal file
@@ -0,0 +1,340 @@
|
||||
define([ 'jquery', 'transition' ], function ( jQuery ) {
|
||||
/* ========================================================================
|
||||
* Bootstrap: modal.js v3.3.5
|
||||
* http://getbootstrap.com/javascript/#modals
|
||||
* ========================================================================
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// MODAL CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var Modal = function (element, options) {
|
||||
this.options = options
|
||||
this.$body = $(document.body)
|
||||
this.$element = $(element)
|
||||
this.$dialog = this.$element.find('.modal-dialog')
|
||||
this.$backdrop = null
|
||||
this.isShown = null
|
||||
this.originalBodyPad = null
|
||||
this.scrollbarWidth = 0
|
||||
this.ignoreBackdropClick = false
|
||||
|
||||
if (this.options.remote) {
|
||||
this.$element
|
||||
.find('.modal-content')
|
||||
.load(this.options.remote, $.proxy(function () {
|
||||
this.$element.trigger('loaded.bs.modal')
|
||||
}, this))
|
||||
}
|
||||
}
|
||||
|
||||
Modal.VERSION = '3.3.5'
|
||||
|
||||
Modal.TRANSITION_DURATION = 300
|
||||
Modal.BACKDROP_TRANSITION_DURATION = 150
|
||||
|
||||
Modal.DEFAULTS = {
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
show: true
|
||||
}
|
||||
|
||||
Modal.prototype.toggle = function (_relatedTarget) {
|
||||
return this.isShown ? this.hide() : this.show(_relatedTarget)
|
||||
}
|
||||
|
||||
Modal.prototype.show = function (_relatedTarget) {
|
||||
var that = this
|
||||
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = true
|
||||
|
||||
this.checkScrollbar()
|
||||
this.setScrollbar()
|
||||
this.$body.addClass('modal-open')
|
||||
|
||||
this.escape()
|
||||
this.resize()
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
|
||||
|
||||
this.$dialog.on('mousedown.dismiss.bs.modal', function () {
|
||||
that.$element.one('mouseup.dismiss.bs.modal', function (e) {
|
||||
if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
|
||||
})
|
||||
})
|
||||
|
||||
this.backdrop(function () {
|
||||
var transition = $.support.transition && that.$element.hasClass('fade')
|
||||
|
||||
if (!that.$element.parent().length) {
|
||||
that.$element.appendTo(that.$body) // don't move modals dom position
|
||||
}
|
||||
|
||||
that.$element
|
||||
.show()
|
||||
.scrollTop(0)
|
||||
|
||||
that.adjustDialog()
|
||||
|
||||
if (transition) {
|
||||
that.$element[0].offsetWidth // force reflow
|
||||
}
|
||||
|
||||
that.$element.addClass('in')
|
||||
|
||||
that.enforceFocus()
|
||||
|
||||
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
transition ?
|
||||
that.$dialog // wait for modal to slide in
|
||||
.one('bsTransitionEnd', function () {
|
||||
that.$element.trigger('focus').trigger(e)
|
||||
})
|
||||
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
|
||||
that.$element.trigger('focus').trigger(e)
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.hide = function (e) {
|
||||
if (e) e.preventDefault()
|
||||
|
||||
e = $.Event('hide.bs.modal')
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (!this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = false
|
||||
|
||||
this.escape()
|
||||
this.resize()
|
||||
|
||||
$(document).off('focusin.bs.modal')
|
||||
|
||||
this.$element
|
||||
.removeClass('in')
|
||||
.off('click.dismiss.bs.modal')
|
||||
.off('mouseup.dismiss.bs.modal')
|
||||
|
||||
this.$dialog.off('mousedown.dismiss.bs.modal')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$element
|
||||
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
|
||||
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
|
||||
this.hideModal()
|
||||
}
|
||||
|
||||
Modal.prototype.enforceFocus = function () {
|
||||
$(document)
|
||||
.off('focusin.bs.modal') // guard against infinite focus loop
|
||||
.on('focusin.bs.modal', $.proxy(function (e) {
|
||||
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
|
||||
this.$element.trigger('focus')
|
||||
}
|
||||
}, this))
|
||||
}
|
||||
|
||||
Modal.prototype.escape = function () {
|
||||
if (this.isShown && this.options.keyboard) {
|
||||
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
|
||||
e.which == 27 && this.hide()
|
||||
}, this))
|
||||
} else if (!this.isShown) {
|
||||
this.$element.off('keydown.dismiss.bs.modal')
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.resize = function () {
|
||||
if (this.isShown) {
|
||||
$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
|
||||
} else {
|
||||
$(window).off('resize.bs.modal')
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.hideModal = function () {
|
||||
var that = this
|
||||
this.$element.hide()
|
||||
this.backdrop(function () {
|
||||
that.$body.removeClass('modal-open')
|
||||
that.resetAdjustments()
|
||||
that.resetScrollbar()
|
||||
that.$element.trigger('hidden.bs.modal')
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.removeBackdrop = function () {
|
||||
this.$backdrop && this.$backdrop.remove()
|
||||
this.$backdrop = null
|
||||
}
|
||||
|
||||
Modal.prototype.backdrop = function (callback) {
|
||||
var that = this
|
||||
var animate = this.$element.hasClass('fade') ? 'fade' : ''
|
||||
|
||||
if (this.isShown && this.options.backdrop) {
|
||||
var doAnimate = $.support.transition && animate
|
||||
|
||||
this.$backdrop = $(document.createElement('div'))
|
||||
.addClass('modal-backdrop ' + animate)
|
||||
.appendTo(this.$body)
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
|
||||
if (this.ignoreBackdropClick) {
|
||||
this.ignoreBackdropClick = false
|
||||
return
|
||||
}
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.options.backdrop == 'static'
|
||||
? this.$element[0].focus()
|
||||
: this.hide()
|
||||
}, this))
|
||||
|
||||
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
||||
|
||||
this.$backdrop.addClass('in')
|
||||
|
||||
if (!callback) return
|
||||
|
||||
doAnimate ?
|
||||
this.$backdrop
|
||||
.one('bsTransitionEnd', callback)
|
||||
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
|
||||
callback()
|
||||
|
||||
} else if (!this.isShown && this.$backdrop) {
|
||||
this.$backdrop.removeClass('in')
|
||||
|
||||
var callbackRemove = function () {
|
||||
that.removeBackdrop()
|
||||
callback && callback()
|
||||
}
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$backdrop
|
||||
.one('bsTransitionEnd', callbackRemove)
|
||||
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
|
||||
callbackRemove()
|
||||
|
||||
} else if (callback) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// these following methods are used to handle overflowing modals
|
||||
|
||||
Modal.prototype.handleUpdate = function () {
|
||||
this.adjustDialog()
|
||||
}
|
||||
|
||||
Modal.prototype.adjustDialog = function () {
|
||||
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
|
||||
|
||||
this.$element.css({
|
||||
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
|
||||
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.resetAdjustments = function () {
|
||||
this.$element.css({
|
||||
paddingLeft: '',
|
||||
paddingRight: ''
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.checkScrollbar = function () {
|
||||
var fullWindowWidth = window.innerWidth
|
||||
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
|
||||
var documentElementRect = document.documentElement.getBoundingClientRect()
|
||||
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
|
||||
}
|
||||
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
|
||||
this.scrollbarWidth = this.measureScrollbar()
|
||||
}
|
||||
|
||||
Modal.prototype.setScrollbar = function () {
|
||||
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
|
||||
this.originalBodyPad = document.body.style.paddingRight || ''
|
||||
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
|
||||
}
|
||||
|
||||
Modal.prototype.resetScrollbar = function () {
|
||||
this.$body.css('padding-right', this.originalBodyPad)
|
||||
}
|
||||
|
||||
Modal.prototype.measureScrollbar = function () { // thx walsh
|
||||
var scrollDiv = document.createElement('div')
|
||||
scrollDiv.className = 'modal-scrollbar-measure'
|
||||
this.$body.append(scrollDiv)
|
||||
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
|
||||
this.$body[0].removeChild(scrollDiv)
|
||||
return scrollbarWidth
|
||||
}
|
||||
|
||||
|
||||
// MODAL PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option, _relatedTarget) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.modal')
|
||||
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
|
||||
if (typeof option == 'string') data[option](_relatedTarget)
|
||||
else if (options.show) data.show(_relatedTarget)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.modal
|
||||
|
||||
$.fn.modal = Plugin
|
||||
$.fn.modal.Constructor = Modal
|
||||
|
||||
|
||||
// MODAL NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.modal.noConflict = function () {
|
||||
$.fn.modal = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// MODAL DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
|
||||
var $this = $(this)
|
||||
var href = $this.attr('href')
|
||||
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
|
||||
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
|
||||
|
||||
if ($this.is('a')) e.preventDefault()
|
||||
|
||||
$target.one('show.bs.modal', function (showEvent) {
|
||||
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
|
||||
$target.one('hidden.bs.modal', function () {
|
||||
$this.is(':visible') && $this.trigger('focus')
|
||||
})
|
||||
})
|
||||
Plugin.call($target, option, this)
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
});
|
||||
62
static/src/js/lib/bootstrap/transition.js
Normal file
62
static/src/js/lib/bootstrap/transition.js
Normal file
@@ -0,0 +1,62 @@
|
||||
define([ 'jquery', 'transition' ], function ( jQuery ) {
|
||||
/* ========================================================================
|
||||
* Bootstrap: transition.js v3.3.5
|
||||
* http://getbootstrap.com/javascript/#transitions
|
||||
* ========================================================================
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
|
||||
// ============================================================
|
||||
|
||||
function transitionEnd() {
|
||||
var el = document.createElement('bootstrap')
|
||||
|
||||
var transEndEventNames = {
|
||||
WebkitTransition : 'webkitTransitionEnd',
|
||||
MozTransition : 'transitionend',
|
||||
OTransition : 'oTransitionEnd otransitionend',
|
||||
transition : 'transitionend'
|
||||
}
|
||||
|
||||
for (var name in transEndEventNames) {
|
||||
if (el.style[name] !== undefined) {
|
||||
return { end: transEndEventNames[name] }
|
||||
}
|
||||
}
|
||||
|
||||
return false // explicit for ie8 ( ._.)
|
||||
}
|
||||
|
||||
// http://blog.alexmaccaw.com/css-transitions
|
||||
$.fn.emulateTransitionEnd = function (duration) {
|
||||
var called = false
|
||||
var $el = this
|
||||
$(this).one('bsTransitionEnd', function () { called = true })
|
||||
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
||||
setTimeout(callback, duration)
|
||||
return this
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$.support.transition = transitionEnd()
|
||||
|
||||
if (!$.support.transition) return
|
||||
|
||||
$.event.special.bsTransitionEnd = {
|
||||
bindType: $.support.transition.end,
|
||||
delegateType: $.support.transition.end,
|
||||
handle: function (e) {
|
||||
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
});
|
||||
@@ -26,8 +26,15 @@
|
||||
*
|
||||
* Make it work in bootstrap v3
|
||||
*/
|
||||
|
||||
!function ($) {
|
||||
(function(factory){
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["jquery"], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($, undefined) {
|
||||
|
||||
function UTCDate() {
|
||||
return new Date(Date.UTC.apply(Date, arguments));
|
||||
@@ -1764,6 +1771,17 @@
|
||||
'</div>';
|
||||
$.fn.datetimepicker.DPGlobal = DPGlobal;
|
||||
|
||||
$.fn.datetimepicker.dates['zh-CN'] = {
|
||||
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
|
||||
daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
|
||||
months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||
today: "今天",
|
||||
suffix: [],
|
||||
meridiem: ["上午", "下午"]
|
||||
};
|
||||
|
||||
/* DATETIMEPICKER NO CONFLICT
|
||||
* =================== */
|
||||
|
||||
@@ -1790,4 +1808,4 @@
|
||||
$('[data-provide="datetimepicker-inline"]').datetimepicker();
|
||||
});
|
||||
|
||||
}(window.jQuery);
|
||||
}));
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
* Simplified Chinese translation for bootstrap-datetimepicker
|
||||
* Yuan Cheung <advanimal@gmail.com>
|
||||
*/
|
||||
;(function($){
|
||||
!function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery', '_datetimePicker'], factory);
|
||||
} else {
|
||||
factory(root.jQuery);
|
||||
}
|
||||
}(this, function($){
|
||||
$.fn.datetimepicker.dates['zh-CN'] = {
|
||||
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
|
||||
daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
@@ -13,4 +19,4 @@
|
||||
suffix: [],
|
||||
meridiem: ["上午", "下午"]
|
||||
};
|
||||
}(jQuery));
|
||||
});
|
||||
|
||||
@@ -25,8 +25,13 @@
|
||||
* THE SOFTWARE.
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
!function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], factory);
|
||||
} else {
|
||||
factory(root.jQuery);
|
||||
}
|
||||
}(this, function ($) {
|
||||
'use strict';
|
||||
|
||||
// VALIDATOR CLASS DEFINITION
|
||||
@@ -322,4 +327,4 @@
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
});
|
||||
|
||||
@@ -114,9 +114,6 @@ def my_submission(request, submission_id):
|
||||
except Submission.DoesNotExist:
|
||||
return error_page(request, u"提交不存在")
|
||||
|
||||
if submission.user_id != request.user.id and not submission.shared:
|
||||
return error_page(request, u"提交不存在")
|
||||
|
||||
if submission.contest_id:
|
||||
try:
|
||||
problem = ContestProblem.objects.get(id=submission.problem_id,
|
||||
|
||||
@@ -127,9 +127,7 @@
|
||||
|
||||
<script src="/static/js/config.js"></script>
|
||||
<script src="/static/js/require.js"></script>
|
||||
<script>
|
||||
require(["bootstrap", "admin"]);
|
||||
</script>
|
||||
<script src="/static/js/app/admin/admin.js"></script>
|
||||
|
||||
<!-- footer begin -->
|
||||
<div class="footer">
|
||||
|
||||
@@ -34,5 +34,5 @@
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script src="/static/js/app/oj/account/change_password.js"></script>
|
||||
<script src="/static/js/app/oj/account/changePassword.js"></script>
|
||||
{% endblock %}
|
||||
@@ -78,5 +78,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_block %}
|
||||
<script src="/static/js/app/oj/problem/problem_list.js"></script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -2,25 +2,25 @@
|
||||
{% block body %}
|
||||
{% load submission %}
|
||||
<div class="container main">
|
||||
<div class="col-lg-12 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">
|
||||
<a href="/contest/{{ contest.id }}/submissions/">提交</a>
|
||||
</li>
|
||||
<li role="presentation" class="active">
|
||||
<a href="/contest/{{ contest.id }}/rank/">排名</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-tabs nav-tabs-google contest-tab">
|
||||
<li role="presentation">
|
||||
<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" class="active">
|
||||
<a href="/contest/{{ contest.id }}/rank/">排名</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
{% if result %}
|
||||
|
||||
{% if result %}
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -50,22 +50,24 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<input type="checkbox" id="auto-refresh" {% if auto_refresh %}checked{% endif %} onchange="if(this.checked){location.href='?auto_refresh=true'}else{location.href=location.href.split('?')[0]}"> 自动刷新
|
||||
{% else %}
|
||||
<p>还没有结果</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<input type="checkbox" id="auto-refresh" {% if auto_refresh %}checked{% endif %}
|
||||
onchange="if(this.checked){location.href='?auto_refresh=true'}else{location.href=location.href.split('?')[0]}">
|
||||
自动刷新
|
||||
{% else %}
|
||||
<p>还没有结果</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block js_block %}
|
||||
{% if auto_refresh %}
|
||||
<script>
|
||||
setTimeout(function(){
|
||||
location.reload();
|
||||
}, 5000);
|
||||
</script>
|
||||
{% if auto_refresh %}
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
location.reload();
|
||||
}, 5000);
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -37,5 +37,5 @@
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script src="/static/js/app/oj/contest/contest_password.js"></script>
|
||||
<script src="/static/js/app/oj/contest/contestPassword.js"></script>
|
||||
{% endblock %}
|
||||
@@ -21,58 +21,59 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr class="" success>
|
||||
<th>#</th>
|
||||
<th>题目名称</th>
|
||||
<th>用户</th>
|
||||
<th>提交时间</th>
|
||||
<th>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" id="languageFilter" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
语言<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="languageFilter">
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=1">C</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=2">C++</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=3">Java</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/">取消筛选</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
<th>运行时间</th>
|
||||
<th>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" id="resultFilter" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
结果<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="resultFilter">
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=0">Accepted</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=6">Wrong Answer</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=1">Runtime Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=2">Time Limit Exceeded</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=3">Memory Limit Exceeded</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=4">Compile Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=5">Format Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/">取消筛选</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% if submissions %}
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr class="" success>
|
||||
<th>#</th>
|
||||
<th>题目名称</th>
|
||||
<th>用户</th>
|
||||
<th>提交时间</th>
|
||||
<th>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" id="languageFilter" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
语言<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="languageFilter">
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=1">C</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=2">C++</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=3">Java</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/">取消筛选</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
<th>运行时间</th>
|
||||
<th>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" id="resultFilter" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
结果<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="resultFilter">
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=0">Accepted</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=6">Wrong Answer</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=1">Runtime Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=2">Time Limit Exceeded</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=3">Memory Limit Exceeded</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=4">Compile Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=5">Format Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/">取消筛选</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% if submissions %}
|
||||
<tbody>
|
||||
{% for item in submissions %}
|
||||
<tr>
|
||||
{% ifequal item.user_id request.user.id %}
|
||||
<th scope="row"><a href="/submission/{{ item.id }}/">
|
||||
{{ forloop.counter |add:start_id }}</a></th>
|
||||
{% else %}
|
||||
<th scope="row">{{ forloop.counter |add:start_id }}</th>
|
||||
{% endifequal %}
|
||||
<th scope="row">
|
||||
{% if item.show_link %}
|
||||
<a href="/submission/{{ item.id }}/">{{ forloop.counter |add:start_id }}</a>
|
||||
{% else %}
|
||||
{{ forloop.counter |add:start_id }}
|
||||
{% endif %}
|
||||
</th>
|
||||
<th scope="row">
|
||||
<a href="/contest/{{ item.contest_id }}/problem/{{ item.problem_id }}/">{{ item.title }}</a>
|
||||
</th>
|
||||
@@ -94,10 +95,10 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% else %}
|
||||
<p>本场比赛还没有提交记录</p>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% else %}
|
||||
<p>本场比赛还没有提交记录</p>
|
||||
{% endif %}
|
||||
</table>
|
||||
|
||||
<nav>
|
||||
<ul class="pager">
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
{% 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>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr class="" success>
|
||||
<th>#</th>
|
||||
<th>题目名称</th>
|
||||
<th>用户</th>
|
||||
<th>提交时间</th>
|
||||
<th>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" id="languageFilter" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
语言<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="languageFilter">
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=1">C</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=2">C++</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?language=3">Java</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/">取消筛选</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
<th>运行时间</th>
|
||||
<th>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" id="resultFilter" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="true">
|
||||
结果<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="resultFilter">
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=0">Accepted</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=6">Wrong Answer</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=1">Runtime Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=2">Time Limit Exceeded</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=3">Memory Limit Exceeded</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=4">Compile Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/?result=5">Format Error</a></li>
|
||||
<li><a href="/contest/{{ contest.id }}/submissions/">取消筛选</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% if submissions %}
|
||||
<tbody>
|
||||
|
||||
{% for item in submissions %}
|
||||
<tr>
|
||||
<th scope="row"><a href="/submission/{{ item.id }}/">
|
||||
{{ forloop.counter |add:start_id }}</a></th>
|
||||
<th scope="row">
|
||||
<a href="/contest/{{ item.contest_id }}/problem/{{ item.problem_id }}/">{{ item.title }}</a>
|
||||
</th>
|
||||
<td>{{ item.user_id|get_username }}</td>
|
||||
<td>{{ item.create_time }}</td>
|
||||
<td>
|
||||
{{ item.language|translate_language }}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.accepted_answer_time %}
|
||||
{{ item.accepted_answer_time }}ms
|
||||
{% else %}
|
||||
--
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="alert-{{ item.result|translate_result_class }}">
|
||||
<strong>{{ item.result|translate_result }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% else %}
|
||||
<p>本场比赛还没有提交记录</p>
|
||||
{% endif %}
|
||||
</table>
|
||||
|
||||
<nav>
|
||||
<ul class="pager">
|
||||
{% if previous_page %}
|
||||
<li class="previous"><a
|
||||
href="/contest/{{ contest.id }}/submissions/{{ previous_page }}/{% if filter %}?{{ filter.name }}={{ filter.content }}{% endif %}">
|
||||
<span aria-hidden="true">←</span> 上一页</a></li>
|
||||
{% endif %}
|
||||
{% if next_page %}
|
||||
<li class="next">
|
||||
<a href="/contest/{{ contest.id }}/submissions/{{ next_page }}/{% if filter %}?{{ filter.name }}={{ filter.content }}{% endif %}">
|
||||
下一页 <span aria-hidden="true">→</span></a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>青岛大学在线评测平台 - 首页</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/fullpage/jquery.fullPage.css">
|
||||
<link href="/static/css/fullpage/jquery.fullPage.css" rel="stylesheet">
|
||||
<link rel="shortcut icon" href="/static/img/favicon.ico">
|
||||
<style>
|
||||
html, textarea, input, option, select, button {
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
<div id="code-field">
|
||||
<textarea id="code-editor">{{ submission.code }}</textarea>
|
||||
</div>
|
||||
{% ifequal request.user.id submission.user_id %}
|
||||
|
||||
<div id="share-code" class="col-lg-6 col-md-6">
|
||||
{% if submission.shared %}
|
||||
@@ -74,7 +73,7 @@
|
||||
{% if not submission.shared %}style="display: none" {% endif %}>{{ problem.title }}
|
||||
{{ request.build_absolute_uri }}</textarea>
|
||||
</div>
|
||||
{% endifequal %}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -89,5 +89,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_block %}
|
||||
<script src="/static/js/app/oj/problem/problem_list.js"></script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -86,10 +86,6 @@
|
||||
<script src="/static/js/require.js"></script>
|
||||
<script>
|
||||
require(["bootstrap"]);
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
{% block js_block %}{% endblock %}
|
||||
<!-- footer begin -->
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
青岛大学 ACM 队是一支优秀的队伍,一支充满活力与激情的队伍,它满载着光辉与荣誉。在过去的几年里,集训队的队员曾代表我校多次
|
||||
参加竞赛,获得了佳绩。
|
||||
青岛大学 ACM 队是一支优秀的队伍,一支充满活力与激情的队伍,它满载着光辉与荣誉。在过去的几年里,集训队的队员曾代表我校多次参加竞赛,获得了佳绩。
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
59
tools/release_static.py
Normal file
59
tools/release_static.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# coding=utf-8
|
||||
import hashlib
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
|
||||
template_src_path = "template/src/"
|
||||
template_release_path = "template/release/"
|
||||
|
||||
static_src_path = "static/src/"
|
||||
static_release_path = "static/release/"
|
||||
|
||||
# 删除模板的 release 文件夹
|
||||
shutil.rmtree(template_release_path)
|
||||
# 复制一份模板文件夹到 release
|
||||
shutil.copytree(template_src_path, template_release_path)
|
||||
|
||||
# 删除静态文件的 release 文件夹
|
||||
# shutil.rmtree(static_release_path)
|
||||
# 复制一份静态文件文件夹到 release
|
||||
# shutil.copytree(static_src_path, static_release_path)
|
||||
|
||||
js_re = re.compile(r'<script src="(.+)"></script>')
|
||||
css_re = re.compile(r'<link href="(.+)" rel="stylesheet">')
|
||||
|
||||
name_map = {}
|
||||
|
||||
|
||||
def process(match):
|
||||
file_path = match.group(1).replace("/static/", "")
|
||||
# print file_path, match.group(), match.group(1)
|
||||
|
||||
if not os.path.exists(static_release_path + file_path):
|
||||
return match.group(0)
|
||||
|
||||
if file_path in name_map:
|
||||
md5 = name_map[file_path]
|
||||
else:
|
||||
# rename
|
||||
md5 = hashlib.md5(open(static_release_path + file_path, "r").read()).hexdigest()
|
||||
# os.rename(static_release_path + js_path, static_release_path + js_path + "?v=" + md5)
|
||||
if ".js" in file_path:
|
||||
return '<script src="/static/%s"></script>' % (file_path + "?v=" + md5[:6], )
|
||||
elif ".css" in file_path:
|
||||
return '<link rel="stylesheet" type="text/css" href="/static/%s">' % (file_path + "?v=" + md5[:6], )
|
||||
else:
|
||||
return match.group(0)
|
||||
|
||||
|
||||
for root, dirs, files in os.walk(template_release_path):
|
||||
for name in files:
|
||||
html_path = os.path.join(root, name)
|
||||
html_content = open(html_path, "r").read()
|
||||
js_replaced_html_content = re.sub(js_re, process, html_content)
|
||||
css_replaced_html_content = re.sub(css_re, process, js_replaced_html_content)
|
||||
|
||||
f = open(html_path, "w")
|
||||
f.write(css_replaced_html_content)
|
||||
f.close()
|
||||
37
tools/template_js_path.py
Normal file
37
tools/template_js_path.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# coding=utf-8
|
||||
import hashlib
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
|
||||
template_src_path = "template/src/"
|
||||
|
||||
total_file = []
|
||||
module_list = []
|
||||
|
||||
print "\n\n-------------\n\n"
|
||||
print u" //以下都是页面 script 标签引用的js"
|
||||
for root, dirs, files in os.walk(template_src_path):
|
||||
for name in files:
|
||||
html_path = os.path.join(root, name)
|
||||
html_content = open(html_path, "r").read()
|
||||
r = re.findall(re.compile('<script src="(.*)"></script>'), html_content)
|
||||
if r:
|
||||
for item in r:
|
||||
if item and "app" in item:
|
||||
total_file.append(item)
|
||||
|
||||
i = 0
|
||||
for item in set(total_file):
|
||||
module_name = item.replace("/static/js/", "").split("/")[-1].replace(".js", "") + "_" + str(i)
|
||||
|
||||
module_list.append(module_name)
|
||||
print " " + module_name + "_pack" + ": \"" + item.replace("/static/js/", "").replace(".js", "") + "\","
|
||||
i += 1
|
||||
|
||||
print "\n\n-------------\n\n"
|
||||
|
||||
for item in module_list:
|
||||
print " {"
|
||||
print " name: \"" + item + "_pack\""
|
||||
print " },"
|
||||
Reference in New Issue
Block a user