fix bugs due to problem id

This commit is contained in:
zema1 2017-09-29 21:58:20 +08:00
parent 51c229a2c5
commit 2a91fd5e9f
8 changed files with 54 additions and 25 deletions

View File

@ -226,7 +226,7 @@ class UserProfileAPITest(APITestCase):
def test_get_profile_without_login(self): def test_get_profile_without_login(self):
resp = self.client.get(self.url) resp = self.client.get(self.url)
self.assertDictEqual(resp.data, {"error": None, "data": 0}) self.assertDictEqual(resp.data, {"error": None, "data": {}})
def test_get_profile(self): def test_get_profile(self):
self.create_user("test", "test123") self.create_user("test", "test123")

View File

@ -39,7 +39,7 @@ class UserProfileAPI(APIView):
""" """
user = request.user user = request.user
if not user.is_authenticated(): if not user.is_authenticated():
return self.success(0) return self.success({})
username = request.GET.get("username") username = request.GET.get("username")
try: try:
if username: if username:

View File

@ -3,6 +3,8 @@ import hashlib
from django.utils import timezone from django.utils import timezone
from utils.api.tests import APITestCase from utils.api.tests import APITestCase
from utils.cache import default_cache
from utils.constants import CacheKey
from .models import JudgeServer, JudgeServerToken, SMTPConfig from .models import JudgeServer, JudgeServerToken, SMTPConfig
@ -76,7 +78,10 @@ class WebsiteConfigAPITest(APITestCase):
url = self.reverse("website_info_api") url = self.reverse("website_info_api")
resp = self.client.get(url) resp = self.client.get(url)
self.assertSuccess(resp) self.assertSuccess(resp)
self.assertEqual(resp.data["data"]["name_shortcut"], "test oj") self.assertEqual(resp.data["data"]["name_shortcut"], "oj")
def tearDown(self):
default_cache.delete(CacheKey.website_config)
class JudgeServerHeartbeatTest(APITestCase): class JudgeServerHeartbeatTest(APITestCase):

View File

@ -4,17 +4,16 @@ import logging
from urllib.parse import urljoin from urllib.parse import urljoin
import requests import requests
from django.core.cache import cache
from django.db import transaction from django.db import transaction
from django.db.models import F from django.db.models import F
from account.models import User from account.models import User
from conf.models import JudgeServer, JudgeServerToken from conf.models import JudgeServer, JudgeServerToken
from contest.models import ContestRuleType, ACMContestRank, OIContestRank from contest.models import ContestRuleType, ACMContestRank, OIContestRank, ContestStatus
from judge.languages import languages from judge.languages import languages
from problem.models import Problem, ProblemRuleType from problem.models import Problem, ProblemRuleType
from submission.models import JudgeStatus, Submission from submission.models import JudgeStatus, Submission
from utils.cache import judge_cache from utils.cache import judge_cache, default_cache
from utils.constants import CacheKey from utils.constants import CacheKey
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -126,6 +125,7 @@ class JudgeDispatcher(object):
if resp["err"]: if resp["err"]:
self.submission.result = JudgeStatus.COMPILE_ERROR self.submission.result = JudgeStatus.COMPILE_ERROR
self.submission.statistic_info["err_info"] = resp["data"] self.submission.statistic_info["err_info"] = resp["data"]
self.submission.statistic_info["score"] = 0
else: else:
self._compute_statistic_info(resp["data"]) self._compute_statistic_info(resp["data"])
error_test_case = list(filter(lambda case: case["result"] != 0, resp["data"])) error_test_case = list(filter(lambda case: case["result"] != 0, resp["data"]))
@ -154,6 +154,9 @@ class JudgeDispatcher(object):
return self._request(urljoin(service_url, "compile_spj"), data=data) return self._request(urljoin(service_url, "compile_spj"), data=data)
def update_problem_status(self): def update_problem_status(self):
if self.contest_id and self.contest.status != ContestStatus.CONTEST_UNDERWAY:
logger.info("Contest debug mode, id: " + str(self.contest_id) + ", submission id: " + self.submission.id)
return
with transaction.atomic(): with transaction.atomic():
# prepare problem and user_profile # prepare problem and user_profile
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id) problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
@ -168,15 +171,15 @@ class JudgeDispatcher(object):
oi_problems_status = user_profile.oi_problems_status.get(key, {}) oi_problems_status = user_profile.oi_problems_status.get(key, {})
# update submission and accepted number counter # update submission and accepted number counter
problem.submission_number += 1
if self.submission.result == JudgeStatus.ACCEPTED:
problem.accepted_number += 1
# only when submission is not in contest, we update user profile, # only when submission is not in contest, we update user profile,
# in other words, users' submission in a contest will not be counted in user profile # in other words, users' submission in a contest will not be counted in user profile
if not self.contest_id: if not self.contest_id:
user_profile.submission_number += 1 user_profile.submission_number += 1
if self.submission.result == JudgeStatus.ACCEPTED: if self.submission.result == JudgeStatus.ACCEPTED:
user_profile.accepted_number += 1 user_profile.accepted_number += 1
problem.submission_number += 1
if self.submission.result == JudgeStatus.ACCEPTED:
problem.accepted_number += 1
problem_id = str(self.problem.id) problem_id = str(self.problem.id)
if self.problem.rule_type == ProblemRuleType.ACM: if self.problem.rule_type == ProblemRuleType.ACM:
@ -217,8 +220,10 @@ class JudgeDispatcher(object):
"submission_number", "accepted_number", "acm_problems_status", "oi_problems_status"]) "submission_number", "accepted_number", "acm_problems_status", "oi_problems_status"])
def update_contest_rank(self): def update_contest_rank(self):
if self.contest_id and self.contest.status != ContestStatus.CONTEST_UNDERWAY:
return
if self.contest.real_time_rank: if self.contest.real_time_rank:
cache.delete(str(self.contest.id) + "_rank_cache") default_cache.delete(CacheKey.contest_rank_cache + str(self.contest_id))
with transaction.atomic(): with transaction.atomic():
if self.contest.rule_type == ContestRuleType.ACM: if self.contest.rule_type == ContestRuleType.ACM:
acm_rank, _ = ACMContestRank.objects.select_for_update(). \ acm_rank, _ = ACMContestRank.objects.select_for_update(). \
@ -232,7 +237,7 @@ class JudgeDispatcher(object):
def _update_acm_contest_rank(self, rank): def _update_acm_contest_rank(self, rank):
info = rank.submission_info.get(str(self.submission.problem_id)) info = rank.submission_info.get(str(self.submission.problem_id))
# 因前面更改过,这里需要重新获取 # 因前面更改过,这里需要重新获取
problem = Problem.objects.get(contest_id=self.contest_id, _id=self.problem.id) problem = Problem.objects.get(contest_id=self.contest_id, id=self.problem.id)
# 此题提交过 # 此题提交过
if info: if info:
if info["is_ac"]: if info["is_ac"]:

