Ejemplo n.º 1
0
    def set_seat_frequency(self, frequency):
        FREQUENCY_TIMEOUT = 10

        time_now = monotonic()
        time_expires = time_now + FREQUENCY_TIMEOUT
        self.set_message_direct(
            __("!!! Frequency changing to {0} in <10s !!!").format(frequency))
        gevent.sleep(10)

        self.set_seat_frequency_direct(frequency)
        self.set_message_direct(__(""))
Ejemplo n.º 2
0
 def getClusterStatusInfo(self):
     nowTime = monotonic()
     payload = []
     for slave in self.slaves:
         upTimeSecs = int(round(
             nowTime -
             slave.firstContactTime)) if slave.lastContactTime > 0 else 0
         downTimeSecs = int(round(slave.secsSinceDisconnect)
                            ) if slave.lastContactTime <= 0 else 0
         totalUpSecs = slave.totalUpTimeSecs + upTimeSecs
         totalDownSecs = slave.totalDownTimeSecs + downTimeSecs
         payload.append(
             {'address': slave.address, \
              'modeIndicator': ('M' if slave.isMirrorMode else 'S'), \
              'minLatencyMs':  slave.latencyAveragerObj.minVal, \
              'avgLatencyMs': slave.latencyAveragerObj.getIntAvgVal(), \
              'maxLatencyMs': slave.latencyAveragerObj.maxVal, \
              'lastLatencyMs': slave.latencyAveragerObj.lastVal, \
              'numDisconnects': slave.numDisconnects, \
              'numContacts': slave.numContacts, \
              'timeDiffMs': slave.timeDiffMedianMs, \
              'upTimeSecs': upTimeSecs, \
              'downTimeSecs': downTimeSecs, \
              'availability': round((100.0*totalUpSecs/(totalUpSecs+totalDownSecs) \
                                    if totalUpSecs+totalDownSecs > 0 else 0), 1), \
              'last_contact': int(nowTime-slave.lastContactTime) if slave.lastContactTime >= 0 else \
                              (__("connection lost") if slave.numDisconnects > 0 else __("never connected"))
              })
     return {'slaves': payload}
Ejemplo n.º 3
0
    def do_heat_set(self, arg):
        self.logger.info("VRx Signaling Heat Set")
        try:
            heat_id = arg["heat_id"]
        except KeyError:
            self.logger.error(
                "Unable to send callsigns. heat_id not found in event.")
            return

        for heatseat in Database.HeatNode.query.filter_by(
                heat_id=heat_id).all():
            heatseat_index = heatseat.seat_index
            if heatseat_index < self.num_seats:  # TODO this may break with non-contiguous nodes
                if heatseat.pilot_id != Database.PILOT_ID_NONE:
                    pilot = Database.Pilot.query.get(heatseat.pilot_id)
                    self.set_message_direct(heatseat_index, pilot.callsign)
                else:
                    self.set_message_direct(heatseat_index, __("-None-"))
Ejemplo n.º 4
0
    def do_heat_set(self, arg):
        self.logger.info("VRx Signaling Heat Set")
        try:
            heat_id = arg["heat_id"]
        except KeyError:
            self.logger.error(
                "Unable to send callsigns. heat_id not found in event.")
            return
        try:
            RACE = arg["race"]
        except KeyError:
            self.logger.error(
                "Unable to send callsigns. RACE not found in event")
            return

        for heatnode in Database.HeatNode.query.filter_by(
                heat_id=heat_id).all():
            if heatnode.node_index < self.num_nodes:
                if heatnode.pilot_id != Database.PILOT_ID_NONE:
                    pilot = Database.Pilot.query.get(heatnode.pilot_id)
                    self.set_message_direct(heatnode.node_index,
                                            pilot.callsign)
                else:
                    self.set_message_direct(heatnode.node_index, __("-None-"))
Ejemplo n.º 5
0
 def set_seat_frequency(self, seat_number, frequency):
     fmsg = __("Frequency Change: ") + str(frequency)
     seat = self._seats[seat_number]
     seat.set_seat_frequency(frequency)
