init commit
commit
197ecb5a10
@ -0,0 +1,432 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import re
|
||||
from threading import Thread, Semaphore
|
||||
from draft_kings import Client
|
||||
from fantasypros_proj import FantasyProsProjections
|
||||
|
||||
MIN_PERPOINT = 50
|
||||
MAX_PERPOINT = 2000
|
||||
# MIN_PERPOINT = 50
|
||||
# MAX_PERPOINT = 1000
|
||||
# MIN_PERPOINT = 200
|
||||
# MAX_PERPOINT = 800
|
||||
MAX_SALARY = 50000
|
||||
LINEUP_POS = ['qb', 'rb', 'wr', 'te', 'dst']
|
||||
MAX_THREADS = 3
|
||||
lock = Semaphore(value=MAX_THREADS)
|
||||
|
||||
class DraftKingsDraft:
|
||||
|
||||
def __init__(self, draft_group_id):
|
||||
self._draft_group_id = draft_group_id
|
||||
self._proj = {}
|
||||
self._get_fpros_proj()
|
||||
self._players = (
|
||||
Client().
|
||||
available_players(draft_group_id=draft_group_id).
|
||||
players)
|
||||
self._pos = {
|
||||
'qb': DraftKingsDraftPosition([], 'qb', num_in_lineup=1),
|
||||
'rb': DraftKingsDraftPosition([], 'rb', num_in_lineup=3),
|
||||
'wr': DraftKingsDraftPosition([], 'wr', num_in_lineup=3),
|
||||
'te': DraftKingsDraftPosition([], 'te', num_in_lineup=1),
|
||||
'dst': DraftKingsDraftPosition([], 'dst', num_in_lineup=1),
|
||||
'k': DraftKingsDraftPosition([], 'k', num_in_lineup=0)}
|
||||
print('DEBUG: Sorting players by position.')
|
||||
self._sort_players_by_pos()
|
||||
|
||||
# Initialize position groups for making lineups.
|
||||
self._lineup_pos_combo_index = {}
|
||||
threads = {}
|
||||
for pos in LINEUP_POS:
|
||||
threads[pos] = Thread(target=self.run_init_lineup, args=(pos,))
|
||||
threads[pos].start()
|
||||
self._lineup_pos_combo_index[pos] = 0
|
||||
for pos in LINEUP_POS:
|
||||
threads[pos].join()
|
||||
|
||||
# self._find_good_subsets()
|
||||
self._gen_lineup()
|
||||
prev_lineup = self._lineup
|
||||
while self._lineup.salary <= MAX_SALARY:
|
||||
prev_lineup = self._lineup
|
||||
print(self._lineup.pretty_str())
|
||||
success = self._improve_lineup()
|
||||
if not success:
|
||||
print('**** Failed')
|
||||
break
|
||||
self._gen_lineup()
|
||||
self._lineup = prev_lineup
|
||||
|
||||
def run_init_lineup(self, pos):
|
||||
lock.acquire()
|
||||
print(f'DEBUG: Start \'{pos}\' thread.')
|
||||
self._pos[pos].init_lineup()
|
||||
lock.release()
|
||||
print(f'DEBUG: \'{pos}\' thread ended.')
|
||||
|
||||
def draft_kings_players(self):
|
||||
""" Returns all players in the draft_kings module format. """
|
||||
return self._players
|
||||
|
||||
def quarter_backs(self):
|
||||
return self.qbs()
|
||||
def qbs(self):
|
||||
return self._get_pos_players('qb')
|
||||
def running_backs(self):
|
||||
return self.rbs()
|
||||
def rbs(self):
|
||||
return self._get_pos_players('rb')
|
||||
def wide_reveivers(self):
|
||||
return self.wrs()
|
||||
def wrs(self):
|
||||
return self._get_pos_players('wr')
|
||||
def tight_ends(self):
|
||||
return self.tes()
|
||||
def tes(self):
|
||||
return self._get_pos_players('te')
|
||||
def defenses(self):
|
||||
return self.dsts()
|
||||
def dsts(self):
|
||||
return self._get_pos_players('dst')
|
||||
def kickers(self):
|
||||
return self.ks()
|
||||
def ks(self):
|
||||
return self._get_pos_players('k')
|
||||
|
||||
def _get_pos_players(self, pos):
|
||||
""" TODO REM is this useful? """
|
||||
return self._pos[pos]._players
|
||||
|
||||
def _get_fpros_proj(self):
|
||||
for pos in LINEUP_POS:
|
||||
self._proj[pos] = FantasyProsProjections(pos)
|
||||
|
||||
def _sort_players_by_pos(self):
|
||||
|
||||
for player in self._players:
|
||||
pos = player.position_details.name.lower()
|
||||
|
||||
if pos not in self._pos:
|
||||
raise Exception("Can't handle position: " +
|
||||
player.position_details.name)
|
||||
|
||||
fpros_proj = self._proj[pos].get_projection(player.first_name, player.last_name)
|
||||
|
||||
self._pos[pos]._players.append(DraftKingsDraftPlayer(player, fpros_proj=fpros_proj))
|
||||
|
||||
def _get_player_for_lineup(self, pos, lineup_slot):
|
||||
return self._get_pos_players(pos)[self._pos[pos].
|
||||
lineup_indexes[lineup_slot]]
|
||||
|
||||
def _gen_lineup(self):
|
||||
players = {}
|
||||
for pos in LINEUP_POS:
|
||||
players[pos] = (
|
||||
list(self._pos[pos]
|
||||
.pos_combos[self._lineup_pos_combo_index[pos]]
|
||||
.players))
|
||||
|
||||
self._lineup = DraftKingsDraftLineup(
|
||||
qb=players['qb'][0],
|
||||
rb1=players['rb'][0],
|
||||
rb2=players['rb'][1],
|
||||
wr1=players['wr'][0],
|
||||
wr2=players['wr'][1],
|
||||
wr3=players['wr'][2],
|
||||
te=players['te'][0],
|
||||
flex=players['rb'][2],
|
||||
dst=players['dst'][0])
|
||||
|
||||
def lineup(self):
|
||||
return self._lineup
|
||||
|
||||
def _improve_lineup(self):
|
||||
lowest = {'pos': LINEUP_POS[0], 'perpoint': MAX_PERPOINT}
|
||||
|
||||
# Find lowest perpoint for a position group.
|
||||
for pos_key in LINEUP_POS:
|
||||
|
||||
pos = self._pos[pos_key]
|
||||
|
||||
# Make sure this position isn't already the highest possible.
|
||||
if pos.highest:
|
||||
continue
|
||||
|
||||
# lineup_indexes = pos.lineup_indexes
|
||||
# for player in pos._players[lineup_indexes[-1]:]:
|
||||
# if player.perpoint < lowest['perpoint']:
|
||||
# lowest['pos'] = pos_key
|
||||
# lowest['perpoint'] = player.perpoint
|
||||
|
||||
index = self._lineup_pos_combo_index[pos_key]
|
||||
print("{} perpoint {}".format(pos_key, pos.pos_combos[index].fpros_perpoint))
|
||||
if pos.pos_combos[index].fpros_perpoint < lowest['perpoint']:
|
||||
lowest['perpoint'] = pos.pos_combos[index].fpros_perpoint
|
||||
lowest['pos'] = pos_key
|
||||
|
||||
# If we didn't find a pos group that isn't allready highest then we
|
||||
# can't improve. This is, however, very unlikely so we log a warning.
|
||||
if lowest['perpoint'] == MAX_PERPOINT:
|
||||
print("WARNING: All position groups are already maxxed! " +
|
||||
"Something probably went wrong.")
|
||||
return False
|
||||
|
||||
# Bump up lowest pos.
|
||||
index = self._lineup_pos_combo_index[lowest['pos']]
|
||||
if (index + 1) == len(self._pos[lowest['pos']].pos_combos):
|
||||
self._pos[lowest['pos']].highest = True
|
||||
return self._improve_lineup()
|
||||
else:
|
||||
self._lineup_pos_combo_index[lowest['pos']] += 1
|
||||
return True
|
||||
|
||||
class DraftKingsDraftPositionCombo:
|
||||
def __init__(self, players):
|
||||
self.players = players
|
||||
self.salary = 0
|
||||
self.points = 0.0
|
||||
self.fpros_points = 0.0
|
||||
for player in players:
|
||||
self.salary += player.salary
|
||||
self.points += player.points
|
||||
self.fpros_points += player.fpros_proj
|
||||
self.perpoint = self.salary / self.points if self.points != 0.0 else 0.0
|
||||
self.fpros_perpoint = self.salary / self.fpros_points if self.fpros_points != 0.0 else 0.0
|
||||
|
||||
def __str__(self):
|
||||
combo = (f'{{ fpros_perpoint: {self.fpros_perpoint}, ' +
|
||||
f'fpros_points: {self.fpros_points}, ' +
|
||||
f'perpoint: {self.perpoint}, points: {self.points}, ' +
|
||||
f'salary: {self.salary}, players: [ ')
|
||||
players = []
|
||||
for player in self.players:
|
||||
players.append(player.last_name)
|
||||
combo += ', '.join(players) + ' ] }'
|
||||
return combo
|
||||
|
||||
class DraftKingsDraftPosition:
|
||||
def __init__(self,
|
||||
players,
|
||||
pos_str,
|
||||
start_index=0,
|
||||
stop_index=0,
|
||||
num_in_lineup=1):
|
||||
|
||||
self._players = players
|
||||
self._sort_players(lambda p: p.perpoint)
|
||||
self.pos = pos_str
|
||||
|
||||
# If start_index or stop_index was manually set then use those values,
|
||||
# if not, then calculate the indexes based on MIN_PERPOINT and
|
||||
# MAX_PERPOINT.
|
||||
if start_index != 0 or stop_index != 0:
|
||||
self.start_index = start_index
|
||||
self.stop_index = stop_index
|
||||
else:
|
||||
self.start_index = 0
|
||||
self.stop_index = 0
|
||||
self._calc_start_index()
|
||||
self._calc_stop_index()
|
||||
print(f'DEBUG: Using {self.stop_index-self.start_index} players in ' +
|
||||
f'the \'{pos_str}\' group.')
|
||||
|
||||
self.num_in_lineup = num_in_lineup
|
||||
self.highest = False
|
||||
self.lineup_indexes = []
|
||||
self.pos_combos = []
|
||||
self.pos_combos_sets = set()
|
||||
|
||||
# TODO This is where we initialized lineup indexes, but its not clear
|
||||
# if thats needed going forward.
|
||||
# self.
|
||||
# if len(players) == 0:
|
||||
# self._init_lineup_indexes()
|
||||
|
||||
# def players(self, new_players=None):
|
||||
# if new_players is None:
|
||||
# return self._players
|
||||
# else:
|
||||
# self._players = new_players
|
||||
# self._calc_start_index()
|
||||
# self._calc_stop_index()
|
||||
|
||||
def init_lineup(self):
|
||||
|
||||
self._sort_players(lambda p: p.fpros_perpoint)
|
||||
self._calc_start_index()
|
||||
self._calc_stop_index()
|
||||
|
||||
self.lineup_indexes = []
|
||||
for i in range(self.num_in_lineup):
|
||||
self.lineup_indexes.append(self.start_index + i)
|
||||
|
||||
self.pos_combos_sets = set()
|
||||
self.pos_combos = []
|
||||
print(f'DEBUG: Calculating position combo sets for {self.pos}.')
|
||||
self._calc_pos_combo_sets(set(), self.num_in_lineup)
|
||||
for combo_set in self.pos_combos_sets:
|
||||
self.pos_combos.append(DraftKingsDraftPositionCombo(combo_set))
|
||||
# self.pos_combos = sorted(self.pos_combos, key=lambda c: c.perpoint)
|
||||
print(f'DEBUG: Sorting position combo sets for {self.pos}.')
|
||||
self.pos_combos = sorted(self.pos_combos, key=lambda c: c.fpros_perpoint)
|
||||
self.pos_combos_sets = set()
|
||||
|
||||
# Strip out all entries in pos_combos that aren't increasing in points.
|
||||
stripped_pos_combos = []
|
||||
points_to_beat = 0
|
||||
print(f'DEBUG: Stripping position combo sets for {self.pos}.')
|
||||
for combo in self.pos_combos:
|
||||
if combo.fpros_perpoint > MIN_PERPOINT and combo.fpros_points > points_to_beat:
|
||||
stripped_pos_combos.append(combo)
|
||||
points_to_beat = combo.fpros_points
|
||||
self.pos_combos = stripped_pos_combos
|
||||
|
||||
def _calc_pos_combo_sets(self, starting_perm, final_size):
|
||||
|
||||
players_avail = self._players[self.start_index:self.stop_index]
|
||||
for player in starting_perm:
|
||||
players_avail = (
|
||||
list(filter(
|
||||
lambda p: p.object.player_id != player.object.player_id,
|
||||
players_avail)))
|
||||
|
||||
done_recursing = len(starting_perm) == (final_size - 1)
|
||||
for player in players_avail:
|
||||
new_perm = starting_perm.copy()
|
||||
new_perm.add(player)
|
||||
if done_recursing:
|
||||
self.pos_combos_sets.add(frozenset(new_perm))
|
||||
else:
|
||||
self._calc_pos_combo_sets(new_perm, final_size)
|
||||
|
||||
# def get_next_best_players_index(self, starting_index):
|
||||
# player1 = self._players[starting_index]
|
||||
# for i in range(starting_index + 1, len(self._players)):
|
||||
# tmp_player = self._players[i]
|
||||
# if tmp_player.points > player1.points:
|
||||
# return i
|
||||
|
||||
def _calc_start_index(self):
|
||||
""" Assumes players are already sorted. """
|
||||
self.start_index = 0
|
||||
for i, player in enumerate(self._players):
|
||||
if player.fpros_perpoint > MIN_PERPOINT:
|
||||
self.start_index = i
|
||||
break
|
||||
print(f'DEBUG: Set \'{self.pos}\' start_index to {self.start_index}.' +
|
||||
f' Using {self.stop_index-self.start_index} players.')
|
||||
|
||||
def _calc_stop_index(self):
|
||||
""" Assumes players are already sorted. """
|
||||
self.stop_index = len(self._players)
|
||||
for i, player in enumerate(self._players):
|
||||
if player.fpros_perpoint > MAX_PERPOINT:
|
||||
self.stop_index = i
|
||||
break
|
||||
print(f'DEBUG: Set \'{self.pos}\' stop_index to {self.stop_index}.' +
|
||||
f' Using {self.stop_index-self.start_index} players.')
|
||||
|
||||
def _sort_players(self, key):
|
||||
self._players = sorted(self._players, key=key)
|
||||
|
||||
class DraftKingsDraftPlayer:
|
||||
def __init__(self, player, fpros_proj=0.0):
|
||||
self.first_name = player.first_name
|
||||
self.last_name = player.last_name
|
||||
self.fpros_proj = fpros_proj
|
||||
self.salary = player.draft_details.salary
|
||||
self.points = player.points_per_game
|
||||
self.perpoint = self.salary / self.points if self.points != 0 else 0
|
||||
self.fpros_perpoint = self.salary / self.fpros_proj if self.fpros_proj != 0 else 0
|
||||
self.pos = player.position_details.name
|
||||
self.object = player
|
||||
|
||||
def name(self):
|
||||
return "%s %s" % (self.first_name, self.last_name)
|
||||
|
||||
def __str__(self):
|
||||
return ("{ fpros_perpoint: %f, perpoint: %f, name: \"%s\", salary: %d, fpros_proj: %f, points: %f, " +
|
||||
"pos: %s}") % (
|
||||
self.fpros_perpoint,
|
||||
self.perpoint,
|
||||
self.name(),
|
||||
self.salary,
|
||||
self.fpros_proj,
|
||||
self.points,
|
||||
self.pos)
|
||||
|
||||
class DraftKingsDraftLineup:
|
||||
def __init__(self, qb, rb1, rb2, wr1, wr2, wr3, te, flex, dst):
|
||||
self._qb = qb
|
||||
self._rb1 = rb1
|
||||
self._rb2 = rb2
|
||||
self._wr1 = wr1
|
||||
self._wr2 = wr2
|
||||
self._wr3 = wr3
|
||||
self._te = te
|
||||
self._flex = flex
|
||||
self._dst = dst
|
||||
self.points = self.calc_points()
|
||||
self.salary = self.calc_salary()
|
||||
|
||||
def __str__(self):
|
||||
return "lineup: { points: %f, salary: %d }" % (
|
||||
self.points,
|
||||
self.salary)
|
||||
|
||||
def pretty_str(self):
|
||||
col_width = [0, 0, 0, 0, 0]
|
||||
rows = []
|
||||
lineup_str = (f'Lineup Total-Points: {self.points} ' +
|
||||
f'Total-Salary: {self.salary}\n')
|
||||
for player in [self._qb, self._rb1, self._rb2, self._wr1,
|
||||
self._wr2, self._wr3, self._te, self._flex, self._dst]:
|
||||
|
||||
row = [player.pos.upper(), player.name(), str(player.fpros_proj),
|
||||
str(player.salary), str(player.fpros_perpoint)]
|
||||
for i, val in enumerate(row):
|
||||
if len(val) > col_width[i]:
|
||||
col_width[i] = len(val)
|
||||
rows.append(row)
|
||||
|
||||
for row in rows:
|
||||
for i, val in enumerate(row):
|
||||
lineup_str += val + ' ' + (' ' * (col_width[i]-len(val)))
|
||||
lineup_str += '\n'
|
||||
|
||||
return lineup_str
|
||||
|
||||
def calc_dk_points(self):
|
||||
return (self._qb.points + self._rb1.points + self._rb2.points +
|
||||
self._wr1.points + self._wr2.points + self._wr3.points +
|
||||
self._te.points + self._flex.points + self._dst.points)
|
||||
|
||||
def calc_points(self):
|
||||
return (self._qb.fpros_proj + self._rb1.fpros_proj +
|
||||
self._rb2.fpros_proj + self._wr1.fpros_proj +
|
||||
self._wr2.fpros_proj + self._wr3.fpros_proj +
|
||||
self._te.fpros_proj + self._flex.fpros_proj +
|
||||
self._dst.fpros_proj)
|
||||
|
||||
def calc_salary(self):
|
||||
return (self._qb.salary + self._rb1.salary + self._rb2.salary +
|
||||
self._wr1.salary + self._wr2.salary + self._wr3.salary +
|
||||
self._te.salary + self._flex.salary + self._dst.salary)
|
||||
|
||||
def run():
|
||||
draft = DraftKingsDraft(74624)
|
||||
for i, wr, in enumerate(draft.wrs()):
|
||||
print("%s %s" % (wr.perpoint, wr.points))
|
||||
|
||||
# TODO REM STARTHERE we need to make all 'points' and 'perpoint' to have
|
||||
# 'fpros' or 'dk' prefix.
|
||||
def debug():
|
||||
draft = DraftKingsDraft(74624)
|
||||
return draft
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# run()
|
||||
debug()
|
||||
@ -0,0 +1,437 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import pandas
|
||||
import re
|
||||
|
||||
class FantasyProsProjections:
|
||||
|
||||
# TODO REM need to add week # and scoring.
|
||||
PROJ_URL = 'https://www.fantasypros.com/nfl/projections/{pos}.php'
|
||||
ROS_URL = 'https://www.fantasypros.com/nfl/rankings/ros-ppr-overall.php'
|
||||
PLAYER_URL = ('https://www.fantasypros.com/nfl/projections/{name}.php?' +
|
||||
'week={week}')
|
||||
|
||||
# TEMPORARY CONSTANT TODO
|
||||
WEEK_NUM = 1
|
||||
|
||||
def __init__(self, pos):
|
||||
self.pos = pos
|
||||
self.week = self.WEEK_NUM
|
||||
self.data = {}
|
||||
self._get_proj_data()
|
||||
|
||||
def get_projection(self, first_name, last_name):
|
||||
for fpros_name, proj in self.data.items():
|
||||
if (re.match(f'.*{first_name}.*', fpros_name) and
|
||||
re.match(f'.*{last_name}.*', fpros_name)):
|
||||
return proj
|
||||
|
||||
# If we got here then we couldn't find the name. This can happen if the
|
||||
# player is out for the week, therefore we look.... TODO
|
||||
site_proj = self._get_proj_from_player_site(
|
||||
f'{first_name} {last_name}')
|
||||
|
||||
# TODO In the future maybe we can keep IGNORED_PLAYERS empty and
|
||||
# populate it based on these if statements.
|
||||
# if site_proj > 0:
|
||||
# print(f'DEBUG: Projection from site for {first_name} ' +
|
||||
# f'{last_name} was {site_proj}.')
|
||||
# if site_proj < 2:
|
||||
# print(f'IGNORE: {first_name} {last_name}XXX')
|
||||
return site_proj
|
||||
|
||||
def _get_proj_from_player_site(self, name):
|
||||
if name in self.IGNORED_PLAYERS:
|
||||
return 0.0
|
||||
elif name in self.FPROS_NAME_TO_URL_PARAM:
|
||||
name_param = self.FPROS_NAME_TO_URL_PARAM[name]
|
||||
else:
|
||||
print(f'DEBUG: Getting projection for {name} from player site.')
|
||||
# Convert the name to our URL arg by:
|
||||
# - Strip 'II' 'III' at the end of the name.
|
||||
# - Replace spaces with '-'s.
|
||||
# - Convert to lowercase.
|
||||
name_param = (re.sub(r' [IV]+$', '', name)
|
||||
.replace(' ', '-')
|
||||
.replace('.', '')
|
||||
.replace('\'', '')
|
||||
.lower())
|
||||
name_param = re.sub(r'-[js]r$', '', name_param)
|
||||
|
||||
# TODO REM STARTHERE We still need to figure out how to detect when
|
||||
# this fails....
|
||||
html = pandas.read_html(self.PLAYER_URL.format(name=name_param,
|
||||
week=self.week))
|
||||
proj_points = html[0]['Points'].get(0)
|
||||
if (isinstance(proj_points, str) and
|
||||
re.match("^Player does not have", proj_points)):
|
||||
return 0.0
|
||||
return proj_points
|
||||
|
||||
def _get_proj_data(self):
|
||||
html = pandas.read_html(self.PROJ_URL.format(pos=self.pos))
|
||||
data = html[0]
|
||||
drop_keys = []
|
||||
for key in data.keys():
|
||||
if isinstance(data.keys(), pandas.core.indexes.multi.MultiIndex):
|
||||
keyname = key[1]
|
||||
else:
|
||||
keyname = key
|
||||
if keyname != 'Player' and keyname != 'FPTS':
|
||||
drop_keys.append(key)
|
||||
data2 = data.drop(drop_keys, axis=1)
|
||||
for elem in data2.itertuples():
|
||||
# self.data.append(
|
||||
# FantasyProsPlayerProjection(
|
||||
# name=sub(r' \w+$', '', elem[1]),
|
||||
# proj_points=elem[2]))
|
||||
name = ''
|
||||
if self.pos == 'dst':
|
||||
name = elem[1]
|
||||
else:
|
||||
name = re.sub(r' \w+$', '', elem[1])
|
||||
self.data[name] = elem[2]
|
||||
|
||||
# def _get_ros_data(self):
|
||||
|
||||
# These players are ignored.
|
||||
#
|
||||
# TODO only Cal Adomitis do we really want to ignore. We ignore the other
|
||||
# to speed things up and to potentially avoid rate limiting (if there is
|
||||
# any) for fpros.
|
||||
# IGNORED_PLAYERS = {
|
||||
# 'Cal Adomitis',
|
||||
# 'Jack Coco',
|
||||
# 'Damarea Crockett', # This guy has no projection and doesn't work,
|
||||
# # not sure why.
|
||||
# 'Bisi Johnson',
|
||||
# 'Brian Robinson Jr.',
|
||||
# 'Cameron Batson',
|
||||
# 'Drew Ogletree',
|
||||
# 'Dylan Parham',
|
||||
# 'Gerrit Prince',
|
||||
# 'Johnny Johnson III',
|
||||
# 'Kevin Rader',
|
||||
# 'P.J. Walker',
|
||||
# 'Pierre Strong Jr.',
|
||||
# 'Ricky Person Jr.',
|
||||
# 'Ronald Jones II',
|
||||
# 'Scotty Miller',
|
||||
# 'Spencer Brown',
|
||||
# 'Troy Hairston',
|
||||
# 'Velus Jones Jr.',
|
||||
# 'Willie Johnson'
|
||||
# }
|
||||
# # Purposely not ignoring Gabe Davis because he's projected to score
|
||||
# # points.
|
||||
IGNORED_PLAYERS = {
|
||||
'Mike Evans',
|
||||
'Deshaun Watson',
|
||||
'DeAndre Hopkins',
|
||||
'Jameson Williams',
|
||||
'Tyrion Davis-Price',
|
||||
'Zach Wilson',
|
||||
'Kenneth Walker III',
|
||||
'Sam Darnold',
|
||||
'Colt McCoy',
|
||||
'Blaine Gabbert',
|
||||
'Gus Edwards',
|
||||
'Jeff Driskel',
|
||||
'Tim Boyle',
|
||||
'Giovani Bernard',
|
||||
'Mason Rudolph',
|
||||
'Elijah Mitchell',
|
||||
'Brian Robinson Jr.',
|
||||
'Ryan Griffin',
|
||||
'Danny Etling',
|
||||
'Kenjon Barner',
|
||||
'Patrick Laird',
|
||||
'Kylin Hill',
|
||||
'Tyler Goodson',
|
||||
'Bailey Zappe',
|
||||
'Ben Mason',
|
||||
'Ricky Person Jr.',
|
||||
'Tyler Badie',
|
||||
'J.J. Taylor',
|
||||
'Kevin Harris',
|
||||
'Shane Buechele',
|
||||
'Chris Oladokun',
|
||||
'Sam Ehlinger',
|
||||
'D\'vonte Price',
|
||||
'Phillip Lindsay',
|
||||
'Kellen Mond',
|
||||
'Josh Rosen',
|
||||
'Jeremy McNichols',
|
||||
'Anthony McFarland Jr.',
|
||||
'Jason Huntley',
|
||||
'John Kelly Jr.',
|
||||
'P.J. Walker',
|
||||
'Matt Corral',
|
||||
'Jacob Eason',
|
||||
'Jake Luton',
|
||||
'John Lovett',
|
||||
'Latavius Murray',
|
||||
'Nathan Peterman',
|
||||
'Darrynton Evans',
|
||||
'Darius Anderson',
|
||||
'Royce Freeman',
|
||||
'Gerrid Doaks',
|
||||
'Skylar Thompson',
|
||||
'Matt Barkley',
|
||||
'John Lovett',
|
||||
'ZaQuandre White',
|
||||
'Raheem Blackshear',
|
||||
'Duke Johnson',
|
||||
'David Blough',
|
||||
'Ty Chandler',
|
||||
'Bryant Koback',
|
||||
'Greg Bell',
|
||||
'Jermar Jefferson',
|
||||
'Jason Cabinda',
|
||||
'Chris Streveler',
|
||||
'Jake Browning',
|
||||
'Nick Bawden',
|
||||
'Zonovan Knight',
|
||||
'Trayveon Williams',
|
||||
'Elijah Holyfield',
|
||||
'Chase Garbers',
|
||||
'Logan Woodside',
|
||||
'Sincere McCormick',
|
||||
'Austin Walter',
|
||||
'Trenton Cannon',
|
||||
'Sam Howell',
|
||||
'Ian Book',
|
||||
'Jaret Patterson',
|
||||
'Kennedy Brooks',
|
||||
'E.J. Perry',
|
||||
'Easton Stick',
|
||||
'Mekhi Sargent',
|
||||
'Larry Rountree III',
|
||||
'Jarrett Guarantano',
|
||||
'Bryce Perkins',
|
||||
'Jonathan Ward',
|
||||
'Kyren Williams',
|
||||
'Ronnie Rivers',
|
||||
'Sean Mannion',
|
||||
'Darwin Thompson',
|
||||
'Damien Williams',
|
||||
'B.J. Baylor',
|
||||
'Trey Lance',
|
||||
'Josh Johnson',
|
||||
'Damarea Crockett',
|
||||
'Devine Ozigbo',
|
||||
'Davis Webb',
|
||||
'Sandro Platzgummer',
|
||||
'Jashaun Corbin',
|
||||
'Malik Davis',
|
||||
'Qadree Ollison',
|
||||
'Tre\'Quan Smith',
|
||||
'Antoine Wesley',
|
||||
'Deven Thompkins',
|
||||
'Samori Toure',
|
||||
'Travis Fulgham',
|
||||
'Juwann Winfree',
|
||||
'Slade Bolden',
|
||||
'Makai Polk',
|
||||
'Binjimen Victor',
|
||||
'Ty Montgomery',
|
||||
'Tyquan Thornton',
|
||||
'Kristian Wilkerson',
|
||||
'Laquon Treadwell',
|
||||
'Lynn Bowden Jr.',
|
||||
'Tre Nixon',
|
||||
'Justyn Ross',
|
||||
'Corey Coleman',
|
||||
'Daurice Fountain',
|
||||
'Jerrion Ealy',
|
||||
'Cornell Powell',
|
||||
'Ethan Fernea',
|
||||
'Steven Sims Jr.',
|
||||
'Calvin Austin III',
|
||||
'Anthony Miller',
|
||||
'Cody White',
|
||||
'Michael Woods II',
|
||||
'Jakeem Grant Sr.',
|
||||
'Isaiah Weston',
|
||||
'Chester Rogers',
|
||||
'Mike Harley Jr.',
|
||||
'Daylen Baldwin',
|
||||
'Andre Roberts',
|
||||
'C.J. Saunders',
|
||||
'Preston Williams',
|
||||
'Derek Wright',
|
||||
'Kawaan Baker',
|
||||
'Rashid Shaheed',
|
||||
'Kirk Merritt',
|
||||
'N\'Keal Harry',
|
||||
'Nsimba Webster',
|
||||
'Isaiah Coulter',
|
||||
'John Metchie III',
|
||||
'Drew Estrada',
|
||||
'Johnny Johnson III',
|
||||
'Jalen Camp',
|
||||
'Erik Ezukanma',
|
||||
'Braylon Sanders',
|
||||
'Freddie Swain',
|
||||
'Marquez Stevenson',
|
||||
'Tavon Austin',
|
||||
'Isaiah Hodgins',
|
||||
'Blake Proehl',
|
||||
'Bisi Johnson',
|
||||
'Thomas Hennigan',
|
||||
'Travis Toivonen',
|
||||
'Trishton Jackson',
|
||||
'Dan Chisena',
|
||||
'Tom Kennedy',
|
||||
'Maurice Alexander',
|
||||
'Denzel Mims',
|
||||
'Rodney Adams',
|
||||
'Irvin Charles',
|
||||
'Tarik Black',
|
||||
'Trenton Irwin',
|
||||
'Kwamie Lassiter II',
|
||||
'DJ Turner',
|
||||
'Isaiah Zuber',
|
||||
'Chris Lacy',
|
||||
'Racey McMath',
|
||||
'Dez Fitzpatrick',
|
||||
'Mason Kinsey',
|
||||
'Kyric McGowan',
|
||||
'Alex Erickson',
|
||||
'Marken Michel',
|
||||
'Deon Cain',
|
||||
'Devon Allen',
|
||||
'Auden Tate',
|
||||
'Kendric Pryor',
|
||||
'Willie Johnson',
|
||||
'Kevin Austin Jr.',
|
||||
'Seth Williams',
|
||||
'Jaylon Moore',
|
||||
'Joe Reed',
|
||||
'Michael Bandy',
|
||||
'Jason Moore Jr.',
|
||||
'Javon Wims',
|
||||
'Jeff Cotton Jr.',
|
||||
'Lance McCutcheon',
|
||||
'J.J. Koski',
|
||||
'Austin Trammell',
|
||||
'Dareke Young',
|
||||
'Cody Thompson',
|
||||
'J.J. Arcega-Whiteside',
|
||||
'Cade Johnson',
|
||||
'Bo Melton',
|
||||
'Calvin Ridley',
|
||||
'Josh Ali',
|
||||
'Frank Darby',
|
||||
'Cameron Batson',
|
||||
'Willie Snead IV',
|
||||
'Malik Turner',
|
||||
'Tay Martin',
|
||||
'Jalen Virgil',
|
||||
'Tim Patrick',
|
||||
'Vyncint Smith',
|
||||
'Darrius Shepherd',
|
||||
'James Washington',
|
||||
'Collin Johnson',
|
||||
'Marcus Johnson',
|
||||
'Kalil Pimpleton',
|
||||
'Brandon Smith',
|
||||
'Dontario Drummond',
|
||||
'David Wells',
|
||||
'Tyler Davis',
|
||||
'Shaun Beyer',
|
||||
'Jack Coco',
|
||||
'Charlie Kolar',
|
||||
'Jalen Wydermyer',
|
||||
'Matt Sokol',
|
||||
'Blake Bell',
|
||||
'Jordan Franks',
|
||||
'Kendall Blanton',
|
||||
'James Winchester',
|
||||
'Drew Ogletree',
|
||||
'Jared Scott',
|
||||
'Nikola Kalinic',
|
||||
'Rodney Williams II',
|
||||
'Jesse James',
|
||||
'Miller Forristall',
|
||||
'Zaire Mitchell-Paden',
|
||||
'Colin Thompson',
|
||||
'Josh Babicz',
|
||||
'Lucas Krull',
|
||||
'Zach Wood',
|
||||
'J.P. Holtz',
|
||||
'Patrick Scales',
|
||||
'Chase Allen',
|
||||
'Teagan Quitoriano',
|
||||
'Mason Schreck',
|
||||
'Adam Shaheen',
|
||||
'Zach Davidson',
|
||||
'Andrew DePaola',
|
||||
'Nick Muse',
|
||||
'Garrett Griffin',
|
||||
'Lawrence Cager',
|
||||
'Cal Adomitis',
|
||||
'Clark Harris',
|
||||
'Nick Bowers',
|
||||
'Cole Fotheringham',
|
||||
'Tommy Hudson',
|
||||
'Thomas Odukoya',
|
||||
'Kevin Rader',
|
||||
'Curtis Hodges',
|
||||
'Eli Wolf',
|
||||
'Tyree Jackson',
|
||||
'Dalton Keene',
|
||||
'Gerrit Prince',
|
||||
'Stone Smartt',
|
||||
'Hunter Kampmoyer',
|
||||
'Bernhard Seikovits',
|
||||
'Jared Pinkney',
|
||||
'Roger Carter Jr.',
|
||||
'Tyler Mabry',
|
||||
'Tyler Ott',
|
||||
'Feleipe Franks',
|
||||
'John FitzPatrick',
|
||||
'MyCole Pruitt',
|
||||
'Beau Brinkley',
|
||||
'Tucker Fisk',
|
||||
'Jordan Matthews',
|
||||
'Troy Fumagalli',
|
||||
'Greg Dulcich',
|
||||
'Dominique Dafney',
|
||||
'Austin Allen',
|
||||
'Ian Bunting',
|
||||
'Sean McKeon'
|
||||
}
|
||||
|
||||
# All of these players don't have the expected url param.
|
||||
# TODO Is this actually DRAFT_KINGS_NAME_TO_FPROS_URL_PARAM?
|
||||
FPROS_NAME_TO_URL_PARAM = {
|
||||
'Bisi Johnson': 'olabisi-johnson',
|
||||
'Brian Robinson Jr.': 'brian-robinson-jr',
|
||||
'Cameron Batson': 'cam-batson',
|
||||
'Drew Ogletree': 'andrew-ogletree',
|
||||
'Dylan Parham': 'dylan-parham-te',
|
||||
'Gabe Davis': 'gabriel-davis',
|
||||
'Gerrit Prince': 'gerrit-prince-te',
|
||||
'Johnny Johnson III': 'johnny-johnson-iii',
|
||||
'Kevin Rader': 'kevin-radar',
|
||||
'P.J. Walker': 'phillip-walker',
|
||||
'Pierre Strong Jr.': 'pierre-strong-jr',
|
||||
'Ricky Person Jr.': 'ricky-person-jr',
|
||||
'Ronald Jones II': 'ronald-jones-ii',
|
||||
'Scotty Miller': 'scott-miller',
|
||||
'Spencer Brown': 'spencer-brown-rb',
|
||||
'Troy Hairston': 'troy-hairston-ii',
|
||||
'Velus Jones Jr.': 'velus-jonesjr',
|
||||
'Willie Johnson': 'willie-jackson'
|
||||
}
|
||||
|
||||
|
||||
class FantasyProsPlayerProjection:
|
||||
|
||||
def __init__(self, name, proj_points):
|
||||
self.name = name
|
||||
self.proj_points = proj_points
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__dict__)
|
||||
Loading…
Reference in New Issue