def _render(self, team_number):
        self.response.headers['content-type'] = 'text/plain; charset="utf-8"'
        user = self.request.get('user')
        if user:
            user_str = '@{}, '.format(user)
        else:
            user_str = ''

        team_event_or_error = validate_team(user_str, team_number)
        if type(team_event_or_error) == str:
            return team_event_or_error

        _, event = team_event_or_error
        event_code_upper = event.event_short.upper()

        matches_future = TeamEventMatchesQuery('frc{}'.format(team_number), event.key.id()).fetch_async()
        matches = MatchHelper.play_order_sort_matches(matches_future.get_result())

        # No match schedule yet
        if not matches:
            return "{}[{}] Team {} has no scheduled matches yet.".format(user_str, event_code_upper, team_number)

        next_match = None
        for match in matches:
            if not match.has_been_played:
                next_match = match
                break

        if next_match is None:
            return "{}[{}] Team {} has no more scheduled matches.".format(user_str, event_code_upper, team_number)

        return "{}[{}] Team {} will be playing in match {}.".format(user_str, event_code_upper, team_number, match.short_name)
Exemplo n.º 2
0
    def _render(self, team_number, tz_str=None):
        import pytz
        from pytz.exceptions import UnknownTimeZoneError

        user = self.request.get('user')
        if user:
            user_str = '@{}, '.format(user)
        else:
            user_str = ''

        try:
            arg_tz = pytz.timezone(tz_str) if tz_str else None
        except UnknownTimeZoneError:
            arg_tz = None

        team_event_or_error = validate_team(user_str, team_number)
        if type(team_event_or_error) == str:
            return team_event_or_error

        _, event = team_event_or_error
        event_code_upper = event.event_short.upper()

        matches_future = TeamEventMatchesQuery('frc{}'.format(team_number),
                                               event.key.id()).fetch_async()
        matches = MatchHelper.play_order_sort_matches(
            matches_future.get_result())

        # No match schedule yet
        if not matches:
            return "{}[{}] Team {} has no scheduled matches yet.".format(
                user_str, event_code_upper, team_number)

        next_match = None
        for match in matches:
            if not match.has_been_played:
                next_match = match
                break

        if next_match is None:
            return "{}[{}] Team {} has no more scheduled matches.".format(
                user_str, event_code_upper, team_number)

        predicted_str = "predicted" if next_match.predicted_time else "scheduled"
        match_time = next_match.predicted_time if next_match.predicted_time else next_match.time
        timezone = arg_tz if arg_tz else pytz.timezone(event.timezone_id)
        predicted_time_local = pytz.utc.localize(match_time).astimezone(
            timezone) if timezone else match_time
        time_string = ", {} to start at {}".format(
            predicted_str,
            predicted_time_local.strftime("%a %H:%M %Z")) if match_time else ""
        return "{}[{}] Team {} will be playing in match {}{}".format(
            user_str, event_code_upper, team_number, next_match.short_name,
            time_string)
    def test_match_updated(self):
        affected_refs = {
            'key':
            {ndb.Key(Match, '2015casj_qm1'),
             ndb.Key(Match, '2015casj_qm2')},
            'event': {ndb.Key(Event, '2015casj'),
                      ndb.Key(Event, '2015cama')},
            'team_keys': {ndb.Key(Team, 'frc254'),
                          ndb.Key(Team, 'frc604')},
            'year': {2014, 2015},
        }
        cache_keys = [
            q.cache_key
            for q in get_affected_queries.match_updated(affected_refs)
        ]

        self.assertEqual(len(cache_keys), 16)
        self.assertTrue(MatchQuery('2015casj_qm1').cache_key in cache_keys)
        self.assertTrue(MatchQuery('2015casj_qm2').cache_key in cache_keys)
        self.assertTrue(
            MatchGdcvDataQuery('2015casj_qm1').cache_key in cache_keys)
        self.assertTrue(
            MatchGdcvDataQuery('2015casj_qm2').cache_key in cache_keys)
        self.assertTrue(EventMatchesQuery('2015casj').cache_key in cache_keys)
        self.assertTrue(EventMatchesQuery('2015cama').cache_key in cache_keys)
        self.assertTrue(
            EventMatchesGdcvDataQuery('2015casj').cache_key in cache_keys)
        self.assertTrue(
            EventMatchesGdcvDataQuery('2015cama').cache_key in cache_keys)
        self.assertTrue(
            TeamEventMatchesQuery('frc254', '2015casj').cache_key in
            cache_keys)
        self.assertTrue(
            TeamEventMatchesQuery('frc254', '2015cama').cache_key in
            cache_keys)
        self.assertTrue(
            TeamEventMatchesQuery('frc604', '2015casj').cache_key in
            cache_keys)
        self.assertTrue(
            TeamEventMatchesQuery('frc604', '2015cama').cache_key in
            cache_keys)
        self.assertTrue(
            TeamYearMatchesQuery('frc254', 2014).cache_key in cache_keys)
        self.assertTrue(
            TeamYearMatchesQuery('frc254', 2015).cache_key in cache_keys)
        self.assertTrue(
            TeamYearMatchesQuery('frc604', 2014).cache_key in cache_keys)
        self.assertTrue(
            TeamYearMatchesQuery('frc604', 2015).cache_key in cache_keys)
