Пример #1
0
    def statistics_available_plots(self, request, category, object):
        """Available plots for given object in given category.
           Does not check user's permission for viewing those statistics."""

        result = []
        rtimes = rounds_times(request)

        def plot_kind(name, object):
            return (statistics_plot_kinds[name], object)

        def pi_results_visible(pi):
            return rtimes[pi.round].public_results_visible(request.timestamp) \
                   or is_contest_admin(request) or is_contest_observer(request)

        if category == 'CONTEST':
            if not object:
                object = request.contest

            result.append(plot_kind('SUBMISSIONS_HISTOGRAM_CONTEST', object))

            pis = visible_problem_instances(request)

            # Do not add this plot if it would be empty.
            if any(pi_results_visible(pi) and not pi.round.is_trial
                   for pi in pis):
                result.append(plot_kind('POINTS_HISTOGRAM_CONTEST', object))

        if category == 'PROBLEM':
            result.append(plot_kind('POINTS_HISTOGRAM_PROBLEM', object))
            result.append(plot_kind('POINTS_TABLE_PROBLEM', object))
            result.append(plot_kind('POINTS_TO_SOURCE_LENGTH_PROBLEM', object))
            result.append(plot_kind('TEST_SCORES_TABLE_PROBLEM', object))

        return result
Пример #2
0
    def statistics_available_plots(self, request, category, object):
        """Available plots for given object in given category.
           Does not check user's permission for viewing those statistics."""

        result = []
        rtimes = rounds_times(request, self.contest)

        def plot_kind(name, object):
            return (statistics_plot_kinds[name], object)

        def pi_results_visible(pi):
            return rtimes[pi.round].public_results_visible(request.timestamp) \
                   or is_contest_admin(request) or is_contest_observer(request)

        if category == 'CONTEST':
            if not object:
                object = request.contest

            result.append(plot_kind('SUBMISSIONS_HISTOGRAM_CONTEST', object))

            pis = visible_problem_instances(request)

            # Do not add this plot if it would be empty.
            if any(
                    pi_results_visible(pi) and not pi.round.is_trial
                    for pi in pis):
                result.append(plot_kind('POINTS_HISTOGRAM_CONTEST', object))

        if category == 'PROBLEM':
            result.append(plot_kind('POINTS_HISTOGRAM_PROBLEM', object))
            result.append(plot_kind('POINTS_TABLE_PROBLEM', object))
            result.append(plot_kind('POINTS_TO_SOURCE_LENGTH_PROBLEM', object))
            result.append(plot_kind('TEST_SCORES_TABLE_PROBLEM', object))

        return result
Пример #3
0
def _last_finished_round_id(request):
    past_rounds = [rt for rt in rounds_times(request).iteritems()
                   if rt[1].is_past(request.timestamp)]
    if not past_rounds:
        return None
    last_round = max(past_rounds, key=lambda x: x[1].end)
    return last_round[0].id
Пример #4
0
def contest_dashboard_view(request, round_pk=None):
    messages = messages_template_context(request, visible_messages(request))[
               :NUMBER_OF_RECENT_ACTIONS]

    queryset = Submission.objects \
        .filter(problem_instance__contest=request.contest) \
        .order_by('-date') \
        .select_related('user', 'problem_instance',
                        'problem_instance__contest',
                        'problem_instance__round',
                        'problem_instance__problem')

    ss = [submission_template_context(request, s) for s in
          queryset[:NUMBER_OF_RECENT_ACTIONS]]

    rtimes = list(rounds_times(request, request.contest).items())
    rtimes.sort(key=lambda r_rt: r_rt[0].start_date)

    if round_pk is None and len(rtimes) > 0:
        # First active round, or last one if there are no active ones
        round_pk = next(
            ((r, rt) for r, rt in rtimes if rt.is_active(request.timestamp)),
            rtimes[-1])[0].pk

    context = {
        'round_times': rtimes,
        'selected_round': None,
        'records': messages,
        'submissions': ss
    }

    if round_pk is not None:
        context.update(get_round_context(request, round_pk))

    return TemplateResponse(request, 'simpleui/contest/contest.html', context)
Пример #5
0
def _last_finished_round_id(request):
    past_rounds = [
        rt for rt in rounds_times(request).iteritems()
        if rt[1].is_past(request.timestamp)
    ]
    if not past_rounds:
        return None
    last_round = max(past_rounds, key=lambda x: x[1].end)
    return last_round[0].id
