def _render(self, year=None, explicit_year=False):
        events = event_query.EventListQuery(year).fetch()
        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        district_enums = set()
        for event in events:
            if event.event_district_enum is not None and event.event_district_enum != DistrictType.NO_DISTRICT:
                district_enums.add(event.event_district_enum)

        districts = []  # a tuple of (district abbrev, district name)
        for district_enum in district_enums:
            districts.append((DistrictType.type_abbrevs[district_enum],
                              DistrictType.type_names[district_enum]))
        districts = sorted(districts, key=lambda d: d[1])

        self.template_values.update({
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
            "districts": districts,
        })

        path = os.path.join(os.path.dirname(__file__), '../templates/event_list.html')
        return template.render(path, self.template_values)
Exemple #2
0
    def _render(self, year=None, explicit_year=False):
        events = event_query.EventListQuery(year).fetch()
        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        district_enums = set()
        for event in events:
            if event.event_district_enum is not None and event.event_district_enum != DistrictType.NO_DISTRICT:
                district_enums.add(event.event_district_enum)

        districts = []  # a tuple of (district abbrev, district name)
        for district_enum in district_enums:
            districts.append((DistrictType.type_abbrevs[district_enum],
                              DistrictType.type_names[district_enum]))
        districts = sorted(districts, key=lambda d: d[1])

        self.template_values.update({
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
            "districts": districts,
        })

        return jinja2_engine.render('event_list.html', self.template_values)
    def get(self, event_key=None):
        self._require_login()
        self._require_registration()

        if event_key is None:
            events = EventHelper.getEventsWithinADay()
            EventHelper.sort_events(events)
            self.template_values['events'] = events
            self.response.out.write(jinja2_engine.render('mytba_add_hot_matches_base.html', self.template_values))
            return

        event = Event.get_by_id(event_key)
        if not event:
            self.abort(404)

        subscriptions_future = Subscription.query(
            Subscription.model_type==ModelType.MATCH,
            Subscription.notification_types==NotificationType.UPCOMING_MATCH,
            ancestor=self.user_bundle.account.key).fetch_async(projection=[Subscription.model_key])

        matches = []
        if event.matchstats and 'match_predictions' in event.matchstats:
            match_predictions = event.matchstats['match_predictions']
            max_hotness = 0
            min_hotness = float('inf')
            for match in event.matches:
                if not match.has_been_played and match.key.id() in match_predictions:
                    prediction = match_predictions[match.key.id()]
                    red_score = prediction['red']['score']
                    blue_score = prediction['blue']['score']
                    if red_score > blue_score:
                        winner_score = red_score
                        loser_score = blue_score
                    else:
                        winner_score = blue_score
                        loser_score = red_score

                    hotness = winner_score + 2.0*loser_score  # Favor close high scoring matches

                    max_hotness = max(max_hotness, hotness)
                    min_hotness = min(min_hotness, hotness)
                    match.hotness = hotness
                    matches.append(match)

        existing_subscriptions = set()
        for sub in subscriptions_future.get_result():
            existing_subscriptions.add(sub.model_key)

        hot_matches = []
        for match in matches:
            match.hotness = 100 * (match.hotness - min_hotness) / (max_hotness - min_hotness)
            match.already_subscribed = match.key.id() in existing_subscriptions
            hot_matches.append(match)
        hot_matches = sorted(hot_matches, key=lambda match: -match.hotness)
        matches_dict = {'qm': hot_matches[:25]}

        self.template_values['event'] = event
        self.template_values['matches'] = matches_dict

        self.response.out.write(jinja2_engine.render('mytba_add_hot_matches.html', self.template_values))
