Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions espn_api/base_league.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,23 @@ def _get_all_pro_schedule(self):
pro_team_schedule[team['id']] = pro_game
return pro_team_schedule

def _get_offers(self, week: int = None):
'''Returns a list of free agent auction bids'''
if week is None:
bids = []
for week in range(0, 18):
data = self.espn_request.get_league_offers(week=week)
transactions = data.get('transactions', [])
if transactions: # Only append non-empty transaction lists
for t in transactions:
bids.append(t)
else:
data = self.espn_request.get_league_offers(week=week)
bids = data.get('transactions', [])
print(bids)

return bids

def standings(self) -> List:
standings = sorted(self.teams, key=lambda x: x.final_standing if x.final_standing != 0 else x.standing, reverse=False)
return standings
Expand Down
54 changes: 54 additions & 0 deletions espn_api/football/league.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .box_player import BoxPlayer
from .player import Player
from .activity import Activity
from .offer import Offer
from .settings import Settings
from .utils import power_points, two_step_dominance
from .constant import POSITION_MAP, ACTIVITY_MAP, TRANSACTION_TYPES
Expand Down Expand Up @@ -422,3 +423,56 @@ def transactions(self, scoring_period: int = None, types: Set[str] = {"FREEAGENT
transactions = data['transactions']

return [Transaction(transaction, self.player_map, self.get_team_data) for transaction in transactions]

def offers_report(self, week: int = None) -> List[Offer]:
'''Returns a list of all waiver/free agent auction offers sorted by timestamp and bid amount'''

data = self._get_offers(week)
bids = [Offer(bid, self.player_map, self.get_team_data) for bid in data]

if len(bids) == 0:
return []

# Process bids to fix missing timestamps
# For any bid without a timestamp, search for another bid for the same player
# from the same team that has a timestamp and use that timestamp
for bid in bids:
if bid.result != 'Canceled' and bid.time is None:
for other_bid in bids:
if bid.id != other_bid.id and other_bid.time is not None:
if other_bid.player == bid.player and other_bid.teamId == bid.teamId:
bid.time = other_bid.time
break

# Group bids by report_time
reports = {}
for bid in bids:
if bid.time not in reports:
reports[bid.time] = []
reports[bid.time].append(bid)

# Sort report times
sorted_report_times = sorted([t for t in reports.keys() if t is not None])

# Create a sorted list of offers, with the highest bid for each player first
sorted_offers = []
for report_time in sorted_report_times:
report = reports[report_time]
# Sort by bid amount (highest first)
report.sort(reverse=True)

# Process the bids in order
processed_players = set()
for bid in report:
# If this player hasn't been processed yet, add all related bids
if bid.player not in processed_players:
sorted_offers.append(bid)
processed_players.add(bid.player)

# Find and add all other bids for the same player
for other_bid in report:
if other_bid.id != bid.id and other_bid.player == bid.player:
sorted_offers.append(other_bid)

return sorted_offers

64 changes: 64 additions & 0 deletions espn_api/football/offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from datetime import datetime


class Offer(object):
def __init__(self, data, player_map, get_team_data):
status = data['status']
self.id = data['id']
self.time = None
if status == 'CANCELED':
self.result = 'Canceled'
else:
if status == 'EXECUTED':
self.result = 'Processed'
elif status == 'FAILED_INVALIDPLAYERSOURCE':
self.result = 'Outbid'
elif status == 'FAILED_AUCTIONBUDGETEXCEEDED':
self.result = 'Budget Exceeded'
elif status == 'FAILED_POSITIONLIMIT':
self.result = 'Position Limit Exceeded'
elif status == 'FAILED_ROSTERLOCK':
self.result = 'Failed Due to Roster Lock'
elif status == 'FAILED_PLAYERALREADYDROPPED' or status == 'FAILED_ROSTERLIMIT' or status == 'PENDING':
self.result = 'Player already dropped'
else:
self.result = status
# fixes bug with unprocessed waivers stuck on "PENDING" status
if 'processDate' in data:
self.time = datetime.fromtimestamp(int(data['processDate'] / 1000)) # convert from milliseconds to seconds
self.amount = data['bidAmount']
self.teamId = data['teamId']
self.dropped_player = None
for item in data['items']:
if item['type'] == 'ADD':
self.player = item['playerId']
elif item['type'] == 'DROP' and self.result == 'Processed':
self.dropped_player = item['playerId']

def __lt__(self, other):
# sort by status, then bid amount
result_ranking = {'Processed': 7,
'Outbid': 6,
'Player already dropped': 5,
'Budget Exceeded': 4,
'Position Limit Exceeded': 3,
'Failed Due to Roster Lock': 2,
'CANCELLED': 1,
'PENDING': 0}
if result_ranking[self.result] != result_ranking[other.result]:
return result_ranking[self.result] < result_ranking[other.result]
else:
# sort by bid amount
return self.amount < other.amount

def __repr__(self):
if self.result == 'Canceled':
return 'Canceled bid'
else:
ret_string = 'Offer(Date:{0}, Player:{1}, Team:{2}, Result:{3}, Bid:{4}'.format(self.time, self.player, self.teamId,
self.result, self.amount)
if self.dropped_player:
ret_string += ', Dropped:{0})'.format(self.dropped_player)
else:
ret_string += ')'
return ret_string
13 changes: 13 additions & 0 deletions espn_api/requests/espn_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ def get_league_message_board(self, msg_types = None):
data = self.get(params=params, extend=extend, headers=headers)
return data

def get_league_offers(self, week: int):
'''Gets the league offers reports'''
params = {
'scoringPeriodId': week,
'view': 'mTransactions2'
}

filters = {"transactions": {"filterType": {"value": ["WAIVER", "WAIVER_ERROR"]}}}
headers = {'x-fantasy-filter': json.dumps(filters)}

data = self.league_get(params=params, headers=headers)
return data

def get_player_card(self, playerIds: List[int], max_scoring_period: int, additional_filters: List = None):
'''Gets the player card'''
params = { 'view': 'kona_playercard' }
Expand Down