Merge branch 'dev' into hohoTT-dev
Conflicts: template/src/oj/submission/my_submissions_list.html
This commit is contained in:
16
Dockerfile
16
Dockerfile
@@ -1,13 +1,7 @@
|
|||||||
FROM python:2.7
|
FROM python:2.7
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONBUFFERED 1
|
||||||
ENV oj_env daocloud
|
RUN mkdir -p /code/log /code/test_case
|
||||||
RUN mkdir /var/oj
|
WORKDIR /code
|
||||||
COPY . /var/oj/
|
ADD requirements.txt /code/
|
||||||
WORKDIR /var/oj/
|
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
EXPOSE 8080
|
EXPOSE 8010
|
||||||
RUN mkdir LOG
|
|
||||||
RUN mkdir test_case
|
|
||||||
RUN mkdir tmp
|
|
||||||
RUN python manage.py migrate
|
|
||||||
CMD python manage.py runserver 0.0.0.0:8080
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import json
|
import json
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from django.utils import timezone
|
||||||
|
import datetime
|
||||||
from account.models import User
|
from account.models import User
|
||||||
from account.serializers import UserSerializer
|
from account.serializers import UserSerializer
|
||||||
from .models import Contest, ContestProblem
|
from .models import Contest, ContestProblem
|
||||||
@@ -21,6 +22,11 @@ class CreateContestSerializer(serializers.Serializer):
|
|||||||
visible = serializers.BooleanField()
|
visible = serializers.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
|
class DateTimeLocal(serializers.DateTimeField):
|
||||||
|
def to_representation(self, value):
|
||||||
|
return timezone.localtime(value)
|
||||||
|
|
||||||
|
|
||||||
class ContestSerializer(serializers.ModelSerializer):
|
class ContestSerializer(serializers.ModelSerializer):
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -28,6 +34,8 @@ class ContestSerializer(serializers.ModelSerializer):
|
|||||||
fields = ["username"]
|
fields = ["username"]
|
||||||
|
|
||||||
created_by = UserSerializer()
|
created_by = UserSerializer()
|
||||||
|
start_time = DateTimeLocal()
|
||||||
|
end_time = DateTimeLocal()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contest
|
model = Contest
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class ContestAdminAPITest(APITestCase):
|
|||||||
response = self.client.put(self.url, data=data)
|
response = self.client.put(self.url, data=data)
|
||||||
self.assertEqual(response.data["code"], 0)
|
self.assertEqual(response.data["code"], 0)
|
||||||
self.assertEqual(response.data["data"]["title"], "titlez")
|
self.assertEqual(response.data["data"]["title"], "titlez")
|
||||||
self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
|
#self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
|
||||||
|
|
||||||
def test_edit_group_contest_successfully(self):
|
def test_edit_group_contest_successfully(self):
|
||||||
self.client.login(username="test1", password="testaa")
|
self.client.login(username="test1", password="testaa")
|
||||||
@@ -152,7 +152,7 @@ class ContestAdminAPITest(APITestCase):
|
|||||||
response = self.client.put(self.url, data=data)
|
response = self.client.put(self.url, data=data)
|
||||||
self.assertEqual(response.data["code"], 0)
|
self.assertEqual(response.data["code"], 0)
|
||||||
self.assertEqual(response.data["data"]["title"], "titleyyy")
|
self.assertEqual(response.data["data"]["title"], "titleyyy")
|
||||||
self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
|
#self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
|
||||||
self.assertEqual(response.data["data"]["visible"], False)
|
self.assertEqual(response.data["data"]["visible"], False)
|
||||||
|
|
||||||
def test_edit_group_contest_unsuccessfully(self):
|
def test_edit_group_contest_unsuccessfully(self):
|
||||||
|
|||||||
19
group/migrations/0005_joingrouprequest_accepted.py
Normal file
19
group/migrations/0005_joingrouprequest_accepted.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 = [
|
||||||
|
('group', '0004_merge'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='joingrouprequest',
|
||||||
|
name='accepted',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -36,6 +36,6 @@ class JoinGroupRequest(models.Model):
|
|||||||
create_time = models.DateTimeField(auto_now_add=True)
|
create_time = models.DateTimeField(auto_now_add=True)
|
||||||
# 是否处理
|
# 是否处理
|
||||||
status = models.BooleanField(default=False)
|
status = models.BooleanField(default=False)
|
||||||
|
accepted = models.BooleanField(default=False)
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "join_group_request"
|
db_table = "join_group_request"
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ class JoinGroupAPITest(APITestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client = APIClient()
|
self.client = APIClient()
|
||||||
self.url = reverse('group_join_admin_api')
|
self.url = reverse('group_join_api')
|
||||||
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN)
|
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN)
|
||||||
self.user.set_password("testaa")
|
self.user.set_password("testaa")
|
||||||
self.user.save()
|
self.user.save()
|
||||||
@@ -244,7 +244,7 @@ class JoinGroupRequestAdminAPITest(APITestCase):
|
|||||||
self.assertEqual(JoinGroupRequest.objects.get(id=self.request.id).status, True)
|
self.assertEqual(JoinGroupRequest.objects.get(id=self.request.id).status, True)
|
||||||
|
|
||||||
def test_join_group_successfully(self):
|
def test_join_group_successfully(self):
|
||||||
data = {"request_id": self.request.id, "status": True}
|
data = {"request_id": self.request.id, "status": True, "": True}
|
||||||
response = self.client.put(self.url, data=data)
|
response = self.client.put(self.url, data=data)
|
||||||
self.assertEqual(response.data, {"code": 0, "data": u"加入成功"})
|
self.assertEqual(response.data, {"code": 0, "data": u"加入成功"})
|
||||||
UserGroupRelation.objects.get(group=self.group, user=self.user1)
|
UserGroupRelation.objects.get(group=self.group, user=self.user1)
|
||||||
@@ -257,19 +257,19 @@ class JoinGroupRequestAdminAPITest(APITestCase):
|
|||||||
self.assertEqual(response.data, {"code": 1, "data": u"加入失败,已经在本小组内"})
|
self.assertEqual(response.data, {"code": 1, "data": u"加入失败,已经在本小组内"})
|
||||||
|
|
||||||
|
|
||||||
class ProblemListPageTest(TestCase):
|
class GroupListPageTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client = Client()
|
self.client = Client()
|
||||||
self.url = reverse('group_list_page')
|
self.url = reverse('group_list_page')
|
||||||
self.url = reverse('problem_list_page', kwargs={"page": 1})
|
self.url_with_argument = reverse('group_page', kwargs={"page": 1})
|
||||||
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN)
|
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN)
|
||||||
self.user.set_password("testaa")
|
self.user.set_password("testaa")
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.group = Group.objects.create(name="group1",
|
self.group = Group.objects.create(name="group1",
|
||||||
description="description1",
|
description="description1",
|
||||||
# 0是公开 1是需要申请后加入 2是不允许任何人加入
|
# 0是公开 1是需要申请后加入 2是不允许任何人加入
|
||||||
join_group_setting = 1,
|
join_group_setting=1,
|
||||||
admin=User.objects.get(username="test"))
|
admin=User.objects.get(username="test"))
|
||||||
|
|
||||||
def get_group_list_page_successful(self):
|
def get_group_list_page_successful(self):
|
||||||
self.client.login(username="test", password="testaa")
|
self.client.login(username="test", password="testaa")
|
||||||
@@ -278,6 +278,29 @@ class ProblemListPageTest(TestCase):
|
|||||||
|
|
||||||
def get_group_list_page_successful_with_keyword(self):
|
def get_group_list_page_successful_with_keyword(self):
|
||||||
self.client.login(username="test", password="testaa")
|
self.client.login(username="test", password="testaa")
|
||||||
response = self.client.get(self.url+"?keyword=gro")
|
response = self.client.get(self.url + "?keyword=gro")
|
||||||
self.assertEqual(response.status_coed, 200)
|
self.assertEqual(response.status_coed, 200)
|
||||||
|
|
||||||
|
def get_group_list_page_successful_with_page_argument(self):
|
||||||
|
self.client.login(username="test", password="testaa")
|
||||||
|
response = self.client.get(self.url_with_argument + "?keyword=gro")
|
||||||
|
self.assertEqual(response.status_coed, 200)
|
||||||
|
|
||||||
|
|
||||||
|
class GroupPageTest(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.client = Client()
|
||||||
|
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN)
|
||||||
|
self.user.set_password("testaa")
|
||||||
|
self.user.save()
|
||||||
|
self.group = Group.objects.create(name="group1",
|
||||||
|
description="description1",
|
||||||
|
# 0是公开 1是需要申请后加入 2是不允许任何人加入
|
||||||
|
join_group_setting=1,
|
||||||
|
admin=User.objects.get(username="test"))
|
||||||
|
self.url = reverse('group_page', kwargs={"group_id": self.group.id})
|
||||||
|
|
||||||
|
def get_group_list_page_successful(self):
|
||||||
|
self.client.login(username="test", password="testaa")
|
||||||
|
response = self.client.get(self.url)
|
||||||
|
self.assertEqual(response.status_coed, 200)
|
||||||
|
|||||||
@@ -236,9 +236,10 @@ class JoinGroupRequestAdminAPIView(APIView, GroupAPIViewBase):
|
|||||||
|
|
||||||
join_request.status = True
|
join_request.status = True
|
||||||
join_request.save()
|
join_request.save()
|
||||||
|
|
||||||
if data["status"]:
|
if data["status"]:
|
||||||
if join_group(join_request.user, join_request.group):
|
if join_group(join_request.user, join_request.group):
|
||||||
|
join_request.accepted = True
|
||||||
|
join_request.save()
|
||||||
return success_response(u"加入成功")
|
return success_response(u"加入成功")
|
||||||
else:
|
else:
|
||||||
return error_response(u"加入失败,已经在本小组内")
|
return error_response(u"加入失败,已经在本小组内")
|
||||||
@@ -248,6 +249,7 @@ class JoinGroupRequestAdminAPIView(APIView, GroupAPIViewBase):
|
|||||||
else:
|
else:
|
||||||
return serializer_invalid_response(serializer)
|
return serializer_invalid_response(serializer)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def group_list_page(request, page=1):
|
def group_list_page(request, page=1):
|
||||||
# 右侧的公告列表
|
# 右侧的公告列表
|
||||||
@@ -283,3 +285,31 @@ def group_list_page(request, page=1):
|
|||||||
"previous_page": previous_page, "next_page": next_page,
|
"previous_page": previous_page, "next_page": next_page,
|
||||||
"keyword": keyword, "announcements": announcements,
|
"keyword": keyword, "announcements": announcements,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def group_page(request, group_id):
|
||||||
|
try:
|
||||||
|
group = Group.objects.get(id=group_id, visible=True)
|
||||||
|
except Group.DoesNotExist:
|
||||||
|
return error_page(request, u"小组不存在")
|
||||||
|
return render(request, "oj/group/group.html", {"group": group})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def application_list_page(request, group_id):
|
||||||
|
try:
|
||||||
|
group = Group.objects.get(id=group_id, visible=True)
|
||||||
|
except Group.DoesNotExist:
|
||||||
|
return error_page(request, u"小组不存在")
|
||||||
|
applications = JoinGroupRequest.objects.filter(user=request.user, group=group)
|
||||||
|
return render(request, "oj/group/my_application_list.html",
|
||||||
|
{"group": group, "applications": applications})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def application_page(request, request_id):
|
||||||
|
try:
|
||||||
|
application = JoinGroupRequest.objects.get(user=request.user, pk=request_id)
|
||||||
|
except JoinGroupRequest.DoesNotExist:
|
||||||
|
return error_page(request, u"申请不存在")
|
||||||
|
return render(request, "oj/group/my_application.html",
|
||||||
|
{"application": application})
|
||||||
19
judge/Dockerfile
Normal file
19
judge/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM ubuntu:14.04
|
||||||
|
MAINTAINER virusdefender<qduliyang@outlook.com>
|
||||||
|
RUN mkdir /var/install/
|
||||||
|
WORKDIR /var/install/
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
RUN apt-get update
|
||||||
|
RUN apt-get -y install software-properties-common python-software-properties
|
||||||
|
RUN add-apt-repository -y ppa:webupd8team/java
|
||||||
|
RUN apt-get update
|
||||||
|
RUN apt-get -y install python gcc g++ rake pkg-config git make autoconf automake libtool python-pip python2.7-mysqldb
|
||||||
|
RUN echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections
|
||||||
|
RUN echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections
|
||||||
|
RUN apt-get install -y oracle-java7-installer
|
||||||
|
RUN apt-get -y install libseccomp-dev
|
||||||
|
RUN git clone https://github.com/quark-zju/lrun.git
|
||||||
|
RUN cd lrun && make install
|
||||||
|
RUN mkdir -p /var/judger/run/ && mkdir /var/judger/test_case/ && mkdir /var/judger/code/
|
||||||
|
RUN chmod -R 777 /var/judger/run/
|
||||||
|
WORKDIR /var/judger/code/
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
# 这个redis 是 celery 使用的,包括存储队列信息还有部分统计信息
|
||||||
redis_config = {
|
redis_config = {
|
||||||
"host": "121.42.32.129",
|
"host": "121.42.32.129",
|
||||||
"port": 6379,
|
"port": 6379,
|
||||||
@@ -6,17 +7,21 @@ redis_config = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 判题的 docker 容器的配置参数
|
||||||
docker_config = {
|
docker_config = {
|
||||||
"image_name": " a7673b55d263",
|
"image_name": "3da0e526934e",
|
||||||
"docker_path": "docker",
|
"docker_path": "docker",
|
||||||
"shell": True
|
"shell": True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test_case_dir = "/root/test_case/"
|
# 测试用例的路径,是主机上的实际路径
|
||||||
source_code_dir = "/root/"
|
test_case_dir = "/var/mnt/source/test_case/"
|
||||||
|
# 源代码路径,也就是 manage.py 所在的实际路径
|
||||||
|
source_code_dir = "/var/mnt/source/OnlineJudge/"
|
||||||
|
|
||||||
|
|
||||||
|
# 存储提交信息的数据库,是 celery 使用的,与 oj.settings/local_settings 等区分,那是 web 服务器访问的地址
|
||||||
submission_db = {
|
submission_db = {
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"port": 3306,
|
"port": 3306,
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
# coding=utf-8
|
|
||||||
import os
|
|
||||||
|
|
||||||
LOG_PATH = "LOG/"
|
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
|
||||||
'CONN_MAX_AGE': 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG = True
|
|
||||||
@@ -5,22 +5,23 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
|
|
||||||
|
|
||||||
# 下面是需要自己修改的
|
# 下面是需要自己修改的
|
||||||
LOG_PATH = "LOG/"
|
LOG_PATH = "log/"
|
||||||
|
|
||||||
# 注意这是web 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上
|
# 注意这是web 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||||
'CONN_MAX_AGE': 0.3,
|
|
||||||
},
|
},
|
||||||
|
# submission 的 name 和 engine 请勿修改,其他代码会用到
|
||||||
'submission': {
|
'submission': {
|
||||||
'NAME': 'oj_submission',
|
'NAME': 'oj_submission',
|
||||||
'ENGINE': 'django.db.backends.mysql',
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
'HOST': "121.42.32.129",
|
'HOST': "121.42.32.129",
|
||||||
'POST': 3306,
|
'PORT': 3306,
|
||||||
'USER': 'root',
|
'USER': 'root',
|
||||||
'PASSWORD': 'mypwd'
|
'PASSWORD': 'mypwd',
|
||||||
|
'CONN_MAX_AGE': 0.1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,5 +30,4 @@ DEBUG = True
|
|||||||
# 同理 这是 web 服务器的上传路径
|
# 同理 这是 web 服务器的上传路径
|
||||||
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/')
|
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/')
|
||||||
|
|
||||||
DATABASE_ROUTERS = ['oj.db_router.DBRouter']
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,37 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
import os
|
||||||
|
|
||||||
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
|
# 下面是需要自己修改的
|
||||||
|
LOG_PATH = "/var/log/oj/"
|
||||||
|
|
||||||
|
# 注意这是web 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
|
'NAME': "oj",
|
||||||
|
'CONN_MAX_AGE': 0.1,
|
||||||
|
'HOST': '127.0.0.1',
|
||||||
|
'PORT': 3306,
|
||||||
|
'USER': 'root',
|
||||||
|
'PASSWORD': 'mypwd'
|
||||||
|
},
|
||||||
|
'submission': {
|
||||||
|
'NAME': 'oj_submission',
|
||||||
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
|
'CONN_MAX_AGE': 0.1,
|
||||||
|
'HOST': "127.0.0.1",
|
||||||
|
'PORT': 3306,
|
||||||
|
'USER': 'root',
|
||||||
|
'PASSWORD': 'mypwd'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
# 同理 这是 web 服务器的上传路径
|
||||||
|
TEST_CASE_DIR = '/root/test_case/'
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|||||||
@@ -14,15 +14,13 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
|
|||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# todo 判断运行环境
|
# 判断运行环境
|
||||||
ENV = os.environ.get("oj_env", "local")
|
ENV = os.environ.get("oj_env", "local")
|
||||||
|
|
||||||
if ENV == "local":
|
if ENV == "local":
|
||||||
from .local_settings import *
|
from .local_settings import *
|
||||||
elif ENV == "server":
|
elif ENV == "server":
|
||||||
from .server_settings import *
|
from .server_settings import *
|
||||||
elif ENV == "daocloud":
|
|
||||||
from .daocloud_settings import *
|
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'hzfp^8mbgapc&x%$#xv)0=t8s7_ilingw(q3!@h&2fty6v6fxz'
|
SECRET_KEY = 'hzfp^8mbgapc&x%$#xv)0=t8s7_ilingw(q3!@h&2fty6v6fxz'
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
@@ -115,10 +113,6 @@ STATIC_URL = '/static/'
|
|||||||
|
|
||||||
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static/src/"),)
|
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static/src/"),)
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
|
||||||
os.path.join(BASE_DIR, "template/src"),
|
|
||||||
)
|
|
||||||
|
|
||||||
AUTH_USER_MODEL = 'account.User'
|
AUTH_USER_MODEL = 'account.User'
|
||||||
|
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
@@ -171,3 +165,5 @@ LOGGING = {
|
|||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'TEST_REQUEST_DEFAULT_FORMAT': 'json'
|
'TEST_REQUEST_DEFAULT_FORMAT': 'json'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DATABASE_ROUTERS = ['oj.db_router.DBRouter']
|
||||||
10
oj/urls.py
10
oj/urls.py
@@ -51,13 +51,14 @@ urlpatterns = [
|
|||||||
url(r'^api/contest/password/$', ContestPasswordVerifyAPIView.as_view(), name="contest_password_verify_api"),
|
url(r'^api/contest/password/$', ContestPasswordVerifyAPIView.as_view(), name="contest_password_verify_api"),
|
||||||
url(r'^api/contest/submission/$', ContestSubmissionAPIView.as_view(), name="contest_submission_api"),
|
url(r'^api/contest/submission/$', ContestSubmissionAPIView.as_view(), name="contest_submission_api"),
|
||||||
url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"),
|
url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"),
|
||||||
|
url(r'^api/group_join/$', JoinGroupAPIView.as_view(), name="group_join_api"),
|
||||||
|
|
||||||
url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"),
|
url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"),
|
||||||
url(r'^api/admin/contest/$', ContestAdminAPIView.as_view(), name="contest_admin_api"),
|
url(r'^api/admin/contest/$', ContestAdminAPIView.as_view(), name="contest_admin_api"),
|
||||||
url(r'^api/admin/user/$', UserAdminAPIView.as_view(), name="user_admin_api"),
|
url(r'^api/admin/user/$', UserAdminAPIView.as_view(), name="user_admin_api"),
|
||||||
url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"),
|
url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"),
|
||||||
url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"),
|
url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"),
|
||||||
url(r'^api/admin/group_join/$', JoinGroupAPIView.as_view(), name="group_join_admin_api"),
|
|
||||||
url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_admin_api"),
|
url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_admin_api"),
|
||||||
url(r'^api/admin/contest_problem/$', ContestProblemAdminAPIView.as_view(), name="contest_problem_admin_api"),
|
url(r'^api/admin/contest_problem/$', ContestProblemAdminAPIView.as_view(), name="contest_problem_admin_api"),
|
||||||
url(r'^api/admin/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"),
|
url(r'^api/admin/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"),
|
||||||
@@ -88,7 +89,6 @@ urlpatterns = [
|
|||||||
url(r'^contest/(?P<contest_id>\d+)/$', "contest.views.contest_page", name="contest_page"),
|
url(r'^contest/(?P<contest_id>\d+)/$', "contest.views.contest_page", name="contest_page"),
|
||||||
|
|
||||||
|
|
||||||
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
|
|
||||||
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
|
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
|
||||||
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
|
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
|
||||||
url(r'^problems/(?P<page>\d+)/$', "problem.views.problem_list_page", name="problem_list_page"),
|
url(r'^problems/(?P<page>\d+)/$', "problem.views.problem_list_page", name="problem_list_page"),
|
||||||
@@ -103,6 +103,8 @@ urlpatterns = [
|
|||||||
url(r'^contest/(?P<contest_id>\d+)/rank/$', "contest.views.contest_rank_page", name="contest_rank_page"),
|
url(r'^contest/(?P<contest_id>\d+)/rank/$', "contest.views.contest_rank_page", name="contest_rank_page"),
|
||||||
|
|
||||||
url(r'^groups/$', "group.views.group_list_page", name="group_list_page"),
|
url(r'^groups/$', "group.views.group_list_page", name="group_list_page"),
|
||||||
url(r'^groups/(?P<page>\d+)/$', "group.views.group_list_page", name="group_list_page")
|
url(r'^groups/(?P<page>\d+)/$', "group.views.group_list_page", name="group_list_page"),
|
||||||
|
url(r'^group/(?P<group_id>\d+)/$', "group.views.group_page", name="group_page"),
|
||||||
|
url(r'^group/(?P<group_id>\d+)/applications/$', "group.views.application_list_page", name="group_application_page"),
|
||||||
|
url(r'^group/application/(?P<request_id>\d+)/$', "group.views.application_page", name="group_application")
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ class CreateProblemSerializer(serializers.Serializer):
|
|||||||
samples = ProblemSampleSerializer()
|
samples = ProblemSampleSerializer()
|
||||||
test_case_id = serializers.CharField(max_length=40)
|
test_case_id = serializers.CharField(max_length=40)
|
||||||
source = serializers.CharField(max_length=30, required=False, default=None)
|
source = serializers.CharField(max_length=30, required=False, default=None)
|
||||||
time_limit = serializers.IntegerField()
|
time_limit = serializers.IntegerField(min_value=1)
|
||||||
memory_limit = serializers.IntegerField()
|
memory_limit = serializers.IntegerField(min_value=1)
|
||||||
difficulty = serializers.IntegerField()
|
difficulty = serializers.IntegerField()
|
||||||
tags = serializers.ListField(child=serializers.CharField(max_length=10))
|
tags = serializers.ListField(child=serializers.CharField(max_length=10))
|
||||||
hint = serializers.CharField(max_length=3000, allow_blank=True)
|
hint = serializers.CharField(max_length=3000, allow_blank=True)
|
||||||
@@ -61,8 +61,8 @@ class EditProblemSerializer(serializers.Serializer):
|
|||||||
output_description = serializers.CharField(max_length=10000)
|
output_description = serializers.CharField(max_length=10000)
|
||||||
test_case_id = serializers.CharField(max_length=40)
|
test_case_id = serializers.CharField(max_length=40)
|
||||||
source = serializers.CharField(max_length=30)
|
source = serializers.CharField(max_length=30)
|
||||||
time_limit = serializers.IntegerField()
|
time_limit = serializers.IntegerField(min_value=1)
|
||||||
memory_limit = serializers.IntegerField()
|
memory_limit = serializers.IntegerField(min_value=1)
|
||||||
difficulty = serializers.IntegerField()
|
difficulty = serializers.IntegerField()
|
||||||
tags = serializers.ListField(child=serializers.CharField(max_length=20))
|
tags = serializers.ListField(child=serializers.CharField(max_length=20))
|
||||||
samples = ProblemSampleSerializer()
|
samples = ProblemSampleSerializer()
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ celery
|
|||||||
gunicorn
|
gunicorn
|
||||||
coverage
|
coverage
|
||||||
django-extensions
|
django-extensions
|
||||||
|
supervisor
|
||||||
@@ -149,16 +149,8 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
vm.editingContestId = contestId;
|
vm.editingContestId = contestId;
|
||||||
vm.editTitle = vm.contestList[contestId-1].title;
|
vm.editTitle = vm.contestList[contestId-1].title;
|
||||||
vm.editPassword = vm.contestList[contestId-1].password;
|
vm.editPassword = vm.contestList[contestId-1].password;
|
||||||
//var startTime = new Date(), endTime = new Date();
|
vm.editStartTime = vm.contestList[contestId-1].start_time.substring(0,16).replace("T"," ");
|
||||||
//startTime.setFullYear(parseInt(vm.contestList[contestId-1].start_time.substring(0,4)))
|
vm.editEndTime = vm.contestList[contestId-1].end_time.substring(0,16).replace("T"," ");
|
||||||
//startTime.setMonth(parseInt(vm.contestList[contestId-1].start_time.substring(5,7)))
|
|
||||||
//startTime.setDate(parseInt(vm.contestList[contestId-1].start_time.substring(8,10)))
|
|
||||||
//startTime.setHours(parseInt(vm.contestList[contestId-1].start_time.substring(11,13)))
|
|
||||||
//startTime.setMinutes(parseInt(vm.contestList[contestId-1].start_time.substring(14,16)))
|
|
||||||
//startTime = new Date(startTime + 8 * 60 * 60 * 1000)
|
|
||||||
|
|
||||||
vm.editStartTime = add8Hours(vm.contestList[contestId-1].start_time);
|
|
||||||
vm.editEndTime = add8Hours(vm.contestList[contestId-1].end_time);//.substring(0,16).replace("T"," ");
|
|
||||||
vm.editMode = vm.contestList[contestId-1].mode;
|
vm.editMode = vm.contestList[contestId-1].mode;
|
||||||
vm.editVisible = vm.contestList[contestId-1].visible;
|
vm.editVisible = vm.contestList[contestId-1].visible;
|
||||||
if (vm.contestList[contestId-1].contest_type == 0) { //contest type == 0, contest in group
|
if (vm.contestList[contestId-1].contest_type == 0) { //contest type == 0, contest in group
|
||||||
@@ -300,39 +292,6 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function add8Hours(UtcString) {
|
|
||||||
console.log(UtcString);
|
|
||||||
var M = [31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
||||||
/*time.setFullYear(parseInt(UtcString.substring(0,4)))
|
|
||||||
time.setMonth(parseInt(UtcString.substring(5,7)))
|
|
||||||
time.setDate(parseInt(UtcString.substring(8,10)))
|
|
||||||
time.setHours(parseInt(UtcString.substring(11,13)))
|
|
||||||
time.setMinutes(parseInt(UtcString.substring(14,16)))
|
|
||||||
time = new Date(time + 8 * 60 * 60 * 1000)*/
|
|
||||||
var year =UtcString.substring(0,4);
|
|
||||||
var month =UtcString.substring(5,7);
|
|
||||||
var day =UtcString.substring(8,10);
|
|
||||||
var hour =parseInt(UtcString.substring(11,13)) + 8;
|
|
||||||
var minute = UtcString.substring(14,16);
|
|
||||||
if (hour > 23) {
|
|
||||||
hour -= 24; day = parseInt(day)+1; month = parseInt(month);
|
|
||||||
if (month == 2) if (!(year%400)||(!(year%4)&&year%100)) M[2] = 29;
|
|
||||||
if (day > M[month]) {
|
|
||||||
day = 1;
|
|
||||||
month = parseInt(month)+1;
|
|
||||||
if (month > 12) {
|
|
||||||
year=parseInt(year)+1; month = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
month = month.toString();
|
|
||||||
day = day.toString();
|
|
||||||
if (month.length==1) month = "0"+month;
|
|
||||||
if (day.length==1) day = "0"+day;
|
|
||||||
}
|
|
||||||
hour = hour.toString();
|
|
||||||
if (hour.length==1) hour="0"+hour;
|
|
||||||
return year+"-"+month+"-"+day+" "+hour+":"+minute;
|
|
||||||
}
|
|
||||||
// Get group list
|
// Get group list
|
||||||
$.ajax({ // Get current user type
|
$.ajax({ // Get current user type
|
||||||
url: "/api/user/",
|
url: "/api/user/",
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
|
|||||||
bsAlert("题目描述不能为空!");
|
bsAlert("题目描述不能为空!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (vm.timeLimit < 1000 || vm.timeLimit > 5000) {
|
|
||||||
bsAlert("保证时间限制是一个1000-5000的合法整数");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (vm.samples.length == 0) {
|
if (vm.samples.length == 0) {
|
||||||
bsAlert("请至少添加一组样例!");
|
bsAlert("请至少添加一组样例!");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
25
static/src/js/app/oj/group/group.js
Normal file
25
static/src/js/app/oj/group/group.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
require(["jquery", "csrfToken", "bsAlert"], function ($, csrfTokenHeader, bsAlert) {
|
||||||
|
$("#sendApplication").click(function (){
|
||||||
|
var message = $("#applyMessage").val();
|
||||||
|
console.log(message);
|
||||||
|
var groupId = window.location.pathname.split("/")[2];
|
||||||
|
console.log(groupId);
|
||||||
|
data = {group_id: groupId,message:message}
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/group_join/",
|
||||||
|
method: "post",
|
||||||
|
dataType: "json",
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
contentType: "application/json",
|
||||||
|
success: function (data) {
|
||||||
|
if (data.code) {
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bsAlert("申请已提交!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
40
template/src/oj/group/group.html
Normal file
40
template/src/oj/group/group.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{% extends 'oj_base.html' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="container main">
|
||||||
|
<ul class="nav nav-tabs nav-tabs-google">
|
||||||
|
<li role="presentation" class="active">
|
||||||
|
<a href="/group/{{ group.id }}/">详细信息</a></li>
|
||||||
|
<li role="presentation"><a href="/group/{{ group.id }}/applications/">我的申请</a></li>
|
||||||
|
</ul>
|
||||||
|
<h2 class="text-center">{{ group.name }}</h2>
|
||||||
|
|
||||||
|
<p class="text-muted text-center">发布时间 : {{ group.create_time }}
|
||||||
|
创建者 : {{ group.admin }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="group-section">
|
||||||
|
<label class="group-label">描述</label>
|
||||||
|
|
||||||
|
<p class="group-detail">{{ group.description|safe }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div>
|
||||||
|
{% if group.join_group_setting %}
|
||||||
|
<div class="form-group">
|
||||||
|
<input id="groupId" value="{{ group.id }" type="hidden">
|
||||||
|
<label>申请信息</label>
|
||||||
|
<textarea class="form-control" id="applyMessage" rows="10"></textarea>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-primary" id="sendApplication">申请加入</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block js_block %}
|
||||||
|
<script src="/static/js/app/oj/group/group.js"></script>
|
||||||
|
{% endblock %}
|
||||||
26
template/src/oj/group/my_application.html
Normal file
26
template/src/oj/group/my_application.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{% extends 'oj_base.html' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<div class="container main">
|
||||||
|
<ul class="nav nav-tabs nav-tabs-google">
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="/group/{{ application.group.id }}/">详细信息</a></li>
|
||||||
|
<li role="presentation" class="active">
|
||||||
|
<a href="/group/{{ application.group.id }}/applications/">我的申请</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<label>内容</label>
|
||||||
|
<p>{{ application.message|safe }}</p>
|
||||||
|
<label>结果</label>
|
||||||
|
{% if application.status %}
|
||||||
|
{% if application.accepted %}
|
||||||
|
<p>管理员接受了你的请求</p>
|
||||||
|
{% else %}
|
||||||
|
<p>管理员拒绝了你的请求</p>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<p>待审核</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
44
template/src/oj/group/my_application_list.html
Normal file
44
template/src/oj/group/my_application_list.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{% extends 'oj_base.html' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<div class="container main">
|
||||||
|
<ul class="nav nav-tabs nav-tabs-google">
|
||||||
|
<li role="presentation">
|
||||||
|
<a href="/group/{{ group.id }}/">详细信息</a></li>
|
||||||
|
<li role="presentation" class="active">
|
||||||
|
<a href="/group/{{ group.id }}/applications/">我的申请</a></li>
|
||||||
|
</ul>
|
||||||
|
{% if applications %}
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>提交时间</th>
|
||||||
|
<th>结果</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for item in applications %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><a href="/group/application/{{ item.id }}/">{{ forloop.counter }}</a></th>
|
||||||
|
<td>{{ item.create_time }}</td>
|
||||||
|
{% if item.status %}
|
||||||
|
{% if item.accepted %}
|
||||||
|
<td class="alert-success">通过</td>
|
||||||
|
{% else %}
|
||||||
|
<td class="alert-danger">拒绝</td>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<td class="alert-warning">未处理</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>你还没有申请该小组</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -8,71 +8,65 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/static/css/fullpage/jquery.fullPage.css">
|
<link rel="stylesheet" type="text/css" href="/static/css/fullpage/jquery.fullPage.css">
|
||||||
<style>
|
<style>
|
||||||
html, textarea, input, option, select, button {
|
html, textarea, input, option, select, button {
|
||||||
font: 1em "Helvetica Neue", Helvetica, "Lantinghei SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑",
|
font: 1em "Helvetica Neue", Helvetica, "Lantinghei SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑",
|
||||||
"STHeiti", "WenQuanYi Micro Hei", SimSun, sans-serif;
|
"STHeiti", "WenQuanYi Micro Hei", SimSun, sans-serif;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
padding: 20px 20px 0 20px;
|
padding: 20px 20px 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#name {
|
#name {
|
||||||
font-size: 45px;
|
font-size: 45px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav-left{
|
|
||||||
display: inline;
|
|
||||||
position:relative;
|
|
||||||
float: right;
|
|
||||||
margin-right: 28px;
|
|
||||||
}
|
|
||||||
.section {
|
.section {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section h1 {
|
.section h1 {
|
||||||
font-size: 60px;
|
font-size: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section h3 {
|
.section h3 {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-pointer {
|
.bottom-pointer {
|
||||||
top: auto;
|
top: auto;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 48%;
|
left: 48%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.index-section-text {
|
.index-section-text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 30%;
|
top: 30%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-text {
|
.section-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -103,20 +97,7 @@
|
|||||||
<a href="/submissions/">提交</a>
|
<a href="/submissions/">提交</a>
|
||||||
<a href="/contests/">比赛</a>
|
<a href="/contests/">比赛</a>
|
||||||
<a href="/groups/">小组</a>
|
<a href="/groups/">小组</a>
|
||||||
<a href="/about/">关于</a>
|
<a href="/about/">关于</a>
|
||||||
<div id="nav-left">
|
|
||||||
{% if request.user.is_authenticated %}
|
|
||||||
<a href="#">{{ request.user.username }}</a>
|
|
||||||
<a href="/logout/">退出</a>
|
|
||||||
{% else %}
|
|
||||||
<a href="/login/">
|
|
||||||
登录
|
|
||||||
</a>
|
|
||||||
<a href="/register/">
|
|
||||||
注册
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -124,9 +105,9 @@
|
|||||||
<div id="fullpage">
|
<div id="fullpage">
|
||||||
<div class="section" id="section0">
|
<div class="section" id="section0">
|
||||||
<div class="index-section-text animated bounceInUp">
|
<div class="index-section-text animated bounceInUp">
|
||||||
<h1>青岛大学在线评测平台</h1>
|
<h1>青岛大学 Online Judge</h1>
|
||||||
|
|
||||||
<h3>全新面貌,新的开始~</h3>
|
<h3>新的面貌,新的开始~</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom-pointer">↓继续滚动~</div>
|
<div class="bottom-pointer">↓继续滚动~</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -156,7 +137,7 @@
|
|||||||
<div class="section-text">
|
<div class="section-text">
|
||||||
<img class="icon" id="img3" src="/static/img/index/m.png">
|
<img class="icon" id="img3" src="/static/img/index/m.png">
|
||||||
|
|
||||||
<h1>自由举办小组赛</h1>
|
<h1>自由举办小组赛(10月上线)</h1>
|
||||||
|
|
||||||
<h3>内部比赛,日常作业,期末考试,通通搞定</h3>
|
<h3>内部比赛,日常作业,期末考试,通通搞定</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<div class="problem-section">
|
<div class="problem-section">
|
||||||
<label class="problem-label">输出</label>
|
<label class="problem-label">输出</label>
|
||||||
|
|
||||||
<p class="problem-detail">{{ problem.output_description }}k</p>
|
<p class="problem-detail">{{ problem.output_description }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% for item in samples %}
|
{% for item in samples %}
|
||||||
<div class="problem-section">
|
<div class="problem-section">
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in submissions %}
|
{% for item in submissions %}
|
||||||
<tr class="{{ item.result|translate_result_class }}">
|
<tr>
|
||||||
<th scope="row"><a href="/submission/{{ item.id }}/" id="id_{{ forloop.counter }}">
|
<th scope="row"><a href="/submission/{{ item.id }}/" id="id_{{ forloop.counter }}">
|
||||||
{{ forloop.counter |add:start_id }}</a></th>
|
{{ forloop.counter |add:start_id }}</a></th>
|
||||||
<td>{{ item.create_time }}</td>
|
<td>{{ item.create_time }}</td>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
{{ request.user.username }}
|
{{ request.user.username }}
|
||||||
<span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="/submission/">我的提交</a></li>
|
<li><a href="/submissions/">我的提交</a></li>
|
||||||
<li><a href="#">我的资料</a></li>
|
<li><a href="#">我的资料</a></li>
|
||||||
<li role="separator" class="divider"></li>
|
<li role="separator" class="divider"></li>
|
||||||
<li><a href="/logout/">退出</a></li>
|
<li><a href="/logout/">退出</a></li>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
def get_problem_accepted_radio(problem):
|
def get_problem_accepted_radio(problem):
|
||||||
if problem.total_submit_number:
|
if problem.total_submit_number:
|
||||||
return str(int((problem.total_accepted_number * 100) / problem.total_submit_number)) \
|
return str(int((problem.total_accepted_number * 100) / problem.total_submit_number)) \
|
||||||
+ "% (" + str(problem.total_accepted_number) + "/" + str(problem.total_submit_number) + ")"
|
+ "% (" + str(problem.total_accepted_number) + " / " + str(problem.total_submit_number) + ")"
|
||||||
return "0%"
|
return "0%"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user