Exemplo n.º 1
0
    def calculate_event_points(cls, event):
        event.get_awards_async()
        event.get_matches_async()

        # Typically 3 for District CMP, 1 otherwise
        POINTS_MULTIPLIER = DistrictPointValues.DISTRICT_CMP_MULTIPLIER.get(event.year, DistrictPointValues.DISTRICT_CMP_MULIPLIER_DEFAULT) if event.event_type_enum == EventType.DISTRICT_CMP else DistrictPointValues.STANDARD_MULTIPLIER

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }
        single_district_points = copy.deepcopy(district_points)

        # match points
        if event.year >= 2015:
            # Switched to ranking-based points for 2015 and onward
            cls.calc_rank_based_match_points(event, district_points, event.matches, POINTS_MULTIPLIER)
        else:
            cls.calc_wlt_based_match_points(district_points, event.matches, POINTS_MULTIPLIER)

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event, POINTS_MULTIPLIER, event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points
        else:
            msg = "Event {} has no alliance selection district_points!".format(event.key.id())
            if event.event_type_enum in EventType.SEASON_EVENT_TYPES:
                logging.warning(msg)
            else:
                logging.info(msg)

        # award points
        for award in event.awards:
            point_value = 0
            if event.year >= 2014:
                if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                    if award.award_type_enum == AwardType.CHAIRMANS:
                        point_value = DistrictPointValues.CHAIRMANS.get(event.year, DistrictPointValues.CHAIRMANS_DEFAULT)
                    elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                        point_value = DistrictPointValues.EI_AND_RAS_DEFAULT
                    else:
                        point_value = DistrictPointValues.OTHER_AWARD_DEFAULT
            else:  # Legacy awards
                if award.award_type_enum in DistrictPointValues.LEGACY_5_PT_AWARDS.get(event.year, []):
                    point_value = 5
                elif award.award_type_enum in DistrictPointValues.LEGACY_2_PT_AWARDS.get(event.year, []):
                    point_value = 2

            # Add award points to all teams who won
            if point_value:
                for team in award.team_list:
                    district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points
    def calculate_event_points(cls, event):
        event.get_awards_async()
        event.get_matches_async()
        district_team_key_futures = DistrictTeam.query(
            DistrictTeam.district == event.event_district_enum, DistrictTeam.year == event.year
        ).fetch_async(None, keys_only=True)

        # Typically 3 for District CMP, 1 otherwise
        POINTS_MULTIPLIER = (
            DistrictPointValues.DISTRICT_CMP_MULTIPLIER.get(
                event.year, DistrictPointValues.DISTRICT_CMP_MULIPLIER_DEFAULT
            )
            if event.event_type_enum == EventType.DISTRICT_CMP
            else DistrictPointValues.STANDARD_MULTIPLIER
        )

        district_points = {
            "points": defaultdict(
                lambda: {"qual_points": 0, "elim_points": 0, "alliance_points": 0, "award_points": 0, "total": 0}
            ),
            "tiebreakers": defaultdict(
                lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                    "qual_wins": 0,
                    "highest_qual_scores": [],
                }
            ),
        }
        single_district_points = district_points.copy()

        # match points
        if event.year >= 2015:
            # Switched to ranking-based points for 2015 and onward
            cls.calc_rank_based_match_points(event, district_points, event.matches, POINTS_MULTIPLIER)
        else:
            cls.calc_wlt_based_match_points(district_points, event.matches, POINTS_MULTIPLIER)

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(
                event, POINTS_MULTIPLIER, event.alliance_selections
            )
            for team, points in selection_points.items():
                district_points["points"][team]["alliance_points"] += points
        else:
            msg = "Event {} has no alliance selection district_points!".format(event.key.id())
            if event.event_type_enum in EventType.SEASON_EVENT_TYPES:
                logging.warning(msg)
            else:
                logging.info(msg)

        # award points
        for award in event.awards:
            point_value = 0
            if event.year >= 2014:
                if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                    if award.award_type_enum == AwardType.CHAIRMANS:
                        point_value = DistrictPointValues.CHAIRMANS.get(
                            event.year, DistrictPointValues.CHAIRMANS_DEFAULT
                        )
                    elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                        point_value = DistrictPointValues.EI_AND_RAS_DEFAULT
                    else:
                        point_value = DistrictPointValues.OTHER_AWARD_DEFAULT
            else:  # Legacy awards
                if award.award_type_enum in DistrictPointValues.LEGACY_5_PT_AWARDS.get(event.year, []):
                    point_value = 5
                elif award.award_type_enum in DistrictPointValues.LEGACY_2_PT_AWARDS.get(event.year, []):
                    point_value = 2

            # Add award points to all teams who won
            for team in award.team_list:
                district_points["points"][team.id()]["award_points"] += point_value * POINTS_MULTIPLIER

        # Filter out teams not in this district (only keep those with a DistrictTeam present for this district)
        for district_team_future in ndb.get_multi_async(district_team_key_futures.get_result()):
            district_team = district_team_future.get_result()
            team_key = district_team.team.id()
            if team_key in district_points["points"]:
                single_district_points["points"][team_key] = district_points["points"][team_key]
            if team_key in district_points["tiebreakers"]:
                single_district_points["tiebreakers"][team_key] = district_points["tiebreakers"][team_key]

        for team, point_breakdown in single_district_points["points"].items():
            for p in point_breakdown.values():
                single_district_points["points"][team]["total"] += p

        return single_district_points
