mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-11-04 14:49:58 +08:00
fix many bugs
This commit is contained in:
parent
f0655ee305
commit
aa4240790b
@ -372,10 +372,9 @@ class UserRankAPI(APIView):
|
|||||||
if rule_type not in ContestRuleType.choices():
|
if rule_type not in ContestRuleType.choices():
|
||||||
rule_type = ContestRuleType.ACM
|
rule_type = ContestRuleType.ACM
|
||||||
profiles = UserProfile.objects.select_related("user")\
|
profiles = UserProfile.objects.select_related("user")\
|
||||||
.filter(submission_number__gt=0)\
|
|
||||||
.exclude(user__is_disabled=True)
|
.exclude(user__is_disabled=True)
|
||||||
if rule_type == ContestRuleType.ACM:
|
if rule_type == ContestRuleType.ACM:
|
||||||
profiles = profiles.order_by("-accepted_number", "submission_number")
|
profiles = profiles.filter(submission_number__gt=0).order_by("-accepted_number", "submission_number")
|
||||||
else:
|
else:
|
||||||
profiles = profiles.order_by("-total_score")
|
profiles = profiles.filter(total_score__gt=0).order_by("-total_score")
|
||||||
return self.success(self.paginate_data(request, profiles, RankInfoSerializer))
|
return self.success(self.paginate_data(request, profiles, RankInfoSerializer))
|
||||||
|
|||||||
@ -15,4 +15,4 @@ class Announcement(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "announcement"
|
db_table = "announcement"
|
||||||
ordering = ('-create_time',)
|
ordering = ("-create_time",)
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class Contest(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "contest"
|
db_table = "contest"
|
||||||
ordering = ("-create_time",)
|
ordering = ("-start_time",)
|
||||||
|
|
||||||
|
|
||||||
class AbstractContestRank(models.Model):
|
class AbstractContestRank(models.Model):
|
||||||
|
|||||||
@ -95,7 +95,7 @@ class ContestAPITest(APITestCase):
|
|||||||
self.assertSuccess(resp)
|
self.assertSuccess(resp)
|
||||||
|
|
||||||
|
|
||||||
class ContestAnnouncementAPITest(APITestCase):
|
class ContestAnnouncementAdminAPITest(APITestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.create_super_admin()
|
self.create_super_admin()
|
||||||
self.url = self.reverse("contest_announcement_admin_api")
|
self.url = self.reverse("contest_announcement_admin_api")
|
||||||
@ -120,7 +120,7 @@ class ContestAnnouncementAPITest(APITestCase):
|
|||||||
|
|
||||||
def test_get_contest_announcements(self):
|
def test_get_contest_announcements(self):
|
||||||
self.test_create_contest_announcement()
|
self.test_create_contest_announcement()
|
||||||
response = self.client.get(self.url)
|
response = self.client.get(self.url + "?contest_id=" + str(self.data["contest_id"]))
|
||||||
self.assertSuccess(response)
|
self.assertSuccess(response)
|
||||||
|
|
||||||
def test_get_one_contest_announcement(self):
|
def test_get_one_contest_announcement(self):
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from urllib.parse import urljoin
|
|||||||
import requests
|
import requests
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from account.models import User
|
from account.models import User
|
||||||
from conf.models import JudgeServer
|
from conf.models import JudgeServer
|
||||||
@ -79,7 +80,10 @@ class JudgeDispatcher(object):
|
|||||||
try:
|
try:
|
||||||
for i in range(len(resp_data)):
|
for i in range(len(resp_data)):
|
||||||
if resp_data[i]["result"] == JudgeStatus.ACCEPTED:
|
if resp_data[i]["result"] == JudgeStatus.ACCEPTED:
|
||||||
score += self.problem.test_case_score[i]["score"]
|
resp_data[i]["score"] = self.problem.test_case_score[i]["score"]
|
||||||
|
score += resp_data[i]["score"]
|
||||||
|
else:
|
||||||
|
resp_data[i]["score"] = 0
|
||||||
except IndexError:
|
except IndexError:
|
||||||
logger.error(f"Index Error raised when summing up the score in problem {self.problem.id}")
|
logger.error(f"Index Error raised when summing up the score in problem {self.problem.id}")
|
||||||
self.submission.statistic_info["score"] = 0
|
self.submission.statistic_info["score"] = 0
|
||||||
@ -115,8 +119,11 @@ class JudgeDispatcher(object):
|
|||||||
|
|
||||||
Submission.objects.filter(id=self.submission.id).update(result=JudgeStatus.JUDGING)
|
Submission.objects.filter(id=self.submission.id).update(result=JudgeStatus.JUDGING)
|
||||||
|
|
||||||
# TODO: try catch
|
service_url = server.service_url
|
||||||
resp = self._request(urljoin(server.service_url, "/judge"), data=data)
|
# not set service_url, it should be a linked container
|
||||||
|
if not service_url:
|
||||||
|
service_url = settings.DEFAULT_JUDGE_SERVER_SERVICE_URL
|
||||||
|
resp = self._request(urljoin(service_url, "/judge"), data=data)
|
||||||
self.submission.info = resp
|
self.submission.info = resp
|
||||||
if resp["err"]:
|
if resp["err"]:
|
||||||
self.submission.result = JudgeStatus.COMPILE_ERROR
|
self.submission.result = JudgeStatus.COMPILE_ERROR
|
||||||
@ -201,7 +208,7 @@ class JudgeDispatcher(object):
|
|||||||
logger.info("Contest debug mode, id: " + str(self.contest_id) + ", submission id: " + self.submission.id)
|
logger.info("Contest debug mode, id: " + str(self.contest_id) + ", submission id: " + self.submission.id)
|
||||||
return
|
return
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
user = User.objects.select_for_update().select_related("userprofile").get(id=self.submission.user_id)
|
user = User.objects.select_for_update().get(id=self.submission.user_id)
|
||||||
user_profile = user.userprofile
|
user_profile = user.userprofile
|
||||||
problem_id = str(self.problem.id)
|
problem_id = str(self.problem.id)
|
||||||
if self.contest.rule_type == ContestRuleType.ACM:
|
if self.contest.rule_type == ContestRuleType.ACM:
|
||||||
@ -298,5 +305,7 @@ class JudgeDispatcher(object):
|
|||||||
last_score = rank.submission_info.get(problem_id)
|
last_score = rank.submission_info.get(problem_id)
|
||||||
if last_score:
|
if last_score:
|
||||||
rank.total_score = rank.total_score - last_score + current_score
|
rank.total_score = rank.total_score - last_score + current_score
|
||||||
|
else:
|
||||||
|
rank.total_score = rank.total_score + current_score
|
||||||
rank.submission_info[problem_id] = current_score
|
rank.submission_info[problem_id] = current_score
|
||||||
rank.save()
|
rank.save()
|
||||||
|
|||||||
@ -26,7 +26,7 @@ ALLOWED_HOSTS = ["*"]
|
|||||||
|
|
||||||
TEST_CASE_DIR = "/tmp"
|
TEST_CASE_DIR = "/tmp"
|
||||||
|
|
||||||
LOG_PATH = "/tmp/"
|
LOG_PATH = f"{BASE_DIR}/log/"
|
||||||
|
|
||||||
AVATAR_URI_PREFIX = "/static/avatar"
|
AVATAR_URI_PREFIX = "/static/avatar"
|
||||||
AVATAR_UPLOAD_DIR = f"{BASE_DIR}{AVATAR_URI_PREFIX}"
|
AVATAR_UPLOAD_DIR = f"{BASE_DIR}{AVATAR_URI_PREFIX}"
|
||||||
|
|||||||
@ -30,3 +30,4 @@ AVATAR_UPLOAD_DIR = "/data/avatar"
|
|||||||
|
|
||||||
TEST_CASE_DIR = "/data/test_case"
|
TEST_CASE_DIR = "/data/test_case"
|
||||||
LOG_PATH = "/data/log"
|
LOG_PATH = "/data/log"
|
||||||
|
DEFAULT_JUDGE_SERVER_SERVICE_URL = "http://judge-server:8080/"
|
||||||
|
|||||||
@ -10,6 +10,7 @@ For the full list of settings and their values, see
|
|||||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
from .custom_settings import *
|
from .custom_settings import *
|
||||||
|
|
||||||
@ -20,17 +21,17 @@ else:
|
|||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
# Applications
|
# Applications
|
||||||
INSTALLED_APPS = (
|
VENDOR_APPS = (
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
|
)
|
||||||
'account',
|
LOCAL_APPS = (
|
||||||
|
'account',
|
||||||
'announcement',
|
'announcement',
|
||||||
'conf',
|
'conf',
|
||||||
'problem',
|
'problem',
|
||||||
@ -38,8 +39,11 @@ INSTALLED_APPS = (
|
|||||||
'utils',
|
'utils',
|
||||||
'submission',
|
'submission',
|
||||||
'options',
|
'options',
|
||||||
|
'judge',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
INSTALLED_APPS = VENDOR_APPS + LOCAL_APPS
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE_CLASSES = (
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@ -115,17 +119,16 @@ LOGGING = {
|
|||||||
'formatters': {
|
'formatters': {
|
||||||
'standard': {
|
'standard': {
|
||||||
'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s'}
|
'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s'}
|
||||||
# 日志格式
|
|
||||||
},
|
},
|
||||||
'handlers': {
|
'handlers': {
|
||||||
'django_error': {
|
'django_error': {
|
||||||
'level': 'DEBUG',
|
'level': 'WARNING',
|
||||||
'class': 'logging.handlers.RotatingFileHandler',
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
'filename': os.path.join(LOG_PATH, 'django.log'),
|
'filename': os.path.join(LOG_PATH, 'django.log'),
|
||||||
'formatter': 'standard'
|
'formatter': 'standard'
|
||||||
},
|
},
|
||||||
'app_info': {
|
'app_info': {
|
||||||
'level': 'DEBUG',
|
'level': 'INFO',
|
||||||
'class': 'logging.handlers.RotatingFileHandler',
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
'filename': os.path.join(LOG_PATH, 'app_info.log'),
|
'filename': os.path.join(LOG_PATH, 'app_info.log'),
|
||||||
'formatter': 'standard'
|
'formatter': 'standard'
|
||||||
@ -137,23 +140,30 @@ LOGGING = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'app_info': {
|
|
||||||
'handlers': ['app_info', "console"],
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'propagate': True
|
|
||||||
},
|
|
||||||
'django.request': {
|
'django.request': {
|
||||||
'handlers': ['django_error', 'console'],
|
'handlers': ['django_error', 'console'],
|
||||||
'level': 'DEBUG',
|
'level': 'WARNING',
|
||||||
|
'propagate': True,
|
||||||
|
},
|
||||||
|
'django.server': {
|
||||||
|
'handlers': ['django_error', 'console'],
|
||||||
|
'level': 'ERROR',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
},
|
},
|
||||||
'django.db.backends': {
|
'django.db.backends': {
|
||||||
'handlers': ['console'],
|
'handlers': ['django_error', 'console'],
|
||||||
'level': 'ERROR',
|
'level': 'WARNING',
|
||||||
'propagate': True,
|
'propagate': True,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
app_logger = {
|
||||||
|
'handlers': ['app_info', 'console'],
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'propagate': False
|
||||||
|
}
|
||||||
|
LOGGING["loggers"].update({app: deepcopy(app_logger) for app in LOCAL_APPS})
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
|
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': (
|
||||||
@ -163,6 +173,7 @@ REST_FRAMEWORK = {
|
|||||||
|
|
||||||
REDIS_URL = "redis://%s:%s" % (REDIS_CONF["host"], REDIS_CONF["port"])
|
REDIS_URL = "redis://%s:%s" % (REDIS_CONF["host"], REDIS_CONF["port"])
|
||||||
|
|
||||||
|
|
||||||
def redis_config(db):
|
def redis_config(db):
|
||||||
def make_key(key, key_prefix, version):
|
def make_key(key, key_prefix, version):
|
||||||
return key
|
return key
|
||||||
@ -175,16 +186,14 @@ def redis_config(db):
|
|||||||
"KEY_FUNCTION": make_key
|
"KEY_FUNCTION": make_key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
"default": redis_config(db=1)
|
"default": redis_config(db=1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
||||||
SESSION_CACHE_ALIAS = "default"
|
SESSION_CACHE_ALIAS = "default"
|
||||||
|
|
||||||
|
|
||||||
CELERY_RESULT_BACKEND = f"{REDIS_URL}/2"
|
CELERY_RESULT_BACKEND = f"{REDIS_URL}/2"
|
||||||
BROKER_URL = f"{REDIS_URL}/3"
|
BROKER_URL = f"{REDIS_URL}/3"
|
||||||
CELERY_TASK_SOFT_TIME_LIMIT = CELERY_TASK_TIME_LIMIT = 180
|
CELERY_TASK_SOFT_TIME_LIMIT = CELERY_TASK_TIME_LIMIT = 180
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db import transaction, IntegrityError
|
from django.db import transaction, IntegrityError
|
||||||
|
|
||||||
@ -6,6 +7,11 @@ from utils.shortcuts import rand_str
|
|||||||
from .models import SysOptions as SysOptionsModel
|
from .models import SysOptions as SysOptionsModel
|
||||||
|
|
||||||
|
|
||||||
|
def default_token():
|
||||||
|
token = os.environ.get("JUDGE_SERVER_TOKEN")
|
||||||
|
return token if token else rand_str()
|
||||||
|
|
||||||
|
|
||||||
class OptionKeys:
|
class OptionKeys:
|
||||||
website_base_url = "website_base_url"
|
website_base_url = "website_base_url"
|
||||||
website_name = "website_name"
|
website_name = "website_name"
|
||||||
@ -25,7 +31,7 @@ class OptionDefaultValue:
|
|||||||
allow_register = True
|
allow_register = True
|
||||||
submission_list_show_all = True
|
submission_list_show_all = True
|
||||||
smtp_config = {}
|
smtp_config = {}
|
||||||
judge_server_token = rand_str
|
judge_server_token = default_token
|
||||||
|
|
||||||
|
|
||||||
class _SysOptionsMeta(type):
|
class _SysOptionsMeta(type):
|
||||||
|
|||||||
@ -113,5 +113,5 @@ class ContestProblemSerializer(BaseProblemSerializer):
|
|||||||
class ContestProblemSafeSerializer(BaseProblemSerializer):
|
class ContestProblemSafeSerializer(BaseProblemSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Problem
|
model = Problem
|
||||||
exclude = ("test_case_score", "test_case_id", "visible", "is_public", "difficulty"
|
exclude = ("test_case_score", "test_case_id", "visible", "is_public", "difficulty",
|
||||||
"submission_number", "accepted_number", "statistic_info")
|
"submission_number", "accepted_number", "statistic_info")
|
||||||
|
|||||||
@ -76,7 +76,7 @@ class TestCaseUploadAPI(CSRFExemptAPIView):
|
|||||||
content = zip_file.read(item).replace(b"\r\n", b"\n")
|
content = zip_file.read(item).replace(b"\r\n", b"\n")
|
||||||
size_cache[item] = len(content)
|
size_cache[item] = len(content)
|
||||||
if item.endswith(".out"):
|
if item.endswith(".out"):
|
||||||
md5_cache[item] = hashlib.md5(content).hexdigest()
|
md5_cache[item] = hashlib.md5(content.rstrip()).hexdigest()
|
||||||
f.write(content)
|
f.write(content)
|
||||||
test_case_info = {"spj": spj, "test_cases": {}}
|
test_case_info = {"spj": spj, "test_cases": {}}
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class SubmissionAPI(APIView):
|
|||||||
return self.error("The contest have ended")
|
return self.error("The contest have ended")
|
||||||
if contest.status == ContestStatus.CONTEST_NOT_START and not contest.is_contest_admin(request.user):
|
if contest.status == ContestStatus.CONTEST_NOT_START and not contest.is_contest_admin(request.user):
|
||||||
return self.error("Contest have not started")
|
return self.error("Contest have not started")
|
||||||
if not contest.problem_details_permission():
|
if not contest.problem_details_permission(request.user):
|
||||||
hide_id = True
|
hide_id = True
|
||||||
|
|
||||||
if data.get("captcha"):
|
if data.get("captcha"):
|
||||||
@ -110,6 +110,9 @@ class SubmissionAPI(APIView):
|
|||||||
@validate_serializer(ShareSubmissionSerializer)
|
@validate_serializer(ShareSubmissionSerializer)
|
||||||
@login_required
|
@login_required
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
|
"""
|
||||||
|
share submission
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
submission = Submission.objects.select_related("problem").get(id=request.data["id"])
|
submission = Submission.objects.select_related("problem").get(id=request.data["id"])
|
||||||
except Submission.DoesNotExist:
|
except Submission.DoesNotExist:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user