Exemple #1
0
 def filter_visible_reports(self, request, submission, queryset):
     if is_contest_basicadmin(request) or is_contest_observer(request):
         return queryset
     return queryset.filter(
         status='ACTIVE',
         kind__in=self.get_visible_reports_kinds(request, submission),
     )
Exemple #2
0
 def has_change_permission(self, request, obj=None):
     if obj:
         return False
     # is_contest_observer() is required in here, because otherwise
     # observers get a 403 response. Any actions that modify submissions
     # will be blocked in get_actions()
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #3
0
 def has_change_permission(self, request, obj=None):
     if obj:
         return False
     # is_contest_observer() is required in here, because otherwise
     # observers get a 403 response. Any actions that modify submissions
     # will be blocked in get_actions()
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #4
0
    def can_generate_user_out(self, request, submission_report):
        """Determines if the current user is allowed to generate outs from
        ``submission_report``.

        Default implementations delegates to
        ``report_actions_config`` associated with the problem,
        :meth:`~ContestController.can_see_problem`,
        :meth:`~ContestController.filter_my_visible_submissions`,
        except for admins and observers, which get full access.
        """
        submission = submission_report.submission
        if is_contest_basicadmin(request) or is_contest_observer(request):
            return True
        if not has_report_actions_config(submission.problem_instance.problem):
            return False
        config = submission.problem_instance.problem.report_actions_config

        return (config.can_user_generate_outs
                and submission.user == request.user
                and self.can_see_problem(request, submission.problem_instance)
                and self.filter_visible_reports(
                    request,
                    submission,
                    SubmissionReport.objects.filter(id=submission_report.id),
                ).exists())
Exemple #5
0
 def test_utils(self):
     ofactory = partial(self.factory, self.observer)
     cfactory = partial(self.factory, self.cadmin)
     ufactory = partial(self.factory, User.objects.get(username='******'))
     self.assertFalse(can_enter_contest(ufactory(self.during)))
     self.assertTrue(is_contest_admin(cfactory(self.during)))
     self.assertTrue(can_enter_contest(cfactory(self.during)))
     self.assertTrue(is_contest_observer(ofactory(self.during)))
     self.assertTrue(can_enter_contest(ofactory(self.during)))
Exemple #6
0
    def get_default_submission_kind(self, request):
        """Returns default kind of newly created submission by the current user.

           The default implementation returns ``'IGNORED'`` for non-contestants.
           In other cases it returns ``'NORMAL'``.
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return 'IGNORED'
        return 'NORMAL'
Exemple #7
0
    def get_default_submission_kind(self, request):
        """Returns default kind of newly created submission by the current user.

           The default implementation returns ``'IGNORED'`` for non-contestants.
           In other cases it returns ``'NORMAL'``.
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return 'IGNORED'
        return 'NORMAL'
Exemple #8
0
def points_to_source_length_problem(request, problem):
    submissions = ProgramSubmission.objects.filter(
        problem_instance=problem,
        submissionreport__userresultforproblem__isnull=False)

    contest = request.contest
    controller = contest.controller

    if is_contest_admin(request) or is_contest_observer(request):
        visible_submissions = submissions
    else:
        visible_submissions = controller.filter_my_visible_submissions(
            request, submissions)

    data = []

    for s in submissions:
        record = {'x': s.source_length, 'y': int_score(s.score), 'url': ''}

        kwargs = {'submission_id': s.id, 'contest_id': contest.id}
        if visible_submissions.filter(id=s.id).exists():
            record['url'] = reverse('submission', kwargs=kwargs)
        elif controller.can_see_source(request, s.submission_ptr):
            record['url'] = reverse('show_submission_source', kwargs=kwargs)

        data.append(record)

    data = sorted(data)

    # Assumes that max_score is exactly the same for each submission
    max_score = None
    if submissions:
        score_reports = ScoreReport.objects.filter(
            submission_report__submission__in=submissions,
            submission_report__status='ACTIVE',
            submission_report__kind__in=('NORMAL', 'FULL'),
        )
        if score_reports:
            max_score = score_reports.latest('id').max_score
    max_score = int_score(max_score, 0)

    return {
        'plot_name': _("Points vs source length scatter"),
        'data': [data],
        'x_min': 0,
        'y_min': 0,
        'y_max': max_score,
        'titles': {
            'xAxis': _("Source length (bytes)"),
            'yAxis': _("Points"),
        },
        'series': [problem.short_name],
        'series_extra_options': [{
            'color': 'rgba(47, 126, 216, 0.5)'
        }],
    }
