NDOJ/judge/tasks/submission.py

88 lines
3.1 KiB
Python
Raw Normal View History

2020-01-21 06:35:58 +00:00
from celery import shared_task
from django.core.cache import cache
from django.utils.translation import gettext as _
2023-05-27 01:33:19 +00:00
from judge.models import Problem, Profile, Submission, SubmissionTestCase
2020-01-21 06:35:58 +00:00
from judge.utils.celery import Progress
2022-05-14 17:57:27 +00:00
__all__ = ("apply_submission_filter", "rejudge_problem_filter", "rescore_problem")
2020-01-21 06:35:58 +00:00
2023-03-26 03:11:56 +00:00
def apply_submission_filter(queryset, id_range, languages, results, contest):
2020-01-21 06:35:58 +00:00
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)
2023-03-26 03:11:56 +00:00
if contest:
queryset = queryset.filter(contest_object=contest)
2020-01-21 06:35:58 +00:00
queryset = queryset.exclude(status__in=Submission.IN_PROGRESS_GRADING_STATUS)
return queryset
@shared_task(bind=True)
2022-05-14 17:57:27 +00:00
def rejudge_problem_filter(
2023-03-26 03:11:56 +00:00
self, problem_id, id_range=None, languages=None, results=None, contest=None
2022-05-14 17:57:27 +00:00
):
2020-01-21 06:35:58 +00:00
queryset = Submission.objects.filter(problem_id=problem_id)
2023-04-05 17:24:29 +00:00
queryset = apply_submission_filter(queryset, id_range, languages, results, contest)
2020-01-21 06:35:58 +00:00
rejudged = 0
2023-05-27 01:33:19 +00:00
with Progress(self, queryset.count() * 2) as p:
for submission in queryset:
SubmissionTestCase.objects.filter(submission_id=submission.id).delete()
rejudged += 1
if rejudged % 10 == 0:
p.done = rejudged
2020-01-21 06:35:58 +00:00
for submission in queryset.iterator():
2023-05-27 01:33:19 +00:00
submission.judge(rejudge=True, batch_rejudge=True, delete_testcases=False)
2020-01-21 06:35:58 +00:00
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)
2022-05-14 17:57:27 +00:00
with Progress(self, submissions.count(), stage=_("Modifying submissions")) as p:
2020-01-21 06:35:58 +00:00
rescored = 0
for submission in submissions.iterator():
2022-05-14 17:57:27 +00:00
submission.points = round(
submission.case_points / submission.case_total * problem.points
if submission.case_total
else 0,
1,
)
2020-01-21 06:35:58 +00:00
if not problem.partial and submission.points < problem.points:
submission.points = 0
2022-05-14 17:57:27 +00:00
submission.save(update_fields=["points"])
2020-01-21 06:35:58 +00:00
submission.update_contest()
rescored += 1
if rescored % 10 == 0:
p.done = rescored
2022-05-14 17:57:27 +00:00
with Progress(
self,
submissions.values("user_id").distinct().count(),
stage=_("Recalculating user points"),
) as p:
2020-01-21 06:35:58 +00:00
users = 0
2022-05-14 17:57:27 +00:00
profiles = Profile.objects.filter(
id__in=submissions.values_list("user_id", flat=True).distinct()
)
2020-01-21 06:35:58 +00:00
for profile in profiles.iterator():
profile._updating_stats_only = True
profile.calculate_points()
2022-05-14 17:57:27 +00:00
cache.delete("user_complete:%d" % profile.id)
cache.delete("user_attempted:%d" % profile.id)
2020-01-21 06:35:58 +00:00
users += 1
if users % 10 == 0:
p.done = users
return rescored