diff --git a/judge/contest_format/__init__.py b/judge/contest_format/__init__.py index 8d2ccc9..9f6d628 100644 --- a/judge/contest_format/__init__.py +++ b/judge/contest_format/__init__.py @@ -4,4 +4,5 @@ from judge.contest_format.ecoo import ECOOContestFormat from judge.contest_format.icpc import ICPCContestFormat from judge.contest_format.ioi import IOIContestFormat from judge.contest_format.new_ioi import NewIOIContestFormat +from judge.contest_format.ultimate import UltimateContestFormat from judge.contest_format.registry import choices, formats diff --git a/judge/contest_format/ultimate.py b/judge/contest_format/ultimate.py new file mode 100644 index 0000000..7960d02 --- /dev/null +++ b/judge/contest_format/ultimate.py @@ -0,0 +1,55 @@ +from django.utils.translation import gettext_lazy + +from judge.contest_format.ioi import IOIContestFormat +from judge.contest_format.registry import register_contest_format +from django.db.models import Min, OuterRef, Subquery + +# This contest format only counts last submission for each problem. + + +@register_contest_format("ultimate") +class UltimateContestFormat(IOIContestFormat): + name = gettext_lazy("Ultimate") + + def update_participation(self, participation): + cumtime = 0 + score = 0 + format_data = {} + + queryset = participation.submissions + if self.contest.freeze_after: + queryset = queryset.filter( + submission__date__lt=participation.start + self.contest.freeze_after + ) + + queryset = ( + queryset.values("problem_id") + .filter( + id=Subquery( + queryset.filter(problem_id=OuterRef("problem_id")) + .order_by("-id") + .values("id")[:1] + ) + ) + .values_list("problem_id", "submission__date", "points") + ) + + for problem_id, time, points in queryset: + if self.config["cumtime"]: + dt = (time - participation.start).total_seconds() + if points: + cumtime += dt + else: + dt = 0 + format_data[str(problem_id)] = { + "time": dt, + "points": points, + } + score += points + + self.handle_frozen_state(participation, format_data) + participation.cumtime = max(cumtime, 0) + participation.score = round(score, self.contest.points_precision) + participation.tiebreaker = 0 + participation.format_data = format_data + participation.save() diff --git a/judge/migrations/0167_ultimate_contest_format.py b/judge/migrations/0167_ultimate_contest_format.py new file mode 100644 index 0000000..636e882 --- /dev/null +++ b/judge/migrations/0167_ultimate_contest_format.py @@ -0,0 +1,32 @@ +# Generated by Django 3.2.18 on 2023-09-01 00:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("judge", "0166_display_rank_index"), + ] + + operations = [ + migrations.AlterField( + model_name="contest", + name="format_name", + field=models.CharField( + choices=[ + ("atcoder", "AtCoder"), + ("default", "Default"), + ("ecoo", "ECOO"), + ("icpc", "ICPC"), + ("ioi", "IOI"), + ("ioi16", "New IOI"), + ("ultimate", "Ultimate"), + ], + default="default", + help_text="The contest format module to use.", + max_length=32, + verbose_name="contest format", + ), + ), + ]