Cloned DMOJ

This commit is contained in:
thanhluong 2020-01-21 15:35:58 +09:00
parent f623974b58
commit 49dc9ff10c
513 changed files with 132349 additions and 39 deletions

3
judge/tasks/__init__.py Normal file
View 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
View 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
View 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
View 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