diff --git a/custom/players.py b/custom/players.py index 3de741c..a58e56d 100644 --- a/custom/players.py +++ b/custom/players.py @@ -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): @@ -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( diff --git a/custom/teams.py b/custom/teams.py new file mode 100644 index 0000000..0c7a681 --- /dev/null +++ b/custom/teams.py @@ -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() diff --git a/tests/test_players.py b/tests/test_players.py index 8e1d8ae..033fbb0 100644 --- a/tests/test_players.py +++ b/tests/test_players.py @@ -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, + } + } diff --git a/tests/test_teams.py b/tests/test_teams.py new file mode 100644 index 0000000..35d5b46 --- /dev/null +++ b/tests/test_teams.py @@ -0,0 +1,61 @@ +import pytest + +from custom.teams import get_teams +from custom.teams import builder + + +def test_teams(monkeypatch): + async def mock_get_teams(): + return [ + { + "code": 3, + "draw": 0, + "form": None, + "id": 1, + "loss": 0, + "name": "Arsenal", + "played": 0, + "points": 0, + "position": 0, + "short_name": "ARS", + "strength": 4, + "team_division": None, + "unavailable": False, + "win": 0, + "strength_overall_home": 1230, + "strength_overall_away": 1285, + "strength_attack_home": 1250, + "strength_attack_away": 1250, + "strength_defence_home": 1210, + "strength_defence_away": 1320, + "pulse_id": 1, + }, + { + "code": 7, + "draw": 0, + "form": None, + "id": 2, + "loss": 0, + "name": "Aston Villa", + "played": 0, + "points": 0, + "position": 0, + "short_name": "AVL", + "strength": 3, + "team_division": None, + "unavailable": False, + "win": 0, + "strength_overall_home": 1115, + "strength_overall_away": 1175, + "strength_attack_home": 1130, + "strength_attack_away": 1190, + "strength_defence_home": 1100, + "strength_defence_away": 1160, + "pulse_id": 2, + }, + ] + + monkeypatch.setattr("custom.teams.get_teams", mock_get_teams) + + teams = builder() + assert teams == {1: {"short_name": "ARS"}, 2: {"short_name": "AVL"}}