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
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
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