From fda07dd892aef996ec7aed242c7d3ba8bf909cec Mon Sep 17 00:00:00 2001 From: Jason Cameron Date: Sat, 2 Nov 2024 22:29:53 -0400 Subject: [PATCH] Add in a new (custom) bonuses fmt Signed-off-by: Jason Cameron --- judge/contest_format/__init__.py | 1 + judge/contest_format/bonuses.py | 97 ++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 judge/contest_format/bonuses.py diff --git a/judge/contest_format/__init__.py b/judge/contest_format/__init__.py index acefe4c9fa..65e7f36483 100644 --- a/judge/contest_format/__init__.py +++ b/judge/contest_format/__init__.py @@ -1,4 +1,5 @@ from judge.contest_format.atcoder import AtCoderContestFormat +from judge.contest_format.bonuses import BonusesContestFormat from judge.contest_format.default import DefaultContestFormat from judge.contest_format.ecoo import ECOOContestFormat from judge.contest_format.icpc import ICPCContestFormat diff --git a/judge/contest_format/bonuses.py b/judge/contest_format/bonuses.py new file mode 100644 index 0000000000..59837a1711 --- /dev/null +++ b/judge/contest_format/bonuses.py @@ -0,0 +1,97 @@ +from datetime import timedelta + +from django.db import connection +from django.template.defaultfilters import floatformat +from django.urls import reverse +from django.utils.html import format_html +from django.utils.safestring import mark_safe +from django.utils.translation import gettext as _, gettext_lazy + +from judge.contest_format.default import DefaultContestFormat +from judge.contest_format.registry import register_contest_format +from judge.timezone import from_database_time +from judge.utils.timedelta import nice_repr + + +@register_contest_format('bonuses') +class BonusesContestFormat(DefaultContestFormat): + """ + Used as a way to break ties by the sum of the last score + altering submission time on problems with a non-zero score.' + """ + + name = gettext_lazy('Bonuses') + + def __init__(self, contest, config): + self.config = self.config_defaults.copy() + self.config.update(config or {}) + self.contest = contest + + def update_participation(self, participation): + cumtime = 0 + points = 0 + format_data = {} + + with connection.cursor() as cursor: + cursor.execute( + """ + SELECT MAX(cs.points) as `score`, ( + SELECT MIN(csub.date) + FROM judge_contestsubmission ccs LEFT OUTER JOIN + judge_submission csub ON (csub.id = ccs.submission_id) + WHERE ccs.problem_id = cp.id AND ccs.participation_id = %s AND ccs.points = MAX(cs.points) + ) AS `time`, cp.id AS `prob` + FROM judge_contestproblem cp INNER JOIN + judge_contestsubmission cs ON (cs.problem_id = cp.id AND cs.participation_id = %s) LEFT OUTER JOIN + judge_submission sub ON (sub.id = cs.submission_id) + GROUP BY cp.id + """, + (participation.id, participation.id), + ) + + for score, time, prob in cursor.fetchall(): + time = from_database_time(time) + dt = (time - participation.start).total_seconds() + + if score: + cumtime = max(cumtime, dt) + + format_data[str(prob)] = {'time': dt, 'points': score} + points += score + + participation.cumtime = cumtime + participation.score = round(points, self.contest.points_precision) + participation.tiebreaker = 0 + participation.format_data = format_data + participation.save() + + def display_user_problem(self, participation, contest_problem): + format_data = (participation.format_data or {}).get(str(contest_problem.id)) + if format_data: + 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, + ), + ), + url=reverse( + 'contest_user_submissions', + args=[ + self.contest.key, + participation.user.user.username, + contest_problem.problem.code, + ], + ), + points=floatformat(format_data['points']), + time=nice_repr(timedelta(seconds=format_data['time']), 'noday'), + ) + else: + return mark_safe('') + + def get_short_form_display(self): + yield _('The maximum score submission for each problem will be used.') + yield _('Ties will be broken by the last score altering submission time.')