def doAwardInsights(self, year):
        """
        Calculate award insights for a given year. Returns a list of Insights.
        """
        # Get all Blue Banner, Division Finalist, and Championship Finalist awards
        blue_banner_award_keys_future = Award.query(
            Award.year == year,
            Award.award_type_enum.IN(AwardType.BLUE_BANNER_AWARDS),
            Award.event_type_enum.IN({
                EventType.REGIONAL, EventType.DISTRICT,
                EventType.DISTRICT_CMP_DIVISION, EventType.DISTRICT_CMP,
                EventType.CMP_DIVISION, EventType.CMP_FINALS, EventType.FOC
            })).fetch_async(10000, keys_only=True)
        cmp_finalist_award_keys_future = Award.query(
            Award.year == year, Award.award_type_enum == AwardType.FINALIST,
            Award.event_type_enum.IN(
                {EventType.CMP_DIVISION,
                 EventType.CMP_FINALS})).fetch_async(10000, keys_only=True)

        award_futures = ndb.get_multi_async(
            set(blue_banner_award_keys_future.get_result()).union(
                set(cmp_finalist_award_keys_future.get_result())))

        insights = []
        insights += self._calculateBlueBanners(award_futures, year)
        insights += self._calculateChampionshipStats(award_futures, year)
        insights += self._calculateRegionalStats(award_futures, year)
        insights += self._calculateSuccessfulElimTeamups(award_futures, year)

        return insights
    def test_awards_update(self):
        self.awards_auth.put()

        awards = [{'name_str': 'Winner', 'team_key': 'frc254'},
                  {'name_str': 'Winner', 'team_key': 'frc604'},
                  {'name_str': 'Volunteer Blahblah', 'team_key': 'frc1', 'awardee': 'Bob Bobby'}]
        request_body = json.dumps(awards)

        request_path = '/api/trusted/v1/event/2014casj/awards/update'
        sig = md5.new('{}{}{}'.format('321tEsTsEcReT', request_path, request_body)).hexdigest()
        response = self.testapp.post(request_path, request_body, headers={'X-TBA-Auth-Id': 'tEsT_id_4', 'X-TBA-Auth-Sig': sig}, expect_errors=True)

        self.assertEqual(response.status_code, 200)

        db_awards = Award.query(Award.event == self.event.key).fetch(None)
        self.assertEqual(len(db_awards), 2)
        self.assertTrue('2014casj_1' in [a.key.id() for a in db_awards])
        self.assertTrue('2014casj_5' in [a.key.id() for a in db_awards])

        awards = [{'name_str': 'Winner', 'team_key': 'frc254'},
                  {'name_str': 'Winner', 'team_key': 'frc604'}]
        request_body = json.dumps(awards)

        sig = md5.new('{}{}{}'.format('321tEsTsEcReT', request_path, request_body)).hexdigest()
        response = self.testapp.post(request_path, request_body, headers={'X-TBA-Auth-Id': 'tEsT_id_4', 'X-TBA-Auth-Sig': sig}, expect_errors=True)

        self.assertEqual(response.status_code, 200)

        db_awards = Award.query(Award.event == self.event.key).fetch(None)
        self.assertEqual(len(db_awards), 1)
        self.assertTrue('2014casj_1' in [a.key.id() for a in db_awards])
    def test_awards_update(self):
        self.awards_auth.put()

        awards = [{'name_str': 'Winner', 'team_key': 'frc254'},
                  {'name_str': 'Winner', 'team_key': 'frc604'},
                  {'name_str': 'Volunteer Blahblah', 'team_key': 'frc1', 'awardee': 'Bob Bobby'}]
        request_body = json.dumps(awards)

        request_path = '/api/trusted/v1/event/2014casj/awards/update'
        sig = md5.new('{}{}{}'.format('321tEsTsEcReT', request_path, request_body)).hexdigest()
        response = self.testapp.post(request_path, request_body, headers={'X-TBA-Auth-Id': 'tEsT_id_4', 'X-TBA-Auth-Sig': sig}, expect_errors=True)

        self.assertEqual(response.status_code, 200)

        db_awards = Award.query(Award.event == self.event.key).fetch(None)
        self.assertEqual(len(db_awards), 2)
        self.assertTrue('2014casj_1' in [a.key.id() for a in db_awards])
        self.assertTrue('2014casj_5' in [a.key.id() for a in db_awards])

        awards = [{'name_str': 'Winner', 'team_key': 'frc254'},
                  {'name_str': 'Winner', 'team_key': 'frc604'}]
        request_body = json.dumps(awards)

        sig = md5.new('{}{}{}'.format('321tEsTsEcReT', request_path, request_body)).hexdigest()
        response = self.testapp.post(request_path, request_body, headers={'X-TBA-Auth-Id': 'tEsT_id_4', 'X-TBA-Auth-Sig': sig}, expect_errors=True)

        self.assertEqual(response.status_code, 200)

        db_awards = Award.query(Award.event == self.event.key).fetch(None)
        self.assertEqual(len(db_awards), 1)
        self.assertTrue('2014casj_1' in [a.key.id() for a in db_awards])
    def doAwardInsights(self, year):
        """
        Calculate award insights for a given year. Returns a list of Insights.
        """
        # Get all Blue Banner, Division Finalist, and Championship Finalist awards
        blue_banner_award_keys_future = Award.query(
            Award.year == year,
            Award.award_type_enum.IN(AwardType.BLUE_BANNER_AWARDS),
            Award.event_type_enum.IN({EventType.REGIONAL, EventType.DISTRICT, EventType.DISTRICT_CMP, EventType.CMP_DIVISION, EventType.CMP_FINALS})
        ).fetch_async(10000, keys_only=True)
        cmp_finalist_award_keys_future = Award.query(
            Award.year == year,
            Award.award_type_enum == AwardType.FINALIST,
            Award.event_type_enum.IN({EventType.CMP_DIVISION, EventType.CMP_FINALS})
        ).fetch_async(10000, keys_only=True)

        award_futures = ndb.get_multi_async(
            set(blue_banner_award_keys_future.get_result()).union(
            set(cmp_finalist_award_keys_future.get_result()))
        )

        insights = []
        insights += self._calculateBlueBanners(award_futures, year)
        insights += self._calculateChampionshipStats(award_futures, year)
        insights += self._calculateRegionalStats(award_futures, year)
        insights += self._calculateSuccessfulElimTeamups(award_futures, year)

        return insights
