diff --git a/espn_api/baseball/box_player.py b/espn_api/baseball/box_player.py new file mode 100644 index 00000000..2e6f3266 --- /dev/null +++ b/espn_api/baseball/box_player.py @@ -0,0 +1,35 @@ +from .constant import POSITION_MAP, PRO_TEAM_MAP +from .player import Player +from datetime import datetime, timedelta + + +class BoxPlayer(Player): + '''player with extra data from a matchup''' + def __init__(self, data, pro_schedule, week, year): + super(BoxPlayer, self).__init__(data, year) + self.slot_position = 'FA' + self.pro_opponent = "None" # professional team playing against + self.pro_pos_rank = 0 # rank of professional team against player position + self.game_played = 100 # 0-100 for percent of game played + self.on_bye_week = False + + if 'lineupSlotId' in data: + self.slot_position = POSITION_MAP[data['lineupSlotId']] + + player = data['playerPoolEntry']['player'] if 'playerPoolEntry' in data else data['player'] + if player['proTeamId'] in pro_schedule: + (opp_id, date) = pro_schedule[player['proTeamId']] + self.game_date = datetime.fromtimestamp(date/1000.0) + self.game_played = 100 if datetime.now() > self.game_date + timedelta(hours=3) else 0 + self.pro_opponent = PRO_TEAM_MAP[opp_id] + else: # bye week + self.on_bye_week = True + + stats = self.stats.get(week, {}) + self.points = stats.get('points', 0) + self.points_breakdown = stats.get('breakdown', 0) + self.projected_points = stats.get('projected_points', 0) + self.projected_breakdown = stats.get('projected_breakdown', 0) + + def __repr__(self): + return f'Player({self.name}, points:{self.points}, projected:{self.projected_points})' diff --git a/espn_api/baseball/box_score.py b/espn_api/baseball/box_score.py index 628cccc2..29e27181 100644 --- a/espn_api/baseball/box_score.py +++ b/espn_api/baseball/box_score.py @@ -1,4 +1,5 @@ from abc import ABC, abstractmethod +from .box_player import BoxPlayer from .constant import STATS_MAP @@ -34,7 +35,7 @@ def __repr__(self): class H2HCategoryBoxScore(BoxScore): '''Boxscore class for head to head categories leagues''' - def __init__(self, data): + def __init__(self, data, pro_schedule, year, scoring_period = 0): super().__init__(data) def _process_team(self, team_data, is_home_team): @@ -68,9 +69,29 @@ def _process_team(self, team_data, is_home_team): class H2HPointsBoxScore(BoxScore): '''Boxscore class for head to head points leagues''' - def __init__(self, data): + def __init__(self, data, pro_schedule, year, scoring_period = 0): super().__init__(data) + (self.home_team, self.home_score, self.home_projected, self.home_lineup) = self._get_team_data('home', data, pro_schedule, scoring_period, year) + + (self.away_team, self.away_score, self.away_projected, self.away_lineup) = self._get_team_data('away', data, pro_schedule, scoring_period, year) + def _process_team(self, team_data, is_home_team): super()._process_team(team_data, is_home_team) # TODO implement setting the scores + + def _get_team_data(self, team, data, pro_schedule, week, year): + if team not in data: + return (0, 0, -1, []) + + team_id = data[team]['teamId'] + team_projected = -1 + if 'totalPointsLive' in data[team]: + team_score = round(data[team]['totalPointsLive'], 2) + team_projected = round(data[team].get('totalProjectedPointsLive', -1), 2) + else: + team_score = round(data[team]['totalPoints'], 2) + team_roster = data[team].get('rosterForCurrentScoringPeriod', {}).get('entries', []) + team_lineup = [BoxPlayer(player, pro_schedule, week, year) for player in team_roster] + + return (team_id, team_score, team_projected, team_lineup) diff --git a/espn_api/baseball/league.py b/espn_api/baseball/league.py index 7ddda8ee..9fed45d5 100644 --- a/espn_api/baseball/league.py +++ b/espn_api/baseball/league.py @@ -136,7 +136,7 @@ def free_agents(self, week: int=None, size: int=50, position: str=None, position data = self.espn_request.league_get(params=params, headers=headers) players = data['players'] - return [Player(player) for player in players] + return [Player(player, self.year) for player in players] def box_scores(self, matchup_period: int = None, scoring_period: int = None) -> List[Union[BoxScore, H2HCategoryBoxScore]]: '''Returns list of box score for a given matchup or scoring period''' @@ -159,9 +159,10 @@ def box_scores(self, matchup_period: int = None, scoring_period: int = None) -> filters = {"schedule":{"filterMatchupPeriodIds":{"value":[matchup_id]}}} headers = {'x-fantasy-filter': json.dumps(filters)} data = self.espn_request.league_get(params=params, headers=headers) + pro_schedule = self._get_pro_schedule(scoring_id) schedule = data['schedule'] - box_data = [self._box_score_class(matchup) for matchup in schedule] + box_data = [self._box_score_class(matchup, pro_schedule, self.year, scoring_id) for matchup in schedule] for team in self.teams: for matchup in box_data: diff --git a/espn_api/baseball/player.py b/espn_api/baseball/player.py index 86161a61..d02aceac 100644 --- a/espn_api/baseball/player.py +++ b/espn_api/baseball/player.py @@ -4,7 +4,7 @@ class Player(object): '''Player are part of team''' - def __init__(self, data): + def __init__(self, data, year): self.name = json_parsing(data, 'fullName') self.playerId = json_parsing(data, 'id') self.position = POSITION_MAP.get(json_parsing(data, 'defaultPositionId') - 1, json_parsing(data, 'defaultPositionId') - 1) @@ -15,10 +15,28 @@ def __init__(self, data): self.injuryStatus = json_parsing(data, 'injuryStatus') self.stats = {} - # add available stats player = data.get('playerPoolEntry', {}).get('player') or data['player'] self.injuryStatus = player.get('injuryStatus', self.injuryStatus) self.injured = player.get('injured', False) + + # add available stats + player_stats = player.get('stats', []) + for stats in player_stats: + if stats.get('seasonId') != year: + continue + stats_breakdown = stats.get('stats') or stats.get('appliedStats', {}) + breakdown = {STATS_MAP.get(int(k), k):v for (k,v) in stats_breakdown.items()} + points = round(stats.get('appliedTotal', 0), 2) + scoring_period = stats.get('scoringPeriodId') + stat_source = stats.get('statSourceId') + (points_type, breakdown_type) = ('points', 'breakdown') if stat_source == 0 else ('projected_points', 'projected_breakdown') + if self.stats.get(scoring_period): + self.stats[scoring_period][points_type] = points + self.stats[scoring_period][breakdown_type] = breakdown + else: + self.stats[scoring_period] = {points_type: points, breakdown_type: breakdown} + self.total_points = self.stats.get(0, {}).get('points', 0) + self.projected_total_points = self.stats.get(0, {}).get('projected_points', 0) def __repr__(self): return 'Player(%s)' % (self.name, ) diff --git a/espn_api/baseball/team.py b/espn_api/baseball/team.py index fc7e7901..ed0d81d5 100644 --- a/espn_api/baseball/team.py +++ b/espn_api/baseball/team.py @@ -27,20 +27,20 @@ def __init__(self, data, member, roster, schedule, year, **kwargs): if 'logo' in data: self.logo_url = data['logo'] - self._fetch_roster(roster) + self._fetch_roster(roster, year) self._fetch_schedule(schedule) def __repr__(self): return f'Team({self.team_name})' - def _fetch_roster(self, data): + def _fetch_roster(self, data, year): '''Fetch teams roster''' self.roster.clear() roster = data['entries'] for player in roster: - self.roster.append(Player(player)) + self.roster.append(Player(player, year)) def _fetch_schedule(self, data): diff --git a/tests/baseball/integration/test_league.py b/tests/baseball/integration/test_league.py index c1a8b436..03f93c16 100644 --- a/tests/baseball/integration/test_league.py +++ b/tests/baseball/integration/test_league.py @@ -23,7 +23,7 @@ def test_league_free_agents(self): self.assertNotEqual(len(free_agents), 0) def test_league_box_scores(self): - box_scores = self.league.box_scores(1) + box_scores = self.league.box_scores(0) self.assertNotEqual(len(box_scores), 0)