NDOJ/judge/tasks/submission.py
2020-01-21 15:35:58 +09:00

67 lines
2.6 KiB
Python

from celery import shared_task
from django.core.cache import cache
from django.utils.translation import gettext as _
from judge.models import Problem, Profile, Submission
from judge.utils.celery import Progress
__all__ = ('apply_submission_filter', 'rejudge_problem_filter', 'rescore_problem')
def apply_submission_filter(queryset, id_range, languages, results):
if id_range:
start, end = id_range
queryset = queryset.filter(id__gte=start, id__lte=end)
if languages:
queryset = queryset.filter(language_id__in=languages)
if results:
queryset = queryset.filter(result__in=results)
queryset = queryset.exclude(status__in=Submission.IN_PROGRESS_GRADING_STATUS)
return queryset
@shared_task(bind=True)
def rejudge_problem_filter(self, problem_id, id_range=None, languages=None, results=None):
queryset = Submission.objects.filter(problem_id=problem_id)
queryset = apply_submission_filter(queryset, id_range, languages, results)
rejudged = 0
with Progress(self, queryset.count()) as p:
for submission in queryset.iterator():
submission.judge(rejudge=True, batch_rejudge=True)
rejudged += 1
if rejudged % 10 == 0:
p.done = rejudged
return rejudged
@shared_task(bind=True)
def rescore_problem(self, problem_id):
problem = Problem.objects.get(id=problem_id)
submissions = Submission.objects.filter(problem_id=problem_id)
with Progress(self, submissions.count(), stage=_('Modifying submissions')) as p:
rescored = 0
for submission in submissions.iterator():
submission.points = round(submission.case_points / submission.case_total * problem.points
if submission.case_total else 0, 1)
if not problem.partial and submission.points < problem.points:
submission.points = 0
submission.save(update_fields=['points'])
submission.update_contest()
rescored += 1
if rescored % 10 == 0:
p.done = rescored
with Progress(self, submissions.values('user_id').distinct().count(), stage=_('Recalculating user points')) as p:
users = 0
profiles = Profile.objects.filter(id__in=submissions.values_list('user_id', flat=True).distinct())
for profile in profiles.iterator():
profile._updating_stats_only = True
profile.calculate_points()
cache.delete('user_complete:%d' % profile.id)
cache.delete('user_attempted:%d' % profile.id)
users += 1
if users % 10 == 0:
p.done = users
return rescored