Skip to content

Commit

Permalink
Merge branch 'master' into api-consistency
Browse files Browse the repository at this point in the history
  • Loading branch information
jtyliu committed Aug 23, 2021
2 parents 11dba54 + bf3fbaf commit 9c6311f
Show file tree
Hide file tree
Showing 34 changed files with 665 additions and 163 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ See it live at [dmoj.ca](https://dmoj.ca/)!
* Supports ICPC/IOI/AtCoder/ECOO formats out-of-the box
* **System testing** supported
* **Hidden scoreboards** and **virtual participation**
* Topcoder-style **rating**
* [Elo-MMR](https://arxiv.org/abs/2101.00400)-style **rating**
* **Plagiarism detection** via [Stanford MOSS](https://theory.stanford.edu/~aiken/moss/)
* Restricting contest access to particular organizations or users
* Rich problem statements, with support for **LaTeX math and diagrams**
Expand Down
2 changes: 1 addition & 1 deletion judge/admin/contest.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
fieldsets = (
(None, {'fields': ('key', 'name', 'authors', 'curators', 'testers')}),
(_('Settings'), {'fields': ('is_visible', 'use_clarifications', 'hide_problem_tags', 'hide_problem_authors',
'run_pretests_only', 'locked_after', 'scoreboard_visibility',
'show_short_display', 'run_pretests_only', 'locked_after', 'scoreboard_visibility',
'points_precision')}),
(_('Scheduling'), {'fields': ('start_time', 'end_time', 'time_limit')}),
(_('Details'), {'fields': ('description', 'og_image', 'logo_override_image', 'tags', 'summary')}),
Expand Down
4 changes: 2 additions & 2 deletions judge/admin/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ def has_add_permission(self, request):

class ProfileAdmin(NoBatchDeleteMixin, VersionAdmin):
fields = ('user', 'display_rank', 'about', 'organizations', 'timezone', 'language', 'ace_theme',
'math_engine', 'last_access', 'ip', 'mute', 'is_unlisted', 'notes', 'is_totp_enabled', 'user_script',
'current_contest')
'math_engine', 'last_access', 'ip', 'mute', 'is_unlisted', 'username_display_override',
'notes', 'is_totp_enabled', 'user_script', 'current_contest')
readonly_fields = ('user',)
list_display = ('admin_user_admin', 'email', 'is_totp_enabled', 'timezone_full',
'date_joined', 'last_access', 'ip', 'show_public')
Expand Down
15 changes: 14 additions & 1 deletion judge/contest_format/atcoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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_lazy
from django.utils.translation import gettext as _, gettext_lazy, ungettext

from judge.contest_format.default import DefaultContestFormat
from judge.contest_format.registry import register_contest_format
Expand Down Expand Up @@ -112,3 +112,16 @@ def display_user_problem(self, participation, contest_problem):
)
else:
return mark_safe('<td></td>')

def get_short_form_display(self):
yield _('The maximum score submission for each problem will be used.')

penalty = self.config['penalty']
if penalty:
yield ungettext(
'Each submission before the first maximum score submission will incur a **penalty of %d minute**.',
'Each submission before the first maximum score submission will incur a **penalty of %d minutes**.',
penalty,
) % penalty

yield _('Ties will be broken by the last score altering submission time.')
9 changes: 9 additions & 0 deletions judge/contest_format/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ def get_label_for_problem(self, index):
"""
raise NotImplementedError()

@abstractmethod
def get_short_form_display(self):
"""
Returns a generator of Markdown strings to display the contest format's settings in short form.
:return: A generator, where each item is an individual line.
"""
raise NotImplementedError()

@classmethod
def best_solution_state(cls, points, total):
if not points:
Expand Down
6 changes: 5 additions & 1 deletion judge/contest_format/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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_lazy
from django.utils.translation import gettext as _, gettext_lazy

from judge.contest_format.base import BaseContestFormat
from judge.contest_format.registry import register_contest_format
Expand Down Expand Up @@ -74,3 +74,7 @@ def get_problem_breakdown(self, participation, contest_problems):

def get_label_for_problem(self, index):
return str(index + 1)

def get_short_form_display(self):
yield _('The maximum score submission for each problem will be used.')
yield _('Ties will be broken by the sum of the last submission time on problems with a non-zero score.')
24 changes: 23 additions & 1 deletion judge/contest_format/ecoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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_lazy
from django.utils.translation import gettext as _, gettext_lazy, ungettext

from judge.contest_format.default import DefaultContestFormat
from judge.contest_format.registry import register_contest_format
Expand Down Expand Up @@ -125,3 +125,25 @@ def display_participation_result(self, participation):
points=floatformat(participation.score, -self.contest.points_precision),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday') if self.config['cumtime'] else '',
)

def get_short_form_display(self):
yield _('The score on your **last** non-CE submission for each problem will be used.')

first_ac_bonus = self.config['first_ac_bonus']
if first_ac_bonus:
yield _(
'There is a **%d bonus** for fully solving on your first non-CE submission.',
) % first_ac_bonus

time_bonus = self.config['time_bonus']
if time_bonus:
yield ungettext(
'For every **%d minute** you submit before the end of your window, there will be a **1** point bonus.',
'For every **%d minutes** you submit before the end of your window, there will be a **1** point bonus.',
time_bonus,
) % time_bonus

if self.config['cumtime']:
yield _('Ties will be broken by the sum of the last submission time on **all** problems.')
else:
yield _('Ties by score will **not** be broken.')
16 changes: 15 additions & 1 deletion judge/contest_format/icpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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_lazy
from django.utils.translation import gettext as _, gettext_lazy, ungettext

from judge.contest_format.default import DefaultContestFormat
from judge.contest_format.registry import register_contest_format
Expand Down Expand Up @@ -122,3 +122,17 @@ def get_label_for_problem(self, index):
ret += chr((index - 1) % 26 + 65)
index = (index - 1) // 26
return ret[::-1]

def get_short_form_display(self):
yield _('The maximum score submission for each problem will be used.')

penalty = self.config['penalty']
if penalty:
yield ungettext(
'Each submission before the first maximum score submission will incur a **penalty of %d minute**.',
'Each submission before the first maximum score submission will incur a **penalty of %d minutes**.',
penalty,
) % penalty

yield _('Ties will be broken by the sum of the last score altering submission time on problems with a non-zero '
'score, followed by the time of the last score altering submission.')
13 changes: 11 additions & 2 deletions judge/contest_format/ioi.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.db import connection
from django.utils.translation import gettext_lazy
from django.utils.translation import gettext as _, gettext_lazy

from judge.contest_format.legacy_ioi import LegacyIOIContestFormat
from judge.contest_format.registry import register_contest_format
Expand Down Expand Up @@ -79,7 +79,7 @@ def update_participation(self, participation):
format_data[problem_id]['points'] += subtask_points
format_data[problem_id]['time'] = max(dt, format_data[problem_id]['time'])

for _, problem_data in format_data.items():
for problem_data in format_data.values():
penalty = problem_data['time']
points = problem_data['points']
if self.config['cumtime'] and points:
Expand All @@ -91,3 +91,12 @@ def update_participation(self, participation):
participation.tiebreaker = 0
participation.format_data = format_data
participation.save()

def get_short_form_display(self):
yield _('The maximum score for each problem batch will be used.')

if self.config['cumtime']:
yield _('Ties will be broken by the sum of the last score altering submission time on problems with a '
'non-zero score.')
else:
yield _('Ties by score will **not** be broken.')
11 changes: 10 additions & 1 deletion judge/contest_format/legacy_ioi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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_lazy
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
Expand Down Expand Up @@ -92,3 +92,12 @@ def display_participation_result(self, participation):
points=floatformat(participation.score, -self.contest.points_precision),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday') if self.config['cumtime'] else '',
)

def get_short_form_display(self):
yield _('The maximum score submission for each problem will be used.')

if self.config['cumtime']:
yield _('Ties will be broken by the sum of the last score altering submission time on problems with a '
'non-zero score.')
else:
yield _('Ties by score will **not** be broken.')
2 changes: 1 addition & 1 deletion judge/fixtures/demo.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@

],
"date": "2017-12-02T05:00:00Z",
"description": "Tudor is sitting in math class, on his laptop. Clearly, he is not paying attention in this situation. However, he gets called on by his math teacher to do some problems. Since his math teacher did not expect much from Tudor, he only needs to do some simple addition problems. However, simple for you and I may not be simple for Tudor , so please help him!\n\n## Input Specification\n\nThe first line will contain an integer ~N~ (~1 \\le N \\le 100\\,000~), the number of addition problems Tudor needs to do. The next ~N~ lines will each contain two space-separated integers whose absolute value is less than ~1\\,000\\,000\\,000~, the two integers Tudor needs to add.\n\n## Output Specification\n\nOutput ~N~ lines of one integer each, the solutions to the addition problems in order.\n\n## Sample Input\n\n 2\n 1 1\n -1 0\n\n## Sample Output\n\n 2\n -1",
"description": "Tudor is sitting in math class, on his laptop. Clearly, he is not paying attention in this situation. However, he gets called on by his math teacher to do some problems. Since his math teacher did not expect much from Tudor, he only needs to do some simple addition problems. However, simple for you and I may not be simple for Tudor, so please help him!\n\n## Input Specification\n\nThe first line will contain an integer ~N~ (~1 \\le N \\le 100\\,000~), the number of addition problems Tudor needs to do. The next ~N~ lines will each contain two space-separated integers whose absolute value is less than ~1\\,000\\,000\\,000~, the two integers Tudor needs to add.\n\n## Output Specification\n\nOutput ~N~ lines of one integer each, the solutions to the addition problems in order.\n\n## Sample Input\n\n 2\n 1 1\n -1 0\n\n## Sample Output\n\n 2\n -1",
"group": 1,
"is_manually_managed": false,
"is_public": true,
Expand Down
18 changes: 18 additions & 0 deletions judge/migrations/0122_username_display_override.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.24 on 2021-08-09 01:42

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('judge', '0121_per_problem_sub_access_control'),
]

operations = [
migrations.AddField(
model_name='profile',
name='username_display_override',
field=models.CharField(blank=True, max_length=100, verbose_name='display name override', help_text='name displayed in place of username'),
),
]
Loading

0 comments on commit 9c6311f

Please sign in to comment.