def get(self, alias): special_webcasts_future = Sitevar.get_by_id_async('gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() aliases = special_webcasts.contents.get("aliases", {}) if special_webcasts else {} if alias in aliases: self.redirect("/gameday{}".format(aliases[alias])) return # Allow an alias to be an event key if not ValidationHelper.event_id_validator(alias): event = Event.get_by_id(alias) if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return # Allow an alias to be a team number team_key = "frc{}".format(alias) if not ValidationHelper.team_id_validator(team_key): now = datetime.datetime.now() team_events_future = TeamYearEventsQuery(team_key, now.year).fetch_async() team_events = team_events_future.get_result() for event in team_events: if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return self.redirect("/gameday") return
def test_event_updated(self): affected_refs = { 'key': {ndb.Key(Event, '2015casj'), ndb.Key(Event, '2015cama')}, 'year': {2014, 2015}, 'district_key': {ndb.Key(District, '2015fim'), ndb.Key(District, '2014mar')} } cache_keys = [ q.cache_key for q in get_affected_queries.event_updated(affected_refs) ] self.assertEqual(len(cache_keys), 10) self.assertTrue(EventQuery('2015casj').cache_key in cache_keys) self.assertTrue(EventQuery('2015cama').cache_key in cache_keys) self.assertTrue(EventListQuery(2014).cache_key in cache_keys) self.assertTrue(EventListQuery(2015).cache_key in cache_keys) self.assertTrue(DistrictEventsQuery('2015fim').cache_key in cache_keys) self.assertTrue(DistrictEventsQuery('2014mar').cache_key in cache_keys) self.assertTrue(TeamEventsQuery('frc254').cache_key in cache_keys) self.assertTrue(TeamEventsQuery('frc604').cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc254', 2015).cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc604', 2015).cache_key in cache_keys)
def get(self, alias): special_webcasts_future = Sitevar.get_by_id_async( 'gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() aliases = special_webcasts.contents.get( "aliases", {}) if special_webcasts else {} if alias in aliases: self.redirect("/gameday{}".format(aliases[alias])) return # Allow an alias to be an event key if not ValidationHelper.event_id_validator(alias): event = Event.get_by_id(alias) if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return # Allow an alias to be a team number team_key = "frc{}".format(alias) if not ValidationHelper.team_id_validator(team_key): now = datetime.datetime.now() team_events_future = TeamYearEventsQuery(team_key, now.year).fetch_async() team_events = team_events_future.get_result() for event in team_events: if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return self.redirect("/gameday") return
def test_eventteam_updated(self): affected_refs = { 'event': {ndb.Key(Event, '2015casj'), ndb.Key(Event, '2015cama')}, 'team': {ndb.Key(Team, 'frc254'), ndb.Key(Team, 'frc604')}, 'year': {2014, 2015} } cache_keys = [ q.cache_key for q in get_affected_queries.eventteam_updated(affected_refs) ] self.assertEqual(len(cache_keys), 14) self.assertTrue(TeamEventsQuery('frc254').cache_key in cache_keys) self.assertTrue(TeamEventsQuery('frc604').cache_key in cache_keys) self.assertTrue( TeamParticipationQuery('frc254').cache_key in cache_keys) self.assertTrue( TeamParticipationQuery('frc604').cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc254', 2014).cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc254', 2015).cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc604', 2014).cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc604', 2015).cache_key in cache_keys) self.assertTrue(TeamListYearQuery(2014, 0).cache_key in cache_keys) self.assertTrue(TeamListYearQuery(2014, 1).cache_key in cache_keys) self.assertTrue(TeamListYearQuery(2015, 0).cache_key in cache_keys) self.assertTrue(TeamListYearQuery(2015, 1).cache_key in cache_keys) self.assertTrue(EventTeamsQuery('2015casj').cache_key in cache_keys) self.assertTrue(EventTeamsQuery('2015cama').cache_key in cache_keys)
def event_updated(affected_refs): event_keys = _filter(affected_refs['key']) years = _filter(affected_refs['year']) event_district_keys = _filter(affected_refs['district_key']) event_team_keys_future = EventTeam.query(EventTeam.event.IN([event_key for event_key in event_keys])).fetch_async(None, keys_only=True) events_future = ndb.get_multi_async(event_keys) queries_and_keys = [] for event_key in event_keys: queries_and_keys.append((EventQuery(event_key.id()))) queries_and_keys.append(EventDivisionsQuery(event_key.id())) for year in years: queries_and_keys.append((EventListQuery(year))) for event_district_key in event_district_keys: queries_and_keys.append((DistrictEventsQuery(event_district_key.id()))) for et_key in event_team_keys_future.get_result(): team_key = et_key.id().split('_')[1] year = int(et_key.id()[:4]) queries_and_keys.append((TeamEventsQuery(team_key))) queries_and_keys.append((TeamYearEventsQuery(team_key, year))) events_with_parents = filter(lambda e: e.get_result() is not None and e.get_result().parent_event is not None, events_future) parent_keys = set([e.get_result().parent_event for e in events_with_parents]) for parent_key in parent_keys: queries_and_keys.append((EventDivisionsQuery(parent_key.id()))) return queries_and_keys
def test_district_updated(self): affected_refs = { 'key': {ndb.Key(District, '2016ne')}, 'year': {2015, 2016}, 'abbreviation': {'ne', 'chs'} } cache_keys = [ q.cache_key for q in get_affected_queries.district_updated(affected_refs) ] self.assertEqual(len(cache_keys), 11) self.assertTrue(DistrictsInYearQuery(2015).cache_key in cache_keys) self.assertTrue(DistrictsInYearQuery(2016).cache_key in cache_keys) self.assertTrue(DistrictHistoryQuery('ne').cache_key in cache_keys) self.assertTrue(DistrictHistoryQuery('chs').cache_key in cache_keys) self.assertTrue(DistrictQuery('2016ne').cache_key in cache_keys) self.assertTrue(TeamDistrictsQuery('frc604').cache_key in cache_keys) # Necessary because APIv3 Event models include the District model self.assertTrue(EventQuery('2016necmp').cache_key in cache_keys) self.assertTrue(EventListQuery(2016).cache_key in cache_keys) self.assertTrue(DistrictEventsQuery('2016ne').cache_key in cache_keys) self.assertTrue(TeamEventsQuery('frc125').cache_key in cache_keys) self.assertTrue( TeamYearEventsQuery('frc125', 2016).cache_key in cache_keys)
def _render(self, team_key, year=None, model_type=None): if year: events, self._last_modified = TeamYearEventsQuery(team_key, int(year)).fetch(dict_version=3, return_updated=True) else: events, self._last_modified = TeamEventsQuery(team_key).fetch(dict_version=3, return_updated=True) if model_type is not None: events = filter_event_properties(events, model_type) return json.dumps(events, ensure_ascii=True, indent=2, sort_keys=True)
def _render(self, team_key, year=None): self._set_team(team_key) events = TeamYearEventsQuery(self.team_key, self.year).fetch() events = [ModelToDict.eventConverter(event) for event in events] return json.dumps(events, ensure_ascii=True)
def _get_past_stats(self, cur_event, team_list): past_stats_mean = defaultdict(list) # team key > values past_stats_var = defaultdict(list) # team key > values no_priors_team_list = team_list for year_diff in xrange(1): team_events_futures = [] for team in no_priors_team_list: team_events_futures.append( (team, TeamYearEventsQuery(team, cur_event.year - year_diff).fetch_async())) no_priors_team_list = [] for team, events_future in team_events_futures: events = events_future.get_result() EventHelper.sort_events(events) no_past_mean = True for event in events: if event.event_type_enum in EventType.SEASON_EVENT_TYPES and \ event.start_date < cur_event.start_date and \ event.event_type_enum != EventType.CMP_FINALS and \ event.details: # event.details is backed by in-context cache predictions = event.details.predictions if predictions and predictions.get( 'stat_mean_vars' ) and predictions['stat_mean_vars'].get('qual'): if team in predictions['stat_mean_vars'][ 'qual'].get(self._stat, {}).get('mean', []): team_mean = predictions['stat_mean_vars'][ 'qual'][self._stat]['mean'][team] if year_diff != 0: team_mean *= 1 # TODO: Hacky; scale based on actual data past_stats_mean[team].append(team_mean) no_past_mean = False if team in predictions['stat_mean_vars'][ 'qual'].get(self._stat, {}).get('var', []): team_var = predictions['stat_mean_vars'][ 'qual'][self._stat]['var'][team] if year_diff != 0: team_var = self._default_var * 3 # TODO: Hacky; scale based on actual data past_stats_var[team].append(team_var) if no_past_mean: no_priors_team_list.append(team) return past_stats_mean, past_stats_var
def eventteam_updated(affected_refs): event_keys = filter(None, affected_refs['event']) team_keys = filter(None, affected_refs['team']) years = filter(None, affected_refs['year']) queries_and_keys = [] for team_key in team_keys: queries_and_keys.append(TeamEventsQuery(team_key.id())) queries_and_keys.append(TeamParticipationQuery(team_key.id())) page_num = _get_team_page_num(team_key.id()) for year in years: queries_and_keys.append(TeamYearEventsQuery(team_key.id(), year)) queries_and_keys.append(TeamListYearQuery(year, page_num)) for event_key in event_keys: queries_and_keys.append(EventTeamsQuery(event_key.id())) return queries_and_keys
def event_updated(affected_refs): event_keys = filter(None, affected_refs['key']) years = filter(None, affected_refs['year']) event_district_keys = filter(None, affected_refs['event_district_key']) event_team_keys_future = EventTeam.query(EventTeam.event.IN([event_key for event_key in event_keys])).fetch_async(None, keys_only=True) queries_and_keys = [] for year in years: queries_and_keys.append((EventListQuery(year))) for event_district_key in event_district_keys: queries_and_keys.append((DistrictEventsQuery(event_district_key))) for et_key in event_team_keys_future.get_result(): team_key = et_key.id().split('_')[1] year = int(et_key.id()[:4]) queries_and_keys.append((TeamEventsQuery(team_key))) queries_and_keys.append((TeamYearEventsQuery(team_key, year))) return queries_and_keys
def get(self): self._require_registration() user = self.user_bundle.account.key now = datetime.datetime.now() team_favorites_future = Favorite.query( Favorite.model_type == ModelType.TEAM, ancestor=user).fetch_async() favorite_team_keys = map(lambda f: ndb.Key(Team, f.model_key), team_favorites_future.get_result()) favorite_teams_future = ndb.get_multi_async(favorite_team_keys) favorite_teams = [ team_future.get_result() for team_future in favorite_teams_future ] favorite_teams_events_futures = [] for team in favorite_teams: favorite_teams_events_futures.append( TeamYearEventsQuery(team.key_name, now.year).fetch_async()) past_events_by_event = {} live_events_by_event = {} future_events_by_event = {} for team, events_future in zip(favorite_teams, favorite_teams_events_futures): events = events_future.get_result() if not events: continue EventHelper.sort_events(events) # Sort by date for event in events: if event.within_a_day: if event.key_name not in live_events_by_event: live_events_by_event[event.key_name] = (event, []) live_events_by_event[event.key_name][1].append(team) elif event.start_date < now: if event.key_name not in past_events_by_event: past_events_by_event[event.key_name] = (event, []) past_events_by_event[event.key_name][1].append(team) else: if event.key_name not in future_events_by_event: future_events_by_event[event.key_name] = (event, []) future_events_by_event[event.key_name][1].append(team) break # Only find one next event for each team past_events = [] past_eventteams = [] for past_event, past_eventteam in past_events_by_event.itervalues(): past_events.append(past_event) past_eventteams.append(past_eventteam) past_events_with_teams = EventTeamStatusHelper.buildEventTeamStatus( past_events, past_eventteams, favorite_teams) past_events_with_teams.sort(key=lambda x: x[0].name) past_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0])) past_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0])) live_events = [] live_eventteams = [] for live_event, live_eventteam in live_events_by_event.itervalues(): live_events.append(live_event) live_eventteams.append(live_eventteam) live_events_with_teams = EventTeamStatusHelper.buildEventTeamStatus( live_events, live_eventteams, favorite_teams) live_events_with_teams.sort(key=lambda x: x[0].name) future_events_with_teams = [] for event_key, data in future_events_by_event.iteritems(): future_events_with_teams.append( (data[0], TeamHelper.sortTeams(data[1]))) future_events_with_teams.sort(key=lambda x: x[0].name) future_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0])) future_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0])) # Resolve future before rendering for _, teams_and_statuses_future in past_events_with_teams: for team_and_status_future in teams_and_statuses_future: team_and_status_future[1] = team_and_status_future[ 1].get_result() for _, teams_and_statuses_future in live_events_with_teams: for team_and_status_future in teams_and_statuses_future: team_and_status_future[1] = team_and_status_future[ 1].get_result() self.template_values.update({ 'past_events_with_teams': past_events_with_teams, 'live_events_with_teams': live_events_with_teams, 'future_events_with_teams': future_events_with_teams, }) path = os.path.join(os.path.dirname(__file__), '../templates/mytba_live.html') self.response.out.write(template.render(path, self.template_values))
def _getteam_nextmatch(cls, request): team_number = request['result']['parameters']['team_number'] team_key = 'frc{}'.format(team_number) team = Team.get_by_id(team_key) if team: events = TeamYearEventsQuery(team_key, datetime.datetime.now().year).fetch() EventHelper.sort_events(events) # Find first current or future event for event in events: if event.now: matches = TeamEventMatchesQuery(team_key, event.key.id()).fetch() matches = MatchHelper.play_order_sort_matches(matches) if matches: next_match = None for match in matches: if not match.has_been_played: next_match = match break if next_match is not None: if match.predicted_time: eta = match.predicted_time - datetime.datetime.now( ) eta_str = None if eta < datetime.timedelta(minutes=5): fmt = 'Team {0} will be playing in {1} soon at the {3}.' else: eta_str = '' days = eta.days hours, rem = divmod(eta.seconds, 3600) minutes, _ = divmod(rem, 60) if days: eta_str += ' {} day{}'.format( days, '' if days == 1 else 's') if hours: eta_str += ' {} hour{}'.format( hours, '' if hours == 1 else 's') if minutes: eta_str += ' {} minute{}'.format( minutes, '' if minutes == 1 else 's') fmt = 'Team {0} will be playing in {1} in about{2} at the {3}.' text = fmt.format(team_number, match.verbose_name, eta_str, event.normalized_name) tts = fmt.format( cls._team_number_tts(team_number), match.verbose_name, eta_str, event.normalized_name) else: fmt = 'Team {0} will be playing in {1} at the {2}.' text = fmt.format(team_number, match.verbose_name, event.normalized_name) tts = fmt.format( cls._team_number_tts(team_number), match.verbose_name, event.normalized_name) add_messages = cls._create_link_chip( match.verbose_name, 'https://www.thebluealliance.com/match/{}'. format(match.key.id())) else: fmt = 'Team {0} has no more scheduled matches at the {1}.' text = fmt.format(team_number, event.normalized_name) tts = fmt.format(cls._team_number_tts(team_number), event.normalized_name) add_messages = [] else: fmt = 'Team {0} has no scheduled matches at the {1}.' text = fmt.format(team_number, event.normalized_name) tts = fmt.format(cls._team_number_tts(team_number), event.normalized_name) add_messages = [] break elif event.future: fmt = 'Team {0} will be competing at the {1} which begins on {2}.' event_date = event.start_date.strftime("%B %d") text = fmt.format(team_number, event.normalized_name, event_date) tts = fmt.format(cls._team_number_tts(team_number), event.normalized_name, event_date) add_messages = cls._create_link_chip( 'event page', 'https://www.thebluealliance.com/event/{}'.format( event.key.id())) break else: fmt = 'Team {0} is not registered for any more events this season.' text = fmt.format(team_number) tts = fmt.format(cls._team_number_tts(team_number)) add_messages = [] fmt = ' Would you like to know more about {} or another team?' text += fmt.format(team_number) tts += fmt.format(cls._team_number_tts(team_number)) add_messages += cls._create_suggestion_chips([ 'Current status', 'Location', 'Rookie year', 'Another team', 'No thanks', ]) else: fmt = 'Team {0} does not exist. Please ask about another team.' text = fmt.format(team_number) tts = fmt.format(cls._team_number_tts(team_number)) add_messages = [] return { 'speech': text, 'messages': cls._create_simple_response(text, tts=tts) + add_messages, }
def _getteam_status(cls, request): team_number = request['result']['parameters']['team_number'] team_key = 'frc{}'.format(team_number) team = Team.get_by_id(team_key) if team: events = TeamYearEventsQuery(team_key, datetime.datetime.now().year).fetch() current_event = None for event in events: if event.now: current_event = event if current_event: event_team = EventTeam.get_by_id('{}_{}'.format( current_event.key.id(), team_key)) text = EventTeamStatusHelper.generate_team_at_event_status_string( team_key, event_team.status, formatting=False, event=current_event) tts = 'Team {} {}'.format( cls._team_number_tts(team_number), EventTeamStatusHelper.generate_team_at_event_status_string( team_key, event_team.status, formatting=False, event=current_event, include_team=False, verbose=True)) additional_prompt = ' Would you like to know more about {} or another team?'.format( team_number) text += additional_prompt tts += additional_prompt messages = cls._create_simple_response(text, tts=tts) +\ cls._create_link_chip(current_event.display_name, 'https://www.thebluealliance.com/event/{}'.format(current_event.key.id())) else: fmt = 'Team {0} is not currently competing. Would you like to know more about {0} or another team?' text = fmt.format(team_number) tts = fmt.format(cls._team_number_tts(team_number)) messages = cls._create_simple_response(text, tts=tts) messages += cls._create_suggestion_chips([ 'Next match', 'Location', 'Rookie year', 'Another team', 'No thanks', ]) else: fmt = 'Team {0} does not exist. Please ask about another team.' text = fmt.format(team_number) tts = fmt.format(cls._team_number_tts(team_number)) messages = cls._create_simple_response(text, tts=tts) return { 'speech': text, 'messages': messages, }
def get(self): self._require_registration() user = self.user_bundle.account.key now = datetime.datetime.now() year = self.request.get('year') if year and year.isdigit(): year = int(year) else: year = now.year team_favorites_future = Favorite.query( Favorite.model_type == ModelType.TEAM, ancestor=user).fetch_async() favorite_team_keys = map(lambda f: ndb.Key(Team, f.model_key), team_favorites_future.get_result()) favorite_teams_future = ndb.get_multi_async(favorite_team_keys) favorite_teams = [ team_future.get_result() for team_future in favorite_teams_future ] favorite_teams_events_futures = [] favorite_teams_awards_futures = {} for team in favorite_teams: favorite_teams_events_futures.append( TeamYearEventsQuery(team.key_name, year).fetch_async()) favorite_teams_awards_futures[team.key.id()] = TeamYearAwardsQuery( team.key_name, year).fetch_async() past_events_by_event = {} live_events_by_event = {} future_events_by_event = {} favorite_event_team_keys = [] for team, events_future in zip(favorite_teams, favorite_teams_events_futures): events = events_future.get_result() if not events: continue EventHelper.sort_events(events) # Sort by date for event in events: favorite_event_team_keys.append( ndb.Key(EventTeam, '{}_{}'.format(event.key.id(), team.key.id()))) if event.within_a_day: if event.key_name not in live_events_by_event: live_events_by_event[event.key_name] = (event, []) live_events_by_event[event.key_name][1].append(team) elif event.start_date < now: if event.key_name not in past_events_by_event: past_events_by_event[event.key_name] = (event, []) past_events_by_event[event.key_name][1].append(team) else: if event.key_name not in future_events_by_event: future_events_by_event[event.key_name] = (event, []) future_events_by_event[event.key_name][1].append(team) event_team_awards = defaultdict(lambda: defaultdict(list)) for team_key, awards_future in favorite_teams_awards_futures.items(): for award in awards_future.get_result(): event_team_awards[award.event.id()][team_key].append(award) ndb.get_multi(favorite_event_team_keys) # Warms context cache past_events_with_teams = [] for event, teams in past_events_by_event.itervalues(): teams_and_statuses = [] for team in teams: event_team = EventTeam.get_by_id('{}_{}'.format( event.key.id(), team.key.id())) # Should be in context cache status_str = { 'alliance': EventTeamStatusHelper. generate_team_at_event_alliance_status_string( team.key.id(), event_team.status), 'playoff': EventTeamStatusHelper. generate_team_at_event_playoff_status_string( team.key.id(), event_team.status), } teams_and_statuses.append( (team, event_team.status, status_str, AwardHelper.organizeAwards( event_team_awards[event.key.id()][team.key.id()]))) teams_and_statuses.sort(key=lambda x: x[0].team_number) past_events_with_teams.append((event, teams_and_statuses)) past_events_with_teams.sort(key=lambda x: x[0].name) past_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0])) past_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0])) live_events_with_teams = [] for event, teams in live_events_by_event.itervalues(): teams_and_statuses = [] for team in teams: event_team = EventTeam.get_by_id('{}_{}'.format( event.key.id(), team.key.id())) # Should be in context cache status_str = { 'alliance': EventTeamStatusHelper. generate_team_at_event_alliance_status_string( team.key.id(), event_team.status), 'playoff': EventTeamStatusHelper. generate_team_at_event_playoff_status_string( team.key.id(), event_team.status), } teams_and_statuses.append( (team, event_team.status, status_str)) teams_and_statuses.sort(key=lambda x: x[0].team_number) live_events_with_teams.append((event, teams_and_statuses)) live_events_with_teams.sort(key=lambda x: x[0].name) live_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0])) live_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0])) future_events_with_teams = [] for event, teams in future_events_by_event.itervalues(): teams.sort(key=lambda t: t.team_number) future_events_with_teams.append((event, teams)) future_events_with_teams.sort(key=lambda x: x[0].name) future_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0])) future_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0])) self.template_values.update({ 'year': year, 'past_only': year < now.year, 'past_events_with_teams': past_events_with_teams, 'live_events_with_teams': live_events_with_teams, 'future_events_with_teams': future_events_with_teams, }) path = os.path.join(os.path.dirname(__file__), '../templates/mytba_live.html') self.response.out.write(template.render(path, self.template_values))
def get(self): self._require_login() self._require_registration() user = self.user_bundle.account.key now = datetime.datetime.now() team_favorites_future = Favorite.query( Favorite.model_type == ModelType.TEAM, ancestor=user).fetch_async() live_events = EventHelper.getEventsWithinADay() favorite_team_keys = map(lambda f: ndb.Key(Team, f.model_key), team_favorites_future.get_result()) favorite_teams_future = ndb.get_multi_async(favorite_team_keys) live_eventteams_futures = [] for event in live_events: live_eventteams_futures.append( EventTeamsQuery(event.key_name).fetch_async()) favorite_teams = [ team_future.get_result() for team_future in favorite_teams_future ] favorite_teams_events_futures = [] for team in favorite_teams: favorite_teams_events_futures.append( TeamYearEventsQuery(team.key_name, now.year).fetch_async()) live_events_with_teams = EventTeamStatusHelper.buildEventTeamStatus( live_events, live_eventteams_futures, favorite_teams) future_events_by_event = {} for team, events_future in zip(favorite_teams, favorite_teams_events_futures): events = events_future.get_result() if not events: continue EventHelper.sort_events(events) next_event = next( (e for e in events if e.start_date > now and not e.within_a_day), None) if next_event: if next_event.key_name not in future_events_by_event: future_events_by_event[next_event.key_name] = (next_event, []) future_events_by_event[next_event.key_name][1].append(team) future_events_with_teams = [] for event_key, data in future_events_by_event.iteritems(): future_events_with_teams.append( (data[0], TeamHelper.sortTeams(data[1]))) future_events_with_teams.sort(key=lambda x: x[0].name) future_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0])) future_events_with_teams.sort( key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0])) self.template_values.update({ 'live_events_with_teams': live_events_with_teams, 'future_events_with_teams': future_events_with_teams, }) path = os.path.join(os.path.dirname(__file__), '../templates/mytba_live.html') self.response.out.write(template.render(path, self.template_values))