from functools import total_ordering
from django.utils.translation import gettext as _
from oioioi.contests.scores import ScoreValue
@total_ordering
[docs]class BinaryScore(ScoreValue):
"""Score representing binary grading: accepted or rejected.
Sum of binary scores is accepted only when every single score were
accepted.
"""
def __init__(self, solved=False):
self.accepted = solved
[docs] def __add__(self, other):
return BinaryScore(self.accepted and other.accepted)
[docs] def __eq__(self, other):
if other is None:
return False
return self.accepted == other.accepted
[docs] def __lt__(self, other):
if other is None:
return False
return self.accepted < other.accepted
[docs] def __hash__(self):
return self.accepted
@classmethod
[docs] def _from_repr(cls, value):
return BinaryScore(value == 'accepted')
[docs] def _to_repr(self):
return 'accepted' if self.accepted else 'rejected'
[docs] def __unicode__(self):
if self.accepted:
return _("Accepted")
else:
return _("Rejected")
[docs] def to_int(self):
return int(self.accepted)
@total_ordering
[docs]class ACMScore(ScoreValue):
"""ACM style score consisting of number of solved problems, total time
needed for solving problems and time penalty for each
unsuccessful submission.
NOTE: When adding :class:`ACMScore`s only scores with positive
:attr:`problems_solved` are considered to avoid adding
:attr:`time_passed` or :attr:`penalties_count`
when :attr:`problems_solved` equals zero. That's because ACM ICPC rules
states that team doesn't obtain any penalty for nonsolved problems.
"""
[docs] time_passed = 0 # in seconds
[docs] penalty_time = 20 * 60 # in seconds
def __init__(self, problems_solved=0, time_passed=0, penalties_count=0):
self.problems_solved = int(problems_solved)
self.time_passed = int(time_passed)
self.penalties_count = int(penalties_count)
[docs] def __add__(self, other):
sum = ACMScore()
if self.problems_solved > 0:
sum.problems_solved += self.problems_solved
sum.time_passed += self.time_passed
sum.penalties_count += self.penalties_count
if other.problems_solved > 0:
sum.problems_solved += other.problems_solved
sum.time_passed += other.time_passed
sum.penalties_count += other.penalties_count
return sum
[docs] def __eq__(self, other):
if other is None:
return False
return (self.problems_solved, -self.total_time) == (
other.problems_solved,
-other.total_time,
)
[docs] def __lt__(self, other):
if other is None:
return False
return (self.problems_solved, -self.total_time) < (
other.problems_solved,
-other.total_time,
)
[docs] def __hash__(self):
return self.total_time
[docs] def __unicode__(self):
penalty_string = self.penalty_repr()
time_string = ''
if self.problems_solved > 0:
time_string = self.time_passed_repr()
if penalty_string != '':
time_string += ' '
return str(time_string + penalty_string)
[docs] def csv_repr(self):
if self.problems_solved == 0:
return ''
return str(self.penalties_count)
[docs] def penalty_repr(self):
if self.penalties_count <= 3:
return '*' * self.penalties_count
else:
return '*(%d)' % (self.penalties_count,)
[docs] def total_time_repr(self):
return '%d:%02d:%02d' % (
self.total_time / 3600,
(self.total_time % 3600) / 60,
self.total_time % 60,
)
[docs] def time_passed_repr(self):
return format_time(self.time_passed)
@classmethod
[docs] def _from_repr(cls, value):
tokens = [int(x) for x in value.split(':')]
try:
_ordering, problems_solved, time_passed, penalties_count = tokens
except ValueError:
# try decoding older format
problems_solved, time_passed, penalties_count = tokens
return ACMScore(problems_solved, time_passed, penalties_count)
[docs] def _to_repr(self):
"""Store score as string \
``"ACM:problems_solved:total_time:penalties_count"`` where:
``problems_solved`` is number of problems solved,
``total_time`` is total number of seconds needed to solve problems,
``penalties_count`` is number of unsuccessful submissions.
"""
ordering = 10 ** 10 * (self.problems_solved + 1) - self.total_time
return '%020d:%010d:%010d:%010d' % (
ordering,
self.problems_solved,
self.time_passed,
self.penalties_count,
)
@property
[docs] def total_time(self):
if self.problems_solved > 0:
return self.time_passed + self.penalties_count * self.penalty_time
else:
return 0
[docs] def to_int(self):
return self.problems_solved