Exemple #4
0
    def _render(self, year=None, explicit_year=False):
        event_keys = Event.query(Event.year == year).fetch(1000,
                                                           keys_only=True)
        events = ndb.get_multi(event_keys)
        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        district_enums = set()
        for event in events:
            if event.event_district_enum is not None and event.event_district_enum != DistrictType.NO_DISTRICT:
                district_enums.add(event.event_district_enum)

        districts = []  # a tuple of (district abbrev, district name)
        for district_enum in district_enums:
            districts.append((DistrictType.type_abbrevs[district_enum],
                              DistrictType.type_names[district_enum]))
        districts = sorted(districts, key=lambda d: d[1])

        self.template_values.update({
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
            "districts": districts,
        })

        path = os.path.join(os.path.dirname(__file__),
                            '../templates/event_list.html')
        return template.render(path, self.template_values)
    def get(self, event_key=None):
        self._require_registration()

        if event_key is None:
            events = EventHelper.getEventsWithinADay()
            EventHelper.sort_events(events)
            self.template_values['events'] = events
            self.response.out.write(jinja2_engine.render('mytba_add_hot_matches_base.html', self.template_values))
            return

        event = Event.get_by_id(event_key)
        if not event:
            self.abort(404)

        subscriptions_future = Subscription.query(
            Subscription.model_type==ModelType.MATCH,
            Subscription.notification_types==NotificationType.UPCOMING_MATCH,
            ancestor=self.user_bundle.account.key).fetch_async(projection=[Subscription.model_key])

        matches = []
        if event.matchstats and 'match_predictions' in event.matchstats:
            match_predictions = event.matchstats['match_predictions']
            max_hotness = 0
            min_hotness = float('inf')
            for match in event.matches:
                if not match.has_been_played and match.key.id() in match_predictions:
                    prediction = match_predictions[match.key.id()]
                    red_score = prediction['red']['score']
                    blue_score = prediction['blue']['score']
                    if red_score > blue_score:
                        winner_score = red_score
                        loser_score = blue_score
                    else:
                        winner_score = blue_score
                        loser_score = red_score

                    hotness = winner_score + 2.0*loser_score  # Favor close high scoring matches

                    max_hotness = max(max_hotness, hotness)
                    min_hotness = min(min_hotness, hotness)
                    match.hotness = hotness
                    matches.append(match)

        existing_subscriptions = set()
        for sub in subscriptions_future.get_result():
            existing_subscriptions.add(sub.model_key)

        hot_matches = []
        for match in matches:
            match.hotness = 100 * (match.hotness - min_hotness) / (max_hotness - min_hotness)
            match.already_subscribed = match.key.id() in existing_subscriptions
            hot_matches.append(match)
        hot_matches = sorted(hot_matches, key=lambda match: -match.hotness)
        matches_dict = {'qm': hot_matches[:25]}

        self.template_values['event'] = event
        self.template_values['matches'] = matches_dict

        self.response.out.write(jinja2_engine.render('mytba_add_hot_matches.html', self.template_values))
    def _render(self, district_abbrev, year=None):
        self._set_district(district_abbrev)

        if self.year < 2014:
            return json.dumps([], ensure_ascii=True)

        event_keys = Event.query(
            Event.year == self.year,
            Event.event_district_enum == self.district).fetch(None,
                                                              keys_only=True)
        if not event_keys:
            return json.dumps([], ensure_ascii=True)
        events = ndb.get_multi(event_keys)

        event_futures = ndb.get_multi_async(event_keys)
        event_team_keys_future = EventTeam.query(
            EventTeam.event.IN(event_keys)).fetch_async(None, keys_only=True)

        team_futures = ndb.get_multi_async(
            set([
                ndb.Key(Team,
                        et_key.id().split('_')[1])
                for et_key in event_team_keys_future.get_result()
            ]))

        events = [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        team_totals = DistrictHelper.calculate_rankings(
            events, team_futures, self.year)

        rankings = []

        current_rank = 1
        for key, points in team_totals:
            point_detail = {}
            point_detail["rank"] = current_rank
            point_detail["team_key"] = key
            point_detail["event_points"] = {}
            for event in points["event_points"]:
                event_key = event[0].key_name
                point_detail["event_points"][event_key] = event[1]
                event_details = Event.get_by_id(event_key)
                point_detail["event_points"][event[0].key_name][
                    'district_cmp'] = True if event_details.event_type_enum == EventType.DISTRICT_CMP else False

            if "rookie_bonus" in points:
                point_detail["rookie_bonus"] = points["rookie_bonus"]
            else:
                point_detail["rookie_bonus"] = 0
            point_detail["point_total"] = points["point_total"]
            rankings.append(point_detail)
            current_rank += 1

        return json.dumps(rankings)
    def _render(self, district_abbrev, year=None, explicit_year=False):
        district_type = DistrictType.abbrevs[district_abbrev]

        event_keys = Event.query(Event.year == year, Event.event_district_enum == district_type).fetch(None, keys_only=True)
        if not event_keys:
            self.abort(404)

        # needed for valid_years
        all_cmp_event_keys_future = Event.query(Event.event_district_enum == district_type, Event.event_type_enum == EventType.DISTRICT_CMP).fetch_async(None, keys_only=True)

        # needed for valid_districts
        district_cmp_keys_future = Event.query(Event.year == year, Event.event_type_enum == EventType.DISTRICT_CMP).fetch_async(None, keys_only=True)  # to compute valid_districts

        event_futures = ndb.get_multi_async(event_keys)
        event_team_keys_future = EventTeam.query(EventTeam.event.IN(event_keys)).fetch_async(None, keys_only=True)
        if year == 2014:  # TODO: only 2014 has accurate rankings calculations
            team_futures = ndb.get_multi_async(set([ndb.Key(Team, et_key.id().split('_')[1]) for et_key in event_team_keys_future.get_result()]))

        events = [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        district_cmp_futures = ndb.get_multi_async(district_cmp_keys_future.get_result())

        if year == 2014:  # TODO: only 2014 has accurate rankings calculations
            team_totals = DistrictHelper.calculate_rankings(events, team_futures, year)
        else:
            team_totals = None

        valid_districts = set()
        for district_cmp_future in district_cmp_futures:
            district_cmp = district_cmp_future.get_result()
            cmp_dis_type = district_cmp.event_district_enum
            if cmp_dis_type is None:
                logging.warning("District event {} has unknown district type!".format(district_cmp.key.id()))
            else:
                valid_districts.add((DistrictType.type_names[cmp_dis_type], DistrictType.type_abbrevs[cmp_dis_type]))
        valid_districts = sorted(valid_districts, key=lambda (name, _): name)

        self.template_values.update({
            'explicit_year': explicit_year,
            'year': year,
            'valid_years': sorted(set([int(event_key.id()[:4]) for event_key in all_cmp_event_keys_future.get_result()])),
            'valid_districts': valid_districts,
            'district_name': DistrictType.type_names[district_type],
            'district_abbrev': district_abbrev,
            'events': events,
            'team_totals': team_totals,
        })

        path = os.path.join(os.path.dirname(__file__), '../templates/district_details.html')
        return template.render(path, self.template_values)
    def _render(self, district_abbrev, year=None):
        self._set_district(district_abbrev)

        if self.year < 2009:
            return json.dumps([], ensure_ascii=True)

        event_keys = Event.query(Event.year == self.year, Event.event_district_enum == self.district).fetch(
            None, keys_only=True
        )
        if not event_keys:
            return json.dumps([], ensure_ascii=True)
        events = ndb.get_multi(event_keys)

        event_futures = ndb.get_multi_async(event_keys)
        event_team_keys_future = EventTeam.query(EventTeam.event.IN(event_keys)).fetch_async(None, keys_only=True)

        team_futures = ndb.get_multi_async(
            set([ndb.Key(Team, et_key.id().split("_")[1]) for et_key in event_team_keys_future.get_result()])
        )

        events = [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        team_totals = DistrictHelper.calculate_rankings(events, team_futures, self.year)

        rankings = []

        current_rank = 1
        for key, points in team_totals:
            point_detail = {}
            point_detail["rank"] = current_rank
            point_detail["team_key"] = key
            point_detail["event_points"] = {}
            for event in points["event_points"]:
                event_key = event[0].key_name
                point_detail["event_points"][event_key] = event[1]
                event_details = Event.get_by_id(event_key)
                point_detail["event_points"][event[0].key_name]["district_cmp"] = (
                    True if event_details.event_type_enum == EventType.DISTRICT_CMP else False
                )

            if "rookie_bonus" in points:
                point_detail["rookie_bonus"] = points["rookie_bonus"]
            else:
                point_detail["rookie_bonus"] = 0
            point_detail["point_total"] = points["point_total"]
            rankings.append(point_detail)
            current_rank += 1

        return json.dumps(rankings)
    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))
Exemple #10
0
    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 _render(self, year=None, explicit_year=False):
        state_prov = self.request.get('state_prov', None)

        districts_future = DistrictsInYearQuery(year).fetch_async()
        all_events_future = event_query.EventListQuery(
            year).fetch_async()  # Needed for state_prov
        if state_prov:
            events_future = Event.query(
                Event.year == year,
                Event.state_prov == state_prov).fetch_async()
        else:
            events_future = all_events_future

        events = events_future.get_result()
        if state_prov == '' or (state_prov and not events):
            self.redirect(self.request.path, abort=True)

        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        districts = []  # a tuple of (district abbrev, district name)
        for district in districts_future.get_result():
            districts.append((district.abbreviation, district.display_name))
        districts = sorted(districts, key=lambda d: d[1])

        valid_state_provs = set()
        for event in all_events_future.get_result():
            if event.state_prov:
                valid_state_provs.add(event.state_prov)
        valid_state_provs = sorted(valid_state_provs)

        self.template_values.update({
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
            "districts": districts,
            "state_prov": state_prov,
            "valid_state_provs": valid_state_provs,
        })

        if year == datetime.datetime.now().year:
            self._cache_expiration = self.SHORT_CACHE_EXPIRATION

        return jinja2_engine.render('event_list.html', self.template_values)
    def _render(self, year=None, explicit_year=False):
        state_prov = self.request.get('state_prov', None)

        all_events_future = event_query.EventListQuery(year).fetch_async()  # Needed for state_prov
        if state_prov:
            events_future = Event.query(Event.year==year, Event.state_prov==state_prov).fetch_async()
        else:
            events_future = all_events_future

        events = events_future.get_result()
        if state_prov == '' or (state_prov and not events):
            self.redirect(self.request.path, abort=True)

        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        district_enums = set()
        for event in events:
            if event.event_district_enum is not None and event.event_district_enum != DistrictType.NO_DISTRICT:
                district_enums.add(event.event_district_enum)

        districts = []  # a tuple of (district abbrev, district name)
        for district_enum in district_enums:
            districts.append((DistrictType.type_abbrevs[district_enum],
                              DistrictType.type_names[district_enum]))
        districts = sorted(districts, key=lambda d: d[1])

        valid_state_provs = set()
        for event in all_events_future.get_result():
            if event.state_prov:
                valid_state_provs.add(event.state_prov)
        valid_state_provs = sorted(valid_state_provs)

        self.template_values.update({
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
            "districts": districts,
            "state_prov": state_prov,
            "valid_state_provs": valid_state_provs,
        })

        return jinja2_engine.render('event_list.html', self.template_values)
Exemple #13
0
    def _render(self, year=None, explicit_year=False):
        event_keys = Event.query(Event.year == year).fetch(1000, keys_only=True)
        events = ndb.get_multi(event_keys)
        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        template_values = {
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
        }

        path = os.path.join(os.path.dirname(__file__), '../templates/event_list.html')
        return template.render(path, template_values)
    def _render(self, year=None, explicit_year=False):
        state_prov = self.request.get('state_prov', None)

        districts_future = DistrictsInYearQuery(year).fetch_async()
        all_events_future = event_query.EventListQuery(year).fetch_async()  # Needed for state_prov
        if state_prov:
            events_future = Event.query(Event.year==year, Event.state_prov==state_prov).fetch_async()
        else:
            events_future = all_events_future

        events = events_future.get_result()
        if state_prov == '' or (state_prov and not events):
            self.redirect(self.request.path, abort=True)

        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        districts = []  # a tuple of (district abbrev, district name)
        for district in districts_future.get_result():
            districts.append((district.abbreviation, district.display_name))
        districts = sorted(districts, key=lambda d: d[1])

        valid_state_provs = set()
        for event in all_events_future.get_result():
            if event.state_prov:
                valid_state_provs.add(event.state_prov)
        valid_state_provs = sorted(valid_state_provs)

        self.template_values.update({
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
            "districts": districts,
            "state_prov": state_prov,
            "valid_state_provs": valid_state_provs,
        })

        if year == datetime.datetime.now().year:
            self._cache_expiration = self.SHORT_CACHE_EXPIRATION

        return jinja2_engine.render('event_list.html', self.template_values)
Exemple #15
0
    def _render(self, district_abbrev, year=None):
        self._set_district(district_abbrev, self.year)

        if self.year < 2009:
            return json.dumps([], ensure_ascii=True)

        events_future = DistrictEventsQuery(
            District.renderKeyName(self.year, district_abbrev)).fetch_async()
        district_teams_future = DistrictTeamsQuery("{}{}".format(
            year, district_abbrev)).fetch_async()

        events = events_future.get_result()
        if not events:
            return json.dumps([], ensure_ascii=True)
        EventHelper.sort_events(events)

        team_totals = DistrictHelper.calculate_rankings(
            events, district_teams_future.get_result(), self.year)

        rankings = []

        current_rank = 1
        for key, points in team_totals:
            point_detail = {}
            point_detail["rank"] = current_rank
            point_detail["team_key"] = key
            point_detail["event_points"] = {}
            for event in points["event_points"]:
                event_key = event[0].key_name
                point_detail["event_points"][event_key] = event[1]
                event_details = Event.get_by_id(event_key)
                point_detail["event_points"][event[0].key_name][
                    'district_cmp'] = True if event_details.event_type_enum == EventType.DISTRICT_CMP else False

            if "rookie_bonus" in points:
                point_detail["rookie_bonus"] = points["rookie_bonus"]
            else:
                point_detail["rookie_bonus"] = 0
            point_detail["point_total"] = points["point_total"]
            rankings.append(point_detail)
            current_rank += 1

        return json.dumps(rankings)
Exemple #16
0
    def get(self, district_key):
        district = District.get_by_id(district_key)
        if not district:
            self.response.out.write(
                "District {} does not exist!".format(district_key))
            return

        events_future = DistrictEventsQuery(district_key).fetch_async()
        teams_future = DistrictTeamsQuery(district_key).fetch_async()

        events = events_future.get_result()
        for event in events:
            event.prep_details()
        EventHelper.sort_events(events)
        team_totals = DistrictHelper.calculate_rankings(
            events, teams_future, district.year)

        rankings = []
        current_rank = 1
        for key, points in team_totals:
            point_detail = {}
            point_detail["rank"] = current_rank
            point_detail["team_key"] = key
            point_detail["event_points"] = []
            for event, event_points in points["event_points"]:
                event_points['event_key'] = event.key.id()
                event_points['district_cmp'] = (
                    event.event_type_enum == EventType.DISTRICT_CMP or
                    event.event_type_enum == EventType.DISTRICT_CMP_DIVISION)
                point_detail["event_points"].append(event_points)

            point_detail["rookie_bonus"] = points.get("rookie_bonus", 0)
            point_detail["point_total"] = points["point_total"]
            rankings.append(point_detail)
            current_rank += 1

        if rankings:
            district.rankings = rankings
            DistrictManipulator.createOrUpdate(district)

        if 'X-Appengine-Taskname' not in self.request.headers:  # Only write out if not in taskqueue
            self.response.out.write(
                "Finished calculating rankings for: {}".format(district_key))
    def get(self, when):
        if when == "now":
            events = EventHelper.getEventsWithinADay()
        else:
            events = Event.query(Event.year == int(when)).fetch(500)

        EventHelper.sort_events(events)
        for event in events:
            taskqueue.add(
                queue_name=
                'run-in-order',  # Because predictions depend on past events
                url='/tasks/math/do/event_matchstats/' + event.key_name,
                method='GET')

        template_values = {'event_count': len(events), 'year': when}

        path = os.path.join(os.path.dirname(__file__),
                            '../templates/math/event_matchstats_enqueue.html')
        self.response.out.write(template.render(path, template_values))
Exemple #18
0
    def _render(self, year=None, explicit_year=False):
        event_keys = Event.query(Event.year == year).fetch(1000,
                                                           keys_only=True)
        events = ndb.get_multi(event_keys)
        EventHelper.sort_events(events)

        week_events = EventHelper.groupByWeek(events)

        template_values = {
            "events": events,
            "explicit_year": explicit_year,
            "selected_year": year,
            "valid_years": self.VALID_YEARS,
            "week_events": week_events,
        }

        path = os.path.join(os.path.dirname(__file__),
                            '../templates/event_list.html')
        return template.render(path, template_values)
    def get(self, when):
        if when == "now":
            events = EventHelper.getEventsWithinADay()
        else:
            events = Event.query(Event.year == int(when)).fetch(500)

        EventHelper.sort_events(events)
        for event in events:
            taskqueue.add(
                queue_name='run-in-order',  # Because predictions depend on past events
                url='/tasks/math/do/event_matchstats/' + event.key_name,
                method='GET')

        template_values = {
            'event_count': len(events),
            'year': when
        }

        path = os.path.join(os.path.dirname(__file__), '../templates/math/event_matchstats_enqueue.html')
        self.response.out.write(template.render(path, template_values))
    def get(self, district_key):
        district = District.get_by_id(district_key)
        if not district:
            self.response.out.write("District {} does not exist!".format(district_key))
            return

        events_future = DistrictEventsQuery(district_key).fetch_async()
        teams_future = DistrictTeamsQuery(district_key).fetch_async()

        events = events_future.get_result()
        for event in events:
            event.prep_details()
        EventHelper.sort_events(events)
        team_totals = DistrictHelper.calculate_rankings(events, teams_future, district.year)

        rankings = []
        current_rank = 1
        for key, points in team_totals:
            point_detail = {}
            point_detail["rank"] = current_rank
            point_detail["team_key"] = key
            point_detail["event_points"] = []
            for event, event_points in points["event_points"]:
                event_points['event_key'] = event.key.id()
                event_points['district_cmp'] = (
                    event.event_type_enum == EventType.DISTRICT_CMP or
                    event.event_type_enum == EventType.DISTRICT_CMP_DIVISION)
                point_detail["event_points"].append(event_points)

            point_detail["rookie_bonus"] = points.get("rookie_bonus", 0)
            point_detail["point_total"] = points["point_total"]
            rankings.append(point_detail)
            current_rank += 1

        if rankings:
            district.rankings = rankings
            DistrictManipulator.createOrUpdate(district)

        if 'X-Appengine-Taskname' not in self.request.headers:  # Only write out if not in taskqueue
            self.response.out.write("Finished calculating rankings for: {}".format(district_key))
    def _render(self, district_abbrev, year=None):
        self._set_district(district_abbrev, self.year)

        if self.year < 2009:
            return json.dumps([], ensure_ascii=True)

        events_future = DistrictEventsQuery(District.renderKeyName(self.year, district_abbrev)).fetch_async()
        district_teams_future = DistrictTeamsQuery("{}{}".format(year, district_abbrev)).fetch_async()

        events = events_future.get_result()
        if not events:
            return json.dumps([], ensure_ascii=True)
        EventHelper.sort_events(events)

        team_totals = DistrictHelper.calculate_rankings(events, district_teams_future.get_result(), self.year)

        rankings = []

        current_rank = 1
        for key, points in team_totals:
            point_detail = {}
            point_detail["rank"] = current_rank
            point_detail["team_key"] = key
            point_detail["event_points"] = {}
            for event in points["event_points"]:
                event_key = event[0].key_name
                point_detail["event_points"][event_key] = event[1]
                event_details = Event.get_by_id(event_key)
                point_detail["event_points"][event[0].key_name]['district_cmp'] = True if event_details.event_type_enum == EventType.DISTRICT_CMP else False

            if "rookie_bonus" in points:
                point_detail["rookie_bonus"] = points["rookie_bonus"]
            else:
                point_detail["rookie_bonus"] = 0
            point_detail["point_total"] = points["point_total"]
            rankings.append(point_detail)
            current_rank += 1

        return json.dumps(rankings)
    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 _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 _render(self, district_abbrev, year=None, explicit_year=False):
        district = DistrictQuery('{}{}'.format(year, district_abbrev)).fetch()
        if not district:
            self.abort(404)

        events_future = DistrictEventsQuery(district.key_name).fetch_async()

        # needed for district teams
        district_teams_future = DistrictTeamsQuery(district.key_name).fetch_async()

        # needed for valid_years
        history_future = DistrictHistoryQuery(district.abbreviation).fetch_async()

        # needed for valid_districts
        districts_in_year_future = DistrictsInYearQuery(district.year).fetch_async()

        # needed for active team statuses
        live_events = []
        if year == datetime.datetime.now().year:  # Only show active teams for current year
            live_events = EventHelper.getWeekEvents()
        live_eventteams_futures = []
        for event in live_events:
            live_eventteams_futures.append(EventTeamsQuery(event.key_name).fetch_async())

        events = events_future.get_result()
        EventHelper.sort_events(events)
        events_by_key = {}
        for event in events:
            events_by_key[event.key.id()] = event
        week_events = EventHelper.groupByWeek(events)

        valid_districts = set()
        districts_in_year = districts_in_year_future.get_result()
        for dist in districts_in_year:
            valid_districts.add((dist.display_name, dist.abbreviation))
        valid_districts = sorted(valid_districts, key=lambda (name, _): name)

        teams = TeamHelper.sortTeams(district_teams_future.get_result())
        team_keys = set([t.key.id() for t in teams])

        num_teams = len(teams)
        middle_value = num_teams / 2
        if num_teams % 2 != 0:
            middle_value += 1
        teams_a, teams_b = teams[:middle_value], teams[middle_value:]

        # Currently Competing Team Status
        event_team_keys = []
        for event, teams_future in zip(live_events, live_eventteams_futures):
            for team in teams_future.get_result():
                if team.key.id() in team_keys:
                    event_team_keys.append(ndb.Key(EventTeam, '{}_{}'.format(event.key.id(), team.key.id())))  # Should be in context cache

        ndb.get_multi(event_team_keys)  # Warms context cache
        live_events_with_teams = []
        for event, teams_future in zip(live_events, live_eventteams_futures):
            teams_and_statuses = []
            has_teams = False
            for team in teams_future.get_result():
                if team.key.id() in team_keys:
                    has_teams = True
                    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
                    ))
            if has_teams:
                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]))

        # Get valid years
        district_history = history_future.get_result()
        valid_years = map(lambda d: d.year, district_history)
        valid_years = sorted(valid_years)

        self.template_values.update({
            'explicit_year': explicit_year,
            'year': year,
            'valid_years': valid_years,
            'valid_districts': valid_districts,
            'district_name': district.display_name,
            'district_abbrev': district_abbrev,
            'week_events': week_events,
            'events_by_key': events_by_key,
            'rankings': district.rankings,
            'advancement': district.advancement,
            'teams_a': teams_a,
            'teams_b': teams_b,
            'live_events_with_teams': live_events_with_teams,
        })

        return jinja2_engine.render('district_details.html', 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))
