Reformat using black

This commit is contained in:
cuom1999 2022-05-14 12:57:27 -05:00
parent efee4ad081
commit a87fb49918
221 changed files with 19127 additions and 7310 deletions

View file

@ -14,14 +14,14 @@ from judge.timezone import from_database_time
from judge.utils.timedelta import nice_repr
@register_contest_format('atcoder')
@register_contest_format("atcoder")
class AtCoderContestFormat(DefaultContestFormat):
name = gettext_lazy('AtCoder')
config_defaults = {'penalty': 5}
config_validators = {'penalty': lambda x: x >= 0}
'''
name = gettext_lazy("AtCoder")
config_defaults = {"penalty": 5}
config_validators = {"penalty": lambda x: x >= 0}
"""
penalty: Number of penalty minutes each incorrect submission adds. Defaults to 5.
'''
"""
@classmethod
def validate(cls, config):
@ -29,7 +29,9 @@ class AtCoderContestFormat(DefaultContestFormat):
return
if not isinstance(config, dict):
raise ValidationError('AtCoder-styled contest expects no config or dict as config')
raise ValidationError(
"AtCoder-styled contest expects no config or dict as config"
)
for key, value in config.items():
if key not in cls.config_defaults:
@ -37,7 +39,9 @@ class AtCoderContestFormat(DefaultContestFormat):
if not isinstance(value, type(cls.config_defaults[key])):
raise ValidationError('invalid type for config key "%s"' % key)
if not cls.config_validators[key](value):
raise ValidationError('invalid value "%s" for config key "%s"' % (value, key))
raise ValidationError(
'invalid value "%s" for config key "%s"' % (value, key)
)
def __init__(self, contest, config):
self.config = self.config_defaults.copy()
@ -51,7 +55,8 @@ class AtCoderContestFormat(DefaultContestFormat):
format_data = {}
with connection.cursor() as cursor:
cursor.execute('''
cursor.execute(
"""
SELECT MAX(cs.points) as `score`, (
SELECT MIN(csub.date)
FROM judge_contestsubmission ccs LEFT OUTER JOIN
@ -62,21 +67,27 @@ class AtCoderContestFormat(DefaultContestFormat):
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))
""",
(participation.id, participation.id),
)
for score, time, prob in cursor.fetchall():
time = from_database_time(time)
dt = (time - participation.start).total_seconds()
# Compute penalty
if self.config['penalty']:
if self.config["penalty"]:
# An IE can have a submission result of `None`
subs = participation.submissions.exclude(submission__result__isnull=True) \
.exclude(submission__result__in=['IE', 'CE']) \
.filter(problem_id=prob)
subs = (
participation.submissions.exclude(
submission__result__isnull=True
)
.exclude(submission__result__in=["IE", "CE"])
.filter(problem_id=prob)
)
if score:
prev = subs.filter(submission__date__lte=time).count() - 1
penalty += prev * self.config['penalty'] * 60
penalty += prev * self.config["penalty"] * 60
else:
# We should always display the penalty, even if the user has a score of 0
prev = subs.count()
@ -86,7 +97,7 @@ class AtCoderContestFormat(DefaultContestFormat):
if score:
cumtime = max(cumtime, dt)
format_data[str(prob)] = {'time': dt, 'points': score, 'penalty': prev}
format_data[str(prob)] = {"time": dt, "points": score, "penalty": prev}
points += score
participation.cumtime = cumtime + penalty
@ -98,17 +109,38 @@ class AtCoderContestFormat(DefaultContestFormat):
def display_user_problem(self, participation, contest_problem):
format_data = (participation.format_data or {}).get(str(contest_problem.id))
if format_data:
penalty = format_html('<small style="color:red"> ({penalty})</small>',
penalty=floatformat(format_data['penalty'])) if format_data['penalty'] else ''
penalty = (
format_html(
'<small style="color:red"> ({penalty})</small>',
penalty=floatformat(format_data["penalty"]),
)
if format_data["penalty"]
else ""
)
return format_html(
'<td class="{state} problem-score-col"><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)),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
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"]),
penalty=penalty,
time=nice_repr(timedelta(seconds=format_data['time']), 'noday'),
time=nice_repr(timedelta(seconds=format_data["time"]), "noday"),
)
else:
return mark_safe('<td class="problem-score-col"></td>')

View file

@ -93,7 +93,7 @@ class BaseContestFormat(six.with_metaclass(ABCMeta)):
@classmethod
def best_solution_state(cls, points, total):
if not points:
return 'failed-score'
return "failed-score"
if points == total:
return 'full-score'
return 'partial-score'
return "full-score"
return "partial-score"

View file

@ -13,14 +13,16 @@ from judge.contest_format.registry import register_contest_format
from judge.utils.timedelta import nice_repr
@register_contest_format('default')
@register_contest_format("default")
class DefaultContestFormat(BaseContestFormat):
name = gettext_lazy('Default')
name = gettext_lazy("Default")
@classmethod
def validate(cls, config):
if config is not None and (not isinstance(config, dict) or config):
raise ValidationError('default contest expects no config or empty dict as config')
raise ValidationError(
"default contest expects no config or empty dict as config"
)
def __init__(self, contest, config):
super(DefaultContestFormat, self).__init__(contest, config)
@ -30,14 +32,18 @@ class DefaultContestFormat(BaseContestFormat):
points = 0
format_data = {}
for result in participation.submissions.values('problem_id').annotate(
time=Max('submission__date'), points=Max('points'),
for result in participation.submissions.values("problem_id").annotate(
time=Max("submission__date"),
points=Max("points"),
):
dt = (result['time'] - participation.start).total_seconds()
if result['points']:
dt = (result["time"] - participation.start).total_seconds()
if result["points"]:
cumtime += dt
format_data[str(result['problem_id'])] = {'time': dt, 'points': result['points']}
points += result['points']
format_data[str(result["problem_id"])] = {
"time": dt,
"points": result["points"],
}
points += result["points"]
participation.cumtime = max(cumtime, 0)
participation.score = points
@ -49,30 +55,50 @@ class DefaultContestFormat(BaseContestFormat):
format_data = (participation.format_data or {}).get(str(contest_problem.id))
if format_data:
return format_html(
u'<td class="{state} problem-score-col"><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)),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points'], -self.contest.points_precision),
time=nice_repr(timedelta(seconds=format_data['time']), 'noday'),
'<td class="{state} problem-score-col"><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
)
),
url=reverse(
"contest_user_submissions",
args=[
self.contest.key,
participation.user.user.username,
contest_problem.problem.code,
],
),
points=floatformat(
format_data["points"], -self.contest.points_precision
),
time=nice_repr(timedelta(seconds=format_data["time"]), "noday"),
)
else:
return mark_safe('<td class="problem-score-col"></td>')
def display_participation_result(self, participation):
return format_html(
u'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
points=floatformat(participation.score, -self.contest.points_precision),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday'),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), "noday"),
)
def get_problem_breakdown(self, participation, contest_problems):
return [(participation.format_data or {}).get(str(contest_problem.id)) for contest_problem in contest_problems]
return [
(participation.format_data or {}).get(str(contest_problem.id))
for contest_problem in contest_problems
]
def get_contest_problem_label_script(self):
return '''
return """
function(n)
return tostring(math.floor(n + 1))
end
'''
"""

View file

@ -14,17 +14,21 @@ from judge.timezone import from_database_time
from judge.utils.timedelta import nice_repr
@register_contest_format('ecoo')
@register_contest_format("ecoo")
class ECOOContestFormat(DefaultContestFormat):
name = gettext_lazy('ECOO')
config_defaults = {'cumtime': False, 'first_ac_bonus': 10, 'time_bonus': 5}
config_validators = {'cumtime': lambda x: True, 'first_ac_bonus': lambda x: x >= 0, 'time_bonus': lambda x: x >= 0}
'''
name = gettext_lazy("ECOO")
config_defaults = {"cumtime": False, "first_ac_bonus": 10, "time_bonus": 5}
config_validators = {
"cumtime": lambda x: True,
"first_ac_bonus": lambda x: x >= 0,
"time_bonus": lambda x: x >= 0,
}
"""
cumtime: Specify True if cumulative time is to be used in breaking ties. Defaults to False.
first_ac_bonus: The number of points to award if a solution gets AC on its first non-IE/CE run. Defaults to 10.
time_bonus: Number of minutes to award an extra point for submitting before the contest end.
Specify 0 to disable. Defaults to 5.
'''
"""
@classmethod
def validate(cls, config):
@ -32,7 +36,9 @@ class ECOOContestFormat(DefaultContestFormat):
return
if not isinstance(config, dict):
raise ValidationError('ECOO-styled contest expects no config or dict as config')
raise ValidationError(
"ECOO-styled contest expects no config or dict as config"
)
for key, value in config.items():
if key not in cls.config_defaults:
@ -40,7 +46,9 @@ class ECOOContestFormat(DefaultContestFormat):
if not isinstance(value, type(cls.config_defaults[key])):
raise ValidationError('invalid type for config key "%s"' % key)
if not cls.config_validators[key](value):
raise ValidationError('invalid value "%s" for config key "%s"' % (value, key))
raise ValidationError(
'invalid value "%s" for config key "%s"' % (value, key)
)
def __init__(self, contest, config):
self.config = self.config_defaults.copy()
@ -53,7 +61,8 @@ class ECOOContestFormat(DefaultContestFormat):
format_data = {}
with connection.cursor() as cursor:
cursor.execute('''
cursor.execute(
"""
SELECT (
SELECT MAX(ccs.points)
FROM judge_contestsubmission ccs LEFT OUTER JOIN
@ -69,25 +78,31 @@ class ECOOContestFormat(DefaultContestFormat):
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, participation.id))
""",
(participation.id, participation.id, participation.id),
)
for score, time, prob, subs, max_score in cursor.fetchall():
time = from_database_time(time)
dt = (time - participation.start).total_seconds()
if self.config['cumtime']:
if self.config["cumtime"]:
cumtime += dt
bonus = 0
if score > 0:
# First AC bonus
if subs == 1 and score == max_score:
bonus += self.config['first_ac_bonus']
bonus += self.config["first_ac_bonus"]
# Time bonus
if self.config['time_bonus']:
bonus += (participation.end_time - time).total_seconds() // 60 // self.config['time_bonus']
if self.config["time_bonus"]:
bonus += (
(participation.end_time - time).total_seconds()
// 60
// self.config["time_bonus"]
)
points += bonus
format_data[str(prob)] = {'time': dt, 'points': score, 'bonus': bonus}
format_data[str(prob)] = {"time": dt, "points": score, "bonus": bonus}
points += score
participation.cumtime = cumtime
@ -99,25 +114,47 @@ class ECOOContestFormat(DefaultContestFormat):
def display_user_problem(self, participation, contest_problem):
format_data = (participation.format_data or {}).get(str(contest_problem.id))
if format_data:
bonus = format_html('<small> +{bonus}</small>',
bonus=floatformat(format_data['bonus'])) if format_data['bonus'] else ''
bonus = (
format_html(
"<small> +{bonus}</small>", bonus=floatformat(format_data["bonus"])
)
if format_data["bonus"]
else ""
)
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)),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
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"]),
bonus=bonus,
time=nice_repr(timedelta(seconds=format_data['time']), 'noday'),
time=nice_repr(timedelta(seconds=format_data["time"]), "noday"),
)
else:
return mark_safe('<td></td>')
return mark_safe("<td></td>")
def display_participation_result(self, participation):
return format_html(
'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
points=floatformat(participation.score),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday') if self.config['cumtime'] else '',
cumtime=nice_repr(timedelta(seconds=participation.cumtime), "noday")
if self.config["cumtime"]
else "",
)

View file

@ -14,14 +14,14 @@ from judge.timezone import from_database_time
from judge.utils.timedelta import nice_repr
@register_contest_format('icpc')
@register_contest_format("icpc")
class ICPCContestFormat(DefaultContestFormat):
name = gettext_lazy('ICPC')
config_defaults = {'penalty': 20}
config_validators = {'penalty': lambda x: x >= 0}
'''
name = gettext_lazy("ICPC")
config_defaults = {"penalty": 20}
config_validators = {"penalty": lambda x: x >= 0}
"""
penalty: Number of penalty minutes each incorrect submission adds. Defaults to 20.
'''
"""
@classmethod
def validate(cls, config):
@ -29,7 +29,9 @@ class ICPCContestFormat(DefaultContestFormat):
return
if not isinstance(config, dict):
raise ValidationError('ICPC-styled contest expects no config or dict as config')
raise ValidationError(
"ICPC-styled contest expects no config or dict as config"
)
for key, value in config.items():
if key not in cls.config_defaults:
@ -37,7 +39,9 @@ class ICPCContestFormat(DefaultContestFormat):
if not isinstance(value, type(cls.config_defaults[key])):
raise ValidationError('invalid type for config key "%s"' % key)
if not cls.config_validators[key](value):
raise ValidationError('invalid value "%s" for config key "%s"' % (value, key))
raise ValidationError(
'invalid value "%s" for config key "%s"' % (value, key)
)
def __init__(self, contest, config):
self.config = self.config_defaults.copy()
@ -52,7 +56,8 @@ class ICPCContestFormat(DefaultContestFormat):
format_data = {}
with connection.cursor() as cursor:
cursor.execute('''
cursor.execute(
"""
SELECT MAX(cs.points) as `points`, (
SELECT MIN(csub.date)
FROM judge_contestsubmission ccs LEFT OUTER JOIN
@ -63,21 +68,27 @@ class ICPCContestFormat(DefaultContestFormat):
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))
""",
(participation.id, participation.id),
)
for points, time, prob in cursor.fetchall():
time = from_database_time(time)
dt = (time - participation.start).total_seconds()
# Compute penalty
if self.config['penalty']:
if self.config["penalty"]:
# An IE can have a submission result of `None`
subs = participation.submissions.exclude(submission__result__isnull=True) \
.exclude(submission__result__in=['IE', 'CE']) \
.filter(problem_id=prob)
subs = (
participation.submissions.exclude(
submission__result__isnull=True
)
.exclude(submission__result__in=["IE", "CE"])
.filter(problem_id=prob)
)
if points:
prev = subs.filter(submission__date__lte=time).count() - 1
penalty += prev * self.config['penalty'] * 60
penalty += prev * self.config["penalty"] * 60
else:
# We should always display the penalty, even if the user has a score of 0
prev = subs.count()
@ -88,7 +99,7 @@ class ICPCContestFormat(DefaultContestFormat):
cumtime += dt
last = max(last, dt)
format_data[str(prob)] = {'time': dt, 'points': points, 'penalty': prev}
format_data[str(prob)] = {"time": dt, "points": points, "penalty": prev}
score += points
participation.cumtime = max(0, cumtime + penalty)
@ -100,23 +111,44 @@ class ICPCContestFormat(DefaultContestFormat):
def display_user_problem(self, participation, contest_problem):
format_data = (participation.format_data or {}).get(str(contest_problem.id))
if format_data:
penalty = format_html('<small style="color:red"> ({penalty})</small>',
penalty=floatformat(format_data['penalty'])) if format_data['penalty'] else ''
penalty = (
format_html(
'<small style="color:red"> ({penalty})</small>',
penalty=floatformat(format_data["penalty"]),
)
if format_data["penalty"]
else ""
)
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)),
url=reverse('contest_user_submissions',
args=[self.contest.key, participation.user.user.username, contest_problem.problem.code]),
points=floatformat(format_data['points']),
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"]),
penalty=penalty,
time=nice_repr(timedelta(seconds=format_data['time']), 'noday'),
time=nice_repr(timedelta(seconds=format_data["time"]), "noday"),
)
else:
return mark_safe('<td></td>')
return mark_safe("<td></td>")
def get_contest_problem_label_script(self):
return '''
return """
function(n)
n = n + 1
ret = ""
@ -126,4 +158,4 @@ class ICPCContestFormat(DefaultContestFormat):
end
return ret
end
'''
"""

View file

@ -14,13 +14,13 @@ from judge.timezone import from_database_time
from judge.utils.timedelta import nice_repr
@register_contest_format('ioi')
@register_contest_format("ioi")
class IOIContestFormat(DefaultContestFormat):
name = gettext_lazy('IOI')
config_defaults = {'cumtime': False}
'''
name = gettext_lazy("IOI")
config_defaults = {"cumtime": False}
"""
cumtime: Specify True if time penalties are to be computed. Defaults to False.
'''
"""
@classmethod
def validate(cls, config):
@ -28,7 +28,9 @@ class IOIContestFormat(DefaultContestFormat):
return
if not isinstance(config, dict):
raise ValidationError('IOI-styled contest expects no config or dict as config')
raise ValidationError(
"IOI-styled contest expects no config or dict as config"
)
for key, value in config.items():
if key not in cls.config_defaults:
@ -47,7 +49,8 @@ class IOIContestFormat(DefaultContestFormat):
format_data = {}
with connection.cursor() as cursor:
cursor.execute('''
cursor.execute(
"""
SELECT MAX(cs.points) as `score`, (
SELECT MIN(csub.date)
FROM judge_contestsubmission ccs LEFT OUTER JOIN
@ -58,17 +61,21 @@ class IOIContestFormat(DefaultContestFormat):
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))
""",
(participation.id, participation.id),
)
for score, time, prob in cursor.fetchall():
if self.config['cumtime']:
dt = (from_database_time(time) - participation.start).total_seconds()
if self.config["cumtime"]:
dt = (
from_database_time(time) - participation.start
).total_seconds()
if score:
cumtime += dt
else:
dt = 0
format_data[str(prob)] = {'time': dt, 'points': score}
format_data[str(prob)] = {"time": dt, "points": score}
points += score
participation.cumtime = max(cumtime, 0)
@ -82,12 +89,29 @@ class IOIContestFormat(DefaultContestFormat):
if format_data:
return format_html(
'<td class="{state} problem-score-col"><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)),
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') if self.config['cumtime'] else '',
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")
if self.config["cumtime"]
else "",
)
else:
return mark_safe('<td class="problem-score-col"></td>')
@ -96,5 +120,7 @@ class IOIContestFormat(DefaultContestFormat):
return format_html(
'<td class="user-points">{points}<div class="solving-time">{cumtime}</div></td>',
points=floatformat(participation.score),
cumtime=nice_repr(timedelta(seconds=participation.cumtime), 'noday') if self.config['cumtime'] else '',
cumtime=nice_repr(timedelta(seconds=participation.cumtime), "noday")
if self.config["cumtime"]
else "",
)