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):
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):
self.create_user("test", "test123")

View File

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

View File

@ -3,6 +3,8 @@ import hashlib
from django.utils import timezone
from utils.api.tests import APITestCase
from utils.cache import default_cache
from utils.constants import CacheKey
from .models import JudgeServer, JudgeServerToken, SMTPConfig
@ -76,7 +78,10 @@ class WebsiteConfigAPITest(APITestCase):
url = self.reverse("website_info_api")
resp = self.client.get(url)
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):

View File

@ -4,17 +4,16 @@ import logging
from urllib.parse import urljoin
import requests
from django.core.cache import cache
from django.db import transaction
from django.db.models import F
from account.models import User
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 problem.models import Problem, ProblemRuleType
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
logger = logging.getLogger(__name__)
@ -126,6 +125,7 @@ class JudgeDispatcher(object):
if resp["err"]:
self.submission.result = JudgeStatus.COMPILE_ERROR
self.submission.statistic_info["err_info"] = resp["data"]
self.submission.statistic_info["score"] = 0
else:
self._compute_statistic_info(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)
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():
# prepare problem and user_profile
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, {})
# 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,
# in other words, users' submission in a contest will not be counted in user profile
if not self.contest_id:
user_profile.submission_number += 1
if self.submission.result == JudgeStatus.ACCEPTED:
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)
if self.problem.rule_type == ProblemRuleType.ACM:
@ -217,8 +220,10 @@ class JudgeDispatcher(object):
"submission_number", "accepted_number", "acm_problems_status", "oi_problems_status"])
def update_contest_rank(self):
if self.contest_id and self.contest.status != ContestStatus.CONTEST_UNDERWAY:
return
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():
if self.contest.rule_type == ContestRuleType.ACM:
acm_rank, _ = ACMContestRank.objects.select_for_update(). \
@ -232,7 +237,7 @@ class JudgeDispatcher(object):
def _update_acm_contest_rank(self, rank):
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["is_ac"]:

View File

@ -18,7 +18,8 @@ class ProblemAPI(APIView):
problem_id = request.GET.get("problem_id")
if problem_id:
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)
except Problem.DoesNotExist:
return self.error("Problem does not exist")
@ -27,7 +28,7 @@ class ProblemAPI(APIView):
if not limit:
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")
if tag_text:
@ -54,9 +55,9 @@ class ProblemAPI(APIView):
oi_problems_status = profile.oi_problems_status.get("problems", {})
for problem in data["results"]:
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:
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)
@ -83,5 +84,5 @@ class ContestProblemAPI(APIView):
else:
problems_status = profile.oi_problems_status.get("contest_problems", {})
for problem in data:
problem["my_status"] = problems_status.get(problem["_id"], None)
return self.success(ContestProblemSerializer(contest_problems, many=True).data)
problem["my_status"] = problems_status.get(str(problem["id"]), None)
return self.success(data)

View File

@ -20,6 +20,7 @@ class SubmissionModelSerializer(serializers.ModelSerializer):
# 不显示submission info的serializer, 用于ACM rule_type
class SubmissionSafeSerializer(serializers.ModelSerializer):
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
statistic_info = serializers.JSONField()
class Meta:
@ -28,6 +29,7 @@ class SubmissionSafeSerializer(serializers.ModelSerializer):
class SubmissionListSerializer(serializers.ModelSerializer):
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
statistic_info = serializers.JSONField()
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"}
DEFAULT_SUBMISSION_DATA = {
"problem_id": "110",
"problem_id": "1",
"user_id": 1,
"username": "test",
"code": "xxxxxxxxxxxxxx",

View File

@ -1,3 +1,4 @@
from account.models import AdminType
from account.decorators import login_required, check_contest_permission
from judge.tasks import judge_task
# 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))
try:
problem = Problem.objects.get(_id=problem_id,
problem = Problem.objects.get(id=problem_id,
contest_id=contest_id,
visible=True)
except Problem.DoesNotExist:
@ -53,15 +54,17 @@ class SubmissionAPI(APIView):
contest = Contest.objects.get(id=data["contest_id"])
except Contest.DoesNotExist:
return self.error("Contest doesn't exist.")
if contest.status != ContestStatus.CONTEST_UNDERWAY and request.user != contest.created_by:
return self.error("Contest have not started or have ended, you can't submit code.")
if contest.status == ContestStatus.CONTEST_ENDED:
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"))
@login_required
def get(self, request):
submission_id = request.GET.get("id")
if not submission_id:
return self.error("Parameter id doesn't exist.")
return self.error("Parameter id do esn't exist.")
try:
submission = Submission.objects.select_related("problem").get(id=submission_id)
except Submission.DoesNotExist:
@ -86,8 +89,21 @@ class SubmissionListAPI(APIView):
@check_contest_permission
def _get_contest_submission_list(self, request):
subs = Submission.objects.filter(contest_id=self.contest.id)
return self.process_submissions(request, subs)
contest = self.contest
# 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):
problem_id = request.GET.get("problem_id")
@ -98,7 +114,7 @@ class SubmissionListAPI(APIView):
problem = Problem.objects.get(_id=problem_id, visible=True)
except Problem.DoesNotExist:
return self.error("Problem doesn't exist")
submissions = problem.submission_set.all()
submissions = submissions.filter(problem=problem)
if myself and myself == "1":
submissions = submissions.filter(user_id=request.user.id)
if result: