コード例 #1
0
    def first_team(self):
        if not self.squad_full:
            verbose_print("Squad not full, can't pick first team.")
            return
        df = self.selected
        df.sort_values(by=["score", "score_per_value", "value"],
                       ascending=[False, False, True],
                       inplace=True)

        first_team = pd.DataFrame()

        # First pick a keeper:
        keeper = df.loc[df["position"] == "GK", :].iloc[0].to_dict()
        first_team = first_team.append(keeper, ignore_index=True)
        df = df.loc[df["position"] != "GK"]

        # Then pick the rest of the team:
        max_picks = {"DEF": 5, "MID": 5, "FWD": 3}
        picked = {"DEF": 0, "MID": 0, "FWD": 0}
        for row in df.iterrows():
            if len(first_team) == 11:
                break
            player = row[1].to_dict()
            if picked[player["position"]] < max_picks[player["position"]]:
                first_team = first_team.append(player, ignore_index=True)
                picked[player["position"]] += 1
            # Can't have 5 midfielders AND 5 defenders:
            if picked["DEF"] == 5:
                max_picks["MID"] = 4
            if picked["MID"] == 5:
                max_picks["DEF"] = 4

        first_team["code"] = first_team["code"].astype(int)
        return first_team
コード例 #2
0
 def load_squad(self, filename):
     fp = os.path.join(DIR_SQUADS, f"{filename}.csv")
     assert os.path.isfile(fp), f"Squad file not found: {filename}"
     df = pd.read_csv(fp, encoding="utf-8")
     self.selected = df
     verbose_print(
         f"Squad of {len(self.selected)} players loaded from {fp}")
コード例 #3
0
 def add_player(self, code: int, year: int, week: int, live=False):
     """Add a player to the current squad."""
     player = self.PlayerInformation.get_player(code, year, week, live)
     score = self.PlayerScorer.get_player_gw_score(code, year, week)
     player["score"] = score
     player["score_per_value"] = score / player["value"]
     self.Squad.add_player(**player)
     verbose_print(f"Player added to squad: {player['name']}")
コード例 #4
0
 def remove_player(self, code):
     if code not in list(self.selected["code"]):
         raise ValueError(f"code not in team: {code}")
     name = self.selected.loc[self.selected["code"] == code,
                              "name"].values[0]
     self.selected = self.selected.loc[
         self.selected["code"] != code].reset_index(drop=True)
     verbose_print(
         f"Removed player from squad ({len(self.selected)} remain): {name}")
コード例 #5
0
 def vice_captain(self):
     if not self.squad_full:
         verbose_print("Squad not full, can't pick vice-captain.")
         return
     else:
         df = self.selected
         df.sort_values(by=["score", "score_per_value", "value"],
                        ascending=[False, False, True],
                        inplace=True)
         vc = df.iloc[1]
     return {vc["code"]: vc["name"]}
コード例 #6
0
def optimiser(self, year: int, week: int, iterations: int = 100,
              live: bool = False, r: int = 2,
              score_per_value: bool = False):
    """Optimise the currently selected squad by selecting r-length combinations
    of players in the squad, then comparing them against all r-length
    combinations of non-selected (available) players and seeing if
    substituting the combinations raises the overall team score."""
    score_col = "score_per_value" if score_per_value else "score"
    increase = 0
    original_score = self.Squad.total_score_per_val if score_per_value else self.Squad.total_score

    for i in range(iterations):
        optimisations = squad_optimisations(self, year, week, live=live, r=r, score_per_value=score_per_value)
        if not len(optimisations):
            new_score = self.Squad.total_score_per_val if score_per_value else self.Squad.total_score
            verbose_print("Can't optimise team anymore:"
                          f"\n> Original total {score_col}: {original_score:,.3f}"
                          f"\n> Raised {score_col} by total: {increase:,.3f}"
                          f"\n> New total {score_col}: {new_score:,.3f}")
            return
        for row in optimisations.iterrows():
            opt = row[1].to_dict()
            to_remove = opt["players_to_remove"]

            # Create a copy of the current team to try replacements:
            test = self._test_new_squad
            current_squad = self.Squad.selected.copy()
            test.selected = current_squad.loc[~current_squad["code"].isin(to_remove)]

            # Try to add each new player:
            try:
                for p in range(r):
                    add_player = dict(code=int(opt[f"p{p}"]))
                    add_player["name"] = self.PlayerInformation.player_names(live=live)[add_player["code"]]
                    add_player["position"] = opt[f"p{p}_position"]
                    add_player["value"] = opt[f"p{p}_val"]
                    add_player["score"] = opt[f"p{p}_score"]
                    add_player["score_per_value"] = opt[f"p{p}_score_per_val"]
                    add_player["team"] = self.PlayerInformation.player_teams(year, live=live)[add_player["code"]]
                    test.add_player(**add_player)
                if score_per_value:
                    added = (test.total_score_per_val - self.Squad.total_score_per_val)
                else:
                    added = (test.total_score - self.Squad.total_score)
                verbose_print(f"Increased {score_col} by: {added}")
                increase += added
                self.Squad.selected = test.selected
                break
            except (AlreadySelected, MaxedOutTeam):
                continue
