From 7c9ca190931d4a5269ac772b7718e01f39385ed4 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Sat, 19 Oct 2019 02:21:47 +0100 Subject: [PATCH 01/10] return id indexed dicts for fixtures, teams, players etc --- fpl/fpl.py | 32 +++++++++++++++++------------ tests/test_fpl.py | 52 +++++++++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/fpl/fpl.py b/fpl/fpl.py index 8c94dc0..9d3c5aa 100644 --- a/fpl/fpl.py +++ b/fpl/fpl.py @@ -39,7 +39,7 @@ position_converter, scale, team_converter) -class FPL(): +class FPL: """The FPL class.""" def __init__(self, session): @@ -102,8 +102,8 @@ async def get_teams(self, team_ids=None, return_json=False): if return_json: return teams - return [Team(team_information, self.session) - for team_information in teams] + return {team_information["id"]: Team(team_information, self.session) + for team_information in teams} async def get_team(self, team_id, return_json=False): """Returns the team with the given ``team_id``. @@ -177,6 +177,7 @@ async def get_player_summary(self, player_id, return_json=False): return PlayerSummary(player_summary) + # not used async def get_player_summaries(self, player_ids, return_json=False): """Returns a list of summaries of players whose ID are in the ``player_ids`` list. @@ -275,7 +276,10 @@ async def get_players(self, player_ids=None, include_summary=False, for player_id in player_ids] players = await asyncio.gather(*tasks) - return players + if return_json: + return list(filter(lambda p: p["id"] in player_ids, players)) + + return {player.id: player for player in players} async def get_fixture(self, fixture_id, return_json=False): """Returns the fixture with the given ``fixture_id``. @@ -352,7 +356,7 @@ async def get_fixtures_by_id(self, fixture_ids, return_json=False): if return_json: return fixtures - return [Fixture(fixture) for fixture in fixtures] + return {fixture["id"]: Fixture(fixture) for fixture in fixtures} async def get_fixtures_by_gameweek(self, gameweek, return_json=False): """Returns a list of all fixtures of the given ``gameweek``. @@ -375,7 +379,7 @@ async def get_fixtures_by_gameweek(self, gameweek, return_json=False): if return_json: return fixtures - return [Fixture(fixture) for fixture in fixtures] + return {fixture["id"]: Fixture(fixture) for fixture in fixtures} async def get_fixtures(self, return_json=False): """Returns a list of *all* fixtures. @@ -402,10 +406,9 @@ async def get_fixtures(self, return_json=False): if return_json: return fixtures - return [Fixture(fixture) for fixture in fixtures] + return {fixture["id"]: Fixture(fixture) for fixture in fixtures} - async def get_gameweek(self, gameweek_id, include_live=False, - return_json=False): + async def get_gameweek(self, gameweek_id, return_json=False): """Returns the gameweek with the ID ``gameweek_id``. Information is taken from e.g.: @@ -441,8 +444,7 @@ async def get_gameweek(self, gameweek_id, include_live=False, return Gameweek(static_gameweek) - async def get_gameweeks(self, gameweek_ids=None, include_live=False, - return_json=False): + async def get_gameweeks(self, gameweek_ids=None, return_json=False): """Returns either a list of *all* gamweeks, or a list of gameweeks whose IDs are in the ``gameweek_ids`` list. @@ -462,11 +464,15 @@ async def get_gameweeks(self, gameweek_ids=None, include_live=False, gameweek_ids = range(1, 39) tasks = [asyncio.ensure_future( - self.get_gameweek(gameweek_id, include_live, return_json)) + self.get_gameweek(gameweek_id, return_json)) for gameweek_id in gameweek_ids] gameweeks = await asyncio.gather(*tasks) - return gameweeks + + if return_json: + return gameweeks + + return {gameweek.id: gameweek for gameweek in gameweeks} async def get_classic_league(self, league_id, return_json=False): """Returns the classic league with the given ``league_id``. Requires diff --git a/tests/test_fpl.py b/tests/test_fpl.py index 84a6cbb..cc24dc8 100644 --- a/tests/test_fpl.py +++ b/tests/test_fpl.py @@ -50,20 +50,20 @@ async def test_team(self, loop, fpl): async def test_teams(self, loop, fpl): teams = await fpl.get_teams() - assert isinstance(teams, list) - assert len(teams) == 20 - assert isinstance(teams[0], Team) + assert isinstance(teams, dict) + assert len(teams.values()) == 20 + assert isinstance(teams[10], Team) teams = await fpl.get_teams(return_json=True) assert isinstance(teams, list) assert len(teams) == 20 - assert isinstance(teams[0], dict) + assert isinstance(teams[1], dict) teams = await fpl.get_teams(team_ids=[1, 2, 3]) - assert isinstance(teams, list) - assert len(teams) == 3 - assert isinstance(teams[0], Team) - assert [team.id for team in teams] == [1, 2, 3] + assert isinstance(teams, dict) + assert len(teams.values()) == 3 + assert isinstance(teams[1], Team) + assert [team.id for team in teams.values()] == [1, 2, 3] async def test_player_summary(self, loop, fpl): # test non positive id @@ -107,19 +107,24 @@ async def test_player(self, loop, fpl): async def test_players(self, loop, fpl): players = await fpl.get_players() - assert isinstance(players, list) - assert isinstance(players[0], Player) + assert isinstance(players, dict) + assert isinstance(players[1], Player) players = await fpl.get_players(return_json=True) assert isinstance(players, list) assert isinstance(players[0], dict) players = await fpl.get_players([1, 2, 3]) - assert len(players) == 3 + assert len(players.values()) == 3 - players = await fpl.get_players([1, 2, 3], True) + players = await fpl.get_players([1, 2, 3], include_summary=True) + assert len(players.values()) == 3 + summary_keys = ("history_past", "history", "fixtures") + assert all([isinstance(getattr(players[2], key), list) for key in summary_keys]) + + players = await fpl.get_players([1, 2, 3], include_summary=True, return_json=True) assert len(players) == 3 - assert isinstance(players[0].fixtures, list) + assert all([isinstance(players[2][key], list) for key in summary_keys]) async def test_fixture(self, loop, fpl): # test fixture with unknown id @@ -139,8 +144,8 @@ async def test_fixtures_by_id(self, loop, fpl): assert len(fixtures) == 0 fixtures = await fpl.get_fixtures_by_id([100, 200, 300]) - assert isinstance(fixtures, list) - assert isinstance(fixtures[0], Fixture) + assert isinstance(fixtures, dict) + assert isinstance(fixtures[100], Fixture) fixtures = await fpl.get_fixtures_by_id( [100, 200, 300], return_json=True) @@ -153,8 +158,8 @@ async def test_fixtures_by_id(self, loop, fpl): async def test_fixtures_by_gameweek(self, loop, fpl): for gameweek in range(1, 39): fixtures = await fpl.get_fixtures_by_gameweek(gameweek) - assert isinstance(fixtures, list) - assert isinstance(fixtures[0], Fixture) + assert isinstance(fixtures, dict) + assert all([isinstance(fixtures[fixture_id], Fixture) for fixture_id in fixtures.keys()]) fixtures = await fpl.get_fixtures_by_gameweek( gameweek, return_json=True) @@ -162,17 +167,17 @@ async def test_fixtures_by_gameweek(self, loop, fpl): async def test_fixtures(self, loop, fpl): fixtures = await fpl.get_fixtures() - assert isinstance(fixtures, list) - assert isinstance(fixtures[0], Fixture) + assert isinstance(fixtures, dict) + assert isinstance(fixtures[10], Fixture) fixtures = await fpl.get_fixtures(return_json=True) assert isinstance(fixtures[0], dict) async def test_gameweeks(self, loop, fpl): gameweeks = await fpl.get_gameweeks() - assert isinstance(gameweeks, list) - assert len(gameweeks) == 38 - assert isinstance(gameweeks[0], Gameweek) + assert isinstance(gameweeks, dict) + assert len(gameweeks.values()) == 38 + assert isinstance(gameweeks[10], Gameweek) gameweeks = await fpl.get_gameweeks([1, 2, 3], return_json=True) assert isinstance(gameweeks, list) @@ -183,9 +188,12 @@ async def test_gameweek(self, loop, fpl): gameweek = await fpl.get_gameweek(20) assert isinstance(gameweek, Gameweek) assert gameweek.id == 20 + assert not hasattr(gameweek, "elements") gameweek = await fpl.get_gameweek(20, return_json=True) assert isinstance(gameweek, dict) + assert gameweek["id"] == 20 + assert "elements" not in gameweek.keys() async def test_classic_league(self, loop, fpl): await fpl.login() From 45c52a59357b173f6c03459e04ffc07482a1c0b0 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Sat, 19 Oct 2019 02:30:21 +0100 Subject: [PATCH 02/10] . --- tests/test_fpl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_fpl.py b/tests/test_fpl.py index 4390bfb..4f3927f 100644 --- a/tests/test_fpl.py +++ b/tests/test_fpl.py @@ -182,6 +182,7 @@ async def test_gameweeks(self, loop, fpl): async def test_gameweek(self, loop, fpl): gameweek = await fpl.get_gameweek(20) assert isinstance(gameweek, Gameweek) + # noinspection PyUnresolvedReferences assert gameweek.id == 20 assert not hasattr(gameweek, "elements") @@ -193,6 +194,7 @@ async def test_gameweek(self, loop, fpl): gameweek = await fpl.get_gameweek(1, include_live=True) assert isinstance(gameweek, Gameweek) assert hasattr(gameweek, "elements") + # noinspection PyUnresolvedReferences assert isinstance(gameweek.elements, dict) gameweek = await fpl.get_gameweek(1, include_live=True, return_json=True) @@ -200,7 +202,6 @@ async def test_gameweek(self, loop, fpl): assert "elements" in gameweek.keys() assert isinstance(gameweek["elements"], dict) - @pytest.mark.skip(reason="Cannot currently test it.") async def test_classic_league(self, loop, fpl): await fpl.login() @@ -253,6 +254,7 @@ async def test_points_against(self, loop, fpl): points_against = await fpl.get_points_against() assert isinstance(points_against, dict) + # noinspection PyPep8Naming async def test_FDR(self, loop, fpl): def test_main(fdr): assert isinstance(fdr, dict) From b60c788c55480ba92ed4731ffc11c617758e8bc7 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Sat, 19 Oct 2019 14:36:07 +0100 Subject: [PATCH 03/10] apply live scores to players --- fpl/fpl.py | 31 ++++++++++++++++++++----------- tests/test_fpl.py | 11 +++++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/fpl/fpl.py b/fpl/fpl.py index b0fb03c..12087a5 100644 --- a/fpl/fpl.py +++ b/fpl/fpl.py @@ -216,7 +216,7 @@ async def get_player_summaries(self, player_ids, return_json=False): return [PlayerSummary(player_summary) for player_summary in player_summaries] - async def get_player(self, player_id, players=None, include_summary=False, + async def get_player(self, player_id, players=None, gameweek=None, include_summary=False, return_json=False): """Returns the player with the given ``player_id``. @@ -224,6 +224,7 @@ async def get_player(self, player_id, players=None, include_summary=False, https://fantasy.premierleague.com/api/bootstrap-static/ https://fantasy.premierleague.com/api/element-summary/1/ (optional) + :param gameweek: the current gameweek data (for applying live scores) :param player_id: A player's ID. :type player_id: string or int :param list players: (optional) A list of players. @@ -249,12 +250,15 @@ async def get_player(self, player_id, players=None, include_summary=False, player["id"], return_json=True) player.update(player_summary) + if gameweek: + player["live_score"] = gameweek.elements[player_id]["stats"]["total_points"] + if return_json: return player return Player(player, self.session) - async def get_players(self, player_ids=None, include_summary=False, + async def get_players(self, player_ids=None, include_summary=False, include_live=None, return_json=False): """Returns either a list of *all* players, or a list of players whose IDs are in the given ``player_ids`` list. @@ -263,6 +267,7 @@ async def get_players(self, player_ids=None, include_summary=False, https://fantasy.premierleague.com/api/bootstrap-static/ https://fantasy.premierleague.com/api/element-summary/1/ (optional) + :param include_live: (optional) include a player's live score :param list player_ids: (optional) A list of player IDs :param boolean include_summary: (optional) Includes a player's summary if ``True``. @@ -273,13 +278,17 @@ async def get_players(self, player_ids=None, include_summary=False, :rtype: list """ players = getattr(self, "elements") + gameweek = None if not player_ids: player_ids = [player["id"] for player in players.values()] + if include_live: + gameweek = await self.get_gameweek(getattr(self, "current_gameweek"), include_live=True) + tasks = [asyncio.ensure_future( self.get_player( - player_id, players, include_summary, return_json)) + player_id, players, gameweek, include_summary, return_json)) for player_id in player_ids] players = await asyncio.gather(*tasks) @@ -415,7 +424,7 @@ async def get_fixtures(self, return_json=False): return {fixture["id"]: Fixture(fixture) for fixture in fixtures} - async def get_gameweek(self, gameweek_id, return_json=False): + async def get_gameweek(self, gameweek_id, include_live=False, return_json=False): """Returns the gameweek with the ID ``gameweek_id``. Information is taken from e.g.: @@ -423,7 +432,7 @@ async def get_gameweek(self, gameweek_id, return_json=False): https://fantasy.premierleague.com/api/event/1/live/ :param int gameweek_id: A gameweek's ID. - :param bool include_summary: (optional) Includes a gameweek's live data + :param bool include_live: (optional) Includes a gameweek's live data if ``True``. :param return_json: (optional) Boolean. If ``True`` returns a ``dict``, if ``False`` returns a :class:`Gameweek` object. Defaults to @@ -450,16 +459,16 @@ async def get_gameweek(self, gameweek_id, return_json=False): # include live bonus points if not static_gameweek['finished']: fixtures = await self.get_fixtures_by_gameweek(gameweek_id) - fixtures = filter(lambda f: not f.finished, fixtures) + fixtures = filter(lambda f: not f.finished, fixtures.values()) bonus_for_gameweek = [] for fixture in fixtures: bonus = fixture.get_bonus(provisional=True) bonus_for_gameweek.extend(bonus['a'] + bonus['h']) bonus_for_gameweek = {b['element']: b['value'] for b in bonus_for_gameweek} - for player_id, bonus_points in bonus_for_gameweek: - if live_gameweek["elements"][player_id]["bonus"] == 0: - live_gameweek["elements"][player_id]["bonus"] += bonus_points - live_gameweek["elements"][player_id]["total_points"] += bonus_points + for player_id, bonus_points in bonus_for_gameweek.items(): + if live_gameweek["elements"][player_id]["stats"]["bonus"] == 0: + live_gameweek["elements"][player_id]["stats"]["bonus"] += bonus_points + live_gameweek["elements"][player_id]["stats"]["total_points"] += bonus_points static_gameweek.update(live_gameweek) @@ -488,7 +497,7 @@ async def get_gameweeks(self, gameweek_ids=None, return_json=False): gameweek_ids = range(1, 39) tasks = [asyncio.ensure_future( - self.get_gameweek(gameweek_id, return_json)) + self.get_gameweek(gameweek_id, False, return_json)) for gameweek_id in gameweek_ids] gameweeks = await asyncio.gather(*tasks) diff --git a/tests/test_fpl.py b/tests/test_fpl.py index 69e6831..036fdb4 100644 --- a/tests/test_fpl.py +++ b/tests/test_fpl.py @@ -137,6 +137,10 @@ async def test_players(self, loop, fpl): summary_keys = ("history_past", "history", "fixtures") assert all([isinstance(getattr(players[2], key), list) for key in summary_keys]) + players = await fpl.get_players([1, 2, 3], include_live=True) + assert len(players.values()) == 3 + assert isinstance(getattr(players[2], "live_score"), int) + players = await fpl.get_players([1, 2, 3], include_summary=True, return_json=True) assert len(players) == 3 assert all([isinstance(players[2][key], list) for key in summary_keys]) @@ -222,7 +226,6 @@ async def test_gameweek(self, loop, fpl): assert "elements" in gameweek.keys() assert isinstance(gameweek["elements"], dict) - @pytest.mark.skip(reason="Cannot currently test it.") async def test_classic_league(self, loop, fpl): await fpl.login() classic_league = await fpl.get_classic_league(173226) @@ -276,11 +279,11 @@ async def test_points_against(self, loop, fpl): # noinspection PyPep8Naming async def test_FDR(self, loop, fpl): - def test_main(fdr): - assert isinstance(fdr, dict) + def test_main(fdr_): + assert isinstance(fdr_, dict) location_extrema = {"H": [], "A": []} - for _, positions in fdr.items(): + for _, positions in fdr_.items(): for location in positions.values(): location_extrema["H"].append(location["H"]) location_extrema["A"].append(location["A"]) From aa6eb6fa94c1226bfce3ea014fc5995b824ba991 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Sun, 20 Oct 2019 20:30:47 +0100 Subject: [PATCH 04/10] get user live score (tests not done yet) --- fpl/fpl.py | 17 ++++- fpl/models/user.py | 180 +++++++++++++++++++++++++++++++-------------- 2 files changed, 140 insertions(+), 57 deletions(-) diff --git a/fpl/fpl.py b/fpl/fpl.py index 12087a5..15abf1b 100644 --- a/fpl/fpl.py +++ b/fpl/fpl.py @@ -250,8 +250,12 @@ async def get_player(self, player_id, players=None, gameweek=None, include_summa player["id"], return_json=True) player.update(player_summary) + player["image_url"] = f'https://platform-static-files.s3.amazonaws.com' \ + f'/premierleague/photos/players/110x140/p{player["code"]}.png' + if gameweek: player["live_score"] = gameweek.elements[player_id]["stats"]["total_points"] + player["did_not_play"] = gameweek.elements[player_id]["did_not_play"] if return_json: return player @@ -459,9 +463,9 @@ async def get_gameweek(self, gameweek_id, include_live=False, return_json=False) # include live bonus points if not static_gameweek['finished']: fixtures = await self.get_fixtures_by_gameweek(gameweek_id) - fixtures = filter(lambda f: not f.finished, fixtures.values()) + fixtures_not_finished = filter(lambda f: not f.finished, fixtures.values()) bonus_for_gameweek = [] - for fixture in fixtures: + for fixture in fixtures_not_finished: bonus = fixture.get_bonus(provisional=True) bonus_for_gameweek.extend(bonus['a'] + bonus['h']) bonus_for_gameweek = {b['element']: b['value'] for b in bonus_for_gameweek} @@ -470,6 +474,15 @@ async def get_gameweek(self, gameweek_id, include_live=False, return_json=False) live_gameweek["elements"][player_id]["stats"]["bonus"] += bonus_points live_gameweek["elements"][player_id]["stats"]["total_points"] += bonus_points + # mark players that did not play + fixtures_started = filter(lambda f: f.started, fixtures.values()) + fixtures_started = list(map(lambda f: f.id, fixtures_started)) + for element in live_gameweek["elements"].values(): + player_id = element["id"] + no_minutes = element["stats"]["minutes"] == 0 + game_started = any([game["fixture"] in fixtures_started for game in element["explain"]]) + live_gameweek["elements"][player_id]["did_not_play"] = no_minutes and game_started + static_gameweek.update(live_gameweek) if return_json: diff --git a/fpl/models/user.py b/fpl/models/user.py index 25ed616..c5d6407 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -103,7 +103,22 @@ def _set_captain(lineup, captain, captain_type, player_ids): player[captain_type] = True -class User(): +def _valid_formation(players): + positions = list(map(lambda x: x.element_type, players)) + g = positions.count(1) + d = positions.count(2) + m = positions.count(3) + f = positions.count(4) + return all([ + g == 1, + 3 <= d <= 5, + 2 <= m <= 5, + 1 <= f <= 3, + sum([g, d, m, f]) == 11 + ]) + + +class User: """A class representing a user of the Fantasy Premier League. >>> from fpl import FPL @@ -125,6 +140,11 @@ def __init__(self, user_information, session): for k, v in user_information.items(): setattr(self, k, v) + @property + async def history(self): + history = await fetch(self._session, API_URLS["user_history"].format(getattr(self, "id"))) + return history + async def get_gameweek_history(self, gameweek=None): """Returns a list containing the gameweek history of the user. @@ -134,20 +154,14 @@ async def get_gameweek_history(self, gameweek=None): :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: list if gameweek is ``None``, otherwise dict. """ - if hasattr(self, "_history"): - history = self._history - else: - history = await fetch( - self._session, API_URLS["user_history"].format(self.id)) - self._history = history + current = (await self.history)["current"] if gameweek is not None: valid_gameweek(gameweek) - return next(gw for gw in history["current"] - if gw["event"] == gameweek) + return next(gw for gw in current if gw["event"] == gameweek) - return history["current"] + return current async def get_season_history(self): """Returns a list containing the seasonal history of the user. @@ -157,14 +171,8 @@ async def get_season_history(self): :rtype: list """ - if hasattr(self, "_history"): - history = self._history - else: - history = await fetch( - self._session, API_URLS["user_history"].format(self.id)) - - self._history = history - return history["past"] + past = (await self.history)["past"] + return past async def get_chips_history(self, gameweek=None): """Returns a list containing the chip history of the user. @@ -175,25 +183,19 @@ async def get_chips_history(self, gameweek=None): :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: list """ - if hasattr(self, "_history"): - history = self._history - else: - history = await fetch( - self._session, API_URLS["user_history"].format(self.id)) - - self._history = history + chips = (await self.history)["chips"] if gameweek is not None: valid_gameweek(gameweek) try: - return next(chip for chip in history["chips"] - if chip["event"] == gameweek) + return next(chip for chip in chips if chip["event"] == gameweek) except StopIteration: return None - return history["chips"] + return chips - async def get_picks(self, gameweek=None): + @property + async def picks(self): """Returns a dict containing the user's picks each gameweek. Key is the gameweek number, value contains picks of the gameweek. @@ -204,34 +206,102 @@ async def get_picks(self, gameweek=None): :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: dict """ - if hasattr(self, "_picks"): - picks = self._picks - else: - tasks = [asyncio.ensure_future( - fetch(self._session, - API_URLS["user_picks"].format(self.id, gameweek))) - for gameweek in range(self.started_event, - self.current_event + 1)] - picks = await asyncio.gather(*tasks) - self._picks = picks - if gameweek is not None: - valid_gameweek(gameweek) - try: - pick = next(pick for pick in picks - if pick["entry_history"]["event"] == gameweek) - except StopIteration: - return {} - else: - return {pick["entry_history"]["event"]: pick["picks"]} + tasks = [asyncio.ensure_future( + fetch(self._session, API_URLS["user_picks"].format(getattr(self, "id"), gameweek)) + ) for gameweek in range(getattr(self, "started_event"), getattr(self, "current_event") + 1)] + picks = await asyncio.gather(*tasks) + picks = {p["entry_history"]["event"]: p for p in picks} + return picks - picks_out = {} - for pick in picks: - try: - picks_out[pick["entry_history"]["event"]] = pick["picks"] - except KeyError: - pass - return picks_out + @property + async def picks_for_current_gameweek(self): + """Returns a dict containing the user's picks each gameweek. + + Key is the gameweek number, value contains picks of the gameweek. + + Information is taken from e.g.: + https://fantasy.premierleague.com/api/entry/91928/event/1/picks/ + + :param gameweek: (optional): The gameweek. Defaults to ``None``. + :rtype: dict + """ + + current_gameweek = getattr(self, "current_event") + picks = await self.picks + return picks[current_gameweek] + + async def get_formation(self, players): + """ + Get a user's formation for the current gameweek + :param players: (required) player dict from fpl.get_players() + :return: The user's formation + :rtype string + """ + picks = await self.picks_for_current_gameweek + picks = picks["picks"] + first_xi = filter(lambda x: x['position'] <= 11, picks) # get starting 11 + first_xi_ids = map(lambda x: x['element'], first_xi) # get ids of starting 11 + # get positions of starting 11 + first_xi_element_types = list(map(lambda x: getattr(players[x], "element_type"), first_xi_ids)) + d = first_xi_element_types.count(2) + m = first_xi_element_types.count(3) + f = first_xi_element_types.count(4) + return f"{d}-{m}-{f}" + + async def get_live_score(self, players): + """ + Get a user's live score for the current gameweek + :param players: (required) player dict from fpl.get_players() with live scores + :return: The user's live score + :rtype int + """ + picks = await self.picks_for_current_gameweek + active_chip = picks["active_chip"] + picks = picks["picks"] + + first_xi = filter(lambda x: x['position'] <= 11, picks) + first_xi = map(lambda x: x['element'], first_xi) + first_xi = set(first_xi) + subs = filter(lambda x: x['position'] > 11, picks) + subs = map(lambda x: x['element'], subs) + subs = list(subs) + subs_out = filter(lambda x: players[x].did_not_play, first_xi) + subs_out = map(lambda x: players[x].id, subs_out) + subs_out = list(subs_out) + + if active_chip == "bboost": + first_xi.update(subs) + else: + for sub_out in subs_out: + i = 0 + first_xi.remove(sub_out) + first_xi.add(subs[0]) + valid_formation = _valid_formation(map(lambda x: players[x], first_xi)) + while not valid_formation and i <= 3: + i += 1 + first_xi.remove(subs[i - 1]) + first_xi.add(subs[i]) + valid_formation = _valid_formation(map(lambda x: players[x], first_xi)) + subs.pop(i) + + first_xi_live_scores = map(lambda x: getattr(players[x], "live_score"), first_xi) + + captain = next(pick["element"] for pick in picks if pick["is_captain"]) + try: + vice_captain = next( + pick["element"] for pick in picks if pick["is_vice_captain"] and pick["multiplier"] == 1) + except StopIteration: + vice_captain = None + + captain_points = getattr(players[captain], "live_score") + if captain in subs_out and vice_captain: + captain_points = getattr(players[vice_captain], "live_score") + + if active_chip == "3xc": + captain_points *= 2 + + return sum(first_xi_live_scores) + captain_points async def get_active_chips(self, gameweek=None): """Returns a list containing the user's active chip for each gameweek, From 7e4b95a29baf50ea7c4a49c24874bb5e8b9b4359 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Sun, 20 Oct 2019 21:52:15 +0100 Subject: [PATCH 05/10] transfers --- fpl/models/user.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/fpl/models/user.py b/fpl/models/user.py index c5d6407..cec788d 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -383,6 +383,22 @@ async def get_team(self): return response["picks"] + @property + async def transfers(self): + return await fetch(self._session, API_URLS["user_transfers"].format(getattr(self, "id"))) + + @property + async def transfers_for_current_gameweek(self): + current_gameweek = getattr(self, "current_event") + picks = await self.picks_for_current_gameweek + transfers = await self.transfers + transfers = list(filter(lambda x: x["event"] == current_gameweek, transfers)) + return { + "transfers_made": picks["entry_history"]["event_transfers"], + "transfers_cost": picks["entry_history"]["event_transfers_cost"], + "transfers": transfers + } + async def get_transfers(self, gameweek=None): """Returns either a list of all the user's transfers, or a list of transfers made in the given gameweek. @@ -423,23 +439,17 @@ async def get_latest_transfers(self): return transfers - # async def get_wildcards(self): - # """Returns a list containing information about when (and if) the user - # has played their wildcard(s). - - # Information is taken from e.g.: - # https://fantasy.premierleague.com/drf/entry/3808385/transfers - - # :rtype: list - # """ - # if hasattr(self, "_transfers"): - # return self._transfers["wildcards"] + async def get_wildcards(self): + """Returns a list containing information about when (and if) the user + has played their wildcard(s). - # transfers = await fetch( - # self._session, API_URLS["user_transfers"].format(self.id)) + Information is taken from e.g.: + https://fantasy.premierleague.com/drf/entry/3808385/history - # self._transfers = transfers - # return transfers["wildcards"] + :rtype: list + """ + chips_played = await self.get_chips_history() + return list(filter(lambda x: x["name"] == "wildcard", chips_played)) async def get_watchlist(self): """Returns the user's watchlist. Requires the user to have logged in From a38e172018e19a3bdf5f428a0be5876120b2b864 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Mon, 21 Oct 2019 00:12:00 +0100 Subject: [PATCH 06/10] points hit --- fpl/models/user.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fpl/models/user.py b/fpl/models/user.py index cec788d..6ff979f 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -258,6 +258,7 @@ async def get_live_score(self, players): """ picks = await self.picks_for_current_gameweek active_chip = picks["active_chip"] + points_hit = picks["entry_history"]["event_transfers_cost"] picks = picks["picks"] first_xi = filter(lambda x: x['position'] <= 11, picks) @@ -301,7 +302,7 @@ async def get_live_score(self, players): if active_chip == "3xc": captain_points *= 2 - return sum(first_xi_live_scores) + captain_points + return sum(first_xi_live_scores) + captain_points - points_hit async def get_active_chips(self, gameweek=None): """Returns a list containing the user's active chip for each gameweek, From 9942d93a38dbe93d6ba2317b3b70e14ce74a421d Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Mon, 21 Oct 2019 03:09:48 +0100 Subject: [PATCH 07/10] get total points pycharm cleanup --- fpl/models/user.py | 95 ++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/fpl/models/user.py b/fpl/models/user.py index 6ff979f..9d2be8b 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -1,9 +1,6 @@ import asyncio import json -import aiohttp -from urllib3.util import response - from ..constants import API_URLS from ..utils import fetch, logged_in, post, get_headers @@ -120,18 +117,17 @@ def _valid_formation(players): class User: """A class representing a user of the Fantasy Premier League. - - >>> from fpl import FPL - >>> import aiohttp - >>> import asyncio - >>> - >>> async def main(): - ... async with aiohttp.ClientSession() as session: - ... fpl = FPL(session) - ... user = await fpl.get_user(3808385) - ... print(user) - ... - >>> asyncio.run(main()) + # >>> from fpl import FPL + # >>> import aiohttp + # >>> import asyncio + # >>> + # >>> async def main(): + # ... async with aiohttp.ClientSession() as session: + # ... fpl = FPL(session) + # ... user = await fpl.get_user(3808385) + # ... print(user) + # ... + # >>> asyncio.run(main()) Amos Bastian - Netherlands """ @@ -203,7 +199,6 @@ async def picks(self): Information is taken from e.g.: https://fantasy.premierleague.com/api/entry/91928/event/1/picks/ - :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: dict """ @@ -223,7 +218,6 @@ async def picks_for_current_gameweek(self): Information is taken from e.g.: https://fantasy.premierleague.com/api/entry/91928/event/1/picks/ - :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: dict """ @@ -271,6 +265,7 @@ async def get_live_score(self, players): subs_out = map(lambda x: players[x].id, subs_out) subs_out = list(subs_out) + # noinspection SpellCheckingInspection if active_chip == "bboost": first_xi.update(subs) else: @@ -304,6 +299,21 @@ async def get_live_score(self, players): return sum(first_xi_live_scores) + captain_points - points_hit + async def get_live_total_points(self, players): + """ + Get a user's live total points + :param players: (required) player dict from fpl.get_players() with live scores + :return: The user's live overall points total + :rtype int + """ + history = await self.get_gameweek_history() + history = filter(lambda x: x["event"] < getattr(self, "current_event"), history) + history = map(lambda x: x["total_points"] - x["event_transfers cost"], history) + + live_score = + await self.get_live_score(players) + + return sum(history) + live_score + async def get_active_chips(self, gameweek=None): """Returns a list containing the user's active chip for each gameweek, or the active chip of the given gameweek. @@ -314,15 +324,7 @@ async def get_active_chips(self, gameweek=None): :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: list """ - if hasattr(self, "_picks"): - picks = self._picks - else: - tasks = [asyncio.ensure_future( - fetch(self._session, - API_URLS["user_picks"].format(self.id, gameweek))) - for gameweek in range(1, self.current_event + 1)] - picks = await asyncio.gather(*tasks) - self._picks = picks + picks = await self.picks if gameweek is not None: valid_gameweek(gameweek) @@ -344,15 +346,8 @@ async def get_automatic_substitutions(self, gameweek=None): :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: list """ - if hasattr(self, "_picks"): - picks = self._picks - else: - tasks = [asyncio.ensure_future( - fetch(self._session, - API_URLS["user_picks"].format(self.id, gameweek))) - for gameweek in range(1, self.current_event + 1)] - picks = await asyncio.gather(*tasks) - self._picks = picks + + picks = await self.picks if gameweek is not None: valid_gameweek(gameweek) @@ -377,7 +372,7 @@ async def get_team(self): raise Exception("User must be logged in.") response = await fetch( - self._session, API_URLS["user_team"].format(self.id)) + self._session, API_URLS["user_team"].format(getattr(self, "id"))) if response == {"details": "You cannot view this entry"}: raise ValueError("User ID does not match provided email address!") @@ -410,11 +405,8 @@ async def get_transfers(self, gameweek=None): :param gameweek: (optional): The gameweek. Defaults to ``None``. :rtype: list """ - transfers = getattr(self, "_transfers", None) - if not transfers: - transfers = await fetch( - self._session, API_URLS["user_transfers"].format(self.id)) - self._transfers = transfers + + transfers = await self.transfers if gameweek is not None: valid_gameweek(gameweek) @@ -436,7 +428,7 @@ async def get_latest_transfers(self): raise Exception("User must be logged in.") transfers = await fetch( - self._session, API_URLS["user_latest_transfers"].format(self.id)) + self._session, API_URLS["user_latest_transfers"].format(getattr(self, "id"))) return transfers @@ -467,14 +459,12 @@ async def get_watchlist(self): me = await fetch(self._session, API_URLS["me"]) return me["watched"] - def _get_transfer_payload( - self, players_out, players_in, user_team, players, wildcard, - free_hit): + def _get_transfer_payload(self, players_out, players_in, user_team, players, wildcard, free_hit): """Returns the payload needed to make the desired transfers.""" payload = { "confirmed": False, - "entry": self.id, - "event": self.current_event + 1, + "entry": getattr(self, "id"), + "event": getattr(self, "current_event") + 1, "transfers": [], "wildcard": wildcard, "freehit": free_hit @@ -509,7 +499,7 @@ async def transfer(self, players_out, players_in, max_hit=60, :param wildcard: bool, optional :param free_hit: Boolean for playing free hit, defaults to False :param free_hit: bool, optional - :return: Returns the response given by a succesful transfer. + :return: Returns the response given by a successful transfer. :rtype: dict """ if wildcard and free_hit: @@ -618,8 +608,7 @@ async def _create_new_lineup(self, players_in, players_out, lineup): lineup[in_i][is_vc], lineup[out_i][is_vc]) starters, subs = lineup[:11], lineup[11:] - new_starters = sorted(starters, key=lambda x: ( - x["element_type"] - 1) * 100 + x["position"]) + new_starters = sorted(starters, key=lambda x: (x["element_type"] - 1) * 100 + x["position"]) lineup = new_starters + subs for position, player in enumerate(lineup): @@ -645,7 +634,7 @@ async def _post_substitutions(self, lineup): headers = get_headers("https://fantasy.premierleague.com/a/team/my") await post( - self._session, API_URLS["user_team"].format(self.id) + "/", + self._session, API_URLS["user_team"].format(getattr(self, "id")) + "/", payload=payload, headers=headers) async def _captain_helper(self, captain, captain_type): @@ -725,5 +714,5 @@ async def substitute(self, players_in, players_out, captain=None, await self._post_substitutions(lineup) def __str__(self): - return (f"{self.player_first_name} {self.player_last_name} - " - f"{self.player_region_name}") + return (f"{getattr(self, 'player_first_name')} {getattr(self, 'player_last_name')} - " + f"{getattr(self, 'player_region_name')}") From d24917e09960bbbeb9de396e85d4db19340407d7 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Mon, 21 Oct 2019 23:11:58 +0100 Subject: [PATCH 08/10] requested amendments --- fpl/fpl.py | 9 +++--- fpl/models/user.py | 73 ++++++++++++++++++++++++---------------------- fpl/utils.py | 12 +++++--- 3 files changed, 50 insertions(+), 44 deletions(-) diff --git a/fpl/fpl.py b/fpl/fpl.py index 15abf1b..7d5a0cf 100644 --- a/fpl/fpl.py +++ b/fpl/fpl.py @@ -297,9 +297,9 @@ async def get_players(self, player_ids=None, include_summary=False, include_live players = await asyncio.gather(*tasks) if return_json: - return list(filter(lambda p: p["id"] in player_ids, players)) + return [player for player in players if player["id"] in player_ids] - return {player.id: player for player in players} + return {player.id: player for player in players if player.id in player_ids} async def get_fixture(self, fixture_id, return_json=False): """Returns the fixture with the given ``fixture_id``. @@ -463,7 +463,7 @@ async def get_gameweek(self, gameweek_id, include_live=False, return_json=False) # include live bonus points if not static_gameweek['finished']: fixtures = await self.get_fixtures_by_gameweek(gameweek_id) - fixtures_not_finished = filter(lambda f: not f.finished, fixtures.values()) + fixtures_not_finished = [fixture for fixture in fixtures.values() if not fixture.finished] bonus_for_gameweek = [] for fixture in fixtures_not_finished: bonus = fixture.get_bonus(provisional=True) @@ -475,8 +475,7 @@ async def get_gameweek(self, gameweek_id, include_live=False, return_json=False) live_gameweek["elements"][player_id]["stats"]["total_points"] += bonus_points # mark players that did not play - fixtures_started = filter(lambda f: f.started, fixtures.values()) - fixtures_started = list(map(lambda f: f.id, fixtures_started)) + fixtures_started = [fixture.id for fixture in fixtures.values() if fixture.started] for element in live_gameweek["elements"].values(): player_id = element["id"] no_minutes = element["stats"]["minutes"] == 0 diff --git a/fpl/models/user.py b/fpl/models/user.py index 9d2be8b..108a6dc 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -101,7 +101,7 @@ def _set_captain(lineup, captain, captain_type, player_ids): def _valid_formation(players): - positions = list(map(lambda x: x.element_type, players)) + positions = [player.element_type for player in players] g = positions.count(1) d = positions.count(2) m = positions.count(3) @@ -115,6 +115,14 @@ def _valid_formation(players): ]) +def _get_first_xi(picks, players): + return [players[pick["element"]].id for pick in picks if pick["position"] <= 11] + + +def _get_subs(picks, players): + return [players[pick["element"]].id for pick in picks if pick["position"] > 11] + + class User: """A class representing a user of the Fantasy Premier League. # >>> from fpl import FPL @@ -234,13 +242,10 @@ async def get_formation(self, players): """ picks = await self.picks_for_current_gameweek picks = picks["picks"] - first_xi = filter(lambda x: x['position'] <= 11, picks) # get starting 11 - first_xi_ids = map(lambda x: x['element'], first_xi) # get ids of starting 11 - # get positions of starting 11 - first_xi_element_types = list(map(lambda x: getattr(players[x], "element_type"), first_xi_ids)) - d = first_xi_element_types.count(2) - m = first_xi_element_types.count(3) - f = first_xi_element_types.count(4) + first_xi = [players[player_id].element_type for player_id in _get_first_xi(picks, players)] + d = first_xi.count(2) + m = first_xi.count(3) + f = first_xi.count(4) return f"{d}-{m}-{f}" async def get_live_score(self, players): @@ -255,46 +260,44 @@ async def get_live_score(self, players): points_hit = picks["entry_history"]["event_transfers_cost"] picks = picks["picks"] - first_xi = filter(lambda x: x['position'] <= 11, picks) - first_xi = map(lambda x: x['element'], first_xi) - first_xi = set(first_xi) - subs = filter(lambda x: x['position'] > 11, picks) - subs = map(lambda x: x['element'], subs) - subs = list(subs) - subs_out = filter(lambda x: players[x].did_not_play, first_xi) - subs_out = map(lambda x: players[x].id, subs_out) - subs_out = list(subs_out) - - # noinspection SpellCheckingInspection - if active_chip == "bboost": + first_xi = set(_get_first_xi(picks, players)) + subs = _get_subs(picks, players) + subs_out = [player_id for player_id in first_xi if players[player_id].did_not_play] + + if active_chip == "bboost": # count scores for all 15 players if bench boost chip is active first_xi.update(subs) else: + # perform auto-subs if applicable for sub_out in subs_out: i = 0 - first_xi.remove(sub_out) - first_xi.add(subs[0]) - valid_formation = _valid_formation(map(lambda x: players[x], first_xi)) + first_xi.remove(sub_out) # remove first sub out + first_xi.add(subs[0]) # add first sub in + valid_formation = _valid_formation([players[player_id] for player_id in first_xi]) + # check formation is valid + # if formation not valid, move on to the next sub while not valid_formation and i <= 3: i += 1 - first_xi.remove(subs[i - 1]) - first_xi.add(subs[i]) - valid_formation = _valid_formation(map(lambda x: players[x], first_xi)) - subs.pop(i) + first_xi.remove(subs[i - 1]) # remove previous player subbed in + first_xi.add(subs[i]) # add next sub in + # check formation + valid_formation = _valid_formation([players[player_id] for player_id in first_xi]) + subs.pop(i) # when complete, remove the subbed in player from the list of subs - first_xi_live_scores = map(lambda x: getattr(players[x], "live_score"), first_xi) + first_xi_live_scores = [players[player_id].live_score for player_id in first_xi] captain = next(pick["element"] for pick in picks if pick["is_captain"]) try: vice_captain = next( pick["element"] for pick in picks if pick["is_vice_captain"] and pick["multiplier"] == 1) + # only if multiplier == 1, i.e. vice-captain not already applied by FPL except StopIteration: vice_captain = None - captain_points = getattr(players[captain], "live_score") + captain_points = players[captain].live_score if captain in subs_out and vice_captain: - captain_points = getattr(players[vice_captain], "live_score") + captain_points = players[vice_captain].live_score - if active_chip == "3xc": + if active_chip == "3xc": # for triple captain chip captain_points *= 2 return sum(first_xi_live_scores) + captain_points - points_hit @@ -307,8 +310,8 @@ async def get_live_total_points(self, players): :rtype int """ history = await self.get_gameweek_history() - history = filter(lambda x: x["event"] < getattr(self, "current_event"), history) - history = map(lambda x: x["total_points"] - x["event_transfers cost"], history) + history = [x["total_points"] - x["event_transfers cost"] for x in history + if x["event"] < getattr(self, "current_event")] live_score = + await self.get_live_score(players) @@ -388,7 +391,7 @@ async def transfers_for_current_gameweek(self): current_gameweek = getattr(self, "current_event") picks = await self.picks_for_current_gameweek transfers = await self.transfers - transfers = list(filter(lambda x: x["event"] == current_gameweek, transfers)) + transfers = [transfer for transfer in transfers if transfer["event"] == current_gameweek] return { "transfers_made": picks["entry_history"]["event_transfers"], "transfers_cost": picks["entry_history"]["event_transfers_cost"], @@ -442,7 +445,7 @@ async def get_wildcards(self): :rtype: list """ chips_played = await self.get_chips_history() - return list(filter(lambda x: x["name"] == "wildcard", chips_played)) + return [chip for chip in chips_played if chip["name"] == "wildcard"] async def get_watchlist(self): """Returns the user's watchlist. Requires the user to have logged in diff --git a/fpl/utils.py b/fpl/utils.py index e39f290..a690622 100644 --- a/fpl/utils.py +++ b/fpl/utils.py @@ -6,18 +6,21 @@ headers = {"User-Agent": "https://github.com/amosbastian/fpl"} -async def fetch(session, url): +async def fetch(session, url, params=None): + if params is None: + params = {} while True: + # noinspection PyBroadException try: - async with session.get(url, headers=headers) as response: + async with session.get(url, headers=headers, params=params) as response: assert response.status == 200 return await response.json() except Exception: pass -async def post(session, url, payload, headers): - async with session.post(url, data=payload, headers=headers) as response: +async def post(session, url, payload, headers_): + async with session.post(url, data=payload, headers=headers_) as response: return await response.json() @@ -151,6 +154,7 @@ def logged_in(session): :return: True if user is logged in else False :rtype: bool """ + # noinspection PyTypeChecker return "csrftoken" in session.cookie_jar.filter_cookies( "https://users.premierleague.com/") From 96077319d5fea4b2d7bf90e925d6ad82dd89bad1 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Tue, 22 Oct 2019 13:41:35 +0100 Subject: [PATCH 09/10] import async_property library --- fpl/fpl.py | 4 ++-- fpl/models/user.py | 25 ++++++++++++++++++------- setup.py | 4 +++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/fpl/fpl.py b/fpl/fpl.py index 7d5a0cf..259b980 100644 --- a/fpl/fpl.py +++ b/fpl/fpl.py @@ -250,8 +250,8 @@ async def get_player(self, player_id, players=None, gameweek=None, include_summa player["id"], return_json=True) player.update(player_summary) - player["image_url"] = f'https://platform-static-files.s3.amazonaws.com' \ - f'/premierleague/photos/players/110x140/p{player["code"]}.png' + player["image_url"] = (f'https://platform-static-files.s3.amazonaws.com' + f'/premierleague/photos/players/110x140/p{player["code"]}.png') if gameweek: player["live_score"] = gameweek.elements[player_id]["stats"]["total_points"] diff --git a/fpl/models/user.py b/fpl/models/user.py index 108a6dc..42c32a6 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -1,6 +1,8 @@ import asyncio import json +from async_property import async_cached_property + from ..constants import API_URLS from ..utils import fetch, logged_in, post, get_headers @@ -120,7 +122,11 @@ def _get_first_xi(picks, players): def _get_subs(picks, players): - return [players[pick["element"]].id for pick in picks if pick["position"] > 11] + return [players[pick["element"]].id + for pick in picks + if pick["position"] > 11 + and + not players[pick["element"]].did_not_play] class User: @@ -144,7 +150,7 @@ def __init__(self, user_information, session): for k, v in user_information.items(): setattr(self, k, v) - @property + @async_cached_property async def history(self): history = await fetch(self._session, API_URLS["user_history"].format(getattr(self, "id"))) return history @@ -198,15 +204,12 @@ async def get_chips_history(self, gameweek=None): return chips - @property + @async_cached_property async def picks(self): """Returns a dict containing the user's picks each gameweek. - Key is the gameweek number, value contains picks of the gameweek. - Information is taken from e.g.: https://fantasy.premierleague.com/api/entry/91928/event/1/picks/ - :rtype: dict """ @@ -382,8 +385,16 @@ async def get_team(self): return response["picks"] - @property + @async_cached_property async def transfers(self): + """Returns either a list of all the user's transfers, or a list of + transfers made in the given gameweek. + + Information is taken from e.g.: + https://fantasy.premierleague.com/api/entry/91928/transfers/ + + :rtype: list + """ return await fetch(self._session, API_URLS["user_transfers"].format(getattr(self, "id"))) @property diff --git a/setup.py b/setup.py index b1ff261..36847b4 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,7 @@ "Source": "https://github.com/amosbastian/fpl" }, install_requires=[ + "async_property", "Click", "colorama", "codecov", @@ -36,7 +37,8 @@ "pytest-aiohttp", "pytest-cov", "pytest-mock", - "pytest", 'requests' + "pytest", + "requests" ], entry_points=""" [console_scripts] From da5c281f07718dbda06b89ca52b6891ff19232e9 Mon Sep 17 00:00:00 2001 From: johnmadden86 Date: Tue, 22 Oct 2019 14:32:23 +0100 Subject: [PATCH 10/10] fix for finished gameweek --- fpl/fpl.py | 10 ++++++++-- fpl/models/player.py | 2 ++ fpl/models/user.py | 8 ++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/fpl/fpl.py b/fpl/fpl.py index 259b980..04befae 100644 --- a/fpl/fpl.py +++ b/fpl/fpl.py @@ -262,7 +262,7 @@ async def get_player(self, player_id, players=None, gameweek=None, include_summa return Player(player, self.session) - async def get_players(self, player_ids=None, include_summary=False, include_live=None, + async def get_players(self, player_ids=None, include_summary=False, include_live=False, return_json=False): """Returns either a list of *all* players, or a list of players whose IDs are in the given ``player_ids`` list. @@ -287,8 +287,14 @@ async def get_players(self, player_ids=None, include_summary=False, include_live if not player_ids: player_ids = [player["id"] for player in players.values()] + current_gameweek_id = getattr(self, "current_gameweek") + gameweeks = getattr(self, "events") + current_gameweek = gameweeks[current_gameweek_id] + current_gameweek_finished = current_gameweek["finished"] + include_live = include_live and not current_gameweek_finished + if include_live: - gameweek = await self.get_gameweek(getattr(self, "current_gameweek"), include_live=True) + gameweek = await self.get_gameweek(current_gameweek_id, include_live=include_live) tasks = [asyncio.ensure_future( self.get_player( diff --git a/fpl/models/player.py b/fpl/models/player.py index 098e993..40167a4 100644 --- a/fpl/models/player.py +++ b/fpl/models/player.py @@ -25,6 +25,8 @@ def __init__(self, player_information, session): self._session = session for k, v in player_information.items(): setattr(self, k, v) + self.did_not_play = False + self.live_score = getattr(self, "event_points") @property async def games_played(self): diff --git a/fpl/models/user.py b/fpl/models/user.py index 42c32a6..063b5ec 100644 --- a/fpl/models/user.py +++ b/fpl/models/user.py @@ -290,19 +290,19 @@ async def get_live_score(self, players): captain = next(pick["element"] for pick in picks if pick["is_captain"]) try: - vice_captain = next( - pick["element"] for pick in picks if pick["is_vice_captain"] and pick["multiplier"] == 1) - # only if multiplier == 1, i.e. vice-captain not already applied by FPL + vice_captain = next(pick["element"] for pick in picks if pick["is_vice_captain"]) except StopIteration: vice_captain = None captain_points = players[captain].live_score - if captain in subs_out and vice_captain: + if captain in subs_out + subs: captain_points = players[vice_captain].live_score if active_chip == "3xc": # for triple captain chip captain_points *= 2 + print(sum(first_xi_live_scores), captain_points, points_hit) + return sum(first_xi_live_scores) + captain_points - points_hit async def get_live_total_points(self, players):