Пример #6
0
    def get_round_times(self, request, round):
        """Determines the times of the round for the user doing the request.

           The default implementation returns an instance of :class:`RoundTimes`
           cached by round_times() method.

           Round must belong to request.contest.

           :returns: an instance of :class:`RoundTimes`
        """
        return rounds_times(request)[round]
    def get_round_times(self, request, round):
        """Determines the times of the round for the user doing the request.

           The default implementation returns an instance of
           :class:`RoundTimes` cached by round_times() method.

           Round must belong to request.contest.

           :returns: an instance of :class:`RoundTimes`
        """
        return rounds_times(request)[round]
Пример #8
0
def contest_dashboard_view(request, round_pk=None):
    if request.user.is_superuser:
        return redirect('default_contest_view', contest_id=request.contest.id)

    messages = messages_template_context(
        request, visible_messages(request))[:NUMBER_OF_RECENT_ACTIONS]

    queryset = (Submission.objects.filter(
        problem_instance__contest=request.contest).order_by(
            '-date').select_related(
                'user',
                'problem_instance',
                'problem_instance__contest',
                'problem_instance__round',
                'problem_instance__problem',
            ))

    ss = [
        submission_template_context(request, s)
        for s in queryset[:NUMBER_OF_RECENT_ACTIONS]
    ]

    rtimes = list(rounds_times(request, request.contest).items())
    rtimes.sort(key=lambda r_rt: r_rt[0].start_date)

    if round_pk is None and len(rtimes) > 0:
        # First active round, or last one if there are no active ones
        round_pk = next(
            ((r, rt) for r, rt in rtimes if rt.is_active(request.timestamp)),
            rtimes[-1])[0].pk

    context = {
        'round_times':
        rtimes,
        'selected_round':
        None,
        'records':
        messages,
        'submissions':
        ss,
        'contest_dashboard_url_name':
        'simpleui_contest_dashboard',
        'public_contest':
        isinstance(
            request.contest.controller.registration_controller(),
            PublicContestRegistrationController,
        ),
    }

    if round_pk is not None:
        context.update(get_round_context(request, round_pk))

    return TemplateResponse(request, 'simpleui/contest/contest.html', context)
Пример #9
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)
Пример #10
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)
    def get_submission_relative_time(self, submission):
        # FIXME: SIO-1387 RoundTimes shouldn't require request
        # Workaround by mock Request object
        class DummyRequest(object):
            def __init__(self, contest, user):
                self.contest = contest
                self.user = user

        rtimes = rounds_times(DummyRequest(self.contest, submission.user))
        round_start = rtimes[submission.problem_instance.round].get_start()
        submission_time = submission.date - round_start
        # Python2.6 does not support submission_time.total_seconds()
        return submission_time.days * 24 * 3600 + submission_time.seconds
Пример #12
0
    def get_submission_relative_time(self, submission):
        # FIXME: SIO-1387 RoundTimes shouldn't require request
        # Workaround by mock Request object
        class DummyRequest(object):
            def __init__(self, user):
                self.user = user or AnonymousUser()

        rtimes = rounds_times(DummyRequest(submission.user or AnonymousUser()),
                              self.contest)
        round_start = rtimes[submission.problem_instance.round].get_start()
        submission_time = submission.date - round_start
        # Python2.6 does not support submission_time.total_seconds()
        seconds = submission_time.days * 24 * 3600 + submission_time.seconds
        return max(0, seconds)
Пример #13
0
    def get_round_times(self, request, round):
        """Determines the times of the round for the user doing the request.

           The default implementation returns an instance of
           :class:`RoundTimes` cached by round_times() method.

           Round must belong to request.contest.
           Request is optional (round extensions won't be included if omitted).

           :returns: an instance of :class:`RoundTimes`
        """
        if request is not None:
            return rounds_times(request, self.contest)[round]
        else:
            return generic_rounds_times(None, self.contest)[round]
Пример #14
0
    def get_round_times(self, request, round):
        """Determines the times of the round for the user doing the request.

        The default implementation returns an instance of
        :class:`RoundTimes` cached by round_times() method.

        Round must belong to request.contest.
        Request is optional (round extensions won't be included if omitted).

        :returns: an instance of :class:`RoundTimes`
        """
        if request is not None:
            return rounds_times(request, self.contest)[round]
        else:
            return generic_rounds_times(None, self.contest)[round]
    def statistics_available_plot_groups(self, request):
        problem_instances = visible_problem_instances(request)

        result = []
        times = rounds_times(request)

        can_see_any_problems = False
        for pi in problem_instances:
            can_see_round = times[pi.round].results_visible(request.timestamp)
            if can_see_round:
                result.append(('PROBLEM', pi.short_name, pi.problem.name))
                can_see_any_problems = True

        if can_see_any_problems:
            result.insert(
                0, ('CONTEST', request.contest.id, request.contest.name))
        return result
