def __unicode__(self):
		"""
		Returns a string representation
		"""
		if self.end_time is not None:
			return self.place.name + u" du " + self.start_time.astimezone(tz()).strftime(u"%d/%m/%Y %H:%M") + u" au " + self.end_time.astimezone(tz()).strftime(u"%d/%m/%Y %H:%M")
		else:
			return self.place.name + u" du " + self.start_time.astimezone(tz()).strftime(u"%d/%m/%Y %H:%M") + u" à maintenant"
Beispiel #2
0
	def __unicode__(self):
		"""
		Returns a string representation
		"""
		if self.end_time is not None:
			return self.place.name + u" du " + self.start_time.astimezone(tz()).strftime(u"%d/%m/%Y %H:%M") + u" au " + self.end_time.astimezone(tz()).strftime(u"%d/%m/%Y %H:%M")
		else:
			return self.place.name + u" du " + self.start_time.astimezone(tz()).strftime(u"%d/%m/%Y %H:%M") + u" à maintenant"
	def current_opening(self):
		"""
		Return the current opening if any, or None
		"""
		now = datetime.now(tz())
		try:
			return self.openings.get(Q(start_time__lte=now, end_time__gt=now) | Q(start_time__lte=now, end_time=None))
		except PlaceOpening.DoesNotExist:
			return None
Beispiel #4
0
	def current_opening(self):
		"""
		Return the current opening if any, or None
		"""
		now = datetime.now(tz())
		try:
			return self.openings.get(Q(start_time__lte=now, end_time__gt=now) | Q(start_time__lte=now, end_time=None))
		except PlaceOpening.DoesNotExist:
			return None
Beispiel #5
0
        def process_match_row(row, tournament):
            try:
                # Some of them store in decimal (% of day passed).
                days = int(float(row[1]))
                seconds = (float(row[1]) % 1) * 86400  # 86400 in 1 day.
                # hour, minute, second, microsecond
                time = datetime.time(seconds // 3600, seconds // 60,
                                     seconds // 1, seconds % 1)

            except ValueError:
                # Otherwise attempt to match "(Day 1 )11:03(:00) AM".
                strtime = re.match(
                    "^(Day (?P<day>\d+) )?"
                    "(?P<hour>((0?|1)[0-9])|(2[0-3])):(?P<minute>[0-5][0-9])"
                    "(:(?P<second>[0-5][0-9]))? (?P<meridiem>[AP]M)$", row[1],
                    re.IGNORECASE)

                if strtime:

                    def getint(group):
                        # Helper function: make integer from regex group.
                        val = strtime.group(group)
                        if val is None:
                            return 0
                        return int(val)

                    # Days are 1-indexed (subtract 1), but None -> 0.
                    # By using max(0, day-1), it can't fall below 0.
                    days = max(0, getint('day') - 1)

                    # Calculate hour before instantiating immutable time().
                    hour = getint('hour')
                    if strtime.group('meridiem').upper() == "PM" and hour < 12:
                        hour += 12

                    # No microsecond value available here.
                    time = datetime.time(hour, getint('minute'),
                                         getint('second'))

                else:
                    raise ValueError(
                        _("Couldn't parse timestamp {!r}.").format(
                            row[1])) from None

            # We can't simply add a timedelta to the start date.
            # e.g. 11am on the day where daylight savings starts, hours=11 will
            # actually result in 12pm (2am-3am does not exist).
            time = datetime.datetime.combine(
                date + datetime.timedelta(days=days), time)
            time = tz().localize(time)

            players = defaultdict(dict)
            # Each field column is `(field * station) - 1` (zero-indexed).
            # e.g. A1,A2,B1,B2, etc. (works for any number of stations/fields).
            for col, team in enumerate(row[3:]):
                if not team:
                    continue  # No team, skip.
                team = int(team)

                field = col // len(STATIONS)
                if field > len(FIELDS):
                    # (Avoids FIELDS[field] IndexError, more details this way.)
                    raise ValueError(
                        _("Field number {0} too large (max {1}) (time {2}).").
                        format(field, len(FIELDS), time.isoformat()))

                players[field][col % len(STATIONS)] = team

            if not players:
                players[0] = {}  # Default to first field (no players).
            elif len(players) > 1:
                # Warn, but not a breaking error, even if extra supplied.
                self.stdout.write(
                    self.style.WARNING(
                        _("Splitting simultaneous match (time {}).").format(
                            time.isoformat())))

            for field in players:
                # Now save the objects to the database.
                number = 1
                round = 1
                last = Match.objects.filter(
                    tournament=tournament).order_by('number').last()
                if last is not None:
                    number = last.number + 1
                    round = last.round

                # Enum value by index for field.
                match = Match(tournament=tournament,
                              number=number,
                              round=round,
                              field=FIELDS[field],
                              schedule=time,
                              actual=None)
                match.full_clean()  # Ensure friendly errors.
                match.save()

                # Find players that fail full_clean() (duplicate team/round).
                clean_players = []
                dirty_players = []  # "Clean failed."
                for stn, team in players[field].items():
                    team = Team.objects.get(number=team)
                    # Get station enum value by index.
                    player = Player(team=team,
                                    match=match,
                                    station=STATIONS[stn],
                                    surrogate=False)
                    try:
                        player.full_clean()
                        # No exceptions, so it's clean.
                        clean_players.append(player)
                    except ValidationError:
                        # Too difficult to ensure correct ValidationError, so
                        # just assume it is. Presumably any db constraints will
                        # restrict all the important things anyway.
                        dirty_players.append(player)

                # If (players exist, and) all are repeats, then next round.
                if dirty_players and not clean_players:
                    match.round += 1
                    match.save()  # During setup, no race condition F(...).
                # Else, make the extras surrogates.
                else:
                    for p in dirty_players:
                        p.surrogate = True
                # Finally, save all.
                clean_players.extend(dirty_players)
                for p in clean_players:
                    p.full_clean()  # Ensure friendly errors.
                    p.save()