diff --git a/contest/migrations/0005_contestproblem_score.py b/contest/migrations/0005_contestproblem_score.py
new file mode 100644
index 0000000..e0a025d
--- /dev/null
+++ b/contest/migrations/0005_contestproblem_score.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('contest', '0004_remove_contestproblem_difficulty'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='contestproblem',
+ name='score',
+ field=models.IntegerField(default=0),
+ ),
+ ]
diff --git a/contest/migrations/0006_merge.py b/contest/migrations/0006_merge.py
new file mode 100644
index 0000000..9a4fe59
--- /dev/null
+++ b/contest/migrations/0006_merge.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('contest', '0005_contestsubmission'),
+ ('contest', '0005_contestproblem_score'),
+ ]
+
+ operations = [
+ ]
diff --git a/contest/models.py b/contest/models.py
index de9f2e1..338e3b1 100644
--- a/contest/models.py
+++ b/contest/models.py
@@ -55,6 +55,7 @@ class ContestProblem(AbstractProblem):
contest = models.ForeignKey(Contest)
# 比如A B 或者1 2 或者 a b 将按照这个排序
sort_index = models.CharField(max_length=30)
+ score = models.IntegerField(default=0)
class Meta:
db_table = "contest_problem"
diff --git a/contest/serializers.py b/contest/serializers.py
index 23d8474..a9f33ee 100644
--- a/contest/serializers.py
+++ b/contest/serializers.py
@@ -70,11 +70,11 @@ class CreateContestProblemSerializer(serializers.Serializer):
time_limit = serializers.IntegerField()
memory_limit = serializers.IntegerField()
hint = serializers.CharField(max_length=3000, allow_blank=True)
+ score = serializers.IntegerField(required=False, default=0)
sort_index = serializers.CharField(max_length=30)
class ContestProblemSerializer(serializers.ModelSerializer):
-
class ContestSerializer(serializers.ModelSerializer):
class Meta:
model = Contest
@@ -101,10 +101,9 @@ class EditContestProblemSerializer(serializers.Serializer):
hint = serializers.CharField(max_length=3000, allow_blank=True)
visible = serializers.BooleanField()
sort_index = serializers.CharField(max_length=30)
+ score = serializers.IntegerField(required=False, default=0)
class ContestPasswordVerifySerializer(serializers.Serializer):
contest_id = serializers.IntegerField()
password = serializers.CharField(max_length=30)
-
-
diff --git a/contest/tests.py b/contest/tests.py
index 6cce9e8..58c9127 100644
--- a/contest/tests.py
+++ b/contest/tests.py
@@ -28,6 +28,9 @@ class ContestAdminAPITest(APITestCase):
self.group = Group.objects.create(name="group1", description="des0",
join_group_setting=0, visible=True,
admin=user2)
+ self.group2 = Group.objects.create(name="group2", description="des0",
+ join_group_setting=0, visible=True,
+ admin=user1)
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
@@ -78,7 +81,7 @@ class ContestAdminAPITest(APITestCase):
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 0)
- def test_group_contest_successfully(self):
+ def test_group_contest_super_admin_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title3", "description": "description3", "mode": 1, "contest_type": 0,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
@@ -86,6 +89,14 @@ class ContestAdminAPITest(APITestCase):
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 0)
+ def test_group_contest_admin_successfully(self):
+ self.client.login(username="test2", password="testbb")
+ data = {"title": "title6", "description": "description6", "mode": 2, "contest_type": 0,
+ "show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
+ "end_time": "2015-08-15T12:00:00.000Z", "groups": [self.group.id], "visible": True}
+ response = self.client.post(self.url, data=data)
+ self.assertEqual(response.data["code"], 0)
+
def test_time_error(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title2", "description": "description2", "mode": 1, "contest_type": 2,
@@ -141,6 +152,15 @@ class ContestAdminAPITest(APITestCase):
self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
self.assertEqual(response.data["data"]["visible"], False)
+ def test_edit_group_contest_unsuccessfully(self):
+ self.client.login(username="test2", password="testbb")
+ data = {"id": self.group_contest.id, "title": "titleyyy", "description": "descriptionyyyy", "mode": 1,
+ "contest_type": 0, "show_rank": True, "show_user_submission": True,
+ "start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T13:00:00.000Z",
+ "groups": [self.group.id], "visible": False}
+ response = self.client.put(self.url, data=data)
+ self.assertEqual(response.data["code"], 1)
+
def test_edit_group_at_least_one(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.group_contest.id, "title": "titleyyy", "description": "descriptionyyyy", "mode": 1,
@@ -169,7 +189,8 @@ 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": 2,
+ data = {"id": self.global_contest.id, "title": "title0", "description": "description0", "mode": 1,
+ "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "visible": True}
response = self.client.put(self.url, data=data)
@@ -189,6 +210,10 @@ class ContestAdminAPITest(APITestCase):
self.client.login(username="test1", password="testaa")
self.assertEqual(self.client.get(self.url).data["code"], 0)
+ def test_get_data_successfully_by_normal_admin(self):
+ self.client.login(username="test2", password="testbb")
+ self.assertEqual(self.client.get(self.url).data["code"], 0)
+
def test_keyword_contest(self):
self.client.login(username="test1", password="testaa")
response = self.client.get(self.url + "?visible=true")
@@ -209,24 +234,30 @@ class ContestProblemAdminAPItEST(APITestCase):
self.user = User.objects.create(username="test1", admin_type=SUPER_ADMIN)
self.user.set_password("testaa")
self.user.save()
+ self.user2 = User.objects.create(username="test2", admin_type=ADMIN)
+ self.user2.set_password("testaa")
+ self.user2.save()
+ self.user3 = User.objects.create(username="test3", admin_type=ADMIN)
+ self.user3.set_password("testaa")
+ self.user3.save()
self.client.login(username="test1", password="testaa")
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
end_time="2015-08-15T12:00:00.000Z",
password="aacc", created_by=User.objects.get(username="test1"))
- self. contest_problem = ContestProblem.objects.create(title="titlex",
- description="descriptionx",
- input_description="input1_description",
- output_description="output1_description",
- test_case_id="1",
- samples=json.dumps([{"input": "1 1", "output": "2"}]),
- time_limit=100,
- memory_limit=1000,
- hint="hint1",
- created_by=User.objects.get(username="test1"),
- contest=Contest.objects.get(title="titlex"),
- sort_index="a")
+ self.contest_problem = ContestProblem.objects.create(title="titlex",
+ description="descriptionx",
+ input_description="input1_description",
+ output_description="output1_description",
+ test_case_id="1",
+ samples=json.dumps([{"input": "1 1", "output": "2"}]),
+ time_limit=100,
+ memory_limit=1000,
+ hint="hint1",
+ created_by=User.objects.get(username="test1"),
+ contest=Contest.objects.get(title="titlex"),
+ sort_index="a")
# 以下是发布比赛题目的测试
def test_invalid_format(self):
@@ -311,6 +342,10 @@ class ContestProblemAdminAPItEST(APITestCase):
self.client.login(username="test1", password="testaa")
self.assertEqual(self.client.get(self.url).data["code"], 0)
+ def test_get_data_unsuccessfully(self):
+ self.client.login(username="test1", password="testaa")
+ self.assertEqual(self.client.get(self.url+"?contest_id=12").data["code"], 1)
+
def test_keyword_contest(self):
self.client.login(username="test1", password="testaa")
response = self.client.get(self.url + "?visible=true")
@@ -333,4 +368,33 @@ class ContestProblemAdminAPItEST(APITestCase):
response = self.client.get(self.url, data=data)
self.assertEqual(response.data["code"], 0)
+ def test_query_contest_problem_exists_by_contest_id(self):
+ self.client.login(username="test3", password="testaa")
+ response = self.client.get(self.url + "?contest_id=1")
+ self.assertEqual(response.data["code"], 0)
+ self.assertEqual(len(response.data["data"]), 0)
+
+ def test_query_contest_problem_exists_by_normal_admin(self):
+ self.client.login(username="test2", password="testaa")
+ data = {"contest_problem_id": self.contest_problem.id}
+ response = self.client.get(self.url, data=data)
+ self.assertEqual(response.data["code"], 0)
+
+ def test_edit_problem_unsuccessfully_can_not_access(self):
+ self.client.login(username="test2", password="testaa")
+ data = {"id": self.contest_problem.id,
+ "title": "title2222222",
+ "description": "description22222222",
+ "input_description": "input_description2",
+ "output_description": "output_description2",
+ "test_case_id": "1",
+ "source": "source1",
+ "samples": [{"input": "1 1", "output": "2"}],
+ "time_limit": "100",
+ "memory_limit": "1000",
+ "hint": "hint1",
+ "sort_index": "b",
+ "visible": True}
+ response = self.client.put(self.url, data=data)
+ self.assertEqual(response.data["code"], 1)
diff --git a/contest/views.py b/contest/views.py
index 8134dca..65b9c05 100644
--- a/contest/views.py
+++ b/contest/views.py
@@ -2,17 +2,18 @@
import json
import datetime
from functools import wraps
+from collections import OrderedDict
from django.utils.timezone import now
from django.shortcuts import render
from django.db import IntegrityError
from django.utils import dateparse
-from django.db.models import Q
+from django.db.models import Q, Count, Sum
from django.core.paginator import Paginator
from rest_framework.views import APIView
from utils.shortcuts import (serializer_invalid_response, error_response,
success_response, paginate, rand_str, error_page)
-from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN
+from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN, User
from account.decorators import login_required
from group.models import Group
from announcement.models import Announcement
@@ -279,15 +280,21 @@ def contest_problem_page(request, contest_id, contest_problem_id):
contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True)
except ContestProblem.DoesNotExist:
return error_page(request, u"比赛题目不存在")
+ warning = "您已经提交过本题的正确答案!"
show_warning = False
try:
submission = ContestSubmission.objects.get(user=request.user, contest=contest, problem=contest_problem)
show_warning = submission.ac
except ContestSubmission.DoesNotExist:
pass
- return render(request, "oj/contest/contest_problem.html", {"contest_problem": contest_problem,
+
+ # 已经结束
+ if contest.status == -1:
+ show_warning = True
+ warning = "比赛已经结束!"
+ return render(request, "oj/contest/contest_problem.html", {"contest_problem": contest_problem, "contest": contest,
"samples": json.loads(contest_problem.samples),
- "show_warning": show_warning})
+ "show_warning": show_warning, "warning": warning})
@check_user_contest_permission
@@ -353,4 +360,55 @@ def contest_list_page(request, page=1):
+def _cmp(x, y):
+ if x["total_ac"] > y["total_ac"]:
+ return 1
+ elif x["total_ac"] < y["total_ac"]:
+ return -1
+ else:
+ if x["total_time"] < y["total_time"]:
+ return 1
+ else:
+ return -1
+
+
+@check_user_contest_permission
+def contest_rank_page(request, contest_id):
+ result = ContestSubmission.objects.values("user_id").annotate(total_submit=Count("user_id"))
+ for i in range(0, len(result)):
+ # 这个人所有的提交
+ submissions = ContestSubmission.objects.filter(user_id=result[i]["user_id"])
+ result[i]["total_ac"] = submissions.filter(ac=True).count()
+ result[i]["user"] = User.objects.get(id=result[i]["user_id"])
+ result[i]["submissions"] = submissions.order_by("problem__sort_index")
+ result[i]["total_time"] = submissions.filter(ac=True).aggregate(total_time=Sum("total_time"))["total_time"]
+ print result
+
+ return render(request, "oj/contest/contest_rank.html")
+
+ #
+ #
+ # return
+ # contest = Contest.objects.get(id=contest_id)
+ # contest_submissions = ContestSubmission.objects.filter(contest=contest)
+ # result = {}
+ # # 先把数据按照用户id 为 key 整理一下
+ # # {1: {"submissions": [], "total_time": 0, "total_ac": 0}}
+ # for item in contest_submissions:
+ # if item.user.id not in contest_submissions:
+ # result[item.user.id] = {"user": {"id": item.user.id, "username": item.user.username,
+ # "real_name": item.user.real_name},
+ # "submissions": [], "total_time": 0, "total_ac": 0}
+ # result[item.user.id]["submissions"].append(ContestSubmissionSerializer(item).data)
+ # if item.ac:
+ # result[item.user.id]["total_time"] += item.total_time
+ # result[item.user.id]["total_ac"] += 1
+ # l = []
+ # for k, v in result.iteritems():
+ # l.append(v)
+ # print sorted(l, cmp=_cmp, reverse=True)
+
+
+
+
diff --git a/static/src/css/contest/add_contest.css b/static/src/css/contest/add_contest.css
new file mode 100644
index 0000000..af9ee38
--- /dev/null
+++ b/static/src/css/contest/add_contest.css
@@ -0,0 +1,5 @@
+.group-tag {
+ padding-left: 5px; color: #46799b; background: #e0eaf1; white-space: nowrap;
+ overflow: hidden; cursor: pointer; border-radius: 2px 0 0 2px;
+ float: left; padding: 0 4px;box-sizing: border-box;list-style-type: none; margin: 5px;
+}
diff --git a/static/src/js/app/admin/admin.js b/static/src/js/app/admin/admin.js
index 989cbf7..bd0d51e 100644
--- a/static/src/js/app/admin/admin.js
+++ b/static/src/js/app/admin/admin.js
@@ -75,6 +75,9 @@ define("admin", ["jquery", "avalon"], function ($, avalon) {
groupId: -1,
problemId: -1,
adminNavList: [],
+ $contestMode: -1,
+ $problemId: -1,
+ $contestId: -1,
hide_loading: function () {
$("#loading-gif").hide();
},
@@ -123,6 +126,18 @@ define("admin", ["jquery", "avalon"], function ($, avalon) {
vm.template_url = "template/problem/submission_list.html";
});
+ vm.$watch("showContestProblemPage", function (problemId, contestId, contestMode) {
+ vm.$problemId = problemId;
+ vm.$contestId = contestId;
+ vm.$contestMode = contestMode
+ vm.template_url = "template/contest/edit_problem.html";
+ });
+
+ vm.$watch("showContestListPage", function (problemId) {
+ vm.problemId = problemId;
+ vm.template_url = "template/contest/contest_list.html";
+ });
+
avalon.scan();
window.onhashchange = function () {
diff --git a/static/src/js/app/admin/contest/addContest.js b/static/src/js/app/admin/contest/addContest.js
new file mode 100644
index 0000000..437fbdf
--- /dev/null
+++ b/static/src/js/app/admin/contest/addContest.js
@@ -0,0 +1,166 @@
+require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "datetimePicker",
+ "validator"],
+ function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
+
+ //avalon.vmodels.add_contest = null;
+ $("#add-contest-form").validator().on('submit', function (e) {
+ if (!e.isDefaultPrevented()){
+ e.preventDefault();
+ var ajaxData = {
+ title: vm.title,
+ description: vm.description,
+ mode: vm.mode,
+ contest_type: 0,
+ show_rank: vm.showRank,
+ show_user_submission: vm.showSubmission,
+ start_time: vm.startTime,
+ end_time: vm.endTime,
+ visible: false
+ };
+ if (vm.choseGroupList.length == 0) {
+ bsAlert("你没有选择参赛用户!");
+ return false;
+ }
+ if (vm.choseGroupList[0].id == 0) { //everyone | public contest
+ if (vm.password) {
+ ajaxData.password = vm.password;
+ ajaxData.contest_type = 2;
+ }
+ else{
+ ajaxData.contest_type = 1;
+ }
+ }
+ else { // Add groups info
+ ajaxData.groups = [];
+ for (var i = 0; vm.choseGroupList[i]; i++)
+ ajaxData.groups.push(parseInt(vm.choseGroupList[i].id))
+ }
+
+ $.ajax({ // Add contest
+ beforeSend: csrfTokenHeader,
+ url: "/api/admin/contest/",
+ dataType: "json",
+ contentType: "application/json",
+ data: JSON.stringify(ajaxData),
+ method: "post",
+ contentType: "application/json",
+ success: function (data) {
+ if (!data.code) {
+ bsAlert("添加成功!将转到比赛列表页以便为比赛添加问题(注意比赛当前状态为:隐藏)");
+ vm.title = "";
+ vm.description = "";
+ vm.startTime = "";
+ vm.endTime = "";
+ vm.password = "";
+ vm.mode = "";
+ vm.showRank = false;
+ vm.showSubmission = false;
+ vm.group = "-1";
+ vm.groupList = [];
+ vm.choseGroupList = [];
+ vm.passwordUsable = false;
+ location.hash = "#contest/contest_list";
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+ });
+ }
+ return false;
+ });
+
+ editor("#editor");
+ if (avalon.vmodels.add_contest)
+ var vm = avalon.vmodels.add_contest;
+ else
+ var vm = avalon.define({
+ $id: "add_contest",
+ title: "",
+ description: "",
+ startTime: "",
+ endTime: "",
+ password: "",
+ mode: "",
+ showRank: false,
+ showSubmission: false,
+ group: "-1",
+ groupList: [],
+ choseGroupList: [],
+ passwordUsable: false,
+ addGroup: function() {
+ if (vm.group == -1) return;
+ if (vm.groupList[vm.group].id == 0){
+ vm.passwordUsable = true;
+ vm.choseGroupList = [];
+ for (var key in vm.groupList){
+ vm.groupList[key].chose = true;
+ }
+ }
+ vm.groupList[vm.group]. chose = true;
+ vm.choseGroupList.push({name:vm.groupList[vm.group].name, index:vm.group, id:vm.groupList[vm.group].id});
+ vm.group = -1;
+ },
+ removeGroup: function(groupIndex){
+ if (vm.groupList[vm.choseGroupList[groupIndex].index].id == 0){
+ vm.passwordUsable = false;
+ for (key in vm.groupList){
+ vm.groupList[key].chose = false;
+ }
+ }
+ vm.groupList[vm.choseGroupList[groupIndex].index].chose = false;
+ vm.choseGroupList.remove(vm.choseGroupList[groupIndex]);
+ }
+ });
+
+ $.ajax({ // Get current user type
+ url: "/api/user/",
+ method: "get",
+ dataType: "json",
+ success: function (data) {
+ if (!data.code) {
+ if (data.data.admin_type == 2) { // Is super user
+ vm.isGlobal = true;
+ vm.groupList.push({id:0,name:"所有人",chose:false});
+ }
+ $.ajax({ // Get the group list of current user
+ beforeSend: csrfTokenHeader,
+ url: "/api/admin/group/",
+ method: "get",
+ dataType: "json",
+ success: function (data) {
+ if (!data.code) {
+ if (!data.data.length) {
+ bsAlert("您的用户权限只能创建组内比赛,但是您还没有创建过小组");
+ return;
+ }
+ for (var i = 0; i < data.data.length; i++) {
+ var item = data.data[i];
+ item["chose"] = false;
+ vm.groupList.push(item);
+ }
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ avalon.scan();
+
+ $("#contest_start_time").datetimepicker({
+ format: "yyyy-mm-dd hh:ii",
+ minuteStep: 5,
+ weekStart: 1,
+ language: "zh-CN"
+ });
+ $("#contest_end_time").datetimepicker({
+ format: "yyyy-mm-dd hh:ii",
+ minuteStep: 5,
+ weekStart: 1,
+ language: "zh-CN"
+ });
+ });
\ No newline at end of file
diff --git a/static/src/js/app/admin/contest/add_contest.js b/static/src/js/app/admin/contest/add_contest.js
deleted file mode 100644
index dfa8d60..0000000
--- a/static/src/js/app/admin/contest/add_contest.js
+++ /dev/null
@@ -1,231 +0,0 @@
-require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "datetimePicker",
- "validator"],
- function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
- avalon.vmodels.add_contest = null;
- $("#add-contest-form").validator().on('submit', function (e) {
- if (!e.isDefaultPrevented()){
- e.preventDefault();
- var ajaxData = {
- title: vm.title,
- description: vm.description,
- mode: vm.mode,
- contest_type: 0,
- show_rank: vm.showRank,
- show_user_submission: vm.showSubmission,
- //password: vm.password,
- start_time: vm.startTime,
- end_time: vm.endTime,
- visible: true
- };
- if (vm.choseGroupList[0].id == 0) //everyone | public contest
- if (vm.password == "")
- ajaxData.contest_type = 1;
- else{
- ajaxData.password = vm.password;
- }
- else { // Add groups info
- ajaxData.groups = [];
- for (var i = 0; vm.choseGroupList[i]; i++)
- ajaxData.groups.push(parseInt(vm.choseGroupList[i].id))
- }
-
-
- console.log(ajaxData);
- $.ajax({
- beforeSend: csrfTokenHeader,
- url: "/api/admin/contest/",
- dataType: "json",
- contentType: "application/json",
- data: JSON.stringify(ajaxData),
- method: "post",
- contentType: "application/json",
- success: function (data) {
- if (!data.code) {
- bsAlert("添加成功!");
- console.log(data);
- }
- else {
- bsAlert(data.data);
- console.log(data);
- }
- }
- });
- console.log(JSON.stringify(ajaxData));
- }
- return false;
- });
-
- editor("#editor");
- editor("#problemDescriptionEditor");
- editor("#problemHintEditor");
-
- var vm = avalon.define({
- $id: "add_contest",
- title: "",
- description: "",
- startTime: "",
- endTime: "",
- password: "",
- mode: "",
- showRank: false,
- showSubmission: false,
- problems: [],
- editingProblemId: 0,
- editSamples: [],
- editTestCaseList: [],
- group: "-1",
- groupList: [],
- choseGroupList: [],
- showProblemEditArea: function (problemIndex) {
- if (vm.editingProblemId == problemIndex){
- vm.problems[vm.editingProblemId-1].samples = vm.editSamples;
- vm.editingProblemId = 0;
- }
- else {
- if (vm.editingProblemId)
- {
- vm.problems[vm.editingProblemId-1].samples = vm.editSamples;
- vm.problems[vm.editingProblemId-1].testCaseList = vm.editTestCaseList;
- }
- vm.editingProblemId = problemIndex;
- vm.editSamples = [];
- vm.editSamples = vm.problems[vm.editingProblemId-1].samples;
- vm.editTestCaseList = [];
- vm.editTestCaseList = vm.problems[vm.editingProblemId-1].testCaseList;
- }
- },
- passwordUsable: false,
- add_problem: function () {
- var problem = {
- title: "",
- timeLimit: 1000,
- memoryLimit: 256,
- description: "",
- samples: [],
- visible: true,
- test_case_id: "",
- testCaseList: [],
- hint: "",
- score: 0,
- uploadSuccess: false,
- };
- vm.problems.push(problem);
- vm.showProblemEditArea(vm.problems.length);
- },
- del_problem: function (problemIndex) {
- if (confirm("你确定要删除么?")) {
- vm.editingProblemId = 0;
- vm.problems.remove(vm.problems[problemIndex-1]);
- }
- },
- hidden: function () {
- vm.problems[vm.editingProblemId-1].samples = editSamples;
- vm.problems[vm.editingProblemId-1].testCaseList = editTestCaseList;
- vm.editingProblemId = 0;
- },
- toggle: function (item) {
- item.visible = !item.visible;
- },
- add_sample: function () {
- vm.editSamples.push({visible: true, input: "", output: ""});
- },
- del_sample: function (sample) {
- if (confirm("你确定要删除么?")) {
- editSamples.remove(sample);
- }
- },
- getBtnContent: function (item) {
- if (item.visible)
- return "折叠";
- return "展开";
- },
- addGroup: function() {
- if (vm.group == -1) return;
- if (vm.groupList[vm.group].id == 0){
- vm.passwordUsable = true;
- vm.choseGroupList = [];
- for (var key in vm.groupList){
- vm.groupList[key].chose = true;
- }
- }
- vm.groupList[vm.group]. chose = true;
- vm.choseGroupList.push({name:vm.groupList[vm.group].name, index:vm.group, id:vm.groupList[vm.group].id});
- },
- unchose: function(groupIndex){
- if (vm.groupList[vm.choseGroupList[groupIndex].index].id == 0){
- vm.passwordUsable = false;
- for (key in vm.groupList){
- vm.groupList[key].chose = false;
- }
- }
- vm.groupList[vm.choseGroupList[groupIndex].index].chose = false;
- vm.choseGroupList.remove(vm.choseGroupList[groupIndex]);
- }
- });
-
- var isSuperAdmin = true;
- $.ajax({ //用于获取该用户创建的所有小组的ajax请求
- beforeSend: csrfTokenHeader,
- url: "/api/admin/group/?my_group=true",
- dataType: "json",
- method: "get",
- contentType: "application/json",
- success: function (data) {
- if (!data.code) {
- if (isSuperAdmin)
- vm.groupList.push({id:0, name:"所有人", chose: false});
- for (var key in data.data) {
- data.data[key].chose = false;
- vm.groupList.push(data.data[key]);
- }
- }
- else {
- bsAlert(data.data);
- console.log(data);
- }
- }
- });
-
-
-
- uploader("#uploader", "/api/admin/test_case_upload/", function (file, respond) {
- if (respond.code)
- bsAlert(respond.data);
- else {
- vm.problems[vm.editingProblemId-1].test_case_id = respond.data.test_case_id;
- vm.problems[vm.editingProblemId-1].uploadSuccess = true;
- vm.editTestCaseList = [];
- for (var i = 0; i < respond.data.file_list.input.length; i++) {
- vm.editTestCaseList.push({
- input: respond.data.file_list.input[i],
- output: respond.data.file_list.output[i]
- });
- }
- vm.problems[vm.editingProblemId-1].testCaseList = vm.editTestCaseList;
- bsAlert("测试数据添加成功!共添加"+vm.editTestCaseList.length +"组测试数据");
- }
- },
- function(){
- if (vm.editingProblemId == 0)
- {
- bsAlert("你还未指定一道题目!");
- return false;
- }
- }
- );
-
- avalon.scan();
-
- $("#contest_start_time").datetimepicker({
- format: "yyyy-mm-dd hh:ii",
- minuteStep: 5,
- weekStart: 1,
- language: "zh-CN"
- });
- $("#contest_end_time").datetimepicker({
- format: "yyyy-mm-dd hh:ii",
- minuteStep: 5,
- weekStart: 1,
- language: "zh-CN"
- });
- });
diff --git a/static/src/js/app/admin/contest/contestList.js b/static/src/js/app/admin/contest/contestList.js
new file mode 100644
index 0000000..9c1ba71
--- /dev/null
+++ b/static/src/js/app/admin/contest/contestList.js
@@ -0,0 +1,331 @@
+require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker", "validator"], function ($, avalon, csrfTokenHeader, bsAlert, editor) {
+
+ avalon.ready(function () {
+
+ $("#edit-contest-form").validator().on('submit', function (e) {
+ if (!e.isDefaultPrevented()){
+ e.preventDefault();
+ var ajaxData = {
+ id: vm.contestList[vm.editingContestId-1].id,
+ title: vm.editTitle,
+ description: vm.editDescription,
+ mode: vm.editMode,
+ contest_type: 0,
+ show_rank: vm.editShowRank,
+ show_user_submission: vm.editShowSubmission,
+ start_time: vm.editStartTime,
+ end_time: vm.editEndTime,
+ visible: vm.editVisible
+ };
+ if (vm.choseGroupList.length == 0) {
+ bsAlert("你没有选择参赛用户!");
+ return false;
+ }
+ if (vm.editDescription == "") {
+ bsAlert("比赛描述不能为空!");
+ return false;
+ }
+ if (vm.choseGroupList[0].id == 0) { //everyone | public contest
+ if (vm.editPassword) {
+ ajaxData.password = vm.editPassword;
+ ajaxData.contest_type = 2;
+ }
+ else{
+ ajaxData.contest_type = 1;
+ }
+ }
+ else { // Add groups info
+ ajaxData.groups = [];
+ for (var i = 0; vm.choseGroupList[i]; i++)
+ ajaxData.groups.push(parseInt(vm.choseGroupList[i].id))
+ }
+
+ $.ajax({ // Add contest
+ beforeSend: csrfTokenHeader,
+ url: "/api/admin/contest/",
+ dataType: "json",
+ contentType: "application/json",
+ data: JSON.stringify(ajaxData),
+ method: "put",
+ contentType: "application/json",
+ success: function (data) {
+ if (!data.code) {
+ bsAlert("修改成功!");
+ vm.editingContestId = 0; // Hide the editor
+ vm.getPage(1); // Refresh the contest list
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+ });
+ }
+ return false;
+ });
+
+ if(avalon.vmodels.contestList){
+ // this page has been loaded before, so set the default value
+ var vm = avalon.vmodels.contestList;
+ vm.contestList= [];
+ vm.previousPage= 0;
+ vm.nextPage= 0;
+ vm.page= 1;
+ vm.totalPage= 1;
+ vm.group= "-1";
+ vm.groupList= [];
+ vm.choseGroupList= [];
+ vm.passwordUsable= false;
+ vm.keyword= "";
+ vm.editingContestId= 0;
+ vm.editTitle= "";
+ vm.editDescription= "";
+ vm.editProblemList= [];
+ vm.editPassword= "";
+ vm.editStartTime= "";
+ vm.editEndTime= "";
+ vm.editMode= "";
+ vm.editShowRank= false;
+ vm.editShowSubmission= false;
+ vm.editProblemList= [];
+ vm.editVisible= false;
+ vm.editChoseGroupList= [];
+ vm.editingProblemContestIndex= 0;
+ }
+ else {
+ var vm = avalon.define({
+ $id: "contestList",
+ contestList: [],
+ previousPage: 0,
+ nextPage: 0,
+ page: 1,
+ totalPage: 1,
+ showVisibleOnly: false,
+ group: "-1",
+ groupList: [],
+ choseGroupList: [],
+ passwordUsable: false,
+ keyword: "",
+ editingContestId: 0,
+ editTitle: "",
+ editDescription: "",
+ editProblemList: [],
+ editPassword: "",
+ editStartTime: "",
+ editEndTime: "",
+ editMode: "",
+ editShowRank: false,
+ editShowSubmission: false,
+ editProblemList: [],
+ editVisible: false,
+ editChoseGroupList: [],
+ editingProblemContestIndex: 0,
+ getNext: function () {
+ if (!vm.nextPage)
+ return;
+ getPageData(vm.page + 1);
+ },
+ getPrevious: function () {
+ if (!vm.previousPage)
+ return;
+ getPageData(vm.page - 1);
+ },
+ getBtnClass: function (btn) {
+ if (btn == "next") {
+ return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
+ }
+ else {
+ return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
+ }
+ },
+ getPage: function (page_index) {
+ getPageData(page_index);
+ },
+ showEditContestArea: function (contestId) {
+ if (vm.editingContestId && !confirm("如果继续将丢失未保存的信息,是否继续?"))
+ return;
+ if (contestId == vm.editingContestId)
+ vm.editingContestId = 0;
+ else {
+ vm.editingContestId = contestId;
+ vm.editTitle = vm.contestList[contestId-1].title;
+ vm.editPassword = vm.contestList[contestId-1].password;
+ vm.editStartTime = vm.contestList[contestId-1].start_time.substring(0,16).replace("T"," ");
+ vm.editEndTime = vm.contestList[contestId-1].end_time.substring(0,16).replace("T"," ");
+ vm.editMode = vm.contestList[contestId-1].mode;
+ vm.editVisible = vm.contestList[contestId-1].visible;
+ if (vm.contestList[contestId-1].contest_type == 0) { //contest type == 0, contest in group
+ //Clear the choseGroupList
+ while (vm.choseGroupList.length) {
+ vm.removeGroup(0);
+ }
+
+ for (var i = 0; i < vm.contestList[contestId-1].groups.length; i++){
+ var id = parseInt(vm.contestList[contestId-1].groups[i]);
+ var index = 0;
+ for (; vm.groupList[index]; index++) {
+ if (vm.groupList[index].id == id)
+ break;
+ }
+ vm.groupList[index].chose = true;
+ vm.choseGroupList.push({
+ name:vm.groupList[index].name,
+ index:index,
+ id:id
+ });
+ }
+ }
+ else{
+ vm.group = "0";
+ vm.addGroup()//vm.editChoseGroupList = [0]; id 0 is for the group of everyone~
+ }
+ vm.editShowRank = vm.contestList[contestId-1].show_rank;
+ vm.editShowSubmission = vm.contestList[contestId-1].show_user_submission;
+ editor("#editor").setValue(vm.contestList[contestId-1].description);
+ vm.editingProblemContestIndex = 0;
+ }
+ },
+ showEditProblemArea: function(contestId) {
+ if (vm.editingProblemContestIndex == contestId) {
+ vm.editingProblemContestIndex = 0;
+ return;
+ }
+ if (vm.editingContestId&&!confirm("如果继续将丢失未保存的信息,是否继续?")){
+ return;
+ }
+ $.ajax({ // Get the problem list of current contest
+ beforeSend: csrfTokenHeader,
+ url: "/api/admin/contest_problem/?contest_id=" + vm.contestList[contestId-1].id,
+ method: "get",
+ dataType: "json",
+ success: function (data) {
+ if (!data.code) {
+ vm.editProblemList = data.data;
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+ });
+ vm.editingContestId = 0;
+ vm.editingProblemContestIndex = contestId;
+ vm.editMode = vm.contestList[contestId-1].mode;
+ },
+ addGroup: function() {
+ if (vm.group == -1) return;
+ if (vm.groupList[vm.group].id == 0){
+ vm.passwordUsable = true;
+ vm.choseGroupList = [];
+ for (var i = 0; i < vm.groupList.length; i++) {
+ vm.groupList[i].chose = true;
+ }
+ }
+ vm.groupList[vm.group]. chose = true;
+ // index of the group is relative. It is related to user
+ vm.choseGroupList.push({name:vm.groupList[vm.group].name, index:vm.group, id:vm.groupList[vm.group].id});
+ vm.group = -1;
+ },
+ removeGroup: function(groupIndex){
+ if (vm.groupList[vm.choseGroupList[groupIndex].index].id == 0){
+ vm.passwordUsable = false;
+ for (var i = 0; i < vm.groupList.length; i++) {
+ vm.groupList[i].chose = false;
+ }
+ }
+ vm.groupList[vm.choseGroupList[groupIndex].index].chose = false;
+ vm.choseGroupList.remove(vm.choseGroupList[groupIndex]);
+ },
+ add_problem: function () {
+ vm.$fire("up!showContestProblemPage", 0, vm.contestList[vm.editingProblemContestIndex-1].id, vm.editMode);
+ },
+ showProblemEditor: function(el) {
+ vm.$fire("up!showContestProblemPage", el.id, vm.contestList[vm.editingProblemContestIndex-1].id, vm.editMode);
+ },
+ getYesOrNo: function(yORn) {
+ if (yORn) return "是";
+ return "否";
+ }
+ });
+ vm.$watch("showVisibleOnly", function() {
+ getPageData(1);
+ })
+ }
+ getPageData(1);
+
+ //init time picker
+ $("#contest_start_time").datetimepicker({
+ format: "yyyy-mm-dd hh:ii",
+ minuteStep: 5,
+ weekStart: 1,
+ language: "zh-CN"
+ });
+ $("#contest_end_time").datetimepicker({
+ format: "yyyy-mm-dd hh:ii",
+ minuteStep: 5,
+ weekStart: 1,
+ language: "zh-CN"
+ });
+
+ function getPageData(page) {
+ var url = "/api/admin/contest/?paging=true&page=" + page + "&page_size=10";
+ if (vm.showVisibleOnly)
+ url += "&visible=true"
+ if (vm.keyword != "")
+ url += "&keyword=" + vm.keyword;
+ $.ajax({
+ url: url,
+ dataType: "json",
+ method: "get",
+ success: function (data) {
+ if (!data.code) {
+ vm.contestList = data.data.results;
+ vm.totalPage = data.data.total_page;
+ vm.previousPage = data.data.previous_page;
+ vm.nextPage = data.data.next_page;
+ vm.page = page;
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+ });
+ }
+ // Get group list
+ $.ajax({ // Get current user type
+ url: "/api/user/",
+ method: "get",
+ dataType: "json",
+ success: function (data) {
+ if (!data.code) {
+ if (data.data.admin_type == 2) { // Is super user
+ vm.isGlobal = true;
+ vm.groupList.push({id:0,name:"所有人",chose:false});
+ }
+ $.ajax({ // Get the group list of current user
+ beforeSend: csrfTokenHeader,
+ url: "/api/admin/group/",
+ method: "get",
+ dataType: "json",
+ success: function (data) {
+ if (!data.code) {
+ if (!data.data.length) {
+ //this user have no group can use
+ return;
+ }
+ for (var i = 0; i < data.data.length; i++) {
+ var item = data.data[i];
+ item["chose"] = false;
+ vm.groupList.push(item);
+ }
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ });
+ avalon.scan();
+});
diff --git a/static/src/js/app/admin/contest/contest_list.js b/static/src/js/app/admin/contest/contest_list.js
deleted file mode 100644
index 1b2de7a..0000000
--- a/static/src/js/app/admin/contest/contest_list.js
+++ /dev/null
@@ -1,139 +0,0 @@
-require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker"], function ($, avalon, csrfTokenHeader, bsAlert, editor) {
-
- avalon.ready(function () {
- if (avalon.vmodels.contestList) {
- vm = avalon.vmodels.contestList;
- vm.editingContest = 0;
- }
- else {
- var vm = avalon.define({
- $id: "contestList",
- contestList: [],
- previousPage: 0,
- nextPage: 0,
- page: 1,
- totalPage: 1,
- group: "-1",
- groupList: [],
- keyword: "",
- editingContestId: 0,
- editTitle: "",
- editProblemList: [],
- editPassword: "",
- editStartTime: "",
- editEndTime: "",
- editMode: "",
- editShowRank: false,
- editShowSubmission: false,
- editProblemList: [],
- editingProblemId: 0,
- editSamples: [],
- editTestCaseList: [],
- editChoseGroupList: [],
- modelNameList: ["ACM", "AC总数", "分数"],
- contestTypeNameList: ["小组赛", "公开赛", "有密码保护的公开赛"],
- getNext: function () {
- if (!vm.nextPage)
- return;
- getPageData(vm.page + 1);
- },
- getPrevious: function () {
- if (!vm.previousPage)
- return;
- getPageData(vm.page - 1);
- },
- getBtnClass: function (btn) {
- if (btn == "next") {
- return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
- }
- else {
- return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
- }
- },
- getPage: function (page_index) {
- getPageData(page_index);
- },
- showEditContestArea: function (contestId) {
- if (contestId == vm.editingContestId)
- vm.editingContestId = 0;
- else {
- vm.editingContestId = contestId;
- vm.editTitle = vm.contestList[contestId - 1].title;
- vm.editEndTime = vm.contestList[contestId - 1].end_time;
- vm.editPassword = vm.contestList[contestId - 1].password;
- vm.editStartTime = vm.contestList[contestId - 1].start_time;
- vm.editMode = vm.contestList[contestId - 1].mode;
- vm.editChoseGroupList = [];
- //= vm.contestList[contestId-1].group;//
- /*for (var key in vm.contestList[contestId-1].groups){
- var id = parseInt(vm.contestList[contestId-1].groups);
- for ()
- vm.editChoseGroupList.push({
- name:vm.groupList[vm.group].name,
- index:index,
- id:parseInt(vm.contestList[contestId-1].groups)
- });
- }*/
- vm.editShowRank = vm.contestList[contestId - 1].show_rank;
- vm.editShowSubmission = vm.contestList[contestId - 1].show_user_submission;
- //vm.editProblemList = vm.contestList[contestId-1].problems
- editor("#editor").setValue(vm.contestList[contestId - 1].description);
- vm.editingProblemList = vm.contestList[contestId - 1].problemList;
- }
- }
- });
-
- getPageData(1);
- }
-
- function getPageData(page) {
-
- var url = "/api/admin/contest/?paging=true&page=" + page + "&page_size=10";
- if (vm.keyword != "")
- url += "&keyword=" + vm.keyword;
- $.ajax({
- url: url,
- dataType: "json",
- method: "get",
- success: function (data) {
- if (!data.code) {
- vm.contestList = data.data.results;
- vm.totalPage = data.data.total_page;
- vm.previousPage = data.data.previous_page;
- vm.nextPage = data.data.next_page;
- vm.page = page;
- }
- else {
- bsAlert(data.data);
- }
- }
- });
- }
-
- var isSuperAdmin = true;
-
- $.ajax({ //用于获取该用户创建的所有小组的ajax请求
-
- url: "/api/admin/group/",
- method: "get",
- dataType: "json",
- success: function (data) {
- if (!data.code) {
- if (!data.data.length) {
- bsAlert("您的用户权限只能创建组内比赛,但是您还没有创建过小组");
- return;
- }
- for (var i = 0; i < data.data.length; i++) {
- var item = data.data[i];
- item["chose"] = false;
- vm.groupList.push(item);
- }
- }
- else {
- bsAlert(data.data);
- }
- }
- });
- });
- avalon.scan();
-});
diff --git a/static/src/js/app/admin/contest/editProblem.js b/static/src/js/app/admin/contest/editProblem.js
new file mode 100644
index 0000000..51a668d
--- /dev/null
+++ b/static/src/js/app/admin/contest/editProblem.js
@@ -0,0 +1,203 @@
+require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagEditor", "validator", "jqueryUI"],
+ function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
+
+ avalon.ready(function () {
+
+ $("#edit-problem-form").validator()
+ .on('submit', function (e) {
+ if (!e.isDefaultPrevented()){
+ e.preventDefault();
+ if (vm.testCaseId == "") {
+ bsAlert("你还没有上传测试数据!");
+ return false;
+ }
+ if (vm.description == "") {
+ bsAlert("题目描述不能为空!");
+ return false;
+ }
+ if (vm.timeLimit < 1000 || vm.timeLimit > 5000) {
+ bsAlert("保证时间限制是一个1000-5000的合法整数");
+ return false;
+ }
+ if (vm.samples.length == 0) {
+ bsAlert("请至少添加一组样例!");
+ return false;
+ }
+ for (var i = 0; i < vm.samples.length; i++) {
+ if (vm.samples[i].input == "" || vm.samples[i].output == "") {
+ bsAlert("样例输入与样例输出不能为空!");
+ return false;
+ }
+ }
+ var ajaxData = {
+ title: vm.title,
+ description: vm.description,
+ time_limit: vm.timeLimit,
+ memory_limit: vm.memoryLimit,
+ samples: [],
+ test_case_id: vm.testCaseId,
+ hint: vm.hint,
+ visible: vm.visible,
+ contest_id: avalon.vmodels.admin.$contestId,
+ input_description: vm.inputDescription,
+ output_description: vm.outputDescription,
+ sort_index: vm.sortIndex,
+ };
+ if (vm.contestMode == '2') {
+ if (!vm.score) {
+ bsAlert("请输入有效的分值!")
+ return false;
+ }
+ ajaxData.score = vm.score;
+ }
+ var method = "post";
+ if (avalon.vmodels.admin.$problemId) {
+ method = "put";
+ ajaxData.id = avalon.vmodels.admin.$problemId;
+ }
+
+ for (var i = 0; i < vm.samples.$model.length; i++) {
+ ajaxData.samples.push({input: vm.samples.$model[i].input, output: vm.samples.$model[i].output});
+ }
+
+ $.ajax({
+ beforeSend: csrfTokenHeader,
+ url: "/api/admin/contest_problem/",
+ dataType: "json",
+ data: JSON.stringify(ajaxData),
+ method: method,
+ contentType: "application/json",
+ success: function (data) {
+ if (!data.code) {
+ bsAlert("题目编辑成功!");
+ vm.goBack(true);
+ }
+ else {
+ bsAlert(data.data);
+ }
+ }
+
+ });
+ return false;
+ }
+ });
+
+ if (!avalon.vmodels.editProblem)
+ var vm = avalon.define({
+ $id: "editProblem",
+ title: "",
+ description: "",
+ timeLimit: 0,
+ memoryLimit: 0,
+ samples: [],
+ hint: "",
+ sortIndex: "",
+ visible: true,
+ inputDescription: "",
+ outputDescription: "",
+ testCaseIdd: "",
+ contestMode: 0,
+ score: 1,
+ uploadSuccess: false,
+ testCaseList: [],
+ addSample: function () {
+ vm.samples.push({input: "", output: "", "visible": true});
+ },
+ delSample: function (sample) {
+ if (confirm("你确定要删除么?")) {
+ vm.samples.remove(sample);
+ }
+ },
+ toggleSample: function (sample) {
+ sample.visible = !sample.visible;
+ },
+ getBtnContent: function (item) {
+ if (item.visible)
+ return "折叠";
+ return "展开";
+ },
+ goBack: function(check){
+ if (check||confirm("这将丢失所有的改动,确定要继续么?")) {
+ vm.$fire("up!showContestListPage");
+ }
+ }
+ });
+ else
+ vm = avalon.vmodels.editProblem;
+
+ var hintEditor = editor("#hint");
+ var descriptionEditor = editor("#problemDescription");
+ var testCaseUploader = uploader("#testCaseFile", "/api/admin/test_case_upload/", function (file, response) {
+ if (response.code)
+ bsAlert(response.data);
+ else {
+ vm.testCaseId = response.data.test_case_id;
+ vm.uploadSuccess = true;
+ vm.testCaseList = [];
+ for (var i = 0; i < response.data.file_list.input.length; i++) {
+ vm.testCaseList.push({
+ input: response.data.file_list.input[i],
+ output: response.data.file_list.output[i]
+ });
+ }
+ bsAlert("测试数据添加成功!共添加" + vm.testCaseList.length + "组测试数据");
+ }
+ });
+
+ vm.contestMode = avalon.vmodels.admin.$contestMode;
+ if (avalon.vmodels.admin.$problemId){
+ $.ajax({
+ url: "/api/admin/contest_problem/?contest_problem_id=" + avalon.vmodels.admin.$problemId,
+ method: "get",
+ dataType: "json",
+ success: function (data) {
+ if (data.code) {
+ bsAlert(data.data);
+ }
+ else { // Edit mode load the problem data
+ var problem = data.data;
+ vm.testCaseList = [];
+ vm.sortIndex = problem.sort_index;
+ vm.title = problem.title;
+ vm.description = problem.description;
+ vm.timeLimit = problem.time_limit;
+ vm.memoryLimit = problem.memory_limit;
+ vm.hint = problem.hint;
+ vm.visible = problem.visible;
+ vm.inputDescription = problem.input_description;
+ vm.outputDescription = problem.output_description;
+ vm.score = problem.score;
+ vm.samples = [];
+ vm.testCaseId = problem.test_case_id;
+ for (var i = 0; i < problem.samples.length; i++) {
+ vm.samples.push({
+ input: problem.samples[i].input,
+ output: problem.samples[i].output,
+ visible: false
+ })
+ }
+ hintEditor.setValue(vm.hint);
+ descriptionEditor.setValue(vm.description);
+ }
+ }
+ });
+ }
+ else { //Create new problem Set default values
+ vm.testCaseList = [];
+ vm.title = "";
+ vm.timeLimit = 1000;
+ vm.memoryLimit = 256;
+ vm.samples = [];
+ vm.visible = true;
+ vm.inputDescription = "";
+ vm.outputDescription = "";
+ vm.testCaseId = "";
+ vm.sortIndex = "";
+ vm.score = 0;
+ hintEditor.setValue("");
+ descriptionEditor.setValue("");
+ }
+ });
+ avalon.scan();
+
+ });
diff --git a/static/src/js/app/admin/problem/add_problem.js b/static/src/js/app/admin/problem/addProblem.js
similarity index 71%
rename from static/src/js/app/admin/problem/add_problem.js
rename to static/src/js/app/admin/problem/addProblem.js
index 7331a8a..d34cd9a 100644
--- a/static/src/js/app/admin/problem/add_problem.js
+++ b/static/src/js/app/admin/problem/addProblem.js
@@ -1,7 +1,7 @@
require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagEditor", "validator", "jqueryUI"],
function ($, avalon, editor, uploader, bsAlert, csrfTokenHeader) {
avalon.ready(function () {
- avalon.vmodels.addProblem = null;
+
$("#add-problem-form").validator()
.on('submit', function (e) {
if (!e.isDefaultPrevented()){
@@ -63,6 +63,7 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
success: function (data) {
if (!data.code) {
bsAlert("题目添加成功!");
+ location.hash = "problem/problem_list";
}
else {
bsAlert(data.data);
@@ -92,41 +93,61 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
var hintEditor = editor("#hint");
var problemDescription = editor("#problemDescription");
-
- var vm = avalon.define({
- $id: "addProblem",
- title: "",
- description: "",
- timeLimit: 1000,
- memoryLimit: 256,
- samples: [{input: "", output: "", "visible": true}],
- hint: "",
- visible: true,
- difficulty: 0,
- tags: [],
- inputDescription: "",
- outputDescription: "",
- testCaseId: "",
- testCaseList: [],
- uploadSuccess: false,
- source: "",
- addSample: function () {
- vm.samples.push({input: "", output: "", "visible": true});
- },
- delSample: function (sample) {
- if (confirm("你确定要删除么?")) {
- vm.samples.remove(sample);
+ if (avalon.vmodels.addProblem) {
+ var vm = avalon.vmodels.addProblem;
+ vm.title = "";
+ vm.description = "";
+ vm.timeLimit = 1000;
+ vm.memoryLimit = 256;
+ vm.samples = [{input: "", output: "", "visible": true}];
+ vm.hint = "";
+ vm.visible = true;
+ vm.difficulty = 0;
+ vm.tags = [];
+ vm.inputDescription = "";
+ vm.outputDescription = "";
+ vm.testCaseId = "";
+ vm.testCaseList = [];
+ vm.uploadSuccess = false;
+ vm.source = "";
+ hintEditor.setValue("");
+ problemDescription.setValue("");
+ }
+ else
+ var vm = avalon.define({
+ $id: "addProblem",
+ title: "",
+ description: "",
+ timeLimit: 1000,
+ memoryLimit: 256,
+ samples: [{input: "", output: "", "visible": true}],
+ hint: "",
+ visible: true,
+ difficulty: 0,
+ tags: [],
+ inputDescription: "",
+ outputDescription: "",
+ testCaseId: "",
+ testCaseList: [],
+ uploadSuccess: false,
+ source: "",
+ addSample: function () {
+ vm.samples.push({input: "", output: "", "visible": true});
+ },
+ delSample: function (sample) {
+ if (confirm("你确定要删除么?")) {
+ vm.samples.remove(sample);
+ }
+ },
+ toggleSample: function (sample) {
+ sample.visible = !sample.visible;
+ },
+ getBtnContent: function (item) {
+ if (item.visible)
+ return "折叠";
+ return "展开";
}
- },
- toggleSample: function (sample) {
- sample.visible = !sample.visible;
- },
- getBtnContent: function (item) {
- if (item.visible)
- return "折叠";
- return "展开";
- }
- });
+ });
var tagAutoCompleteList = [];
diff --git a/static/src/js/app/admin/problem/edit_problem.js b/static/src/js/app/admin/problem/editProblem.js
similarity index 80%
rename from static/src/js/app/admin/problem/edit_problem.js
rename to static/src/js/app/admin/problem/editProblem.js
index 72a6b7c..a746d7a 100644
--- a/static/src/js/app/admin/problem/edit_problem.js
+++ b/static/src/js/app/admin/problem/editProblem.js
@@ -3,8 +3,6 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
avalon.ready(function () {
-
-
$("#edit-problem-form").validator()
.on('submit', function (e) {
if (!e.isDefaultPrevented()){
@@ -66,6 +64,7 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
success: function (data) {
if (!data.code) {
bsAlert("题目编辑成功!");
+ vm.showProblemListPage();
}
else {
bsAlert(data.data);
@@ -76,49 +75,60 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
return false;
}
});
-
- if(avalon.vmodels.editProblem){
- var vm = avalon.vmodels.editProblem;
- }
- else {
- var vm = avalon.define({
- $id: "editProblem",
- title: "",
- description: "",
- timeLimit: -1,
- memoryLimit: -1,
- samples: [],
- hint: "",
- visible: true,
- difficulty: 0,
- inputDescription: "",
- outputDescription: "",
- testCaseIdd: "",
- uploadSuccess: false,
- source: "",
- testCaseList: [],
- addSample: function () {
- vm.samples.push({input: "", output: "", "visible": true});
- },
- delSample: function (sample) {
- if (confirm("你确定要删除么?")) {
- vm.samples.remove(sample);
- }
- },
- toggleSample: function (sample) {
- sample.visible = !sample.visible;
- },
- getBtnContent: function (item) {
- if (item.visible)
- return "折叠";
- return "展开";
- },
- showProblemListPage: function () {
- vm.$fire("up!showProblemListPage");
+ if (avalon.vmodels.editProblem) {
+ var vm = avalon.vmodels.editProblem;
+ title: "",
+ description= "";
+ timeLimit= -1;
+ memoryLimit= -1;
+ samples= [];
+ hint= "";
+ visible= true;
+ difficulty= 0;
+ inputDescription= "";
+ outputDescription= "";
+ testCaseIdd= "";
+ uploadSuccess= false;
+ source= "";
+ testCaseList= [];
+ }
+ else
+ var vm = avalon.define({
+ $id: "editProblem",
+ title: "",
+ description: "",
+ timeLimit: -1,
+ memoryLimit: -1,
+ samples: [],
+ hint: "",
+ visible: true,
+ difficulty: 0,
+ inputDescription: "",
+ outputDescription: "",
+ testCaseIdd: "",
+ uploadSuccess: false,
+ source: "",
+ testCaseList: [],
+ addSample: function () {
+ vm.samples.push({input: "", output: "", "visible": true});
+ },
+ delSample: function (sample) {
+ if (confirm("你确定要删除么?")) {
+ vm.samples.remove(sample);
}
- });
-
- }
+ },
+ toggleSample: function (sample) {
+ sample.visible = !sample.visible;
+ },
+ getBtnContent: function (item) {
+ if (item.visible)
+ return "折叠";
+ return "展开";
+ },
+ showProblemListPage: function(){
+ vm.$fire("up!showProblemListPage");
+ }
+ });
var hintEditor = editor("#hint");
var descriptionEditor = editor("#problemDescription");
var testCaseUploader = uploader("#testCaseFile", "/api/admin/test_case_upload/", function (file, response) {
@@ -148,7 +158,6 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
}
else {
var problem = data.data;
- console.log(problem);
vm.title = problem.title;
vm.description = problem.description;
vm.timeLimit = problem.time_limit;
@@ -204,4 +213,4 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
});
avalon.scan();
- });
+ });
\ No newline at end of file
diff --git a/static/src/js/app/admin/problem/problem.js b/static/src/js/app/admin/problem/problem.js
index cb1a0f0..2632ebf 100644
--- a/static/src/js/app/admin/problem/problem.js
+++ b/static/src/js/app/admin/problem/problem.js
@@ -41,10 +41,8 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT
vm.$fire("up!showProblemSubmissionPage", problemId);
}
});
-
- getPageData(1);
}
-
+ getPageData(1);
function getPageData(page) {
var url = "/api/admin/problem/?paging=true&page=" + page + "&page_size=10";
if (vm.keyword != "")
diff --git a/static/src/js/app/admin/problem/submission_list.js b/static/src/js/app/admin/problem/submissionList.js
similarity index 91%
rename from static/src/js/app/admin/problem/submission_list.js
rename to static/src/js/app/admin/problem/submissionList.js
index 8593557..405cffa 100644
--- a/static/src/js/app/admin/problem/submission_list.js
+++ b/static/src/js/app/admin/problem/submissionList.js
@@ -40,6 +40,12 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT
},
getPage: function (page_index) {
getPageData(page_index);
+ },
+ showSubmissionDetailPage: function (submissionId) {
+
+ },
+ showProblemListPage: function(){
+ vm.$fire("up!showProblemListPage");
}
});
@@ -66,9 +72,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT
});
}
- avalon.scan();
-
});
-
+ avalon.scan();
});
\ No newline at end of file
diff --git a/static/src/js/app/admin/user/userList.js b/static/src/js/app/admin/user/userList.js
index 0842dc5..3f80c89 100644
--- a/static/src/js/app/admin/user/userList.js
+++ b/static/src/js/app/admin/user/userList.js
@@ -3,58 +3,68 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "validator"], function ($,
// avalon:定义模式 userList
avalon.ready(function () {
- avalon.vmodels.userList = null;
- var vm = avalon.define({
- $id: "userList",
- //通用变量
- userList: [],
- previousPage: 0,
- nextPage: 0,
- page: 1,
- editingUserId: 0,
- totalPage: 1,
- userType: ["一般用户", "管理员", "超级管理员"],
- keyword: "",
- showAdminOnly: false,
- //编辑区域同步变量
- username: "",
- realName: "",
- email: "",
- adminType: 0,
- id: 0,
- getNext: function () {
- if (!vm.nextPage)
- return;
- getPageData(vm.page + 1);
- },
- getPrevious: function () {
- if (!vm.previousPage)
- return;
- getPageData(vm.page - 1);
- },
- getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
- if (btn) {
- return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
+ //avalon.vmodels.userList = null;
+ if (avalon.vmodels.userList) {
+ var vm = avalon.vmodels.userList;
+ // initialize avalon object
+ userList = []; previousPage= 0; nextPage= 0; page = 1;
+ editingUserId= 0; totalPage = 1; keyword= ""; showAdminOnly= false;
+ //user editor fields
+ username= ""; realName= ""; email= ""; adminType= 0; id= 0;
+ }
+ else {
+ var vm = avalon.define({
+ $id: "userList",
+ //通用变量
+ userList: [],
+ previousPage: 0,
+ nextPage: 0,
+ page: 1,
+ editingUserId: 0,
+ totalPage: 1,
+ userType: ["一般用户", "管理员", "超级管理员"],
+ keyword: "",
+ showAdminOnly: false,
+ //编辑区域同步变量
+ username: "",
+ realName: "",
+ email: "",
+ adminType: 0,
+ id: 0,
+ getNext: function () {
+ if (!vm.nextPage)
+ return;
+ getPageData(vm.page + 1);
+ },
+ getPrevious: function () {
+ if (!vm.previousPage)
+ return;
+ getPageData(vm.page - 1);
+ },
+ getBtnClass: function (btn) { //上一页/下一页按钮启用禁用逻辑
+ if (btn == "next") {
+ return vm.nextPage ? "btn btn-primary" : "btn btn-primary disabled";
+ }
+ else {
+ return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
+ }
+ },
+ editUser: function (user) { //点击编辑按钮的事件,显示/隐藏编辑区
+ vm.username = user.username;
+ vm.realName = user.real_name;
+ vm.adminType = user.admin_type;
+ vm.email = user.email;
+ vm.id = user.id;
+ if (vm.editingUserId == user.id)
+ vm.editingUserId = 0;
+ else
+ vm.editingUserId = user.id;
+ },
+ search: function () {
+ getPageData(1);
}
- else {
- return vm.previousPage ? "btn btn-primary" : "btn btn-primary disabled";
- }
- },
- editUser: function (user) { //点击编辑按钮的事件,显示/隐藏编辑区
- vm.username = user.username;
- vm.realName = user.real_name;
- vm.adminType = user.admin_type;
- vm.email = user.email;
- vm.id = user.id;
- if (vm.editingUserId == user.id)
- vm.editingUserId = 0;
- else
- vm.editingUserId = user.id;
- },
- search: function () {
- getPageData(1);
- }
- });
+ });
+ }
vm.$watch("showAdminOnly", function () {
getPageData(1);
});
diff --git a/submission/views.py b/submission/views.py
index af2c41d..17c1615 100644
--- a/submission/views.py
+++ b/submission/views.py
@@ -156,5 +156,4 @@ def my_submission_list_page(request, page=1):
return render(request, "oj/submission/my_submissions_list.html",
{"submissions": current_page, "page": int(page),
- "previous_page": previous_page, "next_page": next_page, "start_id": int(page) * 20 - 20})
-
+ "previous_page": previous_page, "next_page": next_page, "start_id": int(page) * 20 - 20})
\ No newline at end of file
diff --git a/template/admin/contest/add_contest.html b/template/admin/contest/add_contest.html
index 44ae98a..6f237c5 100644
--- a/template/admin/contest/add_contest.html
+++ b/template/admin/contest/add_contest.html
@@ -6,8 +6,9 @@
@@ -17,51 +18,46 @@
开始时间
-
-
- 结束时间
-
-
-
- 允许参加的用户
-
-
- 密码保护
-
-
+
允许参加的用户
-
+
+ 请选择
+ {{el.name}}
+
+
+
+
-
{{el.name}}
+
{{el.name}}
排名方式
@@ -94,135 +90,12 @@
-
添加题目
-
添加
-
-
- 编号
- 题目
- 测试数据
-
-
-
- 题目{{ $index+1 }}
- {{ el.title }}
- {{ el.testCaseList.length }}组
-
- 编辑
- 删除
-
-
-
-
-
-
-
-
-
-
-
题目{{editingProblemId}}
-
隐藏
-
删除
-
-
-
-
- 题目描述
-
- 请填写题目描述
-
-
- 提示
-
-
-
-
-
-
-
-
-
测试数据
-
-
- 编号
- 输入文件名
- 输出文件名
-
-
- {{$index}}
- {{ el.input }}
- {{ el.output }}
-
-
-
-
-
-
-
-
-
上传测试测试数据
-
-
请将所有测试用例打包在一个文件中上传,所有文件要在压缩包的根目录,且输入输出文件名要以从1开始连续数字标识要对应例如:
- 1.in 1.out 2.in 2.out
-
-
@@ -230,4 +103,4 @@
-
+
diff --git a/template/admin/contest/contest_list.html b/template/admin/contest/contest_list.html
index ab878ae..5c15629 100644
--- a/template/admin/contest/contest_list.html
+++ b/template/admin/contest/contest_list.html
@@ -15,154 +15,174 @@
ID
比赛
- 比赛类型
公开排名
- 开始时间
- 结束时间
+ 可见
创建时间
创建者
+
-
+
{{ el.id }}
{{ el.title }}
- {{ contestTypeNameList[el.contest_type] }}
- {{ el.show_rank }}
- {{ el.start_time|date("yyyy-MM-dd HH:mm:ss")}}
- {{ el.end_time|date("yyyy-MM-dd HH:mm:ss")}}
+ {{ getYesOrNo(el.show_rank) }}
+ {{ getYesOrNo(el.visible) }}
{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}
{{ el.created_by.username }}
+
+ 编辑
+ 编辑问题
+
+
+ 仅显示可见
+
页数:{{ page }}/{{ totalPage }}
上一页
下一页
-
- 比赛名称
-
-
-
-
- 说明
-
-
-
-
- 开始时间
-
-
- 结束时间
-
-
-
-
- 允许参加的用户
-
-
- 密码保护
-
-
-
-
- 请选择
- {{el.name}}
-
-
-
-
-
-
- 排名方式
-
-
- 结束前是否开放排名
-
-
- 是否公开提交记录
-
-
-
-
-
-
添加题目
-
添加
-
-
- 编号
- 题目
- 测试数据
-
-
-
- 题目{{ $index+1 }}
- {{ el.title }}
- {{ el.testCaseList.length }}组
-
- 编辑
- 删除
-
-
-
+
+
+
+
+
允许参加的用户
+
+
+
+ 请选择
+ {{el.name}}
+
+
+
+
+ 密码保护
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 是否可见
+
+ 可见
+
+
+
+
结束前是否开放排名
+
+
+
+ 开放排名
+
+
+
+
+
是否公开提交记录
+
+
+
+ 允许查看提交记录
+
+
+
+
+ 保存修改
+
+
+
+
+
题目列表
+
添加
+
+
+ 编号
+ 题目
+ 分值
+ 可见
+ 创建时间
+
+
+
+ {{ el.sort_index }}
+ {{ el.title }}
+ {{ el.score}}
+ {{ getYesOrNo(el.visible) }}
+ {{ el.create_time|date("yyyy-MM-dd HH:mm:ss") }}
+
+ 编辑
+
+
+
-
+
-
+
diff --git a/template/admin/contest/edit_problem.html b/template/admin/contest/edit_problem.html
new file mode 100644
index 0000000..331917c
--- /dev/null
+++ b/template/admin/contest/edit_problem.html
@@ -0,0 +1,138 @@
+
+
+
diff --git a/template/admin/problem/add_problem.html b/template/admin/problem/add_problem.html
index fadea4c..38c22c6 100644
--- a/template/admin/problem/add_problem.html
+++ b/template/admin/problem/add_problem.html
@@ -134,4 +134,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/template/admin/problem/edit_problem.html b/template/admin/problem/edit_problem.html
index 3dd0870..0a2b7b5 100644
--- a/template/admin/problem/edit_problem.html
+++ b/template/admin/problem/edit_problem.html
@@ -140,4 +140,4 @@
-
+
diff --git a/template/admin/problem/submission_list.html b/template/admin/problem/submission_list.html
index 6d94dab..70aacb8 100644
--- a/template/admin/problem/submission_list.html
+++ b/template/admin/problem/submission_list.html
@@ -1,4 +1,10 @@
+
+
+
提交列表
@@ -25,4 +31,4 @@
下一页
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/template/oj/contest/contest_rank.html b/template/oj/contest/contest_rank.html
new file mode 100644
index 0000000..89d1e40
--- /dev/null
+++ b/template/oj/contest/contest_rank.html
@@ -0,0 +1,30 @@
+{% extends "oj_base.html" %}
+{% block body %}
+ {% load contest %}
+
+{% endblock %}
+
+
+{% block js_block %}
+{% endblock %}
\ No newline at end of file