def test_order_rounds_by_focus(self): r1 = Round(start_date=datetime(2012, 1, 1, 8, 0), end_date= datetime(2012, 1, 1, 10, 0)) r2 = Round(start_date=datetime(2012, 1, 1, 9, 59), end_date= datetime(2012, 1, 1, 11, 00)) r3 = Round(start_date=datetime(2012, 1, 2, 8, 0), end_date= datetime(2012, 1, 2, 10, 0)) rounds = [r1, r2, r3] controller = ContestController(None) class FakeRequest(object): def __init__(self, timestamp): self.timestamp = timestamp self.user = AnonymousUser() for date, expected_order in ( (datetime(2011, 1, 1), [r1, r2, r3]), (datetime(2012, 1, 1, 7, 0), [r1, r2, r3]), (datetime(2012, 1, 1, 7, 55), [r1, r2, r3]), (datetime(2012, 1, 1, 9, 40), [r1, r2, r3]), (datetime(2012, 1, 1, 9, 45), [r2, r1, r3]), (datetime(2012, 1, 1, 9, 59, 29), [r2, r1, r3]), (datetime(2012, 1, 1, 9, 59, 31), [r1, r2, r3]), (datetime(2012, 1, 1, 10, 0, 1), [r2, r3, r1]), (datetime(2012, 1, 1, 11, 0, 1), [r2, r3, r1]), (datetime(2012, 1, 2, 2, 0, 1), [r3, r2, r1]), (datetime(2012, 1, 2, 2, 7, 55), [r3, r2, r1]), (datetime(2012, 1, 2, 2, 9, 0), [r3, r2, r1]), (datetime(2012, 1, 2, 2, 11, 0), [r3, r2, r1])): self.assertEqual(controller.order_rounds_by_focus( FakeRequest(date), rounds), expected_order)
def render_report(self, request, report): if report.kind == 'FAILURE': return ContestController.render_report(self, request, report) score_report = ScoreReport.objects.get(submission_report=report) compilation_report = \ CompilationReport.objects.get(submission_report=report) test_reports = TestReport.objects.filter(submission_report=report) \ .order_by('test__order', 'test_group', 'test_name') group_reports = GroupReport.objects.filter(submission_report=report) show_scores = any(gr.score is not None for gr in group_reports) group_reports = dict((g.group, g) for g in group_reports) groups = [] for group_name, tests in itertools.groupby(test_reports, attrgetter('test_group')): groups.append({ 'tests': list(tests), 'report': group_reports[group_name] }) return render_to_string( 'programs/report.html', context_instance=RequestContext( request, { 'report': report, 'score_report': score_report, 'compilation_report': compilation_report, 'groups': groups, 'show_scores': show_scores }))
def test_order_rounds_by_focus(self): r1 = Round(start_date=datetime(2012, 1, 1, 8, 0), end_date=datetime(2012, 1, 1, 10, 0)) r2 = Round(start_date=datetime(2012, 1, 1, 9, 59), end_date=datetime(2012, 1, 1, 11, 00)) r3 = Round(start_date=datetime(2012, 1, 2, 8, 0), end_date=datetime(2012, 1, 2, 10, 0)) rounds = [r1, r2, r3] controller = ContestController(None) class FakeRequest(object): def __init__(self, timestamp): self.timestamp = timestamp for date, expected_order in ((datetime(2011, 1, 1), [r1, r2, r3]), (datetime(2012, 1, 1, 7, 0), [r1, r2, r3]), (datetime(2012, 1, 1, 7, 55), [r1, r2, r3]), (datetime(2012, 1, 1, 9, 40), [r1, r2, r3]), (datetime(2012, 1, 1, 9, 45), [r2, r1, r3]), (datetime(2012, 1, 1, 9, 59, 29), [r2, r1, r3]), (datetime(2012, 1, 1, 9, 59, 31), [r1, r2, r3]), (datetime(2012, 1, 1, 10, 0, 1), [r2, r3, r1]), (datetime(2012, 1, 1, 11, 0, 1), [r2, r3, r1]), (datetime(2012, 1, 2, 2, 0, 1), [r3, r2, r1]), (datetime(2012, 1, 2, 2, 7, 55), [r3, r2, r1]), (datetime(2012, 1, 2, 2, 9, 0), [r3, r2, r1]), (datetime(2012, 1, 2, 2, 11, 0), [r3, r2, r1])): self.assertEqual( controller.order_rounds_by_focus(FakeRequest(date), rounds), expected_order)
def render_report(self, request, report): if report.kind == 'FAILURE': return ContestController.render_report(self, request, report) score_report = ScoreReport.objects.get(submission_report=report) compilation_report = \ CompilationReport.objects.get(submission_report=report) test_reports = TestReport.objects.filter(submission_report=report) \ .order_by('test_group', 'test_name') group_reports = GroupReport.objects.filter(submission_report=report) group_reports = dict((g.group, g) for g in group_reports) groups = [] for group_name, tests in itertools.groupby(test_reports, attrgetter('test_group')): groups.append({'tests': list(tests), 'report': group_reports[group_name]}) return render_to_string('programs/report.html', context_instance=RequestContext(request, {'report': report, 'score_report': score_report, 'compilation_report': compilation_report, 'groups': groups}))
from django.template.loader import render_to_string from oioioi.contests.controllers import ContestController from oioioi.questions.views import messages_template_context, visible_messages class QuestionsContestControllerMixin(object): """ContestController mixin that adds participants' questions to his info. """ def get_contest_participant_info_list(self, request, user): messages = messages_template_context(request, visible_messages(request, author=user)) prev = super(QuestionsContestControllerMixin, self) \ .get_contest_participant_info_list(request, user) if messages: prev.append((30, render_to_string('questions/user_list_table.html', {'contest': request.contest, 'hide_author': True, 'records': messages, 'user': request.user}))) return prev ContestController.mix_in(QuestionsContestControllerMixin)
from django.template.loader import render_to_string from oioioi.contests.controllers import ContestController from oioioi.questions.views import messages_template_context, visible_messages class QuestionsContestControllerMixin(object): """ContestController mixin that adds participants' questions to his info. """ def get_contest_participant_info_list(self, request, user): messages = messages_template_context( request, visible_messages(request, author=user)) prev = super(QuestionsContestControllerMixin, self) \ .get_contest_participant_info_list(request, user) if messages: prev.append((30, render_to_string( 'questions/user_list_table.html', { 'contest': request.contest, 'hide_author': True, 'records': messages, 'user': request.user }))) return prev ContestController.mix_in(QuestionsContestControllerMixin)
@request_cached def anonymous_participants(request): if not hasattr(request, 'contest'): return frozenset({}) return frozenset((p.user for p in Participant.objects .filter(contest=request.contest, anonymous=True) .select_related('user'))) class EmailShowContestControllerMixin(object): """Contest controller defines whether in participants' data view email should be shown. That is a case in OI-type contest. """ show_email_in_participants_data = False ContestController.mix_in(EmailShowContestControllerMixin) class AnonymousContestControllerMixin(object): def get_user_public_name(self, request, user): assert self.contest == request.contest if request.user.is_superuser or can_see_personal_data(request) \ or not user in anonymous_participants(request): return get_user_display_name(user) else: return user.username def get_contest_participant_info_list(self, request, user): prev = super(AnonymousContestControllerMixin, self).\ get_contest_participant_info_list(request, user) try:
function. The default implementation returns None. """ return None def default_contestlogo_link(self): """Returns a contest logo link. If a contest admin specifies a contest logo link in the contest settings view, it will be used instead of the one returned by this function. The default implementation returns an empty string. """ return '' def default_contesticons_urls(self): """Returns a list of URLs of images which will be used to decorate the user side menu. If a contest admin adds some icon urls in the contest settings view, they will be used instead of the urls returned by this function. The default implementation returns an empty list. """ return [] ContestController.mix_in(LogoContestControllerMixin)
from oioioi.contests.controllers import ContestController class PrintingContestControllerMixin(object): """Disallow printing by default.""" def can_print_files(self, request): return False ContestController.mix_in(PrintingContestControllerMixin)
from django.contrib.auth.models import User from oioioi.base.utils import RegisteredSubclassesBase, ObjectWithMixins from oioioi.contests.models import ProblemInstance, UserResultForProblem from oioioi.contests.controllers import ContestController from oioioi.contests.utils import is_contest_admin, is_contest_observer CONTEST_RANKING_KEY = 'c' class RankingMixinForContestController(object): def ranking_controller(self): """Return the actual :class:`RankingController` for the contest.""" return DefaultRankingController(self.contest) ContestController.mix_in(RankingMixinForContestController) class RankingController(RegisteredSubclassesBase, ObjectWithMixins): modules_with_subclasses = ['controllers'] abstract = True def __init__(self, contest): self.contest = contest def available_rankings(self, request): """Returns a list of available rankings. Each ranking is a pair ``(key, description)``. """
from oioioi.contests.controllers import ContestController class LivedataContestControllerMixin(object): """ContestController mixin that sets a default setting for livedata visibility. """ def can_see_livedata(self, request): return False ContestController.mix_in(LivedataContestControllerMixin)
from django.core.urlresolvers import reverse from oioioi.contests.controllers import ContestController from oioioi.contests.utils import can_enter_contest class DashboardDefaultViewMixin(object): def default_view(self, request): if request.contest and can_enter_contest(request): return reverse('contest_dashboard', kwargs={'contest_id': self.contest.id}) else: return super(DashboardDefaultViewMixin, self).default_view(request) ContestController.mix_in(DashboardDefaultViewMixin)
:return: Unicode containing HTML. """ raise NotImplementedError def can_see_stats(self, request): """Determines if statistics should be shown""" if is_contest_admin(request) or is_contest_observer(request): return True try: sconfig = request.contest.statistics_config return sconfig.visible_to_users and \ request.timestamp >= sconfig.visibility_date except StatisticsConfig.DoesNotExist: return False ContestController.mix_in(StatisticsMixinForContestController) class StatisticsMixinForProgrammingContestController(object): def can_see_problem_statistics(self, request, pi): controller = pi.controller rtimes = rounds_times(request) can_see_problem = controller.can_see_problem(request, pi) if pi.round: can_see_round_results = rtimes[pi.round].public_results_visible( request.timestamp) else: can_see_round_results = False can_observe = is_contest_admin(request) or is_contest_observer(request)
super(ProblemExperienceMixinForContestController, self)\ .submission_judged(submission, rejudged) try: report = SubmissionReport.objects.get( userresultforproblem__user=submission.user, userresultforproblem__problem_instance= submission.problem_instance ) PROBLEM_EXPERIENCE_SOURCE.handle_submission_report(report) except SubmissionReport.DoesNotExist: pass # Possible in tests ContestController.mix_in(ProblemExperienceMixinForContestController) class TaskSuggestionController(ObjectWithMixins): """Since we're collecting some data about the user we can somehow suggest a task for him to complete on theirs learning level, this controller is the API. To provide your implementation you should mix-in with this class and override suggest_task which should return a suggested problem for the user. You might want to also call super and do something with the task you got from a mixed-in object higher in hierarchy, but it's not required Warning though, this controller might return None if no task is suggested eg. no tasks in the database """
raise forms.ValidationError(_( "Team does not exist")) form.clean_user = clean_user else: form.fields['team'] = forms.CharField( initial=tm.team.name, label=_("Team name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), help_text=_("You are in the team, but you are also the " "admin, so you can send solution as the " "team user or as yourself.")) except TeamMembership.DoesNotExist: pass def create_submission(self, request, problem_instance, form_data, **kwargs): submission = super(TeamsMixinForContestController, self) \ .create_submission(request, problem_instance, form_data, **kwargs) if not is_contest_admin: try: tm = TeamMembership.objects.get(user=request.user, team__contest=request.contest) submission.user = tm.team.user submission.save() except TeamMembership.DoesNotExist: pass return submission ContestController.mix_in(TeamsMixinForContestController)
def render_report_failure(self, request, report): return ContestController.render_report(self, request, report)
from oioioi.contests.controllers import ContestController from oioioi.participants.controllers import OnsiteRegistrationController from oioioi.participants.utils import is_onsite_contest class IpAuthSyncControllerMixin(object): def mixins_for_admin(self): from oioioi.ipauthsync.admin import \ ContestAdminWithIpAuthSyncInlineMixin mixins = super(IpAuthSyncControllerMixin, self) \ .mixins_for_admin() if is_onsite_contest(self.contest): mixins = mixins + (ContestAdminWithIpAuthSyncInlineMixin,) return mixins ContestController.mix_in(IpAuthSyncControllerMixin) class IpAuthSyncRegistrationControllerMixin(object): def ipauthsync_validate_ip(self, region, ip, user): """Validates IP reported by a region server. Should raise an exception if the returned IP does not look like a correct IP address from the given region. """ pass OnsiteRegistrationController.mix_in(IpAuthSyncRegistrationControllerMixin)
If a contest admin specifies a contest logo URL in the contest settings view, it will be used instead of the one returned by this function. The default implementation returns None. """ return None def default_contestlogo_link(self): """Returns a contest logo link. If a contest admin specifies a contest logo link in the contest settings view, it will be used instead of the one returned by this function. The default implementation returns an empty string. """ return '' def default_contesticons_urls(self): """Returns a list of URLs of images which will be used to decorate the user side menu. If a contest admin adds some icon urls in the contest settings view, they will be used instead of the urls returned by this function. The default implementation returns an empty list. """ return [] ContestController.mix_in(LogoContestControllerMixin)
""" raise NotImplementedError def can_see_stats(self, request): """Determines if statistics should be shown""" if is_contest_admin(request) or is_contest_observer(request): return True try: sconfig = request.contest.statistics_config return (sconfig.visible_to_users and request.timestamp >= sconfig.visibility_date) except StatisticsConfig.DoesNotExist: return False ContestController.mix_in(StatisticsMixinForContestController) class StatisticsMixinForProgrammingContestController(object): def can_see_problem_statistics(self, request, pi): controller = pi.controller rtimes = rounds_times(request, self.contest) can_see_problem = controller.can_see_problem(request, pi) if pi.round: can_see_round_results = rtimes[pi.round].public_results_visible( request.timestamp) else: can_see_round_results = False can_observe = is_contest_admin(request) or is_contest_observer(request)
from django.core.urlresolvers import reverse from oioioi.contests.controllers import ContestController class DashboardDefaultViewMixin(object): def default_view(self, request): if request.user.is_authenticated(): return reverse('contest_dashboard', kwargs={'contest_id': self.contest.id}) else: return super(DashboardDefaultViewMixin, self).default_view(request) ContestController.mix_in(DashboardDefaultViewMixin)
class RankingMixinForContestController(object): """ContestController mixin that sets up rankings app. """ def ranking_controller(self): """Return the actual :class:`RankingController` for the contest.""" return DefaultRankingController(self.contest) def update_user_results(self, user, problem_instance, *args, **kwargs): super(RankingMixinForContestController, self) \ .update_user_results(user, problem_instance, *args, **kwargs) Ranking.invalidate_contest(problem_instance.round.contest) ContestController.mix_in(RankingMixinForContestController) class RankingController(RegisteredSubclassesBase, ObjectWithMixins): """Ranking system uses two types of keys: "partial key"s and "full key"s. Please note that full keys are abbreviated in the code as "key"s. A pair (request, partial_key) should allow to build a full key, while a partial_key can always be extracted from the full key. partial keys identify the rounds to display and are used everywhere outside controllers and rankingsd (e.g. in views and urls). However, the actual ranking contents can depend on many other factors, like user permissions. This was the reason for introduction of full keys, which are always sufficient to choose the right data for serialization and display. """
submissions = (Submission.objects.filter( problem_instance__contest=request.contest, user=user).order_by('-date').select_related()) info_list = super(DisqualificationContestControllerMixin, self).get_contest_participant_info_list( request, user) disqualification = self.render_disqualifications( request, user, submissions) if disqualification: info_list.append((75, disqualification)) return info_list ContestController.mix_in(DisqualificationContestControllerMixin) class DisqualificationProgrammingContestControllerMixin(object): """ContestController mixin that renders submission disqualification info.""" def render_submission(self, request, submission): prev = super(DisqualificationProgrammingContestControllerMixin, self).render_submission(request, submission) if self.is_submission_disqualified(submission) or ( is_contest_admin(request) and self.has_disqualification_history(submission)): return prev + self.render_submission_disqualifiaction( request, submission) return prev
def anonymous_participants(request): if not hasattr(request, 'contest'): return frozenset({}) return frozenset((p.user for p in Participant.objects.filter( contest=request.contest, anonymous=True).select_related('user'))) class EmailShowContestControllerMixin(object): """Contest controller defines whether in participants' data view email should be shown. That is a case in OI-type contest. """ show_email_in_participants_data = False ContestController.mix_in(EmailShowContestControllerMixin) class AnonymousContestControllerMixin(object): """ContestController mixin that adds participants info for anonymous contests. """ def get_user_public_name(self, request, user): assert self.contest == request.contest if request.user.is_superuser or can_see_personal_data(request) \ or user not in anonymous_participants(request): return get_user_display_name(user) else: return user.username def get_contest_participant_info_list(self, request, user):
from oioioi.participants.controllers import OnsiteRegistrationController from oioioi.participants.utils import is_onsite_contest class IpAuthSyncControllerMixin(object): """ContestController mixin that sets up the ipauthsync app.""" def mixins_for_admin(self): from oioioi.ipauthsync.admin import ContestAdminWithIpAuthSyncInlineMixin mixins = super(IpAuthSyncControllerMixin, self).mixins_for_admin() if is_onsite_contest(self.contest): mixins = mixins + (ContestAdminWithIpAuthSyncInlineMixin, ) return mixins ContestController.mix_in(IpAuthSyncControllerMixin) class IpAuthSyncRegistrationControllerMixin(object): """RegistrationController mixin that adds a functionality to validate IP address. """ def ipauthsync_validate_ip(self, region, ip, user): """Validates IP reported by a region server. Should raise an exception if the returned IP does not look like a correct IP address from the given region. """ pass
def get_contest_participant_info_list(self, request, user): submissions = Submission.objects.filter( problem_instance__contest=request.contest, user=user) \ .order_by('-date').select_related() info_list = super(DisqualificationContestControllerMixin, self) \ .get_contest_participant_info_list(request, user) disqualification = self.render_disqualifications(request, user, submissions) if disqualification: info_list.append((75, disqualification)) return info_list ContestController.mix_in(DisqualificationContestControllerMixin) class DisqualificationProgrammingContestControllerMixin(object): """ContestController mixin that renders submission disqualification info. """ def render_submission(self, request, submission): prev = super(DisqualificationProgrammingContestControllerMixin, self) \ .render_submission(request, submission) if self.is_submission_disqualified(submission) or \ (is_contest_admin(request) and self.has_disqualification_history(submission)): return prev + self.render_submission_disqualifiaction(request, submission)
form.clean_user = clean_user else: form.fields['team'] = forms.CharField( initial=tm.team.name, label=_("Team name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), help_text=_("You are in the team, but you are also the " "admin, so you can send solution as the " "team user or as yourself.")) except TeamMembership.DoesNotExist: pass def create_submission(self, request, problem_instance, form_data, **kwargs): submission = super(TeamsMixinForContestController, self) \ .create_submission(request, problem_instance, form_data, **kwargs) if not is_contest_admin: try: tm = TeamMembership.objects.get(user=request.user, team__contest=request.contest) submission.user = tm.team.user submission.save() except TeamMembership.DoesNotExist: pass return submission ContestController.mix_in(TeamsMixinForContestController)
from oioioi.contests.controllers import ContestController from oioioi.forum.models import Forum class ContestControllerWithForum(object): """Contest controller defines whether this particular contests needs forum application. Set True in a contest controller, if you want to let the participants use your forum. Do not change it here! This requires adding 'oioioi.forum' in Installed_apps in your settings.py """ create_forum = True def adjust_contest(self): super(ContestControllerWithForum, self).adjust_contest() try: forum = self.contest.forum except: forum = Forum(contest=self.contest) forum.save() ContestController.mix_in(ContestControllerWithForum)
from oioioi.contests.controllers import ContestController from oioioi.forum.models import Forum class ContestControllerWithForum(object): """Contest controller defines whether this particular contests needs forum application. Set True in a contest controller, if you want to let the participants use your forum. Do not change it here! This requires adding 'oioioi.forum' in Installed_apps in your settings.py """ create_forum = True def adjust_contest(self): super(ContestControllerWithForum, self).adjust_contest() Forum.objects.get_or_create(contest=self.contest) ContestController.mix_in(ContestControllerWithForum)
return frozenset((p.user for p in Participant.objects .filter(contest=request.contest, anonymous=True) .select_related('user'))) class AnonymousContestControllerMixin(object): def get_user_public_name(self, request, user): assert self.contest == request.contest if request.user.is_superuser or can_see_personal_data(request) \ or not user in anonymous_participants(request): return get_user_display_name(user) else: return user.username def get_contest_participant_info_list(self, request, user): prev = super(AnonymousContestControllerMixin, self).\ get_contest_participant_info_list(request, user) try: part = Participant.objects.get(user=user, contest=request.contest) context = {'participant': part} rendered_info = render_to_string( 'participants/participant_info.html', context_instance=RequestContext(request, context)) prev.append((98, rendered_info)) except Participant.DoesNotExist: pass return prev ContestController.mix_in(AnonymousContestControllerMixin)