コード例 #7
0
 def total_first_team_value(self):
     if not self.squad_full:
         verbose_print("Squad not full.")
         return
     return self.first_team["value"].sum()
コード例 #8
0
 def save_squad(self, filename):
     fp = os.path.join(DIR_SQUADS, f"{filename}.csv")
     self.selected.to_csv(fp, encoding="utf-8", index=False)
     verbose_print(f"Squad of {len(self.selected)} players saved at: {fp}")
コード例 #9
0
    def get_player_pool(self, year, week, live=False, position=None,
                        min_score=None, min_score_per_value=None, max_val=None,
                        drop_unavailable=True, drop_selected=True,
                        drop_maxed_out=True):
        """Get a pool of players to select from which meet the criteria."""
        df = self.players(year, week, live)
        n = len(df)

        if position:
            position = [position] if isinstance(position, str) else position
            assert all([p in ["GK", "DEF", "MID", "FWD"] for p in position]), \
                f"invalid position(s): {', '.join(position)}"
            df = df.loc[df["position"].isin(position)]
            verbose_print(f"Dropped {n - len(df):,} rows for `position`")
            n = len(df)
        if isinstance(min_score, Number):
            df = df.loc[df[self.scoring_metric] > min_score]
            verbose_print(f"Dropped {n - len(df):,} rows for `min_score`")
            n = len(df)
        if isinstance(min_score_per_value, Number):
            df = df.loc[df[self.val_metric] > min_score_per_value]
            verbose_print(f"Dropped {n - len(df):,} rows for `min_score_per_value`")
            n = len(df)
        if isinstance(max_val, Number):
            df = df.loc[df["value"] <= max_val]
            verbose_print(f"Dropped {n - len(df):,} rows for `max_val`")
            n = len(df)
        if isinstance(self.min_minute_percent, Number):
            df = df.loc[df["minutes_percent"] >= self.min_minute_percent]
            verbose_print(f"Dropped {n - len(df):,} rows for `self.min_minute_percent`")
            n = len(df)
        if drop_unavailable:
            available = self.player_availability(year, week, live, self.percent_chance)
            df["available"] = df.index.map(available)
            # Drop False available (or NaN - assumed to have left league):
            df["available"].fillna(False, inplace=True)
            df = df.loc[df["available"]]
            verbose_print(f"Dropped {n - len(df):,} rows for `drop_unavailable`")
            n = len(df)

        # Remove already selected players:
        if drop_selected:
            df = df.loc[~df.index.isin(self.Squad.selected_list)]
            verbose_print(f"Dropped {n - len(df):,} rows for `drop_selected`")
            n = len(df)

        # Remove players from teams already maxed out:
        if drop_maxed_out:
            if len(self.Squad.maxed_out_teams):
                df = df.loc[~df["team"].isin(self.Squad.maxed_out_teams)]
                verbose_print(f"Dropped {n - len(df):,} rows for `drop_maxed_out`")
                n = len(df)

        # Rename scoring columns to generic names:
        df.rename(columns={self.scoring_metric: "score", self.val_metric: "score_per_value"}, inplace=True)

        # Drop players with NaNs in these columns - they have left the league:
        df.dropna(subset=["position", "value", "team", "score_per_value"], inplace=True)

        return df