def process_team_season_json(team, jdata, season): season_dicts = dictify(jdata['resultSets'][0]) for sdict in season_dicts: sdict['SEASON_ID'] = make_season_int(sdict['YEAR']) if sdict['SEASON_ID'] == season.year: log.debug(sdict['YEAR']) sdict['SEASON'] = season sdict['W'] = sdict['WINS'] sdict['L'] = sdict['LOSSES'] sdict['W_PCT'] = sdict['WIN_PCT'] sdict['PLAYOFF_WINS'] = sdict['PO_WINS'] sdict['PLAYOFF_LOSSES'] = sdict['PO_LOSSES'] sdict['NBA_FINALS_APPEARANCE'] = (sdict['NBA_FINALS_APPEARANCE'] != "N/A") sdict['TEAM'] = team sdict['SEASON_TYPE'] = jdata['parameters']['SeasonType'] sdict['PER_MODE'] = jdata['parameters']['PerMode'] sdict = convert_dict_keys_to_lowercase( sdict, override_list=["CONF_RANK", "DIV_RANK", "W", "L"], aux_list=[ "YEAR", "WINS", "LOSSES", "WIN_PCT", "PO_WINS", "PO_LOSSES" ]) filter_dict = make_unique_filter_dict(TeamSeason, sdict) season, created = TeamSeason.objects.update_or_create( **filter_dict, defaults=sdict) if created: log.debug(("Created team season ", filter_dict))
def lineups(self): lineups_list = [] for row in self.raw_data: final_data = auto_strip_and_convert_fields(model=self.model, data=row, make_instance=False) player_ids = [ int(pid.strip()) for pid in row['group_id'].split("-") ] players = Player.objects.filter( player_id__in=player_ids).order_by('id') filter_dict = make_unique_filter_dict(self.model, final_data) filter_dict['group_quantity'] = final_data['group_quantity'] lineup = self.model.filter_on_players(players, filter_dict).first() if lineup is None: lineup = self.model(**final_data) lineup.save() lineup.players = players lineup.save() log.debug(("Created new lineup: ", filter_dict, players)) else: for fld in final_data: setattr(lineup, fld, final_data[fld]) lineup.save() lineups_list.append(lineup) return lineups_list
def lineup_players_changed(sender, **kwargs): instance = kwargs.get('instance') if isinstance(instance, Lineup): if kwargs.get('action') == 'pre_remove': filter_dict = make_unique_filter_dict(instance.__class__, instance=instance) cur_pids = list(instance.players.all().values_list('id', flat=True).distinct()) new_pids = list(kwargs.get('pk_set', set())) # TODO: Deal with cur_pids & new_pids having players in common all_pids = cur_pids + new_pids cur_lineups = instance.__class__.filter_on_players(all_pids, filter_dict) if cur_lineups.exists(): raise IntegrityError("This lineup already exists!")
def _get_objects(self, detail_flag=False): log.debug("in _get objects") log.debug(("len(self.raw_data): ", len(self.raw_data))) objects = [] idx = 1 if detail_flag else 0 rawdata = self.raw_data[idx] parms = rawdata['parameters'] measure_type = parms['MeasureType'] on = rawdata['resultSets'][1] off = rawdata['resultSets'][2] rows = on['rowSet'] + off['rowSet'] headers = on['headers'] prefix = "Player" middle = measure_type.replace(" ", "") if detail_flag else "" suffix = "OnOffDetail" if detail_flag else "OnOffSummary" model = get_model(prefix, middle, suffix) for row in rows: data = dict(zip(headers, row)) data['SEASON_ID'] = make_season_int(parms['Season']) data['MEASURE_TYPE'] = parms['MeasureType'] data['SEASON_TYPE'] = parms['SeasonType'] data['PER_MODE'] = parms['PerMode'] data['TEAM'] = Team.objects.get(team_id=data['TEAM_ID']) data['PLAYER'] = Player.objects.get(player_id=data['VS_PLAYER_ID']) if detail_flag: if measure_type == "Misc": data['PTS_SECOND_CHANCE'] = data['PTS_2ND_CHANCE'] data['OPP_PTS_SECOND_CHANCE'] = data['OPP_PTS_2ND_CHANCE'] elif measure_type == "Scoring": data['PCT_PTS_2PT_MIDRANGE'] = data['PCT_PTS_2PT_MR'] final_data = auto_strip_and_convert_fields(model, data, uppercase=True, make_instance=False) filter_dict = make_unique_filter_dict(model, final_data) obj, created = model.objects.update_or_create(**filter_dict, defaults=final_data) if created: log.debug(("Created new OnOff ", filter_dict)) objects.append(obj) return objects
def create_update_all_seasons_for_player(player, year=None): player_seasons = [] url = NBA_BASE_URL + PLAYER_CAREER_STATS_ENDPOINT parms = PLAYER_CAREER_STATS_PARAMS parms['PlayerID'] = player.player_id # Removing Per36 & PerGame cut down the requests by 2/3 per_mode = "Totals" parms['PerMode'] = per_mode json_data = get_json_response(url, params=parms) result_sets = json_data['resultSets'] for rset in result_sets: season_type = rset['name'] if not any(ignore in season_type for ignore in IGNORE_SEASON_TYPES): headers = rset['headers'] rows = rset['rowSet'] team = None for row in rows: data = dict(zip(headers, row)) # log.debug("Data: " + str(data)) dteam_key = "TEAM_ID" if "TEAM_ID" in data else "Team_ID" if team is None or data[dteam_key] != team.team_id: try: team = Team.objects.get(team_id=data[dteam_key]) except Exception as e: log.debug(("ELEPHANT", data)) raise e conv_data = convert_dict_keys_to_lowercase(data, override_list=['LEAGUE_ID']) conv_data['season_id'] = make_season_int(conv_data.get('season_id', 0)) # year=None -> update/create all seasons. Always update career. if year is not None and conv_data['season_id'] not in [0, year]: continue conv_data['season_type'] = season_type conv_data['player'] = player conv_data['team'] = team conv_data['per_mode'] = per_mode # log.debug("Converted Data: " + str(conv_data)) filters = make_unique_filter_dict(PlayerSeason, conv_data) season, created = PlayerSeason.objects.update_or_create(**filters, defaults=conv_data) if created: log.debug(("Created a new season: ", filters)) player_seasons.append(season) return player_seasons
def splits(self): prefix = "Player" if self.player_or_team == PlayerStats else "Team" model = get_model(prefix=prefix, middle=self.measure_type.replace( "Base", "Traditional"), suffix="Split") splits = [] for row in self.raw_data: data = auto_strip_and_convert_fields(model=model, data=row, make_instance=False) filter_dict = make_unique_filter_dict(model, data=data) split, created = model.objects.update_or_create(**filter_dict, defaults=data) if created: log.debug("Created a new split with the following parms:") log.debug(filter_dict) splits.append(split) return splits
def instantiate_correct_split_type(data): from nba_stats import models as nba_stats_models if "player" in data: entity_type = "Player" elif "team" in data: entity_type = "Team" else: raise Exception("Neither team nor player found in data") split_type = "Traditional" if data['measure_type'] == "Base" else data['measure_type'] class_name = entity_type + split_type + "Split" model = getattr(nba_stats_models, class_name) # This removes all fields in the data dict that aren't actually in the model. # This is to account for differences in naming, cruft, etc. This may unintentionally cover up # Some mistakes. final_data = {field.name: data[field.name] for field in model._meta.get_fields() if (field.name != 'id' and field.name in data)} try: find_args = make_unique_filter_dict(model, final_data) except Exception as e: log.debug(("INITIAL DATA", data)) log.debug(("FINAL DATA ", final_data)) log.debug(("CLASS NAME", class_name, "MODEL", model)) log.exception(e) raise e try: split, created = model.objects.update_or_create(**find_args, defaults=final_data) if created: log.debug("Created a nwew split with the following params:") log.debug(find_args) except Exception as e: log.debug(("INITIAL DATA", data)) log.debug(("FIND ARGS", find_args)) log.debug(("MODEL", model)) log.debug(("FINAL DATA", final_data)) log.exception(e) raise e return split
def tracking(self): tracks = [] for row in self.raw_data: # Something weird is happening here, but only in specific cases # Which are yet to be determined data = auto_strip_and_convert_fields(model=self.model, data=row, make_instance=False) filter_dict = make_unique_filter_dict(self.model, data=data) track, created = self.model.objects.update_or_create(**filter_dict, defaults=data) if created: log.debug( "Created a new tracking record with the following parms:") log.debug(filter_dict) tracks.append(track) return tracks
def shotcharts(self, game_ids=None): shotchart_details = [] team = None game = None for detail in self.raw_data: if game_ids is not None and detail['GAME_ID'] not in game_ids: continue detail['PLAYER'] = self.player if team is None or detail['TEAM_ID'] != team.team_id: log.debug(detail['TEAM_ID']) team = Team.objects.get(team_id=detail['TEAM_ID']) log.debug(team) detail['TEAM'] = team if game is None or detail['GAME_ID'] != getattr(game, 'game_id', None): try: game = Game.objects.get(game_id=detail['GAME_ID']) except Exception as e: log.debug(("DATA", detail)) log.exception(e) raise e detail['GAME'] = game converted_dict = convert_dict_keys_to_lowercase(detail) filter_dict = make_unique_filter_dict(PlayerShotChartDetail, converted_dict) shotchart_dtl, created = PlayerShotChartDetail.objects.get_or_create(**filter_dict, defaults=converted_dict) if created: log.debug(("Created a new shot chart detail: ", filter_dict)) shotchart_details.append(shotchart_dtl) return shotchart_details
def transactions(self): log.debug(("Beginning fetching transactions for ", self.player.display_first_last)) transactions = [] raw_transactions = self.raw_data.find_all(attrs={'class': "transaction"}) for rawt in raw_transactions: to_team = None from_team = None date_str, description = rawt.text.split(":") date_parts = date_str.replace(",", "").split() month = MONTHS[date_parts[0].lower()] trans_date = date(year=int(date_parts[2]), month=month, day=int(date_parts[1])) descr_parts = description.strip().split() if "trade" in description.lower(): transaction_type = "Traded" elif "announce" in description.lower(): transaction_type = "Retired" elif ("assigned" in description.lower() or "recalled" in description.lower()): # This is just D-League Shuffling. Move on. continue else: transaction_type = descr_parts[0] try: to_team_tag = rawt.find(self._to_team) if to_team_tag: # TODO: Update teams to account for these abbreviations. # Not sure how much perf will be gained though to_team_abb = to_team_tag.attrs.get('data-attr-to') if to_team_abb in ["NOH", "NOK"]: to_team_abb = "NOP" elif to_team_abb == "NJN": to_team_abb = "BKN" elif to_team_abb == "VAN": to_team_abb = "MEM" elif to_team_abb == "WSB": to_team_abb = "WAS" elif to_team_abb == "SEA": to_team_abb = "OKC" to_team = Team.objects.get(Q(bbref_abbreviation=to_team_abb) | Q(abbreviation=to_team_abb)) from_team_tag = rawt.find(self._from_team) if from_team_tag: from_team_abb = from_team_tag.attrs.get('data-attr-from') if from_team_abb in ["NOH", "NOK"]: from_team_abb = "NOP" elif from_team_abb == "NJN": from_team_abb = "BKN" elif from_team_abb == "VAN": from_team_abb = "VAN" elif from_team_abb == "WSB": from_team_abb = "WAS" elif from_team_abb == "SEA": from_team_abb = "OKC" from_team = Team.objects.get(Q(bbref_abbreviation=from_team_abb) | Q(abbreviation=from_team_abb)) except Exception as e: # Most likely just came across a player being assigned to the D-League log.debug(("player", self.player.display_first_last, description)) log.exception(e) raise e data = {'player': self.player, 'from_team': from_team, 'to_team':to_team, 'transaction_date': trans_date, 'transaction_type': transaction_type, 'description': description.strip()} filter_dict = make_unique_filter_dict(Transaction, data) try: transaction, created = Transaction.objects.get_or_create(**filter_dict, defaults=data) except Exception as e: log.debug(("FILTER DICT", filter_dict)) log.exception(e) raise e transactions.append(transaction) log.debug(("completed fetching transactions for ", self.player.display_first_last)) return transactions