Пример #1
0
def district_updated(affected_refs):
    years = _filter(affected_refs['year'])
    district_abbrevs = _filter(affected_refs['abbreviation'])
    district_keys = _filter(affected_refs['key'])

    district_team_keys_future = DistrictTeam.query(DistrictTeam.district_key.IN(list(district_keys))).fetch_async(None, keys_only=True)
    district_event_keys_future = Event.query(Event.district_key.IN(list(district_keys))).fetch_async(keys_only=True)

    queries_and_keys = []
    for year in years:
        queries_and_keys.append(DistrictsInYearQuery(year))

    for abbrev in district_abbrevs:
        queries_and_keys.append(DistrictHistoryQuery(abbrev))

    for key in district_keys:
        queries_and_keys.append(DistrictQuery(key.id()))

    for dt_key in district_team_keys_future.get_result():
        team_key = dt_key.id().split('_')[1]
        queries_and_keys.append(TeamDistrictsQuery(team_key))

    # Necessary because APIv3 Event models include the District model
    affected_event_refs = {
        'key': set(),
        'year': set(),
        'district_key': district_keys,
    }
    for event_key in district_event_keys_future.get_result():
        affected_event_refs['key'].add(event_key)
        affected_event_refs['year'].add(int(event_key.id()[:4]))
    queries_and_keys += event_updated(affected_event_refs)

    return queries_and_keys
    def get(self, team_number):
        self._require_admin()

        team = Team.get_by_id("frc" + team_number)
        if not team:
            self.abort(404)
        event_teams = EventTeam.query(EventTeam.team == team.key).fetch(500)
        team_medias = Media.query(Media.references == team.key).fetch(500)
        robots = Robot.query(Robot.team == team.key).fetch()
        district_teams = DistrictTeam.query(
            DistrictTeam.team == team.key).fetch()
        years_participated = sorted(
            TeamParticipationQuery(team.key_name).fetch())

        team_medias_by_year = {}
        for media in team_medias:
            if media.year in team_medias_by_year:
                team_medias_by_year[media.year].append(media)
            else:
                team_medias_by_year[media.year] = [media]
        media_years = sorted(team_medias_by_year.keys(), reverse=True)

        self.template_values.update({
            'event_teams': event_teams,
            'team': team,
            'team_media_years': media_years,
            'team_medias_by_year': team_medias_by_year,
            'robots': robots,
            'district_teams': district_teams,
            'years_participated': years_participated,
        })

        path = os.path.join(os.path.dirname(__file__),
                            '../../templates/admin/team_details.html')
        self.response.out.write(template.render(path, self.template_values))
Пример #3
0
    def get(self, year):
        year = int(year)
        year_dcmps = DistrictChampsInYearQuery(year).fetch()
        districts_to_write = []

        for dcmp in year_dcmps:
            district_abbrev = DistrictType.type_abbrevs[
                dcmp.event_district_enum]
            district_key = District.renderKeyName(year, district_abbrev)
            logging.info("Creating {}".format(district_key))

            district = District(
                id=district_key,
                year=year,
                abbreviation=district_abbrev,
                display_name=DistrictType.type_names[dcmp.event_district_enum],
                elasticsearch_name=next(
                    (k
                     for k, v in DistrictType.elasticsearch_names.iteritems()
                     if v == dcmp.event_district_enum), None))
            districts_to_write.append(district)

        logging.info("Writing {} new districts".format(
            len(districts_to_write)))
        DistrictManipulator.createOrUpdate(districts_to_write,
                                           run_post_update_hook=False)

        for dcmp in year_dcmps:
            district_abbrev = DistrictType.type_abbrevs[
                dcmp.event_district_enum]
            district_key = District.renderKeyName(year, district_abbrev)
            district_events_future = DistrictEventsQuery(
                district_key).fetch_async()

            district_events = district_events_future.get_result()
            logging.info("Found {} events to update".format(
                len(district_events)))
            events_to_write = []
            for event in district_events:
                event.district_key = ndb.Key(District, district_key)
                events_to_write.append(event)
            EventManipulator.createOrUpdate(events_to_write)

        for dcmp in year_dcmps:
            district_abbrev = DistrictType.type_abbrevs[
                dcmp.event_district_enum]
            district_key = District.renderKeyName(year, district_abbrev)
            districtteams_future = DistrictTeam.query(
                DistrictTeam.year == year,
                DistrictTeam.district == DistrictType.abbrevs.get(
                    district_abbrev, None)).fetch_async()

            districtteams = districtteams_future.get_result()
            logging.info("Found {} DistrictTeams to update".format(
                len(districtteams)))
            districtteams_to_write = []
            for districtteam in districtteams:
                districtteam.district_key = ndb.Key(District, district_key)
                districtteams_to_write.append(districtteam)
            DistrictTeamManipulator.createOrUpdate(districtteams_to_write)
