add migration to correct database record; rejudge function now can work normally.

This commit is contained in:
virusdefender 2018-03-27 13:53:30 +08:00 committed by zema1
parent a0da0b5fa6
commit 2e50910931
4 changed files with 90 additions and 18 deletions

View File

@ -85,12 +85,11 @@ class SPJCompiler(DispatcherBase):
class JudgeDispatcher(DispatcherBase): class JudgeDispatcher(DispatcherBase):
def __init__(self, submission_id, problem_id, is_rejudge=False): def __init__(self, submission_id, problem_id):
super().__init__() super().__init__()
self.submission = Submission.objects.get(id=submission_id) self.submission = Submission.objects.get(id=submission_id)
self.contest_id = self.submission.contest_id self.contest_id = self.submission.contest_id
self.is_rejudge = is_rejudge self.last_result = self.submission.result if self.submission.info else None
self.last_result = None
if self.contest_id: if self.contest_id:
self.problem = Problem.objects.select_related("contest").get(id=problem_id, contest_id=self.contest_id) self.problem = Problem.objects.select_related("contest").get(id=problem_id, contest_id=self.contest_id)
@ -122,7 +121,7 @@ class JudgeDispatcher(DispatcherBase):
def judge(self): def judge(self):
server = self.choose_judge_server() server = self.choose_judge_server()
if not server: if not server:
data = {"submission_id": self.submission.id, "problem_id": self.problem.id, "is_rejudge": self.is_rejudge} data = {"submission_id": self.submission.id, "problem_id": self.problem.id}
cache.lpush(CacheKey.waiting_queue, json.dumps(data)) cache.lpush(CacheKey.waiting_queue, json.dumps(data))
return return
@ -153,7 +152,6 @@ class JudgeDispatcher(DispatcherBase):
"spj_compile_config": spj_config.get("compile"), "spj_compile_config": spj_config.get("compile"),
"spj_src": self.problem.spj_code "spj_src": self.problem.spj_code
} }
self.last_result = self.submission.result
Submission.objects.filter(id=self.submission.id).update(result=JudgeStatus.JUDGING) Submission.objects.filter(id=self.submission.id).update(result=JudgeStatus.JUDGING)
@ -181,30 +179,66 @@ class JudgeDispatcher(DispatcherBase):
if self.contest_id: if self.contest_id:
if self.contest.status != ContestStatus.CONTEST_UNDERWAY or \ if self.contest.status != ContestStatus.CONTEST_UNDERWAY or \
User.objects.get(id=self.submission.user_id).is_contest_admin(self.contest): 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 return
self.update_contest_problem_status() self.update_contest_problem_status()
self.update_contest_rank() self.update_contest_rank()
else:
if self.last_result:
self.update_problem_status_rejudge()
else: else:
self.update_problem_status() self.update_problem_status()
# 至此判题结束,尝试处理任务队列中剩余的任务 # 至此判题结束,尝试处理任务队列中剩余的任务
process_pending_task() 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): def update_problem_status(self):
result = str(self.submission.result) result = str(self.submission.result)
problem_id = str(self.problem.id) problem_id = str(self.problem.id)
with transaction.atomic(): with transaction.atomic():
# update problem status # update problem status
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)
if not self.is_rejudge:
problem.submission_number += 1 problem.submission_number += 1
if self.submission.result == JudgeStatus.ACCEPTED: if self.submission.result == JudgeStatus.ACCEPTED:
if self.last_result != JudgeStatus.ACCEPTED:
problem.accepted_number += 1 problem.accepted_number += 1
else:
if self.last_result == JudgeStatus.ACCEPTED:
problem.accepted_number -= 1
problem_info = problem.statistic_info problem_info = problem.statistic_info
problem_info[result] = problem_info.get(result, 0) + 1 problem_info[result] = problem_info.get(result, 0) + 1
problem.save(update_fields=["accepted_number", "submission_number", "statistic_info"]) problem.save(update_fields=["accepted_number", "submission_number", "statistic_info"])

View File

@ -4,5 +4,5 @@ from judge.dispatcher import JudgeDispatcher
@shared_task @shared_task
def judge_task(submission_id, problem_id, is_rejudge=False): def judge_task(submission_id, problem_id):
JudgeDispatcher(submission_id, problem_id, is_rejudge=is_rejudge).judge() JudgeDispatcher(submission_id, problem_id).judge()

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.tasks import judge_task
# from judge.dispatcher import JudgeDispatcher # from judge.dispatcher import JudgeDispatcher
from utils.api import APIView from utils.api import APIView
from ..models import Submission, JudgeStatus from ..models import Submission
class SubmissionRejudgeAPI(APIView): class SubmissionRejudgeAPI(APIView):
@ -19,5 +19,5 @@ class SubmissionRejudgeAPI(APIView):
submission.statistic_info = {} submission.statistic_info = {}
submission.save() submission.save()
judge_task.delay(submission.id, submission.problem.id, is_rejudge=True) judge_task.delay(submission.id, submission.problem.id)
return self.success() return self.success()