Ejemplo n.º 6
0
    def do_lap_recorded(self, args):
        '''
        *** TODO: Formatting for hardware (OSD length, etc.)
        '''

        RESULTS_TIMEOUT = 5  # maximum time to wait for results to generate
        LAP_HEADER = Options.get('osd_lapHeader')
        POS_HEADER = Options.get('osd_positionHeader')

        if 'node_index' in args:
            seat_index = args['node_index']
        else:
            self.logger.warning('Failed to send results: Seat not specified')
            return False

        # wait for results to generate
        time_now = monotonic()
        timeout = time_now + RESULTS_TIMEOUT
        while self.RACE.cacheStatus != Results.CacheStatus.VALID and time_now < timeout:
            time_now = monotonic()
            gevent.sleep()

        if self.RACE.cacheStatus == Results.CacheStatus.VALID:
            '''
            Get relevant results
            '''

            results = self.RACE.results

            # select correct results
            # *** leaderboard = results[results['meta']['primary_leaderboard']]
            win_condition = self.RACE.format.win_condition

            if win_condition == WinCondition.FASTEST_3_CONSECUTIVE:
                leaderboard = results['by_consecutives']
            elif win_condition == WinCondition.FASTEST_LAP:
                leaderboard = results['by_fastest_lap']
            else:
                # WinCondition.MOST_LAPS
                # WinCondition.FIRST_TO_LAP_X
                # WinCondition.NONE
                leaderboard = results['by_race_time']

            # get this seat's results
            for index, result in enumerate(leaderboard):
                if result['node'] == seat_index:  #TODO issue408
                    rank_index = index
                    break

            # check for best lap
            is_best_lap = False
            if result['fastest_lap_raw'] == result['last_lap_raw']:
                is_best_lap = True

            # get the next faster results
            next_rank_split = None
            next_rank_split_result = None
            if result['position'] > 1:
                next_rank_split_result = leaderboard[rank_index - 1]

                if next_rank_split_result['total_time_raw']:
                    if win_condition == WinCondition.FASTEST_3_CONSECUTIVE:
                        if next_rank_split_result['consecutives_raw']:
                            next_rank_split = result[
                                'consecutives_raw'] - next_rank_split_result[
                                    'consecutives_raw']
                    elif win_condition == WinCondition.FASTEST_LAP:
                        if next_rank_split_result['fastest_lap_raw']:
                            next_rank_split = result[
                                'last_lap_raw'] - next_rank_split_result[
                                    'fastest_lap_raw']
                    else:
                        # WinCondition.MOST_LAPS
                        # WinCondition.FIRST_TO_LAP_X
                        next_rank_split = result[
                            'total_time_raw'] - next_rank_split_result[
                                'total_time_raw']
                        next_rank_split_fastest = ''
            else:
                # check split to self
                next_rank_split_result = leaderboard[rank_index]

                if win_condition == WinCondition.FASTEST_3_CONSECUTIVE or win_condition == WinCondition.FASTEST_LAP:
                    if next_rank_split_result['fastest_lap_raw']:
                        if result['last_lap_raw'] > next_rank_split_result[
                                'fastest_lap_raw']:
                            next_rank_split = result[
                                'last_lap_raw'] - next_rank_split_result[
                                    'fastest_lap_raw']

            # get the next slower results
            prev_rank_split = None
            prev_rank_split_result = None
            if rank_index + 1 in leaderboard:
                prev_rank_split_result = leaderboard[rank_index - 1]

                if prev_rank_split_result['total_time_raw']:
                    if win_condition == WinCondition.FASTEST_3_CONSECUTIVE:
                        if prev_rank_split_result['consecutives_raw']:
                            prev_rank_split = result[
                                'consecutives_raw'] - prev_rank_split_result[
                                    'consecutives_raw']
                            prev_rank_split_fastest = prev_rank_split
                    elif win_condition == WinCondition.FASTEST_LAP:
                        if prev_rank_split_result['fastest_lap_raw']:
                            prev_rank_split = result[
                                'last_lap_raw'] - prev_rank_split_result[
                                    'fastest_lap_raw']
                            prev_rank_split_fastest = result[
                                'fastest_lap_raw'] - prev_rank_split_result[
                                    'fastest_lap_raw']
                    else:
                        # WinCondition.MOST_LAPS
                        # WinCondition.FIRST_TO_LAP_X
                        prev_rank_split = result[
                            'total_time_raw'] - prev_rank_split_result[
                                'total_time_raw']
                        prev_rank_split_fastest = ''

            # get the fastest result
            first_rank_split = None
            first_rank_split_result = None
            if result['position'] > 2:
                first_rank_split_result = leaderboard[0]

                if next_rank_split_result['total_time_raw']:
                    if win_condition == WinCondition.FASTEST_3_CONSECUTIVE:
                        if first_rank_split_result['consecutives_raw']:
                            first_rank_split = result[
                                'consecutives_raw'] - first_rank_split_result[
                                    'consecutives_raw']
                    elif win_condition == WinCondition.FASTEST_LAP:
                        if first_rank_split_result['fastest_lap_raw']:
                            first_rank_split = result[
                                'last_lap_raw'] - first_rank_split_result[
                                    'fastest_lap_raw']
                    else:
                        # WinCondition.MOST_LAPS
                        # WinCondition.FIRST_TO_LAP_X
                        first_rank_split = result[
                            'total_time_raw'] - first_rank_split_result[
                                'total_time_raw']
            '''
            Set up output objects
            '''

            osd = {
                'position_prefix': POS_HEADER,
                'position': str(result['position']),
                'callsign': result['callsign'],
                'lap_prefix': LAP_HEADER,
                'lap_number': '',
                'last_lap_time': '',
                'total_time': result['total_time'],
                'total_time_laps': result['total_time_laps'],
                'consecutives': result['consecutives'],
                'is_best_lap': is_best_lap,
            }

            if result['laps']:
                osd['lap_number'] = str(result['laps'])
                osd['last_lap_time'] = result['last_lap']
            else:
                osd['lap_prefix'] = ''
                osd['lap_number'] = __('HS')
                osd['last_lap_time'] = result['total_time']
                osd['is_best_lap'] = False

            if next_rank_split:
                osd_next_split = {
                    'position_prefix': POS_HEADER,
                    'position': str(next_rank_split_result['position']),
                    'callsign': next_rank_split_result['callsign'],
                    'split_time': RHUtils.time_format(next_rank_split),
                }

                osd_next_rank = {
                    'position_prefix': POS_HEADER,
                    'position': str(next_rank_split_result['position']),
                    'callsign': next_rank_split_result['callsign'],
                    'lap_prefix': LAP_HEADER,
                    'lap_number': '',
                    'last_lap_time': '',
                    'total_time': result['total_time'],
                }

                if next_rank_split_result['laps']:
                    osd_next_rank['lap_number'] = str(
                        next_rank_split_result['laps'])
                    osd_next_rank['last_lap_time'] = next_rank_split_result[
                        'last_lap']
                else:
                    osd_next_rank['lap_prefix'] = ''
                    osd_next_rank['lap_number'] = __('HS')
                    osd_next_rank['last_lap_time'] = next_rank_split_result[
                        'total_time']

            if first_rank_split:
                osd_first_split = {
                    'position_prefix': POS_HEADER,
                    'position': str(first_rank_split_result['position']),
                    'callsign': first_rank_split_result['callsign'],
                    'split_time': RHUtils.time_format(first_rank_split),
                }
            '''
            Format and send messages
            '''

            # "Pos-Callsign L[n]|0:00:00"
            message = osd['position_prefix'] + osd['position'] + '-' + osd[
                'callsign'][:10] + ' ' + osd['lap_prefix'] + osd[
                    'lap_number'] + '|' + osd['last_lap_time']

            if win_condition == WinCondition.FASTEST_3_CONSECUTIVE:
                # "Pos-Callsign L[n]|0:00:00 | #/0:00.000" (current | best consecutives)
                if result['laps'] >= 3:
                    message += ' | 3/' + osd['consecutives']
                elif result['laps'] == 2:
                    message += ' | 2/' + osd['total_time_laps']

            elif win_condition == WinCondition.FASTEST_LAP:
                if next_rank_split:
                    # pilot in 2nd or lower
                    # "Pos-Callsign L[n]|0:00:00 / +0:00.000 Callsign"
                    message += ' / +' + osd_next_split[
                        'split_time'] + ' ' + osd_next_split['callsign'][:10]
                elif osd['is_best_lap']:
                    # pilot in 1st and is best lap
                    # "Pos:Callsign L[n]:0:00:00 / Best"
                    message += ' / ' + __('Best Lap')
            else:
                # WinCondition.MOST_LAPS
                # WinCondition.FIRST_TO_LAP_X
                # WinCondition.NONE

                # "Pos-Callsign L[n]|0:00:00 / +0:00.000 Callsign"
                if next_rank_split:
                    message += ' / +' + osd_next_split[
                        'split_time'] + ' ' + osd_next_split['callsign'][:10]

            # send message to crosser
            seat_dest = seat_index
            self.set_message_direct(seat_dest, message)
            self.logger.debug('msg n{1}:  {0}'.format(message, seat_dest))

            # show split when next pilot crosses
            if next_rank_split:
                if win_condition == WinCondition.FASTEST_3_CONSECUTIVE or win_condition == WinCondition.FASTEST_LAP:
                    # don't update
                    pass

                else:
                    # WinCondition.MOST_LAPS
                    # WinCondition.FIRST_TO_LAP_X
                    # WinCondition.NONE

                    # update pilot ahead with split-behind

                    # "Pos-Callsign L[n]|0:00:00"
                    message = osd_next_rank['position_prefix'] + osd_next_rank[
                        'position'] + '-' + osd_next_rank[
                            'callsign'][:10] + ' ' + osd_next_rank[
                                'lap_prefix'] + osd_next_rank[
                                    'lap_number'] + '|' + osd_next_rank[
                                        'last_lap_time']

                    # "Pos-Callsign L[n]|0:00:00 / -0:00.000 Callsign"
                    message += ' / -' + osd_next_split[
                        'split_time'] + ' ' + osd['callsign'][:10]

                    seat_dest = leaderboard[rank_index - 1]['node']
                    self.set_message_direct(seat_dest, message)
                    self.logger.debug('msg n{1}:  {0}'.format(
                        message, seat_dest))

        else:
            self.logger.warning(
                'Failed to send results: Results not available')
            return False
