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)
예제 #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)
예제 #3
0
    def get(self, event_key):
        event = Event.get_by_id(event_key)
        matchstats_dict = MatchstatsHelper.calculate_matchstats(
            event.matches, event.year)
        if any([v != {} for v in matchstats_dict.values()]):
            pass
        else:
            logging.warn(
                "Matchstat calculation for {} failed!".format(event_key))
            matchstats_dict = None

        predictions_dict = None
        if event.year in {
                2016, 2017, 2018, 2019, 2020
        } and event.event_type_enum in EventType.SEASON_EVENT_TYPES or event.enable_predictions:
            sorted_matches = MatchHelper.play_order_sort_matches(event.matches)
            match_predictions, match_prediction_stats, stat_mean_vars = PredictionHelper.get_match_predictions(
                sorted_matches)
            ranking_predictions, ranking_prediction_stats = PredictionHelper.get_ranking_predictions(
                sorted_matches, match_predictions)

            predictions_dict = {
                'match_predictions': match_predictions,
                'match_prediction_stats': match_prediction_stats,
                'stat_mean_vars': stat_mean_vars,
                'ranking_predictions': ranking_predictions,
                'ranking_prediction_stats': ranking_prediction_stats
            }

        event_insights = EventInsightsHelper.calculate_event_insights(
            event.matches, event.year)

        event_details = EventDetails(
            id=event_key,
            matchstats=matchstats_dict,
            predictions=predictions_dict,
            insights=event_insights,
        )
        EventDetailsManipulator.createOrUpdate(event_details)

        template_values = {
            'matchstats_dict': matchstats_dict,
        }

        if 'X-Appengine-Taskname' not in self.request.headers:  # Only write out if not in taskqueue
            path = os.path.join(os.path.dirname(__file__),
                                '../templates/math/event_matchstats_do.html')
            self.response.out.write(template.render(path, template_values))