Exemple #26
0
    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)

        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))
Exemple #27
0
    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
        favorites = Favorite.query(ancestor=user).fetch()
        subscriptions = Subscription.query(ancestor=user).fetch()

        team_keys = set()
        team_fav = {}
        team_subs = {}
        event_keys = set()
        event_fav = {}
        event_subs = {}
        events = []
        match_keys = set()
        match_event_keys = set()
        match_fav = {}
        match_subs = {}
        for item in favorites + subscriptions:
            if item.model_type == ModelType.TEAM:
                team_keys.add(ndb.Key(Team, item.model_key))
                if type(item) == Favorite:
                    team_fav[item.model_key] = item
                elif type(item) == Subscription:
                    team_subs[item.model_key] = item
            elif item.model_type == ModelType.MATCH:
                match_keys.add(ndb.Key(Match, item.model_key))
                match_event_keys.add(ndb.Key(Event, item.model_key.split('_')[0]))
                if type(item) == Favorite:
                    match_fav[item.model_key] = item
                elif type(item) == Subscription:
                    match_subs[item.model_key] = item
            elif item.model_type == ModelType.EVENT:
                if item.model_key.endswith('*'):  # All year events wildcard
                    event_year = int(item.model_key[:-1])
                    events.append(Event(  # add fake event for rendering
                        id=item.model_key,
                        short_name='ALL EVENTS',
                        event_short=item.model_key,
                        year=event_year,
                        start_date=datetime.datetime(event_year, 1, 1),
                        end_date=datetime.datetime(event_year, 1, 1)
                    ))
                else:
                    event_keys.add(ndb.Key(Event, item.model_key))
                if type(item) == Favorite:
                    event_fav[item.model_key] = item
                elif type(item) == Subscription:
                    event_subs[item.model_key] = item

        team_futures = ndb.get_multi_async(team_keys)
        event_futures = ndb.get_multi_async(event_keys)
        match_futures = ndb.get_multi_async(match_keys)
        match_event_futures = ndb.get_multi_async(match_event_keys)

        teams = sorted([team_future.get_result() for team_future in team_futures], key=lambda x: x.team_number)
        team_fav_subs = []
        for team in teams:
            fav = team_fav.get(team.key.id(), None)
            subs = team_subs.get(team.key.id(), None)
            team_fav_subs.append((team, fav, subs))

        events += [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        event_fav_subs = []
        for event in events:
            fav = event_fav.get(event.key.id(), None)
            subs = event_subs.get(event.key.id(), None)
            event_fav_subs.append((event, fav, subs))

        matches = [match_future.get_result() for match_future in match_futures]
        match_events = [match_event_future.get_result() for match_event_future in match_event_futures]
        MatchHelper.natural_sort_matches(matches)

        match_fav_subs_by_event = {}
        for event in match_events:
            match_fav_subs_by_event[event.key.id()] = (event, [])

        for match in matches:
            event_key = match.key.id().split('_')[0]
            fav = match_fav.get(match.key.id(), None)
            subs = match_subs.get(match.key.id(), None)
            match_fav_subs_by_event[event_key][1].append((match, fav, subs))

        event_match_fav_subs = sorted(match_fav_subs_by_event.values(), key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0]))
        event_match_fav_subs = sorted(event_match_fav_subs, key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0]))

        self.template_values['team_fav_subs'] = team_fav_subs
        self.template_values['event_fav_subs'] = event_fav_subs
        self.template_values['event_match_fav_subs'] = event_match_fav_subs
        self.template_values['status'] = self.request.get('status')
        self.template_values['year'] = datetime.datetime.now().year

        self.response.out.write(jinja2_engine.render('mytba.html', self.template_values))
    def _render(self, district_abbrev, year=None, explicit_year=False):
        district = DistrictQuery('{}{}'.format(year, district_abbrev)).fetch()
        if not district:
            self.abort(404)

        events_future = DistrictEventsQuery(district.key_name).fetch_async()

        # needed for district teams
        district_teams_future = DistrictTeamsQuery(
            district.key_name).fetch_async()

        # needed for valid_years
        history_future = DistrictHistoryQuery(
            district.abbreviation).fetch_async()

        # needed for valid_districts
        districts_in_year_future = DistrictsInYearQuery(
            district.year).fetch_async()

        # needed for active team statuses
        live_events = []
        if year == datetime.datetime.now(
        ).year:  # Only show active teams for current year
            live_events = EventHelper.getWeekEvents()
        live_eventteams_futures = []
        for event in live_events:
            live_eventteams_futures.append(
                EventTeamsQuery(event.key_name).fetch_async())

        events = events_future.get_result()
        EventHelper.sort_events(events)
        events_by_key = {}
        for event in events:
            events_by_key[event.key.id()] = event
        week_events = EventHelper.groupByWeek(events)

        valid_districts = set()
        districts_in_year = districts_in_year_future.get_result()
        for dist in districts_in_year:
            valid_districts.add((dist.display_name, dist.abbreviation))
        valid_districts = sorted(valid_districts, key=lambda (name, _): name)

        teams = TeamHelper.sortTeams(district_teams_future.get_result())
        team_keys = set([t.key.id() for t in teams])

        num_teams = len(teams)
        middle_value = num_teams / 2
        if num_teams % 2 != 0:
            middle_value += 1
        teams_a, teams_b = teams[:middle_value], teams[middle_value:]

        # Currently Competing Team Status
        event_team_keys = []
        for event, teams_future in zip(live_events, live_eventteams_futures):
            for team in teams_future.get_result():
                if team.key.id() in team_keys:
                    event_team_keys.append(
                        ndb.Key(EventTeam, '{}_{}'.format(
                            event.key.id(),
                            team.key.id())))  # Should be in context cache

        ndb.get_multi(event_team_keys)  # Warms context cache
        live_events_with_teams = []
        for event, teams_future in zip(live_events, live_eventteams_futures):
            teams_and_statuses = []
            has_teams = False
            for team in teams_future.get_result():
                if team.key.id() in team_keys:
                    has_teams = True
                    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))
            if has_teams:
                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]))

        # Get valid years
        district_history = history_future.get_result()
        valid_years = map(lambda d: d.year, district_history)
        valid_years = sorted(valid_years)

        self.template_values.update({
            'explicit_year':
            explicit_year,
            'year':
            year,
            'valid_years':
            valid_years,
            'valid_districts':
            valid_districts,
            'district_name':
            district.display_name,
            'district_abbrev':
            district_abbrev,
            'week_events':
            week_events,
            'events_by_key':
            events_by_key,
            'rankings':
            district.rankings,
            'advancement':
            district.advancement,
            'teams_a':
            teams_a,
            'teams_b':
            teams_b,
            'live_events_with_teams':
            live_events_with_teams,
        })

        return jinja2_engine.render('district_details.html',
                                    self.template_values)