Esempio n. 5
0
 def getAwards(self, keys, year=None):
     awards = []
     for key in keys:
         if year == None:
             awards += Award.query(Award.name == key)
         else:
             awards += Award.query(Award.name == key, Award.year == year)
     return awards
Esempio n. 6
0
    def _render(self, team_key, event_key):
        award_keys_future = Award.query(Award.team_list == ndb.Key(Team, self.team_key), Award.event == ndb.Key(Event, event_key)).fetch_async(None, keys_only=True)
        awards = ndb.get_multi(award_keys_future.get_result())

        awards_dicts = [ModelToDict.awardConverter(award) for award in AwardHelper.organizeAwards(awards)]

        return json.dumps(awards_dicts, ensure_ascii=True)
    def _process_request(self, request, event_key):
        event = Event.get_by_id(event_key)

        awards = []
        for award in JSONAwardsParser.parse(request.body, event_key):
            awards.append(Award(
                id=Award.render_key_name(event.key_name, award['award_type_enum']),
                name_str=award['name_str'],
                award_type_enum=award['award_type_enum'],
                year=event.year,
                event=event.key,
                event_type_enum=event.event_type_enum,
                team_list=[ndb.Key(Team, team_key) for team_key in award['team_key_list']],
                recipient_json_list=award['recipient_json_list']
            ))

        # it's easier to clear all awards and add new ones than try to find the difference
        old_award_keys = Award.query(Award.event == event.key).fetch(None, keys_only=True)
        AwardManipulator.delete_keys(old_award_keys)

        if event.remap_teams:
            EventHelper.remapteams_awards(awards, event.remap_teams)
        AwardManipulator.createOrUpdate(awards)

        self.response.out.write(json.dumps({'Success': "Awards successfully updated"}))
Esempio n. 8
0
    def _render(self, *args, **kw):
        awards_future = Award.query(
            Award.award_type_enum == AwardType.CHAIRMANS,
            Award.event_type_enum == EventType.CMP_FINALS).fetch_async()

        teams_by_year = defaultdict(list)
        for award in awards_future.get_result():
            for team_key in award.team_list:
                teams_by_year[award.year].append((
                    team_key.get_async(),
                    award.event.get_async(),
                    award,
                    media_query.TeamTagMediasQuery(
                        team_key.id(), MediaTag.CHAIRMANS_VIDEO).fetch_async(),
                    media_query.TeamTagMediasQuery(
                        team_key.id(),
                        MediaTag.CHAIRMANS_PRESENTATION).fetch_async(),
                    media_query.TeamTagMediasQuery(
                        team_key.id(), MediaTag.CHAIRMANS_ESSAY).fetch_async(),
                ))

        teams_by_year = sorted(teams_by_year.items(), key=lambda (k, v): -k)
        for _, tea in teams_by_year:
            tea.sort(key=lambda x: x[1].get_result().start_date)

        self.template_values.update({
            'teams_by_year': teams_by_year,
        })

        return jinja2_engine.render('hof.html', self.template_values)
Esempio n. 9
0
 def _query_async(self):
     team_key = self._query_args[0]
     event_key = self._query_args[1]
     awards = yield Award.query(
         Award.team_list == ndb.Key(Team, team_key),
         Award.event == ndb.Key(Event, event_key)).fetch_async()
     raise ndb.Return(awards)
Esempio n. 10
0
 def _query_async(self):
     team_key = self._query_args[0]
     year = self._query_args[1]
     awards = yield Award.query(
         Award.team_list == ndb.Key(Team, team_key),
         Award.year == year).fetch_async()
     raise ndb.Return(awards)
    def _render(self, team_number):
        team = Team.get_by_id("frc" + team_number)

        if not team:
            return self.redirect("/error/404")

        event_team_keys_future = EventTeam.query(EventTeam.team == team.key).fetch_async(1000, keys_only=True)
        award_keys_future = Award.query(Award.team == team.key).fetch_async(1000, keys_only=True)

        event_teams_futures = ndb.get_multi_async(event_team_keys_future.get_result())
        awards_futures = ndb.get_multi_async(award_keys_future.get_result())

        event_keys = [event_team_future.get_result().event for event_team_future in event_teams_futures]
        events_futures = ndb.get_multi_async(event_keys)

        awards_by_event = {}
        for award_future in awards_futures:
            award = award_future.get_result()
            if award.event.id() not in awards_by_event:
                awards_by_event[award.event.id()] = [award]
            else:
                awards_by_event[award.event.id()].append(award)

        event_awards = []
        current_event = None
        matches_upcoming = None
        short_cache = False
        for event_future in events_futures:
            event = event_future.get_result()
            if event.now:
                current_event = event

                team_matches_future = Match.query(Match.event == event.key, Match.team_key_names == team.key_name)\
                  .fetch_async(500, keys_only=True)
                matches = ndb.get_multi(team_matches_future.get_result())
                matches_upcoming = MatchHelper.upcomingMatches(matches)

            if event.within_a_day:
                short_cache = True

            if event.key_name in awards_by_event:
                sorted_awards = AwardHelper.organizeAwards(awards_by_event[event.key_name])['list']
            else:
                sorted_awards = []
            event_awards.append((event, sorted_awards))
        event_awards = sorted(event_awards, key=lambda (e, _): e.start_date if e.start_date else datetime.datetime(e.year, 12, 31))

        years = sorted(set([et.get_result().year for et in event_teams_futures if et.get_result().year != None]))

        template_values = {'team': team,
                           'event_awards': event_awards,
                           'years': years,
                           'current_event': current_event,
                           'matches_upcoming': matches_upcoming}

        if short_cache:
            self._cache_expiration = self.SHORT_CACHE_EXPIRATION

        path = os.path.join(os.path.dirname(__file__), '../templates/team_history.html')
        return template.render(path, template_values)