Exemple #9
0
def points_to_source_length_problem(request, problem):
    submissions = ProgramSubmission.objects.filter(
            problem_instance=problem,
            submissionreport__userresultforproblem__isnull=False)

    contest = request.contest
    controller = contest.controller

    if is_contest_admin(request) or is_contest_observer(request):
        visible_submissions = submissions
    else:
        visible_submissions = \
                controller.filter_my_visible_submissions(request, submissions)

    data = []

    for s in submissions:
        record = {'x': s.source_length,
                  'y': int_score(s.score),
                  'url': ''}

        kwargs = {'submission_id': s.id,
                  'contest_id': contest.id}
        if visible_submissions.filter(id=s.id).exists():
            record['url'] = reverse('submission', kwargs=kwargs)
        elif controller.can_see_source(request, s.submission_ptr):
            record['url'] = reverse('show_submission_source', kwargs=kwargs)

        data.append(record)

    data = sorted(data)

    # Assumes that max_score is exactly the same for each submission
    max_score = None
    if submissions:
        score_reports = ScoreReport.objects.filter(
                submission_report__submission__in=submissions,
                submission_report__status='ACTIVE',
                submission_report__kind__in=('NORMAL', 'FULL'))
        if score_reports:
            max_score = score_reports.latest('id').max_score
    max_score = int_score(max_score, 0)

    return {
        'plot_name': _("Points vs source length scatter"),
        'data': [data],
        'x_min': 0,
        'y_min': 0,
        'y_max': max_score,
        'titles': {
            'xAxis': _("Source length (bytes)"),
            'yAxis': _("Points"),
        },
        'series': [problem.short_name],
        'series_extra_options': [{'color': 'rgba(47, 126, 216, 0.5)'}],
    }
Exemple #10
0
def livedata_events_view(request, round_id):
    user_is_participant = \
        Q(submission__user__participant__contest_id=request.contest.id,
          submission__user__participant__status='ACTIVE')
    submission_ignored = Q(submission__kind='IGNORED')

    reports = SubmissionReport.objects \
        .filter(user_is_participant) \
        .exclude(submission_ignored) \
        .select_related('submission') \
        .prefetch_related('scorereport_set')

    if (is_contest_admin(request) or is_contest_observer(request)) and \
            'from' in request.GET:
        # Only admin/observer is allowed to specify 'from' parameter.
        start_time = datetime.datetime.utcfromtimestamp(
            int(request.GET['from'])).replace(tzinfo=utc)
        reports = reports.filter(creation_date__gte=start_time)

    round = get_object_or_404(request.contest.round_set.all(), pk=round_id)
    contest_start = round.start_date
    reports = reports.filter(submission__problem_instance__round=round)
    if is_contest_admin(request):
        freeze_time = None
    else:
        freeze_time = request.contest.controller.get_round_freeze_time(round)

    return [
        {
            'submissionId': 'START',
            'reportId': 'START',
            'teamId': 'START',
            'taskId': 'START',
            'submissionTimestamp': int(
                dateformat.format(request.timestamp, 'U')),
            'judgingTimestamp': int(dateformat.format(contest_start, 'U')),
            'result': 'CTRL',
        }
    ] + [{
        'submissionId':
        report.submission_id,
        'reportId':
        report.pk,
        'teamId':
        report.submission.user_id,
        'taskId':
        report.submission.problem_instance_id,
        'submissionTimestamp':
        int(dateformat.format(report.submission.date, 'U')),
        'judgingTimestamp':
        int(dateformat.format(report.creation_date, 'U')),
        'result':
        report.score_report.status if freeze_time is None or
        report.submission.date < freeze_time else RESULT_FOR_FROZEN_SUBMISSION,
    } for report in reports.order_by('creation_date')
         if report.score_report is not None]
Exemple #11
0
 def test_utils(self):
     ofactory = partial(self.factory, self.observer)
     cfactory = partial(self.factory, self.cadmin)
     ufactory = partial(self.factory,
                        User.objects.get(username='******'))
     self.assertFalse(can_enter_contest(ufactory(self.during)))
     self.assertTrue(is_contest_admin(cfactory(self.during)))
     self.assertTrue(can_enter_contest(cfactory(self.during)))
     self.assertTrue(is_contest_observer(ofactory(self.during)))
     self.assertTrue(can_enter_contest(ofactory(self.during)))