Пример #4
0
    def get_team_cache_keys_and_controllers(cls, affected_refs):
        """
        Gets cache keys and controllers that references this team
        """
        team_keys = affected_refs['key']

        event_team_keys_future = EventTeam.query(
            EventTeam.team.IN([team_key for team_key in team_keys
                               ])).fetch_async(None, keys_only=True)
        district_team_keys_future = DistrictTeam.query(
            DistrictTeam.team.IN([team_key for team_key in team_keys
                                  ])).fetch_async(None, keys_only=True)

        event_keys = set()
        for et_key in event_team_keys_future.get_result():
            event_key_name = et_key.id().split('_')[0]
            event_keys.add(ndb.Key(Event, event_key_name))

        district_keys = set()
        for dt_key in district_team_keys_future.get_result():
            district_key_name = dt_key.id().split('_')[0]
            district_keys.add(district_key_name)

        return cls._get_teams_cache_keys_and_controllers(team_keys) + \
            cls._get_eventteams_cache_keys_and_controllers(event_keys) + \
            cls._get_teamlist_cache_keys_and_controllers(team_keys) + \
            cls._get_districtteams_cache_keys_and_controllers(district_keys, team_keys) + \
            cls._queries_to_cache_keys_and_controllers(get_affected_queries.team_updated(affected_refs))
Пример #5
0
def team_updated(affected_refs):
    team_keys = filter(None, affected_refs['key'])

    event_team_keys_future = EventTeam.query(
        EventTeam.team.IN([team_key for team_key in team_keys
                           ])).fetch_async(None, keys_only=True)
    district_team_keys_future = DistrictTeam.query(
        DistrictTeam.team.IN([team_key for team_key in team_keys
                              ])).fetch_async(None, keys_only=True)

    queries_and_keys = []
    for team_key in team_keys:
        queries_and_keys.append((TeamQuery(team_key.id())))
        page_num = _get_team_page_num(team_key.id())
        queries_and_keys.append((TeamListQuery(page_num)))

    for et_key in event_team_keys_future.get_result():
        year = int(et_key.id()[:4])
        event_key = et_key.id().split('_')[0]
        page_num = _get_team_page_num(et_key.id().split('_')[1])
        queries_and_keys.append((TeamListYearQuery(year, page_num)))
        queries_and_keys.append((EventTeamsQuery(event_key)))

    for dt_key in district_team_keys_future.get_result():
        district_key = dt_key.id().split('_')[0]
        queries_and_keys.append((DistrictTeamsQuery(district_key)))

    return queries_and_keys
    def get(self, team_number):
        self._require_admin()

        team = Team.get_by_id("frc" + team_number)
        if not team:
            self.abort(404)
        event_teams = EventTeam.query(EventTeam.team == team.key).fetch(500)
        team_medias = Media.query(Media.references == team.key).fetch(500)
        robots = Robot.query(Robot.team == team.key).fetch()
        district_teams = DistrictTeam.query(DistrictTeam.team == team.key).fetch()
        years_participated = sorted(TeamParticipationQuery(team.key_name).fetch())

        team_medias_by_year = {}
        for media in team_medias:
            if media.year in team_medias_by_year:
                team_medias_by_year[media.year].append(media)
            else:
                team_medias_by_year[media.year] = [media]
        media_years = sorted(team_medias_by_year.keys(), reverse=True)

        self.template_values.update({
            'event_teams': event_teams,
            'team': team,
            'team_media_years': media_years,
            'team_medias_by_year': team_medias_by_year,
            'robots': robots,
            'district_teams': district_teams,
            'years_participated': years_participated,
        })

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/team_details.html')
        self.response.out.write(template.render(path, self.template_values))