Пример #16
0
def contest_dashboard_view(request, round_pk=None):
    messages = messages_template_context(
        request, visible_messages(request))[:NUMBER_OF_RECENT_ACTIONS]

    queryset = Submission.objects \
        .filter(problem_instance__contest=request.contest) \
        .order_by('-date') \
        .select_related('user', 'problem_instance',
                        'problem_instance__contest',
                        'problem_instance__round',
                        'problem_instance__problem')

    ss = [
        submission_template_context(request, s)
        for s in queryset[:NUMBER_OF_RECENT_ACTIONS]
    ]

    rtimes = rounds_times(request).items()
    rtimes.sort(key=lambda (r, rt): r.start_date)

    if round_pk is None and len(rtimes) > 0:
        # First active round, or last one if there are no active ones
        round_pk = next(
            ((r, rt) for r, rt in rtimes if rt.is_active(request.timestamp)),
            rtimes[-1])[0].pk

    context = {
        'round_times': rtimes,
        'selected_round': None,
        'records': messages,
        'submissions': ss
    }

    if round_pk is not None:
        context.update(get_round_context(request, round_pk))

    return TemplateResponse(request, 'simpleui/contest/contest.html', context)
Пример #17
0
def navbar_countdown(context):
    timestamp = getattr(context['request'], 'timestamp', None)
    contest = getattr(context['request'], 'contest', None)
    if not (timestamp and contest):
        return {}
    rtimes = rounds_times(context['request']).values()
    next_rounds_times = [rt for rt in rtimes if rt.is_future(timestamp)]
    next_rounds_times.sort(key=lambda rt: rt.get_start())
    current_rounds_times = [rt for rt in rtimes
                            if rt.is_active(timestamp) and rt.get_end()]
    current_rounds_times.sort(key=lambda rt: rt.get_end())

    if current_rounds_times:
        countdown_destination = _("end of the round.")
        remaining_seconds = time.mktime((current_rounds_times[0].get_end())
                .timetuple()) - time.mktime(timestamp.timetuple())
        round_duration = time.mktime(current_rounds_times[0].get_end()
                .timetuple()) - time.mktime(current_rounds_times[0].get_start()
                    .timetuple())
        elapsed_part = 1 - 1. * remaining_seconds / round_duration
    elif next_rounds_times:
        countdown_destination = _("start of the round.")
        remaining_seconds = time.mktime((next_rounds_times[0].get_start())
            .timetuple()) - time.mktime(timestamp.timetuple())
        round_duration = 0
    else:
        return {}

    seconds = remaining_seconds % 60
    seconds_str = ungettext('%(seconds)d second ',
        '%(seconds)d seconds ', seconds) % {'seconds': seconds}
    remaining_seconds /= 60
    minutes = int(remaining_seconds % 60)
    minutes_str = ungettext('%(minutes)d minute ',
        '%(minutes)d minutes ', minutes) % {'minutes': minutes}
    remaining_seconds /= 60
    hours = int(remaining_seconds % 24)
    hours_str = ungettext('%(hours)d hour ',
        '%(hours)d hours ', hours) % {'hours': hours}
    remaining_seconds /= 24
    days = int(remaining_seconds)
    days_str = ungettext('%(days)d day ',
        '%(days)d days ', days) % {'days': days}
    if days:
        countdown_days = days_str + hours_str + minutes_str + seconds_str
        countdown_text = \
            ungettext('%(countdown_days)sleft to the %(countdown_dest)s',
                      '%(countdown_days)sleft to the %(countdown_dest)s',
                      days) % {'countdown_days': countdown_days,
                               'countdown_dest': countdown_destination}
    elif hours:
        countdown_hours = hours_str + minutes_str + seconds_str
        countdown_text = \
            ungettext('%(countdown_hours)sleft to the %(countdown_dest)s',
                      '%(countdown_hours)sleft to the %(countdown_dest)s',
                      hours) % {'countdown_hours': countdown_hours,
                                'countdown_dest': countdown_destination}
    elif minutes:
        countdown_minutes = minutes_str + seconds_str
        countdown_text = \
            ungettext('%(countdown_minutes)sleft to the %(countdown_dest)s',
                      '%(countdown_minutes)sleft to the %(countdown_dest)s',
                      minutes) % {'countdown_minutes': countdown_minutes,
                                  'countdown_dest': countdown_destination}
    elif seconds:
        countdown_seconds = seconds_str
        countdown_text = \
            ungettext('%(countdown_seconds)sleft to the %(countdown_dest)s',
                      '%(countdown_seconds)sleft to the %(countdown_dest)s',
                      seconds) % {'countdown_seconds': countdown_seconds,
                                  'countdown_dest': countdown_destination}
    else:
        if round_duration:
            countdown_text = _("The round is over!")
        else:
            countdown_text = _("The round has started!")

    if round_duration:
        if elapsed_part < 0.5:
            red = int(510 * elapsed_part)
            green = 255
        else:
            red = 255
            green = int(510 * (1 - elapsed_part))
        blue = 0
        bar_color = 'rgb(%d,%d,%d)' % (red, green, blue)
        elapsed_part = str(int(elapsed_part * 100)) + '%'
    else:
        bar_color = ''
        elapsed_part = ''

    return {'countdown_text': countdown_text, 'bar_color': bar_color,
        'elapsed_part': elapsed_part}
