From 99fbb6dfaabadd7d1d6ae8724044208c6300a58e Mon Sep 17 00:00:00 2001 From: esp Date: Mon, 10 Aug 2015 14:47:06 +0800 Subject: [PATCH 01/20] =?UTF-8?q?[=E5=89=8D=E7=AB=AF]=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E4=BA=9B=E5=AD=97=E6=AE=B5=EF=BC=8C=E9=9A=BE?= =?UTF-8?q?=E5=BA=A6=EF=BC=8C=E6=A0=87=E7=AD=BE=EF=BC=8C=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=8F=AF=E8=A7=81=20=20[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/js/app/admin/problem/add_problem.js | 23 ++++++++++- template/admin/problem/add_problem.html | 39 +++++++++++++------ 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/static/src/js/app/admin/problem/add_problem.js b/static/src/js/app/admin/problem/add_problem.js index c60fd23..015af05 100644 --- a/static/src/js/app/admin/problem/add_problem.js +++ b/static/src/js/app/admin/problem/add_problem.js @@ -1,4 +1,4 @@ -require(["jquery", "avalon", "editor", "uploader", "validation"], +require(["jquery", "avalon", "editor", "uploader", "tagEditor", "validation"], function ($, avalon, editor, uploader) { avalon.vmodels.add_problem = null; $("#add-problem-form") @@ -69,7 +69,7 @@ require(["jquery", "avalon", "editor", "uploader", "validation"], }); var problemDiscription = editor("#problemDescription"); var testCaseUploader = uploader("#testCaseFile", "/admin/api/testCase");//{ - + var hinteditor = editor("#hint"); /*auto: true, swf: '/static/js/lib/webuploader/Uploader.swf', server: 'http://webuploader.duapp.com/server/fileupload.php', @@ -80,6 +80,7 @@ require(["jquery", "avalon", "editor", "uploader", "validation"], mimeTypes: 'zip/*' }*/ // }); + $("#tags").tagEditor(); var vm = avalon.define({ $id: "add_problem", title: "", @@ -87,6 +88,19 @@ require(["jquery", "avalon", "editor", "uploader", "validation"], cpu: 0, memory: 0, samples: [], + hint: "", + visible: false, + difficulty: 0, + tags: [], + tag: "", + checkTag: function () { + alert("11"); + if (event.keyCode == 13) + { + alert("You press the enter key!"); + return false; + } + }, add_sample: function () { vm.samples.push({input: "", output: "", "visible": true}); }, @@ -104,5 +118,10 @@ require(["jquery", "avalon", "editor", "uploader", "validation"], return "展开"; } }); + function checkTags(e) + { + e.preventDefault(); + } + //$("#tag").bind("keydown", checkTags(evevt)); avalon.scan(); }); \ No newline at end of file diff --git a/template/admin/problem/add_problem.html b/template/admin/problem/add_problem.html index 1da56a9..029fae8 100644 --- a/template/admin/problem/add_problem.html +++ b/template/admin/problem/add_problem.html @@ -10,22 +10,36 @@ 请填写题目描述 -
- +
+ +
-
- -
-
-
- + +
+
+
-
-
- +
+
+
+
+
+ +
+
+
+
+ +
+
+
+ +
添加 @@ -75,4 +89,5 @@
- \ No newline at end of file + + \ No newline at end of file From fe4fc946575583821f0bdf012d799dfc14ab32e1 Mon Sep 17 00:00:00 2001 From: esp Date: Mon, 10 Aug 2015 16:44:29 +0800 Subject: [PATCH 02/20] =?UTF-8?q?[=E5=89=8D=E7=AB=AF]=20=E5=9C=A8add=5Fpro?= =?UTF-8?q?blem=E5=AE=8C=E6=88=90=E4=BA=86webuploader=E7=9A=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE,=E4=BF=AE=E6=94=B9uploader.swf=E7=9A=84=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=8C=E5=8F=88=E6=94=BE=E5=9B=9E=E5=8E=9F=E5=9C=B0?= =?UTF-8?q?=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{js/lib/webuploader => img}/Uploader.swf | Bin .../src/js/app/admin/problem/add_problem.js | 37 +++++++++--------- template/admin/problem/add_problem.html | 14 +++++-- 3 files changed, 29 insertions(+), 22 deletions(-) rename static/src/{js/lib/webuploader => img}/Uploader.swf (100%) diff --git a/static/src/js/lib/webuploader/Uploader.swf b/static/src/img/Uploader.swf similarity index 100% rename from static/src/js/lib/webuploader/Uploader.swf rename to static/src/img/Uploader.swf diff --git a/static/src/js/app/admin/problem/add_problem.js b/static/src/js/app/admin/problem/add_problem.js index 015af05..c0ac63f 100644 --- a/static/src/js/app/admin/problem/add_problem.js +++ b/static/src/js/app/admin/problem/add_problem.js @@ -1,5 +1,5 @@ -require(["jquery", "avalon", "editor", "uploader", "tagEditor", "validation"], - function ($, avalon, editor, uploader) { +require(["jquery", "avalon", "editor", "uploader", "bs_alert", "tagEditor", "validation"], + function ($, avalon, editor, uploader, bs_alert) { avalon.vmodels.add_problem = null; $("#add-problem-form") .formValidation({ @@ -68,18 +68,20 @@ require(["jquery", "avalon", "editor", "uploader", "tagEditor", "validation"], console.log(ajaxData); }); var problemDiscription = editor("#problemDescription"); - var testCaseUploader = uploader("#testCaseFile", "/admin/api/testCase");//{ + var testCaseUploader = uploader("#testCaseFile", "/api/admin/test_case_upload/",function(file, respond){ + if (respond.code) + bs_alert(respond.data); + else{ + vm.test_case_id = respond.data.test_case_id; + vm.uploadSuccess = true; + vm.testCaseList = []; + for (var i = 0; i < respond.data.file_list.input.length; i++) + { + vm.testCaseList.push({input: respond.data.file_list.input[i], output: respond.data.file_list.output[i]}); + } + } + }); var hinteditor = editor("#hint"); - /*auto: true, - swf: '/static/js/lib/webuploader/Uploader.swf', - server: 'http://webuploader.duapp.com/server/fileupload.php', - multiple:false, - accept: { - title: 'Zip', - extensions: 'zip', - mimeTypes: 'zip/*' - }*/ - // }); $("#tags").tagEditor(); var vm = avalon.define({ $id: "add_problem", @@ -93,6 +95,9 @@ require(["jquery", "avalon", "editor", "uploader", "tagEditor", "validation"], difficulty: 0, tags: [], tag: "", + test_case_id: "", + testCaseList: [], + uploadSuccess: false, checkTag: function () { alert("11"); if (event.keyCode == 13) @@ -118,10 +123,6 @@ require(["jquery", "avalon", "editor", "uploader", "tagEditor", "validation"], return "展开"; } }); - function checkTags(e) - { - e.preventDefault(); - } - //$("#tag").bind("keydown", checkTags(evevt)); + avalon.scan(); }); \ No newline at end of file diff --git a/template/admin/problem/add_problem.html b/template/admin/problem/add_problem.html index 029fae8..0c6dad0 100644 --- a/template/admin/problem/add_problem.html +++ b/template/admin/problem/add_problem.html @@ -38,9 +38,9 @@

- +
-
+

添加 @@ -74,8 +74,14 @@
-
- +

+
+ 请将所有测试用例打包在一个文件中上传,所有文件要在压缩包的根目录,且输入输出文件名要以从1开始连续数字标识要对应例如:
+ 1.in 1.out 2.in 2.out
+ + + +
编号输入文件名输出文件名
{{$index}}{{el.input}}{{el.output}}
From f37b21aafdeb60a4b33609ed8737b828a21c4c4b Mon Sep 17 00:00:00 2001 From: esp Date: Mon, 10 Aug 2015 16:58:04 +0800 Subject: [PATCH 03/20] =?UTF-8?q?[=E5=89=8D=E7=AB=AF]=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8get=20URL=20=EF=BC=8C?= =?UTF-8?q?=E5=9B=A0=E4=B8=BA=E5=90=8E=E7=AB=AF=E6=94=B9=E5=8A=A8API=20[CI?= =?UTF-8?q?=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/admin/user/user_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/src/js/app/admin/user/user_list.js b/static/src/js/app/admin/user/user_list.js index 8522a21..910c24a 100644 --- a/static/src/js/app/admin/user/user_list.js +++ b/static/src/js/app/admin/user/user_list.js @@ -63,7 +63,7 @@ require(["jquery", "avalon", "csrf", "bs_alert", "validation"], function ($, ava getPageData(1); //用户列表初始化 //Ajax get数据 function getPageData(page) { - var url = "/api/users/?paging=true&page=" + page + "&page_size=10"; + var url = "/api/admin/users/?paging=true&page=" + page + "&page_size=10"; if (vm.showAdminOnly == true) url += "&admin_type=1"; if (vm.key_word != "") From d37bbb3eabb74bbfc988495bc601caaec846c05d Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 10 Aug 2015 16:59:43 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=88=A4=E9=A2=98?= =?UTF-8?q?=E7=9A=84=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84=EF=BC=9B=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0celery=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- judge/__init__.py | 1 + judge/controller/README.md | 1 + judge/controller/__init__.py | 1 + judge/controller/celery.py | 5 +++++ judge/controller/tasks.py | 8 ++++++++ judge/judger/__init__.py | 0 judge/{ => judger}/client.py | 0 judge/{ => judger}/compiler.py | 0 judge/{ => judger}/judge_exceptions.py | 0 judge/{ => judger}/language.py | 0 judge/{ => judger}/result.py | 0 judge/{ => judger}/settings.py | 0 judge/{ => judger}/utils.py | 0 13 files changed, 16 insertions(+) create mode 100644 judge/controller/README.md create mode 100644 judge/controller/__init__.py create mode 100644 judge/controller/celery.py create mode 100644 judge/controller/tasks.py create mode 100644 judge/judger/__init__.py rename judge/{ => judger}/client.py (100%) rename judge/{ => judger}/compiler.py (100%) rename judge/{ => judger}/judge_exceptions.py (100%) rename judge/{ => judger}/language.py (100%) rename judge/{ => judger}/result.py (100%) rename judge/{ => judger}/settings.py (100%) rename judge/{ => judger}/utils.py (100%) diff --git a/judge/__init__.py b/judge/__init__.py index e69de29..9bad579 100644 --- a/judge/__init__.py +++ b/judge/__init__.py @@ -0,0 +1 @@ +# coding=utf-8 diff --git a/judge/controller/README.md b/judge/controller/README.md new file mode 100644 index 0000000..9dd5603 --- /dev/null +++ b/judge/controller/README.md @@ -0,0 +1 @@ +celery -A judge.controller worker -l DEBUG \ No newline at end of file diff --git a/judge/controller/__init__.py b/judge/controller/__init__.py new file mode 100644 index 0000000..9bad579 --- /dev/null +++ b/judge/controller/__init__.py @@ -0,0 +1 @@ +# coding=utf-8 diff --git a/judge/controller/celery.py b/judge/controller/celery.py new file mode 100644 index 0000000..8e776e2 --- /dev/null +++ b/judge/controller/celery.py @@ -0,0 +1,5 @@ +# coding=utf-8 +from __future__ import absolute_import +from celery import Celery + +app = Celery("judge", broker="redis://localhost:6379/0", include=["judge.controller.tasks"]) \ No newline at end of file diff --git a/judge/controller/tasks.py b/judge/controller/tasks.py new file mode 100644 index 0000000..f0c32bc --- /dev/null +++ b/judge/controller/tasks.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from __future__ import absolute_import +from judge.controller.celery import app + + +@app.task +def judge(source_code, language, test_case_id): + print source_code, language, test_case_id \ No newline at end of file diff --git a/judge/judger/__init__.py b/judge/judger/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/judge/client.py b/judge/judger/client.py similarity index 100% rename from judge/client.py rename to judge/judger/client.py diff --git a/judge/compiler.py b/judge/judger/compiler.py similarity index 100% rename from judge/compiler.py rename to judge/judger/compiler.py diff --git a/judge/judge_exceptions.py b/judge/judger/judge_exceptions.py similarity index 100% rename from judge/judge_exceptions.py rename to judge/judger/judge_exceptions.py diff --git a/judge/language.py b/judge/judger/language.py similarity index 100% rename from judge/language.py rename to judge/judger/language.py diff --git a/judge/result.py b/judge/judger/result.py similarity index 100% rename from judge/result.py rename to judge/judger/result.py diff --git a/judge/settings.py b/judge/judger/settings.py similarity index 100% rename from judge/settings.py rename to judge/judger/settings.py diff --git a/judge/utils.py b/judge/judger/utils.py similarity index 100% rename from judge/utils.py rename to judge/judger/utils.py From fc1638d468802930886a91b04b354e49b6549e89 Mon Sep 17 00:00:00 2001 From: esp Date: Mon, 10 Aug 2015 16:59:45 +0800 Subject: [PATCH 05/20] =?UTF-8?q?[=E5=89=8D=E7=AB=AF]=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A2=98=E7=9B=AE=E5=92=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=A1=B5=E9=9D=A2=EF=BC=8C=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=96=B0=E5=AD=97=E6=AE=B5=EF=BC=8C=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E4=B8=8A=E4=BC=A0=E5=8A=9F=E8=83=BD=EF=BC=8C=20?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=B7=B2=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/css/tagEditor/jquery.tag-editor.css | 45 ++++++++++++ static/src/img/delete.png | Bin 0 -> 250 bytes static/src/img/delete.svg | 4 + static/src/js/app/admin/contest/contest.js | 65 ++++++++++++++--- static/src/js/config.js | 1 + .../js/lib/tagEditor/jquery.tag-editor.min.js | 5 ++ template/admin/contest/add_contest.html | 69 +++++++++++++----- template/admin/problem/add_problem.html | 2 +- 8 files changed, 159 insertions(+), 32 deletions(-) create mode 100644 static/src/css/tagEditor/jquery.tag-editor.css create mode 100644 static/src/img/delete.png create mode 100644 static/src/img/delete.svg create mode 100644 static/src/js/lib/tagEditor/jquery.tag-editor.min.js diff --git a/static/src/css/tagEditor/jquery.tag-editor.css b/static/src/css/tagEditor/jquery.tag-editor.css new file mode 100644 index 0000000..a8516b5 --- /dev/null +++ b/static/src/css/tagEditor/jquery.tag-editor.css @@ -0,0 +1,45 @@ +/* surrounding tag container */ +.tag-editor { + list-style-type: none; padding: 0 5px 0 0; margin: 0; overflow: hidden; border: 1px solid #eee; cursor: text; + font: normal 14px sans-serif; color: #555; background: #fff; +} + +/* core styles usually need no change */ +.tag-editor li { display: block; float: left; overflow: hidden; margin: 3px 0; line-height: 1.5; } +.tag-editor div { float: left; padding: 0 4px; } +.tag-editor .placeholder { padding: 0 8px; color: #bbb; } +.tag-editor .tag-editor-spacer { padding: 0; width: 8px; overflow: hidden; color: transparent; background: none; } +.tag-editor input { + vertical-align: inherit; border: 0; outline: none; padding: 0; margin: 0; cursor: text; + font-family: inherit; font-weight: inherit; font-size: inherit; font-style: inherit; + box-shadow: none; background: none; +} + +/* tag style */ +.tag-editor .tag-editor-tag { + padding-left: 5px; color: #46799b; background: #e0eaf1; white-space: nowrap; + overflow: hidden; cursor: pointer; border-radius: 2px 0 0 2px; +} + +/* delete icon */ +.tag-editor .tag-editor-delete { background: #e0eaf1; cursor: pointer; padding-right: 5px; border-radius: 0 2px 2px 0; } +.tag-editor .tag-editor-delete i { + display: inline-block; width: 7px; height: 7px; vertical-align: middle; background: url(/static/img/delete.png) 0 0 no-repeat; + position: relative; top: -1px; +} +.tag-editor .tag-editor-delete:hover i { background-position: 0 -14px; } +.tag-editor .tag-editor-tag.active+.tag-editor-delete, +.tag-editor .tag-editor-tag.active+.tag-editor-delete i { background: none; cursor: text; } + +.tag-editor .tag-editor-tag.active { background: none !important; } + +/* jQuery UI autocomplete - code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css */ +.ui-autocomplete { position: absolute; top: 0; left: 0; cursor: default; font-size: 14px; } +.ui-front { z-index: 9999; } +.ui-menu { list-style: none; padding: 1px; margin: 0; display: block; outline: none; } +.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.4; min-height: 0; /* support: IE7 */ } +.ui-widget-content { border: 1px solid #bbb; background: #fff; color: #555; } +.ui-widget-content a { color: #46799b; } +.ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { background: #e0eaf1; } +.ui-helper-hidden-accessible { display: none; } diff --git a/static/src/img/delete.png b/static/src/img/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..492c9f42d472c2d1b63d6cd5b9a807159374a577 GIT binary patch literal 250 zcmVPx#v`IukR4C8gj=K%QKoCUVnx?Fa&PA9uOoB6{iE%<3eB6U0Ah$&W7Gz=}H<&Ik3)v1~^IzNeI9ZXzU%B+1A}_pp{?=WWajrNGWHaO#E+Vfc6IYJG((XKsy~{ z4*{TuFu?dSByjJcN;`bSC&7EDzJ=e;+0MCdpG{b1I9jTTg#Z8m07*qoM6N<$f|WvJ A<^TWy literal 0 HcmV?d00001 diff --git a/static/src/img/delete.svg b/static/src/img/delete.svg new file mode 100644 index 0000000..f0865cc --- /dev/null +++ b/static/src/img/delete.svg @@ -0,0 +1,4 @@ + + + diff --git a/static/src/js/app/admin/contest/contest.js b/static/src/js/app/admin/contest/contest.js index e9b44ba..3edfb6d 100644 --- a/static/src/js/app/admin/contest/contest.js +++ b/static/src/js/app/admin/contest/contest.js @@ -1,6 +1,5 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker", - "validation" - ], + "validation","tagEditor"], function ($, avalon, editor, uploader) { avalon.vmodels.add_contest = null; $("#add-contest-form") @@ -19,7 +18,7 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker", } } }, - description:{ + description: { validators: { notEmpty: { message: "请输入描述" @@ -100,13 +99,20 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker", }) .on("success.form.fv", function (e) { e.preventDefault(); - var data = {title: vm.title, description: vm.description, start_time: vm.startTime, end_time: vm.endTime, - password: vm.password, model: vm.model, open_rank: vm.openRank, problems:[]}; + var data = { + title: vm.title, description: vm.description, start_time: vm.startTime, end_time: vm.endTime, + password: vm.password, model: vm.model, open_rank: vm.openRank, problems: [] + }; for (var i = 0; i < vm.problems.length; i++) { - var problem = {title: vm.problems[i].title, description:vm.problems[i].description, - cpu:vm.problems[i].cpu, memory:vm.problems[i].memory,samples:[]}; + var problem = { + title: vm.problems[i].title, description: vm.problems[i].description, + cpu: vm.problems[i].cpu, memory: vm.problems[i].memory, samples: [] + }; for (var j = 0; j < vm.problems[i].samples.length; j++) { - problem.samples.push({input:vm.problems[i].samples[j].input, output:vm.problems[i].samples[j].output}) + problem.samples.push({ + input: vm.problems[i].samples[j].input, + output: vm.problems[i].samples[j].output + }) } data.problems.push(problem); } @@ -119,11 +125,13 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker", text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; } + + var editor1 = editor("#editor"); var vm = avalon.define({ $id: "add_contest", - title : "", + title: "", description: "", startTime: "", endTime: "", @@ -133,10 +141,43 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker", problems: [], add_problem: function () { var problem_id = make_id(); - var problem={id: problem_id, title: "", cpu: "", memory: "", description: "",samples: [], webuploader: {}, visible: true}; + var problem = { + id: problem_id, + title: "", + cpu: "", + memory: "", + description: "", + samples: [], + visible: true, + test_case_id: "", + testCaseList: [], + hint: "", + isVisible: false, + difficulty: 0, + tags: [], + tag: "" + }; vm.problems.push(problem); - uploader("#problem-" + problem_id + "-uploader",""); - editor("#problem-" + problem_id + "-description") + var id = vm.problems.length - 1; + editor("#problem-" + problem_id + "-description"); + var hinteditor = editor("#problem-" + problem_id +"-hint"); + $("#problem-" + problem_id +"-tags").tagEditor(); + uploader("#problem-" + problem_id + "-uploader", "/api/admin/test_case_upload/", function (file, respond) { + console.log(respond); + if (respond.code) + bs_alert(respond.data); + else { + vm.problems[id].test_case_id = respond.data.test_case_id; + vm.problems[id].uploadSuccess = true; + vm.problems[id].testCaseList = []; + for (var i = 0; i < respond.data.file_list.input.length; i++) { + vm.problems[id].push({ + input: respond.data.file_list.input[i], + output: respond.data.file_list.output[i] + }); + } + } + }); $("#add-contest-form").formValidation('addField', $('[name="problem_name[]"]')); $("#add-contest-form").formValidation('addField', $('[name="cpu[]"]')); $("#add-contest-form").formValidation('addField', $('[name="memory[]"]')); diff --git a/static/src/js/config.js b/static/src/js/config.js index 2f730b4..f852cc8 100644 --- a/static/src/js/config.js +++ b/static/src/js/config.js @@ -17,6 +17,7 @@ var require = { csrf: "utils/csrf", admin: "app/admin/admin", chart: "lib/chart/Chart", + tagEditor: "lib/tagEditor/jquery.tag-editor.min", //formValidation 不要在代码中单独使用,而是使用和修改utils/validation base: "lib/formValidation/base", diff --git a/static/src/js/lib/tagEditor/jquery.tag-editor.min.js b/static/src/js/lib/tagEditor/jquery.tag-editor.min.js new file mode 100644 index 0000000..911e304 --- /dev/null +++ b/static/src/js/lib/tagEditor/jquery.tag-editor.min.js @@ -0,0 +1,5 @@ +// jQuery tagEditor v1.0.3 +// https://github.com/Pixabay/jQuery-tagEditor +define("tagEditor", ["jquery"], function($){ +!function(t){t.fn.autoGrowInput=function(e){return e=t.extend({maxWidth:250,minWidth:20,comfortZone:0},e),this.filter("input:text").each(function(){var i=(e.minWidth||t(this).width()," "),a=t(this),n=e.comfortZone?e.comfortZone:parseInt(.9*parseInt(t(this).css("fontSize"))),r=t("").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:a.css("fontSize"),fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),letterSpacing:a.css("letterSpacing"),whiteSpace:"nowrap"}),o=function(){if(i!==(i=a.val())){r.html(i.replace(/&/g,"&").replace(/\s/g," ").replace(//g,">"));var t=r.width()+n;t>e.maxWidth&&(t=e.maxWidth),t
 '+r.delimiter[0]+'
').appendTo(o).find(".tag-editor-tag").html('').addClass("active").find("input").val(a).blur(),"blur"!=n?o.click():t(".placeholder",o).remove()):"removeTag"==e?(t(".tag-editor-tag",o).filter(function(){return t(this).html()==a}).closest("li").find(".tag-editor-delete").click(),"blur"!=n&&o.click()):"destroy"==e&&i.css("display",r.elDisplay).removeData("options").next(".tag-editor").remove()}),s}return window.getSelection&&t(document).off("keydown.tag-editor").on("keydown.tag-editor",r),c.each(function(){function e(){!l.placeholder||c.length||t(".deleted, .placeholder, input",s).length||s.append('
  • '+l.placeholder+"
  • ")}function a(i){var a=c.toString();c=t(".tag-editor-tag:not(.deleted)",s).map(function(e,i){var a=t.trim(t(this).hasClass("active")?t(this).find("input").val():t(i).text());return a?a:void 0}).get(),s.data("tags",c),r.val(c.join(l.delimiter[0])),i||a!=c.toString()&&l.onChange(r,s,c),e()}function n(e){var n=e.closest("li"),o=e.val().replace(/ +/," ").split(l.dregex),d=e.data("old_tag"),g=c.slice(0);for(i in o)u=t.trim(o[i]).slice(0,l.maxLength),u&&(l.forceLowercase&&(u=u.toLowerCase()),l.beforeTagSave(r,s,g,d,u),~t.inArray(u,g)&&t(".tag-editor-tag",s).each(function(){t(this).html()==u&&t(this).closest("li").remove()}),g.push(u),n.before('
  •  '+l.delimiter[0]+'
    '+u+'
  • '));e.attr("maxlength",l.maxLength).removeData("old_tag").val("").focus(),a()}var r=t(this),c=[];l.elDisplay=r.css("display"),r.css("display","none");var s=t("
      ').insertAfter(r);r.data("options",l),s.append('
    •  
    • ');var d='
    •  '+l.delimiter[0]+'
    • ';s.click(function(e){if(!window.getSelection||""==getSelection()){if(o=!0,t("input:focus",s).blur(),!o)return!1;o=!0,t(".placeholder",s).remove();var i,a,n,r=99999;return t(".tag-editor-tag",s).each(function(){var o=t(this),l=o.offset(),c=l.left,s=l.top;e.pageY>=s&&e.pageY<=s+o.height()&&(e.pageXi&&(r=i,a=o))}),"before"==n?t(d).insertBefore(a.closest("li")).find(".tag-editor-tag").click():"after"==n?t(d).insertAfter(a.closest("li")).find(".tag-editor-tag").click():t(d).appendTo(s).find(".tag-editor-tag").click(),!1}}),s.on("click",".tag-editor-delete",function(){if(t(this).prev().hasClass("active"))return t(this).closest("li").find("input").caret(-1),!1;var i=t(this).closest("li"),n=i.find(".tag-editor-tag");return l.beforeTagDelete(r,s,c,n.html())===!1?!1:(n.addClass("deleted").animate({width:0},175,function(){i.remove(),e()}),a(),!1)}),l.clickDelete&&s.on("mousedown",".tag-editor-tag",function(i){if(i.ctrlKey||i.which>1){var n=t(this).closest("li"),o=n.find(".tag-editor-tag");return l.beforeTagDelete(r,s,c,o.html())===!1?!1:(o.addClass("deleted").animate({width:0},175,function(){n.remove(),e()}),a(),!1)}}),s.on("click",".tag-editor-tag",function(e){if(l.clickDelete&&(e.ctrlKey||e.which>1))return!1;if(!t(this).hasClass("active")){var i=t(this).html(),a=Math.abs((t(this).offset().left-e.pageX)/t(this).width()),n=parseInt(i.length*a),r=t(this).html('').addClass("active").find("input");if(r.data("old_tag",i).focus().autoGrowInput().trigger("autogrow").caret(n),l.autocomplete){var o=l.autocomplete,c="select"in o?l.autocomplete.select:"";o.select=function(){c&&c(),setTimeout(function(){t(".active",s).find("input").trigger("autogrow")},20)},r.autocomplete(o)}}return!1}),s.on("blur","input",function(){var i=t(this),d=i.data("old_tag"),g=t.trim(i.val().replace(/ +/," ").replace(l.dregex,l.delimiter[0]));if(g){if(g.indexOf(l.delimiter[0])>=0)return void n(i);g!=d&&(l.forceLowercase&&(g=g.toLowerCase()),l.beforeTagSave(r,s,c,d,g),t(".tag-editor-tag:not(.active)",s).each(function(){t(this).html()==g&&t(this).closest("li").remove()}))}else{if(d&&l.beforeTagDelete(r,s,c,d)===!1)return i.val(d).trigger("autogrow").focus(),o=!1,void a();try{i.closest("li").remove()}catch(f){}d&&a()}i.parent().html(g).removeClass("active"),g!=d&&a(),e()});var g;s.on("paste","input",function(){t(this).removeAttr("maxlength"),g=t(this),setTimeout(function(){n(g)},30)});var f;s.on("keypress","input",function(e){l.delimiter.indexOf(String.fromCharCode(e.which))>=0&&(f=t(this),setTimeout(function(){n(f)},20))}),s.on("keydown","input",function(e){var i=t(this);if((37==e.which||!l.autocomplete&&38==e.which)&&!i.caret()||8==e.which&&!i.val()){var a=i.closest("li").prev("li").find(".tag-editor-tag");return a.length?a.click().find("input").caret(-1):i.val()&&t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click(),!1}if((39==e.which||!l.autocomplete&&40==e.which)&&i.caret()==i.val().length){var n=i.closest("li").next("li").find(".tag-editor-tag");return n.length?n.click().find("input").caret(0):i.val()&&s.click(),!1}if(9==e.which){if(e.shiftKey){var a=i.closest("li").prev("li").find(".tag-editor-tag");a.length?a.click().find("input").caret(0):i.val()&&t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click()}else{var n=i.closest("li").next("li").find(".tag-editor-tag");n.length?n.click().find("input").caret(0):i.val()&&s.click()}return!1}if(!(46!=e.which||t.trim(i.val())&&i.caret()!=i.val().length)){var n=i.closest("li").next("li").find(".tag-editor-tag");return n.length?n.click().find("input").caret(0):i.val()&&s.click(),!1}if(13==e.which){var n=i.closest("li").next("li").find(".tag-editor-tag");return n.length?n.click().find("input").caret(0):i.val()&&s.click(),!1}if(36!=e.which||i.caret()){if(35==e.which&&i.caret()==i.val().length)s.find(".tag-editor-tag").last().click();else if(27==e.which)return i.val(i.data("old_tag")?i.data("old_tag"):"").blur(),!1}else s.find(".tag-editor-tag").first().click()});var h=l.initialTags.length?l.initialTags:r.val().split(l.dregex);for(i in h){var u=t.trim(h[i].replace(/ +/," "));u&&(l.forceLowercase&&(u=u.toLowerCase()),c.push(u),s.append('
    •  '+l.delimiter[0]+'
      '+u+'
    • '))}a(!0),l.sortable&&t.fn.sortable&&s.sortable({distance:5,cancel:".tag-editor-spacer, input",helper:"clone",update:function(){a()}})})},t.fn.tagEditor.defaults={initialTags:[],maxLength:50,delimiter:",;",placeholder:"",forceLowercase:!0,clickDelete:!1,sortable:!0,autocomplete:null,onChange:function(){},beforeTagSave:function(){},beforeTagDelete:function(){}}}(jQuery); +}); diff --git a/template/admin/contest/add_contest.html b/template/admin/contest/add_contest.html index 6349814..4a2e37e 100644 --- a/template/admin/contest/add_contest.html +++ b/template/admin/contest/add_contest.html @@ -101,26 +101,40 @@ ms-duplex="problem.title">
      -
      - -
      -
      - -
      -
      -
      - -
      -
      -
      -
      - -
      -
      请填写题目描述 +
      + + +
      + +
      +
      + +
      +
      +
      +
      + +
      +
      +
      +
      + +
      +
      +
      +
      + +
      +
      +
      + +
      @@ -156,7 +170,8 @@
      - +
      @@ -164,7 +179,22 @@
      - +
      + 请将所有测试用例打包在一个文件中上传,所有文件要在压缩包的根目录,且输入输出文件名要以从1开始连续数字标识要对应例如:
      + 1.in 1.out 2.in 2.out +
      + + + + + + + + + + + +
      编号输入文件名输出文件名
      {{$index}}{{el.input}}{{el.output}}
      @@ -184,4 +214,5 @@
      - \ No newline at end of file + + \ No newline at end of file diff --git a/template/admin/problem/add_problem.html b/template/admin/problem/add_problem.html index 0c6dad0..6ebb49a 100644 --- a/template/admin/problem/add_problem.html +++ b/template/admin/problem/add_problem.html @@ -12,7 +12,7 @@
      - +
      From 70a77cccc87617713c5081a563c87e59cc21f16c Mon Sep 17 00:00:00 2001 From: esp Date: Mon, 10 Aug 2015 17:00:39 +0800 Subject: [PATCH 06/20] =?UTF-8?q?[=E5=89=8D=E7=AB=AF]=E4=BF=AE=E6=AD=A3csr?= =?UTF-8?q?f.js=20=20=20=20uploader.js=20=20=E7=9A=84=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/utils/csrf.js | 2 +- static/src/js/utils/uploader.js | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/static/src/js/utils/csrf.js b/static/src/js/utils/csrf.js index 6a004b4..0e21e0f 100644 --- a/static/src/js/utils/csrf.js +++ b/static/src/js/utils/csrf.js @@ -11,7 +11,7 @@ define("csrf",function(){ } function csrfHeader(){ // jquery的请求 - if(arguments.length == 1) { + if(arguments.length == 2) { arguments[0].setRequestHeader("X-CSRFToken", get_cookie("csrftoken")); } // 百度webuploader 的请求 diff --git a/static/src/js/utils/uploader.js b/static/src/js/utils/uploader.js index ec418c5..83c2b1f 100644 --- a/static/src/js/utils/uploader.js +++ b/static/src/js/utils/uploader.js @@ -1,20 +1,23 @@ -define("uploader", ["webuploader"], function(webuploader){ - function uploader(selector, server) { - return webuploader.create({ - +define("uploader", ["webuploader", "csrf"], function(webuploader,csrf){ + function uploader(selector, server, onSuccess) { + var Webuploader= webuploader.create({ + auto: true, // swf文件路径 - swf: "/js/Uploader.swf", - + swf: "/static/img/Uploader.swf", // 文件接收服务端。 server: server, - // 选择文件的按钮。可选。 // 内部根据当前运行是创建,可能是input元素,也可能是flash. pick: selector, - // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传! - resize: false + resize: false, + uploadBeforeSend : csrf }); + Webuploader.on("uploadBeforeSend",csrf); + Webuploader.on("uploadSuccess", onSuccess); + + return Webuploader; } + return uploader; }); \ No newline at end of file From a6268dcb53b62cd7af1e787356855e2f7ff20a82 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 10 Aug 2015 17:59:39 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E9=A2=98=E7=9B=AE?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=9B=B8=E5=85=B3=E7=9A=84=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/urls.py | 3 +- .../0002_remove_problemtag_description.py | 18 ++++++++++++ problem/models.py | 2 +- problem/serizalizers.py | 11 +++++++- problem/views.py | 28 ++++++++++++++++++- 5 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 problem/migrations/0002_remove_problemtag_description.py diff --git a/oj/urls.py b/oj/urls.py index 1431dc6..fbe7856 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -11,7 +11,7 @@ from group.views import GroupAdminAPIView from admin.views import AdminTemplateView from problem.views import ProblemAdminAPIView -from problem.views import TestCaseUploadAPIView +from problem.views import TestCaseUploadAPIView, ProblemTagAdminAPIView urlpatterns = [ @@ -41,4 +41,5 @@ urlpatterns = [ url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"), url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_admin_api"), url(r'^api/admin/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"), + url(r'^api/admin/tag/$', ProblemTagAdminAPIView.as_view(), name="problem_tag_admin_api"), ] diff --git a/problem/migrations/0002_remove_problemtag_description.py b/problem/migrations/0002_remove_problemtag_description.py new file mode 100644 index 0000000..2953e68 --- /dev/null +++ b/problem/migrations/0002_remove_problemtag_description.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('problem', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='problemtag', + name='description', + ), + ] diff --git a/problem/models.py b/problem/models.py index 0132072..3e236af 100644 --- a/problem/models.py +++ b/problem/models.py @@ -6,7 +6,7 @@ from account.models import User class ProblemTag(models.Model): name = models.CharField(max_length=30) - description = models.CharField(max_length=50) + # description = models.CharField(max_length=50) class Meta: db_table = "problem_tag" diff --git a/problem/serizalizers.py b/problem/serizalizers.py index 441c9c5..66f3d75 100644 --- a/problem/serizalizers.py +++ b/problem/serizalizers.py @@ -4,7 +4,7 @@ import json from rest_framework import serializers from account.models import User -from .models import Problem +from .models import Problem, ProblemTag class ProblemSampleSerializer(serializers.ListField): @@ -60,3 +60,12 @@ class EditProblemSerializer(serializers.Serializer): hint = serializers.CharField(max_length=10000) visible = serializers.BooleanField() + + +class ProblemTagSerializer(serializers.ModelSerializer): + class Meta: + model = ProblemTag + + +class CreateProblemTagSerializer(serializers.Serializer): + name = serializers.CharField(max_length=10) \ No newline at end of file diff --git a/problem/views.py b/problem/views.py index 0a5490f..eda2c72 100644 --- a/problem/views.py +++ b/problem/views.py @@ -11,10 +11,36 @@ from django.db.models import Q from rest_framework.views import APIView from utils.shortcuts import serializer_invalid_response, error_response, success_response, paginate, rand_str -from .serizalizers import CreateProblemSerializer, EditProblemSerializer, ProblemSerializer +from .serizalizers import (CreateProblemSerializer, EditProblemSerializer, ProblemSerializer, + ProblemTagSerializer, CreateProblemTagSerializer) from .models import Problem, ProblemTag +class ProblemTagAdminAPIView(APIView): + def post(self, request): + """ + 创建标签的接口 + --- + request_serializer: CreateProblemTagSerializer + """ + serializer = CreateProblemTagSerializer(data=request.data) + if serializer.is_valid(): + try: + tag = ProblemTag.objects.get(name=serializer.data["name"]) + except ProblemTag.DoesNotExist: + tag = ProblemTag.objects.create(name=serializer.data["name"]) + return success_response(ProblemTagSerializer(tag).data) + else: + return error_response(serializer) + + def get(self, request): + keyword = request.GET.get("keyword", None) + if not keyword: + return error_response(u"参数错误") + tags = ProblemTag.objects.filter(name__contains=keyword) + return success_response(ProblemTagSerializer(tags, many=True).data) + + def problem_page(request, problem_id): From 82da537a50436d51431d3dea5a8b860182253005 Mon Sep 17 00:00:00 2001 From: hohoTT <609029365@qq.com> Date: Mon, 10 Aug 2015 18:04:35 +0800 Subject: [PATCH 08/20] =?UTF-8?q?=E5=A2=9E=E6=B7=BBannouncementPage?= =?UTF-8?q?=E9=83=A8=E5=88=86=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- announcement/tests.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/announcement/tests.py b/announcement/tests.py index 435da34..708f3c6 100644 --- a/announcement/tests.py +++ b/announcement/tests.py @@ -1,5 +1,6 @@ # coding=utf-8 from django.core.urlresolvers import reverse +from django.test import TestCase from rest_framework.test import APITestCase, APIClient @@ -87,3 +88,27 @@ class AnnouncementAPITest(APITestCase): self.assertEqual(response.data["code"], 0) for item in response.data["data"]: self.assertEqual(item["visible"], True) + + +class AnnouncementPageTest(TestCase): + def setUp(self): + user = User.objects.create(username="test") + user.set_password("testaa") + user.save() + Announcement.objects.create(title="aa", + content="AA", + created_by=User.objects.get(username="test"), + visible=True) + + Announcement.objects.create(title="bb", + content="BB", + created_by=User.objects.get(username="test"), + visible=False) + + def test_success_announcement(self): + response = self.client.get('/announcement/1/') + self.assertEqual(response.status_code, 200) + + def test_announcement_does_not_exist(self): + response = self.client.get('/announcement/3/') + self.assertTemplateUsed(response, "utils/error.html") From 5254f428b4aac9f07660b78c8189f4c99121d23a Mon Sep 17 00:00:00 2001 From: esp Date: Mon, 10 Aug 2015 18:05:22 +0800 Subject: [PATCH 09/20] =?UTF-8?q?[=E5=89=8D=E7=AB=AF-=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=97=AE=E9=A2=98]=E6=B7=BB=E5=8A=A0=E6=9D=A5=E6=BA=90?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=20=20=20[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/admin/problem/add_problem.js | 1 + template/admin/problem/add_problem.html | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/static/src/js/app/admin/problem/add_problem.js b/static/src/js/app/admin/problem/add_problem.js index c0ac63f..09862d3 100644 --- a/static/src/js/app/admin/problem/add_problem.js +++ b/static/src/js/app/admin/problem/add_problem.js @@ -98,6 +98,7 @@ require(["jquery", "avalon", "editor", "uploader", "bs_alert", "tagEditor", "val test_case_id: "", testCaseList: [], uploadSuccess: false, + source: "", checkTag: function () { alert("11"); if (event.keyCode == 13) diff --git a/template/admin/problem/add_problem.html b/template/admin/problem/add_problem.html index 6ebb49a..1c78a9e 100644 --- a/template/admin/problem/add_problem.html +++ b/template/admin/problem/add_problem.html @@ -1,10 +1,14 @@
      -
      +
      +
      + + +
      From 402c7ee87fcb97c25f14355b91fedf8e3ca138e3 Mon Sep 17 00:00:00 2001 From: hohoTT <609029365@qq.com> Date: Mon, 10 Aug 2015 18:07:08 +0800 Subject: [PATCH 10/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E3=80=81=E4=BF=AE=E6=94=B9=E5=B0=8F=E7=BB=84=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=B0=8F=E7=BB=84=E5=88=97=E8=A1=A8=E6=88=96?= =?UTF-8?q?=E8=80=85=E6=98=AF=E5=8D=95=E4=B8=AA=E5=B0=8F=E7=BB=84=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group/tests.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/group/tests.py b/group/tests.py index 7ce503c..522ac42 100644 --- a/group/tests.py +++ b/group/tests.py @@ -1,3 +1,85 @@ +# coding=utf-8 from django.test import TestCase -# Create your tests here. +from django.core.urlresolvers import reverse + +from rest_framework.test import APITestCase, APIClient + +from account.models import User, SUPER_ADMIN +from group.models import Group + + +class GroupAdminAPITest(APITestCase): + # 以下是创建小组的测试 + def setUp(self): + self.client = APIClient() + self.url = reverse('group_admin_api') + user = User.objects.create(username="test", admin_type=SUPER_ADMIN) + user.set_password("testaa") + user.save() + + def test_invalid_format(self): + self.client.login(username="test", password="testaa") + data = {"name": "group1"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_success_group(self): + self.client.login(username="test", password="testaa") + data = {"name": "group1", "description": "des1", "join_group_setting": "1"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + # 以下是修改小组的测试 + def test_put_invalid_data(self): + self.client.login(username="test", password="testaa") + data = {"name": "group1"} + response = self.client.put(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_edit_group_does_not_exist(self): + self.client.login(username="test", password="testaa") + group = Group.objects.create(name="group1", description="des1", + join_group_setting="1", visible="True", + admin=User.objects.get(username="test")) + data = {"group_id": group.id + 1, "name": "group0", "description": "des0", + "join_group_setting": 2} + response = self.client.put(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"小组不存在"}) + + def test_success_edit_group(self): + self.client.login(username="test", password="testaa") + group = Group.objects.create(name="group1", description="des1", + join_group_setting="1", visible="True", + admin=User.objects.get(username="test")) + data = {"group_id": group.id, "name": "group0", "description": "des0", + "join_group_setting": 2} + response = self.client.put(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + # 以下是查询小组列表或者是单个小组时的测试 + def test_select_group_does_not_exist(self): + self.client.login(username="test", password="testaa") + group = Group.objects.create(name="group1", description="des1", + join_group_setting="1", visible="True", + admin=User.objects.get(username="test")) + data = {"group_id": group.id + 1, "name": "group0", "description": "des0", + "join_group_setting": 2} + response = self.client.get(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"小组不存在"}) + + def test_success_select_group(self): + self.client.login(username="test", password="testaa") + group = Group.objects.create(name="group1", description="des1", + join_group_setting="1", visible="True", + admin=User.objects.get(username="test")) + data = {"group_id": group.id, "name": "group0", "description": "des0", + "join_group_setting": 2} + response = self.client.get(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + def test_success_get_data(self): + self.client.login(username="test", password="testaa") + self.assertEqual(self.client.get(self.url).data["code"], 0) + + From 441b7383bcf2983a793f659863f2db82087bccd3 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 10 Aug 2015 20:18:46 +0800 Subject: [PATCH 11/20] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20js=20submit?= =?UTF-8?q?=5Fproblem=20->=20problem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/js/app/oj/problem/{submit_code.js => problem.js} | 8 +++++--- static/src/js/config.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) rename static/src/js/app/oj/problem/{submit_code.js => problem.js} (84%) diff --git a/static/src/js/app/oj/problem/submit_code.js b/static/src/js/app/oj/problem/problem.js similarity index 84% rename from static/src/js/app/oj/problem/submit_code.js rename to static/src/js/app/oj/problem/problem.js index 287554c..a713c07 100644 --- a/static/src/js/app/oj/problem/submit_code.js +++ b/static/src/js/app/oj/problem/problem.js @@ -22,10 +22,12 @@ require(["jquery", "code_mirror"], function ($, code_mirror) { setTimeout( function () { $("#a").animate({opacity: '1'}) - } - , - 3); + }, 3); + }); + $("#show-more-btn").click(function(){ + $(".hide").attr("class", "problem-section"); + $("#show-more-btn").hide(); }) }); diff --git a/static/src/js/config.js b/static/src/js/config.js index f852cc8..0ecf314 100644 --- a/static/src/js/config.js +++ b/static/src/js/config.js @@ -12,7 +12,7 @@ var require = { validation: "utils/validation", code_mirror: "utils/code_mirror", bs_alert: "utils/bs_alert", - submit_code: "app/oj/problem/submit_code", + problem: "app/oj/problem/problem", contest: "app/admin/contest/contest", csrf: "utils/csrf", admin: "app/admin/admin", From 502b4944f1083368a854732b213e82eeaa0323db Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 10 Aug 2015 20:19:22 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A2=98=E7=9B=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=92=8C=E6=88=91=E7=9A=84=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/urls.py | 2 + problem/views.py | 16 +- template/oj/problem/my_solution.html | 31 ++++ template/oj/problem/my_solutions_list.html | 53 +++++++ template/oj/problem/problem.html | 165 ++++++++++++--------- 5 files changed, 199 insertions(+), 68 deletions(-) create mode 100644 template/oj/problem/my_solution.html create mode 100644 template/oj/problem/my_solutions_list.html diff --git a/oj/urls.py b/oj/urls.py index fbe7856..27635c7 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -42,4 +42,6 @@ urlpatterns = [ url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_admin_api"), url(r'^api/admin/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"), url(r'^api/admin/tag/$', ProblemTagAdminAPIView.as_view(), name="problem_tag_admin_api"), + url(r'^problem/(?P\d+)/my_solutions/', "problem.views.problem_my_solutions_list_page", name="problem_my_solutions_page"), + url(r'^my_solution/(?P\d+)/$', "problem.views.my_solution", name="my_solution_page"), ] diff --git a/problem/views.py b/problem/views.py index eda2c72..8cdf328 100644 --- a/problem/views.py +++ b/problem/views.py @@ -44,8 +44,20 @@ class ProblemTagAdminAPIView(APIView): def problem_page(request, problem_id): - # todo - return render(request, "oj/problem/problem.html") + # try: + # problem = Problem.objects.get(id=problem_id) + # except Problem.DoesNotExist: + # return render(request, "utils/error.html", {"error": u"题目不存在"}) + return render(request, "oj/problem/problem.html", {"problem": {}}) + + +def problem_my_solutions_list_page(request, problem_id): + return render(request, "oj/problem/my_solutions_list.html") + + +def my_solution(request, solution_id): + return render(request, "oj/problem/my_solution.html") + class ProblemAdminAPIView(APIView): diff --git a/template/oj/problem/my_solution.html b/template/oj/problem/my_solution.html new file mode 100644 index 0000000..8f05b10 --- /dev/null +++ b/template/oj/problem/my_solution.html @@ -0,0 +1,31 @@ +{% extends 'oj_base.html' %} + +{% block body %} + +
      + +

      Battle Over Cities - Hard Version

      +

      cpu: 1000ms 内存: 256M

      +
      +
      +

      运行结果:Accepted

      +

      cpu: 1000ms 内存: 256M 语言:python

      +
      +
      +
      + +
      +
      + +{% endblock %} \ No newline at end of file diff --git a/template/oj/problem/my_solutions_list.html b/template/oj/problem/my_solutions_list.html new file mode 100644 index 0000000..613410a --- /dev/null +++ b/template/oj/problem/my_solutions_list.html @@ -0,0 +1,53 @@ +{% extends 'oj_base.html' %} + +{% block body %} + +
      + +

      Battle Over Cities - Hard Version

      +

      cpu: 1000ms 内存: 256M

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #提交时间结果运行时间运行内存语言
      11Error Format333
      2WrongWrong Answer@fat33
      3LarryAccepted@twitter33
      +
      +{% endblock %} \ No newline at end of file diff --git a/template/oj/problem/problem.html b/template/oj/problem/problem.html index cbdc0e5..a4dde86 100644 --- a/template/oj/problem/problem.html +++ b/template/oj/problem/problem.html @@ -1,93 +1,126 @@ {% extends 'oj_base.html' %} {% block body %} -
      - -

      Battle Over Cities - Hard Version

      +
      + +

      Battle Over Cities - Hard Version

      -

      cpu: 1000ms 内存: 256M

      +

      发布时间: 2015-07-05 CPU: 1000ms 内存: 256M

      -
      -
      - +
      +
      + -

      n的阶乘定义为n!=1*2*3*……*n 如3!=6 - n!通常最后会有很多0,如5!=120 最后有一个0,现在统计n!去除末尾的0后,最后k位是多少

      -
      -
      - +

      n的阶乘定义为n!=1*2*3*……*n 如3!=6 + n!通常最后会有很多0,如5!=120 最后有一个0,现在统计n!去除末尾的0后,最后k位是多少

      +
      +
      + -

      第一行包括两个数n,k

      -
      -
      - +

      第一行包括两个数n,k

      +
      +
      + -

      第一行包括两个数n,k

      -
      -
      - +

      第一行包括两个数n,k

      +
      +
      +
       1 2 3 4 5 6 7
       1 2 3 4 5 6 7
      -
      -
      +
      +
      - +
       1 2 3 4 5 6 7
      -
      -
      - -
      - - -
      -
      -
      - - -
      -
      -
      - - +
      + +
      +1 2 3 4 5 6 7
      +1 2 3 4 5 6 7
      -
      -
      -
      -