Пример #7
0
 def _query_async(self):
     district_key = self._query_args[0]
     district_teams = yield DistrictTeam.query(
         DistrictTeam.district_key == ndb.Key(District, district_key)).fetch_async()
     team_keys = map(lambda district_team: district_team.team, district_teams)
     teams = yield ndb.get_multi_async(team_keys)
     raise ndb.Return(teams)
Пример #8
0
    def get(self, team_number):
        self._require_admin()

        team = Team.get_by_id("frc" + team_number)
        event_teams = EventTeam.query(EventTeam.team == team.key).fetch(500)
        team_medias = Media.query(Media.references == team.key).fetch(500)
        robots = Robot.query(Robot.team == team.key).fetch()
        district_teams = DistrictTeam.query(DistrictTeam.team == team.key).fetch()

        team_medias_by_year = {}
        for media in team_medias:
            if media.year in team_medias_by_year:
                team_medias_by_year[media.year].append(media)
            else:
                team_medias_by_year[media.year] = [media]

        self.template_values.update({
            'event_teams': event_teams,
            'team': team,
            'team_medias_by_year': team_medias_by_year,
            'robots': robots,
            'district_teams': district_teams,
        })

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/team_details.html')
        self.response.out.write(template.render(path, self.template_values))
def team_updated(affected_refs):
    team_keys = _filter(affected_refs['key'])

    event_team_keys_future = EventTeam.query(EventTeam.team.IN([team_key for team_key in team_keys])).fetch_async(None, keys_only=True)
    district_team_keys_future = DistrictTeam.query(DistrictTeam.team.IN([team_key for team_key in team_keys])).fetch_async(None, keys_only=True)

    queries_and_keys = []
    for team_key in team_keys:
        queries_and_keys.append((TeamQuery(team_key.id())))
        page_num = _get_team_page_num(team_key.id())
        queries_and_keys.append((TeamListQuery(page_num)))

    for et_key in event_team_keys_future.get_result():
        year = int(et_key.id()[:4])
        event_key = et_key.id().split('_')[0]
        page_num = _get_team_page_num(et_key.id().split('_')[1])
        queries_and_keys.append((TeamListYearQuery(year, page_num)))
        queries_and_keys.append((EventTeamsQuery(event_key)))
        queries_and_keys.append((EventEventTeamsQuery(event_key)))

    for dt_key in district_team_keys_future.get_result():
        district_key = dt_key.id().split('_')[0]
        queries_and_keys.append((DistrictTeamsQuery(district_key)))

    return queries_and_keys
Пример #10
0
def district_updated(affected_refs):
    years = _filter(affected_refs['year'])
    district_abbrevs = _filter(affected_refs['abbreviation'])
    district_keys = _filter(affected_refs['key'])

    district_team_keys_future = DistrictTeam.query(DistrictTeam.district_key.IN(list(district_keys))).fetch_async(None, keys_only=True)
    district_event_keys_future = Event.query(Event.district_key.IN(list(district_keys))).fetch_async(keys_only=True)

    queries_and_keys = []
    for year in years:
        queries_and_keys.append(DistrictsInYearQuery(year))

    for abbrev in district_abbrevs:
        queries_and_keys.append(DistrictHistoryQuery(abbrev))

    for key in district_keys:
        queries_and_keys.append(DistrictQuery(key.id()))

    for dt_key in district_team_keys_future.get_result():
        team_key = dt_key.id().split('_')[1]
        queries_and_keys.append(TeamDistrictsQuery(team_key))

    # Necessary because APIv3 Event models include the District model
    affected_event_refs = {
        'key': set(),
        'year': set(),
        'district_key': district_keys,
    }
    for event_key in district_event_keys_future.get_result():
        affected_event_refs['key'].add(event_key)
        affected_event_refs['year'].add(int(event_key.id()[:4]))
    queries_and_keys += event_updated(affected_event_refs)

    return queries_and_keys