View File

@ -18,7 +18,8 @@ class ProblemAPI(APIView):
problem_id = request.GET.get("problem_id") problem_id = request.GET.get("problem_id")
if problem_id: if problem_id:
try: try:
problem = Problem.objects.select_related("created_by").get(_id=problem_id, visible=True) problem = Problem.objects.select_related("created_by")\
.get(_id=problem_id, contest_id__isnull=True, visible=True)
return self.success(ProblemSerializer(problem).data) return self.success(ProblemSerializer(problem).data)
except Problem.DoesNotExist: except Problem.DoesNotExist:
return self.error("Problem does not exist") return self.error("Problem does not exist")
@ -27,7 +28,7 @@ class ProblemAPI(APIView):
if not limit: if not limit:
return self.error("Limit is needed") return self.error("Limit is needed")
problems = Problem.objects.select_related("created_by").filter(visible=True) problems = Problem.objects.select_related("created_by").filter(contest_id__isnull=True, visible=True)
# 按照标签筛选 # 按照标签筛选
tag_text = request.GET.get("tag") tag_text = request.GET.get("tag")
if tag_text: if tag_text:
@ -54,9 +55,9 @@ class ProblemAPI(APIView):
oi_problems_status = profile.oi_problems_status.get("problems", {}) oi_problems_status = profile.oi_problems_status.get("problems", {})
for problem in data["results"]: for problem in data["results"]:
if problem["rule_type"] == ProblemRuleType.ACM: if problem["rule_type"] == ProblemRuleType.ACM:
problem["my_status"] = acm_problems_status.get(problem["_id"], None) problem["my_status"] = acm_problems_status.get(str(problem["id"]), None)
else: else:
problem["my_status"] = oi_problems_status.get(problem["_id"], None) problem["my_status"] = oi_problems_status.get(str(problem["id"]), None)
return self.success(data) return self.success(data)
@ -83,5 +84,5 @@ class ContestProblemAPI(APIView):
else: else:
problems_status = profile.oi_problems_status.get("contest_problems", {}) problems_status = profile.oi_problems_status.get("contest_problems", {})
for problem in data: for problem in data:
problem["my_status"] = problems_status.get(problem["_id"], None) problem["my_status"] = problems_status.get(str(problem["id"]), None)
return self.success(ContestProblemSerializer(contest_problems, many=True).data) return self.success(data)

View File

@ -20,6 +20,7 @@ class SubmissionModelSerializer(serializers.ModelSerializer):
# 不显示submission info的serializer, 用于ACM rule_type # 不显示submission info的serializer, 用于ACM rule_type
class SubmissionSafeSerializer(serializers.ModelSerializer): class SubmissionSafeSerializer(serializers.ModelSerializer):
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
statistic_info = serializers.JSONField() statistic_info = serializers.JSONField()
class Meta: class Meta:
@ -28,6 +29,7 @@ class SubmissionSafeSerializer(serializers.ModelSerializer):
class SubmissionListSerializer(serializers.ModelSerializer): class SubmissionListSerializer(serializers.ModelSerializer):
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
statistic_info = serializers.JSONField() statistic_info = serializers.JSONField()
show_link = serializers.SerializerMethodField() show_link = serializers.SerializerMethodField()