Пример #18
0
def navbar_countdown(context):
    timestamp = getattr(context['request'], 'timestamp', None)
    contest = getattr(context['request'], 'contest', None)
    if not (timestamp and contest):
        return {}
    rtimes = rounds_times(context['request']).values()
    next_rounds_times = [rt for rt in rtimes if rt.is_future(timestamp)]
    next_rounds_times.sort(key=lambda rt: rt.get_start())
    current_rounds_times = [
        rt for rt in rtimes if rt.is_active(timestamp) and rt.get_end()
    ]
    current_rounds_times.sort(key=lambda rt: rt.get_end())

    if current_rounds_times:
        countdown_destination = _("end of the round.")
        remaining_seconds = time.mktime(
            (current_rounds_times[0].get_end()).timetuple()) - time.mktime(
                timestamp.timetuple())
        round_duration = time.mktime(
            current_rounds_times[0].get_end().timetuple()) - time.mktime(
                current_rounds_times[0].get_start().timetuple())
        elapsed_part = 1 - 1. * remaining_seconds / round_duration
    elif next_rounds_times:
        countdown_destination = _("start of the round.")
        remaining_seconds = time.mktime(
            (next_rounds_times[0].get_start()).timetuple()) - time.mktime(
                timestamp.timetuple())
        round_duration = 0
    else:
        return {}

    seconds = remaining_seconds % 60
    seconds_str = ungettext('%(seconds)d second ', '%(seconds)d seconds ',
                            seconds) % {
                                'seconds': seconds
                            }
    remaining_seconds /= 60
    minutes = int(remaining_seconds % 60)
    minutes_str = ungettext('%(minutes)d minute ', '%(minutes)d minutes ',
                            minutes) % {
                                'minutes': minutes
                            }
    remaining_seconds /= 60
    hours = int(remaining_seconds % 24)
    hours_str = ungettext('%(hours)d hour ', '%(hours)d hours ', hours) % {
        'hours': hours
    }
    remaining_seconds /= 24
    days = int(remaining_seconds)
    days_str = ungettext('%(days)d day ', '%(days)d days ', days) % {
        'days': days
    }
    if days:
        countdown_days = days_str + hours_str + minutes_str + seconds_str
        countdown_text = \
            ungettext('%(countdown_days)sleft to the %(countdown_dest)s',
                      '%(countdown_days)sleft to the %(countdown_dest)s',
                      days) % {'countdown_days': countdown_days,
                               'countdown_dest': countdown_destination}
    elif hours:
        countdown_hours = hours_str + minutes_str + seconds_str
        countdown_text = \
            ungettext('%(countdown_hours)sleft to the %(countdown_dest)s',
                      '%(countdown_hours)sleft to the %(countdown_dest)s',
                      hours) % {'countdown_hours': countdown_hours,
                                'countdown_dest': countdown_destination}
    elif minutes:
        countdown_minutes = minutes_str + seconds_str
        countdown_text = \
            ungettext('%(countdown_minutes)sleft to the %(countdown_dest)s',
                      '%(countdown_minutes)sleft to the %(countdown_dest)s',
                      minutes) % {'countdown_minutes': countdown_minutes,
                                  'countdown_dest': countdown_destination}
    elif seconds:
        countdown_seconds = seconds_str
        countdown_text = \
            ungettext('%(countdown_seconds)sleft to the %(countdown_dest)s',
                      '%(countdown_seconds)sleft to the %(countdown_dest)s',
                      seconds) % {'countdown_seconds': countdown_seconds,
                                  'countdown_dest': countdown_destination}
    else:
        if round_duration:
            countdown_text = _("The round is over!")
        else:
            countdown_text = _("The round has started!")

    if round_duration:
        if elapsed_part < 0.5:
            red = int(510 * elapsed_part)
            green = 255
        else:
            red = 255
            green = int(510 * (1 - elapsed_part))
        blue = 0
        bar_color = 'rgb(%d,%d,%d)' % (red, green, blue)
        elapsed_part = str(int(elapsed_part * 100)) + '%'
    else:
        bar_color = ''
        elapsed_part = ''

    return {
        'countdown_text': countdown_text,
        'bar_color': bar_color,
        'elapsed_part': elapsed_part
    }