Ejemplo n.º 7
0
 def do_race_stop(self, arg):
     self.logger.info("VRx Signaling Race Stop")
     self.set_message_direct(VRxALL, __("Race Stopped. Land Now."))
Ejemplo n.º 8
0
 def do_race_finish(self, arg):
     self.logger.info("VRx Signaling Race Finish")
     self.set_message_direct(VRxALL, __("Finish"))
Ejemplo n.º 9
0
 def do_race_start(self, arg):
     self.logger.info("VRx Signaling Race Start")
     self.set_message_direct(VRxALL, __("Go"))
Ejemplo n.º 10
0
 def do_race_stage(self, arg):
     self.logger.info("VRx Signaling Race Stage")
     self.set_message_direct(VRxALL, __("Ready"))
Ejemplo n.º 11
0
def calc_leaderboard(DB, **params):
    ''' Generates leaderboards '''
    USE_CURRENT = False
    USE_ROUND = None
    USE_HEAT = None
    USE_CLASS = None

    if ('current_race' in params):
        USE_CURRENT = True

    if ('class_id' in params):
        USE_CLASS = params['class_id']
    elif ('round_id' in params and 'heat_id' in params):
        USE_ROUND = params['round_id']
        USE_HEAT = params['heat_id']
    elif ('heat_id' in params):
        USE_ROUND = None
        USE_HEAT = params['heat_id']

    # Get profile (current), frequencies (current), race query (saved), and race format (all)
    if USE_CURRENT:
        profile = params['current_profile']
        profile_freqs = json.loads(profile.frequencies)
        RACE = params['current_race']
        race_format = RACE.format
    else:
        if USE_CLASS:
            race_query = Database.SavedRaceMeta.query.filter_by(class_id=USE_CLASS)
            if race_query.count() >= 1:
                current_format = Database.RaceClass.query.get(USE_CLASS).format_id
            else:
                current_format = None
        elif USE_HEAT:
            if USE_ROUND:
                race_query = Database.SavedRaceMeta.query.filter_by(heat_id=USE_HEAT, round_id=USE_ROUND)
                current_format = race_query.first().format_id
            else:
                race_query = Database.SavedRaceMeta.query.filter_by(heat_id=USE_HEAT)
                if race_query.count() >= 1:
                    heat_class = race_query.first().class_id
                    if heat_class:
                        current_format = Database.RaceClass.query.get(heat_class).format_id
                    else:
                        current_format = None
                else:
                    current_format = None
        else:
            race_query = Database.SavedRaceMeta.query
            current_format = None

        selected_races = race_query.all()
        racelist = [r.id for r in selected_races]

        if current_format:
            race_format = Database.RaceFormat.query.get(current_format)
        else:
            race_format = None

    gevent.sleep()
    # Get the pilot ids for all relevant races
    # Add pilot callsigns
    # Add pilot team names
    # Get total laps for each pilot
    # Get hole shot laps
    pilot_ids = []
    callsigns = []
    nodes = []
    team_names = []
    max_laps = []
    current_laps = []
    holeshots = []

    for pilot in Database.Pilot.query.filter(Database.Pilot.id != Database.PILOT_ID_NONE):
        gevent.sleep()
        if USE_CURRENT:
            laps = []
            for node_index in RACE.node_pilots:
                if RACE.node_pilots[node_index] == pilot.id and node_index < RACE.num_nodes:
                    laps = RACE.get_active_laps()[node_index]
                    break

            if laps:
                max_lap = len(laps) - 1
            else:
                max_lap = 0

            current_heat = Database.HeatNode.query.filter_by(heat_id=RACE.current_heat, pilot_id=pilot.id).first()
            if current_heat and profile_freqs["f"][current_heat.node_index] != RHUtils.FREQUENCY_ID_NONE:
                pilot_ids.append(pilot.id)
                callsigns.append(pilot.callsign)
                nodes.append(current_heat.node_index)
                team_names.append(pilot.team)
                max_laps.append(max_lap)
                current_laps.append(laps)
        else:
            # find hole shots
            holeshot_laps = []
            pilotnode = None
            for race in racelist:
                pilotraces = Database.SavedPilotRace.query \
                    .filter(Database.SavedPilotRace.pilot_id == pilot.id, \
                    Database.SavedPilotRace.race_id == race \
                    ).all()

                if len(pilotraces):
                    pilotnode = pilotraces[-1].node_index

                for pilotrace in pilotraces:
                    gevent.sleep()
                    holeshot_lap = Database.SavedRaceLap.query \
                        .filter(Database.SavedRaceLap.pilotrace_id == pilotrace.id, \
                            Database.SavedRaceLap.deleted != 1, \
                            ).order_by(Database.SavedRaceLap.lap_time_stamp).first()

                    if holeshot_lap:
                        holeshot_laps.append(holeshot_lap.id)

            # get total laps
            stat_query = DB.session.query(DB.func.count(Database.SavedRaceLap.id)) \
                .filter(Database.SavedRaceLap.pilot_id == pilot.id, \
                    Database.SavedRaceLap.deleted != 1, \
                    Database.SavedRaceLap.race_id.in_(racelist), \
                    ~Database.SavedRaceLap.id.in_(holeshot_laps))

            max_lap = stat_query.scalar()
            if max_lap > 0:
                pilot_ids.append(pilot.id)
                callsigns.append(pilot.callsign)
                team_names.append(pilot.team)
                max_laps.append(max_lap)
                holeshots.append(holeshot_laps)
                nodes.append(pilotnode)

    total_time = []
    total_time_laps = []
    last_lap = []
    average_lap = []
    fastest_lap = []
    consecutives = []
    fastest_lap_source = []
    consecutives_source = []

    for i, pilot in enumerate(pilot_ids):
        gevent.sleep()
        # Get the total race time for each pilot
        if USE_CURRENT:
            race_total = 0
            laps_total = 0
            for lap in current_laps[i]:
                race_total += lap['lap_time']
                if lap > 0:
                    laps_total += lap['lap_time']

            total_time.append(race_total)
            total_time_laps.append(laps_total)

        else:
            stat_query = DB.session.query(DB.func.sum(Database.SavedRaceLap.lap_time)) \
                .filter(Database.SavedRaceLap.pilot_id == pilot, \
                    Database.SavedRaceLap.deleted != 1, \
                    Database.SavedRaceLap.race_id.in_(racelist))

            if stat_query.scalar():
                total_time.append(stat_query.scalar())
            else:
                total_time.append(0)

            stat_query = DB.session.query(DB.func.sum(Database.SavedRaceLap.lap_time)) \
                .filter(Database.SavedRaceLap.pilot_id == pilot, \
                    Database.SavedRaceLap.deleted != 1, \
                    Database.SavedRaceLap.race_id.in_(racelist), \
                    ~Database.SavedRaceLap.id.in_(holeshots[i]))

            if stat_query.scalar():
                total_time_laps.append(stat_query.scalar())
            else:
                total_time_laps.append(0)


        gevent.sleep()
        # Get the last lap for each pilot (current race only)
        if max_laps[i] is 0:
            last_lap.append(None) # Add zero if no laps completed
        else:
            if USE_CURRENT:
                last_lap.append(current_laps[i][-1]['lap_time'])
            else:
                last_lap.append(None)

        gevent.sleep()
        # Get the average lap time for each pilot
        if max_laps[i] is 0:
            average_lap.append(0) # Add zero if no laps completed
        else:
            if USE_CURRENT:
                avg_lap = (current_laps[i][-1]['lap_time_stamp'] - current_laps[i][0]['lap_time_stamp']) / (len(current_laps[i]) - 1)

                '''
                timed_laps = filter(lambda x : x['lap_number'] > 0, current_laps[i])

                lap_total = 0
                for lap in timed_laps:
                    lap_total += lap['lap_time']

                avg_lap = lap_total / len(timed_laps)
                '''

            else:
                stat_query = DB.session.query(DB.func.avg(Database.SavedRaceLap.lap_time)) \
                    .filter(Database.SavedRaceLap.pilot_id == pilot, \
                        Database.SavedRaceLap.deleted != 1, \
                        Database.SavedRaceLap.race_id.in_(racelist), \
                        ~Database.SavedRaceLap.id.in_(holeshots[i]))

                avg_lap = stat_query.scalar()

            average_lap.append(avg_lap)

        gevent.sleep()
        # Get the fastest lap time for each pilot
        if max_laps[i] is 0:
            fastest_lap.append(0) # Add zero if no laps completed
            fastest_lap_source.append(None)
        else:
            if USE_CURRENT:
                timed_laps = filter(lambda x : x['lap_number'] > 0, current_laps[i])

                fast_lap = sorted(timed_laps, key=lambda val : val['lap_time'])[0]['lap_time']
                fastest_lap_source.append(None)
            else:
                stat_query = DB.session.query(DB.func.min(Database.SavedRaceLap.lap_time).label('time'), Database.SavedRaceLap.race_id) \
                    .filter(Database.SavedRaceLap.pilot_id == pilot, \
                        Database.SavedRaceLap.deleted != 1, \
                        Database.SavedRaceLap.race_id.in_(racelist), \
                        ~Database.SavedRaceLap.id.in_(holeshots[i])).one()

                fast_lap = stat_query.time

                if USE_HEAT:
                    fastest_lap_source.append(None)
                else:
                    source_query = Database.SavedRaceMeta.query.get(stat_query.race_id)
                    fast_lap_round = source_query.round_id
                    fast_lap_heat = source_query.heat_id
                    fast_lap_heatnote = Database.Heat.query.get(fast_lap_heat).note

                    if fast_lap_heatnote:
                        source_text = fast_lap_heatnote + ' / ' + __('Round') + ' ' + str(fast_lap_round)
                    else:
                        source_text = __('Heat') + ' ' + str(fast_lap_heat) + ' / ' + __('Round') + ' ' + str(fast_lap_round)

                    fastest_lap_source.append(source_text)

            fastest_lap.append(fast_lap)

        gevent.sleep()
        # find best consecutive 3 laps
        if max_laps[i] < 3:
            consecutives.append(None)
            consecutives_source.append(None)
        else:
            all_consecutives = []

            if USE_CURRENT:
                thisrace = current_laps[i][1:]

                for j in range(len(thisrace) - 2):
                    gevent.sleep()
                    all_consecutives.append({
                        'time': thisrace[j]['lap_time'] + thisrace[j+1]['lap_time'] + thisrace[j+2]['lap_time'],
                        'race_id': None,
                    })

            else:
                for race_id in racelist:
                    gevent.sleep()
                    thisrace = DB.session.query(Database.SavedRaceLap.lap_time) \
                        .filter(Database.SavedRaceLap.pilot_id == pilot, \
                            Database.SavedRaceLap.race_id == race_id, \
                            Database.SavedRaceLap.deleted != 1, \
                            ~Database.SavedRaceLap.id.in_(holeshots[i]) \
                            ).all()

                    if len(thisrace) >= 3:
                        for j in range(len(thisrace) - 2):
                            gevent.sleep()
                            all_consecutives.append({
                                'time': thisrace[j].lap_time + thisrace[j+1].lap_time + thisrace[j+2].lap_time,
                                'race_id': race_id
                            })

            # Sort consecutives
            all_consecutives.sort(key = lambda x: (x['time'] is None, x['time']))
            # Get lowest not-none value (if any)

            if all_consecutives:
                consecutives.append(all_consecutives[0]['time'])

                if USE_CURRENT:
                    consecutives_source.append(None)
                else:
                    source_query = Database.SavedRaceMeta.query.get(all_consecutives[0]['race_id'])
                    if source_query:
                        fast_lap_round = source_query.round_id
                        fast_lap_heat = source_query.heat_id
                        fast_lap_heatnote = Database.Heat.query.get(fast_lap_heat).note

                        if fast_lap_heatnote:
                            source_text = fast_lap_heatnote + ' / ' + __('Round') + ' ' + str(fast_lap_round)
                        else:
                            source_text = __('Heat') + ' ' + str(fast_lap_heat) + ' / ' + __('Round') + ' ' + str(fast_lap_round)

                        consecutives_source.append(source_text)
                    else:
                        consecutives_source.append(None)

            else:
                consecutives.append(None)
                consecutives_source.append(None)

    gevent.sleep()
    # Combine for sorting
    leaderboard = zip(callsigns, max_laps, total_time, average_lap, fastest_lap, team_names, consecutives, fastest_lap_source, consecutives_source, last_lap, pilot_ids, nodes, total_time_laps)

    # Reverse sort max_laps x[1], then sort on total time x[2]
    leaderboard_by_race_time = sorted(leaderboard, key = lambda x: (-x[1], x[2] if x[2] > 0 else float('inf')))

    leaderboard_total_data = []
    last_rank = '-'
    last_rank_laps = 0
    last_rank_time = RHUtils.time_format(0)
    for i, row in enumerate(leaderboard_by_race_time, start=1):
        pos = i
        total_time = RHUtils.time_format(row[2])
        if last_rank_laps == row[1] and last_rank_time == total_time:
            pos = last_rank
        last_rank = pos
        last_rank_laps = row[1]
        last_rank_time = total_time

        leaderboard_total_data.append({
            'position': pos,
            'callsign': row[0],
            'laps': row[1],
            'behind': (leaderboard_by_race_time[0][1] - row[1]),
            'total_time': RHUtils.time_format(row[2]),
            'total_time_raw': row[2],
            'total_time_laps': RHUtils.time_format(row[12]),
            'total_time_laps_raw': row[12],
            'average_lap': RHUtils.time_format(row[3]),
            'fastest_lap': RHUtils.time_format(row[4]),
            'fastest_lap_raw': row[4],
            'team_name': row[5],
            'consecutives': RHUtils.time_format(row[6]),
            'consecutives_raw': row[6],
            'fastest_lap_source': row[7],
            'consecutives_source': row[8],
            'last_lap': RHUtils.time_format(row[9]),
            'last_lap_raw': row[9],
            'pilot_id': row[10],
            'node': row[11],
        })

    gevent.sleep()
    # Sort fastest_laps x[4]
    leaderboard_by_fastest_lap = sorted(leaderboard, key = lambda x: (x[4] if x[4] > 0 else float('inf')))

    leaderboard_fast_lap_data = []
    last_rank = '-'
    last_rank_lap = 0
    for i, row in enumerate(leaderboard_by_fastest_lap, start=1):
        pos = i
        fast_lap = RHUtils.time_format(row[4])
        if last_rank_lap == fast_lap:
            pos = last_rank
        last_rank = pos
        last_rank_laps = fast_lap

        leaderboard_fast_lap_data.append({
            'position': pos,
            'callsign': row[0],
            'laps': row[1],
            'total_time': RHUtils.time_format(row[2]),
            'total_time_raw': row[2],
            'total_time_laps': RHUtils.time_format(row[12]),
            'total_time_laps_raw': row[12],
            'average_lap': RHUtils.time_format(row[3]),
            'fastest_lap': RHUtils.time_format(row[4]),
            'fastest_lap_raw': row[4],
            'team_name': row[5],
            'consecutives': RHUtils.time_format(row[6]),
            'consecutives_raw': row[6],
            'fastest_lap_source': row[7],
            'consecutives_source': row[8],
            'last_lap': RHUtils.time_format(row[9]),
            'last_lap_raw': row[9],
            'pilot_id': row[10],
            'node': row[11],
        })

    gevent.sleep()
    # Sort consecutives x[6]
    leaderboard_by_consecutives = sorted(leaderboard, key = lambda x: (x[6] if x[6] > 0 else float('inf')))

    leaderboard_consecutives_data = []
    last_rank = '-'
    last_rank_consecutive = 0
    for i, row in enumerate(leaderboard_by_consecutives, start=1):
        pos = i
        fast_consecutive = RHUtils.time_format(row[4])
        if last_rank_consecutive == fast_consecutive:
            pos = last_rank
        last_rank = pos
        last_rank_consecutive = fast_consecutive

        leaderboard_consecutives_data.append({
            'position': i,
            'callsign': row[0],
            'laps': row[1],
            'total_time': RHUtils.time_format(row[2]),
            'total_time_raw': row[2],
            'total_time_laps': RHUtils.time_format(row[12]),
            'total_time_laps_raw': row[12],
            'average_lap': RHUtils.time_format(row[3]),
            'fastest_lap': RHUtils.time_format(row[4]),
            'fastest_lap_raw': row[4],
            'team_name': row[5],
            'consecutives': RHUtils.time_format(row[6]),
            'consecutives_raw': row[6],
            'fastest_lap_source': row[7],
            'consecutives_source': row[8],
            'last_lap': RHUtils.time_format(row[9]),
            'last_lap_raw': row[9],
            'pilot_id': row[10],
            'node': row[11],
        })

    leaderboard_output = {
        'by_race_time': leaderboard_total_data,
        'by_fastest_lap': leaderboard_fast_lap_data,
        'by_consecutives': leaderboard_consecutives_data
    }

    if race_format:
        if race_format.win_condition == WinCondition.FASTEST_3_CONSECUTIVE:
            primary_leaderboard = 'by_consecutives'
        elif race_format.win_condition == WinCondition.FASTEST_LAP:
            primary_leaderboard = 'by_fastest_lap'
        else:
            # WinCondition.NONE
            # WinCondition.MOST_LAPS
            # WinCondition.FIRST_TO_LAP_X
            primary_leaderboard = 'by_race_time'

        leaderboard_output['meta'] = {
            'primary_leaderboard': primary_leaderboard,
            'win_condition': race_format.win_condition,
            'team_racing_mode': race_format.team_racing_mode,
        }
    else:
        leaderboard_output['meta'] = {
            'primary_leaderboard': 'by_race_time',
            'win_condition': WinCondition.NONE,
            'team_racing_mode': False
        }

    return leaderboard_output
Ejemplo n.º 12
0
 def set_node_frequency(self, node_number, frequency):
     fmsg = __("Frequency Change: ") + str(frequency)
     node = self._nodes[node_number]
     node.set_node_frequency(frequency)