View File

@ -16,7 +16,7 @@ DEFAULT_PROBLEM_DATA = {"_id": "110", "title": "test", "description": "<p>test</
"rule_type": "ACM", "hint": "<p>test</p>", "source": "test"} "rule_type": "ACM", "hint": "<p>test</p>", "source": "test"}
DEFAULT_SUBMISSION_DATA = { DEFAULT_SUBMISSION_DATA = {
"problem_id": "110", "problem_id": "1",
"user_id": 1, "user_id": 1,
"username": "test", "username": "test",
"code": "xxxxxxxxxxxxxx", "code": "xxxxxxxxxxxxxx",

View File

@ -1,3 +1,4 @@
from account.models import AdminType
from account.decorators import login_required, check_contest_permission from account.decorators import login_required, check_contest_permission
from judge.tasks import judge_task from judge.tasks import judge_task
# from judge.dispatcher import JudgeDispatcher # from judge.dispatcher import JudgeDispatcher
@ -25,7 +26,7 @@ def _submit(response, user, problem_id, language, code, contest_id):
return response.error("Please wait %d seconds" % int(bucket.expected_time() + 1)) return response.error("Please wait %d seconds" % int(bucket.expected_time() + 1))
try: try:
problem = Problem.objects.get(_id=problem_id, problem = Problem.objects.get(id=problem_id,
contest_id=contest_id, contest_id=contest_id,
visible=True) visible=True)
except Problem.DoesNotExist: except Problem.DoesNotExist:
@ -53,15 +54,17 @@ class SubmissionAPI(APIView):
contest = Contest.objects.get(id=data["contest_id"]) contest = Contest.objects.get(id=data["contest_id"])
except Contest.DoesNotExist: except Contest.DoesNotExist:
return self.error("Contest doesn't exist.") return self.error("Contest doesn't exist.")
if contest.status != ContestStatus.CONTEST_UNDERWAY and request.user != contest.created_by: if contest.status == ContestStatus.CONTEST_ENDED:
return self.error("Contest have not started or have ended, you can't submit code.") return self.error("The contest have ended")
if contest.status == ContestStatus.CONTEST_NOT_START and request.user != contest.created_by:
return self.error("Contest have not started")
return _submit(self, request.user, data["problem_id"], data["language"], data["code"], data.get("contest_id")) return _submit(self, request.user, data["problem_id"], data["language"], data["code"], data.get("contest_id"))
@login_required @login_required
def get(self, request): def get(self, request):
submission_id = request.GET.get("id") submission_id = request.GET.get("id")
if not submission_id: if not submission_id:
return self.error("Parameter id doesn't exist.") return self.error("Parameter id do esn't exist.")
try: try:
submission = Submission.objects.select_related("problem").get(id=submission_id) submission = Submission.objects.select_related("problem").get(id=submission_id)
except Submission.DoesNotExist: except Submission.DoesNotExist:
@ -86,8 +89,21 @@ class SubmissionListAPI(APIView):
@check_contest_permission @check_contest_permission
def _get_contest_submission_list(self, request): def _get_contest_submission_list(self, request):
subs = Submission.objects.filter(contest_id=self.contest.id) contest = self.contest
return self.process_submissions(request, subs) # todo OI mode
submissions = Submission.objects.filter(contest_id=contest.id)
# filter the test submissions submitted before contest start
if contest.status != ContestStatus.CONTEST_NOT_START:
print(contest.start_time)
submissions = submissions.filter(create_time__gte=contest.start_time)
# 封榜的时候只能看到自己的提交
if not contest.real_time_rank:
if request.user and not (
request.user.admin_type == AdminType.SUPER_ADMIN or request.user == contest.created_by):
submissions = submissions.filter(user_id=request.user.id)
return self.process_submissions(request, submissions)
def process_submissions(self, request, submissions): def process_submissions(self, request, submissions):
problem_id = request.GET.get("problem_id") problem_id = request.GET.get("problem_id")
@ -98,7 +114,7 @@ class SubmissionListAPI(APIView):
problem = Problem.objects.get(_id=problem_id, visible=True) problem = Problem.objects.get(_id=problem_id, visible=True)
except Problem.DoesNotExist: except Problem.DoesNotExist:
return self.error("Problem doesn't exist") return self.error("Problem doesn't exist")
submissions = problem.submission_set.all() submissions = submissions.filter(problem=problem)
if myself and myself == "1": if myself and myself == "1":
submissions = submissions.filter(user_id=request.user.id) submissions = submissions.filter(user_id=request.user.id)
if result: if result: