mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 08:23:20 +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)
|
||||
# 0代表不是管理员 1是普通管理员 2是超级管理员
|
||||
admin_type = models.IntegerField(default=0)
|
||||
# JSON字典用来表示该用户的问题的解决状态 1为ac,2为正在进行
|
||||
problems_status = models.TextField(blank=True)
|
||||
|
||||
|
||||
USERNAME_FIELD = 'username'
|
||||
REQUIRED_FIELDS = []
|
||||
|
@ -433,7 +433,9 @@ def contest_rank_page(request, contest_id):
|
||||
except ContestSubmission.DoesNotExist:
|
||||
result[i]["problems"].append({})
|
||||
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 = sorted(result, cmp=_cmp, reverse=True)
|
||||
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,
|
||||
"result": result,
|
||||
"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})
|
||||
|
@ -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
|
||||
"""
|
||||
注意:
|
||||
此文件包含 celery 的部分配置,但是 celery 并不是运行在docker 中的,所以本配置文件中的 redis和 MySQL 的地址就应该是
|
||||
运行 redis 和 MySQL 的 docker 容器的地址了。怎么获取这个地址见帮助文档。测试用例的路径和源代码路径同理。
|
||||
"""
|
||||
# 这个redis 是 celery 使用的,包括存储队列信息还有部分统计信息
|
||||
redis_config = {
|
||||
"host": "121.42.32.129",
|
||||
"host": "192.168.42.23",
|
||||
"port": 6379,
|
||||
"db": 0
|
||||
}
|
||||
@ -9,23 +14,23 @@ redis_config = {
|
||||
|
||||
# 判题的 docker 容器的配置参数
|
||||
docker_config = {
|
||||
"image_name": "3da0e526934e",
|
||||
"image_name": "judger",
|
||||
"docker_path": "docker",
|
||||
"shell": True
|
||||
}
|
||||
|
||||
|
||||
# 测试用例的路径,是主机上的实际路径
|
||||
test_case_dir = "/var/mnt/source/test_case/"
|
||||
test_case_dir = "/root/test_case/"
|
||||
# 源代码路径,也就是 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 服务器访问的地址
|
||||
submission_db = {
|
||||
"host": "127.0.0.1",
|
||||
"host": "192.168.42.32",
|
||||
"port": 3306,
|
||||
"db": "oj_submission",
|
||||
"user": "root",
|
||||
|
@ -11,7 +11,8 @@ from settings import docker_config, source_code_dir, test_case_dir, log_dir, sub
|
||||
@app.task
|
||||
def judge(submission_id, time_limit, memory_limit, test_case_id):
|
||||
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/code/ " \
|
||||
"-v %s:/var/judger/code/log/ " \
|
||||
|
@ -2,6 +2,9 @@
|
||||
import logging
|
||||
|
||||
import redis
|
||||
import json
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
from judge.judger_controller.settings import redis_config
|
||||
from judge.judger.result import result
|
||||
@ -9,6 +12,7 @@ from submission.models import Submission
|
||||
from problem.models import Problem
|
||||
from contest.models import ContestProblem, Contest, ContestSubmission
|
||||
from account.models import User
|
||||
|
||||
logger = logging.getLogger("app_info")
|
||||
|
||||
|
||||
@ -35,6 +39,21 @@ class MessageQueue(object):
|
||||
problem.save()
|
||||
except Problem.DoesNotExist:
|
||||
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
|
||||
|
||||
@ -53,50 +72,46 @@ class MessageQueue(object):
|
||||
contest_submission = ContestSubmission.objects.get(user_id=submission.user_id, contest=contest,
|
||||
problem_id=contest_problem.id)
|
||||
# 提交次数加1
|
||||
|
||||
if submission.result == result["accepted"]:
|
||||
# 避免这道题已经 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.total_time += contest_submission.ac_time
|
||||
with transaction.atomic():
|
||||
if submission.result == result["accepted"]:
|
||||
# 避免这道题已经 ac 了,但是又重新提交了一遍
|
||||
if not contest_submission.ac:
|
||||
# 这种情况是这个题目前处于错误状态,就使用已经存储了的罚时加上这道题的实际用时
|
||||
contest_submission.ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||
contest_submission.total_time += contest_submission.ac_time
|
||||
contest_submission.total_submission_number += 1
|
||||
# 标记为已经通过
|
||||
if contest_problem.total_accepted_number == 0:
|
||||
contest_submission.first_achieved = True
|
||||
contest_submission.ac = True
|
||||
# contest problem ac 计数器加1
|
||||
contest_problem.total_accepted_number += 1
|
||||
else:
|
||||
# 如果这个提交是错误的,就罚时20分钟
|
||||
contest_submission.total_time += 1200
|
||||
contest_submission.total_submission_number += 1
|
||||
# 标记为已经通过
|
||||
if contest_problem.total_accepted_number == 0:
|
||||
contest_submission.first_achieved = True
|
||||
contest_submission.ac = True
|
||||
# contest problem ac 计数器加1
|
||||
contest_problem.total_accepted_number += 1
|
||||
else:
|
||||
# 如果这个提交是错误的,就罚时20分钟
|
||||
contest_submission.total_time += 1200
|
||||
contest_submission.total_submission_number += 1
|
||||
contest_submission.save()
|
||||
contest_problem.save()
|
||||
contest_submission.save()
|
||||
contest_problem.save()
|
||||
except ContestSubmission.DoesNotExist:
|
||||
# 第一次提交
|
||||
is_ac = submission.result == result["accepted"]
|
||||
first_achieved = False
|
||||
ac_time = 0
|
||||
if is_ac:
|
||||
ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||
total_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||
# 增加题目总的ac数计数器
|
||||
if contest_problem.total_accepted_number == 0:
|
||||
first_achieved = True
|
||||
contest_problem.total_accepted_number += 1
|
||||
contest_problem.save()
|
||||
else:
|
||||
# 没过罚时20分钟
|
||||
total_time = 1200
|
||||
ContestSubmission.objects.create(user_id=submission.user_id, contest=contest, problem=contest_problem,
|
||||
ac=is_ac, total_time=total_time, first_achieved=first_achieved,
|
||||
ac_time=ac_time)
|
||||
|
||||
with transaction.atomic():
|
||||
is_ac = submission.result == result["accepted"]
|
||||
first_achieved = False
|
||||
ac_time = 0
|
||||
if is_ac:
|
||||
ac_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||
total_time = int((submission.create_time - contest.start_time).total_seconds())
|
||||
# 增加题目总的ac数计数器
|
||||
if contest_problem.total_accepted_number == 0:
|
||||
first_achieved = True
|
||||
contest_problem.total_accepted_number += 1
|
||||
contest_problem.save()
|
||||
else:
|
||||
# 没过罚时20分钟
|
||||
total_time = 1200
|
||||
ContestSubmission.objects.create(user_id=submission.user_id, contest=contest, problem=contest_problem,
|
||||
ac=is_ac, total_time=total_time, first_achieved=first_achieved,
|
||||
ac_time=ac_time)
|
||||
|
||||
logger.debug("Start message queue")
|
||||
MessageQueue().listen_task()
|
||||
|
@ -282,11 +282,15 @@ def problem_list_page(request, page=1):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if request.user.is_authenticated() and request.user.problems_status:
|
||||
problems_status = json.loads(request.user.problems_status)
|
||||
else:
|
||||
problems_status = {}
|
||||
# 右侧标签列表 按照关联的题目的数量排序 排除题目数量为0的
|
||||
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",
|
||||
{"problems": current_page, "page": int(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})
|
||||
|
@ -1,4 +1,3 @@
|
||||
@import url("global.css");
|
||||
@import url("bootstrap/bootstrap.min.css");
|
||||
@import url("bootstrap/todc-bootstrap.min.css");
|
||||
@import url("codeMirror/codemirror.css");
|
||||
@ -6,6 +5,7 @@
|
||||
@import url("webuploader/webuploader.css");
|
||||
@import url("datetime_picker/bootstrap-datetimepicker.css");
|
||||
@import url("tagEditor/jquery.tag-editor.css");
|
||||
@import url("global.css");
|
||||
|
||||
#loading-gif {
|
||||
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%;
|
||||
}
|
||||
|
||||
body{
|
||||
height:100%; /*使内容高度和body一样*/
|
||||
margin-bottom:-80px;/*向上缩减80像素,不至于footer超出屏幕可视范围*/
|
||||
body {
|
||||
height: 100%; /*使内容高度和body一样*/
|
||||
margin-bottom: -80px; /*向上缩减80像素,不至于footer超出屏幕可视范围*/
|
||||
}
|
||||
|
||||
.main{
|
||||
.main {
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
|
||||
@ -30,10 +34,11 @@ label {
|
||||
display: none
|
||||
}
|
||||
|
||||
.right{
|
||||
.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/todc-bootstrap.min.css");
|
||||
@import url("codeMirror/codemirror.css");
|
||||
|
||||
@import url("global.css");
|
||||
|
||||
#language-selector {
|
||||
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)
|
||||
except Exception:
|
||||
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 中判题队列长度的计数器
|
||||
r = redis.Redis(host=redis_config["host"], port=redis_config["port"], db=redis_config["db"])
|
||||
r.incr("judge_queue_length")
|
||||
|
@ -54,13 +54,11 @@
|
||||
</nav>
|
||||
<!-- nav end -->
|
||||
|
||||
<!--browser happy begin -->
|
||||
<!--[if lt IE 9]>
|
||||
<div class="alert alert-danger text-center" role="alert">
|
||||
当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.
|
||||
</div>
|
||||
<![endif]-->
|
||||
<!-- browser happy end -->
|
||||
<script>
|
||||
if(navigator.userAgent.indexOf("MSIE") > -1){
|
||||
location.href = "/static/img/unsupported_browser.html";
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container main">
|
||||
<div class="row">
|
||||
|
@ -45,7 +45,12 @@
|
||||
{% for item in result %}
|
||||
<tr>
|
||||
<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>{% if item.total_time %}{{ item.total_time }}{% else %}--{% endif %}</td>
|
||||
{% for problem in item.problems %}
|
||||
|
@ -59,6 +59,12 @@
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
{% if problem.source %}
|
||||
<div class="problem-section hide">
|
||||
<label class="problem-label">来源</label>
|
||||
<div class="problem-detail">{{ problem.source }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<label>选择语言</label>
|
||||
<div>
|
||||
|
@ -28,7 +28,7 @@
|
||||
<tbody>
|
||||
{% for item in problems %}
|
||||
<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>
|
||||
<td><a href="/problem/{{ item.id }}/">{{ item.title }}</a></td>
|
||||
<td>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="zh-cn">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@ -21,13 +21,11 @@
|
||||
|
||||
<body>
|
||||
|
||||
<!--browser happy begin -->
|
||||
<!--[if lt IE 9]>
|
||||
<div class="alert alert-danger text-center" role="alert">
|
||||
当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 <a href="http://browsehappy.com/">升级你的浏览器</a>.
|
||||
</div>
|
||||
<![endif]-->
|
||||
<!-- browser happy end -->
|
||||
<script>
|
||||
if(navigator.userAgent.indexOf("MSIE") > -1){
|
||||
location.href = "/static/img/unsupported_browser.html";
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- nav begin -->
|
||||
<nav class="navbar navbar-masthead navbar-default navbar-static-top">
|
||||
|
@ -22,37 +22,29 @@
|
||||
<li>System Error: 判题系统发生故障,请等待重判</li>
|
||||
<li>Waiting: 你的提交正在等待处理</li>
|
||||
</ul>
|
||||
<h4>支持的语言</h4>
|
||||
<ul>
|
||||
<li>C (GCC 4.8)</li>
|
||||
|
||||
<li>C++ (G++ 4.3)</li>
|
||||
|
||||
<li>Java (Oracle JDK 1.7)</li>
|
||||
</ul>
|
||||
<h4>编译参数</h4>
|
||||
<ul>
|
||||
<li>C</li>
|
||||
<p>gcc -DONLINE_JUDGE -O2 -w -std=c99 {src_path} -lm -o {exe_path}main</p>
|
||||
<li>C++</li>
|
||||
<p>g++ -DONLINE_JUDGE -O2 -w -std=c++11 {src_path} -lm -o {exe_path}main</p>
|
||||
<li>Java</li>
|
||||
<p>javac {src_path} -d {exe_path}</p>
|
||||
<p>java -cp {exe_path} Main</p>
|
||||
</ul>
|
||||
<li>C(GCC 4.8)</li>
|
||||
<pre>gcc -DONLINE_JUDGE -O2 -w -std=c99 {src_path} -lm -o {exe_path}main</pre>
|
||||
<li>C++(G++ 4.3)</li>
|
||||
<pre>g++ -DONLINE_JUDGE -O2 -w -std=c++11 {src_path} -lm -o {exe_path}main</pre>
|
||||
<li>Java(Oracle JDK 1.7)</li>
|
||||
<pre>
|
||||
//编译
|
||||
javac {src_path} -d {exe_path}
|
||||
//运行
|
||||
java -cp {exe_path} Main</pre>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2 class="text-center">常见问题</h2>
|
||||
<ul>
|
||||
<li>输入输出</li>
|
||||
<p>无特殊说明,请使用标准输入输出</p>
|
||||
<li>C/C++的64位整数类型</li>
|
||||
<p>请使用long long声明,使用cin/cout或 %lld输入输出</p>
|
||||
<li>判题结果与本地执行结果不一致</li>
|
||||
<p>是否使用了不同版本的编译器(VC和TC并不完全符合C/C++标准)</p>
|
||||
<p>判题时可能使用了与您测试时不同的测试数据(不仅限于样例中展示的数据)</p>
|
||||
<li>程序执行时间和占用的内存如何计算</li>
|
||||
<p>执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</p>
|
||||
<li>无特殊说明,请使用标准输入输出。</li>
|
||||
<li>Java 代码需使用 Main 作为主类名。C/C++代码使用<code>int main()</code>,并且需要<code>return 0;</code>。</li>
|
||||
<li>C/C++ 的64位整数类型,请使用 <code>long long</code> 声明,使用 <code>cin/cout</code> 或 <code>%lld</code> 输入输出。
|
||||
使用<code>__int64</code>会导致编译错误。</li>
|
||||
<li>程序执行时间指CPU时间,占用内存按执行过程中内存消耗的峰值计,有多组测试数据时以最大的时间和内存消耗为准</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -9,6 +9,12 @@ template_release_path = "template/release/"
|
||||
|
||||
static_src_path = "static/src/"
|
||||
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:
|
||||
# 删除模板的 release 文件夹
|
||||
shutil.rmtree(template_release_path)
|
||||
@ -30,7 +36,6 @@ name_map = {}
|
||||
|
||||
def process(match):
|
||||
file_path = match.group(1).replace("/static/", "")
|
||||
# print file_path, match.group(), match.group(1)
|
||||
|
||||
if not os.path.exists(static_release_path + file_path):
|
||||
return match.group(0)
|
||||
@ -49,9 +54,11 @@ def process(match):
|
||||
return match.group(0)
|
||||
|
||||
|
||||
print "Begin to add md5 stamp in html"
|
||||
for root, dirs, files in os.walk(template_release_path):
|
||||
for name in files:
|
||||
html_path = os.path.join(root, name)
|
||||
print "Processing: " + html_path
|
||||
html_content = open(html_path, "r").read()
|
||||
js_replaced_html_content = re.sub(js_re, process, html_content)
|
||||
css_replaced_html_content = re.sub(css_re, process, js_replaced_html_content)
|
||||
@ -59,3 +66,5 @@ for root, dirs, files in os.walk(template_release_path):
|
||||
f = open(html_path, "w")
|
||||
f.write(css_replaced_html_content)
|
||||
f.close()
|
||||
|
||||
print "Done"
|
||||
|
@ -8,7 +8,16 @@ def get_problem_accepted_radio(problem):
|
||||
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
|
||||
|
||||
register = template.Library()
|
||||
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