Exemple #12
0
    def results_visible(self, request, submission):
        normally = super(DisqualificationContestControllerMixin, self) \
            .results_visible(request, submission)

        if is_contest_admin(request) or is_contest_observer(request):
            return normally

        return normally and \
                not self.is_any_submission_to_problem_disqualified(
                    submission.user, submission.problem_instance)
Exemple #13
0
    def results_visible(self, request, submission):
        normally = super(DisqualificationContestControllerMixin, self) \
            .results_visible(request, submission)

        if is_contest_admin(request) or is_contest_observer(request):
            return normally

        return normally and \
                not self.is_any_submission_to_problem_disqualified(
                    submission.user, submission.problem_instance)
Exemple #14
0
 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
Exemple #15
0
 def _rounds_for_ranking(self, request, key=CONTEST_RANKING_KEY):
     can_see_all = is_contest_admin(request) or is_contest_observer(request)
     ccontroller = self.contest.controller
     queryset = self.contest.round_set.all()
     if key != CONTEST_RANKING_KEY:
         queryset = queryset.filter(id=key)
     for round in queryset:
         times = ccontroller.get_round_times(request, round)
         if can_see_all or times.results_visible(request.timestamp):
             yield round
Exemple #16
0
 def _rounds_for_ranking(self, request, key=CONTEST_RANKING_KEY):
     can_see_all = is_contest_admin(request) or is_contest_observer(request)
     ccontroller = self.contest.controller
     queryset = self.contest.round_set.all()
     if key != CONTEST_RANKING_KEY:
         queryset = queryset.filter(id=key)
     for round in queryset:
         times = ccontroller.get_round_times(request, round)
         if can_see_all or times.results_visible(request.timestamp):
             yield round
Exemple #17
0
 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
Exemple #18
0
    def _get_users_results(self, request, pis, results, rounds, users):
        contest = request.contest
        controller = contest.controller
        by_user = defaultdict(dict)
        for r in results:
            by_user[r.user_id][r.problem_instance_id] = r
        users = users.filter(id__in=by_user.keys())
        data = []
        all_rounds_trial = all(r.is_trial for r in rounds)
        for user in users.order_by('last_name', 'first_name', 'username'):
            by_user_row = by_user[user.id]
            user_results = []
            user_data = {
                'user': user,
                'results': user_results,
                'sum': None
            }

            submissions = Submission.objects.filter(
                    problem_instance__contest=contest)
            if is_contest_admin(request) or is_contest_observer(request):
                my_visible = submissions
            else:
                my_visible = controller.filter_my_visible_submissions(request,
                        submissions)

            for pi in pis:
                result = by_user_row.get(pi.id)
                if result and hasattr(result, 'submission_report') and \
                        hasattr(result.submission_report, 'submission'):
                    submission = result.submission_report.submission
                    kwargs = {'contest_id': contest.id,
                              'submission_id': submission.id}
                    if my_visible.filter(id=submission.id).exists():
                        result.url = reverse('submission', kwargs=kwargs)
                    elif controller.can_see_source(request, submission):
                        result.url = reverse('show_submission_source',
                                kwargs=kwargs)

                user_results.append(result)
                if result and result.score and \
                        (not pi.round.is_trial or all_rounds_trial):
                    if user_data['sum'] is None:
                        user_data['sum'] = result.score
                    else:
                        user_data['sum'] += result.score
            if user_data['sum'] is not None:
                # This rare corner case with sum being None may happen if all
                # user's submissions do not have scores (for example the
                # problems do not support scoring, or all the evaluations
                # failed with System Errors).
                if self._allow_zero_score() or user_data['sum'] != 0:
                    data.append(user_data)
        return data
Exemple #19
0
    def test_utils_archived(self):
        user = User.objects.get(pk=1001)
        contest = Contest.objects.get(pk="uc")

        request = RequestFactory().request()
        request.contest = contest
        request.user = user

        self.assertFalse(is_contest_admin(request))
        self.assertFalse(is_contest_basicadmin(request))
        self.assertTrue(is_contest_observer(request))
Exemple #20
0
    def can_see_source(self, request, submission):
        """Check if submission's source should be visible.
           :type submission: oioioi.contest.Submission

           Consider using filter_visible_sources instead, especially for batch
           queries.
        """
        qs = Submission.objects.filter(id=submission.id)
        if not (is_contest_admin(request) or is_contest_observer(request)) \
                and is_model_submission(submission):
            return False
        return self.filter_visible_sources(request, qs).exists()