Пример #11
0
 def _query_async(self):
     team_key = self._query_args[0]
     district_team_keys = yield DistrictTeam.query(DistrictTeam.team == ndb.Key(Team, team_key)).fetch_async(keys_only=True)
     ret = {}
     for district_team_key in district_team_keys:
         district_key = district_team_key.id().split('_')[0]
         year = int(district_key[:4])
         ret[year] = district_key
     raise ndb.Return(ret)
Пример #12
0
 def _query_async(self):
     district_key = self._query_args[0]
     district_teams = yield DistrictTeam.query(
         DistrictTeam.district_key == ndb.Key(District,
                                              district_key)).fetch_async()
     team_keys = map(lambda district_team: district_team.team,
                     district_teams)
     teams = yield ndb.get_multi_async(team_keys)
     raise ndb.Return(teams)
Пример #13
0
 def _query_async(self):
     team_key = self._query_args[0]
     district_team_keys = yield DistrictTeam.query(
         DistrictTeam.team == ndb.Key(Team, team_key)).fetch_async(
             keys_only=True)
     districts = yield ndb.get_multi_async([
         ndb.Key(District,
                 dtk.id().split('_')[0]) for dtk in district_team_keys
     ])
     raise ndb.Return(filter(lambda x: x is not None, districts))
Пример #14
0
    def get(self, key_name):
        existing_team = Team.get_by_id(key_name)

        fms_df = DatafeedFMSAPI('v2.0')
        df2 = DatafeedFIRSTElasticSearch()
        year = datetime.date.today().year
        fms_details = fms_df.getTeamDetails(year, key_name)

        if fms_details:
            team, district_team, robot = fms_details[0]
        else:
            team = None
            district_team = None
            robot = None

        if team:
            team = TeamManipulator.mergeModels(
                team, df2.getTeamDetails(existing_team))
        else:
            team = df2.getTeamDetails(existing_team)

        if team:
            team = TeamManipulator.createOrUpdate(team)

        # Clean up junk district teams
        # https://www.facebook.com/groups/moardata/permalink/1310068625680096/
        dt_keys = DistrictTeam.query(
            DistrictTeam.team == existing_team.key,
            DistrictTeam.year == year).fetch(keys_only=True)
        keys_to_delete = set()
        for dt_key in dt_keys:
            if not district_team or dt_key.id() != district_team.key.id():
                keys_to_delete.add(dt_key)
        DistrictTeamManipulator.delete_keys(keys_to_delete)

        if district_team:
            district_team = DistrictTeamManipulator.createOrUpdate(
                district_team)

        if robot:
            robot = RobotManipulator.createOrUpdate(robot)

        template_values = {
            'key_name': key_name,
            'team': team,
            'success': team is not None,
            'district': district_team,
            'robot': robot,
        }

        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/datafeeds/usfirst_team_details_get.html')
            self.response.out.write(template.render(path, template_values))
Пример #15
0
 def _query_async(self):
     team_key = self._query_args[0]
     district_team_keys = yield DistrictTeam.query(
         DistrictTeam.team == ndb.Key(Team, team_key)).fetch_async(
             keys_only=True)
     ret = {}
     for district_team_key in district_team_keys:
         district_key = district_team_key.id().split('_')[0]
         year = int(district_key[:4])
         ret[year] = district_key
     raise ndb.Return(ret)
