def test_tie_goes_to_highest_priority_two_ties(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster2 = Roster(id="2", name="team 2", rank=2, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, amount=5)) roster2.waiver_bids.append( WaiverBid(roster_id=roster2.id, player=player1, amount=5)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player2, amount=5)) roster2.waiver_bids.append( WaiverBid(roster_id=roster2.id, player=player2, amount=5)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1, roster2]) assert roster1.waiver_bids[ 0].result == WaiverBidResult.FailedLowerPriority, "Assert 1 failed" assert roster2.waiver_bids[ 0].result == WaiverBidResult.SuccessPending, "Assert 2 failed" assert roster1.waiver_bids[ 1].result == WaiverBidResult.SuccessPending, "Assert 3 failed" assert roster2.waiver_bids[ 1].result == WaiverBidResult.FailedLowerPriority, "Assert 4 failed"
def test_sort_roster(rosters: List[Roster], first): for roster in rosters: roster.wl_points = Roster.calculate_wl_points(roster) rosters = Roster.sort(rosters) assert rosters[0].name == first
def test_random_winner(): rosters = [Roster(name="one"), Roster(name="two")] winners = [] for x in range(1000): rosters = Roster.sort(rosters) sleep(0.001) winners.append(rosters[0].name) assert "one" in winners assert "two" in winners
def update_record(roster: Roster, up_to_week: int, schedule: Schedule, league_start_week: int): wins = 0 losses = 0 ties = 0 total_score_for = 0.0 total_score_against = 0.0 last_result = "-" for week in schedule.weeks: if week.week_number < league_start_week: continue if week.week_number > up_to_week or week.week_type != WeekType.REGULAR: break matchup = next(m for m in week.matchups if m.away and m.away.id == roster.id or m.home and m.home.id == roster.id) if matchup: score_for = matchup.away_score if matchup.away and matchup.away.id == roster.id else matchup.home_score score_against = matchup.home_score if matchup.away and matchup.away.id == roster.id else matchup.away_score total_score_for += score_for total_score_against += score_for won = score_for > score_against lost = score_for < score_against tied = score_for == score_against if won: wins += 1 last_result = "W" if lost: losses += 1 last_result = "L" if tied: ties += 1 last_result = "T" roster.wins = wins roster.losses = losses roster.ties = ties roster.record = Roster.format_record(roster) roster.wl_points = Roster.calculate_wl_points(roster) roster.last_week_result = last_result roster.points_for = total_score_for roster.points_against = total_score_against
def test_waiver_priority_is_reverse_rank(): roster1 = Roster(id="1", name="team 1", rank=1) roster2 = Roster(id="2", name="team 2", rank=3) roster3 = Roster(id="3", name="team 3", rank=4) roster4 = Roster(id="4", name="team 4", rank=2) rosters = [roster1, roster2, roster3, roster4] target = WaiverService(get_roster_player_service()) waiver_priority = target.get_initial_waiver_priority(rosters) assert waiver_priority[0] == "3" assert waiver_priority[1] == "2" assert waiver_priority[2] == "4" assert waiver_priority[3] == "1"
def test_update_by_commisssioner(): league = League.construct(id="league1", draft_state=DraftState.NOT_STARTED, name="Test League", commissioner_id="commish") roster = Roster(id="roster1", name="Mock Roster") user_league = UserLeaguePreview.create(roster, league) roster_repo = get_league_roster_repo(roster) league_repo = get_league_repo(league) user_league_repo = get_user_league_repo(user_league) command_executor = UpdateRosterNameCommandExecutor( league_config_repo=get_league_config_repo, league_repo=league_repo, league_roster_repo=roster_repo, league_week_matchup_repo=get_league_week_matchup_repo(), user_league_repo=user_league_repo, publisher=get_publisher(), league_transaction_repo=get_league_transaction_repo()) new_name = "Update Roster Name" command = UpdateRosterNameCommand(league_id=league.id, roster_id=roster.id, roster_name=new_name, current_user_id=league.commissioner_id) result = command_executor.execute(command) assert result.success expected = new_name actual = roster_repo.get(league.id, roster.id).name are_equal(expected, actual)
def test_cannot_change_while_drafting(): league = League.construct(id="league1", draft_state=DraftState.IN_PROGRESS, name="Test League", commissioner_id="commish") roster = Roster(id="roster1", name="Mock Roster") user_league = UserLeaguePreview.create(roster, league) roster_repo = get_league_roster_repo(roster) league_repo = get_league_repo(league) user_league_repo = get_user_league_repo(user_league) command_executor = UpdateRosterNameCommandExecutor( league_config_repo=get_league_config_repo, league_repo=league_repo, league_roster_repo=roster_repo, league_week_matchup_repo=get_league_week_matchup_repo(), user_league_repo=user_league_repo, publisher=get_publisher(), league_transaction_repo=get_league_transaction_repo()) new_name = "Update Roster Name" command = UpdateRosterNameCommand(league_id=league.id, roster_id=roster.id, roster_name=new_name, current_user_id=roster.id) result = command_executor.execute(command) assert not result.success
def test_drop_transaction_is_created(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster1.positions["2"].player = rb2 roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb1, drop_player=rb2, amount=25)) command = ProcessWaiversCommand(league_id=league.id) executor = get_target([roster1]) executor.execute(command) transaction_repo = executor.waiver_service.roster_player_service.league_transaction_repo transactions = transaction_repo.firestore.get_all(None) transaction = next( (x for x in transactions if x.type == TransactionType.DROP_PLAYER and x.player_id == rb2.id), None) assert transaction, "No drop transaction found"
def test_drop_player_must_still_be_on_roster_already_dropped(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster1.positions["1"].player = player2 roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, drop_player=player2, amount=25)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player3, drop_player=player2, amount=15)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1]) assert roster1.waiver_bids[ 1].result == WaiverBidResult.FailedDropPlayerNotOnRoster
def fix_roster(self, week_number: int, league_id, roster: Roster, games_by_week: Dict[int, List[str]]): for position in roster.positions.values(): if not position.is_starting_position_type() or not position.player: continue player_score = self.player_score_repo.get(league_id, position.player.id) if not player_score: continue for game_id in games_by_week[week_number]: if game_id in player_score.game_scores: game_score = player_score.game_scores[game_id] position.game_score = game_score.total_score roster.this_week_points_for = roster.calculate_score()
def test_teams_with_no_bids_work_ok(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster2 = Roster(id="2", name="team 2", rank=2, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, amount=5)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1, roster2]) assert roster1.waiver_bids[0].result == WaiverBidResult.SuccessPending
def test_roster_budget_not_updated_failed_bids(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster2 = Roster(id="2", name="team 2", rank=2, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, amount=5)) roster2.waiver_bids.append( WaiverBid(roster_id=roster2.id, player=player1, amount=4)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1, roster2]) assert roster2.waiver_budget == 100
def test_highest_bid_wins_second_team(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster2 = Roster(id="2", name="team 2", rank=2, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, amount=4)) roster2.waiver_bids.append( WaiverBid(roster_id=roster2.id, player=player1, amount=5)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1, roster2]) assert roster1.waiver_bids[0].result == WaiverBidResult.FailedOutBid assert roster2.waiver_bids[0].result == WaiverBidResult.SuccessPending
def assign_player_to_roster( self, league_id: str, roster: Roster, player: Player, transaction: Transaction = None, target_position: LeaguePosition = None, record_transaction: bool = False, waiver_bid: int = None ) -> Tuple[bool, Union[str, List[LeagueTransaction]]]: position = target_position or self.find_position_for(player, roster) if not position: return False, "Unable to find position for player" if player.position == PositionType.qb and roster.count_qbs( ) == 1 and not self.dropping(PositionType.qb, target_position): return False, "Rosters are limited to 1 quarterback" if player.position == PositionType.rb and roster.count_rbs( ) == 1 and not self.dropping(PositionType.rb, target_position): return False, "Rosters are limited to 1 running back" if player.position == PositionType.k and roster.count_kickers( ) == 1 and not self.dropping(PositionType.k, target_position): return False, "Rosters are limited to 1 kicker" league_transactions = self.assign_player_to_roster_position( league_id, roster, player, position, transaction, record_transaction=record_transaction, waiver_bid=waiver_bid) return True, league_transactions
def test_update_roster_name_updates_schedule_config_home(): week_number = 1 league = League.construct(id="league1", draft_state=DraftState.NOT_STARTED, name="Test League", schedule_generated=True, commissioner_id="commish") roster = Roster(id="roster1", name="Mock Roster") user_league = UserLeaguePreview.create(roster, league) schedule = create_mock_schedule(week_number) roster_repo = get_league_roster_repo(roster) league_repo = get_league_repo(league) user_league_repo = get_user_league_repo(user_league) matchup_repo = get_league_week_matchup_repo() config_repo = get_league_config_repo() matchup = Matchup(id="1", home=roster, type=MatchupType.REGULAR) matchup_repo.set(league.id, week_number, matchup) schedule.weeks[0].matchups.append(matchup) config_repo.set_schedule_config(league.id, schedule) command_executor = UpdateRosterNameCommandExecutor( league_config_repo=config_repo, league_repo=league_repo, league_roster_repo=roster_repo, league_week_matchup_repo=matchup_repo, user_league_repo=user_league_repo, publisher=get_publisher(), league_transaction_repo=get_league_transaction_repo()) new_name = "Update Roster Name" command = UpdateRosterNameCommand(league_id=league.id, roster_id=roster.id, roster_name=new_name, current_user_id=roster.id) result = command_executor.execute(command) assert result.success expected = new_name updated_schedule = config_repo.get_schedule_config(league.id) actual = updated_schedule.weeks[0].matchups[0].home.name are_equal(expected, actual)
def archive_roster(self, roster: Roster): copy = roster.copy(deep=True) for position in copy.positions.values(): if position.player: for game in self.games_for_week: if position.player.id in game.player_stats: game_stats = game.player_stats[position.player.id] score = self.league_scoring.calculate_score( game_stats.stats) position.game_id = game.id position.game_score = score.total_score return copy
def test_cannot_exceed_waiver_budget_one_bid(): roster1 = Roster(id="1", name="team 1", rank=1, waiver_budget=20, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, amount=25)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1]) assert roster1.waiver_bids[ 0].result == WaiverBidResult.FailedNotEnoughMoney
def test_bids_are_saved(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb1, amount=25)) command = ProcessWaiversCommand(league_id=league.id) executor = get_target([roster1]) executor.execute(command) updated_week = executor.league_week_repo.get(league.id, str(state.current_week - 1)) assert updated_week and updated_week is not None, "Bids were not saved on week"
def test_roster_budget_updated(): # create two bids without drop players, no conflicts, ensure they both work roster1 = Roster(id="1", name="team 1", waiver_budget=100, rank=1, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb1, amount=25)) command = ProcessWaiversCommand(league_id=league.id) executor = get_target([roster1]) executor.execute(command) roster = executor.league_roster_repo.get(league.id, roster1.id) assert roster.waiver_budget == 75, "Waiver budget was not updated"
def test_drop_player_must_still_be_on_roster(): roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) # note that player 2 is not actually in a position on roster1 roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=player1, drop_player=player2, amount=25)) target = WaiverService(get_roster_player_service()) target.process_bids([roster1]) assert roster1.waiver_bids[ 0].result == WaiverBidResult.FailedDropPlayerNotOnRoster
def test_process_two_successful_bids(): # create two bids without drop players, no conflicts, ensure they both work roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb1, amount=25)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=wr1, amount=15)) command = ProcessWaiversCommand(league_id=league.id) executor = get_target([roster1]) executor.execute(command) assert roster1.processed_waiver_bids[ 0].result == WaiverBidResult.Success, "assert 1 failed" assert roster1.processed_waiver_bids[ 1].result == WaiverBidResult.Success, "assert 2 failed"
def test_no_drop_player_no_space_on_roster(): # create two bids without drop players, same position, only one position available # first should pass, second should fail as there is no space on roster after processing the first one roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb1, amount=25)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb3, amount=15)) command = ProcessWaiversCommand(league_id=league.id) executor = get_target([roster1]) executor.execute(command) assert roster1.processed_waiver_bids[ 0].result == WaiverBidResult.Success, "assert 1 failed" assert roster1.processed_waiver_bids[ 1].result == WaiverBidResult.FailedNoRosterSpace, "assert 2 failed"
def remove_player_from_roster(self, league_id: str, roster: Roster, player_id: str, transaction: Transaction = None): for position_id in roster.positions: position = roster.positions[position_id] if not position.player or position.player.id != player_id: continue position.player = None active_filled_positions = [ position for position in roster.positions.values() if position.player and position.position_type.is_active_position_type() ] roster.active_player_count = len(active_filled_positions) self.league_owned_player_repo.delete(league_id, player_id, transaction) self.roster_repo.set(league_id, roster, transaction)
def test_add_transaction_is_created(): # create two bids without drop players, no conflicts, ensure they both work roster1 = Roster(id="1", name="team 1", rank=1, positions=deepcopy(league_positions)) roster1.waiver_bids.append( WaiverBid(roster_id=roster1.id, player=rb1, amount=25)) command = ProcessWaiversCommand(league_id=league.id) executor = get_target([roster1]) executor.execute(command) transaction_repo = executor.waiver_service.roster_player_service.league_transaction_repo transactions = transaction_repo.firestore.get_all(None) transaction = next( (x for x in transactions if x.type == TransactionType.CLAIM_PLAYER and x.player_id == rb1.id), None) assert transaction, "No add transaction found"
def apply_winning_bid(self, league_id: str, bid: WaiverBid, roster: Roster, transaction: Transaction): if bid.drop_player: target_position = roster.find_player_position(bid.drop_player.id) else: target_position = self.roster_player_service.find_position_for( bid.player, roster) if not target_position: bid.result = WaiverBidResult.FailedNoRosterSpace else: success, _ = self.roster_player_service.assign_player_to_roster( league_id, roster, bid.player, transaction, target_position=target_position, record_transaction=True, waiver_bid=bid.amount) if success: bid.result = WaiverBidResult.Success else: bid.result = WaiverBidResult.FailedNoRosterSpace
from typing import List from api.app.domain.entities.roster import Roster from api.app.domain.entities.schedule import MatchupType, PlayoffType import pytest from api.app.domain.services.schedule_service import ScheduledMatchup, combine_schedule, generate_schedule, get_sequence_for_count from api.tests.asserts import are_equal SEASON_WEEKS = 21 # MANAGERS teams = [ Roster(id=1, name="team 1"), Roster(id=2, name="team 2"), Roster(id=3, name="team 3"), Roster(id=4, name="team 4"), Roster(id=5, name="team 5"), Roster(id=6, name="team 6"), Roster(id=7, name="team 7"), Roster(id=8, name="team 8"), ] teamCounts = [2, 4, 6, 8] playoffTypes = [ { "type": PlayoffType.TOP_2, "weeks": 1 }, { "type": PlayoffType.TOP_3, "weeks": 2 },
def calculate(transaction): league = self.league_repo.get(command.league_id, transaction) rosters = self.league_roster_repo.get_all(command.league_id, transaction) rosters = {roster.id: roster for roster in rosters} matchups = self.matchup_repo.get_all(command.league_id, command.week_number, transaction) schedule = self.league_config_repo.get_schedule_config( command.league_id, transaction) week_index = command.week_number - 1 for matchup in matchups: schedule_matchup = next( m for m in schedule.weeks[week_index].matchups if m.id == matchup.id) if not matchup.home and not matchup.away: continue # not sure how this would happen, but there's nothing to calculate if matchup.home: if not command.past_week: # don't copy current roster if re-calculating a previous week matchup.home = self.archive_roster( rosters[matchup.home.id]) matchup.home.this_week_points_for = matchup.home.calculate_score( ) matchup.home.this_week_bench_points_for = matchup.home.calculate_bench_score( ) matchup.home_score = matchup.home.this_week_points_for if matchup.away: if not command.past_week: matchup.away = self.archive_roster( rosters[matchup.away.id]) matchup.away.this_week_points_for = matchup.away.calculate_score( ) matchup.away.this_week_bench_points_for = matchup.away.calculate_bench_score( ) matchup.away_score = matchup.away.this_week_points_for schedule_matchup.away_score = matchup.away_score schedule_matchup.home_score = matchup.home_score self.matchup_repo.set(command.league_id, command.week_number, matchup, transaction) next_week_matchups = schedule.weeks[ week_index + 1].matchups if len(schedule.weeks) > week_index + 1 else None next_week_playoffs = schedule.weeks[ week_index + 1].week_type.is_playoffs() if len( schedule.weeks) > week_index + 1 else False for roster in rosters.values(): update_record(roster, command.week_number, schedule, league.league_start_week) if next_week_matchups: roster_matchup = next( (m for m in next_week_matchups if (m.away and m.away.id == roster.id) or ( m.home and m.home.id == roster.id)), None) if roster_matchup: roster_matchup = MatchupPreview.from_matchup( roster_matchup) else: roster_matchup = None updates = { "matchup": roster_matchup.dict() if roster_matchup else None } self.user_league_repo.partial_update( roster.id, command.league_id, updates, transaction) for week in schedule.weeks: if week.week_number <= command.week_number: continue for matchup in week.matchups: if matchup.away: if not command.past_week: matchup.away = rosters[matchup.away.id].copy( deep=True) matchup.away.positions = [] matchup.away.waiver_bids = [] matchup.away.processed_waiver_bids = [] if matchup.home: if not command.past_week: matchup.home = rosters[matchup.home.id].copy( deep=True) matchup.home.positions = [] matchup.home.waiver_bids = [] matchup.home.processed_waiver_bids = [] rosters = list(rosters.values()) rosters = Roster.sort(rosters) rank = 1 for roster in rosters: roster.rank = rank rank += 1 roster.this_week_points_for = 0 roster.this_week_bench_points_for = 0 for position in roster.positions.values(): position.game_score = 0 self.league_roster_repo.set(command.league_id, roster, transaction) self.league_config_repo.set_schedule_config( command.league_id, schedule, transaction) return CalculateResultsResult( command=command, next_week_is_playoffs=next_week_playoffs)
def create_roster(user_id, display_name) -> Roster: return Roster(id=user_id, name=f"Team {display_name}")
from typing import List from api.app.domain.entities.roster import Roster import pytest from time import sleep case1 = [ # purely by points ([Roster(name="one", wins=1), Roster(name="two", wins=0, losses=1)], "one"), ([Roster(name="two", wins=0, losses=1), Roster(name="one", wins=1)], "one"), # by points for ([Roster(name="one", points_for=100), Roster(name="two", points_for=50)], "one"), ([Roster(name="one", points_for=50), Roster(name="two", points_for=150)], "two"), # by point differential ([Roster(name="one", points_for=100, points_against=50), Roster(name="two", points_for=100, points_against=75)], "one"), ([Roster(name="one", points_for=100, points_against=50), Roster(name="two", points_for=100, points_against=25)], "two"), ] @pytest.mark.parametrize("rosters, first", case1) def test_sort_roster(rosters: List[Roster], first): for roster in rosters: roster.wl_points = Roster.calculate_wl_points(roster) rosters = Roster.sort(rosters) assert rosters[0].name == first
import pytest from api.tests.asserts import are_equal from api.app.domain.entities.roster import Roster from api.app.domain.entities.schedule import Matchup, PlayoffType, ScheduleWeek from api.app.domain.enums.matchup_type import MatchupType from api.app.domain.enums.week_type import WeekType from api.app.domain.services.schedule_service import generate_playoffs # MANAGERS team_1 = Roster(id=1, name="team 1", rank=1) team_2 = Roster(id=2, name="team 2", rank=2) team_3 = Roster(id=3, name="team 3", rank=3) team_4 = Roster(id=4, name="team 4", rank=4) team_5 = Roster(id=5, name="team 5", rank=5) team_6 = Roster(id=6, name="team 6", rank=6) team_7 = Roster(id=7, name="team 7", rank=7) team_8 = Roster(id=8, name="team 8", rank=8) teams = [ team_1, team_2, team_3, team_4, team_5, team_6, team_7, team_8, ]