Esempio n. 12
0
    def _render(self, *args, **kw):
        awards_future = Award.query(
            Award.award_type_enum==AwardType.CHAIRMANS,
            Award.event_type_enum==EventType.CMP_FINALS).fetch_async()

        teams_by_year = defaultdict(list)
        for award in awards_future.get_result():
            for team_key in award.team_list:
                teams_by_year[award.year].append((
                    team_key.get_async(),
                    award.event.get_async(),
                    award,
                    media_query.TeamTagMediasQuery(team_key.id(), MediaTag.CHAIRMANS_VIDEO).fetch_async(),
                    media_query.TeamTagMediasQuery(team_key.id(), MediaTag.CHAIRMANS_PRESENTATION).fetch_async(),
                    media_query.TeamTagMediasQuery(team_key.id(), MediaTag.CHAIRMANS_ESSAY).fetch_async(),
                ))

        teams_by_year = sorted(teams_by_year.items(), key=lambda (k, v): -k)
        for _, tea in teams_by_year:
            tea.sort(key=lambda x: x[1].get_result().start_date)

        self.template_values.update({
            'teams_by_year': teams_by_year,
        })

        return jinja2_engine.render('hof.html', self.template_values)
Esempio n. 13
0
    def _process_request(self, request, event_key):
        event = Event.get_by_id(event_key)

        awards = []
        for award in JSONAwardsParser.parse(request.body, event_key):
            awards.append(
                Award(id=Award.render_key_name(event.key_name,
                                               award['award_type_enum']),
                      name_str=award['name_str'],
                      award_type_enum=award['award_type_enum'],
                      year=event.year,
                      event=event.key,
                      event_type_enum=event.event_type_enum,
                      team_list=[
                          ndb.Key(Team, team_key)
                          for team_key in award['team_key_list']
                      ],
                      recipient_json_list=award['recipient_json_list']))

        # it's easier to clear all awards and add new ones than try to find the difference
        old_award_keys = Award.query(Award.event == event.key).fetch(
            None, keys_only=True)
        AwardManipulator.delete_keys(old_award_keys)

        if event.remap_teams:
            EventHelper.remapteams_awards(awards, event.remap_teams)
        AwardManipulator.createOrUpdate(awards)

        self.response.out.write(
            json.dumps({'Success': "Awards successfully updated"}))
 def _query_async(self):
     team_key = self._query_args[0]
     event_key = self._query_args[1]
     awards = yield Award.query(Award.team_list == ndb.Key(
         Team, team_key), Award.event == ndb.Key(Event,
                                                 event_key)).fetch_async()
     raise ndb.Return(awards)
    def _render(self, team_key, event_key):
        award_keys_future = Award.query(Award.team_list == ndb.Key(Team, self.team_key), Award.event == ndb.Key(Event, event_key)).fetch_async(None, keys_only=True)
        awards = ndb.get_multi(award_keys_future.get_result())

        awards_dicts = [ModelToDict.awardConverter(award) for award in AwardHelper.organizeAwards(awards)]

        return json.dumps(awards_dicts, ensure_ascii=True)
    def update(self, event_key):
        """
        Updates EventTeams for an event.
        Returns a tuple of (teams, event_teams, event_team_keys_to_delete)
        An EventTeam is valid iff the team:
        a) played a match at the event,
        b) the team received an award at the event,
        c) or the event has not yet occurred.
        """
        event = Event.get_by_id(event_key)

        # Add teams from Matches and Awards
        team_ids = set()
        match_key_futures = Match.query(
            Match.event == event.key).fetch_async(1000, keys_only=True)
        award_key_futures = Award.query(
            Award.event == event.key).fetch_async(1000, keys_only=True)
        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        for match_future in match_futures:
            match = match_future.get_result()
            for team in match.team_key_names:
                team_ids.add(team)
        for award_future in award_futures:
            award = award_future.get_result()
            for team_key in award.team_list:
                team_ids.add(team_key.id())

        # Create or update EventTeams
        teams = [Team(id=team_id,
                      team_number=int(team_id[3:]))
                      for team_id in team_ids]

        if teams:
            event_teams = [EventTeam(id=event_key + "_" + team.key.id(),
                                     event=event.key,
                                     team=team.key,
                                     year=event.year)
                                     for team in teams]
        else:
            event_teams = None

        # Delete EventTeams for teams who did not participate in the event
        # Only runs if event is over
        existing_event_teams_keys = EventTeam.query(
            EventTeam.event == event.key).fetch(1000, keys_only=True)
        existing_event_teams = ndb.get_multi(existing_event_teams_keys)
        existing_team_ids = set()
        for et in existing_event_teams:
            existing_team_ids.add(et.team.id())

        et_keys_to_delete = set()
        if event.end_date is not None and event.end_date < datetime.datetime.now():
            for team_id in existing_team_ids.difference(team_ids):
                et_key_name = "{}_{}".format(event.key_name, team_id)
                et_keys_to_delete.add(ndb.Key(EventTeam, et_key_name))
            ndb.delete_multi(et_keys_to_delete)

        return teams, event_teams, et_keys_to_delete
