mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 16:33:22 +00:00
Merge branch 'dev' of https://git.coding.net/virusdefender/qduoj into dev
This commit is contained in:
commit
5011861ee5
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
static/src/js/lib/* linguist-vendored
|
||||||
|
static/src/js/require.js linguist-vendored
|
||||||
|
static/src/js/r.js linguist-vendored
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Qingdao 青岛大学信息工程学院创新实验室
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
33
README.md
33
README.md
@ -0,0 +1,33 @@
|
|||||||
|
# OnlineJudge
|
||||||
|
|
||||||
|
基于 Python 和 Django的在线评测平台。
|
||||||
|
|
||||||
|
文档:https://www.zybuluo.com/virusdefender/note/171932
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
- 完善文档,目前还差很多
|
||||||
|
- 完善测试
|
||||||
|
- 搭建 demo 站点
|
||||||
|
|
||||||
|
![oj_previewindex.png][1]
|
||||||
|
|
||||||
|
![preview.jpeg][2]
|
||||||
|
|
||||||
|
![oj_preview_submission.png][3]
|
||||||
|
|
||||||
|
![contest][4]
|
||||||
|
|
||||||
|
![contest_rank_edit][5]
|
||||||
|
|
||||||
|
![admin_problem][6]
|
||||||
|
|
||||||
|
![admin_contest][7]
|
||||||
|
|
||||||
|
[1]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewindex.png
|
||||||
|
[2]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewproblem.png
|
||||||
|
[3]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewsubmission.png
|
||||||
|
[4]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewcontest.png
|
||||||
|
[5]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewcontest_rank.png?edit
|
||||||
|
[6]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewadmin_problem.png
|
||||||
|
[7]: https://dn-virusdefender-blog-cdn.qbox.me/oj_previewadmin_contest.png
|
19
account/migrations/0002_user_problems_status.py
Normal file
19
account/migrations/0002_user_problems_status.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('account', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='problems_status',
|
||||||
|
field=models.TextField(blank=True),
|
||||||
|
),
|
||||||
|
]
|
@ -30,6 +30,9 @@ class User(AbstractBaseUser):
|
|||||||
create_time = models.DateTimeField(auto_now_add=True)
|
create_time = models.DateTimeField(auto_now_add=True)
|
||||||
# 0代表不是管理员 1是普通管理员 2是超级管理员
|
# 0代表不是管理员 1是普通管理员 2是超级管理员
|
||||||
admin_type = models.IntegerField(default=0)
|
admin_type = models.IntegerField(default=0)
|
||||||
|
# JSON字典用来表示该用户的问题的解决状态 1为ac,2为正在进行
|
||||||
|
problems_status = models.TextField(blank=True)
|
||||||
|
|
||||||
|
|
||||||
USERNAME_FIELD = 'username'
|
USERNAME_FIELD = 'username'
|
||||||
REQUIRED_FIELDS = []
|
REQUIRED_FIELDS = []
|
||||||
|
@ -433,7 +433,9 @@ def contest_rank_page(request, contest_id):
|
|||||||
except ContestSubmission.DoesNotExist:
|
except ContestSubmission.DoesNotExist:
|
||||||
result[i]["problems"].append({})
|
result[i]["problems"].append({})
|
||||||
result[i]["total_ac"] = submissions.filter(ac=True).count()
|
result[i]["total_ac"] = submissions.filter(ac=True).count()
|
||||||
result[i]["username"] = User.objects.get(id=result[i]["user_id"]).username
|
user= User.objects.get(id=result[i]["user_id"])
|
||||||
|
result[i]["username"] = user.username
|
||||||
|
result[i]["real_name"] = user.real_name
|
||||||
result[i]["total_time"] = get_the_time_format(submissions.filter(ac=True).aggregate(total_time=Sum("total_time"))["total_time"])
|
result[i]["total_time"] = get_the_time_format(submissions.filter(ac=True).aggregate(total_time=Sum("total_time"))["total_time"])
|
||||||
result = sorted(result, cmp=_cmp, reverse=True)
|
result = sorted(result, cmp=_cmp, reverse=True)
|
||||||
r.set("contest_rank_" + contest_id, json.dumps(list(result)))
|
r.set("contest_rank_" + contest_id, json.dumps(list(result)))
|
||||||
@ -449,4 +451,5 @@ def contest_rank_page(request, contest_id):
|
|||||||
{"contest": contest, "contest_problems": contest_problems,
|
{"contest": contest, "contest_problems": contest_problems,
|
||||||
"result": result,
|
"result": result,
|
||||||
"auto_refresh": request.GET.get("auto_refresh", None) == "true",
|
"auto_refresh": request.GET.get("auto_refresh", None) == "true",
|
||||||
|
"show_real_name": result.GET.get("show_real_name", None) == "true",
|
||||||
"real_time_rank": contest.real_time_rank})
|
"real_time_rank": contest.real_time_rank})
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
# Create your models here.
|
|
@ -1,3 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
@ -1,23 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
from account.models import User
|
|
||||||
from group.models import Group, UserGroupRelation, JoinGroupRequest
|
|
||||||
|
|
||||||
|
|
||||||
def install(request):
|
|
||||||
for i in range(10):
|
|
||||||
user = User.objects.create(username="root" + str(i), admin_type=2, real_name="real_name", email="11111@qq.com")
|
|
||||||
user.set_password("root")
|
|
||||||
user.save()
|
|
||||||
for i in range(10):
|
|
||||||
group = Group.objects.create(name="group" + str(i),
|
|
||||||
description="description",
|
|
||||||
admin=User.objects.get(username="root0"))
|
|
||||||
for i in range(7):
|
|
||||||
UserGroupRelation.objects.create(user=User.objects.get(username="root" + str(i)), group=group)
|
|
||||||
for i in range(7, 10):
|
|
||||||
JoinGroupRequest.objects.create(user=User.objects.get(username="root" + str(i)),
|
|
||||||
group=group, message=u"你好啊")
|
|
||||||
return HttpResponse("success")
|
|
@ -1,3 +0,0 @@
|
|||||||
/usr/bin/docker run -t -i --privileged -v /var/test_case/:/var/judger/test_case/ -v /var/code/:/var/judger/code/ judger /bin/bash
|
|
||||||
|
|
||||||
python judge/judger/run.py -solution_id 1 -max_cpu_time 1 -max_memory 1 -test_case_id 1
|
|
@ -1,7 +1,12 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
"""
|
||||||
|
注意:
|
||||||
|
此文件包含 celery 的部分配置,但是 celery 并不是运行在docker 中的,所以本配置文件中的 redis和 MySQL 的地址就应该是
|
||||||
|
运行 redis 和 MySQL 的 docker 容器的地址了。怎么获取这个地址见帮助文档。测试用例的路径和源代码路径同理。
|
||||||
|
"""
|
||||||
# 这个redis 是 celery 使用的,包括存储队列信息还有部分统计信息
|
# 这个redis 是 celery 使用的,包括存储队列信息还有部分统计信息
|
||||||
redis_config = {
|
redis_config = {
|
||||||
"host": "121.42.32.129",
|
"host": "192.168.42.23",
|
||||||
"port": 6379,
|
"port": 6379,
|
||||||
"db": 0
|
"db": 0
|
||||||
}
|
}
|
||||||
@ -9,23 +14,23 @@ redis_config = {
|
|||||||
|
|
||||||
# 判题的 docker 容器的配置参数
|
# 判题的 docker 容器的配置参数
|
||||||
docker_config = {
|
docker_config = {
|
||||||
"image_name": "3da0e526934e",
|
"image_name": "judger",
|
||||||
"docker_path": "docker",
|
"docker_path": "docker",
|
||||||
"shell": True
|
"shell": True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# 测试用例的路径,是主机上的实际路径
|
# 测试用例的路径,是主机上的实际路径
|
||||||
test_case_dir = "/var/mnt/source/test_case/"
|
test_case_dir = "/root/test_case/"
|
||||||
# 源代码路径,也就是 manage.py 所在的实际路径
|
# 源代码路径,也就是 manage.py 所在的实际路径
|
||||||
source_code_dir = "/var/mnt/source/OnlineJudge/"
|
source_code_dir = "/root/qduoj/"
|
||||||
# 日志文件夹路径
|
# 日志文件夹路径
|
||||||
log_dir = "/var/log/"
|
log_dir = "/root/log/"
|
||||||
|
|
||||||
|
|
||||||
# 存储提交信息的数据库,是 celery 使用的,与 oj.settings/local_settings 等区分,那是 web 服务器访问的地址
|
# 存储提交信息的数据库,是 celery 使用的,与 oj.settings/local_settings 等区分,那是 web 服务器访问的地址
|
||||||
submission_db = {
|
submission_db = {
|
||||||
"host": "127.0.0.1",
|
"host": "192.168.42.32",
|
||||||
"port": 3306,
|
"port": 3306,
|
||||||
"db": "oj_submission",
|
"db": "oj_submission",
|
||||||
"user": "root",
|
"user": "root",
|
||||||
|
@ -11,7 +11,8 @@ from settings import docker_config, source_code_dir, test_case_dir, log_dir, sub
|
|||||||
@app.task
|
@app.task
|
||||||
def judge(submission_id, time_limit, memory_limit, test_case_id):
|
def judge(submission_id, time_limit, memory_limit, test_case_id):
|
||||||
try:
|
try:
|
||||||
command = "%s run -t -i --privileged --rm=true " \
|
command = "%s run -t -i --privileged --rm " \
|
||||||
|
"--link mysql " \
|
||||||
"-v %s:/var/judger/test_case/ " \
|
"-v %s:/var/judger/test_case/ " \
|
||||||
"-v %s:/var/judger/code/ " \
|
"-v %s:/var/judger/code/ " \
|
||||||
"-v %s:/var/judger/code/log/ " \
|
"-v %s:/var/judger/code/log/ " \
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
import redis
|
import redis
|
||||||
|
import json
|
||||||
|
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
from judge.judger_controller.settings import redis_config
|
from judge.judger_controller.settings import redis_config
|
||||||
from judge.judger.result import result
|
from judge.judger.result import result
|
||||||
@ -9,6 +12,7 @@ from submission.models import Submission
|
|||||||
from problem.models import Problem
|
from problem.models import Problem
|
||||||
from contest.models import ContestProblem, Contest, ContestSubmission
|
from contest.models import ContestProblem, Contest, ContestSubmission
|
||||||
from account.models import User
|
from account.models import User
|
||||||
|
|
||||||
logger = logging.getLogger("app_info")
|
logger = logging.getLogger("app_info")
|
||||||
|
|
||||||
|
|
||||||
@ -35,6 +39,21 @@ class MessageQueue(object):
|
|||||||
problem.save()
|
problem.save()
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
logger.warning("Submission problem does not exist, submission_id: " + submission_id)
|
logger.warning("Submission problem does not exist, submission_id: " + submission_id)
|
||||||
|
continue
|
||||||
|
# 更新该用户的解题状态
|
||||||
|
try:
|
||||||
|
user = User.objects.get(pk=submission.user_id)
|
||||||
|
except User.DoesNotExist:
|
||||||
|
logger.warning("Submission user does not exist, submission_id: " + submission_id)
|
||||||
|
continue
|
||||||
|
if user.problems_status:
|
||||||
|
problems_status = json.loads(user.problems_status)
|
||||||
|
else:
|
||||||
|
problems_status = {}
|
||||||
|
problems_status[str(problem.id)] = 1
|
||||||
|
user.problems_status = json.dumps(problems_status)
|
||||||
|
user.save()
|
||||||
|
|
||||||
# 普通题目的话,到这里就结束了
|
# 普通题目的话,到这里就结束了
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -53,15 +72,11 @@ class MessageQueue(object):
|
|||||||
contest_submission = ContestSubmission.objects.get(user_id=submission.user_id, contest=contest,
|
contest_submission = ContestSubmission.objects.get(user_id=submission.user_id, contest=contest,
|
||||||
problem_id=contest_problem.id)
|
problem_id=contest_problem.id)
|
||||||
# 提交次数加1
|
# 提交次数加1
|
||||||
|
with transaction.atomic():
|
||||||
if submission.result == result["accepted"]:
|
if submission.result == result["accepted"]:
|
||||||
# 避免这道题已经 ac 了,但是又重新提交了一遍
|
# 避免这道题已经 ac 了,但是又重新提交了一遍
|
||||||
if not contest_submission.ac:
|
if not contest_submission.ac:
|
||||||
# 这种情况是这个题目前处于错误状态,就使用已经存储了的罚时加上这道题的实际用时
|
# 这种情况是这个题目前处于错误状态,就使用已经存储了的罚时加上这道题的实际用时
|
||||||
# logger.debug(contest.start_time)
|
|
||||||
# logger.debug(submission.create_time)
|
|
||||||
# logger.debug((submission.create_time - contest.start_time).total_seconds())
|
|
||||||
# logger.debug(int((submission.create_time - contest.start_time).total_seconds() / 60))
|
|
||||||
contest_submission.ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
contest_submission.ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||||
contest_submission.total_time += contest_submission.ac_time
|
contest_submission.total_time += contest_submission.ac_time
|
||||||
contest_submission.total_submission_number += 1
|
contest_submission.total_submission_number += 1
|
||||||
@ -79,6 +94,7 @@ class MessageQueue(object):
|
|||||||
contest_problem.save()
|
contest_problem.save()
|
||||||
except ContestSubmission.DoesNotExist:
|
except ContestSubmission.DoesNotExist:
|
||||||
# 第一次提交
|
# 第一次提交
|
||||||
|
with transaction.atomic():
|
||||||
is_ac = submission.result == result["accepted"]
|
is_ac = submission.result == result["accepted"]
|
||||||
first_achieved = False
|
first_achieved = False
|
||||||
ac_time = 0
|
ac_time = 0
|
||||||
@ -97,6 +113,5 @@ class MessageQueue(object):
|
|||||||
ac=is_ac, total_time=total_time, first_achieved=first_achieved,
|
ac=is_ac, total_time=total_time, first_achieved=first_achieved,
|
||||||
ac_time=ac_time)
|
ac_time=ac_time)
|
||||||
|
|
||||||
|
|
||||||
logger.debug("Start message queue")
|
logger.debug("Start message queue")
|
||||||
MessageQueue().listen_task()
|
MessageQueue().listen_task()
|
||||||
|
@ -282,11 +282,15 @@ def problem_list_page(request, page=1):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if request.user.is_authenticated() and request.user.problems_status:
|
||||||
|
problems_status = json.loads(request.user.problems_status)
|
||||||
|
else:
|
||||||
|
problems_status = {}
|
||||||
# 右侧标签列表 按照关联的题目的数量排序 排除题目数量为0的
|
# 右侧标签列表 按照关联的题目的数量排序 排除题目数量为0的
|
||||||
tags = ProblemTag.objects.annotate(problem_number=Count("problem")).filter(problem_number__gt=0).order_by("-problem_number")
|
tags = ProblemTag.objects.annotate(problem_number=Count("problem")).filter(problem_number__gt=0).order_by("-problem_number")
|
||||||
|
|
||||||
return render(request, "oj/problem/problem_list.html",
|
return render(request, "oj/problem/problem_list.html",
|
||||||
{"problems": current_page, "page": int(page),
|
{"problems": current_page, "page": int(page),
|
||||||
"previous_page": previous_page, "next_page": next_page,
|
"previous_page": previous_page, "next_page": next_page,
|
||||||
"keyword": keyword, "tag": tag_text,
|
"keyword": keyword, "tag": tag_text,"problems_status": problems_status,
|
||||||
"tags": tags, "difficulty_order": difficulty_order})
|
"tags": tags, "difficulty_order": difficulty_order})
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
@import url("global.css");
|
|
||||||
@import url("bootstrap/bootstrap.min.css");
|
@import url("bootstrap/bootstrap.min.css");
|
||||||
@import url("bootstrap/todc-bootstrap.min.css");
|
@import url("bootstrap/todc-bootstrap.min.css");
|
||||||
@import url("codeMirror/codemirror.css");
|
@import url("codeMirror/codemirror.css");
|
||||||
@ -6,6 +5,7 @@
|
|||||||
@import url("webuploader/webuploader.css");
|
@import url("webuploader/webuploader.css");
|
||||||
@import url("datetime_picker/bootstrap-datetimepicker.css");
|
@import url("datetime_picker/bootstrap-datetimepicker.css");
|
||||||
@import url("tagEditor/jquery.tag-editor.css");
|
@import url("tagEditor/jquery.tag-editor.css");
|
||||||
|
@import url("global.css");
|
||||||
|
|
||||||
#loading-gif {
|
#loading-gif {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
html{
|
body, button, input, select, textarea, h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: Georgia, STHeiti, "Microsoft Yahei", SimSun, "Droid Sans";
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body{
|
body {
|
||||||
height:100%; /*使内容高度和body一样*/
|
height: 100%; /*使内容高度和body一样*/
|
||||||
margin-bottom:-80px;/*向上缩减80像素,不至于footer超出屏幕可视范围*/
|
margin-bottom: -80px; /*向上缩减80像素,不至于footer超出屏幕可视范围*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.main{
|
.main {
|
||||||
padding-bottom: 120px;
|
padding-bottom: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,10 +34,11 @@ label {
|
|||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
.right{
|
.right {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror pre {
|
|
||||||
font-family: "Consolas","Bitstream Vera Sans Mono","Courier New", Courier, monospace !important;
|
pre {
|
||||||
|
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
|
||||||
}
|
}
|
@ -1,8 +1,7 @@
|
|||||||
@import url("global.css");
|
|
||||||
@import url("bootstrap/bootstrap.min.css");
|
@import url("bootstrap/bootstrap.min.css");
|
||||||
@import url("bootstrap/todc-bootstrap.min.css");
|
@import url("bootstrap/todc-bootstrap.min.css");
|
||||||
@import url("codeMirror/codemirror.css");
|
@import url("codeMirror/codemirror.css");
|
||||||
|
@import url("global.css");
|
||||||
|
|
||||||
#language-selector {
|
#language-selector {
|
||||||
width: 130px;
|
width: 130px;
|
||||||
|
BIN
static/src/img/chrome.png
Normal file
BIN
static/src/img/chrome.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
static/src/img/firefox.png
Normal file
BIN
static/src/img/firefox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
static/src/img/ie.png
Normal file
BIN
static/src/img/ie.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
37
static/src/img/unsupported_browser.html
Normal file
37
static/src/img/unsupported_browser.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-cn">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>不支持的浏览器</title>
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
padding-top: 50px;;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
margin: 20px;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
很抱歉,我们无法完全兼容低版本的 IE 浏览器,您可以
|
||||||
|
<a href="http://down.tech.sina.com.cn/page/40975.html">
|
||||||
|
<div>
|
||||||
|
<img src="/static/img/chrome.png">使用Chrome
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.mozilla.org/zh-CN/firefox/new/?scene=2#download-fx">
|
||||||
|
<div>
|
||||||
|
<img src="/static/img/firefox.png">使用FireFox
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="http://windows.microsoft.com/en-us/internet-explorer/download-ie">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<img src="/static/img/ie.png">升级IE
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -46,7 +46,14 @@ class SubmissionAPIView(APIView):
|
|||||||
judge.delay(submission.id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
judge.delay(submission.id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
return error_response(u"提交判题任务失败")
|
return error_response(u"提交判题任务失败")
|
||||||
|
# 修改用户解题状态
|
||||||
|
if request.user.problems_status:
|
||||||
|
problems_status = json.loads(request.user.problems_status)
|
||||||
|
else:
|
||||||
|
problems_status = {}
|
||||||
|
problems_status[str(data["problem_id"])] = 2
|
||||||
|
request.user.problems_status = json.dumps(problems_status)
|
||||||
|
request.user.save()
|
||||||
# 增加redis 中判题队列长度的计数器
|
# 增加redis 中判题队列长度的计数器
|
||||||
r = redis.Redis(host=redis_config["host"], port=redis_config["port"], db=redis_config["db"])
|
r = redis.Redis(host=redis_config["host"], port=redis_config["port"], db=redis_config["db"])
|
||||||
r.incr("judge_queue_length")
|
r.incr("judge_queue_length")
|
||||||
|
@ -54,13 +54,11 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<!-- nav end -->
|
<!-- nav end -->
|
||||||
|
|
||||||
<!--browser happy begin -->
|
<script>
|
||||||
<!--[if lt IE 9]>
|
if(navigator.userAgent.indexOf("MSIE") > -1){
|
||||||
<div class="alert alert-danger text-center" role="alert">
|
location.href = "/static/img/unsupported_browser.html";
|
||||||
当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.
|
}
|
||||||
</div>
|
</script>
|
||||||
<![endif]-->
|
|
||||||
<!-- browser happy end -->
|
|
||||||
|
|
||||||
<div class="container main">
|
<div class="container main">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -45,7 +45,12 @@
|
|||||||
{% for item in result %}
|
{% for item in result %}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ forloop.counter }}</th>
|
<th scope="row">{{ forloop.counter }}</th>
|
||||||
<td>{{ item.username }}</td>
|
<td>
|
||||||
|
{{ item.username }}
|
||||||
|
{% if show_real_name %}
|
||||||
|
({{ item.real_name }})
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
<td>{{ item.total_ac }} / {{ item.total_submit }}</td>
|
<td>{{ item.total_ac }} / {{ item.total_submit }}</td>
|
||||||
<td>{% if item.total_time %}{{ item.total_time }}{% else %}--{% endif %}</td>
|
<td>{% if item.total_time %}{{ item.total_time }}{% else %}--{% endif %}</td>
|
||||||
{% for problem in item.problems %}
|
{% for problem in item.problems %}
|
||||||
|
@ -59,6 +59,12 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
{% if problem.source %}
|
||||||
|
<div class="problem-section hide">
|
||||||
|
<label class="problem-label">来源</label>
|
||||||
|
<div class="problem-detail">{{ problem.source }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
<label>选择语言</label>
|
<label>选择语言</label>
|
||||||
<div>
|
<div>
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for item in problems %}
|
{% for item in problems %}
|
||||||
<tr>
|
<tr>
|
||||||
<th><span class="glyphicon glyphicon-ok ac-flag"></span></th>
|
<th><span class="{% get_problem_status problems_status item.id %}"></span></th>
|
||||||
<th scope="row"><a href="/problem/{{ item.id }}/">{{ item.id }}</a></th>
|
<th scope="row"><a href="/problem/{{ item.id }}/">{{ item.id }}</a></th>
|
||||||
<td><a href="/problem/{{ item.id }}/">{{ item.title }}</a></td>
|
<td><a href="/problem/{{ item.id }}/">{{ item.title }}</a></td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="zh-cn">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
@ -21,13 +21,11 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!--browser happy begin -->
|
<script>
|
||||||
<!--[if lt IE 9]>
|
if(navigator.userAgent.indexOf("MSIE") > -1){
|
||||||
<div class="alert alert-danger text-center" role="alert">
|
location.href = "/static/img/unsupported_browser.html";
|
||||||
当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.
|
}
|
||||||
</div>
|
</script>
|
||||||
<![endif]-->
|
|
||||||
<!-- browser happy end -->
|
|
||||||
|
|
||||||
<!-- nav begin -->
|
<!-- nav begin -->
|
||||||
<nav class="navbar navbar-masthead navbar-default navbar-static-top">
|
<nav class="navbar navbar-masthead navbar-default navbar-static-top">
|
||||||
|
@ -22,37 +22,29 @@
|
|||||||
<li>System Error: 判题系统发生故障,请等待重判</li>
|
<li>System Error: 判题系统发生故障,请等待重判</li>
|
||||||
<li>Waiting: 你的提交正在等待处理</li>
|
<li>Waiting: 你的提交正在等待处理</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h4>支持的语言</h4>
|
|
||||||
<ul>
|
|
||||||
<li>C (GCC 4.8)</li>
|
|
||||||
|
|
||||||
<li>C++ (G++ 4.3)</li>
|
|
||||||
|
|
||||||
<li>Java (Oracle JDK 1.7)</li>
|
|
||||||
</ul>
|
|
||||||
<h4>编译参数</h4>
|
<h4>编译参数</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>C</li>
|
<li>C(GCC 4.8)</li>
|
||||||
<p>gcc -DONLINE_JUDGE -O2 -w -std=c99 {src_path} -lm -o {exe_path}main</p>
|
<pre>gcc -DONLINE_JUDGE -O2 -w -std=c99 {src_path} -lm -o {exe_path}main</pre>
|
||||||
<li>C++</li>
|
<li>C++(G++ 4.3)</li>
|
||||||
<p>g++ -DONLINE_JUDGE -O2 -w -std=c++11 {src_path} -lm -o {exe_path}main</p>
|
<pre>g++ -DONLINE_JUDGE -O2 -w -std=c++11 {src_path} -lm -o {exe_path}main</pre>
|
||||||
<li>Java</li>
|
<li>Java(Oracle JDK 1.7)</li>
|
||||||
<p>javac {src_path} -d {exe_path}</p>
|
<pre>
|
||||||
<p>java -cp {exe_path} Main</p>
|
//编译
|
||||||
</ul>
|
javac {src_path} -d {exe_path}
|
||||||
|
//运行
|
||||||
|
java -cp {exe_path} Main</pre>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2 class="text-center">常见问题</h2>
|
<h2 class="text-center">常见问题</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>输入输出</li>
|
<li>无特殊说明,请使用标准输入输出。</li>
|
||||||
<p>无特殊说明,请使用标准输入输出</p>
|
<li>Java 代码需使用 Main 作为主类名。C/C++代码使用<code>int main()</code>,并且需要<code>return 0;</code>。</li>
|
||||||
<li>C/C++的64位整数类型</li>
|
<li>C/C++ 的64位整数类型,请使用 <code>long long</code> 声明,使用 <code>cin/cout</code> 或 <code>%lld</code> 输入输出。
|
||||||
<p>请使用long long声明,使用cin/cout或 %lld输入输出</p>
|
使用<code>__int64</code>会导致编译错误。</li>
|
||||||
<li>判题结果与本地执行结果不一致</li>
|
<li>程序执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</li>
|
||||||
<p>是否使用了不同版本的编译器(VC和TC并不完全符合C/C++标准)</p>
|
|
||||||
<p>判题时可能使用了与您测试时不同的测试数据(不仅限于样例中展示的数据)</p>
|
|
||||||
<li>程序执行时间和占用的内存如何计算</li>
|
|
||||||
<p>执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</p>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,6 +9,12 @@ template_release_path = "template/release/"
|
|||||||
|
|
||||||
static_src_path = "static/src/"
|
static_src_path = "static/src/"
|
||||||
static_release_path = "static/release/"
|
static_release_path = "static/release/"
|
||||||
|
|
||||||
|
print "Begin to compress js"
|
||||||
|
if os.system("node static/src/js/r.js -o static/src/js/build.js"):
|
||||||
|
print "Failed to compress js, exit"
|
||||||
|
exit()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 删除模板的 release 文件夹
|
# 删除模板的 release 文件夹
|
||||||
shutil.rmtree(template_release_path)
|
shutil.rmtree(template_release_path)
|
||||||
@ -30,7 +36,6 @@ name_map = {}
|
|||||||
|
|
||||||
def process(match):
|
def process(match):
|
||||||
file_path = match.group(1).replace("/static/", "")
|
file_path = match.group(1).replace("/static/", "")
|
||||||
# print file_path, match.group(), match.group(1)
|
|
||||||
|
|
||||||
if not os.path.exists(static_release_path + file_path):
|
if not os.path.exists(static_release_path + file_path):
|
||||||
return match.group(0)
|
return match.group(0)
|
||||||
@ -49,9 +54,11 @@ def process(match):
|
|||||||
return match.group(0)
|
return match.group(0)
|
||||||
|
|
||||||
|
|
||||||
|
print "Begin to add md5 stamp in html"
|
||||||
for root, dirs, files in os.walk(template_release_path):
|
for root, dirs, files in os.walk(template_release_path):
|
||||||
for name in files:
|
for name in files:
|
||||||
html_path = os.path.join(root, name)
|
html_path = os.path.join(root, name)
|
||||||
|
print "Processing: " + html_path
|
||||||
html_content = open(html_path, "r").read()
|
html_content = open(html_path, "r").read()
|
||||||
js_replaced_html_content = re.sub(js_re, process, html_content)
|
js_replaced_html_content = re.sub(js_re, process, html_content)
|
||||||
css_replaced_html_content = re.sub(css_re, process, js_replaced_html_content)
|
css_replaced_html_content = re.sub(css_re, process, js_replaced_html_content)
|
||||||
@ -59,3 +66,5 @@ for root, dirs, files in os.walk(template_release_path):
|
|||||||
f = open(html_path, "w")
|
f = open(html_path, "w")
|
||||||
f.write(css_replaced_html_content)
|
f.write(css_replaced_html_content)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
print "Done"
|
||||||
|
@ -8,7 +8,16 @@ def get_problem_accepted_radio(problem):
|
|||||||
return "0%"
|
return "0%"
|
||||||
|
|
||||||
|
|
||||||
|
def get_problem_status(problems_status, problem_id):
|
||||||
|
|
||||||
|
if str(problem_id) in problems_status:
|
||||||
|
if problems_status[str(problem_id)] == 1:
|
||||||
|
return "glyphicon glyphicon-ok ac-flag"
|
||||||
|
return "glyphicon glyphicon-minus dealing-flag"
|
||||||
|
return ""
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
register.filter("accepted_radio", get_problem_accepted_radio)
|
register.filter("accepted_radio", get_problem_accepted_radio)
|
||||||
|
register.simple_tag(get_problem_status, name="get_problem_status")
|
||||||
|
Loading…
Reference in New Issue
Block a user