def genEventTable(status): status_map = { 'future': "Future Events", 'running': "Ongoing Events", 'done': "Completed Events" } events = EventAPI(self.request).filterSelf( event_status=status, event_season=self.season).order_by('event_start_date') event_dict = list( map( lambda event: dict(event_name=event.event_name, event_link=reverse('client.view_dispatch_param', args=["event_scoring", event.id]), event_type=EventTypeAPI(self.request).getSelf( id=event.event_type).event_type_name, event_status=status_map[event.event_status] if event. event_status in status_map else event.event_status, event_region=RegionAPI(self.request).getSelf( id=event.event_region).region_name, event_host=SchoolAPI(self.request).getSelf( id=event.event_host).school_name, event_start_date=event.event_start_date.strftime( "%B %d, %Y"), event_start_date_num=int( event.event_start_date.strftime("%Y%m%d"))), list(events))) event_dict = sorted(event_dict, key=(lambda x: x['event_start_date_num']), reverse=True) return event_dict
def buildEventDetailsDict(self, event): status_map = { 'future': "Future Events", 'running': "Ongoing Events", 'done': "Completed Events" } result = dict( name=event.event_name, description=event.event_description, scoring=('Scoring Page', reverse('client.view_dispatch_param', args=['event_scoring', event.id])), rotation=('Rotation Page', reverse('client.view_dispatch_param', args=['event_rotation', event.id])), season=(SeasonAPI( self.request).getSelf(id=event.event_season).season_name, UrlFunctions.getClientViewLink('seasons')), region=(lambda region_name: (region_name, "{}#{}".format( UrlFunctions.getClientViewLink('schools'), region_name)))( RegionAPI(self.request).getSelf( id=event.event_region).region_name, ), host=(SchoolAPI( self.request).getSelf(id=event.event_host).school_name, UrlFunctions.getClientViewLink('school_specific', event.event_host)), location=event.event_location, status=status_map[event.event_status], start=event.event_start_date.strftime("%B %d, %Y"), end=event.event_end_date.strftime("%B %d, %Y")) return result
def getCurrentLeagueScoreBySchool(self, school_id, compiled=False, subcompiled=False): school = SchoolAPI(self.request).getSelf(id=school_id) if compiled: return self.getCompiledScoreForSchool(school, error=False) else: events = SchoolAPI(self.request).getParticipatedNormalEvents( school_id, Event.EVENT_STATUS_DONE, self.season) # TODO: Optimize the current n x m queries ;_; scores = [ score for score, event in self.getReverseSortedEventScoresList( school, events, subcompiled) ] average_score = self.getAverageScore(scores, school.school_region) final_race_score = self.getFinalRaceScore(school, self.season) total_score = average_score + final_race_score return total_score
def computeLeagueScores(self, initialize=True, override=None): league_scoring_data = self.getPanelLeagueScoreData() league_scoring_map = { data.get('school_id'): data for data in league_scoring_data } # TODO: Have an indicator for finished season and use it to determine whether to recompile league scores # We only recompute if initialize is true and all recorded scores are not None if not (initialize or reduce( lambda x, y: x and (y['recorded_score'] is not None), league_scoring_data, True)): return # We initialize override as all None values if the override variable is not set if override is None: override = [(school_id, False) for school_id in league_scoring_map.keys()] # Update the DB according to override values, otherwise, compute the calculated values again for school_id, override_score in override: league_scoring_api = LeagueScoringAPI(self.request) school_id = int(school_id) school = SchoolAPI(self.request).getSelf(id=school_id) calculated_score = league_scoring_map.get(school_id).get( 'calculated_score') if not override_score: override_score = Score.DEFAULT_LEAGUE_SCORE participated_events = SchoolAPI( self.request).getParticipatedEvents(school_id, Event.EVENT_STATUS_DONE, self.season) school_score_dict = { event.id: league_scoring_api.getScoreForEventBySchool( event, school, False) for event in participated_events } league_scoring_api.setNormalOverrideLeagueScore( school, (calculated_score, override_score)) league_scoring_api.setNormalOverrideSummaryScores( school, school_score_dict)
def __buildRotationTable(self, event): rotation_detail = event.event_rotation_detail boat_identifiers = event.event_boat_rotation_name.split(',') rotation_table = dict() schools = SchoolAPI(self.request).filterSelf(id__in=list(map(lambda x: int(x), event.event_school_ids))) teams = EventAPI(self.request).getEventCascadeTeams(event.id) team_flatten_ids = [team.id for team in teams] team_school_link = dict() team_name_link = dict() for team in TeamAPI(self.request).filterSelf(id__in=team_flatten_ids): team_school_link[team.id] = schools.get(id=team.team_school) team_name_link[team.id] = team_school_link[team.id].school_name + ' - ' + team.team_name for event_tag_id, teams in rotation_detail.items(): event_tag_name = EventTagAPI(self.request).getSelf(id=event_tag_id).event_tag_name rotation_table[event_tag_name] = dict() for team_id, rotations in teams.items(): team_id = int(team_id) rotation_table[event_tag_name][team_id] = dict() rotation_table[event_tag_name][team_id]['team_name'] = team_name_link[team_id] rotation_table[event_tag_name][team_id]['rotations'] = [ boat_identifiers[int(r_num)-1] for r_num in rotations ] return dict(rotation_table)
def getClientLeagueScoreData(self): schools = SchoolAPI(self.request).getAll() result = list() for school in schools: school_id = school.id school_name = school.school_name score = self.getCompiledScoreForSchool(school, error=False) if score is None: compiled = False score = self.tryCompileThenCalculateScore(school) else: compiled = True response = dict(compiled=compiled, school_id=school_id, school_name=school_name, display_score=score, num_race=SchoolAPI( self.request).getParticipatedEvents( school_id=school_id, status=Event.EVENT_STATUS_DONE, season=self.season, ).count()) result.append(response) return result
def getPanelLeagueScoreData(self): schools = SchoolAPI(self.request).getAll() result = list() for school in schools: school_id = school.id school_name = school.school_name participated_events = SchoolAPI( self.request).getParticipatedEvents(school_id, Event.EVENT_STATUS_DONE, self.season) participated_events_num = participated_events.count() calculated_score = self.getCurrentLeagueScoreBySchool( school_id=school.id, compiled=False) recorded_score = self.getCurrentLeagueScoreBySchool( school_id=school.id, compiled=True) response = dict( school_id=school_id, school_name=school_name, participated_events_num=participated_events_num, calculated_score=calculated_score, recorded_score=recorded_score, ) result.append(response) return result
def getAverageFactor(self, region, num_race): num_school_in_region = SchoolAPI( self.request).filterSelf(school_region=region).count() # Specific region has different race num average if num_school_in_region in [1, 2]: base_average_race_num = 1 elif num_school_in_region >= 3: base_average_race_num = 3 else: raise Exception( "Try to retrieve a region with less than or equal to 0 school." ) average_factor = max(base_average_race_num, min(math.ceil(num_race / 2), 4)) return average_factor
def updateSchools(self, school_ids): schools = SchoolAPI(self.request).filterSelf(id__in=school_ids) # Return error if one or more of the school ids could not be found if not len(schools) == len(school_ids): raise Exception( "At least one of the school ids is invalid in updateSchools") old_school_ids = list( map(lambda x: int(x), self.event.event_school_ids)) # Finding all the elements in school_ids that are not already in old_school_ids, and its converse additionList = [e for e in school_ids if e not in old_school_ids] removalList = [e for e in old_school_ids if e not in school_ids] self.event.event_school_ids = school_ids self.event.event_team_number = len(school_ids) # Remove some boat identifiers if less schools, or add more non duplicate numbers if more schools boat_ids = self.event.event_boat_rotation_name.split(',') next_boat_id = (lambda m: m if m is not None else 0)( MiscFunctions.findMaxInStrArr(boat_ids)) + 1 new_boat_ids = boat_ids[:min(self.event.event_team_number, len(boat_ids))] + \ [str(next_boat_id + i) for i in range( max(0, self.event.event_team_number - len(boat_ids)) )] self.event.event_boat_rotation_name = ','.join(new_boat_ids) self.event.save() # Handling Addition first before deletion self.updateSummaryBySchool(additionList, AuthenticationActionType.ADD) self.updateEventTeams(additionList, AuthenticationActionType.ADD) self.updateEventActivities(additionList, AuthenticationActionType.ADD) self.updateEventTeamLinks(additionList, AuthenticationActionType.ADD) # Handling Deletion self.updateSummaryBySchool(removalList, AuthenticationActionType.DELETE) self.updateEventActivities(removalList, AuthenticationActionType.DELETE) self.updateEventTeamLinks(removalList, AuthenticationActionType.DELETE) self.updateEventTeams(removalList, AuthenticationActionType.DELETE) # Update rotation, previous doesn't have information about new teams self.event.event_rotation_detail = self.regenerateRotation() self.event.save() # Update Summary and League Scores self.recalculateScores()
def genSchoolTable(region): schools = SchoolAPI(self.request).filterSelf( school_region=region).order_by('school_name') school_dict = list( map( lambda school: dict( school_name=school.school_name, school_team_name=school.school_default_team_name, school_status=school.school_status, school_season_score=MiscFunctions.truncateDisplayScore( LeagueScoringAPI(self.request). tryCompileThenCalculateScore(school)), school_link=reverse('client.view_dispatch_param', args= ["school_specific", school.id])), list(schools))) return school_dict
def updateEventTeams(self, school_ids, action): event_tags = EventTagAPI( self.request).filterSelf(event_tag_event_id=self.event.id) if action == AuthenticationActionType.ADD: schools = SchoolAPI(self.request).filterSelf(id__in=school_ids) for school in schools: for idx, tag in enumerate(event_tags): team_name = '{} {} {}'.format( school.school_default_team_name, Team.TEAM_NAME_SUFFIX, MiscFunctions.getAlphabet(idx)) TeamAPI(self.request).createSelf(team_name=team_name, team_school=school.id, team_status="active", team_tag_id=tag.id) elif action == AuthenticationActionType.DELETE: TeamAPI(self.request).deleteSelf( legacy=False, team_tag_id__in=[e.id for e in event_tags], team_school__in=school_ids).delete()
def genContent(self, event_id): content = dict() event = EventAPI(self.request).getSelf(id=event_id) schools = SchoolAPI(self.request).getAll() participating_school_ids = [int(school_id) for school_id in event.event_school_ids] for idx, school in enumerate(schools): content[idx] = dict( school_id=school.id, school_url=reverse( 'client.view_dispatch_param', args=['school_specific', school.id] ), school_name=school.school_name, participated=school.id in participating_school_ids, ) content_list = [ v for v in sorted( content.values(), key=lambda x: (x['participated'], -x['school_id']), reverse=True ) ] return content_list
def __buildFleetTable(self, event, force_compile): def __buildFleetScoreTable(): race_table = dict() event_score_map = self.__compileScoreMap(event) for tag_id, tag in zip(event_activity_id_tags, event_activity_name_tags): race_table[tag] = dict() restricted_eas = event_activities.filter( event_activity_event_tag=tag_id).order_by( 'event_activity_order') for ea in restricted_eas: result = ea.event_activity_result if bool(result): for team, rank in result.items(): team_id = int(team) team_name = team_name_link[team_id] rank = rank if rank not in event_score_map else rank + ' (' + str( event_score_map[rank]) + ')' if team_id not in race_table[tag]: race_table[tag][team_id] = dict( team_name=team_name, scores=list(), final_score=0) race_table[tag][team_id]["scores"].append(rank) else: for team in team_ids[tag]: team_name = team_name_link[team] if team not in race_table[tag]: race_table[tag][team] = dict( team_name=team_name, scores=list(), final_score=0) race_table[tag][team]["scores"].append(0) for tag in event_activity_name_tags: for team in team_ids[tag]: score = reduce( (lambda x, y: self.__scoreAdd(x, y, event_score_map)), race_table[tag][team]["scores"]) race_table[tag][team]["final_score"] = int(score) for tag in event_activity_name_tags: temp_table = sorted( race_table[tag].items(), key=lambda x: x[1]["final_score"] if x[1]["final_score"] != 0 else ScoreMappingAPI( self.request).getMaxSentinel()) race_table[tag] = {data[0]: data[1] for data in temp_table} for tag in event_activity_name_tags: prevRanking = 1 prevScore = 0 for index, team in enumerate(race_table[tag]): if race_table[tag][team]["final_score"] == 0: race_table[tag][team]["rank"] = '#' else: if race_table[tag][team]["final_score"] > prevScore: prevRanking = index + 1 prevScore = race_table[tag][team]["final_score"] race_table[tag][team]["rank"] = prevRanking # Sort the race_table by rank (takes care of unassigned rank cases) return race_table def __buildFleetRankingTable(): if not event.event_status == Event.EVENT_STATUS_DONE or force_compile: ranking_table = dict() for school in schools: ranking_table[school.id] = 0 for tag in event_activity_name_tags: for team in team_ids[tag]: ranking_table[team_school_link[ team].id] += score_table[tag][team]["final_score"] school_ranking_list = [ dict(school_id=school_id, school_name=schools.get(id=school_id).school_name, score=data, ranking='#', base_ranking='#', override_ranking=0, need_override=False, note='-') for school_id, data in ranking_table.items() ] school_ranking_list = sorted( school_ranking_list, key=lambda x: x['score'] if x['score'] != 0 else ScoreMappingAPI(self.request ).getMaxSentinel()) prevRanking = 1 prevScore = 0 for index, school_ranking_data in enumerate( school_ranking_list): if school_ranking_data['score'] != 0: if school_ranking_data['score'] > prevScore: prevRanking = index + 1 prevScore = school_ranking_data['score'] school_ranking_list[index]['ranking'] = prevRanking school_ranking_list[index][ 'base_ranking'] = prevRanking else: summaries = list( SummaryAPI(self.request).filterSelf( summary_event_parent=event.id)) school_ranking_list = [ dict( school_id=summary.summary_event_school, school_name=schools.get( id=summary.summary_event_school).school_name, score=summary.summary_event_race_score, ranking=summary.summary_event_ranking + summary.summary_event_override_ranking, base_ranking=summary.summary_event_ranking, override_ranking=summary. summary_event_override_ranking, need_override=True if summary.summary_event_override_ranking != 0 else False, note='Tie-breaker' if summary.summary_event_override_ranking != 0 else '-') for index, summary in enumerate(summaries) ] # Takes care of unassigned ranking cases school_ranking_list = sorted( school_ranking_list, key=lambda x: x['ranking'] if isinstance(x['ranking'], int) else ScoreMappingAPI( self.request).getMaxSentinel()) # TODO: Refactor, this code does not belong to the frontend API, it is for the backend score compilation # Loop to check if entry needs override for index, school_ranking_data in enumerate(school_ranking_list): duplicates = sum((1 if result['base_ranking'] == school_ranking_data['base_ranking'] else 0) for result in school_ranking_list) if duplicates > 1: school_ranking_list[index]['need_override'] = True return school_ranking_list event_activities = EventActivityAPI( self.request).filterSelf(event_activity_event_parent=event.id) schools = SchoolAPI(self.request).filterSelf( id__in=list(map(lambda x: int(x), event.event_school_ids))) teams = EventAPI(self.request).getEventCascadeTeams(event.id) event_activity_id_tags = list() event_activity_name_tags = list() team_ids = dict() team_school_link = dict() team_name_link = dict() distinct_eas = event_activities.distinct('event_activity_event_tag') team_flatten_ids = [team.id for team in teams] for ea in distinct_eas: event_tag_name = EventTagAPI(self.request).getSelf( id=ea.event_activity_event_tag).event_tag_name event_activity_name_tags.append(event_tag_name) event_activity_id_tags.append(ea.event_activity_event_tag) team_ids[event_tag_name] = [ team.id for team in teams.filter( team_tag_id=ea.event_activity_event_tag) ] for team in TeamAPI(self.request).filterSelf(id__in=team_flatten_ids): team_school_link[team.id] = schools.get(id=team.team_school) team_name_link[team.id] = team_school_link[ team.id].school_name + ' - ' + team.team_name score_table = __buildFleetScoreTable() rank_table = __buildFleetRankingTable() return dict(ranking=rank_table, score=score_table)