Пример #16
0
 def _query_async(self):
     district_key = self._query_args[0]
     year = int(district_key[:4])
     district_abbrev = district_key[4:]
     district_type = DistrictType.abbrevs.get(district_abbrev, None)
     district_teams = yield DistrictTeam.query(
         DistrictTeam.year == year,
         DistrictTeam.district == district_type).fetch_async()
     team_keys = map(lambda district_team: district_team.team, district_teams)
     teams = yield ndb.get_multi_async(team_keys)
     raise ndb.Return(teams)
Пример #17
0
 def _query_async(self):
     district_key = self._query_args[0]
     year = int(district_key[:4])
     district_abbrev = district_key[4:]
     district_type = DistrictType.abbrevs.get(district_abbrev, None)
     district_teams = yield DistrictTeam.query(
         DistrictTeam.year == year,
         DistrictTeam.district == district_type).fetch_async()
     team_keys = map(lambda district_team: district_team.team,
                     district_teams)
     teams = yield ndb.get_multi_async(team_keys)
     raise ndb.Return(teams)
Пример #18
0
    def get(self, key_name):
        existing_team = Team.get_by_id(key_name)

        fms_df = DatafeedFMSAPI('v2.0')
        df2 = DatafeedFIRSTElasticSearch()
        year = datetime.date.today().year
        fms_details = fms_df.getTeamDetails(year, key_name)

        if fms_details:
            team, district_team, robot = fms_details[0]
        else:
            team = None
            district_team = None
            robot = None

        if team:
            team = TeamManipulator.mergeModels(team, df2.getTeamDetails(existing_team))
        else:
            team = df2.getTeamDetails(existing_team)

        if team:
            team = TeamManipulator.createOrUpdate(team)

        # Clean up junk district teams
        # https://www.facebook.com/groups/moardata/permalink/1310068625680096/
        dt_keys = DistrictTeam.query(
            DistrictTeam.team == existing_team.key,
            DistrictTeam.year == year).fetch(keys_only=True)
        keys_to_delete = set()
        for dt_key in dt_keys:
            if not district_team or dt_key.id() != district_team.key.id():
                keys_to_delete.add(dt_key)
        DistrictTeamManipulator.delete_keys(keys_to_delete)

        if district_team:
            district_team = DistrictTeamManipulator.createOrUpdate(district_team)

        if robot:
            robot = RobotManipulator.createOrUpdate(robot)

        template_values = {
            'key_name': key_name,
            'team': team,
            'success': team is not None,
            'district': district_team,
            'robot': robot,
        }

        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/datafeeds/usfirst_team_details_get.html')
            self.response.out.write(template.render(path, template_values))
    def get(self, year):
        year = int(year)
        year_dcmps = DistrictChampsInYearQuery(year).fetch()
        districts_to_write = []

        for dcmp in year_dcmps:
            district_abbrev = DistrictType.type_abbrevs[dcmp.event_district_enum]
            district_key = District.renderKeyName(year, district_abbrev)
            logging.info("Creating {}".format(district_key))

            district = District(
                id=district_key,
                year=year,
                abbreviation=district_abbrev,
                display_name=DistrictType.type_names[dcmp.event_district_enum],
                elasticsearch_name=next((k for k, v in DistrictType.elasticsearch_names.iteritems() if v == dcmp.event_district_enum), None)
            )
            districts_to_write.append(district)

        logging.info("Writing {} new districts".format(len(districts_to_write)))
        DistrictManipulator.createOrUpdate(districts_to_write, run_post_update_hook=False)

        for dcmp in year_dcmps:
            district_abbrev = DistrictType.type_abbrevs[dcmp.event_district_enum]
            district_key = District.renderKeyName(year, district_abbrev)
            district_events_future = DistrictEventsQuery(district_key).fetch_async()

            district_events = district_events_future.get_result()
            logging.info("Found {} events to update".format(len(district_events)))
            events_to_write = []
            for event in district_events:
                event.district_key = ndb.Key(District, district_key)
                events_to_write.append(event)
            EventManipulator.createOrUpdate(events_to_write)

        for dcmp in year_dcmps:
            district_abbrev = DistrictType.type_abbrevs[dcmp.event_district_enum]
            district_key = District.renderKeyName(year, district_abbrev)
            districtteams_future = DistrictTeam.query(DistrictTeam.year == year, DistrictTeam.district == DistrictType.abbrevs.get(district_abbrev, None)).fetch_async()

            districtteams = districtteams_future.get_result()
            logging.info("Found {} DistrictTeams to update".format(len(districtteams)))
            districtteams_to_write = []
            for districtteam in districtteams:
                districtteam.district_key = ndb.Key(District, district_key)
                districtteams_to_write.append(districtteam)
            DistrictTeamManipulator.createOrUpdate(districtteams_to_write)
    def get_team_cache_keys_and_controllers(cls, affected_refs):
        """
        Gets cache keys and controllers that references this team
        """
        team_keys = affected_refs['key']

        event_team_keys_future = EventTeam.query(EventTeam.team.IN([team_key for team_key in team_keys])).fetch_async(None, keys_only=True)
        district_team_keys_future = DistrictTeam.query(DistrictTeam.team.IN([team_key for team_key in team_keys])).fetch_async(None, keys_only=True)

        event_keys = set()
        for et_key in event_team_keys_future.get_result():
            event_key_name = et_key.id().split('_')[0]
            event_keys.add(ndb.Key(Event, event_key_name))

        district_keys = set()
        for dt_key in district_team_keys_future.get_result():
            district_key_name = dt_key.id().split('_')[0]
            district_keys.add(district_key_name)

        return cls._get_teams_cache_keys_and_controllers(team_keys) + \
            cls._get_eventteams_cache_keys_and_controllers(event_keys) + \
            cls._get_teamlist_cache_keys_and_controllers(team_keys) + \
            cls._get_districtteams_cache_keys_and_controllers(district_keys, team_keys) + \
            cls._queries_to_cache_keys_and_controllers(get_affected_queries.team_updated(affected_refs))