예제 #4
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)
예제 #5
0
    def get(self, event_key):
        event = Event.get_by_id(event_key)
        matchstats_dict = MatchstatsHelper.calculate_matchstats(event.matches, event.year)
        if any([v != {} for v in matchstats_dict.values()]):
            pass
        else:
            logging.warn("Matchstat calculation for {} failed!".format(event_key))
            matchstats_dict = None

        predictions_dict = None
        if event.year in {2016, 2017, 2018} and event.event_type_enum in EventType.SEASON_EVENT_TYPES or event.enable_predictions:
            sorted_matches = MatchHelper.play_order_sort_matches(event.matches)
            match_predictions, match_prediction_stats, stat_mean_vars = PredictionHelper.get_match_predictions(sorted_matches)
            ranking_predictions, ranking_prediction_stats = PredictionHelper.get_ranking_predictions(sorted_matches, match_predictions)

            predictions_dict = {
                'match_predictions': match_predictions,
                'match_prediction_stats': match_prediction_stats,
                'stat_mean_vars': stat_mean_vars,
                'ranking_predictions': ranking_predictions,
                'ranking_prediction_stats': ranking_prediction_stats
            }

        event_insights = EventInsightsHelper.calculate_event_insights(event.matches, event.year)

        event_details = EventDetails(
            id=event_key,
            matchstats=matchstats_dict,
            predictions=predictions_dict,
            insights=event_insights,
        )
        EventDetailsManipulator.createOrUpdate(event_details)

        template_values = {
            'matchstats_dict': matchstats_dict,
        }

        if 'X-Appengine-Taskname' not in self.request.headers:  # Only write out if not in taskqueue
            path = os.path.join(os.path.dirname(__file__), '../templates/math/event_matchstats_do.html')
            self.response.out.write(template.render(path, template_values))
    def test_event_smulator_batch_advance(self):
        es = EventSimulator(batch_advance=True)

        # Before anything has happened
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details, None)
        self.assertEqual(event.matches, [])

        # Qual match schedule added
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertNotEqual(event.details, None)
        for rank in event.details.rankings2:
            self.assertEqual(rank['sort_orders'][0], 0)

        self.assertEqual(len(event.matches), 72)
        for match in event.matches:
            self.assertEqual(match.comp_level, 'qm')
            self.assertFalse(match.has_been_played)
            self.assertEqual(match.actual_time, None)

        # After each qual match
        for i in xrange(72):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)
            self.assertEqual(event.details.alliance_selections, None)
            self.assertEqual(len(event.matches), 72)

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)

        # Check some final rankings
        self.assertEqual(event.details.rankings2[0]['sort_orders'][0], 22)
        self.assertEqual(event.details.rankings2[-1]['sort_orders'][0], 4)

        # After alliance selections
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections,
                         self._alliance_selections)
        self.assertEqual(len(event.matches), 72)

        # QF schedule added
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections,
                         self._alliance_selections)
        self.assertEqual(len(event.matches), 84)
        for match in event.matches:
            if match.comp_level == 'qm':
                self.assertTrue(match.has_been_played)
                self.assertNotEqual(match.actual_time, None)
            else:
                self.assertEqual(match.comp_level, 'qf')
                self.assertFalse(match.has_been_played)
                self.assertEqual(match.actual_time, None)

        # After each QF match
        for i in xrange(72, 82):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)
            self.assertEqual(event.details.alliance_selections,
                             self._alliance_selections)
            if i <= 75:
                self.assertEqual(len(event.matches), 84)
            elif i <= 77:
                self.assertEqual(len(event.matches), 83)
            else:
                self.assertEqual(len(event.matches), 82)

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if match.key.id() in {'2016nytr_qf1m3', '2016nytr_qf3m3'}:
                    # Unneeded tiebreak matches
                    self.assertFalse(match.has_been_played)
                elif j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)

        # SF schedule added
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections,
                         self._alliance_selections)
        self.assertEqual(len(event.matches), 88)
        for match in event.matches:
            if match.comp_level in {'qm', 'qf'}:
                self.assertTrue(match.has_been_played)
                self.assertNotEqual(match.actual_time, None)
            else:
                self.assertEqual(match.comp_level, 'sf')
                self.assertFalse(match.has_been_played)
                self.assertEqual(match.actual_time, None)

        # After each SF match
        for i in xrange(82, 87):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)

            if i < 85:
                self.assertEqual(event.details.alliance_selections,
                                 self._alliance_selections)
            else:
                self.assertEqual(event.details.alliance_selections,
                                 self._alliance_selections_with_backup)

            if i <= 83:
                self.assertEqual(len(event.matches), 88)
            else:
                self.assertEqual(len(event.matches), 87)

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if match.key.id() == '2016nytr_sf1m3':
                    # Unneeded tiebreak matches
                    self.assertFalse(match.has_been_played)
                elif j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)

        # F schedule added
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections,
                         self._alliance_selections_with_backup)
        self.assertEqual(len(event.matches), 90)
        for match in event.matches:
            if match.comp_level in {'qm', 'qf', 'sf'}:
                self.assertTrue(match.has_been_played)
                self.assertNotEqual(match.actual_time, None)
            else:
                self.assertEqual(match.comp_level, 'f')
                self.assertFalse(match.has_been_played)
                self.assertEqual(match.actual_time, None)

        # After each F match
        for i in xrange(87, 90):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)
            self.assertEqual(event.details.alliance_selections,
                             self._alliance_selections_with_backup)
            self.assertEqual(len(event.matches), 90)

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)
    def test_event_smulator(self):
        es = EventSimulator()

        # Before anything has happened
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details, None)
        self.assertEqual(event.matches, [])

        # Qual match schedule added
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertNotEqual(event.details, None)
        for rank in event.details.rankings2:
            self.assertEqual(rank['sort_orders'][0], 0)

        self.assertEqual(len(event.matches), 72)
        for match in event.matches:
            self.assertEqual(match.comp_level, 'qm')
            self.assertFalse(match.has_been_played)
            self.assertEqual(match.actual_time, None)

        # After each qual match
        for i in xrange(72):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)
            self.assertEqual(event.details.alliance_selections, None)
            self.assertEqual(len(event.matches), 72)

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)

        # Check some final rankings
        self.assertEqual(event.details.rankings2[0]['sort_orders'][0], 22)
        self.assertEqual(event.details.rankings2[-1]['sort_orders'][0], 4)

        # After alliance selections
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections, self._alliance_selections)
        self.assertEqual(len(event.matches), 72)

        # QF schedule added
        es.step()
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections, self._alliance_selections)
        self.assertEqual(len(event.matches), 84)
        for match in event.matches:
            if match.comp_level == 'qm':
                self.assertTrue(match.has_been_played)
                self.assertNotEqual(match.actual_time, None)
            else:
                self.assertEqual(match.comp_level, 'qf')
                self.assertFalse(match.has_been_played)
                self.assertEqual(match.actual_time, None)

        # After each QF match
        for i in xrange(72, 82):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)
            self.assertEqual(event.details.alliance_selections, self._alliance_selections)

            if i <= 75:
                self.assertEqual(len(event.matches), 84)
            elif i <= 77:
                self.assertEqual(len(event.matches), 86)  # 1 match removed, 3 added
            else:
                self.assertEqual(len(event.matches), 88)  # 1 match removed, 3 added

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if match.key.id() in {'2016nytr_qf1m3', '2016nytr_qf3m3'}:
                    # Unneeded tiebreak matches
                    self.assertFalse(match.has_been_played)
                elif j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)

        # Check SF Matches
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections, self._alliance_selections)
        self.assertEqual(len(event.matches), 88)
        for match in event.matches:
            if match.comp_level in {'qm', 'qf'}:
                self.assertTrue(match.has_been_played)
                self.assertNotEqual(match.actual_time, None)
            else:
                self.assertEqual(match.comp_level, 'sf')
                self.assertFalse(match.has_been_played)
                self.assertEqual(match.actual_time, None)

        # After each SF match
        for i in xrange(82, 87):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)

            if i < 85:
                self.assertEqual(event.details.alliance_selections, self._alliance_selections)
            else:
                self.assertEqual(event.details.alliance_selections, self._alliance_selections_with_backup)

            if i <= 83:
                self.assertEqual(len(event.matches), 88)
            else:
                self.assertEqual(len(event.matches), 90)  # 1 match removed, 3 added

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if match.key.id() == '2016nytr_sf1m3':
                    # Unneeded tiebreak matches
                    self.assertFalse(match.has_been_played)
                elif j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)

        # Check F Matches
        event = Event.get_by_id('2016nytr')
        self.assertNotEqual(event, None)
        self.assertEqual(event.details.alliance_selections, self._alliance_selections_with_backup)
        self.assertEqual(len(event.matches), 90)
        for match in event.matches:
            if match.comp_level in {'qm', 'qf', 'sf'}:
                self.assertTrue(match.has_been_played)
                self.assertNotEqual(match.actual_time, None)
            else:
                self.assertEqual(match.comp_level, 'f')
                self.assertFalse(match.has_been_played)
                self.assertEqual(match.actual_time, None)

        # After each F match
        for i in xrange(87, 90):
            es.step()
            event = Event.get_by_id('2016nytr')
            self.assertNotEqual(event, None)
            self.assertEqual(event.details.alliance_selections, self._alliance_selections_with_backup)
            self.assertEqual(len(event.matches), 90)

            matches = MatchHelper.play_order_sort_matches(event.matches)
            for j, match in enumerate(matches):
                if j <= i:
                    self.assertTrue(match.has_been_played)
                    self.assertNotEqual(match.actual_time, None)
                else:
                    self.assertFalse(match.has_been_played)
    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,
        }