Exemple #21
0
    def get_contest_participant_info_list(self, request, user):
        """Returns a list of tuples (priority, info).
           Each entry represents a fragment of HTML with information about the
           user's participation in the contest. This information will be
           visible for contest admins. It can be any information an application
           wants to add.

           The fragments are sorted by priority (descending) and rendered in
           that order.

           The default implementation returns basic info about the contestant:
           his/her full name, e-mail, the user id, his/her submissions and
           round time extensions.

           To add additional info from another application, override this
           method. For integrity, include the result of the parent
           implementation in your output.
        """
        res = [(100, render_to_string('contests/basic_user_info.html', {
                        'request': request,
                        'target_user_name': self.get_user_public_name(request,
                                                                      user),
                        'target_user': user,
                        'user': request.user}))]

        exts = RoundTimeExtension.objects.filter(user=user,
                round__contest=request.contest)
        if exts.exists():
            res.append((99,
                    render_to_string('contests/roundtimeextension_info.html', {
                            'request': request,
                            'extensions': exts,
                            'user': request.user})))

        if is_contest_basicadmin(request) or is_contest_observer(request):
            submissions = Submission.objects.filter(
                    problem_instance__contest=request.contest, user=user) \
                    .order_by('-date').select_related()

            if submissions.exists():
                submission_records = [submission_template_context(request, s)
                        for s in submissions]
                context = {
                    'submissions': submission_records,
                    'show_scores': True
                }
                rendered_submissions = render_to_string(
                        'contests/user_submissions_table.html',
                        context=context, request=request)
                res.append((50, rendered_submissions))

        return res
Exemple #22
0
    def get_contest_participant_info_list(self, request, user):
        """Returns a list of tuples (priority, info).
           Each entry represents a fragment of HTML with information about the
           user's participation in the contest. This information will be
           visible for contest admins. It can be any information an application
           wants to add.

           The fragments are sorted by priority (descending) and rendered in
           that order.

           The default implementation returns basic info about the contestant:
           his/her full name, e-mail, the user id, his/her submissions and
           round time extensions.

           To add additional info from another application, override this
           method. For integrity, include the result of the parent
           implementation in your output.
        """
        res = [(100, render_to_string('contests/basic_user_info.html', {
                        'request': request,
                        'target_user_name': self.get_user_public_name(request,
                                                                      user),
                        'target_user': user,
                        'user': request.user}))]

        exts = RoundTimeExtension.objects.filter(user=user,
                round__contest=request.contest)
        if exts.exists():
            res.append((99,
                    render_to_string('contests/roundtimeextension_info.html', {
                            'request': request,
                            'extensions': exts,
                            'user': request.user})))

        if is_contest_admin(request) or is_contest_observer(request):
            submissions = Submission.objects.filter(
                    problem_instance__contest=request.contest, user=user) \
                    .order_by('-date').select_related()

            if submissions.exists():
                submission_records = [submission_template_context(request, s)
                        for s in submissions]
                context = {
                    'submissions': submission_records,
                    'show_scores': True
                }
                rendered_submissions = render_to_string(
                        'contests/user_submissions_table.html',
                        context_instance=RequestContext(request, context))
                res.append((50, rendered_submissions))

        return res
Exemple #23
0
    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)

        return can_see_problem and (can_see_round_results or can_observe)
Exemple #24
0
    def filter_visible_sources(self, request, queryset):
        """Determines which sources the user could see.

           This usually involves cross-user privileges, like publicizing
           sources. Default implementations delegates to
           :meth:`~ContestController.filter_my_visible_submissions`, except for
           admins and observers, which get full access.

           Queryset's model should be oioioi.contest.Submission
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return queryset
        return self.filter_my_visible_submissions(request, queryset)
Exemple #25
0
    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)

        return can_see_problem and (can_see_round_results or can_observe)
Exemple #26
0
    def filter_visible_sources(self, request, queryset):
        """Determines which sources the user could see.

           This usually involves cross-user privileges, like publicizing
           sources. Default implementations delegates to
           :meth:`~ContestController.filter_my_visible_submissions`, except for
           admins and observers, which get full access.

           Queryset's model should be oioioi.contest.Submission
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return queryset
        return self.filter_my_visible_submissions(request, queryset)
