Skip to content

Commit

Permalink
rewrite to make Players class testable. get_team is extracted from Pl…
Browse files Browse the repository at this point in the history
…ayers and is a variable now
  • Loading branch information
razinc committed Oct 4, 2023
1 parent ad3b959 commit 051acd8
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 123 deletions.
217 changes: 108 additions & 109 deletions custom/players.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from tqdm import tqdm

from custom.constant import Gameweek

from custom.teams import teams

class Players:
def __init__(self, fpl_ids=None, skips=[], ownership=None):
Expand All @@ -19,122 +19,121 @@ def __init__(self, fpl_ids=None, skips=[], ownership=None):
else:
self.fpl_ids = fpl_ids
self.skips = skips
asyncio.run(self.set_attr(ownership))
self.builder(ownership)

async def set_attr(self, ownership):
def builder(self, ownership):
stats = {}
async with aiohttp.ClientSession() as session:
fpl = FPL(session)
players = await fpl.get_players(self.fpl_ids, include_summary=True)
if ownership is not None:
desc = "Parsing top ownership players "
elif self.fpl_ids is None:
desc = "Analysing all players"
else:
desc = "Analysing user's team"
for player in tqdm(players, desc=desc):
fpl_id = player.id

# skip players on loan/ transfer
if player.status == "u":
continue

if fpl_id in self.skips:
players = asyncio.run(self.get_players())
if ownership is not None:
desc = "Parsing top ownership players "
elif self.fpl_ids is None:
desc = "Analysing all players"
else:
desc = "Analysing user's team"
for player in tqdm(players, desc=desc):
fpl_id = player["id"]

# skip players on loan/transfer
if player["status"] == "u":
continue

if fpl_id in self.skips:
continue

element_type = player["element_type"]
if element_type == 1:
pos = "GK"
if element_type == 2:
pos = "DEF"
if element_type == 3:
pos = "MID"
if element_type == 4:
pos = "FOR"

latest_price = player["now_cost"] / 10
try:
price_change = round(
latest_price - player["history"][-1]["value"] / 10, 1
)
# player has not plays yet
except IndexError:
pass

history = player["history"]
rounds = [i["round"] for i in history]
pts_prev_n_gw = {}
total_pts_prev_n_gw = 0
for gw in Gameweek.PREV_N_GWS:
if gw not in rounds:
pts_prev_n_gw[gw] = "Blank GW"
continue

team = await fpl.get_team(player.team)
team_short_name = team.short_name

element_type = player.element_type
if element_type == 1:
pos = "GK"
if element_type == 2:
pos = "DEF"
if element_type == 3:
pos = "MID"
if element_type == 4:
pos = "FOR"

