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
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV oj_env daocloud
|
||||
RUN mkdir /var/oj
|
||||
COPY . /var/oj/
|
||||
WORKDIR /var/oj/
|
||||
ENV PYTHONBUFFERED 1
|
||||
RUN mkdir -p /code/log /code/test_case
|
||||
WORKDIR /code
|
||||
ADD requirements.txt /code/
|
||||
RUN pip install -r requirements.txt
|
||||
EXPOSE 8080
|
||||
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
|
||||
EXPOSE 8010
|
||||
@@ -1,7 +1,8 @@
|
||||
# coding=utf-8
|
||||
import json
|
||||
from rest_framework import serializers
|
||||
|
||||
from django.utils import timezone
|
||||
import datetime
|
||||
from account.models import User
|
||||
from account.serializers import UserSerializer
|
||||
from .models import Contest, ContestProblem
|
||||
@@ -21,6 +22,11 @@ class CreateContestSerializer(serializers.Serializer):
|
||||
visible = serializers.BooleanField()
|
||||
|
||||
|
||||
class DateTimeLocal(serializers.DateTimeField):
|
||||
def to_representation(self, value):
|
||||
return timezone.localtime(value)
|
||||
|
||||
|
||||
class ContestSerializer(serializers.ModelSerializer):
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
@@ -28,6 +34,8 @@ class ContestSerializer(serializers.ModelSerializer):
|
||||
fields = ["username"]
|
||||
|
||||
created_by = UserSerializer()
|
||||
start_time = DateTimeLocal()
|
||||
end_time = DateTimeLocal()
|
||||
|
||||
class Meta:
|
||||
model = Contest
|
||||
|
||||
@@ -141,7 +141,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
response = self.client.put(self.url, data=data)
|
||||
self.assertEqual(response.data["code"], 0)
|
||||
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):
|
||||
self.client.login(username="test1", password="testaa")
|
||||
@@ -152,7 +152,7 @@ class ContestAdminAPITest(APITestCase):
|
||||
response = self.client.put(self.url, data=data)
|
||||
self.assertEqual(response.data["code"], 0)
|
||||
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)
|
||||
|
||||
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)
|
||||
# 是否处理
|
||||
status = models.BooleanField(default=False)
|
||||
|
||||
accepted = models.BooleanField(default=False)
|
||||
class Meta:
|
||||
db_table = "join_group_request"
|
||||
|
||||
@@ -150,7 +150,7 @@ class JoinGroupAPITest(APITestCase):
|
||||
|
||||
def setUp(self):
|
||||
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.set_password("testaa")
|
||||
self.user.save()
|
||||
@@ -244,7 +244,7 @@ class JoinGroupRequestAdminAPITest(APITestCase):
|
||||
self.assertEqual(JoinGroupRequest.objects.get(id=self.request.id).status, True)
|
||||
|
||||
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)
|
||||
self.assertEqual(response.data, {"code": 0, "data": u"加入成功"})
|
||||
UserGroupRelation.objects.get(group=self.group, user=self.user1)
|
||||
@@ -257,18 +257,18 @@ class JoinGroupRequestAdminAPITest(APITestCase):
|
||||
self.assertEqual(response.data, {"code": 1, "data": u"加入失败,已经在本小组内"})
|
||||
|
||||
|
||||
class ProblemListPageTest(TestCase):
|
||||
class GroupListPageTest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
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.set_password("testaa")
|
||||
self.user.save()
|
||||
self.group = Group.objects.create(name="group1",
|
||||
description="description1",
|
||||
# 0是公开 1是需要申请后加入 2是不允许任何人加入
|
||||
join_group_setting = 1,
|
||||
join_group_setting=1,
|
||||
admin=User.objects.get(username="test"))
|
||||
|
||||
def get_group_list_page_successful(self):
|
||||
@@ -278,6 +278,29 @@ class ProblemListPageTest(TestCase):
|
||||
|
||||
def get_group_list_page_successful_with_keyword(self):
|
||||
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)
|
||||
|
||||
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.save()
|
||||
|
||||
if data["status"]:
|
||||
if join_group(join_request.user, join_request.group):
|
||||
join_request.accepted = True
|
||||
join_request.save()
|
||||
return success_response(u"加入成功")
|
||||
else:
|
||||
return error_response(u"加入失败,已经在本小组内")
|
||||
@@ -248,6 +249,7 @@ class JoinGroupRequestAdminAPIView(APIView, GroupAPIViewBase):
|
||||
else:
|
||||
return serializer_invalid_response(serializer)
|
||||
|
||||
|
||||
@login_required
|
||||
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,
|
||||
"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
|
||||
# 这个redis 是 celery 使用的,包括存储队列信息还有部分统计信息
|
||||
redis_config = {
|
||||
"host": "121.42.32.129",
|
||||
"port": 6379,
|
||||
@@ -6,17 +7,21 @@ redis_config = {
|
||||
}
|
||||
|
||||
|
||||
# 判题的 docker 容器的配置参数
|
||||
docker_config = {
|
||||
"image_name": " a7673b55d263",
|
||||
"image_name": "3da0e526934e",
|
||||
"docker_path": "docker",
|
||||
"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 = {
|
||||
"host": "127.0.0.1",
|
||||
"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 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
'CONN_MAX_AGE': 0.3,
|
||||
},
|
||||
# submission 的 name 和 engine 请勿修改,其他代码会用到
|
||||
'submission': {
|
||||
'NAME': 'oj_submission',
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'HOST': "121.42.32.129",
|
||||
'POST': 3306,
|
||||
'PORT': 3306,
|
||||
'USER': 'root',
|
||||
'PASSWORD': 'mypwd'
|
||||
'PASSWORD': 'mypwd',
|
||||
'CONN_MAX_AGE': 0.1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +30,4 @@ DEBUG = True
|
||||
# 同理 这是 web 服务器的上传路径
|
||||
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/')
|
||||
|
||||
DATABASE_ROUTERS = ['oj.db_router.DBRouter']
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
@@ -1 +1,37 @@
|
||||
# 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, ...)
|
||||
import os
|
||||
|
||||
# todo 判断运行环境
|
||||
# 判断运行环境
|
||||
ENV = os.environ.get("oj_env", "local")
|
||||
|
||||
if ENV == "local":
|
||||
from .local_settings import *
|
||||
elif ENV == "server":
|
||||
from .server_settings import *
|
||||
elif ENV == "daocloud":
|
||||
from .daocloud_settings import *
|
||||
|
||||
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!
|
||||
SECRET_KEY = 'hzfp^8mbgapc&x%$#xv)0=t8s7_ilingw(q3!@h&2fty6v6fxz'
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
|
||||
# Application definition
|
||||
@@ -115,10 +113,6 @@ STATIC_URL = '/static/'
|
||||
|
||||
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static/src/"),)
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
os.path.join(BASE_DIR, "template/src"),
|
||||
)
|
||||
|
||||
AUTH_USER_MODEL = 'account.User'
|
||||
|
||||
LOGGING = {
|
||||
@@ -171,3 +165,5 @@ LOGGING = {
|
||||
REST_FRAMEWORK = {
|
||||
'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/submission/$', ContestSubmissionAPIView.as_view(), name="contest_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/contest/$', ContestAdminAPIView.as_view(), name="contest_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_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/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"),
|
||||
@@ -88,7 +89,6 @@ urlpatterns = [
|
||||
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'^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"),
|
||||
@@ -103,6 +103,8 @@ urlpatterns = [
|
||||
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/(?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()
|
||||
test_case_id = serializers.CharField(max_length=40)
|
||||
source = serializers.CharField(max_length=30, required=False, default=None)
|
||||
time_limit = serializers.IntegerField()
|
||||
memory_limit = serializers.IntegerField()
|
||||
time_limit = serializers.IntegerField(min_value=1)
|
||||
memory_limit = serializers.IntegerField(min_value=1)
|
||||
difficulty = serializers.IntegerField()
|
||||
tags = serializers.ListField(child=serializers.CharField(max_length=10))
|
||||
hint = serializers.CharField(max_length=3000, allow_blank=True)
|
||||
@@ -61,8 +61,8 @@ class EditProblemSerializer(serializers.Serializer):
|
||||
output_description = serializers.CharField(max_length=10000)
|
||||
test_case_id = serializers.CharField(max_length=40)
|
||||
source = serializers.CharField(max_length=30)
|
||||
time_limit = serializers.IntegerField()
|
||||
memory_limit = serializers.IntegerField()
|
||||
time_limit = serializers.IntegerField(min_value=1)
|
||||
memory_limit = serializers.IntegerField(min_value=1)
|
||||
difficulty = serializers.IntegerField()
|
||||
tags = serializers.ListField(child=serializers.CharField(max_length=20))
|
||||
samples = ProblemSampleSerializer()
|
||||
|
||||
@@ -8,3 +8,4 @@ celery
|
||||
gunicorn
|
||||
coverage
|
||||
django-extensions
|
||||
supervisor
|
||||
@@ -149,16 +149,8 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "datetimePicker",
|
||||
vm.editingContestId = contestId;
|
||||
vm.editTitle = vm.contestList[contestId-1].title;
|
||||
vm.editPassword = vm.contestList[contestId-1].password;
|
||||
//var startTime = new Date(), endTime = new Date();
|
||||
//startTime.setFullYear(parseInt(vm.contestList[contestId-1].start_time.substring(0,4)))
|
||||
//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.editStartTime = vm.contestList[contestId-1].start_time.substring(0,16).replace("T"," ");
|
||||
vm.editEndTime = vm.contestList[contestId-1].end_time.substring(0,16).replace("T"," ");
|
||||
vm.editMode = vm.contestList[contestId-1].mode;
|
||||
vm.editVisible = vm.contestList[contestId-1].visible;
|
||||
if (vm.contestList[contestId-1].contest_type == 0) { //contest type == 0, contest in group
|
||||
@@ -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
|
||||
$.ajax({ // Get current user type
|
||||
url: "/api/user/",
|
||||
|
||||
@@ -13,10 +13,6 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "tagE
|
||||
bsAlert("题目描述不能为空!");
|
||||
return false;
|
||||
}
|
||||
if (vm.timeLimit < 1000 || vm.timeLimit > 5000) {
|
||||
bsAlert("保证时间限制是一个1000-5000的合法整数");
|
||||
return false;
|
||||
}
|
||||
if (vm.samples.length == 0) {
|
||||
bsAlert("请至少添加一组样例!");
|
||||
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 %}
|
||||
@@ -33,12 +33,6 @@
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#nav-left{
|
||||
display: inline;
|
||||
position:relative;
|
||||
float: right;
|
||||
margin-right: 28px;
|
||||
}
|
||||
.section {
|
||||
position: relative;
|
||||
}
|
||||
@@ -103,20 +97,7 @@
|
||||
<a href="/submissions/">提交</a>
|
||||
<a href="/contests/">比赛</a>
|
||||
<a href="/groups/">小组</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>
|
||||
<a href="/about/">关于</a>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -124,9 +105,9 @@
|
||||
<div id="fullpage">
|
||||
<div class="section" id="section0">
|
||||
<div class="index-section-text animated bounceInUp">
|
||||
<h1>青岛大学在线评测平台</h1>
|
||||
<h1>青岛大学 Online Judge</h1>
|
||||
|
||||
<h3>全新面貌,新的开始~</h3>
|
||||
<h3>新的面貌,新的开始~</h3>
|
||||
</div>
|
||||
<div class="bottom-pointer">↓继续滚动~</div>
|
||||
</div>
|
||||
@@ -156,7 +137,7 @@
|
||||
<div class="section-text">
|
||||
<img class="icon" id="img3" src="/static/img/index/m.png">
|
||||
|
||||
<h1>自由举办小组赛</h1>
|
||||
<h1>自由举办小组赛(10月上线)</h1>
|
||||
|
||||
<h3>内部比赛,日常作业,期末考试,通通搞定</h3>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<div class="problem-section">
|
||||
<label class="problem-label">输出</label>
|
||||
|
||||
<p class="problem-detail">{{ problem.output_description }}k</p>
|
||||
<p class="problem-detail">{{ problem.output_description }}</p>
|
||||
</div>
|
||||
{% for item in samples %}
|
||||
<div class="problem-section">
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in submissions %}
|
||||
<tr class="{{ item.result|translate_result_class }}">
|
||||
<tr>
|
||||
<th scope="row"><a href="/submission/{{ item.id }}/" id="id_{{ forloop.counter }}">
|
||||
{{ forloop.counter |add:start_id }}</a></th>
|
||||
<td>{{ item.create_time }}</td>
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
{{ request.user.username }}
|
||||
<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/submission/">我的提交</a></li>
|
||||
<li><a href="/submissions/">我的提交</a></li>
|
||||
<li><a href="#">我的资料</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a href="/logout/">退出</a></li>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
def get_problem_accepted_radio(problem):
|
||||
if 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%"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user