Esempio n. 17
0
    def get(self):
        self._require_admin()
        award_count = Award.query().count()

        self.template_values.update({"award_count": award_count})

        path = os.path.join(os.path.dirname(__file__),
                            '../../templates/admin/award_dashboard.html')
        self.response.out.write(template.render(path, self.template_values))
Esempio n. 18
0
 def _query_async(self):
     team_key = self._query_args[0]
     event_type_enum = self._query_args[1]
     award_type_enum = self._query_args[2]
     awards = yield Award.query(
         Award.team_list == ndb.Key(Team, team_key),
         Award.event_type_enum == event_type_enum,
         Award.award_type_enum == award_type_enum).fetch_async()
     raise ndb.Return(awards)
 def _query_async(self):
     team_key = self._query_args[0]
     event_type_enum = self._query_args[1]
     award_type_enum = self._query_args[2]
     awards = yield Award.query(
         Award.team_list == ndb.Key(Team, team_key),
         Award.event_type_enum == event_type_enum,
         Award.award_type_enum == award_type_enum).fetch_async()
     raise ndb.Return(awards)
 def get(self):
     award_count = Award.query().count()
     
     template_values = {
         "award_count": award_count
     }
     
     path = os.path.join(os.path.dirname(__file__), '../../templates/admin/award_dashboard.html')
     self.response.out.write(template.render(path, template_values))
    def get(self):
        self._require_admin()
        award_count = Award.query().count()

        self.template_values.update({
            "award_count": award_count
        })

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/award_dashboard.html')
        self.response.out.write(template.render(path, self.template_values))
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(
            None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(
            None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        POINTS_MULTIPLIER = 3 if event.event_type_enum == EventType.DISTRICT_CMP else 1

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }

        # match points
        elim_num_wins = defaultdict(lambda: defaultdict(int))
        elim_alliances = defaultdict(lambda: defaultdict(list))
        for match_future in match_futures:
            match = match_future.get_result()
            if not match.has_been_played:
                continue

            if match.comp_level == 'qm':
                if match.winning_alliance == '':
                    for team in match.team_key_names:
                        district_points['points'][team][
                            'qual_points'] += 1 * POINTS_MULTIPLIER
                else:
                    for team in match.alliances[
                            match.winning_alliance]['teams']:
                        district_points['points'][team][
                            'qual_points'] += 2 * POINTS_MULTIPLIER
                        district_points['tiebreakers'][team]['qual_wins'] += 1

                for color in ['red', 'blue']:
                    for team in match.alliances[color]['teams']:
                        score = match.alliances[color]['score']
                        district_points['tiebreakers'][team][
                            'highest_qual_scores'] = heapq.nlargest(
                                3, district_points['tiebreakers'][team]
                                ['highest_qual_scores'] + [score])
            else:
                if match.winning_alliance == '':
                    continue

                match_set_key = '{}_{}{}'.format(match.event.id(),
                                                 match.comp_level,
                                                 match.set_number)
                elim_num_wins[match_set_key][match.winning_alliance] += 1
                elim_alliances[match_set_key][
                    match.winning_alliance] += match.alliances[
                        match.winning_alliance]['teams']

                if elim_num_wins[match_set_key][match.winning_alliance] >= 2:
                    for team in elim_alliances[match_set_key][
                            match.winning_alliance]:
                        district_points['points'][team][
                            'elim_points'] += 5 * POINTS_MULTIPLIER

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(
                event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team][
                    'alliance_points'] += points * POINTS_MULTIPLIER
        else:
            logging.warning(
                "Event {} has no alliance selection district_points!".format(
                    event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                if award.award_type_enum == AwardType.CHAIRMANS:
                    point_value = 10
                elif award.award_type_enum in {
                        AwardType.ENGINEERING_INSPIRATION,
                        AwardType.ROOKIE_ALL_STAR
                }:
                    point_value = 8
                else:
                    point_value = 5
                for team in award.team_list:
                    district_points['points'][team.id(
                    )]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points
Esempio n. 23
0
    def update(self, event_key):
        """
        Updates EventTeams for an event.
        Returns a tuple of (teams, event_teams, event_team_keys_to_delete)
        An EventTeam is valid iff the team:
        a) played a match at the event,
        b) the team received an award at the event,
        c) the event has not yet occurred,
        d) the team is on an alliance
        e) the winning alliance of one of this event's divisions
        f) or the event is not from the current year. (This is to make sure we don't delete old data we may no longer be able to scrape)
        """
        event = Event.get_by_id(event_key)
        cur_year = datetime.datetime.now().year

        # Add teams from Matches and Awards
        team_ids = set()
        match_key_futures = Match.query(
            Match.event == event.key).fetch_async(1000, keys_only=True)
        award_key_futures = Award.query(
            Award.event == event.key).fetch_async(1000, keys_only=True)
        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        division_futures = ndb.get_multi_async(event.divisions) if event.divisions else []
        division_matches_futures = [Match.query(
            Match.event == division).fetch_async(1000) for division in event.divisions] if event.divisions else []

        for match_future in match_futures:
            match = match_future.get_result()
            for team in match.team_key_names:
                team_ids.add(team)
        for award_future in award_futures:
            award = award_future.get_result()
            for team_key in award.team_list:
                team_ids.add(team_key.id())

        # Add teams from Alliances
        for team in event.alliance_teams:
            team_ids.add(team)

        # Add teams from division winners
        if division_futures and division_matches_futures:
            for division_future, matches_future in zip(division_futures, division_matches_futures):
                division_winners = self.get_event_winners(division_future.get_result(), matches_future.get_result())
                team_ids = team_ids.union(division_winners)

        # Create or update EventTeams
        teams = [Team(id=team_id,
                      team_number=int(team_id[3:]))
                      for team_id in team_ids if team_id[3:].isdigit()]

        if teams:
            event_teams = [EventTeam(id=event_key + "_" + team.key.id(),
                                     event=event.key,
                                     team=team.key,
                                     year=event.year)
                                     for team in teams]
        else:
            event_teams = None

        # Delete EventTeams for teams who did not participate in the event
        # Only runs if event is over
        existing_event_teams_keys = EventTeam.query(
            EventTeam.event == event.key).fetch(1000, keys_only=True)
        existing_event_teams = ndb.get_multi(existing_event_teams_keys)
        existing_team_ids = set()
        for et in existing_event_teams:
            existing_team_ids.add(et.team.id())

        et_keys_to_delete = set()
        if event.year == cur_year and event.end_date is not None and event.end_date < datetime.datetime.now():
            for team_id in existing_team_ids.difference([team.key.id() for team in teams]):
                et_key_name = "{}_{}".format(event.key_name, team_id)
                et_keys_to_delete.add(ndb.Key(EventTeam, et_key_name))

        return teams, event_teams, et_keys_to_delete
 def _query_async(self):
     team_key = self._query_args[0]
     year = self._query_args[1]
     awards = yield Award.query(Award.team_list == ndb.Key(Team, team_key),
                                Award.year == year).fetch_async()
     raise ndb.Return(awards)
 def _query_async(self):
     event_key = self._query_args[0]
     awards = yield Award.query(
         Award.event == ndb.Key(Event, event_key)).fetch_async()
     raise ndb.Return(awards)
Esempio n. 26
0
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(None, keys_only=True)
        district_team_key_futures = DistrictTeam.query(DistrictTeam.district == event.event_district_enum, DistrictTeam.year == event.year).fetch_async(None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())
        district_team_futures = ndb.get_multi_async(district_team_key_futures.get_result())

        # Typically 3 for District CMP, 1 otherwise
        POINTS_MULTIPLIER = DistrictPointValues.DISTRICT_CMP_MULTIPLIER.get(event.year, DistrictPointValues.DISTRICT_CMP_MULIPLIER_DEFAULT) if event.event_type_enum == EventType.DISTRICT_CMP else DistrictPointValues.STANDARD_MULTIPLIER

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }
        single_district_points = district_points.copy()

        # match points
        if event.year >= 2015:
            # Switched to ranking-based points for 2015 and onward
            cls.calc_rank_based_match_points(event, district_points, match_futures, POINTS_MULTIPLIER)
        else:
            cls.calc_wlt_based_match_points(district_points, match_futures, POINTS_MULTIPLIER)

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event.key_name, POINTS_MULTIPLIER, event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points
        else:
            logging.warning("Event {} has no alliance selection district_points!".format(event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            point_value = 0
            if event.year >= 2014:
                if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                    if award.award_type_enum == AwardType.CHAIRMANS:
                        point_value = DistrictPointValues.CHAIRMANS.get(event.year, DistrictPointValues.CHAIRMANS_DEFAULT)
                    elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                        point_value = DistrictPointValues.EI_AND_RAS_DEFAULT
                    else:
                        point_value = DistrictPointValues.OTHER_AWARD_DEFAULT
            else:  # Legacy awards
                if award.award_type_enum in DistrictPointValues.LEGACY_5_PT_AWARDS.get(event.year, []):
                    point_value = 5
                elif award.award_type_enum in DistrictPointValues.LEGACY_2_PT_AWARDS.get(event.year, []):
                    point_value = 2

            # Add award points to all teams who won
            for team in award.team_list:
                district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        # Filter out teams not in this district (only keep those with a DistrictTeam present for this district)
        for district_team_future in district_team_futures:
            district_team = district_team_future.get_result()
            team_key = district_team.team.id()
            if team_key in district_points['points']:
                single_district_points['points'][team_key] = district_points['points'][team_key]
            if team_key in district_points['tiebreakers']:
                single_district_points['tiebreakers'][team_key] = district_points['tiebreakers'][team_key]

        for team, point_breakdown in single_district_points['points'].items():
            for p in point_breakdown.values():
                single_district_points['points'][team]['total'] += p

        return single_district_points
Esempio n. 27
0
 def get_awards_async(self):
     from models.award import Award
     award_keys = yield Award.query(Award.event == self.key).fetch_async(500, keys_only=True)
     self._awards = yield ndb.get_multi_async(award_keys)
Esempio n. 28
0
    def render_team_history(cls, handler, team, is_canonical):
        event_team_keys_future = EventTeam.query(
            EventTeam.team == team.key).fetch_async(1000, keys_only=True)
        award_keys_future = Award.query(
            Award.team_list == team.key).fetch_async(1000, keys_only=True)

        event_teams_futures = ndb.get_multi_async(
            event_team_keys_future.get_result())
        awards_futures = ndb.get_multi_async(award_keys_future.get_result())

        event_keys = [
            event_team_future.get_result().event
            for event_team_future in event_teams_futures
        ]
        events_futures = ndb.get_multi_async(event_keys)

        awards_by_event = {}
        for award_future in awards_futures:
            award = award_future.get_result()
            if award.event.id() not in awards_by_event:
                awards_by_event[award.event.id()] = [award]
            else:
                awards_by_event[award.event.id()].append(award)

        event_awards = []
        current_event = None
        matches_upcoming = None
        short_cache = False
        for event_future in events_futures:
            event = event_future.get_result()
            if event.now:
                current_event = event

                team_matches_future = Match.query(Match.event == event.key, Match.team_key_names == team.key_name)\
                  .fetch_async(500, keys_only=True)
                matches = ndb.get_multi(team_matches_future.get_result())
                matches_upcoming = MatchHelper.upcomingMatches(matches)

            if event.within_a_day:
                short_cache = True

            if event.key_name in awards_by_event:
                sorted_awards = AwardHelper.organizeAwards(
                    awards_by_event[event.key_name])
            else:
                sorted_awards = []
            event_awards.append((event, sorted_awards))
        event_awards = sorted(
            event_awards,
            key=lambda (e, _): e.start_date
            if e.start_date else datetime.datetime(e.year, 12, 31))

        years = sorted(
            set([
                et.get_result().year for et in event_teams_futures
                if et.get_result().year is not None
            ]))

        handler.template_values.update({
            'is_canonical': is_canonical,
            'team': team,
            'event_awards': event_awards,
            'years': years,
            'current_event': current_event,
            'matches_upcoming': matches_upcoming
        })

        if short_cache:
            handler._cache_expiration = handler.SHORT_CACHE_EXPIRATION

        path = os.path.join(os.path.dirname(__file__),
                            '../templates/team_history.html')
        return template.render(path, handler.template_values)
    def _render(self, team_number, year=None, explicit_year=False):
        team = Team.get_by_id("frc" + team_number)
        
        if not team:
            return self.redirect("/error/404")
        
        event_teams = EventTeam.query(EventTeam.team == team.key).fetch(1000)
        event_keys = [event_team.event for event_team in event_teams if event_team.year == year]
        events = ndb.get_multi(event_keys)

        for event in events:
            if not event.start_date:
                event.start_date = datetime.datetime(year, 12, 31) #unknown goes last
        events = sorted(events, key=lambda event: event.start_date)
        
        years = sorted(set([a.year for a in event_teams if a.year != None]))
        
        awards_future = Award.query(Award.year == year, Award.team == team.key).fetch_async(500)
        for e in events:
            e.team_matches_future = Match.query(Match.event == e.key, Match.team_key_names == team.key_name).fetch_async(500)

        # Return an array of event names and a list of matches from that event that the
        # team was a participant in.
        participation = list()
        year_wlt_list = list()

        current_event = None
        matches_upcoming = None
        short_cache = False
        for e in events:
            awards = AwardHelper.organizeAwards([award for award in awards_future.get_result() if award.event == e.key])
            matches = e.team_matches_future.get_result()
            matches_organized = MatchHelper.organizeMatches(matches)
            
            if e.now:
                current_event = e
                matches_upcoming = MatchHelper.upcomingMatches(matches)
                
            if event.within_a_day:
                short_cache = True
                

            wlt = EventHelper.calculateTeamWLTFromMatches(team.key_name, matches)
            year_wlt_list.append(wlt)
            if wlt["win"] + wlt["loss"] + wlt["tie"] == 0:
                display_wlt = None
            else:
                display_wlt = wlt
                
            team_rank = None
            if e.rankings:
                for element in e.rankings:
                    if element[1] == team_number:
                        team_rank = element[0]
                        break
                
            participation.append({ 'event' : e,
                                   'matches' : matches_organized,
                                   'wlt': display_wlt,
                                   'rank': team_rank,
                                   'awards': awards })
        
        year_wlt = {"win": 0, "loss": 0, "tie": 0}
        for wlt in year_wlt_list:
            year_wlt["win"] += wlt["win"]
            year_wlt["loss"] += wlt["loss"]
            year_wlt["tie"] += wlt["tie"]
        if year_wlt["win"] + year_wlt["loss"] + year_wlt["tie"] == 0:
            year_wlt = None                
        
        template_values = { "explicit_year": explicit_year,
                            "team": team,
                            "participation": participation,
                            "year": year,
                            "years": years,
                            "year_wlt": year_wlt,
                            "current_event": current_event,
                            "matches_upcoming": matches_upcoming }
        
        if short_cache:
            self._cache_expiration = self.SHORT_CACHE_EXPIRATION
        
        path = os.path.join(os.path.dirname(__file__), '../templates/team_details.html')
        return template.render(path, template_values)
Esempio n. 30
0
 def _render(self, team_key):
     self._set_team(team_key)
     award_keys_future = Award.query(Award.team_list == self.team.key).fetch_async(1000, keys_only=True)
     awards_futures = ndb.get_multi_async(award_keys_future.get_result())
     awards_list = [ModelToDict.awardConverter(award_future.get_result()) for award_future in awards_futures]
     return json.dumps(awards_list, ensure_ascii=True)
Esempio n. 31
0
 def _query_async(self):
     event_key = self._query_args[0]
     awards = yield Award.query(Award.event == ndb.Key(Event, event_key)).fetch_async()
     raise ndb.Return(awards)
Esempio n. 32
0
 def get_awards_async():
     award_keys = yield Award.query(
         Award.year == year,
         Award.team_list == team.key).fetch_async(500, keys_only=True)
     awards = yield ndb.get_multi_async(award_keys)
     raise ndb.Return(awards)
Esempio n. 33
0
 def prepAwards(self):
     from models.award import Award
     if self._awards_future is None:
         self._awards_future = Award.query(Award.event == self.key).fetch_async(500)
Esempio n. 34
0
 def get_awards_async(self):
     from models.award import Award
     award_keys = yield Award.query(Award.event == self.key).fetch_async(
         500, keys_only=True)
     self._awards = yield ndb.get_multi_async(award_keys)
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        POINTS_MULTIPLIER = 3 if event.event_type_enum == EventType.DISTRICT_CMP else 1

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }

        # match points
        elim_num_wins = defaultdict(lambda: defaultdict(int))
        elim_alliances = defaultdict(lambda: defaultdict(list))
        for match_future in match_futures:
            match = match_future.get_result()
            if not match.has_been_played:
                continue

            if match.comp_level == 'qm':
                if match.winning_alliance == '':
                    for team in match.team_key_names:
                        district_points['points'][team]['qual_points'] += 1 * POINTS_MULTIPLIER
                else:
                    for team in match.alliances[match.winning_alliance]['teams']:
                        district_points['points'][team]['qual_points'] += 2 * POINTS_MULTIPLIER
                        district_points['tiebreakers'][team]['qual_wins'] += 1

                for color in ['red', 'blue']:
                    for team in match.alliances[color]['teams']:
                        score = match.alliances[color]['score']
                        district_points['tiebreakers'][team]['highest_qual_scores'] = heapq.nlargest(3, district_points['tiebreakers'][team]['highest_qual_scores'] + [score])
            else:
                if match.winning_alliance == '':
                    continue

                match_set_key = '{}_{}{}'.format(match.event.id(), match.comp_level, match.set_number)
                elim_num_wins[match_set_key][match.winning_alliance] += 1
                elim_alliances[match_set_key][match.winning_alliance] += match.alliances[match.winning_alliance]['teams']

                if elim_num_wins[match_set_key][match.winning_alliance] >= 2:
                    for team in elim_alliances[match_set_key][match.winning_alliance]:
                        district_points['points'][team]['elim_points'] += 5* POINTS_MULTIPLIER

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points * POINTS_MULTIPLIER
        else:
            logging.warning("Event {} has no alliance selection district_points!".format(event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                if award.award_type_enum == AwardType.CHAIRMANS:
                    point_value = 10
                elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                    point_value = 8
                else:
                    point_value = 5
                for team in award.team_list:
                    district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points
Esempio n. 36
0
    def calculate_event_points(cls, event):
        match_key_futures = Match.query(Match.event == event.key).fetch_async(None, keys_only=True)
        award_key_futures = Award.query(Award.event == event.key).fetch_async(None, keys_only=True)

        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        POINTS_MULTIPLIER = 3 if event.event_type_enum == EventType.DISTRICT_CMP else 1

        district_points = {
            'points': defaultdict(lambda: {
                'qual_points': 0,
                'elim_points': 0,
                'alliance_points': 0,
                'award_points': 0,
                'total': 0,
            }),
            'tiebreakers': defaultdict(lambda: {  # for tiebreaker stats that can't be calculated with 'points'
                'qual_wins': 0,
                'highest_qual_scores': [],
            }),
        }

        # match points
        if event.year == 2015:
            from helpers.match_helper import MatchHelper  # circular import issue

            # qual match points are calculated by rank
            if event.rankings and len(event.rankings) > 1:
                rankings = event.rankings[1:]  # skip title row
                num_teams = len(rankings)
                alpha = 1.07
                for row in rankings:
                    rank = int(row[0])
                    team = 'frc{}'.format(row[1])
                    qual_points = int(np.ceil(cls.inverf(float(num_teams - 2 * rank + 2) / (alpha * num_teams)) * (10.0 / cls.inverf(1.0 / alpha)) + 12))
                    district_points['points'][team]['qual_points'] = qual_points * POINTS_MULTIPLIER
            else:
                logging.warning("Event {} has no rankings for qual_points calculations!".format(event.key.id()))

            matches = MatchHelper.organizeMatches([mf.get_result() for mf in match_futures])

            # qual match calculations. only used for tiebreaking
            for match in matches['qm']:
                for color in ['red', 'blue']:
                    for team in match.alliances[color]['teams']:
                        score = match.alliances[color]['score']
                        district_points['tiebreakers'][team]['highest_qual_scores'] = heapq.nlargest(3, district_points['tiebreakers'][team]['highest_qual_scores'] + [score])

            # elim match point calculations
            # count number of matches played per team per comp level
            num_played = defaultdict(lambda: defaultdict(int))
            for level in ['qf', 'sf']:
                for match in matches[level]:
                    if not match.has_been_played:
                        continue
                    for color in ['red', 'blue']:
                        for team in match.alliances[color]['teams']:
                            num_played[level][team] += 1

            # qf and sf points
            advancement = MatchHelper.generatePlayoffAdvancement2015(matches)
            for last_level, level in [('qf', 'sf'), ('sf', 'f')]:
                for (teams, _, _) in advancement[last_level]:
                    teams = ['frc{}'.format(t) for t in teams]
                    done = False
                    for match in matches[level]:
                        for color in ['red', 'blue']:
                            if set(teams).intersection(set(match.alliances[color]['teams'])) != set():
                                for team in teams:
                                    points = 5.0 if last_level == 'qf' else 3.3
                                    district_points['points'][team]['elim_points'] += int(np.ceil(points * num_played[last_level][team])) * POINTS_MULTIPLIER
                                done = True
                                break
                            if done:
                                break
                        if done:
                            break

            # final points
            num_wins = {'red': 0, 'blue': 0}
            team_matches_played = {'red': [], 'blue': []}
            for match in matches['f']:
                if not match.has_been_played or match.winning_alliance == '':
                    continue

                num_wins[match.winning_alliance] += 1
                for team in match.alliances[match.winning_alliance]['teams']:
                    team_matches_played[match.winning_alliance].append(team)

                if num_wins[match.winning_alliance] >= 2:
                    for team in team_matches_played[match.winning_alliance]:
                        district_points['points'][team]['elim_points'] += 5 * POINTS_MULTIPLIER

        else:
            elim_num_wins = defaultdict(lambda: defaultdict(int))
            elim_alliances = defaultdict(lambda: defaultdict(list))
            for match_future in match_futures:
                match = match_future.get_result()
                if not match.has_been_played:
                    continue

                if match.comp_level == 'qm':
                    if match.winning_alliance == '':
                        for team in match.team_key_names:
                            district_points['points'][team]['qual_points'] += 1 * POINTS_MULTIPLIER
                    else:
                        for team in match.alliances[match.winning_alliance]['teams']:
                            district_points['points'][team]['qual_points'] += 2 * POINTS_MULTIPLIER
                            district_points['tiebreakers'][team]['qual_wins'] += 1

                    for color in ['red', 'blue']:
                        for team in match.alliances[color]['teams']:
                            score = match.alliances[color]['score']
                            district_points['tiebreakers'][team]['highest_qual_scores'] = heapq.nlargest(3, district_points['tiebreakers'][team]['highest_qual_scores'] + [score])
                else:
                    if match.winning_alliance == '':
                        continue

                    match_set_key = '{}_{}{}'.format(match.event.id(), match.comp_level, match.set_number)
                    elim_num_wins[match_set_key][match.winning_alliance] += 1
                    elim_alliances[match_set_key][match.winning_alliance] += match.alliances[match.winning_alliance]['teams']

                    if elim_num_wins[match_set_key][match.winning_alliance] >= 2:
                        for team in elim_alliances[match_set_key][match.winning_alliance]:
                            district_points['points'][team]['elim_points'] += 5* POINTS_MULTIPLIER

        # alliance points
        if event.alliance_selections:
            selection_points = EventHelper.alliance_selections_to_points(event.alliance_selections)
            for team, points in selection_points.items():
                district_points['points'][team]['alliance_points'] += points * POINTS_MULTIPLIER
        else:
            logging.warning("Event {} has no alliance selection district_points!".format(event.key.id()))

        # award points
        for award_future in award_futures:
            award = award_future.get_result()
            if award.award_type_enum not in AwardType.NON_JUDGED_NON_TEAM_AWARDS:
                if award.award_type_enum == AwardType.CHAIRMANS:
                    point_value = 10
                elif award.award_type_enum in {AwardType.ENGINEERING_INSPIRATION, AwardType.ROOKIE_ALL_STAR}:
                    point_value = 8
                else:
                    point_value = 5
                for team in award.team_list:
                    district_points['points'][team.id()]['award_points'] += point_value * POINTS_MULTIPLIER

        for team, point_breakdown in district_points['points'].items():
            for p in point_breakdown.values():
                district_points['points'][team]['total'] += p

        return district_points
 def get_awards_async():
     award_keys = yield Award.query(Award.year == year, Award.team_list == team.key).fetch_async(500, keys_only=True)
     awards = yield ndb.get_multi_async(award_keys)
     raise ndb.Return(awards)
    def update(self, event_key):
        """
        Updates EventTeams for an event.
        Returns a tuple of (teams, event_teams, event_team_keys_to_delete)
        An EventTeam is valid iff the team:
        a) played a match at the event,
        b) the team received an award at the event,
        c) the event has not yet occurred,
        d) or the event is not from the current year. (This is to make sure we don't delete old data we may no longer be able to scrape)
        """
        event = Event.get_by_id(event_key)
        cur_year = datetime.datetime.now().year

        # Add teams from Matches and Awards
        team_ids = set()
        match_key_futures = Match.query(
            Match.event == event.key).fetch_async(1000, keys_only=True)
        award_key_futures = Award.query(
            Award.event == event.key).fetch_async(1000, keys_only=True)
        match_futures = ndb.get_multi_async(match_key_futures.get_result())
        award_futures = ndb.get_multi_async(award_key_futures.get_result())

        for match_future in match_futures:
            match = match_future.get_result()
            for team in match.team_key_names:
                team_ids.add(team)
        for award_future in award_futures:
            award = award_future.get_result()
            for team_key in award.team_list:
                team_ids.add(team_key.id())

        # Create or update EventTeams
        teams = [Team(id=team_id,
                      team_number=int(team_id[3:]))
                      for team_id in team_ids]

        if teams:
            event_teams = [EventTeam(id=event_key + "_" + team.key.id(),
                                     event=event.key,
                                     team=team.key,
                                     year=event.year)
                                     for team in teams]
        else:
            event_teams = None

        # Delete EventTeams for teams who did not participate in the event
        # Only runs if event is over
        existing_event_teams_keys = EventTeam.query(
            EventTeam.event == event.key).fetch(1000, keys_only=True)
        existing_event_teams = ndb.get_multi(existing_event_teams_keys)
        existing_team_ids = set()
        for et in existing_event_teams:
            existing_team_ids.add(et.team.id())

        et_keys_to_delete = set()
        if event.year == cur_year and event.end_date is not None and event.end_date < datetime.datetime.now():
            for team_id in existing_team_ids.difference(team_ids):
                et_key_name = "{}_{}".format(event.key_name, team_id)
                et_keys_to_delete.add(ndb.Key(EventTeam, et_key_name))

        return teams, event_teams, et_keys_to_delete