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)