Source code for oioioi.oi.controllers

import logging

from django.conf import settings
from django.db.models import Q
from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.template.response import TemplateResponse
from django.utils.translation import gettext_lazy as _

from oioioi.base.utils.query_helpers import Q_always_true
from oioioi.base.utils.redirect import safe_redirect
from oioioi.contests.controllers import (
    PastRoundsHiddenContestControllerMixin,
    PublicContestRegistrationController,
)
from oioioi.contests.models import Submission, SubmissionReport
from oioioi.contests.utils import (
    can_see_personal_data,
    is_contest_admin,
    is_contest_observer,
)
from oioioi.oi.models import OIRegistration
from oioioi.participants.controllers import (
    OnsiteContestControllerMixin,
    ParticipantsController,
)
from oioioi.participants.models import Participant
from oioioi.participants.utils import is_participant
from oioioi.programs.controllers import ProgrammingContestController
from oioioi.scoresreveal.utils import is_revealed

[docs]auditLogger = logging.getLogger(__name__ + ".audit")
[docs]class OIRegistrationController(ParticipantsController): @property
[docs] def form_class(self): from oioioi.oi.forms import OIRegistrationForm return OIRegistrationForm
@property
[docs] def participant_admin(self): from oioioi.oi.admin import OIRegistrationParticipantAdmin return OIRegistrationParticipantAdmin
@classmethod
[docs] def anonymous_can_enter_contest(cls): return True
# Redundant because of filter_visible_contests, but saves a db query
[docs] def can_enter_contest(self, request): return True
[docs] def visible_contests_query(self, request): return Q_always_true()
[docs] def can_register(self, request): return super().is_registration_open(request)
[docs] def can_unregister(self, request, participant): return False
[docs] def registration_view(self, request): participant = self._get_participant_for_form(request) if 'oi_oiregistrationformdata' in request.session: # pylint: disable=not-callable form = self.form_class(request.session['oi_oiregistrationformdata']) del request.session['oi_oiregistrationformdata'] else: form = self.get_form(request, participant) form.set_terms_accepted_text(self.get_terms_accepted_phrase()) if request.method == 'POST': if '_add_school' in request.POST: data = request.POST.copy() data.pop('_add_school', None) data.pop('csrfmiddlewaretoken', None) request.session['oi_oiregistrationformdata'] = data return redirect('add_school') elif form.is_valid(): # pylint: disable=maybe-no-member participant, created = Participant.objects.get_or_create( contest=self.contest, user=request.user ) auditLogger.info( "User %d (%s) registered in %s from IP %s UA: %s", request.user.id, request.user.username, self.contest.id, request.META.get('REMOTE_ADDR', '?'), request.META.get('HTTP_USER_AGENT', '?'), ) self.handle_validated_form(request, form, participant) if 'next' in request.GET: return safe_redirect(request, request.GET['next']) else: return redirect('default_contest_view', contest_id=self.contest.id) context = {'form': form, 'participant': participant} return TemplateResponse(request, self.registration_template, context)
[docs] def get_contest_participant_info_list(self, request, user): prev = super(OIRegistrationController, self).get_contest_participant_info_list( request, user ) if can_see_personal_data(request): sensitive_info = OIRegistration.objects.filter( participant__user=user, participant__contest=request.contest ) if sensitive_info.exists(): context = {'model': sensitive_info[0]} rendered_sensitive_info = render_to_string( 'oi/sensitive_participant_info.html', context=context, request=request, ) prev.append((2, rendered_sensitive_info)) return prev
[docs] def mixins_for_admin(self): from oioioi.participants.admin import TermsAcceptedPhraseAdminMixin return super(OIRegistrationController, self).mixins_for_admin() + ( TermsAcceptedPhraseAdminMixin, )
[docs] def can_change_terms_accepted_phrase(self, request): return not OIRegistration.objects.filter( participant__contest=request.contest ).exists()
[docs]class OIContestController(ProgrammingContestController):
[docs] description = _("Polish Olympiad in Informatics - Online")
[docs] create_forum = True
[docs] show_email_in_participants_data = True
[docs] def fill_evaluation_environ(self, environ, submission): super(OIContestController, self).fill_evaluation_environ(environ, submission) environ['group_scorer'] = 'oioioi.programs.utils.min_group_scorer' environ['test_scorer'] = 'oioioi.programs.utils.threshold_linear_test_scorer'
[docs] def registration_controller(self): return OIRegistrationController(self.contest)
[docs] def can_submit(self, request, problem_instance, check_round_times=True): if request.user.is_anonymous: return False if request.user.has_perm('contests.contest_admin', self.contest): return True if not is_participant(request): return False return super(OIContestController, self).can_submit( request, problem_instance, check_round_times )
[docs] def can_see_stats(self, request): return is_contest_admin(request) or is_contest_observer(request)
[docs] def should_confirm_submission_receipt(self, request, submission): return submission.kind == 'NORMAL' and request.user == submission.user
[docs] def update_user_result_for_problem(self, result): try: latest_submission = ( Submission.objects.filter(problem_instance=result.problem_instance) .filter(user=result.user) .filter(score__isnull=False) .exclude(status='CE') .filter(kind='NORMAL') .latest() ) try: report = SubmissionReport.objects.get( submission=latest_submission, status='ACTIVE', kind='NORMAL' ) except SubmissionReport.DoesNotExist: report = None result.score = latest_submission.score result.status = latest_submission.status result.submission_report = report except Submission.DoesNotExist: result.score = None result.status = None result.submission_report = None
[docs] def default_can_see_ranking(self, request): return is_contest_admin(request) or is_contest_observer(request)
[docs] def default_contestlogo_url(self): return '%(url)soi/logo.png' % {'url': settings.STATIC_URL}
[docs] def default_contesticons_urls(self): return [ '%(url)simages/menu/menu-icon-%(i)d.png' % {'url': settings.STATIC_URL, 'i': i} for i in range(1, 4) ]
[docs]class OIOnsiteContestController(OIContestController):
[docs] description = _("Polish Olympiad in Informatics - Onsite")
OIOnsiteContestController.mix_in(OnsiteContestControllerMixin) OIOnsiteContestController.mix_in(PastRoundsHiddenContestControllerMixin)
[docs]class OIFinalOnsiteContestController(OIOnsiteContestController):
[docs] description = _("Polish Olympiad in Informatics - Onsite - Finals")
[docs] def can_see_submission_score(self, request, submission): return True
[docs] def update_user_result_for_problem(self, result): submissions = ( Submission.objects.filter(problem_instance=result.problem_instance) .filter(user=result.user) .filter(score__isnull=False) .exclude(status='CE') .filter(kind='NORMAL') ) if submissions: max_submission = submissions.order_by('-score')[0] try: report = SubmissionReport.objects.get( submission=max_submission, status='ACTIVE', kind='NORMAL' ) except SubmissionReport.DoesNotExist: report = None result.score = max_submission.score result.status = max_submission.status result.submission_report = report else: result.score = None result.status = None result.submission_report = None
[docs]class BOIOnsiteContestController(OIOnsiteContestController):
[docs] description = _("Baltic Olympiad in Informatics")
[docs] create_forum = False
[docs] def can_see_test_comments(self, request, submissionreport): submission = submissionreport.submission return is_contest_admin(request) or self.results_visible(request, submission)
[docs] def reveal_score(self, request, submission): super(BOIOnsiteContestController, self).reveal_score(request, submission) self.update_user_results(submission.user, submission.problem_instance)
[docs] def update_user_result_for_problem(self, result): try: submissions = ( Submission.objects.filter(problem_instance=result.problem_instance) .filter(user=result.user) .filter(score__isnull=False) .exclude(status='CE') .filter(kind='NORMAL') ) chosen_submission = submissions.latest() revealed = submissions.filter(revealed__isnull=False) if revealed: max_revealed = revealed.order_by('-score')[0] if max_revealed.score > chosen_submission.score: chosen_submission = max_revealed try: report = SubmissionReport.objects.get( submission=chosen_submission, status='ACTIVE', kind='NORMAL' ) except SubmissionReport.DoesNotExist: report = None result.score = chosen_submission.score result.status = chosen_submission.status result.submission_report = report except Submission.DoesNotExist: result.score = None result.status = None result.submission_report = None
[docs] def get_visible_reports_kinds(self, request, submission): if is_revealed(submission) or self.results_visible(request, submission): return ['USER_OUTS', 'INITIAL', 'NORMAL'] else: return ['USER_OUTS', 'INITIAL']
[docs] def can_print_files(self, request): return True
[docs] def default_contestlogo_url(self): return None
[docs] def default_contesticons_urls(self): return []
[docs] def fill_evaluation_environ(self, environ, submission): super(BOIOnsiteContestController, self).fill_evaluation_environ( environ, submission ) environ['test_scorer'] = 'oioioi.programs.utils.discrete_test_scorer'
[docs]class BOIOnlineContestController(BOIOnsiteContestController):
[docs] description = _("Baltic Olympiad in Informatics - online")
[docs] create_forum = False
[docs] def registration_controller(self): return PublicContestRegistrationController(self.contest)
[docs] def is_onsite(self): return False