Exemple #30
0
    def get(self):
        self._require_registration()

        user = self.user_bundle.account.key
        favorites = Favorite.query(ancestor=user).fetch()
        subscriptions = Subscription.query(ancestor=user).fetch()

        team_keys = set()
        team_fav = {}
        team_subs = {}
        event_keys = set()
        event_fav = {}
        event_subs = {}
        events = []
        match_keys = set()
        match_event_keys = set()
        match_fav = {}
        match_subs = {}
        for item in favorites + subscriptions:
            if item.model_type == ModelType.TEAM:
                team_keys.add(ndb.Key(Team, item.model_key))
                if type(item) == Favorite:
                    team_fav[item.model_key] = item
                elif type(item) == Subscription:
                    team_subs[item.model_key] = item
            elif item.model_type == ModelType.MATCH:
                match_keys.add(ndb.Key(Match, item.model_key))
                match_event_keys.add(
                    ndb.Key(Event,
                            item.model_key.split('_')[0]))
                if type(item) == Favorite:
                    match_fav[item.model_key] = item
                elif type(item) == Subscription:
                    match_subs[item.model_key] = item
            elif item.model_type == ModelType.EVENT:
                if item.model_key.endswith('*'):  # All year events wildcard
                    event_year = int(item.model_key[:-1])
                    events.append(
                        Event(  # add fake event for rendering
                            id=item.model_key,
                            short_name='ALL EVENTS',
                            event_short=item.model_key,
                            year=event_year,
                            start_date=datetime.datetime(event_year, 1, 1),
                            end_date=datetime.datetime(event_year, 1, 1)))
                else:
                    event_keys.add(ndb.Key(Event, item.model_key))
                if type(item) == Favorite:
                    event_fav[item.model_key] = item
                elif type(item) == Subscription:
                    event_subs[item.model_key] = item

        team_futures = ndb.get_multi_async(team_keys)
        event_futures = ndb.get_multi_async(event_keys)
        match_futures = ndb.get_multi_async(match_keys)
        match_event_futures = ndb.get_multi_async(match_event_keys)

        teams = sorted(
            [team_future.get_result() for team_future in team_futures],
            key=lambda x: x.team_number)
        team_fav_subs = []
        for team in teams:
            fav = team_fav.get(team.key.id(), None)
            subs = team_subs.get(team.key.id(), None)
            team_fav_subs.append((team, fav, subs))

        events += [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        event_fav_subs = []
        for event in events:
            fav = event_fav.get(event.key.id(), None)
            subs = event_subs.get(event.key.id(), None)
            event_fav_subs.append((event, fav, subs))

        matches = [match_future.get_result() for match_future in match_futures]
        match_events = [
            match_event_future.get_result()
            for match_event_future in match_event_futures
        ]
        MatchHelper.natural_sort_matches(matches)

        match_fav_subs_by_event = {}
        for event in match_events:
            match_fav_subs_by_event[event.key.id()] = (event, [])

        for match in matches:
            event_key = match.key.id().split('_')[0]
            fav = match_fav.get(match.key.id(), None)
            subs = match_subs.get(match.key.id(), None)
            match_fav_subs_by_event[event_key][1].append((match, fav, subs))

        event_match_fav_subs = sorted(
            match_fav_subs_by_event.values(),
            key=lambda x: EventHelper.distantFutureIfNoStartDate(x[0]))
        event_match_fav_subs = sorted(
            event_match_fav_subs,
            key=lambda x: EventHelper.distantFutureIfNoEndDate(x[0]))

        self.template_values['team_fav_subs'] = team_fav_subs
        self.template_values['event_fav_subs'] = event_fav_subs
        self.template_values['event_match_fav_subs'] = event_match_fav_subs
        self.template_values['status'] = self.request.get('status')
        self.template_values['year'] = datetime.datetime.now().year

        self.response.out.write(
            jinja2_engine.render('mytba.html', self.template_values))
Exemple #31
0
    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 _render(self, district_abbrev, year=None, explicit_year=False):
        district_type = DistrictType.abbrevs[district_abbrev]

        event_keys = Event.query(Event.year == year, Event.event_district_enum == district_type).fetch(None, keys_only=True)
        if not event_keys:
            self.abort(404)

        # needed for district teams
        district_key = '{}{}'.format(year, district_abbrev)
        district_teams_future = DistrictTeamsQuery(district_key).fetch_async()

        # needed for valid_years
        all_cmp_event_keys_future = Event.query(Event.event_district_enum == district_type, Event.event_type_enum == EventType.DISTRICT_CMP).fetch_async(None, keys_only=True)

        # needed for valid_districts
        district_cmp_keys_future = Event.query(Event.year == year, Event.event_type_enum == EventType.DISTRICT_CMP).fetch_async(None, keys_only=True)  # to compute valid_districts

        # Needed for active team statuses
        live_events = EventHelper.getWeekEvents()
        live_eventteams_futures = []
        for event in live_events:
            live_eventteams_futures.append(EventTeamsQuery(event.key_name).fetch_async())

        event_futures = ndb.get_multi_async(event_keys)
        event_team_keys_future = EventTeam.query(EventTeam.event.IN(event_keys)).fetch_async(None, keys_only=True)
        team_futures = ndb.get_multi_async(set([ndb.Key(Team, et_key.id().split('_')[1]) for et_key in event_team_keys_future.get_result()]))

        events = [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        district_cmp_futures = ndb.get_multi_async(district_cmp_keys_future.get_result())

        team_totals = DistrictHelper.calculate_rankings(events, team_futures, year)

        valid_districts = set()
        for district_cmp_future in district_cmp_futures:
            district_cmp = district_cmp_future.get_result()
            cmp_dis_type = district_cmp.event_district_enum
            if cmp_dis_type is None:
                logging.warning("District event {} has unknown district type!".format(district_cmp.key.id()))
            else:
                valid_districts.add((DistrictType.type_names[cmp_dis_type], DistrictType.type_abbrevs[cmp_dis_type]))
        valid_districts = sorted(valid_districts, key=lambda (name, _): name)

        teams = TeamHelper.sortTeams(district_teams_future.get_result())

        num_teams = len(teams)
        middle_value = num_teams / 2
        if num_teams % 2 != 0:
            middle_value += 1
        teams_a, teams_b = teams[:middle_value], teams[middle_value:]

        # Currently Competing Team Status
        live_events_with_teams = EventTeamStatusHelper.buildEventTeamStatus(live_events, live_eventteams_futures, teams)
        live_events_with_teams.sort(key=lambda x: x[0].name)

        self.template_values.update({
            'explicit_year': explicit_year,
            'year': year,
            'valid_years': sorted(set([int(event_key.id()[:4]) for event_key in all_cmp_event_keys_future.get_result()])),
            'valid_districts': valid_districts,
            'district_name': DistrictType.type_names[district_type],
            'district_abbrev': district_abbrev,
            'events': events,
            'team_totals': team_totals,
            'teams_a': teams_a,
            'teams_b': teams_b,
            'live_events_with_teams': live_events_with_teams,
        })

        path = os.path.join(os.path.dirname(__file__), '../templates/district_details.html')
        return template.render(path, self.template_values)
    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))
