Cloned DMOJ
This commit is contained in:
parent
f623974b58
commit
49dc9ff10c
513 changed files with 132349 additions and 39 deletions
3
judge/tasks/__init__.py
Normal file
3
judge/tasks/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from judge.tasks.demo import *
|
||||
from judge.tasks.moss import *
|
||||
from judge.tasks.submission import *
|
25
judge/tasks/demo.py
Normal file
25
judge/tasks/demo.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import time
|
||||
|
||||
from celery import shared_task
|
||||
|
||||
from judge.utils.celery import Progress
|
||||
|
||||
__all__ = ('success', 'failure', 'progress')
|
||||
|
||||
|
||||
@shared_task
|
||||
def success():
|
||||
pass
|
||||
|
||||
|
||||
@shared_task
|
||||
def failure():
|
||||
raise RuntimeError('This task always fails.')
|
||||
|
||||
|
||||
@shared_task(bind=True)
|
||||
def progress(self, seconds=10):
|
||||
with Progress(self, seconds) as p:
|
||||
for i in range(seconds):
|
||||
time.sleep(1)
|
||||
p.did(1)
|
57
judge/tasks/moss.py
Normal file
57
judge/tasks/moss.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
from celery import shared_task
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.translation import gettext as _
|
||||
from moss import MOSS
|
||||
|
||||
from judge.models import Contest, ContestMoss, ContestParticipation, Submission
|
||||
from judge.utils.celery import Progress
|
||||
|
||||
__all__ = ('run_moss',)
|
||||
|
||||
|
||||
@shared_task(bind=True)
|
||||
def run_moss(self, contest_key):
|
||||
moss_api_key = settings.MOSS_API_KEY
|
||||
if moss_api_key is None:
|
||||
raise ImproperlyConfigured('No MOSS API Key supplied')
|
||||
|
||||
contest = Contest.objects.get(key=contest_key)
|
||||
ContestMoss.objects.filter(contest=contest).delete()
|
||||
|
||||
length = len(ContestMoss.LANG_MAPPING) * contest.problems.count()
|
||||
moss_results = []
|
||||
|
||||
with Progress(self, length, stage=_('Running MOSS')) as p:
|
||||
for problem in contest.problems.all():
|
||||
for dmoj_lang, moss_lang in ContestMoss.LANG_MAPPING:
|
||||
result = ContestMoss(contest=contest, problem=problem, language=dmoj_lang)
|
||||
|
||||
subs = Submission.objects.filter(
|
||||
contest__participation__virtual__in=(ContestParticipation.LIVE, ContestParticipation.SPECTATE),
|
||||
contest_object=contest,
|
||||
problem=problem,
|
||||
language__common_name=dmoj_lang,
|
||||
).order_by('-points').values_list('user__user__username', 'source__source')
|
||||
|
||||
if subs.exists():
|
||||
moss_call = MOSS(moss_api_key, language=moss_lang, matching_file_limit=100,
|
||||
comment='%s - %s' % (contest.key, problem.code))
|
||||
|
||||
users = set()
|
||||
|
||||
for username, source in subs:
|
||||
if username in users:
|
||||
continue
|
||||
users.add(username)
|
||||
moss_call.add_file_from_memory(username, source.encode('utf-8'))
|
||||
|
||||
result.url = moss_call.process()
|
||||
result.submission_count = len(users)
|
||||
|
||||
moss_results.append(result)
|
||||
p.did(1)
|
||||
|
||||
ContestMoss.objects.bulk_create(moss_results)
|
||||
|
||||
return len(moss_results)
|
67
judge/tasks/submission.py
Normal file
67
judge/tasks/submission.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
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
|
Loading…
Add table
Add a link
Reference in a new issue