Source code for oioioi.acm.score

from functools import total_ordering

from django.utils.translation import gettext as _

from oioioi.contests.scores import ScoreValue


[docs]def format_time(seconds): minutes = seconds // 60 return '%d:%02d' % (minutes // 60, minutes % 60)
@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. """
[docs] symbol = 'bool'
[docs] accepted = False
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] symbol = 'ACM'
[docs] problems_solved = 0
[docs] time_passed = 0 # in seconds
[docs] penalties_count = 0
[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