Exemple #27
0
def livedata_events_view(request, round_id):
    user_is_participant = Q(
        submission__user__participant__contest_id=request.contest.id, submission__user__participant__status="ACTIVE"
    )
    submission_ignored = Q(submission__kind="IGNORED")

    reports = (
        SubmissionReport.objects.filter(user_is_participant)
        .exclude(submission_ignored)
        .select_related("submission")
        .prefetch_related("scorereport_set")
    )

    if (is_contest_admin(request) or is_contest_observer(request)) and "from" in request.GET:
        # Only admin/observer is allowed to specify 'from' parameter.
        start_time = datetime.datetime.utcfromtimestamp(int(request.GET["from"])).replace(tzinfo=utc)
        reports = reports.filter(creation_date__gte=start_time)

    round = get_object_or_404(request.contest.round_set.all(), pk=round_id)
    contest_start = round.start_date
    reports = reports.filter(submission__problem_instance__round=round)
    if is_contest_admin(request):
        freeze_time = None
    else:
        freeze_time = request.contest.controller.get_round_freeze_time(round)

    return [
        {
            "submissionId": "START",
            "reportId": "START",
            "teamId": "START",
            "taskId": "START",
            "submissionTimestamp": int(dateformat.format(request.timestamp, "U")),
            "judgingTimestamp": int(dateformat.format(contest_start, "U")),
            "result": "CTRL",
        }
    ] + [
        {
            "submissionId": report.submission_id,
            "reportId": report.pk,
            "teamId": report.submission.user_id,
            "taskId": report.submission.problem_instance_id,
            "submissionTimestamp": int(dateformat.format(report.submission.date, "U")),
            "judgingTimestamp": int(dateformat.format(report.creation_date, "U")),
            "result": report.score_report.status
            if freeze_time is None or report.submission.date < freeze_time
            else RESULT_FOR_FROZEN_SUBMISSION,
        }
        for report in reports.order_by("creation_date")
        if report.score_report is not None
    ]
    def can_see_source(self, request, submission):
        """Determines if the current user is allowed to see source
           of ``submission``.

           This usually involves cross-user privileges, like publicizing
           sources.
           Default implementations delegates to
           :meth:`~ContestController.filter_my_visible_submissions`, except for
           admins and observers, which get full access.
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return True
        queryset = Submission.objects.filter(id=submission.id)
        return self.filter_my_visible_submissions(request, queryset).exists()
Exemple #29
0
def livedata_events_view(request, round_id):
    user_is_participant = \
        Q(submission__user__participant__contest_id=request.contest.id,
          submission__user__participant__status='ACTIVE')
    submission_ignored = Q(submission__kind='IGNORED')

    reports = SubmissionReport.objects \
        .filter(user_is_participant) \
        .exclude(submission_ignored) \
        .select_related('submission') \
        .prefetch_related('scorereport_set')

    if (is_contest_admin(request) or is_contest_observer(request)) and \
            'from' in request.GET:
        # Only admin/observer is allowed to specify 'from' parameter.
        start_time = datetime.datetime.utcfromtimestamp(
                int(request.GET['from'])).replace(tzinfo=utc)
        reports = reports.filter(creation_date__gte=start_time)

    round = get_object_or_404(request.contest.round_set.all(), pk=round_id)
    contest_start = round.start_date
    reports = reports.filter(submission__problem_instance__round=round)
    if is_contest_admin(request):
        freeze_time = None
    else:
        freeze_time = request.contest.controller.get_round_freeze_time(round)

    return [{
        'submissionId': 'START',
        'reportId': 'START',
        'teamId': 'START',
        'taskId': 'START',
        'submissionTimestamp': int(dateformat.format(request.timestamp, 'U')),
        'judgingTimestamp': int(dateformat.format(contest_start, 'U')),
        'result': 'CTRL',
    }] + [{
        'submissionId': report.submission_id,
        'reportId': report.pk,
        'teamId': report.submission.user_id,
        'taskId': report.submission.problem_instance_id,
        'submissionTimestamp':
            int(dateformat.format(report.submission.date, 'U')),
        'judgingTimestamp': int(dateformat.format(report.creation_date, 'U')),
        'result':
            report.score_report.status
            if freeze_time is None or report.submission.date < freeze_time
            else RESULT_FOR_FROZEN_SUBMISSION,
    } for report in reports.order_by('creation_date')
        if report.score_report is not None]
Exemple #30
0
 def _rounds_for_ranking(self, request, key=CONTEST_RANKING_KEY):
     can_see_all = is_contest_admin(request) or is_contest_observer(request)
     ccontroller = self.contest.controller
     if not ccontroller.can_see_ranking(request):
         return
     queryset = self.contest.round_set.all()
     if key != CONTEST_RANKING_KEY:
         queryset = queryset.filter(id=key)
     if can_see_all:
         for round in queryset:
             yield round
     else:
         for round in queryset:
             rtimes = ccontroller.get_round_times(request, round)
             if not rtimes.is_future(request.timestamp):
                 yield round
Exemple #31
0
    def results_visible(self, request, submission):
        """Determines whether it is a good time to show the submission's
           results.

           This method is not used directly in any code outside of the
           controllers. It's a helper method used in a number of other
           controller methods, as described.

           The default implementations uses the round's
           :attr:`~oioioi.contests.models.Round.results_date`. If it's
           ``None``, results are not available. Admins are always shown the
           results.
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return True
        round = submission.problem_instance.round
        rtimes = self.get_round_times(request, round)
        return rtimes.results_visible(request.timestamp)