latest_price = player.now_cost / 10
try:
price_change = round(
latest_price - player.history[-1]["value"] / 10, 1
else:
pts_prev_n_gw[gw] = 0
for i in [i for i, j in enumerate(rounds) if j == gw]:
pts_prev_n_gw[gw] = (
pts_prev_n_gw[gw] + history[i]["total_points"]
)
total_pts_prev_n_gw = (
total_pts_prev_n_gw + history[i]["total_points"]
)
# player has not plays yet
except IndexError:
pass

history = player.history
rounds = [i["round"] for i in history]
pts_prev_n_gw = {}
total_pts_prev_n_gw = 0
for gw in Gameweek.PREV_N_GWS:
if gw not in rounds:
pts_prev_n_gw[gw] = "Blank GW"
continue
else:
pts_prev_n_gw[gw] = 0
for i in [i for i, j in enumerate(rounds) if j == gw]:
pts_prev_n_gw[gw] = (
pts_prev_n_gw[gw] + history[i]["total_points"]
)
total_pts_prev_n_gw = (
total_pts_prev_n_gw + history[i]["total_points"]
)

fixtures = {}
fixture_difficulty_sum = 0
total_games = 0
gameweeks = [i.get("event_name") for i in player.fixtures]
for gw in Gameweek.NEXT_N_GWS:
fixtures[gw] = []
if f"Gameweek {gw}" in gameweeks:
indices = [
i for i, x in enumerate(gameweeks) if x == f"Gameweek {gw}"
]
for i in indices:
if player.fixtures[i]["is_home"] == True:
team_code = player.fixtures[i]["team_a"]
where = "H"
else:
team_code = player.fixtures[i]["team_h"]
where = "A"
difficulty = player.fixtures[i]["difficulty"]
fixture_difficulty_sum = fixture_difficulty_sum + difficulty
total_games = total_games + 1
team_against = await fpl.get_team(team_code)
team_against_short_name = team_against.short_name
fixtures[gw].append(
f"{team_against_short_name} ({where}) ({difficulty})"
)
else:
fixtures[gw] = ["Blank GW"]

stats[fpl_id] = {
"web_name": player.web_name,
"team_short_name": team_short_name,
"pos": pos,
"latest_price": f"£{latest_price}",
"price_change": f"£{price_change}",
"xg": player.expected_goals,
"xa": player.expected_assists,
"sum_xg_xa": float(player.expected_goals)
+ float(player.expected_assists),
"pts_prev_n_gw": pts_prev_n_gw,
"total_pts_prev_n_gw": total_pts_prev_n_gw,
"ep_this": float(player.ep_this),
"ep_next": float(player.ep_next),
"fixtures": fixtures,
"fixture_difficulty_avg": round(
fixture_difficulty_sum / total_games, 1
),
}

if ownership is not None:
stats[fpl_id]["ownership"] = f"{ownership[fpl_id]}%"
fixtures = {}
fixture_difficulty_sum = 0
total_games = 0
gameweeks = [i.get("event_name") for i in player["fixtures"]]
for gw in Gameweek.NEXT_N_GWS:
fixtures[gw] = []
if f"Gameweek {gw}" in gameweeks:
indices = [
i for i, x in enumerate(gameweeks) if x == f"Gameweek {gw}"
]
for i in indices:
if player["fixtures"][i]["is_home"] == True:
team_id = player["fixtures"][i]["team_a"]
where = "H"
else:
team_id = player["fixtures"][i]["team_h"]
where = "A"
difficulty = player["fixtures"][i]["difficulty"]
fixture_difficulty_sum = fixture_difficulty_sum + difficulty
total_games = total_games + 1
team_against_short_name = teams[team_id]["short_name"]
fixtures[gw].append(
f"{team_against_short_name} ({where}) ({difficulty})"
)
else:
fixtures[gw] = ["Blank GW"]

stats[fpl_id] = {
"web_name": player["web_name"],
"team_short_name": teams[player["team"]]["short_name"],
"pos": pos,
"latest_price": f"£{latest_price}",
"price_change": f"£{price_change}",
"xg": player["expected_goals"],
"xa": player["expected_assists"],
"sum_xg_xa": float(player["expected_goals"])
+ float(player["expected_assists"]),
"pts_prev_n_gw": pts_prev_n_gw,
"total_pts_prev_n_gw": total_pts_prev_n_gw,
"ep_this": float(player["ep_this"]),
"ep_next": float(player["ep_next"]),
"fixtures": fixtures,
"fixture_difficulty_avg": round(
fixture_difficulty_sum / total_games, 1
),
}

if ownership is not None:
stats[fpl_id]["ownership"] = f"{ownership[fpl_id]}%"
self.stats = stats

async def get_players(self):
async with aiohttp.ClientSession() as session:
fpl = FPL(session)
players = await fpl.get_players(self.fpl_ids, return_json = True, include_summary=True)
return players

def sort_by_total_pts_prev_n_gw(self):
self.stats = OrderedDict(
sorted(
Expand Down
17 changes: 17 additions & 0 deletions custom/teams.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import asyncio
import aiohttp
from fpl import FPL

async def get_teams():
async with aiohttp.ClientSession() as session:
fpl = FPL(session)
teams = await fpl.get_teams(return_json = True)
return teams

def builder():
teams = {}
for team in asyncio.run(get_teams()):
teams[team["id"]] = {"short_name": team["short_name"]}
return teams

teams = builder()
105 changes: 91 additions & 14 deletions tests/test_players.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,96 @@
from custom.constant import Gameweek
import pytest

from custom.players import Players
from custom.constant import Gameweek

from custom.teams import teams


def test_init_with_mock(monkeypatch):
monkeypatch.setattr(Gameweek, "PREV_N_GWS", [5, 6])
monkeypatch.setattr(Gameweek, "NEXT_N_GWS", [8, 9])
monkeypatch.setitem(
teams, 7, {"short_name": "CHE"}
) # TODO: this works but only patch certain key value pair in the dict, patch the whole var?

def test_players(monkeypatch):
monkeypatch.setattr(Gameweek, "CURRENT_GW", 7)
monkeypatch.setattr(Gameweek, "NO_OF_PREV_GWS", 5)
monkeypatch.setattr(Gameweek, "PREV_N_GWS", [2, 3, 4, 5, 6])
monkeypatch.setattr(Gameweek, "NO_OF_NEXT_GWS", 5)
async def mock_get_players(self):
return [
{
"element_type": 3,
"ep_next": "3.2",
"ep_this": "2.7",
"form": "2.7",
"id": 202,
"now_cost": 54,
"status": "a",
"team": 7,
"web_name": "Gallagher",
"expected_goals": "0.52",
"expected_assists": "0.76",
"fixtures": [
{
"team_h": 6,
"team_a": 7,
"event_name": "Gameweek 8",
"is_home": False,
"difficulty": 2,
},
{
"team_h": 7,
"team_a": 1,
"event_name": "Gameweek 9",
"is_home": True,
"difficulty": 4,
},
],
"history": [
{
"round": 1,
},
{
"round": 2,
},
{
"round": 3,
},
{
"round": 4,
},
{
"total_points": 3,
"round": 5,
},
{
"total_points": 2,
"round": 6,
},
{
"total_points": 3,
"round": 7,
"value": 54,
},
],
}
]

fpl_id = 427
players = Players(fpl_ids=[fpl_id])
monkeypatch.setattr(Players, "get_players", mock_get_players)

assert players.stats[fpl_id]["web_name"] == "Kane"
assert players.stats[fpl_id]["team_short_name"] == "TOT"
assert players.stats[fpl_id]["pos"] == "FOR"
assert players.stats[fpl_id]["understat_id"] == 647
assert players.stats[fpl_id]["pts_prev_n_gw"] == {2: 8, 3: 6, 4: 10, 5: 5, 6: 9}
assert players.stats[fpl_id]["total_pts_prev_n_gw"] == 38
players = Players(fpl_ids=[202])
assert players.stats == {
202: {
"web_name": "Gallagher",
"team_short_name": "CHE",
"pos": "MID",
"latest_price": "£5.4",
"price_change": "£0.0",
"xg": "0.52",
"xa": "0.76",
"sum_xg_xa": 1.28,
"pts_prev_n_gw": {5: 3, 6: 2},
"total_pts_prev_n_gw": 5,
"ep_this": 2.7,
"ep_next": 3.2,
"fixtures": {8: ["BUR (A) (2)"], 9: ["ARS (H) (4)"]},
"fixture_difficulty_avg": 3.0,
}
}
Loading

0 comments on commit 051acd8

Please sign in to comment.