Skip to content

Commit

Permalink
Merge pull request #216 from BenBrostoff/nhl-rules
Browse files Browse the repository at this point in the history
NHL rules - three non skaters
  • Loading branch information
BenBrostoff authored Jan 25, 2024
2 parents c2f0c81 + 282b4df commit eb16209
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 19 deletions.
19 changes: 7 additions & 12 deletions draftfast/optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,25 @@ def run(

if verbose:
print(
"""
f"""
No solution found.
Try adjusting your query by taking away constraints.
OPTIMIZER CONSTRAINTS:
{}
Minimum teams: {rule_set.min_teams or optimizer_settings.min_teams}
Other optimizer contraints: {optimizer_settings}
LINEUP CONSTRAINTS:
{}
{constraints}
PLAYER POOL SETTINGS:
{}
{players}
PLAYER COUNT: {}
""".format(
optimizer_settings,
constraints,
player_settings,
len(players or []),
)
)
PLAYER COUNT: {len(players or [])}
""")
return None


Expand Down
15 changes: 13 additions & 2 deletions draftfast/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
PlayerBanAndLockException,
)
from draftfast.orm import Player
from draftfast.rules import RuleSet
from draftfast.rules import RuleSet, DK_NHL_RULE_SET
from draftfast.lineup_constraints import LineupConstraints


Expand All @@ -19,6 +19,7 @@ def __init__(
lineup_constraints: LineupConstraints,
exposure_dict: dict,
):
self.rule_set = rule_set
self.solver = pywraplp.Solver(
"FD", pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING
)
Expand Down Expand Up @@ -378,12 +379,18 @@ def _set_no_duplicate_lineups(self):
def _set_min_teams(self):
"""
Add constraints for maximum players on an individual team
and total represented teams if applicable
and total represented teams if applicable.
For NHL, the min team restriction does not count
goalies
Ref: https://www.draftkings.com/help/rules/nhl
"""
teams = []
min_teams = self.min_teams

if min_teams > 1:
is_dk_nhl = self.rule_set == DK_NHL_RULE_SET
for team in self.teams:
if team:
team_var = self.solver.IntVar(0, 1, team)
Expand All @@ -392,6 +399,10 @@ def _set_min_teams(self):
self.variables[i]
for i, p in self.enumerated_players
if p.team == team
and (
not is_dk_nhl
or p.pos != 'G'
)
]

# Constrain to individual team for all players
Expand Down
3 changes: 3 additions & 0 deletions draftfast/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ def __init__(
offensive_positions=["C", "W"],
defensive_positions=["G", "D"],
min_matchups=2,
# Note min teams restriction is only for non-skaters,
# and this logic is handled in Optimizer
min_teams=3,
general_position_limits=[],
)

Expand Down
8 changes: 4 additions & 4 deletions draftfast/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ def __init__(
A note on defaults:
min_teams 2 - this constraint is common across Classic and Showdown.
Note that a ruleset cannot be override on min_teams and you
must mutate the ruleset directly; this feature is to avoid
modifying rules that would cause invalid lineups.
- In Showdown, you must have two teams represented, although only
one matchup exists to choose from.
Expand All @@ -140,17 +143,14 @@ def __init__(
def __repr__(self):
if not str(self):
return "<OptimizerSettings: None>"
else:
return str(self)
return str(self)

def __str__(self):
lines = []
if self.stacks and len(self.stacks):
lines.append(
"Stacks: {}".format([(x.team, x.count) for x in self.stacks])
)
if self.min_teams:
lines.append("Min teams: {}".format(self.min_teams))
if self.no_offense_against_defense:
lines.append(
"No offense against D: {}".format(
Expand Down
32 changes: 32 additions & 0 deletions draftfast/test/test_nhl.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,38 @@ def test_nhl_dk():
assertions.assertNotEqual(roster, None)


def test_nhl_dk_unsolvable_three_team_non_goalie_restriction():
"""
Should not solve if unable to get min teams of 3
not including goalie team
"""
player_pool = salary_download.generate_players_from_csvs(
salary_file_location=salary_file,
game=rules.DRAFT_KINGS,
ruleset=rules.DK_NHL_RULE_SET,
)
unique_teams = set()
new_player_pool = []
for p in player_pool:
if len(unique_teams) > 2 and p.team not in unique_teams:
continue

if p.pos != 'G':
unique_teams.add(p.team)

if len(unique_teams) < 3:
new_player_pool.append(p)

assertions.assertEqual(len(unique_teams) > 2, True)

roster = run(
rule_set=rules.DK_NHL_RULE_SET,
player_pool=new_player_pool,
verbose=True,
)
assertions.assertEqual(roster, None)


def test_triple_stack():
player_pool = salary_download.generate_players_from_csvs(
salary_file_location=salary_file,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

setuptools.setup(
name='draftfast',
version='3.12.0',
version='3.12.1',
author='Ben Brostoff',
author_email='[email protected]',
description='A tool to automate and optimize DraftKings and FanDuel '
Expand Down

0 comments on commit eb16209

Please sign in to comment.