예제 #9
0
    def step(self):
        event = Event.get_by_id('2016nytr')

        if self._step == 0:  # Qual match schedule added
            for match in copy.deepcopy(self._all_matches['qm']):
                for alliance in ['red', 'blue']:
                    match.alliances[alliance]['score'] = -1
                match.alliances_json = json.dumps(match.alliances)
                match.score_breakdown_json = None
                match.actual_time = None
                MatchManipulator.createOrUpdate(match)

            self._step += 1
        elif self._step == 1:  # After each qual match
            MatchManipulator.createOrUpdate(self._played_matches['qm'][self._substep])
            if self._substep < len(self._played_matches['qm']) - 1:
                self._substep += 1
            else:
                self._step += 1
                self._substep = 0
            EventDetailsManipulator.createOrUpdate(EventDetails(id='2016nytr'))
        elif self._step == 2:  # After alliance selections
            EventDetailsManipulator.createOrUpdate(EventDetails(
                id='2016nytr',
                alliance_selections=self._alliance_selections_without_backup
            ))
            self._step += 1
        elif self._step == 3:  # QF schedule added
            for match in copy.deepcopy(self._all_matches['qf']):
                for alliance in ['red', 'blue']:
                    match.alliances[alliance]['score'] = -1
                match.alliances_json = json.dumps(match.alliances)
                match.score_breakdown_json = None
                match.actual_time = None
                MatchManipulator.createOrUpdate(match)
            self._step += 1
        elif self._step == 4:  # After each QF match
            new_match = MatchHelper.play_order_sort_matches(self._played_matches['qf'])[self._substep]
            MatchManipulator.createOrUpdate(new_match)

            if not self._batch_advance:
                win_counts = {
                    'red': 0,
                    'blue': 0,
                }
                for i in xrange(new_match.match_number):
                    win_counts[Match.get_by_id(
                        Match.renderKeyName(
                            new_match.event.id(),
                            new_match.comp_level,
                            new_match.set_number,
                            i+1)).winning_alliance] += 1
                for alliance, wins in win_counts.items():
                    if wins == 2:
                        s = new_match.set_number
                        if s in {1, 2}:
                            self._advancement_alliances['sf1']['red' if s == 1 else 'blue'] = new_match.alliances[alliance]['teams']
                        elif s in {3, 4}:
                            self._advancement_alliances['sf2']['red' if s == 3 else 'blue'] = new_match.alliances[alliance]['teams']
                        else:
                            raise Exception("Invalid set number: {}".format(s))

                        for match_set, alliances in self._advancement_alliances.items():
                            if match_set.startswith('sf'):
                                for i in xrange(3):
                                    for match in copy.deepcopy(self._all_matches['sf']):
                                        key = '2016nytr_{}m{}'.format(match_set, i+1)
                                        if match.key.id() == key:
                                            for color in ['red', 'blue']:
                                                match.alliances[color]['score'] = -1
                                                match.alliances[color]['teams'] = alliances.get(color, [])
                                            match.alliances_json = json.dumps(match.alliances)
                                            match.score_breakdown_json = None
                                            match.actual_time = None
                                            MatchManipulator.createOrUpdate(match)

            if self._substep < len(self._played_matches['qf']) - 1:
                self._substep += 1
            else:
                self._step += 1 if self._batch_advance else 2
                self._substep = 0
        elif self._step == 5:  # SF schedule added
            if self._batch_advance:
                for match in copy.deepcopy(self._all_matches['sf']):
                    for alliance in ['red', 'blue']:
                        match.alliances[alliance]['score'] = -1
                    match.alliances_json = json.dumps(match.alliances)
                    match.score_breakdown_json = None
                    match.actual_time = None
                    MatchManipulator.createOrUpdate(match)
                self._step += 1
        elif self._step == 6:  # After each SF match
            new_match = MatchHelper.play_order_sort_matches(self._played_matches['sf'])[self._substep]
            MatchManipulator.createOrUpdate(new_match)

            if not self._batch_advance:
                win_counts = {
                    'red': 0,
                    'blue': 0,
                }
                for i in xrange(new_match.match_number):
                    win_counts[Match.get_by_id(
                        Match.renderKeyName(
                            new_match.event.id(),
                            new_match.comp_level,
                            new_match.set_number,
                            i+1)).winning_alliance] += 1
                for alliance, wins in win_counts.items():
                    if wins == 2:
                        self._advancement_alliances['f1']['red' if new_match.set_number == 1 else 'blue'] = new_match.alliances[alliance]['teams']

                        for match_set, alliances in self._advancement_alliances.items():
                            if match_set.startswith('f'):
                                for i in xrange(3):
                                    for match in copy.deepcopy(self._all_matches['f']):
                                        key = '2016nytr_{}m{}'.format(match_set, i+1)
                                        if match.key.id() == key:
                                            for color in ['red', 'blue']:
                                                match.alliances[color]['score'] = -1
                                                match.alliances[color]['teams'] = alliances.get(color, [])
                                            match.alliances_json = json.dumps(match.alliances)
                                            match.score_breakdown_json = None
                                            match.actual_time = None
                                            MatchManipulator.createOrUpdate(match)

            # Backup robot introduced
            if self._substep == 3:
                EventDetailsManipulator.createOrUpdate(EventDetails(
                    id='2016nytr',
                    alliance_selections=self._event_details.alliance_selections
                ))
            if self._substep < len(self._played_matches['sf']) - 1:
                self._substep += 1
            else:
                self._step += 1 if self._batch_advance else 2
                self._substep = 0
        elif self._step == 7:  # F schedule added
            if self._batch_advance:
                for match in copy.deepcopy(self._all_matches['f']):
                    for alliance in ['red', 'blue']:
                        match.alliances[alliance]['score'] = -1
                    match.alliances_json = json.dumps(match.alliances)
                    match.score_breakdown_json = None
                    match.actual_time = None
                    MatchManipulator.createOrUpdate(match)
                self._step += 1
        elif self._step == 8:  # After each F match
            MatchManipulator.createOrUpdate(
                MatchHelper.play_order_sort_matches(
                    self._played_matches['f'])[self._substep])
            if self._substep < len(self._played_matches['f']) - 1:
                self._substep += 1
            else:
                self._step += 1
                self._substep = 0

        ndb.get_context().clear_cache()
        # Re fetch event matches
        event = Event.get_by_id('2016nytr')
        MatchHelper.deleteInvalidMatches(event.matches, event)
        ndb.get_context().clear_cache()
        self._update_rankings()
예제 #10
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,
        }