def fetch_raw_data(self, season=None, season_type=REGULAR_SEASON, measure_type=BASE, per_mode=TOTALS): if season is None: season = make_season_str(determine_season_for_date(date.today())) log.debug(("Fetching raw data for: ", self.team, season, season_type, measure_type, per_mode)) self.raw_data = [] if self.summary is None: log.debug("Don't have a summary yet. Fetching it.") summary = TeamPlayerOnOffSummary(team_id=self.team.team_id, measure_type=measure_type, per_mode=per_mode, season=str(season), season_type=season_type) self.summary = summary.json detail = TeamPlayerOnOffDetail(team_id=self.team.team_id, measure_type=measure_type, per_mode=per_mode, season=str(season), season_type=season_type) self.detail = detail.json self.raw_data = [self.summary, self.detail]
def shot_chart(request): active_players = Player.active_players.all() cur_year = determine_season_for_date(date.today()) seasons = {} for year in range(2001, cur_year + 1): seasons[year] = make_season_str(year) context = {'players': active_players, 'seasons': seasons} return render(request, "nba_stats/shot_chart.html", context)
def create_play_by_play_for_game(game): log.debug("Creating Play By Play Events for Game " + str(game.game_id)) pbp_events = [] url = (NBA_BASE_URL + PBP_URL).format(game_id=game.game_id, season=make_season_str(game.season), season_type='foo') json_data = get_json_response(url) pbp_data = json_data['resultSets'][0] headers = pbp_data['headers'] for pbp_event in pbp_data['rowSet']: temp_dict = dict(zip(headers, pbp_event)) temp_dict['GAME'] = game # TODO: Write a method that will look for a player and if it doesn't find, creates it. # TODO: The method should then return the player object if temp_dict['PLAYER1_NAME']: player1 = Player.objects.filter( player_id=temp_dict['PLAYER1_ID']).first() if not player1: player1 = Player(player_id=temp_dict['PLAYER1_ID'], display_first_last=temp_dict['PLAYER1_NAME']) player1.save() temp_dict['PLAYER1'] = player1 if temp_dict['PLAYER1_TEAM_ID']: temp_dict['PLAYER1_TEAM'] = Team.objects.filter( team_id=temp_dict['PLAYER1_TEAM_ID']).first() if temp_dict['PLAYER2_NAME']: player2 = Player.objects.filter( player_id=temp_dict['PLAYER2_ID']).first() if not player2: player2 = Player(player_id=temp_dict['PLAYER2_ID'], display_first_last=temp_dict['PLAYER2_NAME']) player2.save() temp_dict['PLAYER2'] = player2 if temp_dict['PLAYER2_TEAM_ID']: temp_dict['PLAYER2_TEAM'] = Team.objects.filter( team_id=temp_dict['PLAYER2_TEAM_ID']).first() if temp_dict['PLAYER3_NAME']: player3 = Player.objects.filter( player_id=temp_dict['PLAYER3_ID']).first() if not player3: player3 = Player(player_id=temp_dict['PLAYER3_ID'], display_first_last=temp_dict['PLAYER1_NAME']) player3.save() temp_dict['PLAYER3'] = player3 if temp_dict['PLAYER3_TEAM_ID']: temp_dict['PLAYER3_TEAM'] = Team.objects.filter( team_id=temp_dict['PLAYER3_TEAM_ID']).first() if temp_dict['SCOREMARGIN'] == 'TIE': temp_dict['SCOREMARGIN'] = 0 pbp_create_data = convert_dict_keys_to_lowercase(temp_dict) pbp_obj = PlayByPlayEvent(**pbp_create_data) pbp_events.append(pbp_obj) return pbp_events
def fetch_raw_data(self, player, season=None): self.player = player if season is None: season = make_season_str(determine_season_for_date(date.today())) log.debug("Pre network call") shot_chart = ShotChart(player_id=player.player_id, season=str(season)) log.debug("post network call") scdtl_dicts = dictify(shot_chart.json['resultSets'][0]) self.raw_data = scdtl_dicts
def create_all_shotchart_details_player(player): player_scdtls = [] # I *think* it should be + 1 for year in range(2001, player.to_year + 1): team = None for season_type in ["Regular Season", "Playoffs"]: season_str = make_season_str(year) log.debug("Season: " + season_str) raw_json = get_player_shotchart(player, season_str, season_type=season_type) # log.debug("Raw JSON: \n" + str(raw_json)) player_scdtls += create_player_shotchart_details_from_json(player, raw_json) return player_scdtls
def fetch_raw_data(self, season=None, season_type=REGULAR_SEASON, player_or_team="P"): if season is None: season = make_season_str(determine_season_for_date(date.today())) self.entity_type = Player if player_or_team == "P" else Team log.debug(("Fetching game logs for ", season, season_type, self.entity_type.__name__)) gl = GameLog(season=season, season_type=season_type, player_or_team=player_or_team) result_set = gl.json['resultSets'][0] self.raw_data = dictify(result_set)
def fetch_raw_data(self, season=None, measure_type="Base", per_mode=TOTALS, season_type=REGULAR_SEASON, group_quantity=5): self.measure_type = measure_type self.model = get_model(prefix=self.measure_type, suffix="Lineup") self.raw_data = [] if measure_type in [USAGE, DEFENSE]: raise ValueError("Usage is not a valid measure type for lineups.") if season is None: season = make_season_str(determine_season_for_date(date.today())) log.debug(("Fetching data", season, season_type, measure_type, per_mode, group_quantity)) # Really hope this respects season type. I've seen scenarios where it doesn't lineup = Lineups(season=str(season), season_type=season_type, per_mode=per_mode, group_quantity=group_quantity, measure_type=measure_type) resp_json = lineup.json parms = resp_json['parameters'] result_set = resp_json['resultSets'][0] lineup_rows = dictify(result_set) for row in lineup_rows: row['TEAM'] = Team.objects.get(team_id=int(row['TEAM_ID'])) row['SEASON_ID'] = make_season_int(parms['Season']) row['MEASURE_TYPE'] = parms['MeasureType'] row['SEASON_TYPE'] = parms['SeasonType'] row['PER_MODE'] = parms['PerMode'] row['GROUP_QUANTITY'] = parms['GroupQuantity'] row['SEASON'] = season if measure_type == "Misc": row['PTS_SECOND_CHANCE'] = row['PTS_2ND_CHANCE'] row['OPP_PTS_SECOND_CHANCE'] = row['OPP_PTS_2ND_CHANCE'] elif measure_type == "Scoring": row['PCT_PTS_2PT_MIDRANGE'] = row['PCT_PTS_2PT_MR'] proc_row = convert_dict_keys_to_lowercase(row) self.raw_data.append(proc_row)
def create_update_all_splits_for_entity(entity, year=None, season_type="Regular Season"): splits = {'Base': [], 'Advanced': [], 'Misc': [], 'Scoring': [], 'Usage': [], 'Shooting': []} parms = GENERAL_SPLITS_PARMS if isinstance(entity, Player): parms['PlayerID'] = ent_nba_id = entity.player_id endpoint = PLAYER_GENERAL_SPLITS_ENDPOINT shooting_endpoint = PLAYER_SHOOTING_SPLITS_ENDPOINT elif isinstance(entity, Team): parms['TeamID'] = ent_nba_id = entity.team_id endpoint = TEAM_GEN_SPLITS_ENDPOINT shooting_endpoint = TEAM_SHOOTING_SPLITS_ENDPOINT else: raise Exception("What are you doing. This function requires a Player or Team.") # teams default to 1996-2015-16 season first_year = getattr(entity, 'from_year', None) or 1996 first_year = 1996 if first_year < 1996 else first_year final_year = getattr(entity, 'to_year', None) or date.today().year if year is not None: if year < first_year or year > final_year: raise ValueError("You passed an invalid year: {yr}. " "Year must be between {first} and {last} " "for {ent}.".format(yr=year, first=first_year, last=final_year, ent=str(entity))) else: first_year = year final_year = year + 1 # Need to loop over every measure_type, per_mode, season, season_type # Could cut this down to Totals & Per100, then calculate everything else. # That cuts the requests in half. Could also jut get box scores, but I think that would # Make it tough (impossible) to get/do per possession data. for per_mode in ['Totals', 'Per100Possessions']: parms['PerMode'] = per_mode parms['SeasonType'] = season_type for cur_year in range(first_year, final_year): parms['Season'] = make_season_str(cur_year) # This is probably the most effective place to make a cut, # But I'm not sure if it can be done. for measure_type in ['Base', 'Advanced', 'Misc', 'Scoring', 'Usage']: parms['MeasureType'] = measure_type log.debug((ent_nba_id, cur_year, season_type, per_mode, measure_type)) url = NBA_BASE_URL + endpoint # Temp. for Hornets try: # This is where like 90% of the time is being spent data = get_json_response(url, parms) except Exception as e: log.exception(e) continue entity_splits = create_update_split_from_raw_json(entity, data) splits[measure_type] += entity_splits url = NBA_BASE_URL + shooting_endpoint # I don't think this actually matters parms['MeasureType'] = "Base" data = get_json_response(url, parms) log.debug((ent_nba_id, cur_year, season_type, per_mode, "Shooting")) shooting_splits = create_update_split_from_raw_json(entity, data) splits['Shooting'] += shooting_splits return splits
from django import forms from datetime import date from nba_stats.utils import make_season_str PLAYER_SPLIT_TYPE_CHOICES = [("Traditional", "Traditional"), ("Advanced", "Advanced"), ("Misc", "Misc"), ("Shooting", "Shooting"), ("Usage", "Usage"), ("Scoring", "Scoring")] SEASON_CHOICES = [(str(year), make_season_str(year)) for year in range(1996, date.today().year)] class GameUpdateForm(forms.Form): begin_date = forms.DateField() end_date = forms.DateField() class SplitSearchForm(forms.Form): season_id = forms.ChoiceField(SEASON_CHOICES, required=False) season_type = forms.CharField(max_length=50, required=False, initial="Regular Season") split_type = forms.ChoiceField(PLAYER_SPLIT_TYPE_CHOICES, required=False) per_mode = forms.CharField(max_length=50, required=False, initial="PerGame") order_by = forms.CharField(max_length=50, required=False) class UserQueryForm(forms.Form):
def create_box_scores_for_game(game, url_suffix, season_type="Regular+Season", box_type="Traditional"): player_box_scores = [] team_box_scores = [] url = (NBA_BASE_URL + url_suffix).format(game_id=game.game_id, season=make_season_str( game.season), season_type=season_type) data = get_json_response(url) if box_type == "Hustle": hustle_status = data['resultSets'][0]['rowSet'][0][1] if not hustle_status: player_stats = None else: player_stats = data['resultSets'][1] else: player_stats = data['resultSets'][0] if player_stats: player_headers = player_stats['headers'] if box_type == "Hustle": team_stats = data['resultSets'][2] else: team_stats = data['resultSets'][1] team_headers = team_stats['headers'] for p in player_stats['rowSet']: temp_dict = dict(zip(player_headers, p)) temp_dict['GAME'] = game temp_dict['TEAM'] = Team.objects.filter( team_id=temp_dict['TEAM_ID']).first() player = Player.objects.filter( player_id=temp_dict['PLAYER_ID']).first() if not player: # TODO: Properly handle the situation where the given player doesn't exist yet log.debug("Player id and name about to look up: %s %s" % (temp_dict['PLAYER_ID'], temp_dict['PLAYER_NAME'])) # Laziest possible player creation... # should probably write a script that goes through the db and # attempts to fill in missing player data player = Player(display_first_last=temp_dict['PLAYER_NAME'], player_id=temp_dict['PLAYER_ID'], team=temp_dict['TEAM']) player.save() temp_dict['PLAYER'] = player if box_type == "Tracking": converted_dict = convert_tracking_dict_to_nbapex_fields( temp_dict, player_flg=True) else: converted_dict = temp_dict p_box_data = convert_dict_keys_to_lowercase(converted_dict) if box_type == 'Hustle': p_box_data['minutes'] = convert_min_sec_to_float( p_box_data['minutes']) else: p_box_data['min'] = convert_min_sec_to_float(p_box_data['min']) pbox = create_correct_type_of_player_box_score( p_box_data, box_type) player_box_scores.append(pbox) for t in team_stats['rowSet']: temp_dict = dict(zip(team_headers, t)) temp_dict['GAME'] = game temp_dict['TEAM'] = Team.objects.filter( team_id=temp_dict['TEAM_ID']).first() if box_type == 'Tracking': converted_dict = convert_tracking_dict_to_nbapex_fields( temp_dict, player_flg=False) else: converted_dict = temp_dict t_box_data = convert_dict_keys_to_lowercase(converted_dict) if box_type == "Hustle": t_box_data['minutes'] = convert_min_sec_to_float( t_box_data['minutes']) else: t_box_data['min'] = convert_min_sec_to_float(t_box_data['min']) tbox = create_correct_type_of_team_box_score(t_box_data, box_type) team_box_scores.append(tbox) else: log.debug("Box scores of type {bt} not available for game {gm}".format( bt=box_type, gm=game.game_id)) ret_dict = {'players': player_box_scores, 'teams': team_box_scores} return ret_dict
def __init__(self, position, lup_date, scoring_settings, entry=None): # TODO: Right now scoring fields will come out in random order. # Maybe we can assign an ordering at creation of scoring settings? self.position = position self.display_position = POSITION_ORDER.get(position)[1] self.matchup = "" self.matchup_status = "" if entry is None: self.player = "None" self.player_id = 0 self.team = "N/A" self.eligibility_classes = " ".join( ["elig-" + str(x) for x in POSITION_ORDER.get(position)[2]]) for fld in scoring_settings.scoring_fields_vals: setattr(self, fld, "") else: self.player = entry.player.display_first_last self.player_id = entry.player.id self.team = entry.player.team.abbreviation self.eligibility_classes = " ".join([ "elig-" + x for x in entry.player.numbered_positions.split(",")[:-1] ]) base_box_score = PlayerTraditionalBoxScore.objects.filter( player=entry.player, game__game_date_est=lup_date) if base_box_score.exists(): self.matchup = base_box_score.first().matchup self.matchup_status = base_box_score.first( ).game.game_status_text split_fields_dict = defaultdict(list) for fld in scoring_settings.scoring_fields_vals: split_type, field = fld.split("__") split_fields_dict[split_type].append(field) for split_type in split_fields_dict: fields = split_fields_dict[split_type] if split_type in [ 'PlayerTracking', 'PlayerFourFactors', 'PlayerHustleStats' ]: suffix = "BoxScore" for fld in fields: setattr(self, split_type + "__" + fld, "TODO") continue else: suffix = "Split" model = get_model(middle=split_type, suffix=suffix) year = determine_season_for_date(lup_date) season = make_season_str(year) season_long_vals = model.objects.filter( season_id=year, player=entry.player, season_type="Regular Season", per_mode="PerGame", group_set="Overall", group_value=season).values(*fields) if season_long_vals.exists(): split = season_long_vals.first() for fld in fields: log.debug((split_type, fld, split[fld])) setattr(self, split_type + "__" + fld, split[fld])
def fetch_raw_data(self, season=None, season_type=REGULAR_SEASON, pt_measure_type=SPEED_DISTANCE, per_mode=TOTALS, group_set="Overall", group_value=None): self.raw_data = [] self.pt_measure_type = pt_measure_type if self.pt_measure_type in ["CatchShoot", "PullUpShot"]: middle = "ShotType" elif "Touch" in self.pt_measure_type or "Drive" in self.pt_measure_type: middle = "Touch" else: middle = self.pt_measure_type self.model = get_model(prefix="Player", middle=middle, suffix="Tracking") # Silly way to do this, I know url = self.base_url + self.endpoint if season is None: season = make_season_str(determine_season_for_date(date.today())) if group_set == "Overall" and group_value is None: group_value = season self.params['Season'] = str(season) self.params['SeasonType'] = season_type self.params['PerMode'] = per_mode self.params['PtMeasureType'] = pt_measure_type if group_set != "Overall": self.params[group_set] = group_value if group_set != "Month": group_value = GROUP_VALUES[group_value] log.debug(("Fetching Player Stats: ", season, season_type, pt_measure_type, per_mode, group_set, group_value)) raw_json = get_json_response(url, self.params) rset = raw_json['resultSets'][0] player_rows = dictify(result_set=rset) processed_rows = [] for row in player_rows: row['PLAYER'] = Player.objects.get(player_id=row['PLAYER_ID']) row['GROUP_SET'] = group_set row['SEASON'] = season row['SEASON_TYPE'] = season_type row['PT_MEASURE_TYPE'] = pt_measure_type row['PER_MODE'] = per_mode if group_set == "Month": row['GROUP_VALUE'] = REVERSE_MONTH_MAP[group_value] else: row['GROUP_VALUE'] = group_value if self.pt_measure_type in ["CatchShoot", "PullUpShot"]: row = convert_shot_type_dict_to_apex(row) elif "Touch" in self.pt_measure_type or "Drive" in self.pt_measure_type: row = convert_touch_dict_to_apex(row) proc_row = convert_dict_keys_to_lowercase( row, override_list=['GROUP_SET', 'GROUP_VALUE']) processed_rows.append(proc_row) self.raw_data = processed_rows
def fetch_raw_data(self, player_or_team=PlayerStats, season=None, season_type=REGULAR_SEASON, measure_type=BASE, per_mode=TOTALS, group_set="Overall", group_value=None): self.measure_type = measure_type self.player_or_team = player_or_team if season is None: season = make_season_str(determine_season_for_date(date.today())) if group_set == "Overall" and group_value is None: group_value = season entity = "Player" if self.player_or_team == PlayerStats else "Team" log.debug( ("Fetching {entity} Stats: ".format(entity=entity), season, season_type, measure_type, per_mode, group_set, group_value)) if group_set != "Overall": if group_set != "Month": group_value = GROUP_VALUES[group_value] kwargs = {GROUP_SETS[group_set]: group_value} else: kwargs = {} stats = player_or_team(season=str(season), season_type=season_type, measure_type=measure_type, per_mode=per_mode, **kwargs) raw_json = stats.json rset = raw_json['resultSets'][0] stat_rows = dictify(result_set=rset) for row in stat_rows: if player_or_team == PlayerStats: row['PLAYER'] = Player.objects.get(player_id=row['PLAYER_ID']) else: row['TEAM'] = Team.objects.get(team_id=row['TEAM_ID']) row['GROUP_SET'] = group_set row['SEASON'] = season row['SEASON_TYPE'] = season_type row['MEASURE_TYPE'] = measure_type row['PER_MODE'] = per_mode if group_set == "Month": row['GROUP_VALUE'] = REVERSE_MONTH_MAP[group_value] else: row['GROUP_VALUE'] = group_value if measure_type == "Misc": row['PTS_SECOND_CHANCE'] = row['PTS_2ND_CHANCE'] row['OPP_PTS_SECOND_CHANCE'] = row['OPP_PTS_2ND_CHANCE'] elif measure_type == "Scoring": row['PCT_PTS_2PT_MIDRANGE'] = row['PCT_PTS_2PT_MR'] elif measure_type == "Shooting": if row['GROUP_SET'] == "Assisted By": row['GROUP_VALUE'] = row['PLAYER_NAME'] stat_rows = [ convert_dict_keys_to_lowercase( row, override_list=['GROUP_SET', 'GROUP_VALUE']) for row in stat_rows ] self.raw_data = stat_rows