Exemple #34
0
    def _render(self, district_abbrev, year=None, explicit_year=False):
        district = DistrictQuery('{}{}'.format(year, district_abbrev)).fetch()
        if not district:
            self.abort(404)

        events_future = DistrictEventsQuery(district.key_name).fetch_async()

        # needed for district teams
        district_teams_future = DistrictTeamsQuery(district.key_name).fetch_async()

        # needed for valid_years
        history_future = DistrictHistoryQuery(district.abbreviation).fetch_async()

        # needed for valid_districts
        districts_in_year_future = DistrictsInYearQuery(district.year).fetch_async()

        # Temp disabled on 2017-02-18 -fangeugene
        # # Needed for active team statuses
        # live_events = []
        # if year == datetime.datetime.now().year:  # Only show active teams for current year
        #     live_events = EventHelper.getWeekEvents()
        # live_eventteams_futures = []
        # for event in live_events:
        #     live_eventteams_futures.append(EventTeamsQuery(event.key_name).fetch_async())

        events = events_future.get_result()
        EventHelper.sort_events(events)
        events_by_key = {}
        for event in events:
            events_by_key[event.key.id()] = event
        week_events = EventHelper.groupByWeek(events)

        valid_districts = set()
        districts_in_year = districts_in_year_future.get_result()
        for dist in districts_in_year:
            valid_districts.add((dist.display_name, dist.abbreviation))
        valid_districts = sorted(valid_districts, key=lambda (name, _): name)

        teams = TeamHelper.sortTeams(district_teams_future.get_result())

        num_teams = len(teams)
        middle_value = num_teams / 2
        if num_teams % 2 != 0:
            middle_value += 1
        teams_a, teams_b = teams[:middle_value], teams[middle_value:]

        # Temp disabled on 2017-02-18 -fangeugene
        # # Currently Competing Team Status
        # live_events_with_teams = EventTeamStatusHelper.buildEventTeamStatus(live_events, live_eventteams_futures, teams)
        # live_events_with_teams.sort(key=lambda x: x[0].name)

        # Get valid years
        district_history = history_future.get_result()
        valid_years = map(lambda d: d.year, district_history)
        valid_years = sorted(valid_years)

        self.template_values.update({
            'explicit_year': explicit_year,
            'year': year,
            'valid_years': valid_years,
            'valid_districts': valid_districts,
            'district_name': district.display_name,
            'district_abbrev': district_abbrev,
            'week_events': week_events,
            'events_by_key': events_by_key,
            'rankings': district.rankings,
            'teams_a': teams_a,
            'teams_b': teams_b,
            # 'live_events_with_teams': live_events_with_teams,  # Temp disabled on 2017-02-18 -fangeugene
        })

        return jinja2_engine.render('district_details.html', 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 get(self):
        self._require_login('/account/register')
        self._require_registration('/account/register')

        user = self.user_bundle.account.key
        favorites = Favorite.query(ancestor=user).fetch()
        subscriptions = Subscription.query(ancestor=user).fetch()

        team_keys = set()
        team_fav = {}
        team_subs = {}
        event_keys = set()
        event_fav = {}
        event_subs = {}
        events = []
        for item in favorites + subscriptions:
            if item.model_type == ModelType.TEAM:
                team_keys.add(ndb.Key(Team, item.model_key))
                if type(item) == Favorite:
                    team_fav[item.model_key] = item
                elif type(item) == Subscription:
                    team_subs[item.model_key] = item
            elif item.model_type == ModelType.EVENT:
                if item.model_key.endswith('*'):  # All year events wildcard
                    event_year = int(item.model_key[:-1])
                    events.append(
                        Event(  # add fake event for rendering
                            id=item.model_key,
                            short_name='ALL EVENTS',
                            event_short=item.model_key,
                            year=event_year,
                            start_date=datetime.datetime(event_year, 1, 1),
                            end_date=datetime.datetime(event_year, 1, 1)))
                else:
                    event_keys.add(ndb.Key(Event, item.model_key))
                if type(item) == Favorite:
                    event_fav[item.model_key] = item
                elif type(item) == Subscription:
                    event_subs[item.model_key] = item

        team_futures = ndb.get_multi_async(team_keys)
        event_futures = ndb.get_multi_async(event_keys)

        teams = sorted(
            [team_future.get_result() for team_future in team_futures],
            key=lambda x: x.team_number)
        team_fav_subs = []
        for team in teams:
            fav = team_fav.get(team.key.id(), None)
            subs = team_subs.get(team.key.id(), None)
            team_fav_subs.append((team, fav, subs))

        events += [event_future.get_result() for event_future in event_futures]
        EventHelper.sort_events(events)

        event_fav_subs = []
        for event in events:
            fav = event_fav.get(event.key.id(), None)
            subs = event_subs.get(event.key.id(), None)
            event_fav_subs.append((event, fav, subs))

        self.template_values['team_fav_subs'] = team_fav_subs
        self.template_values['event_fav_subs'] = event_fav_subs
        self.template_values['status'] = self.request.get('status')
        self.template_values['year'] = datetime.datetime.now().year

        self.response.out.write(
            jinja2_engine.render('mytba.html', self.template_values))