def refresh(self): self.isEmpty = True self.history = None self.category = None self.rcInterp = set() self.rcNumTime = set() self.search.SelectAll() wx.CallAfter(self.Refresh) race = Model.race if race is None: self.clearGrid() return lastGridX, lastGridY = self.grid.GetViewStart() highPrecision = Model.highPrecisionTimes() if highPrecision or race.isTimeTrial: formatTime = lambda t: Utils.formatTime(t, True) formatTimeDiff = lambda a, b: Utils.formatTimeGap( TimeDifference(a, b, True), True) else: formatTime = Utils.formatTime formatTimeDiff = lambda a, b: Utils.formatTimeGap( TimeDifference(a, b, False), False) category = FixCategories(self.categoryChoice, getattr(race, 'historyCategory', 0), doSyncCategories=self.sync.GetValue()) self.hbs.Layout() Finisher = Model.Rider.Finisher results = GetResults(category) lapsDown = { rr.num: rr.gap for rr in results if unicode(rr.gap).startswith('-') } position = { rr.num: pos for pos, rr in enumerate(results, 1) if rr.status == Finisher } winnerLaps = None if results and results[0].status == Finisher: winnerLaps = results[0].laps maxLaps = 0 doLapsToGo = True if race.winAndOut: entries = GetEntries(category) if entries: try: maxLaps = max(e.lap for e in entries if not e.interp) except ValueError: pass if race.isRunning(): maxLaps += 2 else: try: maxLaps = race.getNumLapsFromCategory(category) except Exception as e: maxLaps = race.numLaps doLapsToGo = True if not maxLaps: maxLaps = race.getMaxLap() if race.isRunning(): maxLaps += 2 doLapsToGo = False entries = GetEntries(category) if maxLaps: entries = [e for e in entries if e.lap <= maxLaps] entries = [ e for e in entries if e.lap <= race.getCategoryNumLaps(e.num) ] if race.isTimeTrial: entries = [ Model.Entry(e.num, e.lap, (race.riders[e.num].firstTime or 0.0) + e.t, e.interp) for e in entries ] entries.sort(key=operator.attrgetter('t', 'num')) # Collect the number and times for all entries so we can compute lap times. numTimes = {(e.num, e.lap): e.t for e in entries} self.category = category # Trim out the lap 0 starts. entries = [e for e in entries if e.lap > 0] if not entries: self.clearGrid() return # Organize all the entries into a grid as we would like to see them. self.history = [[]] numSeen = set() lapCur = 0 leaderTimes = [entries[0].t] for e in entries: if e.num in numSeen: numSeen.clear() lapCur += 1 self.history.append([]) leaderTimes.append(e.t) self.history[lapCur].append(e) numSeen.add(e.num) if not any(h for h in self.history): self.clearGrid() return # Show the values. self.isEmpty = False numTimeInfo = race.numTimeInfo colnames = [] raceTime = 0 for c, h in enumerate(self.history): try: lapTime = h[0].t - raceTime raceTime = h[0].t except IndexError as e: lapTime = 0 colnames.append('{}\n{}\n{}\n{}'.format( c + 1, (maxLaps - c - 1) if doLapsToGo else ' ', formatTime(lapTime), formatTime(raceTime))) formatStr = ['$num'] if self.showTimes: formatStr.append(', $raceTime') if self.showLapTimes: formatStr.append(', $lapTime') if self.showTimeDown: formatStr.append(', $downTime') if self.showRiderName: formatStr.append(', $riderName') template = Template(u''.join(formatStr)) try: info = race.excelLink.read() except: info = {} def getName(num): d = info.get(num, {}) return u', '.join( v for v in [d.get('LastName', None), d.get('FirstName', None)] if v) templateSave = template data = [] for col, h in enumerate(self.history): template = templateSave if col + 1 == winnerLaps: if self.showPosition: formatStr.insert(0, '$pos$lapsDown: ') template = Template(u''.join(formatStr)) data.append([ template.safe_substitute({ 'num': e.num, 'pos': Utils.ordinal(position.get(e.num, '')), 'lapsDown': u' ({})'.format(lapsDown[e.num]) if e.num in lapsDown else u'', 'raceTime': formatTime(e.t) if self.showTimes else '', 'lapTime': formatTime(e.t - numTimes[(e.num, e.lap - 1)]) if self.showLapTimes and (e.num, e.lap - 1) in numTimes else '', 'downTime': formatTimeDiff(e.t, leaderTimes[col]) if self.showTimeDown and col < len(leaderTimes) else '', 'riderName': getName(e.num) if self.showRiderName else '', }) for e in h ]) self.rcInterp.update( (row, col) for row, e in enumerate(h) if e.interp) self.rcNumTime.update( (row, col) for row, e in enumerate(h) if numTimeInfo.getInfo(e.num, e.t) is not None) self.grid.Set(data=data, colnames=colnames) self.grid.AutoSizeColumns(True) self.grid.Reset() self.updateColours() self.grid.Set(textColour=self.textColour, backgroundColour=self.backgroundColour) # Fix the grid's scrollbars. self.grid.FitInside() self.grid.Scroll(lastGridX, lastGridY)
def GetSituationGaps( category=None, t=None ): race = Model.race if not race: return [] if t is None: t = race.lastRaceTime() if not race.isRunning() else (datetime.datetime.now() - race.startTime).total_seconds() # Collect the race times from the results data. Finisher = Model.Rider.Finisher raceTimes, riderName = {}, {} for rr in GetResults(category): if not (rr.raceTimes and len(rr.raceTimes) >= 2) or rr._lastTimeOrig < t: continue raceTimes[rr.num] = rr.raceTimes riderName[rr.num] = rr.short_name(15) if not raceTimes: return [] t = min( t, max(rt[-1] for rt in six.itervalues(raceTimes)) ) psLeader = (-1, -1, None) positionSpeeds = [] for bib, rt in six.iteritems(raceTimes): position, speed = GetPositionSpeed(t, rt) positionSpeeds.append( (position, speed, bib) ) if positionSpeeds[-1][0] > psLeader[0]: psLeader = positionSpeeds[-1] leaderPosition, leaderSpeed, leaderRaceTimes = psLeader[0], psLeader[1], raceTimes[psLeader[2]] try: externalInfo = race.excelLink.read() except: externalInfo = {} def getInfo( bib, lapsDown ): name = riderName[bib] nameStr = u'' if not name else u' ' + name if lapsDown: lapsDownStr = u' ({})'.format(lapsDown) bibStr = u'\u2198{}'.format(bib) else: lapsDownStr = u'' bibStr = six.text_type(bib) return u''.join([bibStr, nameStr, lapsDownStr]) gaps = [] for riderPosition, riderSpeed, bib in positionSpeeds: try: gap, lapsDown = GetLeaderGap( t, leaderPosition, leaderSpeed, leaderRaceTimes, riderPosition, riderSpeed, raceTimes[bib] ) except TypeError: continue if gap is not None: gaps.append( (gap, getInfo(bib, lapsDown)) ) gaps.sort() if gaps: gapMin = gaps[0][0] gaps = [[TimeDifference(g[0], gapMin), g[1]] for g in gaps] thisLap = GetLapLE(t, leaderRaceTimes) tCur = t tClock = race.raceTimeToClockTime( tCur ) tETA = leaderRaceTimes[thisLap+1] - t if thisLap+1 != len(leaderRaceTimes) else None tAfterLeader = t - leaderRaceTimes[thisLap] laps = len(leaderRaceTimes) - 1 lap = min( thisLap + 1, laps ) lapsToGo = max(laps - lap, 0) title = u' {}: {}/{} {}: {}'.format( _('Lap'), lap, laps, _('Laps to go'), lapsToGo, ) if tCur is not None: title += u' {}: {}'.format(_('Race'), Utils.formatTime(tCur)) if tClock is not None: if title: title += u' {}: {}'.format(_('Clock'), Utils.formatTime(tClock)) if tETA is not None: title += u' {}: {}'.format(_('Leader ETA'), Utils.formatTime(tETA)) return gaps, tAfterLeader, title, tCur