Exemple #32
0
    def results_visible(self, request, submission):
        """Determines whether it is a good time to show the submission's
        results.

        This method is not used directly in any code outside of the
        controllers. It's a helper method used in a number of other
        controller methods, as described.

        The default implementations uses the round's
        :attr:`~oioioi.contests.models.Round.results_date`. If it's
        ``None``, results are not available. Admins are always shown the
        results.
        """
        if is_contest_basicadmin(request) or is_contest_observer(request):
            return True
        round = submission.problem_instance.round
        rtimes = self.get_round_times(request, round)
        return rtimes.results_visible(request.timestamp)
Exemple #33
0
    def inner(request, round_id):
        should_cache = not is_contest_admin(request) and not is_contest_observer(request)
        if not should_cache:
            return view(request, round_id)

        cache = get_cache("default")
        cache_key = "%s/%s/%s" % (view.__name__, request.contest.id, round_id)
        result = cache.get(cache_key)
        if result is None:
            result = view(request, round_id)
            assert isinstance(result, HttpResponse)
            cache.set(
                cache_key,
                {"content": unicode(result.content), "content_type": result["Content-Type"]},
                settings.LIVEDATA_CACHE_TIMEOUT,
            )
        else:
            result = HttpResponse(result["content"], content_type=result["content_type"])
        return result
Exemple #34
0
    def inner(request, round_id):
        should_cache = not is_contest_admin(request) and \
                       not is_contest_observer(request)
        if not should_cache:
            return view(request, round_id)

        cache_key = '%s/%s/%s' % (view.__name__, request.contest.id, round_id)
        result = cache.get(cache_key)
        if result is None:
            result = view(request, round_id)
            assert isinstance(result, HttpResponse)
            cache.set(cache_key,
                    {'content': six.text_type(result.content),
                     'content_type': result['Content-Type']},
                    settings.LIVEDATA_CACHE_TIMEOUT)
        else:
            result = HttpResponse(result['content'],
                    content_type=result['content_type'])
        return result
Exemple #35
0
    def inner(request, round_id):
        should_cache = not is_contest_admin(request) and \
                       not is_contest_observer(request)
        if not should_cache:
            return view(request, round_id)

        cache_key = '%s/%s/%s' % (view.__name__, request.contest.id, round_id)
        result = cache.get(cache_key)
        if result is None:
            result = view(request, round_id)
            assert isinstance(result, HttpResponse)
            cache.set(
                cache_key, {
                    'content': six.text_type(result.content),
                    'content_type': result['Content-Type']
                }, settings.LIVEDATA_CACHE_TIMEOUT)
        else:
            result = HttpResponse(result['content'],
                                  content_type=result['content_type'])
        return result
Exemple #36
0
    def filter_visible_reports(self, request, submission, queryset):
        """Determines which reports the user should be able to see.

        It need not check whether the submission is visible to the user.

        The default implementation uses
        :meth:`~ContestController.results_visible`.

        :param request: Django request
        :param submission: instance of
                           :class:`~oioioi.contests.models.Submission`
        :param queryset: a queryset, initially filtered at least to
                           select only given submission's reports
        :returns: updated queryset
        """
        if is_contest_basicadmin(request) or is_contest_observer(request):
            return queryset
        if self.results_visible(request, submission):
            return queryset.filter(status='ACTIVE', kind='NORMAL')
        return queryset.none()
