def get_player_list(team, pos): """ Return a list of all players in that team and/or position """ player_list = [{"id": p.player_id, "name": p.name} \ for p in list_players(position=pos,team=team)] return create_response(player_list)
def fit_save_points( gameweek=NEXT_GAMEWEEK, season=CURRENT_SEASON, min_matches=10, min_minutes=90, dbsession=session, ): """Calculate the average save points scored by each goalkeeper for matches they played at least min_minutes in. Mean is calculated as sum of all save points divided by either the number of matches the player has played in or min_matches, whichever is greater. Returns pandas series index by player ID, values average save points. """ df = get_player_scores( season, gameweek, min_minutes=min_minutes, dbsession=dbsession ) goalkeepers = list_players( position="GK", gameweek=gameweek, season=season, dbsession=dbsession ) goalkeepers = [gk.player_id for gk in goalkeepers] df = df[df["player_id"].isin(goalkeepers)] # 1pt per 3 saves df["save_pts"] = (df["saves"] / saves_for_point).astype(int) return mean_group_min_count(df, "player_id", "save_pts", min_count=min_matches)
def list_players_teams_prices(position="all", team="all", dbsession=DBSESSION): """ Return a list of players, each with their current team and price """ return [ "{} ({}): {}".format(p.name, p.team(CURRENT_SEASON), p.current_price(CURRENT_SEASON)) for p in list_players(position=position, team=team, dbsession=dbsession) ]
def calc_predicted_points_for_pos(pos, gw_range, team_model, player_model, season, tag, session): """ Calculate points predictions for all players in a given position and put into the DB """ predictions = {} df_player = None if pos != "GK": # don't calculate attacking points for keepers. df_player = get_fitted_player_model(player_model, pos, season, session) for player in list_players(position=pos, dbsession=session): predictions[player.player_id] = calc_predicted_points( player, team_model, df_player, season, tag, session, gw_range) return predictions
def list_players_teams_prices(position="all", team="all", dbsession=DBSESSION, gameweek=NEXT_GAMEWEEK): """ Return a list of players, each with their current team and price """ return [ "{} ({}): {}".format( p.name, p.team(CURRENT_SEASON, NEXT_GAMEWEEK), p.price(CURRENT_SEASON, NEXT_GAMEWEEK), ) for p in list_players(position=position, team=team, dbsession=dbsession, gameweek=gameweek) ]
def update_players(season, dbsession): """ See if any new players have been added to FPL since we last filled the 'player' table in the db. If so, add them. """ players_from_db = list_players( position="all", team="all", season=season, dbsession=dbsession ) player_data_from_api = fetcher.get_player_summary_data() players_from_api = list(player_data_from_api.keys()) if len(players_from_db) == len(players_from_api): print("Player table already up-to-date.") return 0 elif len(players_from_db) > len(players_from_api): raise RuntimeError( "Something strange has happened - more players in DB than API" ) else: print("Updating player table...") # find the new player(s) from the API api_ids_from_db = [p.fpl_api_id for p in players_from_db] new_players = [p for p in players_from_api if p not in api_ids_from_db] for player_api_id in new_players: first_name = player_data_from_api[player_api_id]["first_name"] second_name = player_data_from_api[player_api_id]["second_name"] name = "{} {}".format(first_name, second_name) # check whether we alreeady have this player in the database - # if yes update that player's data, if no create a new player p = get_player(name, dbsession=dbsession) if p is None: print("Adding player {}".format(name)) p = Player() update = False elif p.fpl_api_id is None: print("Updating player {}".format(name)) update = True else: update = True p.fpl_api_id = player_api_id p.name = name if not update: dbsession.add(p) dbsession.commit() return len(new_players)
def _get_player_list(self): """Get list of active players at the start of the gameweek range, and the id range of players for each position. """ players = [] change_idx = [0] # build players list by position (i.e. all GK, then all DEF etc.) for pos in self.positions: players += list_players( position=pos, season=self.season, gameweek=self.start_gw ) change_idx.append(len(players)) # min and max idx of players for each position position_idx = { self.positions[i - 1]: (change_idx[i - 1], change_idx[i] - 1) for i in range(1, len(change_idx)) } return players, position_idx
def update_players(season, dbsession): """ See if any new players have been added to FPL since we last filled the 'player' table in the db. If so, add them. """ players_from_db = list_players(position="all", team="all", season=season, dbsession=dbsession) player_data_from_api = fetcher.get_player_summary_data() players_from_api = list(player_data_from_api.keys()) if len(players_from_db) == len(players_from_api): print("Player table already up-to-date.") return 0 elif len(players_from_db) > len(players_from_api): raise RuntimeError( "Something strange has happened - more players in DB than API") else: return add_players_to_db(players_from_db, players_from_api, player_data_from_api, dbsession)
def calc_predicted_points_for_pos( pos, team_model, player_model, df_bonus, df_saves, df_cards, season, gw_range, tag, dbsession=session, ): """ Calculate points predictions for all players in a given position and put into the DB """ predictions = {} df_player = None if pos != "GK": # don't calculate attacking points for keepers. df_player = get_fitted_player_model( player_model, pos, season, min(gw_range), dbsession ) for player in list_players( position=pos, season=season, gameweek=min(gw_range), dbsession=dbsession ): predictions[player.player_id] = calc_predicted_points_for_player( player=player, team_model=team_model, df_player=df_player, df_bonus=df_bonus, df_saves=df_saves, df_cards=df_cards, season=season, gw_range=gw_range, tag=tag, dbsession=dbsession, ) return predictions
def calc_predicted_points_for_pos( pos, fixture_goal_probs, df_bonus, df_saves, df_cards, season, gw_range, tag, model=ConjugatePlayerModel(), dbsession=session, ): """ Calculate points predictions for all players in a given position and put into the DB """ df_player = None if pos != "GK": # don't calculate attacking points for keepers. df_player = fit_player_data(pos, season, min(gw_range), model, dbsession) return { player.player_id: calc_predicted_points_for_player( player=player, fixture_goal_probs=fixture_goal_probs, df_player=df_player, df_bonus=df_bonus, df_saves=df_saves, df_cards=df_cards, season=season, gw_range=gw_range, tag=tag, dbsession=dbsession, ) for player in list_players(position=pos, season=season, gameweek=min(gw_range), dbsession=dbsession) }
def get_player_history_table(position="all"): """ Query the player_score table. """ with open("player_history_{}.csv".format(position), "w") as output_file: output_file.write( "player_id,player_name,match_id,goals,assists,minutes,team_goals\n" ) player_ids = list_players(position) for pid in player_ids: player_name = get_player_name(pid) results = session.query(PlayerScore).filter_by(player_id=pid).all() row_count = 0 for row in results: minutes = row.minutes match_id = row.match_id goals = row.goals assists = row.assists # find the match, in order to get team goals Match = None # TODO: Placeholder for missing (deprecated?) Match class match = session.query(Match).filter_by( match_id=row.match_id).first() if match.home_team == row.opponent: team_goals = match.away_score elif match.away_team == row.opponent: team_goals = match.home_score else: print("Unknown opponent!") team_goals = -1 output_file.write("{},{},{},{},{},{},{}\n".format( pid, player_name, match_id, goals, assists, minutes, team_goals)) row_count += 1 if row_count < 38 * 3: for _ in range(row_count, 38 * 3): output_file.write("{},{},0,0,0,0,0\n".format( pid, player_name))
def calc_all_predicted_points( gw_range, season, include_bonus=True, include_cards=True, include_saves=True, num_thread=4, tag="", dbsession=None, ): """ Do the full prediction for players. """ model_team = get_fitted_team_model(season, gameweek=min(gw_range), dbsession=dbsession) model_file = pkg_resources.resource_filename( "airsenal", "stan_model/player_forecasts.pkl") print("Loading pre-compiled player model from {}".format(model_file)) with open(model_file, "rb") as f: model_player = pickle.load(f) df_player = get_all_fitted_player_models(model_player, season, gw_range[0]) if include_bonus: df_bonus = fit_bonus_points(gameweek=gw_range[0], season=season) else: df_bonus = None if include_saves: df_saves = fit_save_points(gameweek=gw_range[0], season=season) else: df_saves = None if include_cards: df_cards = fit_card_points(gameweek=gw_range[0], season=season) else: df_cards = None players = list_players(season=season, gameweek=gw_range[0], dbsession=dbsession) if num_thread is not None and num_thread > 1: queue = Queue() procs = [] for _ in range(num_thread): processor = Process( target=allocate_predictions, args=( queue, gw_range, model_team, df_player, df_bonus, df_saves, df_cards, season, tag, dbsession, ), ) processor.daemon = True processor.start() procs.append(processor) for p in players: queue.put(p.player_id) for _ in range(num_thread): queue.put("DONE") for _, p in enumerate(procs): p.join() else: # single threaded for player in players: predictions = calc_predicted_points_for_player( player, model_team, df_player, df_bonus, df_saves, df_cards, season, gw_range=gw_range, tag=tag, dbsession=dbsession, ) for p in predictions: dbsession.add(p) dbsession.commit() print("Finished adding predictions to db")
def list_players_for_api(team, position, dbsession=DBSESSION): """ List players. Just pass on to utils.list_players but specify the dbsession. """ return list_players(team=team, position=position, dbsession=dbsession)
def calc_all_predicted_points( gw_range, season, include_bonus=True, include_cards=True, include_saves=True, num_thread=4, tag="", player_model=ConjugatePlayerModel(), dbsession=None, ): """ Do the full prediction for players. """ model_team = get_fitted_team_model(season, gameweek=min(gw_range), dbsession=dbsession) print("Calculating fixture score probabilities...") fixtures = get_fixtures_for_gameweek(gw_range, season=season, dbsession=dbsession) fixture_goal_probs = get_goal_probabilities_for_fixtures( fixtures, model_team, max_goals=MAX_GOALS) df_player = get_all_fitted_player_data(season, gw_range[0], model=player_model, dbsession=dbsession) if include_bonus: df_bonus = fit_bonus_points(gameweek=gw_range[0], season=season) else: df_bonus = None if include_saves: df_saves = fit_save_points(gameweek=gw_range[0], season=season) else: df_saves = None if include_cards: df_cards = fit_card_points(gameweek=gw_range[0], season=season) else: df_cards = None players = list_players(season=season, gameweek=gw_range[0], dbsession=dbsession) if num_thread is not None and num_thread > 1: queue = Queue() procs = [] for _ in range(num_thread): processor = Process( target=allocate_predictions, args=( queue, gw_range, fixture_goal_probs, df_player, df_bonus, df_saves, df_cards, season, tag, dbsession, ), ) processor.daemon = True processor.start() procs.append(processor) for p in players: queue.put(p.player_id) for _ in range(num_thread): queue.put("DONE") for _, p in enumerate(procs): p.join() else: # single threaded for player in players: predictions = calc_predicted_points_for_player( player, fixture_goal_probs, df_player, df_bonus, df_saves, df_cards, season, gw_range=gw_range, tag=tag, dbsession=dbsession, ) for p in predictions: dbsession.add(p) dbsession.commit() print("Finished adding predictions to db")
def get_player_history_df( position="all", season=CURRENT_SEASON, gameweek=NEXT_GAMEWEEK, dbsession=session ): """ Query the player_score table to get goals/assists/minutes, and then get the team_goals from the match table. The 'season' argument defined the set of players that will be considered, but for those players, all results will be used. """ col_names = [ "player_id", "player_name", "match_id", "date", "goals", "assists", "minutes", "team_goals", ] player_data = [] players = list_players( position=position, season=season, gameweek=gameweek, dbsession=dbsession ) max_matches_per_player = get_max_matches_per_player( position, season=season, gameweek=gameweek, dbsession=dbsession ) for counter, player in enumerate(players): print( "Filling history dataframe for {}: {}/{} done".format( player.name, counter, len(players) ) ) results = player.scores row_count = 0 for row in results: if is_future_gameweek( row.fixture.season, row.fixture.gameweek, current_season=season, next_gameweek=gameweek, ): continue match_id = row.result_id if not match_id: print( " Couldn't find result for {} {} {}".format( row.fixture.home_team, row.fixture.away_team, row.fixture.date ) ) continue minutes = row.minutes opponent = row.opponent goals = row.goals assists = row.assists # find the match, in order to get team goals match_result = row.result match_date = row.fixture.date if row.fixture.home_team == row.opponent: team_goals = match_result.away_score elif row.fixture.away_team == row.opponent: team_goals = match_result.home_score else: print("Unknown opponent!") team_goals = -1 player_data.append( [ player.player_id, player.name, match_id, match_date, goals, assists, minutes, team_goals, ] ) row_count += 1 ## fill blank rows so they are all the same size if row_count < max_matches_per_player: player_data += [[player.player_id, player.name, 0, 0, 0, 0, 0, 0]] * ( max_matches_per_player - row_count ) df = pd.DataFrame(player_data, columns=col_names) df["date"] = pd.to_datetime(df["date"], errors="coerce") df.reset_index(drop=True, inplace=True) return df