Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix contest scoreboard to properly color AC submissions green (#31) #32

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion judge/contest_format/atcoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from judge.contest_format.registry import register_contest_format
from judge.timezone import from_database_time
from judge.utils.timedelta import nice_repr
from judge.utils.problems import contest_completed_ids


@register_contest_format('atcoder')
Expand Down Expand Up @@ -103,7 +104,7 @@ def display_user_problem(self, participation, contest_problem):
return format_html(
'<td class="{state}"><a href="{url}">{points}{penalty}<div class="solving-time">{time}</div></a></td>',
state=(('pretest-' if self.contest.run_pretests_only and contest_problem.is_pretested else '') +
self.best_solution_state(format_data['points'], contest_problem.points)),
self.best_solution_state(format_data['points'], contest_problem.problem.id in contest_completed_ids(participation))),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
Expand Down
6 changes: 3 additions & 3 deletions judge/contest_format/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ def get_label_for_problem(self, index):
raise NotImplementedError()

@classmethod
def best_solution_state(cls, points, total):
def best_solution_state(cls, points, total, has_ac):
if has_ac:
return 'full-score'
if not points:
return 'failed-score'
if points == total:
return 'full-score'
return 'partial-score'
3 changes: 2 additions & 1 deletion judge/contest_format/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from judge.contest_format.base import BaseContestFormat
from judge.contest_format.registry import register_contest_format
from judge.utils.timedelta import nice_repr
from judge.utils.problems import contest_completed_ids


@register_contest_format('default')
Expand Down Expand Up @@ -51,7 +52,7 @@ def display_user_problem(self, participation, contest_problem):
return format_html(
u'<td class="{state}"><a href="{url}">{points}<div class="solving-time">{time}</div></a></td>',
state=(('pretest-' if self.contest.run_pretests_only and contest_problem.is_pretested else '') +
self.best_solution_state(format_data['points'], contest_problem.points)),
self.best_solution_state(format_data['points'], contest_problem.points, contest_problem.problem.id in contest_completed_ids(participation))),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
Expand Down
3 changes: 2 additions & 1 deletion judge/contest_format/ecoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from judge.contest_format.default import DefaultContestFormat
from judge.contest_format.registry import register_contest_format
from judge.utils.timedelta import nice_repr
from judge.utils.problems import contest_completed_ids


@register_contest_format('ecoo')
Expand Down Expand Up @@ -107,7 +108,7 @@ def display_user_problem(self, participation, contest_problem):
return format_html(
'<td class="{state}"><a href="{url}">{points}{bonus}<div class="solving-time">{time}</div></a></td>',
state=(('pretest-' if self.contest.run_pretests_only and contest_problem.is_pretested else '') +
self.best_solution_state(format_data['points'], contest_problem.points)),
self.best_solution_state(format_data['points'], contest_problem.points, contest_problem.problem.id in contest_completed_ids(participation))),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
Expand Down
3 changes: 2 additions & 1 deletion judge/contest_format/icpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from judge.contest_format.registry import register_contest_format
from judge.timezone import from_database_time
from judge.utils.timedelta import nice_repr
from judge.utils.problems import contest_completed_ids


@register_contest_format('icpc')
Expand Down Expand Up @@ -105,7 +106,7 @@ def display_user_problem(self, participation, contest_problem):
return format_html(
'<td class="{state}"><a href="{url}">{points}{penalty}<div class="solving-time">{time}</div></a></td>',
state=(('pretest-' if self.contest.run_pretests_only and contest_problem.is_pretested else '') +
self.best_solution_state(format_data['points'], contest_problem.points)),
self.best_solution_state(format_data['points'], contest_problem.points, contest_problem.problem.id in contest_completed_ids(participation))),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
Expand Down
3 changes: 2 additions & 1 deletion judge/contest_format/legacy_ioi.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from judge.contest_format.default import DefaultContestFormat
from judge.contest_format.registry import register_contest_format
from judge.utils.timedelta import nice_repr
from judge.utils.problems import contest_completed_ids


@register_contest_format('ioi')
Expand Down Expand Up @@ -75,7 +76,7 @@ def display_user_problem(self, participation, contest_problem):
return format_html(
'<td class="{state}"><a href="{url}">{points}<div class="solving-time">{time}</div></a></td>',
state=(('pretest-' if self.contest.run_pretests_only and contest_problem.is_pretested else '') +
self.best_solution_state(format_data['points'], contest_problem.points)),
self.best_solution_state(format_data['points'], contest_problem.problem.id in contest_completed_ids(participation))),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
Expand Down
14 changes: 7 additions & 7 deletions judge/utils/problems.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
from django.utils import timezone
from django.utils.translation import gettext as _, gettext_noop

from judge.models import Problem, Submission
import judge.models as _

__all__ = ['contest_completed_ids', 'get_result_data', 'user_completed_ids', 'user_editable_ids', 'user_tester_ids']


def user_tester_ids(profile):
return set(Problem.objects.filter(testers=profile).values_list('id', flat=True))
return set(_.Problem.objects.filter(testers=profile).values_list('id', flat=True))


def user_editable_ids(profile):
return set(Problem.get_editable_problems(profile.user).values_list('id', flat=True))
return set(_.Problem.get_editable_problems(profile.user).values_list('id', flat=True))


def contest_completed_ids(participation):
Expand All @@ -34,7 +34,7 @@ def user_completed_ids(profile):
key = 'user_complete:%d' % profile.id
result = cache.get(key)
if result is None:
result = set(Submission.objects.filter(user=profile, result='AC', points=F('problem__points'))
result = set(_.Submission.objects.filter(user=profile, result='AC', points=F('problem__points'))
.values_list('problem_id', flat=True).distinct())
cache.set(key, result, 86400)
return result
Expand All @@ -58,7 +58,7 @@ def user_attempted_ids(profile):
result = cache.get(key)
if result is None:
result = {id: {'achieved_points': points, 'max_points': max_points}
for id, max_points, points in (Submission.objects.filter(user=profile)
for id, max_points, points in (_.Submission.objects.filter(user=profile)
.values_list('problem__id', 'problem__points')
.annotate(points=Max('points'))
.filter(points__lt=F('problem__points')))}
Expand Down Expand Up @@ -88,7 +88,7 @@ def get_result_data(*args, **kwargs):
if kwargs:
raise ValueError(_("Can't pass both queryset and keyword filters"))
else:
submissions = Submission.objects.filter(**kwargs) if kwargs is not None else Submission.objects
submissions = _.Submission.objects.filter(**kwargs) if kwargs is not None else _.Submission.objects
raw = submissions.values('result').annotate(count=Count('result')).values_list('result', 'count')
return _get_result_data(defaultdict(int, raw))

Expand All @@ -97,7 +97,7 @@ def hot_problems(duration, limit):
cache_key = 'hot_problems:%d:%d' % (duration.total_seconds(), limit)
qs = cache.get(cache_key)
if qs is None:
qs = Problem.get_public_problems() \
qs = _.Problem.get_public_problems() \
.filter(submission__date__gt=timezone.now() - duration, points__gt=3, points__lt=25)
qs0 = qs.annotate(k=Count('submission__user', distinct=True)).order_by('-k').values_list('k', flat=True)

Expand Down