Exemple #37
0
    def filter_visible_reports(self, request, submission, queryset):
        """Determines which reports the user should be able to see.

           It need not check whether the submission is visible to the user.

           The default implementation uses
           :meth:`~ContestController.results_visible`.

           :param request: Django request
           :param submission: instance of
                              :class:`~oioioi.contests.models.Submission`
           :param queryset: a queryset, initially filtered at least to
                              select only given submission's reports
           :returns: updated queryset
        """
        if is_contest_admin(request) or is_contest_observer(request):
            return queryset
        if self.results_visible(request, submission):
            return queryset.filter(status='ACTIVE', kind='NORMAL')
        return queryset.none()
Exemple #38
0
    def get_cache_key(self, request, key, page=None):
        """Returns a cache key to be used with group_cache.

           When caching is enabled, every ranking is cached under a
           group corresponding to its contest. All cached rankings in a
           contest are invalidated when a submission is judged.

           The cache key for each ranking should be constructed in a
           way that allows to distinguish between its different
           versions.

           For example, you may want to display a live version of the
           ranking to the admins. Users on the other hand should see
           results only from the finished rounds.

           Default implementation takes into account a few basic
           permissions. It is suitable for the above example and many
           more typical scenarios. However, if the way you generate and
           display the ranking differs significantly from the default
           implementation, you should carefully inspect the code below
           and modify it as needed.

           The html code of each page of the ranking is cached separately.
           Also, the whole ranking is cached as an object.
           :param page specifies the page to be cached.
           If page=None then this method returns the cache_key for whole
           ranking.
        """

        if page is not None:
            try:
                page = int(page)
            except ValueError:
                page = 1

        cache_key = ':'.join([key, str(request.user.is_superuser),
                              str(request.user.is_authenticated()),
                              str(is_contest_admin(request)),
                              str(is_contest_observer(request)),
                              str(page)])
        return cache_key
Exemple #39
0
    def can_generate_user_out(self, request, submission_report):
        """Determines if the current user is allowed to generate outs from
           ``submission_report``.

           Default implementations delegates to
           ``report_actions_config`` associated with the problem,
           :meth:`~ContestController.can_see_problem`,
           :meth:`~ContestController.filter_my_visible_submissions`,
           except for admins and observers, which get full access.
        """
        submission = submission_report.submission
        if is_contest_admin(request) or is_contest_observer(request):
            return True
        if not has_report_actions_config(submission.problem_instance.problem):
            return False
        config = submission.problem_instance.problem.report_actions_config

        return (config.can_user_generate_outs and
                submission.user == request.user and
                self.can_see_problem(request, submission.problem_instance) and
                self.filter_visible_reports(request, submission,
                    SubmissionReport.objects.filter(id=submission_report.id))
                    .exists())
Exemple #40
0
 def can_see_ranking(self, request):
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #41
0
 def filter_visible_reports(self, request, submission, queryset):
     if is_contest_admin(request) or is_contest_observer(request):
         return queryset
     return queryset.filter(status='ACTIVE',
             kind__in=self.get_visible_reports_kinds(request, submission))
 def has_change_permission(self, request, obj=None):
     if obj:
         return False
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #43
0
 def can_see_stats(self, request):
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #44
0
 def can_see_ranking(self, request):
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #45
0
 def can_see_stats(self, request):
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #46
0
 def pi_results_visible(pi):
     return rtimes[pi.round].public_results_visible(request.timestamp) \
            or is_contest_admin(request) or is_contest_observer(request)
Exemple #47
0
 def _rounds_for_ranking(self, request, partial_key=CONTEST_RANKING_KEY):
     can_see_all = is_contest_admin(request) or is_contest_observer(request)
     return self._iter_rounds(can_see_all, request.timestamp, partial_key,
             request)