Exemplo n.º 3
0
    def calculate_event_points(cls, event):
        event.get_awards_async()
        event.get_matches_async()
        district_team_key_futures = DistrictTeam.query(DistrictTeam.district == event.event_district_enum, DistrictTeam.year == event.year).fetch_async(None, keys_only=True)

        # Typically 3 for District CMP, 1 otherwise
        POINTS_MULTIPLIER = DistrictPointValues.DISTRICT_CMP_MULTIPLIER.get(event.year, DistrictPointValues.DISTRICT_CMP_MULIPLIER_DEFAULT) if event.event_type_enum == EventType.DISTRICT_CMP else DistrictPointValues.STANDARD_MULTIPLIER

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }
        single_district_points = district_points.copy()

        # match points
        if event.year >= 2015:
            # Switched to ranking-based points for 2015 and onward
            cls.calc_rank_based_match_points(event, district_points, event.matches, POINTS_MULTIPLIER)
        else:
            cls.calc_wlt_based_match_points(district_points, event.matches, POINTS_MULTIPLIER)

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event.key_name, POINTS_MULTIPLIER, event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points
        else:
            logging.warning("Event {} has no alliance selection district_points!".format(event.key.id()))

        # award points
        for award in event.awards:
            point_value = 0
            if event.year >= 2014:
                if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                    if award.award_type_enum == AwardType.CHAIRMANS:
                        point_value = DistrictPointValues.CHAIRMANS.get(event.year, DistrictPointValues.CHAIRMANS_DEFAULT)
                    elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                        point_value = DistrictPointValues.EI_AND_RAS_DEFAULT
                    else:
                        point_value = DistrictPointValues.OTHER_AWARD_DEFAULT
            else:  # Legacy awards
                if award.award_type_enum in DistrictPointValues.LEGACY_5_PT_AWARDS.get(event.year, []):
                    point_value = 5
                elif award.award_type_enum in DistrictPointValues.LEGACY_2_PT_AWARDS.get(event.year, []):
                    point_value = 2

            # Add award points to all teams who won
            for team in award.team_list:
                district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        # Filter out teams not in this district (only keep those with a DistrictTeam present for this district)
        for district_team_future in ndb.get_multi_async(district_team_key_futures.get_result()):
            district_team = district_team_future.get_result()
            team_key = district_team.team.id()
            if team_key in district_points['points']:
                single_district_points['points'][team_key] = district_points['points'][team_key]
            if team_key in district_points['tiebreakers']:
                single_district_points['tiebreakers'][team_key] = district_points['tiebreakers'][team_key]

        for team, point_breakdown in single_district_points['points'].items():
            for p in point_breakdown.values():
                single_district_points['points'][team]['total'] += p

        return single_district_points
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(
            None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(
            None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        POINTS_MULTIPLIER = 3 if event.event_type_enum == EventType.DISTRICT_CMP else 1

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }

        # match points
        elim_num_wins = defaultdict(lambda: defaultdict(int))
        elim_alliances = defaultdict(lambda: defaultdict(list))
        for match_future in match_futures:
            match = match_future.get_result()
            if not match.has_been_played:
                continue

            if match.comp_level == 'qm':
                if match.winning_alliance == '':
                    for team in match.team_key_names:
                        district_points['points'][team][
                            'qual_points'] += 1 * POINTS_MULTIPLIER
                else:
                    for team in match.alliances[
                            match.winning_alliance]['teams']:
                        district_points['points'][team][
                            'qual_points'] += 2 * POINTS_MULTIPLIER
                        district_points['tiebreakers'][team]['qual_wins'] += 1

                for color in ['red', 'blue']:
                    for team in match.alliances[color]['teams']:
                        score = match.alliances[color]['score']
                        district_points['tiebreakers'][team][
                            'highest_qual_scores'] = heapq.nlargest(
                                3, district_points['tiebreakers'][team]
                                ['highest_qual_scores'] + [score])
            else:
                if match.winning_alliance == '':
                    continue

                match_set_key = '{}_{}{}'.format(match.event.id(),
                                                 match.comp_level,
                                                 match.set_number)
                elim_num_wins[match_set_key][match.winning_alliance] += 1
                elim_alliances[match_set_key][
                    match.winning_alliance] += match.alliances[
                        match.winning_alliance]['teams']

                if elim_num_wins[match_set_key][match.winning_alliance] >= 2:
                    for team in elim_alliances[match_set_key][
                            match.winning_alliance]:
                        district_points['points'][team][
                            'elim_points'] += 5 * POINTS_MULTIPLIER

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(
                event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team][
                    'alliance_points'] += points * POINTS_MULTIPLIER
        else:
            logging.warning(
                "Event {} has no alliance selection district_points!".format(
                    event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                if award.award_type_enum == AwardType.CHAIRMANS:
                    point_value = 10
                elif award.award_type_enum in {
                        AwardType.ENGINEERING_INSPIRATION,
                        AwardType.ROOKIE_ALL_STAR
                }:
                    point_value = 8
                else:
                    point_value = 5
                for team in award.team_list:
                    district_points['points'][team.id(
                    )]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points
Exemplo n.º 5
0
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        POINTS_MULTIPLIER = 3 if event.event_type_enum == EventType.DISTRICT_CMP else 1

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }

        # match points
        if event.year == 2015:
            from helpers.match_helper import MatchHelper  # circular import issue

            # qual match points are calculated by rank
            if event.rankings and len(event.rankings) > 1:
                rankings = event.rankings[1:]  # skip title row
                num_teams = len(rankings)
                alpha = 1.07
                for row in rankings:
                    rank = int(row[0])
                    team = 'frc{}'.format(row[1])
                    qual_points = int(np.ceil(cls.inverf(float(num_teams - 2 * rank + 2) / (alpha * num_teams)) * (10.0 / cls.inverf(1.0 / alpha)) + 12))
                    district_points['points'][team]['qual_points'] = qual_points * POINTS_MULTIPLIER
            else:
                logging.warning("Event {} has no rankings for qual_points calculations!".format(event.key.id()))

            matches = MatchHelper.organizeMatches([mf.get_result() for mf in match_futures])

            # qual match calculations. only used for tiebreaking
            for match in matches['qm']:
                for color in ['red', 'blue']:
                    for team in match.alliances[color]['teams']:
                        score = match.alliances[color]['score']
                        district_points['tiebreakers'][team]['highest_qual_scores'] = heapq.nlargest(3, district_points['tiebreakers'][team]['highest_qual_scores'] + [score])

            # elim match point calculations
            # count number of matches played per team per comp level
            num_played = defaultdict(lambda: defaultdict(int))
            for level in ['qf', 'sf']:
                for match in matches[level]:
                    if not match.has_been_played:
                        continue
                    for color in ['red', 'blue']:
                        for team in match.alliances[color]['teams']:
                            num_played[level][team] += 1

            # qf and sf points
            advancement = MatchHelper.generatePlayoffAdvancement2015(matches)
            for last_level, level in [('qf', 'sf'), ('sf', 'f')]:
                for (teams, _, _) in advancement[last_level]:
                    teams = ['frc{}'.format(t) for t in teams]
                    done = False
                    for match in matches[level]:
                        for color in ['red', 'blue']:
                            if set(teams).intersection(set(match.alliances[color]['teams'])) != set():
                                for team in teams:
                                    points = 5.0 if last_level == 'qf' else 3.3
                                    district_points['points'][team]['elim_points'] += int(np.ceil(points * num_played[last_level][team])) * POINTS_MULTIPLIER
                                done = True
                                break
                            if done:
                                break
                        if done:
                            break

            # final points
            num_wins = {'red': 0, 'blue': 0}
            team_matches_played = {'red': [], 'blue': []}
            for match in matches['f']:
                if not match.has_been_played or match.winning_alliance == '':
                    continue

                num_wins[match.winning_alliance] += 1
                for team in match.alliances[match.winning_alliance]['teams']:
                    team_matches_played[match.winning_alliance].append(team)

                if num_wins[match.winning_alliance] >= 2:
                    for team in team_matches_played[match.winning_alliance]:
                        district_points['points'][team]['elim_points'] += 5 * POINTS_MULTIPLIER

        else:
            elim_num_wins = defaultdict(lambda: defaultdict(int))
            elim_alliances = defaultdict(lambda: defaultdict(list))
            for match_future in match_futures:
                match = match_future.get_result()
                if not match.has_been_played:
                    continue

                if match.comp_level == 'qm':
                    if match.winning_alliance == '':
                        for team in match.team_key_names:
                            district_points['points'][team]['qual_points'] += 1 * POINTS_MULTIPLIER
                    else:
                        for team in match.alliances[match.winning_alliance]['teams']:
                            district_points['points'][team]['qual_points'] += 2 * POINTS_MULTIPLIER
                            district_points['tiebreakers'][team]['qual_wins'] += 1

                    for color in ['red', 'blue']:
                        for team in match.alliances[color]['teams']:
                            score = match.alliances[color]['score']
                            district_points['tiebreakers'][team]['highest_qual_scores'] = heapq.nlargest(3, district_points['tiebreakers'][team]['highest_qual_scores'] + [score])
                else:
                    if match.winning_alliance == '':
                        continue

                    match_set_key = '{}_{}{}'.format(match.event.id(), match.comp_level, match.set_number)
                    elim_num_wins[match_set_key][match.winning_alliance] += 1
                    elim_alliances[match_set_key][match.winning_alliance] += match.alliances[match.winning_alliance]['teams']

                    if elim_num_wins[match_set_key][match.winning_alliance] >= 2:
                        for team in elim_alliances[match_set_key][match.winning_alliance]:
                            district_points['points'][team]['elim_points'] += 5* POINTS_MULTIPLIER

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points * POINTS_MULTIPLIER
        else:
            logging.warning("Event {} has no alliance selection district_points!".format(event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                if award.award_type_enum == AwardType.CHAIRMANS:
                    point_value = 10
                elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                    point_value = 8
                else:
                    point_value = 5
                for team in award.team_list:
                    district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        POINTS_MULTIPLIER = 3 if event.event_type_enum == EventType.DISTRICT_CMP else 1

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }

        # match points
        elim_num_wins = defaultdict(lambda: defaultdict(int))
        elim_alliances = defaultdict(lambda: defaultdict(list))
        for match_future in match_futures:
            match = match_future.get_result()
            if not match.has_been_played:
                continue

            if match.comp_level == 'qm':
                if match.winning_alliance == '':
                    for team in match.team_key_names:
                        district_points['points'][team]['qual_points'] += 1 * POINTS_MULTIPLIER
                else:
                    for team in match.alliances[match.winning_alliance]['teams']:
                        district_points['points'][team]['qual_points'] += 2 * POINTS_MULTIPLIER
                        district_points['tiebreakers'][team]['qual_wins'] += 1

                for color in ['red', 'blue']:
                    for team in match.alliances[color]['teams']:
                        score = match.alliances[color]['score']
                        district_points['tiebreakers'][team]['highest_qual_scores'] = heapq.nlargest(3, district_points['tiebreakers'][team]['highest_qual_scores'] + [score])
            else:
                if match.winning_alliance == '':
                    continue

                match_set_key = '{}_{}{}'.format(match.event.id(), match.comp_level, match.set_number)
                elim_num_wins[match_set_key][match.winning_alliance] += 1
                elim_alliances[match_set_key][match.winning_alliance] += match.alliances[match.winning_alliance]['teams']

                if elim_num_wins[match_set_key][match.winning_alliance] >= 2:
                    for team in elim_alliances[match_set_key][match.winning_alliance]:
                        district_points['points'][team]['elim_points'] += 5* POINTS_MULTIPLIER

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points * POINTS_MULTIPLIER
        else:
            logging.warning("Event {} has no alliance selection district_points!".format(event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                if award.award_type_enum == AwardType.CHAIRMANS:
                    point_value = 10
                elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                    point_value = 8
                else:
                    point_value = 5
                for team in award.team_list:
                    district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points