def fitness(self, player_ids):
        """PyGMO required function. The objective function to minimise.
        In this case:
            - 0 if the proposed squad isn't valid
            - weghted sum of gameweek points otherwise
        """
        # Make squad from player IDs
        squad = Squad(budget=self.budget, season=self.season)
        for idx in player_ids:
            add_ok = squad.add_player(
                self.players[int(idx)].player_id,
                gameweek=self.start_gw,
            )
            if not add_ok:
                return [0]

        # fill empty slots with dummy players (if chosen not to optimise full squad)
        for pos in self.positions:
            if self.dummy_per_position[pos] > 0:
                for _ in range(self.dummy_per_position[pos]):
                    dp = DummyPlayer(
                        self.gw_range, self.tag, pos, price=self.dummy_sub_cost
                    )
                    add_ok = squad.add_player(dp)
                    if not add_ok:
                        return [0]

        # Check squad is valid, if not return fitness of zero
        if not squad.is_complete():
            return [0]

        #  Calc expected points for all gameweeks
        # - weight each gw points by its gw_weight
        # - weight each sub by their sub_weight
        score = 0.0
        for i, gw in enumerate(self.gw_range):
            gw_weight = self.gw_weight[i]
            if gw == self.bench_boost_gw:
                score += gw_weight * squad.get_expected_points(
                    gw, self.tag, bench_boost=True
                )
            elif gw == self.triple_captain_gw:
                score += gw_weight * squad.get_expected_points(
                    gw, self.tag, triple_captain=True
                )
            else:
                score += gw_weight * squad.get_expected_points(gw, self.tag)

            if gw != self.bench_boost_gw:
                score += gw_weight * squad.total_points_for_subs(
                    gw, self.tag, sub_weights=self.sub_weights
                )

        return [-score]
def get_lineup_from_payload(lineup):
    """
    inverse of build_lineup_payload. Returns a squad object from get_lineup

    lineup is a dictionary, with the entry "picks" being a list of dictionaries like:
    {"element":353,"position":1,"selling_price":55,"multiplier":1,"purchase_price":55,"is_captain":false,"is_vice_captain":false}
    """
    s = Squad()
    for p in lineup["picks"]:
        player = get_player_from_api_id(p["element"])
        s.add_player(player, check_budget=False)

    if s.is_complete():
        return s
    else:
        raise RuntimeError("Squad incomplete")
Example #3
0
def make_new_squad_iter(
    gw_range,
    tag,
    budget=1000,
    season=CURRENT_SEASON,
    num_iterations=100,
    update_func_and_args=None,
    verbose=False,
    bench_boost_gw=None,
    triple_captain_gw=None,
    **kwargs,
):
    """
    Make a squad from scratch, i.e. for gameweek 1, or for wildcard, or free hit, by
    selecting high scoring players and then iteratively replacing them with cheaper
    options until we have a valid squad.
    """
    transfer_gw = min(gw_range)  # the gw we're making the new squad
    best_score = 0.0
    best_squad = None

    for iteration in range(num_iterations):
        if verbose:
            print("Choosing new squad: iteration {}".format(iteration))
        if update_func_and_args:
            # call function to update progress bar.
            # this was passed as a tuple (func, increment, pid)
            update_func_and_args[0](update_func_and_args[1],
                                    update_func_and_args[2])
        predicted_points = {}
        t = Squad(budget, season=season)
        # first iteration - fill up from the front
        for pos in positions:
            predicted_points[pos] = get_predicted_points(gameweek=gw_range,
                                                         position=pos,
                                                         tag=tag,
                                                         season=season)
            for pp in predicted_points[pos]:
                t.add_player(pp[0], gameweek=transfer_gw)
                if t.num_position[pos] == TOTAL_PER_POSITION[pos]:
                    break

        # presumably we didn't get a complete squad now
        excluded_player_ids = []
        while not t.is_complete():
            # randomly swap out a player and replace with a cheaper one in the
            # same position
            player_to_remove = t.players[random.randint(0, len(t.players) - 1)]
            remove_cost = player_to_remove.purchase_price
            t.remove_player(player_to_remove.player_id, gameweek=transfer_gw)
            excluded_player_ids.append(player_to_remove.player_id)
            for pp in predicted_points[player_to_remove.position]:
                if (pp[0] not in excluded_player_ids or random.random() <
                        0.3):  # some chance to put player back
                    cp = CandidatePlayer(pp[0],
                                         gameweek=transfer_gw,
                                         season=season)
                    if cp.purchase_price >= remove_cost:
                        continue
                    else:
                        t.add_player(pp[0], gameweek=transfer_gw)
            # now try again to fill up the rest of the squad
            for pos in positions:
                num_missing = TOTAL_PER_POSITION[pos] - t.num_position[pos]
                if num_missing == 0:
                    continue
                for pp in predicted_points[pos]:
                    if pp[0] in excluded_player_ids:
                        continue
                    t.add_player(pp[0], gameweek=transfer_gw)
                    if t.num_position[pos] == TOTAL_PER_POSITION[pos]:
                        break
        # we have a complete squad
        score = 0.0
        for gw in gw_range:
            if gw == bench_boost_gw:
                score += t.get_expected_points(
                    gw, tag, bench_boost=True) * get_discount_factor(
                        gw_range[0], gw)
            elif gw == triple_captain_gw:
                score += t.get_expected_points(
                    gw, tag, triple_captain=True) * get_discount_factor(
                        gw_range[0], gw)
            else:
                score += t.get_expected_points(gw, tag) * get_discount_factor(
                    gw_range[0], gw)
        if score > best_score:
            best_score = score
            best_squad = t

    if verbose:
        print("====================================\n")
        print(best_squad)
        print(best_score)
    return best_squad