Exemple #48
0
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.
    """
    modules_with_subclasses = ['controllers']
    abstract = True
    PERMISSION_CHECKERS = [
        lambda request: 'admin'
        if is_contest_admin(request) else None, lambda request: 'observer'
        if is_contest_observer(request) else None, lambda request: 'regular'
    ]

    def get_partial_key(self, key):
        """Extracts partial key from a full key."""
        return key.split('#')[1]

    def replace_partial_key(self, key, new_partial):
        """Replaces partial key in a full key"""
        return key.split('#')[0] + '#' + new_partial

    def get_full_key(self, request, partial_key):
        """Returns a full key associated with request and partial_key"""
        for checker in self.PERMISSION_CHECKERS:
            res = checker(request)
            if res is not None:
                return res + '#' + partial_key

    def _key_permission(self, key):
        """Returns a permission level associated with given full key"""
        return key.split('#')[0]

    def is_admin_key(self, key):
        """Returns true if a given full key corresponds to users with
           administrative permissions.
        """
        return self._key_permission(key) == 'admin'

    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)``.
        """
        raise NotImplementedError

    def can_search_for_users(self):
        """Determines if in this ranking, searching for users is enabled."""
        return False

    def find_user_position(self, request, partial_key, user):
        """Returns user's position in the ranking.
           User should be an object of class User, not a string with username.

           If user is not in the ranking, None is returned.
        """
        raise NotImplementedError

    def get_rendered_ranking(self, request, partial_key):
        """Retrieves ranking generated by rankingsd.

           You should never override this function. It will be responsible for
           communication with rankingsd and use render_ranking for actual
           HTML generation. Feel free to override render_ranking to customize
           its logic.

           If the ranking is still being generated, or the user requested an
           invalid page, displays an appropriate message.
        """
        page_nr = request.GET.get('page', 1)
        key = self.get_full_key(request, partial_key)
        # Let's pretend the ranking is always up-to-date during tests.
        if getattr(settings, 'MOCK_RANKINGSD', False):
            data = self.serialize_ranking(key)
            html = self._render_ranking_page(key, data, page_nr)
            print(data)
            return mark_safe(html)

        ranking = Ranking.objects.get_or_create(contest=self.contest,
                                                key=key)[0]
        try:
            page = ranking.pages.get(nr=page_nr)
        except RankingPage.DoesNotExist:
            # The ranking hasn't been yet generated
            if page_nr == 1:
                return mark_safe(
                    render_to_string("rankings/generating_ranking.html"))
            return mark_safe(render_to_string("rankings/no_page.html"))

        context = {
            'ranking_html': mark_safe(page.data),
            'is_up_to_date': ranking.is_up_to_date(),
        }
        return mark_safe(
            render_to_string("rankings/rendered_ranking.html", context))

    def get_serialized_ranking(self, key):
        return self.serialize_ranking(key)

    def build_ranking(self, key):
        """Serializes data and renders html for given key.

           Results are processed using serialize_ranking, and then as many
           pages as needed are rendered. Returns a tuple containing serialized
           data and a list of strings, that are html code of ranking pages.
        """
        data = self.serialize_ranking(key)
        pages = []
        num_participants = len(data['rows'])
        on_page = data['participants_on_page']
        num_pages = (num_participants + on_page - 1) / on_page
        num_pages = max(num_pages, 1)  # Render at least a single page
        for i in range(1, num_pages + 1):
            pages.append(self._render_ranking_page(key, data, i))
        return data, pages

    def _fake_request(self, page):
        """Creates a fake request used to render ranking.

           Pagination engine requires access to request object, so it can
           extract page number from GET parameters.
        """
        fake_req = RequestFactory().get('/?page=' + str(page))
        fake_req.user = AnonymousUser()
        fake_req.contest = self.contest
        # This is required by dj-pagination
        # Normally they monkey patch this function in their middleware
        fake_req.page = lambda _: page
        return fake_req

    def _render_ranking_page(self, key, data, page):
        raise NotImplementedError

    def render_ranking_to_csv(self, request, partial_key):
        raise NotImplementedError

    def serialize_ranking(self, key):
        """Returns some data (representing ranking).
           This data will be used by :meth:`render_ranking`
           to generate the html code.
        """
        raise NotImplementedError
Exemple #49
0
 def _rounds_for_ranking(self, request, partial_key=CONTEST_RANKING_KEY):
     can_see_all = is_contest_admin(request) or is_contest_observer(request)
     return self._iter_rounds(can_see_all, request.timestamp, partial_key,
                              request)
Exemple #50
0
 def has_change_permission(self, request, obj=None):
     if obj:
         return False
     return is_contest_admin(request) or is_contest_observer(request)
Exemple #51
0
 def pi_results_visible(pi):
     return (rtimes[pi.round].public_results_visible(request.timestamp)
             or is_contest_admin(request)
             or is_contest_observer(request))