Merge pull request #134 from QingdaoU/fix_rejudge

Fix rejudge
This commit is contained in:
李扬 2018-03-28 12:49:16 +08:00 committed by GitHub
commit b33e2db7e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 17 deletions

View File

@ -89,6 +89,8 @@ class JudgeDispatcher(DispatcherBase):
super().__init__()
self.submission = Submission.objects.get(id=submission_id)
self.contest_id = self.submission.contest_id
self.last_result = self.submission.result if self.submission.info else None
if self.contest_id:
self.problem = Problem.objects.select_related("contest").get(id=problem_id, contest_id=self.contest_id)
self.contest = self.problem.contest
@ -150,11 +152,7 @@ class JudgeDispatcher(DispatcherBase):
"spj_compile_config": spj_config.get("compile"),
"spj_src": self.problem.spj_code
}
self.last_result = None
try:
self.last_result = Submission.objects.get(id=self.submission.id).result
except Submission.DoesNotExist:
pass
Submission.objects.filter(id=self.submission.id).update(result=JudgeStatus.JUDGING)
resp = self._request(urljoin(server.service_url, "/judge"), data=data)
@ -181,30 +179,66 @@ class JudgeDispatcher(DispatcherBase):
if self.contest_id:
if self.contest.status != ContestStatus.CONTEST_UNDERWAY or \
User.objects.get(id=self.submission.user_id).is_contest_admin(self.contest):
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
self.update_contest_problem_status()
self.update_contest_rank()
else:
self.update_problem_status()
if self.last_result:
self.update_problem_status_rejudge()
else:
self.update_problem_status()
# 至此判题结束,尝试处理任务队列中剩余的任务
process_pending_task()
def update_problem_status_rejudge(self):
result = str(self.submission.result)
problem_id = str(self.problem.id)
with transaction.atomic():
# update problem status
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
if self.last_result != JudgeStatus.ACCEPTED and self.submission.result == JudgeStatus.ACCEPTED:
problem.accepted_number += 1
problem_info = problem.statistic_info
problem_info[self.last_result] = problem_info.get(self.last_result, 1) - 1
problem_info[result] = problem_info.get(result, 0) + 1
problem.save(update_fields=["accepted_number", "statistic_info"])
profile = User.objects.select_for_update().get(id=self.submission.user_id).userprofile
if problem.rule_type == ProblemRuleType.ACM:
acm_problems_status = profile.acm_problems_status.get("problems", {})
if acm_problems_status[problem_id]["status"] != JudgeStatus.ACCEPTED:
acm_problems_status[problem_id]["status"] = self.submission.result
if self.submission.result == JudgeStatus.ACCEPTED:
profile.accepted_number += 1
profile.acm_problems_status["problems"] = acm_problems_status
profile.save(update_fields=["accepted_number", "acm_problems_status"])
else:
oi_problems_status = profile.oi_problems_status.get("problems", {})
score = self.submission.statistic_info["score"]
if oi_problems_status[problem_id]["status"] != JudgeStatus.ACCEPTED:
# minus last time score, add this tim score
profile.add_score(this_time_score=score,
last_time_score=oi_problems_status[problem_id]["score"])
oi_problems_status[problem_id]["score"] = score
oi_problems_status[problem_id]["status"] = self.submission.result
if self.submission.result == JudgeStatus.ACCEPTED:
profile.accepted_number += 1
profile.oi_problems_status["problems"] = oi_problems_status
profile.save(update_fields=["accepted_number", "oi_problems_status"])
def update_problem_status(self):
result = str(self.submission.result)
problem_id = str(self.problem.id)
with transaction.atomic():
# update problem status
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
if not self.last_result:
problem.submission_number += 1
problem.submission_number += 1
if self.submission.result == JudgeStatus.ACCEPTED:
if self.last_result != JudgeStatus.ACCEPTED:
problem.accepted_number += 1
else:
if self.last_result == JudgeStatus.ACCEPTED:
problem.accepted_number -= 1
problem.accepted_number += 1
problem_info = problem.statistic_info
problem_info[result] = problem_info.get(result, 0) + 1
problem.save(update_fields=["accepted_number", "submission_number", "statistic_info"])

View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
from django.db.models import Count
def fix_rejudge_bugs(apps, schema_editor):
Submission = apps.get_model("submission", "Submission")
Problem = apps.get_model("problem", "Problem")
User = apps.get_model("account", "User")
for item in Problem.objects.filter(contest__isnull=True):
submissions = Submission.objects.filter(problem=item)
item.submission_number = submissions.count()
results_count = submissions.annotate(count=Count('result')).values('result', 'count')
for stat in results_count:
if stat["result"] == 0:
item.accepted_number = stat["count"]
item.statistic_info[str(stat)] = stat["count"]
item.save(update_fields=["submission_number", "accepted_number", "statistic_info"])
for user in User.objects.all():
submissions = Submission.objects.filter(user_id=user.id)
profile = user.userprofile
profile.submission_number = submissions.count()
profile.accepted_number = submissions.filter(result=0).count()
profile.save(update_fields=["submission_number", "accepted_number"])
class Migration(migrations.Migration):
dependencies = [
('submission', '0009_delete_user_output'),
]
operations = [
migrations.RunPython(fix_rejudge_bugs, reverse_code=migrations.RunPython.noop)
]

View File

@ -2,7 +2,7 @@ from account.decorators import super_admin_required
from judge.tasks import judge_task
# from judge.dispatcher import JudgeDispatcher
from utils.api import APIView
from ..models import Submission, JudgeStatus
from ..models import Submission
class SubmissionRejudgeAPI(APIView):
@ -10,12 +10,11 @@ class SubmissionRejudgeAPI(APIView):
def get(self, request):
id = request.GET.get("id")
if not id:
return self.error("Paramater error, id is required")
return self.error("Parameter error, id is required")
try:
submission = Submission.objects.select_related("problem").get(id=id, contest_id__isnull=True)
except Submission.DoesNotExist:
return self.error("Submission does not exists")
submission.result = JudgeStatus.PENDING
submission.info = {}
submission.statistic_info = {}
submission.save()