Пример #21
0
 def _query_async(self):
     team_key = self._query_args[0]
     district_team_keys = yield DistrictTeam.query(DistrictTeam.team == ndb.Key(Team, team_key)).fetch_async(keys_only=True)
     districts = yield ndb.get_multi_async([ndb.Key(District, dtk.id().split('_')[0]) for dtk in district_team_keys])
     raise ndb.Return(districts)
Пример #22
0
    def calculate_event_points(cls, event):
        event.get_awards_async()
        event.get_matches_async()
        district_team_key_futures = DistrictTeam.query(DistrictTeam.district == event.event_district_enum, DistrictTeam.year == event.year).fetch_async(None, keys_only=True)

        # 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, event.matches, POINTS_MULTIPLIER)
        else:
            cls.calc_wlt_based_match_points(district_points, event.matches, 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 in event.awards:
            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 ndb.get_multi_async(district_team_key_futures.get_result()):
            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
    def calculate_event_points(cls, event):
        event.get_awards_async()
        event.get_matches_async()
        district_team_key_futures = DistrictTeam.query(DistrictTeam.district == event.event_district_enum, DistrictTeam.year == event.year).fetch_async(None, keys_only=True)

        # 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, event.matches, POINTS_MULTIPLIER)
        else:
            cls.calc_wlt_based_match_points(district_points, event.matches, 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:
            msg = "Event {} has no alliance selection district_points!".format(event.key.id())
            if event.event_type_enum in EventType.SEASON_EVENT_TYPES:
                logging.warning(msg)
            else:
                logging.info(msg)

        # award points
        for award in event.awards:
            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 ndb.get_multi_async(district_team_key_futures.get_result()):
            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