From c8663253c1177cc27ac559c0e55185dc2569d58a Mon Sep 17 00:00:00 2001 From: Seyon Sivatharan Date: Wed, 16 Mar 2022 01:19:46 -0400 Subject: [PATCH] Fix contest scoreboard to properly color AC submissions green (#31) --- judge/contest_format/atcoder.py | 3 ++- judge/contest_format/base.py | 6 +++--- judge/contest_format/default.py | 3 ++- judge/contest_format/ecoo.py | 3 ++- judge/contest_format/icpc.py | 3 ++- judge/contest_format/legacy_ioi.py | 3 ++- judge/utils/problems.py | 14 +++++++------- 7 files changed, 20 insertions(+), 15 deletions(-) diff --git a/judge/contest_format/atcoder.py b/judge/contest_format/atcoder.py index 4ef116a253..72069d5ed5 100644 --- a/judge/contest_format/atcoder.py +++ b/judge/contest_format/atcoder.py @@ -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') @@ -103,7 +104,7 @@ def display_user_problem(self, participation, contest_problem): return format_html( '{points}{penalty}
{time}
', 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']), diff --git a/judge/contest_format/base.py b/judge/contest_format/base.py index 0b70fb2c23..1d3d8cbd0c 100644 --- a/judge/contest_format/base.py +++ b/judge/contest_format/base.py @@ -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' diff --git a/judge/contest_format/default.py b/judge/contest_format/default.py index e00381e0b6..23a9a14089 100644 --- a/judge/contest_format/default.py +++ b/judge/contest_format/default.py @@ -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') @@ -51,7 +52,7 @@ def display_user_problem(self, participation, contest_problem): return format_html( u'{points}
{time}
', 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']), diff --git a/judge/contest_format/ecoo.py b/judge/contest_format/ecoo.py index fdae0bd025..e62ea78ceb 100644 --- a/judge/contest_format/ecoo.py +++ b/judge/contest_format/ecoo.py @@ -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') @@ -107,7 +108,7 @@ def display_user_problem(self, participation, contest_problem): return format_html( '{points}{bonus}
{time}
', 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']), diff --git a/judge/contest_format/icpc.py b/judge/contest_format/icpc.py index 3e1918de8a..d3a6acab4a 100644 --- a/judge/contest_format/icpc.py +++ b/judge/contest_format/icpc.py @@ -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') @@ -105,7 +106,7 @@ def display_user_problem(self, participation, contest_problem): return format_html( '{points}{penalty}
{time}
', 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']), diff --git a/judge/contest_format/legacy_ioi.py b/judge/contest_format/legacy_ioi.py index 831b02903a..a3a676a47a 100644 --- a/judge/contest_format/legacy_ioi.py +++ b/judge/contest_format/legacy_ioi.py @@ -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') @@ -75,7 +76,7 @@ def display_user_problem(self, participation, contest_problem): return format_html( '{points}
{time}
', 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']), diff --git a/judge/utils/problems.py b/judge/utils/problems.py index 40be0fc488..529210268d 100644 --- a/judge/utils/problems.py +++ b/judge/utils/problems.py @@ -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): @@ -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 @@ -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')))} @@ -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)) @@ -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)