Exemplo n.º 4
0
    def _render(self, team_key, event_key, model_type=None):
        matches, self._last_modified = TeamEventMatchesQuery(
            team_key, event_key).fetch(dict_version=3, return_updated=True)
        if model_type is not None:
            matches = filter_match_properties(matches, model_type)

        return json.dumps(matches, ensure_ascii=True, indent=2, sort_keys=True)
Exemplo n.º 5
0
    def _render(self, team_number, tz_str=None):
        import pytz
        from pytz.exceptions import UnknownTimeZoneError

        user = self.request.get('user')
        if user:
            user_str = '@{}, '.format(user)
        else:
            user_str = ''

        try:
            arg_tz = pytz.timezone(tz_str) if tz_str else None
        except UnknownTimeZoneError:
            arg_tz = None

        team_event_or_error = validate_team(user_str, team_number)
        if type(team_event_or_error) == str:
            return team_event_or_error

        _, event = team_event_or_error
        event_code_upper = event.event_short.upper()

        matches_future = TeamEventMatchesQuery('frc{}'.format(team_number), event.key.id()).fetch_async()
        matches = MatchHelper.play_order_sort_matches(matches_future.get_result())

        # No match schedule yet
        if not matches:
            return "{}[{}] Team {} has no scheduled matches yet.".format(user_str, event_code_upper, team_number)

        next_match = None
        for match in matches:
            if not match.has_been_played:
                next_match = match
                break

        if next_match is None:
            return "{}[{}] Team {} has no more scheduled matches.".format(user_str, event_code_upper, team_number)

        predicted_str = "predicted" if next_match.predicted_time else "scheduled"
        match_time = next_match.predicted_time if next_match.predicted_time else next_match.time
        timezone = arg_tz if arg_tz else pytz.timezone(event.timezone_id)
        predicted_time_local = pytz.utc.localize(match_time).astimezone(timezone) if timezone else match_time
        time_string = ", {} to start at {}".format(predicted_str, predicted_time_local.strftime("%a %H:%M %Z")) if match_time else ""
        return "{}[{}] Team {} will be playing in match {}{}".format(user_str, event_code_upper, team_number, next_match.short_name, time_string)
Exemplo n.º 6
0
    def generateTeamAtEventStatus(cls, team_key, event):
        """
        Generate Team@Event status items
        :return: a tuple <long summary string, qual record, qual ranking, playoff status>
        """
        team_number = team_key[3:]
        matches_future = TeamEventMatchesQuery(team_key, event.key.id()).fetch_async()
        matches = MatchHelper.organizeMatches(matches_future.get_result())

        # Compute alliances
        alliance_number = cls._get_alliance_number(team_key, event)

        # Playoff Status
        status, short_playoff_status = cls._get_playoff_status(team_key, matches, alliance_number)

        # Still in quals or team did not make it to elims
        # Compute qual W-L-T
        wins, losses, ties, unplayed_qual = cls._get_qual_wlt(team_key, matches)
        if wins == 0 and losses == 0 and ties == 0:
            # No matches played yet
            status = "Team {} has not played any matches yet.".format(team_number) if not status else status

        # Compute rank & num_teams
        # Gets record from ranking data to account for surrogate matches
        rank, ranking_points, record, num_teams = cls._get_rank(team_number, event)
        rank_str = "Rank {} with {} RP".format(rank, ranking_points)

        # Compute final long status for nightbot, if one isn't already there
        if unplayed_qual > 0 and not status:
            if rank is not None:
                status = "Team {} is currently rank {}/{} with a record of {} and {} ranking points.".format(team_number, rank, num_teams, record, ranking_points)
            else:
                status = "Team {} currently has a record of {}.".format(team_number, record)
        elif not status:
            if alliance_number is None:
                status = "Team {} ended qualification matches at rank {}/{} with a record of {}.".format(team_number, rank, num_teams, record)
            elif alliance_number == 0:
                status = "Team {} ended qualification matches at rank {}/{} with a record of {} and was not picked for playoff matches.".format(team_number, rank, num_teams, record)
            else:
                status = "Team {} will be competing in the playoff matches on alliance #{}.".format(team_number, alliance_number)

        return status, record, rank_str, short_playoff_status
