def post(self, event_key): self._require_admin() # Note, we don't actually use event_key. start_date = None if self.request.get("start_date"): start_date = datetime.strptime(self.request.get("start_date"), "%Y-%m-%d") end_date = None if self.request.get("end_date"): end_date = datetime.strptime(self.request.get("end_date"), "%Y-%m-%d") district_key = self.request.get("event_district_key", None) event = Event( id=str(self.request.get("year")) + str.lower(str(self.request.get("event_short"))), end_date=end_date, event_short=self.request.get("event_short"), event_type_enum=EventHelper.parseEventType( self.request.get("event_type_str")), district_key=ndb.Key(District, self.request.get("event_district_key")) if district_key and district_key != 'None' else None, venue=self.request.get("venue"), venue_address=self.request.get("venue_address"), city=self.request.get("city"), state_prov=self.request.get("state_prov"), postalcode=self.request.get("postalcode"), country=self.request.get("country"), name=self.request.get("name"), short_name=self.request.get("short_name"), start_date=start_date, website=self.request.get("website"), year=int(self.request.get("year")), official={ "true": True, "false": False }.get(self.request.get("official").lower()), facebook_eid=self.request.get("facebook_eid"), custom_hashtag=self.request.get("custom_hashtag"), webcast_json=self.request.get("webcast_json"), ) event = EventManipulator.createOrUpdate(event) if self.request.get("alliance_selections_json") or self.request.get( "rankings_json"): event_details = EventDetails( id=event_key, alliance_selections=json.loads( self.request.get("alliance_selections_json")), rankings=json.loads(self.request.get("rankings_json"))) EventDetailsManipulator.createOrUpdate(event_details) MemcacheWebcastFlusher.flushEvent(event.key_name) self.redirect("/admin/event/" + event.key_name)
def get(self, event_key): event = Event.get_by_id(event_key) if not event: self.abort(404) if not event.remap_teams: return event.prepAwardsMatchesTeams() # Remap matches EventHelper.remapteams_matches(event.matches, event.remap_teams) MatchManipulator.createOrUpdate(event.matches) # Remap alliance selections if event.alliance_selections: EventHelper.remapteams_alliances(event.alliance_selections, event.remap_teams) # Remap rankings if event.rankings: EventHelper.remapteams_rankings(event.rankings, event.remap_teams) if event.details and event.details.rankings2: EventHelper.remapteams_rankings2(event.details.rankings2, event.remap_teams) EventDetailsManipulator.createOrUpdate(event.details) # Remap awards EventHelper.remapteams_awards(event.awards, event.remap_teams) AwardManipulator.createOrUpdate(event.awards, auto_union=False)
def get(self, event_key): event = Event.get_by_id(event_key) if event.event_type_enum not in EventType.SEASON_EVENT_TYPES and not self.request.get( 'allow-offseason', None): if 'X-Appengine-Taskname' not in self.request.headers: self.response.out.write( "Can't calculate district points for a non-season event {}!" .format(event.key_name)) return district_points = DistrictHelper.calculate_event_points(event) event_details = EventDetails(id=event_key, district_points=district_points) EventDetailsManipulator.createOrUpdate(event_details) if 'X-Appengine-Taskname' not in self.request.headers: # Only write out if not in taskqueue self.response.out.write(event.district_points) # Enqueue task to update rankings if event.district_key: taskqueue.add( url='/tasks/math/do/district_rankings_calc/{}'.format( event.district_key.id()), method='GET')
def post(self, event_key_id): self._require_admin() event = Event.get_by_id(event_key_id) if not event: self.redirect("/admin/event/" + event.key_name) return event_details = event.details if not event_details or not event_details.alliance_selections: # No alliance data to modify self.redirect("/admin/event/" + event.key_name) return team_in = "frc{}".format(self.request.get("backup_in")) team_out = "frc{}".format(self.request.get("backup_out")) # Make sure both teams are attending the event et_in = EventTeam.get_by_id("{}_{}".format(event.key_name, team_in)) et_out = EventTeam.get_by_id("{}_{}".format(event.key_name, team_out)) if not et_in and et_out: # Bad teams supplied self.redirect("/admin/event/" + event.key_name) return for alliance in event_details.alliance_selections: if team_out in alliance.get('picks', []): alliance['backup'] = {} alliance['backup']['in'] = team_in alliance['backup']['out'] = team_out EventDetailsManipulator.createOrUpdate(event_details) break self.redirect("/admin/event/" + event.key_name) return
def get(self, event_key): df = DatafeedFMSAPI('v2.0', save_response=True) event = Event.get_by_id(event_key) rankings, rankings2 = df.getEventRankings(event_key) if event and event.remap_teams: EventHelper.remapteams_rankings(rankings, event.remap_teams) EventHelper.remapteams_rankings2(rankings2, event.remap_teams) event_details = EventDetails(id=event_key, rankings=rankings, rankings2=rankings2) EventDetailsManipulator.createOrUpdate(event_details) template_values = { 'rankings': rankings, 'event_name': event_details.key.id() } 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_event_rankings_get.html') self.response.out.write(template.render(path, template_values))
def get(self, event_key): event = Event.get_by_id(event_key) if not event: self.abort(404) event_future = EventQuery(event_key).fetch_async(return_updated=True) matches_future = EventMatchesQuery(event_key).fetch_async( return_updated=True) event, _ = event_future.get_result() matches, _ = matches_future.get_result() cleaned_matches = MatchHelper.deleteInvalidMatches(matches, event) matches = MatchHelper.organizeMatches(cleaned_matches) bracket_table, playoff_advancement, _, _ = PlayoffAdvancementHelper.generatePlayoffAdvancement( event, matches) event_details = EventDetails( id=event.key_name, playoff_advancement={ 'advancement': playoff_advancement, 'bracket': bracket_table, }, ) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write("New playoff advancement for {}\n{}".format( event.key_name, json.dumps(event_details.playoff_advancement, indent=2, sort_keys=True)))
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 == 2016: organized_matches = MatchHelper.organizeMatches(event.matches) match_predictions, match_prediction_stats = PredictionHelper.get_match_predictions(organized_matches['qm']) ranking_predictions, ranking_prediction_stats = PredictionHelper.get_ranking_predictions(organized_matches['qm'], match_predictions) predictions_dict = { 'match_predictions': match_predictions, 'match_prediction_stats': match_prediction_stats, 'ranking_predictions': ranking_predictions, 'ranking_prediction_stats': ranking_prediction_stats } event_details = EventDetails( id=event_key, matchstats=matchstats_dict, predictions=predictions_dict ) EventDetailsManipulator.createOrUpdate(event_details) template_values = { 'matchstats_dict': matchstats_dict, } path = os.path.join(os.path.dirname(__file__), '../templates/math/event_matchstats_do.html') self.response.out.write(template.render(path, template_values))
def create_event_details(event_key): event = Event.get_by_id(event_key) if event.alliance_selections or event.district_points or event.matchstats or event.rankings: event_details = EventDetails( id=event_key, alliance_selections=event.alliance_selections, district_points=event.district_points, matchstats=event.matchstats, rankings=event.rankings) EventDetailsManipulator.createOrUpdate(event_details)
def _process_request(self, request, event_key): rankings = JSONRankingsParser.parse(request.body) event = Event.get_by_id(event_key) event_details = EventDetails(id=event_key, rankings=rankings) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write( json.dumps({'Success': "Rankings successfully updated"}))
def _process_request(self, request, event_key): rankings = JSONRankingsParser.parse(request.body) event_details = EventDetails(id=event_key, rankings=rankings) if event_details.year >= 2017: # TODO: Temporary fix. Should directly parse request into rankings2 event_details.rankings2 = RankingsHelper.convert_rankings( event_details) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write( json.dumps({'Success': "Rankings successfully updated"}))
def _process_request(self, request, event_key): alliance_selections = JSONAllianceSelectionsParser.parse(request.body) event = Event.get_by_id(event_key) event_details = EventDetails(id=event_key, alliance_selections=alliance_selections) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write( json.dumps({'Success': "Alliance selections successfully updated"}))
def _process_request(self, request, event_key): rankings = JSONRankingsParser.parse(request.body) event = Event.get_by_id(event_key) event_details = EventDetails( id=event_key, rankings=rankings ) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write(json.dumps({'Success': "Rankings successfully updated"}))
def _process_request(self, request, event_key): alliance_selections = JSONAllianceSelectionsParser.parse(request.body) event = Event.get_by_id(event_key) event_details = EventDetails( id=event_key, alliance_selections=alliance_selections ) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write(json.dumps({'Success': "Alliance selections successfully updated"}))
def _process_request(self, request, event_key): rankings = JSONRankingsParser.parse(request.body) event_details = EventDetails( id=event_key, rankings=rankings ) if event_details.year >= 2017: # TODO: Temporary fix. Should directly parse request into rankings2 event_details.rankings2 = RankingsHelper.convert_rankings(event_details) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write(json.dumps({'Success': "Rankings successfully updated"}))
def _process_request(self, request, event_key): alliance_selections = JSONAllianceSelectionsParser.parse(request.body) event_details = EventDetails( id=event_key, alliance_selections=alliance_selections ) if self.event.remap_teams: EventHelper.remapteams_alliances(event_details.alliance_selections, self.event.remap_teams) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write(json.dumps({'Success': "Alliance selections successfully updated"}))
def post(self, event_key_id): self._require_admin() event = Event.get_by_id(event_key_id) alliance_selections_csv = self.request.get('alliance_selections_csv') alliance_selections = CSVAllianceSelectionsParser.parse( alliance_selections_csv) event_details = EventDetails(id=event_key_id, alliance_selections=alliance_selections) EventDetailsManipulator.createOrUpdate(event_details) self.redirect("/admin/event/" + event.key_name)
def post(self, event_key): self._require_admin() # Note, we don't actually use event_key. start_date = None if self.request.get("start_date"): start_date = datetime.strptime(self.request.get("start_date"), "%Y-%m-%d") end_date = None if self.request.get("end_date"): end_date = datetime.strptime(self.request.get("end_date"), "%Y-%m-%d") district_key = self.request.get("event_district_key", None) event = Event( id=str(self.request.get("year")) + str.lower(str(self.request.get("event_short"))), end_date=end_date, event_short=self.request.get("event_short"), event_type_enum=EventHelper.parseEventType(self.request.get("event_type_str")), district_key=ndb.Key(District, self.request.get("event_district_key")) if district_key and district_key != 'None' else None, venue=self.request.get("venue"), venue_address=self.request.get("venue_address"), city=self.request.get("city"), state_prov=self.request.get("state_prov"), postalcode=self.request.get("postalcode"), country=self.request.get("country"), name=self.request.get("name"), short_name=self.request.get("short_name"), start_date=start_date, website=self.request.get("website"), year=int(self.request.get("year")), official={"true": True, "false": False}.get(self.request.get("official").lower()), facebook_eid=self.request.get("facebook_eid"), custom_hashtag=self.request.get("custom_hashtag"), webcast_json=self.request.get("webcast_json"), playoff_type=int(self.request.get("playoff_type")), ) event = EventManipulator.createOrUpdate(event) if self.request.get("alliance_selections_json") or self.request.get("rankings_json"): event_details = EventDetails( id=event_key, alliance_selections=json.loads(self.request.get("alliance_selections_json")), rankings=json.loads(self.request.get("rankings_json")) ) EventDetailsManipulator.createOrUpdate(event_details) MemcacheWebcastFlusher.flushEvent(event.key_name) self.redirect("/admin/event/" + event.key_name)
def _update_rankings(self): """ Generates and saves fake rankings """ event = Event.get_by_id('2016nytr') team_wins = defaultdict(int) team_losses = defaultdict(int) team_ties = defaultdict(int) teams = set() for match in event.matches: if match.comp_level == 'qm': for alliance in ['red', 'blue']: for team in match.alliances[alliance]['teams']: teams.add(team) if match.has_been_played: if alliance == match.winning_alliance: team_wins[team] += 1 elif match.winning_alliance == '': team_ties[team] += 1 else: team_losses[team] += 1 rankings = [] for team in sorted(teams): wins = team_wins[team] losses = team_losses[team] ties = team_ties[team] rankings.append({ 'team_key': team, 'record': { 'wins': wins, 'losses': losses, 'ties': ties, }, 'matches_played': wins + losses + ties, 'dq': 0, 'sort_orders': [2 * wins + ties, 0, 0, 0, 0], 'qual_average': None, }) rankings = sorted(rankings, key=lambda r: -r['sort_orders'][0]) for i, ranking in enumerate(rankings): ranking['rank'] = i + 1 EventDetailsManipulator.createOrUpdate( EventDetails( id='2016nytr', rankings2=rankings, ))
def post(self): self._require_admin() event_key = self.request.get("event_key").strip() event = Event.get_by_id(event_key) if not event: self.redirect("/admin/event/" + event.key_name) return if event.playoff_type != PlayoffType.ROUND_ROBIN_6_TEAM: logging.warning("Can't set advancement for non-round robin events") self.redirect("/admin/event/" + event.key_name) return advancement_csv = self.request.get("advancement_csv") comp_level = self.request.get("comp_level") matches_per_team = int(self.request.get("num_matches")) if comp_level not in Match.ELIM_LEVELS: logging.warning("Bad comp level: {}".format(comp_level)) self.redirect("/admin/event/" + event.key_name) return parsed_advancement = CSVAdvancementParser.parse( advancement_csv, matches_per_team) advancement = PlayoffAdvancementHelper.generatePlayoffAdvancementFromCSV( event, parsed_advancement, comp_level) cleaned_matches = MatchHelper.deleteInvalidMatches( event.matches, event) matches = MatchHelper.organizeMatches(cleaned_matches) bracket_table = PlayoffAdvancementHelper.generateBracket( matches, event, event.alliance_selections) comp_levels = bracket_table.keys() for comp_level in comp_levels: if comp_level != 'f': del bracket_table[comp_level] existing_details = EventDetails.get_by_id(event.key_name) new_advancement = existing_details.playoff_advancement if existing_details and existing_details.playoff_advancement else {} new_advancement.update(advancement) event_details = EventDetails( id=event.key_name, playoff_advancement={ 'advancement': new_advancement, 'bracket': bracket_table, }, ) EventDetailsManipulator.createOrUpdate(event_details) self.redirect("/admin/event/" + event.key_name) return
def get(self, year): self._require_admin() event_keys = Event.query(Event.year==int(year)).fetch(keys_only=True) event_details = ndb.get_multi([ndb.Key(EventDetails, key.id()) for key in event_keys]) updated = [] for event_detail in event_details: if event_detail: logging.info(event_detail.key.id()) event_detail.rankings2 = RankingsHelper.convert_rankings(event_detail) updated.append(event_detail) EventDetailsManipulator.createOrUpdate(updated) self.response.out.write("DONE")
def post(self, event_key_id): self._require_admin() event = Event.get_by_id(event_key_id) alliance_selections_csv = self.request.get('alliance_selections_csv') alliance_selections = CSVAllianceSelectionsParser.parse(alliance_selections_csv) event_details = EventDetails( id=event_key_id, alliance_selections=alliance_selections ) EventDetailsManipulator.createOrUpdate(event_details) self.redirect("/admin/event/" + event.key_name)
def _update_rankings(self): """ Generates and saves fake rankings """ event = Event.get_by_id('2016nytr') team_wins = defaultdict(int) team_losses = defaultdict(int) team_ties = defaultdict(int) teams = set() for match in event.matches: if match.comp_level == 'qm': for alliance in ['red', 'blue']: for team in match.alliances[alliance]['teams']: teams.add(team) if match.has_been_played: if alliance == match.winning_alliance: team_wins[team] += 1 elif match.winning_alliance == '': team_ties[team] += 1 else: team_losses[team] += 1 rankings = [] for team in sorted(teams): wins = team_wins[team] losses = team_losses[team] ties = team_ties[team] rankings.append({ 'team_key': team, 'record': { 'wins': wins, 'losses': losses, 'ties': ties, }, 'matches_played': wins + losses + ties, 'dq': 0, 'sort_orders': [2 * wins + ties, 0, 0, 0, 0], 'qual_average': None, }) rankings = sorted(rankings, key=lambda r: -r['sort_orders'][0]) for i, ranking in enumerate(rankings): ranking['rank'] = i + 1 EventDetailsManipulator.createOrUpdate(EventDetails( id='2016nytr', rankings2=rankings, ))
def post(self, event_key): self._require_admin() event = Event.get_by_id(event_key) if not event: self.redirect("/admin/event/" + event.key_name) return details = EventDetails.get_by_id(event.key_name) if details: details.playoff_advancement = {} EventDetailsManipulator.createOrUpdate(details) self.redirect("/admin/event/" + event.key_name) return
def get(self, event_key): event = Event.get_by_id(event_key) if event.event_district_enum == DistrictType.NO_DISTRICT: self.response.out.write("Can't calculate district points for a non-district event!") return district_points = DistrictHelper.calculate_event_points(event) event_details = EventDetails( id=event_key, district_points=district_points ) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write(event.district_points)
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))
def get(self, event_key): df = DatafeedFMSAPI('v2.0') rankings = df.getEventRankings(event_key) event_details = EventDetails( id=event_key, rankings=rankings ) EventDetailsManipulator.createOrUpdate(event_details) template_values = {'rankings': rankings, 'event_name': event_details.key.id()} 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_event_rankings_get.html') self.response.out.write(template.render(path, template_values))
def get(self, event_key): df = DatafeedFMSAPI('v2.0', save_response=True) event = Event.get_by_id(event_key) alliance_selections = df.getEventAlliances(event_key) event_details = EventDetails( id=event_key, alliance_selections=alliance_selections ) EventDetailsManipulator.createOrUpdate(event_details) template_values = {'alliance_selections': alliance_selections, 'event_name': event_details.key.id()} 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_event_alliances_get.html') self.response.out.write(template.render(path, template_values))
def get(self, event_key): df = DatafeedFMSAPI('v2.0') event = Event.get_by_id(event_key) alliance_selections = df.getEventAlliances(event_key) event_details = EventDetails( id=event_key, alliance_selections=alliance_selections ) EventDetailsManipulator.createOrUpdate(event_details) template_values = {'alliance_selections': alliance_selections, 'event_name': event_details.key.id()} 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_event_alliances_get.html') self.response.out.write(template.render(path, template_values))
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 get(self, event_key): event = Event.get_by_id(event_key) if event.event_type_enum not in EventType.SEASON_EVENT_TYPES and not self.request.get('allow-offseason', None): if 'X-Appengine-Taskname' not in self.request.headers: self.response.out.write("Can't calculate district points for a non-season event {}!" .format(event.key_name)) return district_points = DistrictHelper.calculate_event_points(event) event_details = EventDetails( id=event_key, district_points=district_points ) EventDetailsManipulator.createOrUpdate(event_details) if 'X-Appengine-Taskname' not in self.request.headers: # Only write out if not in taskqueue self.response.out.write(event.district_points) # Enqueue task to update rankings if event.district_key: taskqueue.add(url='/tasks/math/do/district_rankings_calc/{}'.format(event.district_key.id()), method='GET')
def test_findOrSpawn(self): self.old_event_details.put() self.assertMergedEventDetails(EventDetailsManipulator.findOrSpawn(self.new_event_details))
def test_updateMerge(self): self.assertMergedEventDetails(EventDetailsManipulator.updateMerge(self.new_event_details, self.old_event_details))
def test_updateMerge(self): self.assertMergedEventDetails( EventDetailsManipulator.updateMerge(self.new_event_details, self.old_event_details))
def get(self, event_key): if tba_config.CONFIG["env"] == "prod": # disable in prod for now logging.error("Tried to restore {} from CSV in prod! No can do.".format(event_key)) return event = Event.get_by_id(event_key) # alliances result = urlfetch.fetch(self.ALLIANCES_URL.format(event.year, event_key, event_key)) if result.status_code != 200: logging.warning('Unable to retreive url: ' + (self.ALLIANCES_URL.format(event.year, event_key, event_key))) else: data = result.content.replace('frc', '') alliance_selections = CSVAllianceSelectionsParser.parse(data) event_details = EventDetails( id=event_key, alliance_selections=alliance_selections ) EventDetailsManipulator.createOrUpdate(event_details) # awards result = urlfetch.fetch(self.AWARDS_URL.format(event.year, event_key, event_key)) if result.status_code != 200: logging.warning('Unable to retreive url: ' + (self.AWARDS_URL.format(event.year, event_key, event_key))) else: # convert into expected input format data = StringIO.StringIO() writer = csv.writer(data, delimiter=',') for row in csv.reader(StringIO.StringIO(result.content), delimiter=','): writer.writerow([event.year, event.event_short, row[1], row[2].replace('frc', ''), row[3]]) awards = [] for award in CSVAwardsParser.parse(data.getvalue()): 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, 'frc{}'.format(team_number)) for team_number in award['team_number_list']], recipient_json_list=award['recipient_json_list'] )) AwardManipulator.createOrUpdate(awards) # matches result = urlfetch.fetch(self.MATCHES_URL.format(event.year, event_key, event_key)) if result.status_code != 200: logging.warning('Unable to retreive url: ' + (self.MATCHES_URL.format(event.year, event_key, event_key))) else: data = result.content.replace('frc', '').replace('{}_'.format(event_key), '') match_dicts, _ = OffseasonMatchesParser.parse(data) matches = [ Match( id=Match.renderKeyName( event.key.id(), match.get("comp_level", None), match.get("set_number", 0), match.get("match_number", 0)), event=event.key, year=event.year, set_number=match.get("set_number", 0), match_number=match.get("match_number", 0), comp_level=match.get("comp_level", None), team_key_names=match.get("team_key_names", None), alliances_json=match.get("alliances_json", None) ) for match in match_dicts] MatchManipulator.createOrUpdate(matches) # rankings result = urlfetch.fetch(self.RANKINGS_URL.format(event.year, event_key, event_key)) if result.status_code != 200: logging.warning('Unable to retreive url: ' + (self.RANKINGS_URL.format(event.year, event_key, event_key))) else: # convert into expected input format rankings = list(csv.reader(StringIO.StringIO(result.content), delimiter=',')) event_details = EventDetails( id=event_key, rankings=rankings ) EventDetailsManipulator.createOrUpdate(event_details) self.response.out.write("Done restoring {}!".format(event_key))
def post(self, event_key_id): self._require_admin() event = Event.get_by_id(event_key_id) event.prepAwardsMatchesTeams() remap_teams = {} for key, value in json.loads(self.request.get('remap_teams')).items(): remap_teams['frc{}'.format(key)] = 'frc{}'.format(value) # Remap matches for match in event.matches: for old_team, new_team in remap_teams.items(): # Update team key names for i, key in enumerate(match.team_key_names): if key == old_team: match.dirty = True if new_team.isdigit(): # Only if non "B" teams match.team_key_names[i] = new_team else: del match.team_key_names[i] # Update alliances for color in ['red', 'blue']: for i, key in enumerate(match.alliances[color]['teams']): if key == old_team: match.dirty = True match.alliances[color]['teams'][i] = new_team match.alliances_json = json.dumps(match.alliances) MatchManipulator.createOrUpdate(event.matches) # Remap alliance selections if event.alliance_selections: for row in event.alliance_selections: for choice in ['picks', 'declines']: for old_team, new_team in remap_teams.items(): for i, key in enumerate(row[choice]): if key == old_team: row[choice][i] = new_team # Remap rankings if event.rankings: for row in event.rankings: for old_team, new_team in remap_teams.items(): if row[1] == old_team[3:]: row[1] = new_team[3:] EventDetailsManipulator.createOrUpdate(event.details) # Remap awards for award in event.awards: for old_team, new_team in remap_teams.items(): # Update team keys for i, key in enumerate(award.team_list): if key.id() == old_team: award.dirty = True if new_team.isdigit(): # Only if non "B" teams award.team_list[i] = ndb.Key(Team, new_team) else: del award.team_list[i] # Update recipient list for recipient in award.recipient_list: if str(recipient['team_number']) == old_team[3:]: award.dirty = True recipient['team_number'] = new_team[3:] award.recipient_json_list = [json.dumps(r) for r in award.recipient_list] AwardManipulator.createOrUpdate(event.awards, auto_union=False) self.redirect("/admin/event/" + event.key_name)
def post(self, event_key): self._require_admin() # Note, we don't actually use event_key. start_date = None if self.request.get("start_date"): start_date = datetime.strptime(self.request.get("start_date"), "%Y-%m-%d") end_date = None if self.request.get("end_date"): end_date = datetime.strptime(self.request.get("end_date"), "%Y-%m-%d") first_code = self.request.get("first_code", None) district_key = self.request.get("event_district_key", None) parent_key = self.request.get("parent_event", None) division_key_names = json.loads(self.request.get('divisions'), '[]') if self.request.get('divisions') else [] division_keys = [ndb.Key(Event, key) for key in division_key_names] if division_key_names else [] website = WebsiteHelper.format_url(self.request.get("website")) event = Event( id=str(self.request.get("year")) + str.lower(str(self.request.get("event_short"))), end_date=end_date, event_short=self.request.get("event_short"), first_code=first_code if first_code and first_code != 'None' else None, event_type_enum=int(self.request.get("event_type")) if self.request.get('event_type') else EventType.UNLABLED, district_key=ndb.Key(District, self.request.get("event_district_key")) if district_key and district_key != 'None' else None, venue=self.request.get("venue"), venue_address=self.request.get("venue_address"), city=self.request.get("city"), state_prov=self.request.get("state_prov"), postalcode=self.request.get("postalcode"), country=self.request.get("country"), name=self.request.get("name"), short_name=self.request.get("short_name"), start_date=start_date, website=website, year=int(self.request.get("year")), official={"true": True, "false": False}.get(self.request.get("official").lower()), enable_predictions={"true": True, "false": False}.get(self.request.get("enable_predictions").lower()), facebook_eid=self.request.get("facebook_eid"), custom_hashtag=self.request.get("custom_hashtag"), webcast_json=self.request.get("webcast_json"), playoff_type=int(self.request.get("playoff_type")) if self.request.get('playoff_type') else PlayoffType.BRACKET_8_TEAM, parent_event=ndb.Key(Event, parent_key) if parent_key and parent_key.lower() != 'none' else None, divisions=division_keys, ) event = EventManipulator.createOrUpdate(event) if self.request.get("alliance_selections_json") or self.request.get("rankings_json"): event_details = EventDetails( id=event_key, alliance_selections=json.loads(self.request.get("alliance_selections_json")), rankings=json.loads(self.request.get("rankings_json")) ) EventDetailsManipulator.createOrUpdate(event_details) MemcacheWebcastFlusher.flushEvent(event.key_name) self.redirect("/admin/event/" + event.key_name)
def test_findOrSpawn(self): self.old_event_details.put() self.assertMergedEventDetails( EventDetailsManipulator.findOrSpawn(self.new_event_details))
def test_createOrUpdate(self): EventDetailsManipulator.createOrUpdate(self.old_event_details) self.assertOldEventDetails(EventDetails.get_by_id('2011ct')) EventDetailsManipulator.createOrUpdate(self.new_event_details) self.assertMergedEventDetails(EventDetails.get_by_id('2011ct'))
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()
def post(self, event_key): self._require_admin() # Note, we don't actually use event_key. start_date = None if self.request.get("start_date"): start_date = datetime.strptime(self.request.get("start_date"), "%Y-%m-%d") end_date = None if self.request.get("end_date"): end_date = datetime.strptime(self.request.get("end_date"), "%Y-%m-%d") first_code = self.request.get("first_code", None) district_key = self.request.get("event_district_key", None) parent_key = self.request.get("parent_event", None) division_key_names = json.loads( self.request.get('divisions'), '[]') if self.request.get('divisions') else [] division_keys = [ndb.Key(Event, key) for key in division_key_names ] if division_key_names else [] website = WebsiteHelper.format_url(self.request.get("website")) event = Event( id=str(self.request.get("year")) + str.lower(str(self.request.get("event_short"))), end_date=end_date, event_short=self.request.get("event_short"), first_code=first_code if first_code and first_code != 'None' else None, event_type_enum=int(self.request.get("event_type")) if self.request.get('event_type') else EventType.UNLABLED, district_key=ndb.Key(District, self.request.get("event_district_key")) if district_key and district_key != 'None' else None, venue=self.request.get("venue"), venue_address=self.request.get("venue_address"), city=self.request.get("city"), state_prov=self.request.get("state_prov"), postalcode=self.request.get("postalcode"), country=self.request.get("country"), name=self.request.get("name"), short_name=self.request.get("short_name"), start_date=start_date, website=website, first_eid=self.request.get("first_eid"), year=int(self.request.get("year")), official={ "true": True, "false": False }.get(self.request.get("official").lower()), enable_predictions={ "true": True, "false": False }.get(self.request.get("enable_predictions").lower()), facebook_eid=self.request.get("facebook_eid"), custom_hashtag=self.request.get("custom_hashtag"), webcast_json=self.request.get("webcast_json"), playoff_type=int(self.request.get("playoff_type")) if self.request.get('playoff_type') else PlayoffType.BRACKET_8_TEAM, parent_event=ndb.Key(Event, parent_key) if parent_key and parent_key.lower() != 'none' else None, divisions=division_keys, ) event = EventManipulator.createOrUpdate(event) if self.request.get("alliance_selections_json") or self.request.get( "rankings_json"): event_details = EventDetails( id=event_key, alliance_selections=json.loads( self.request.get("alliance_selections_json")), rankings=json.loads(self.request.get("rankings_json"))) EventDetailsManipulator.createOrUpdate(event_details) MemcacheWebcastFlusher.flushEvent(event.key_name) self.redirect("/admin/event/" + event.key_name)
def store_eventdetail(event, type, data): detail = EventDetails(id=event.key_name) setattr(detail, type, data) return EventDetailsManipulator.createOrUpdate(detail)