Exemplo n.º 7
0
def match_updated(affected_refs):
    event_keys = filter(None, affected_refs['event'])
    team_keys = filter(None, affected_refs['team_keys'])
    years = filter(None, affected_refs['year'])

    queries_and_keys = []
    for event_key in event_keys:
        queries_and_keys.append((EventMatchesQuery(event_key.id())))
        for team_key in team_keys:
            queries_and_keys.append((TeamEventMatchesQuery(team_key.id(), event_key.id())))

    for team_key in team_keys:
        for year in years:
            queries_and_keys.append((TeamYearMatchesQuery(team_key.id(), year)))

    return queries_and_keys
def match_updated(affected_refs):
    match_keys = _filter(affected_refs['key'])
    event_keys = _filter(affected_refs['event'])
    team_keys = _filter(affected_refs['team_keys'])
    years = _filter(affected_refs['year'])

    queries_and_keys = []
    for match_key in match_keys:
        queries_and_keys.append((MatchQuery(match_key.id())))
        queries_and_keys.append((MatchGdcvDataQuery(match_key.id())))

    for event_key in event_keys:
        queries_and_keys.append((EventMatchesQuery(event_key.id())))
        queries_and_keys.append((EventMatchesGdcvDataQuery(event_key.id())))
        for team_key in team_keys:
            queries_and_keys.append(
                (TeamEventMatchesQuery(team_key.id(), event_key.id())))

    for team_key in team_keys:
        for year in years:
            queries_and_keys.append((TeamYearMatchesQuery(team_key.id(),
                                                          year)))

    return queries_and_keys
    def _render(self, team_number):
        self.response.headers['content-type'] = 'text/plain; charset="utf-8"'

        team_event_or_error = validate_team(team_number)
        if type(team_event_or_error) == str:
            return team_event_or_error

        _, event = team_event_or_error
        event_code_upper = event.event_short.upper()

        team_key = 'frc{}'.format(team_number)
        matches_future = TeamEventMatchesQuery(team_key, event.key.id()).fetch_async()
        matches = MatchHelper.organizeMatches(matches_future.get_result())

        # Compute alliances
        alliance_number = None
        if event.alliance_selections:
            for i, alliance in enumerate(event.alliance_selections):
                if team_key in alliance['picks']:
                    alliance_number = i + 1
                    break
            else:
                alliance_number = 0  # Team didn't make it to elims

        level_map = {
            'qf': 'quarters',
            'sf': 'semis',
            'f': 'the finals',
        }
        for comp_level in ['f', 'sf', 'qf']:  # playoffs
            level_str = level_map[comp_level]
            if matches[comp_level]:
                wins = 0
                losses = 0
                for match in matches[comp_level]:
                    if match.has_been_played:
                        if team_key in match.alliances[match.winning_alliance]['teams']:
                            wins += 1
                        else:
                            losses += 1
                if wins == 2:
                    if comp_level == 'f':
                        return "[{}]: Team {} won the event on alliance #{}.".format(event_code_upper, team_number, alliance_number)
                    else:
                        return "[{}]: Team {} won {} on alliance #{}.".format(event_code_upper, team_number, level_str, alliance_number)
                elif losses == 2:
                    return "[{}]: Team {} got knocked out in {} on alliance #{}.".format(event_code_upper, team_number, level_str, alliance_number)
                else:
                    return "[{}]: Team {} is currently {}-{} in {} on alliance #{}.".format(event_code_upper, team_number, wins, losses, level_str, alliance_number)

        # Still in quals or team did not make it to elims
        # Compute qual W-L-T
        wins = 0
        losses = 0
        ties = 0
        unplayed_qual = 0
        for match in matches['qm']:
            if match.has_been_played:
                if match.winning_alliance == '':
                    ties += 1
                elif team_key in match.alliances[match.winning_alliance]['teams']:
                    wins += 1
                else:
                    losses += 1
            else:
                unplayed_qual += 1

        # Compute rank & num_teams
        rank = None
        if event.rankings:
            num_teams = len(event.rankings) - 1
            for i, row in enumerate(event.rankings):
                if row[1] == team_number:
                    rank = i

        if unplayed_qual > 0:
            if rank is not None:
                return "[{}]: Team {} is currently rank {}/{} with a record of {}-{}-{}.".format(event_code_upper, team_number, rank, num_teams, wins, losses, ties)
            else:
                return "[{}]: Team {} currently has a record of {}-{}-{} at [{}].".format(event_code_upper, team_number, wins, losses, ties)
        else:
            if alliance_number is None:
                return "[{}]: Team {} ended qualification matches at rank {}/{} with a record of {}-{}-{}.".format(event_code_upper, team_number, rank, num_teams, wins, losses, ties)
            elif alliance_number == 0:
                return "[{}]: Team {} ended qualification matches at rank {}/{} with a record of {}-{}-{} and was not picked for playoff matches.".format(event_code_upper, team_number, rank, num_teams, wins, losses, ties)
            else:
                return "[{}]: Team {} will be competing in the playoff matches on alliance #{}.".format(event_code_upper, team_number, alliance_number)
    def _render(self, team_number):
        self.response.headers['content-type'] = 'text/plain; charset="utf-8"'
        user = self.request.get('user')
        if user:
            user_str = '@{}, '.format(user)
        else:
            user_str = ''

        team_event_or_error = validate_team(user_str, team_number)
        if type(team_event_or_error) == str:
            return team_event_or_error

        _, event = team_event_or_error
        event_code_upper = event.event_short.upper()

        team_key = 'frc{}'.format(team_number)
        matches_future = TeamEventMatchesQuery(team_key, event.key.id()).fetch_async()
        matches = MatchHelper.organizeMatches(matches_future.get_result())

        # Compute alliances
        alliance_number = None
        if event.alliance_selections:
            for i, alliance in enumerate(event.alliance_selections):
                if team_key in alliance['picks']:
                    alliance_number = i + 1
                    break
            else:
                alliance_number = 0  # Team didn't make it to elims

        level_map = {
            'qf': 'quarters',
            'sf': 'semis',
            'f': 'the finals',
        }
        for comp_level in ['f', 'sf', 'qf']:  # playoffs
            level_str = level_map[comp_level]
            if matches[comp_level]:
                wins = 0
                losses = 0
                for match in matches[comp_level]:
                    if match.has_been_played:
                        if team_key in match.alliances[match.winning_alliance]['teams']:
                            wins += 1
                        else:
                            losses += 1
                if wins == 2:
                    if comp_level == 'f':
                        return "{}[{}] Team {} won the event on alliance #{}.".format(user_str, event_code_upper, team_number, alliance_number)
                    else:
                        return "{}[{}] Team {} won {} on alliance #{}.".format(user_str, event_code_upper, team_number, level_str, alliance_number)
                elif losses == 2:
                    return "{}[{}] Team {} got knocked out in {} on alliance #{}.".format(user_str, event_code_upper, team_number, level_str, alliance_number)
                else:
                    return "{}[{}] Team {} is currently {}-{} in {} on alliance #{}.".format(user_str, event_code_upper, team_number, wins, losses, level_str, alliance_number)

        # Still in quals or team did not make it to elims
        # Compute qual W-L-T
        wins = 0
        losses = 0
        ties = 0
        unplayed_qual = 0
        for match in matches['qm']:
            if match.has_been_played:
                if match.winning_alliance == '':
                    ties += 1
                elif team_key in match.alliances[match.winning_alliance]['teams']:
                    wins += 1
                else:
                    losses += 1
            else:
                unplayed_qual += 1

        if wins == 0 and losses == 0 and ties == 0:
            # No matches played yet
            return "{}[{}] Team {} has not played any matches yet.".format(user_str, event_code_upper, team_number)

        # Compute rank & num_teams
        rank = None
        ranking_points = None
        if event.rankings:
            num_teams = len(event.rankings) - 1
            for i, row in enumerate(event.rankings):
                if row[1] == team_number:
                    rank = i
                    ranking_points = int(float(row[2]))
                    break

        if unplayed_qual > 0:
            if rank is not None:
                return "{}[{}] Team {} is currently rank {}/{} with a record of {}-{}-{} and {} ranking points.".format(user_str, event_code_upper, team_number, rank, num_teams, wins, losses, ties, ranking_points)
            else:
                return "{}[{}] Team {} currently has a record of {}-{}-{}.".format(user_str, event_code_upper, team_number, wins, losses, ties)
        else:
            if alliance_number is None:
                return "{}[{}] Team {} ended qualification matches at rank {}/{} with a record of {}-{}-{}.".format(user_str, event_code_upper, team_number, rank, num_teams, wins, losses, ties)
            elif alliance_number == 0:
                return "{}[{}] Team {} ended qualification matches at rank {}/{} with a record of {}-{}-{} and was not picked for playoff matches.".format(user_str, event_code_upper, team_number, rank, num_teams, wins, losses, ties)
            else:
                return "{}[{}] Team {} will be competing in the playoff matches on alliance #{}.".format(user_str, event_code_upper, team_number, alliance_number)
Exemplo n.º 11
0
    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,
        }
Exemplo n.º 12
0
    def _render(self, team_key, event_key):
        matches = TeamEventMatchesQuery(self.team_key, self.event_key).fetch()

        matches = [ModelToDict.matchConverter(match) for match in matches]

        return json.dumps(matches, ensure_ascii=True)