Фэнтези-футбол (футбол) Симуляторы

Что делает моя программа

Моя программа симулирует фэнтези-футбол. Его входными данными являются команды и результаты команд в конкретном матче, а выходными данными — количество очков, заработанных каждой командой в каждом матче в соответствии с заданными правилами подсчета очков.

Вот пример команды:

team1 = [
    calculate_points.Player(p_id=204597, full_name="Jordan Pickford", club='ENG', 
                              position='goalkeeper', is_captain=True, 
                              is_vice_captain=False, points=0.0),          
    calculate_points.Player(p_id=213442, full_name="Luke Shaw", club='ENG', 
                              position='defender', is_captain=False, 
                              is_vice_captain=True, points=0.0), 
    calculate_points.Player(p_id=204614, full_name="Harry Maguire", club='ENG', 
                              position='defender', is_captain=False, 
                              is_vice_captain=False, points=0.0), 
    calculate_points.Player(p_id=204615, full_name="Mason Mount", club='ENG', 
                              position='midfielder', is_captain=False, 
                              is_vice_captain=False, points=0.0), 
    calculate_points.Player(p_id=204617, full_name="Harry Kane", club='ENG',
                              position='forward', is_captain=False, 
                              is_vice_captain=False, points=0.0),
    ]

И пример командного результата:

team_result1 = calculate_points.TeamResult(
    team='ENG', 
    goals_for=1, 
    goals_against=0, 
    scored_goals=['Harry Kane'], 
    made_assist=['Kalvin Phillips'], 
    played60=['Jordan Pickford', 'Luke Shaw', 'John Stones', 'Harry Maguire',  
               'Kieran Trippier', 'Kyle Walker', 'Kalvin Phillips', 
               'Raheem Sterling', 'Declan Rice', 'Harry Kane'], 
    finished_game=['Jordan Pickford', 'Luke Shaw', 'John Stones', 'Harry Maguire', 
                    'Kieran Trippier', 'Kyle Walker', 'Kalvin Phillips', 
                    'Mason Mount', 'Harry Kane'], 
    got_booked=['Kyle Walker'], 
    made_shots_on_tg=['Harry Kane', 'Harry Kane', 'Raheem Sterling', 
                       'Mason Mount', 'Harry Kane'], 
    saves=3)

Какую обратную связь я хотел бы получить

Суть программы — get_team_points() функция, которая вычисляет, сколько очков команда заработала в данном матче, добавив очки, заработанные каждым игроком в команде.

Чтобы иметь возможность выполнять высокопроизводительное моделирование, он должен работать как можно быстрее. Имея это в виду, я ищу способ добиться этого.

Поскольку у меня нет никаких ограничений на то, что можно использовать для этого, я открыт для любых предложений, включая рефакторинг существующего кода, использование сторонних библиотек, написание расширений C / C ++ или даже переписывание программы на другом языке.

Также приветствуются любые другие отзывы, выходящие за рамки производительности.

Что я уже пробовал

  • уменьшение размера TeamResult объект, я попытался использовать список идентификаторов игроков вместо их полных имен.
  • устранив некоторые вызовы функций, я попытался удалить функции для расчета очков игрока на позицию, такие как calculate_goalkeeper_points(), calculate_defender_points(), calculate_midfielder_points() и calculate_forward_points() чтобы сделать это в одной функции для всех игроков.
  • с использованием Cython для изготовления calculate_team_points() функция предварительно скомпилирована и импортирована как расширение C.

Хотя существенного ускорения эти шаги не получили.

Мой код, включая несколько модульных тестов

Calcul_points.py

from dataclasses import dataclass
from typing import List

CAPTAIN_BONUS = 2.0
VICE_CAPTAIN_BONUS = 1.5

@dataclass
class Scoring:
    """
    Represents football scoring.
    """
    defender_goal: int=6
    midfielder_goal: int=5
    forward_goal: int=4
    assist: int=3
    defender_shot_on_tg: float=0.6
    midfielder_or_forward_shot_on_tg: float=0.4
    goalkeeper_save: float=0.5
    pos_impact: float=0.3
    neg_impact: float=-pos_impact
    yellow_card: int=-1
    defender_or_goalkeeper_clean_sheet: int=4
    midfielder_clean_sheet: int=1
    played60: int=2
    midfielder_or_forward_finished_game: int=1
    
scoring = Scoring()    

PlayerId = int
PlayerName = str
PlayerClub = str
PlayerPosition = str
Points = float

@dataclass
class Player:
    """
    Represents a player in Fantasy Football.
    """
    p_id: PlayerId
    full_name: PlayerName
    club: PlayerClub
    position: PlayerPosition
    is_captain: bool=False
    is_vice_captain: bool=False
    points: Points=0.0
    
Team = List[Player]
Teams = List[Team]    
    
@dataclass
class TeamResult:
    """
    Represents the result of a particular team with its name, goals scored,
    goals conceded, players who scored goals and made assists and the number of
    saves made by the goalkeeper.
    """
    team: PlayerClub
    goals_for: int
    goals_against: int
    scored_goals: List[PlayerName]
    made_assist: List[PlayerName]
    played60: List[PlayerName]
    finished_game: List[PlayerName]
    got_booked: List[PlayerName]
    made_shots_on_tg: List[PlayerName]
    saves: int

TeamResults = List[TeamResult]    

def get_team_points(team: Team, team_result: TeamResult) -> Points:
    """
    Returns how many points the given team earned with the given team result.
    """
    team = calculate_team_points(team, team_result)
    team = apply_captaincy(team)
    return sum(p.points for p in team)

def calculate_team_points(team: Team, team_result: TeamResult) -> Team:
    """
    Assigns earned points for each player in the team.
    """
    points_factory = {
        'goalkeeper': calculate_goalkeeper_points,
        'defender': calculate_defender_points,
        'midfielder': calculate_midfielder_points,
        'forward': calculate_forward_points,
        }
    
    for player in team:
        player.points = points_factory[player.position](player, team_result)
    return team

def calculate_goalkeeper_points(goalkeeper: Player, team_result: TeamResult) -> Points:
    """
    Returns points earned by a goalkeeper.
    """
    got_booked = scoring.yellow_card if goalkeeper.full_name in team_result.got_booked else 0
    goals_conceded = scoring.defender_or_goalkeeper_clean_sheet if team_result.goals_against == 0 else team_result.goals_against // 2 * -1
    impact = calculate_impact(team_result)
    saves = team_result.saves * scoring.goalkeeper_save
    playing_time = scoring.played60
    return sum((goals_conceded, impact, saves, playing_time, got_booked))

def calculate_defender_points(defender: Player, team_result: TeamResult) -> Points:
    """
    Returns points earned by a defender.
    """
    got_booked = scoring.yellow_card if defender.full_name in team_result.got_booked else 0
    goals_conceded = scoring.defender_or_goalkeeper_clean_sheet if team_result.goals_against == 0 else team_result.goals_against // 2 * -1
    impact = calculate_impact(team_result)
    playing_time = scoring.played60
    goals = team_result.scored_goals.count(defender.full_name) * scoring.defender_goal
    assists = team_result.made_assist.count(defender.full_name) * scoring.assist
    shots_on_tg = ((team_result.made_shots_on_tg.count(defender.full_name) - 
                   team_result.scored_goals.count(defender.full_name)) * scoring.defender_shot_on_tg)
    return sum((goals_conceded, impact, playing_time, goals, assists, 
                got_booked, shots_on_tg))

def calculate_midfielder_points(midfielder: Player, team_result: TeamResult) -> Points:
    """
    Returns points earned by a midfielder.
    """    
    got_booked = scoring.yellow_card if midfielder.full_name in team_result.got_booked else 0
    clean_sheet = scoring.midfielder_clean_sheet if team_result.goals_against == 0 else 0
    impact = calculate_impact(team_result)
    playing_time = scoring.midfielder_or_forward_finished_game + scoring.played60 if midfielder.full_name in team_result.finished_game else scoring.played60
    goals = team_result.scored_goals.count(midfielder.full_name) * scoring.midfielder_goal
    assists = team_result.made_assist.count(midfielder.full_name) * scoring.assist
    shots_on_tg = ((team_result.made_shots_on_tg.count(midfielder.full_name) - 
                   team_result.scored_goals.count(midfielder.full_name)) * scoring.midfielder_or_forward_shot_on_tg)    
    return sum((clean_sheet, impact, playing_time, goals, assists, got_booked, 
                shots_on_tg))

def calculate_forward_points(forward: Player, team_result: TeamResult) -> Points:
    """
    Returns points earned by a forward.
    """    
    got_booked = scoring.yellow_card if forward.full_name in team_result.got_booked else 0
    impact = calculate_impact(team_result)
    playing_time = scoring.midfielder_or_forward_finished_game + scoring.played60 if forward.full_name in team_result.finished_game else scoring.played60
    goals = team_result.scored_goals.count(forward.full_name) * scoring.forward_goal
    assists = team_result.made_assist.count(forward.full_name) * scoring.assist
    shots_on_tg = ((team_result.made_shots_on_tg.count(forward.full_name) - 
                   team_result.scored_goals.count(forward.full_name)) * scoring.midfielder_or_forward_shot_on_tg)    
    return sum((impact, playing_time, goals, assists, got_booked, shots_on_tg))

def calculate_impact(team_result: TeamResult) -> Points:
    """
    Calculates impact for a team based on whether it won, lost or drew.
    """
    if team_result.goals_for > team_result.goals_against:
        return scoring.pos_impact
    elif team_result.goals_for < team_result.goals_against:
        return scoring.neg_impact
    return 0

def apply_captaincy(team: Team) -> Team:
    """
    Multiplies points of captain and vice_captain.
    """
    for player in team:
        if player.is_captain:
            player.points *= CAPTAIN_BONUS
        elif player.is_vice_captain:
            player.points *= VICE_CAPTAIN_BONUS
    return team    

test_points.py

import unittest
import calculate_points

team1 = [
    calculate_points.Player(p_id=204597, full_name="Jordan Pickford", club='ENG', 
                              position='goalkeeper', is_captain=True, 
                              is_vice_captain=False, points=0.0),          
    calculate_points.Player(p_id=213442, full_name="Luke Shaw", club='ENG', 
                              position='defender', is_captain=False, 
                              is_vice_captain=True, points=0.0), 
    calculate_points.Player(p_id=204614, full_name="Harry Maguire", club='ENG', 
                              position='defender', is_captain=False, 
                              is_vice_captain=False, points=0.0), 
    calculate_points.Player(p_id=204615, full_name="Mason Mount", club='ENG', 
                              position='midfielder', is_captain=False, 
                              is_vice_captain=False, points=0.0), 
    calculate_points.Player(p_id=204617, full_name="Harry Kane", club='ENG',
                              position='forward',  is_captain=False, 
                              is_vice_captain=False, points=0.0),
    ]

team_result1 = calculate_points.TeamResult(
    team='ENG', 
    goals_for=1, 
    goals_against=0, 
    scored_goals=['Harry Kane'], 
    made_assist=['Kalvin Phillips'], 
    played60=['Jordan Pickford', 'Luke Shaw', 'John Stones', 'Harry Maguire',  
               'Kieran Trippier', 'Kyle Walker', 'Kalvin Phillips', 
               'Raheem Sterling', 'Declan Rice', 'Harry Kane'], 
    finished_game=['Jordan Pickford', 'Luke Shaw', 'John Stones', 'Harry Maguire', 
                    'Kieran Trippier', 'Kyle Walker', 'Kalvin Phillips', 
                    'Mason Mount', 'Harry Kane'], 
    got_booked=['Kyle Walker'], 
    made_shots_on_tg=['Harry Kane', 'Harry Kane', 'Raheem Sterling', 
                       'Mason Mount', 'Harry Kane'], 
    saves=3)

team_result2 = calculate_points.TeamResult(
    team='ENG', 
    goals_for=2, 
    goals_against=1, 
    scored_goals=['Raheem Sterling', 'Mason Mount'], 
    made_assist=['Substitutes', 'Luke Shaw'], 
    played60=['Jordan Pickford', 'Luke Shaw', 'John Stones', 'Harry Maguire', 
              'Kieran Trippier', 'Kyle Walker', 'Kalvin Phillips', 
              'Raheem Sterling', 'Mason Mount', 'Harry Kane'], 
    finished_game=['Jordan Pickford', 'Luke Shaw', 'John Stones', 
                   'Harry Maguire', 'Kieran Trippier', 'Kyle Walker', 
                   'Raheem Sterling'], 
    got_booked=['Jordan Pickford'], 
    made_shots_on_tg=['Harry Kane', 'Mason Mount', 'Mason Mount', 
                      'Substitutes', 'Harry Kane'], saves=2)

team_result3 = calculate_points.TeamResult(
    team='ENG', 
    goals_for=0, 
    goals_against=2, 
    scored_goals=[], 
    made_assist=[], 
    played60=['Jordan Pickford', 'Luke Shaw', 'John Stones', 'Harry Maguire', 
              'Kieran Trippier', 'Kyle Walker', 'Kalvin Phillips', 
              'Declan Rice', 'Harry Kane'], 
    finished_game=['Jordan Pickford', 'Luke Shaw', 'John Stones', 
                   'Harry Maguire', 'Kieran Trippier', 'Kyle Walker', 
                   'Kalvin Phillips', 'Declan Rice', 'Harry Kane'], 
    got_booked=['Luke Shaw', 'John Stones', 'Raheem Sterling', 'Mason Mount'], 
    made_shots_on_tg=['Harry Kane'], saves=2)

class TestGetTeamPoints(unittest.TestCase):
    def test_won_game_with_cleansheet(self):
        self.assertAlmostEqual(calculate_points.get_team_points(team1, team_result1), 44.15)
        
    def test_won_game_with_conceded_goal(self):
        self.assertAlmostEqual(calculate_points.get_team_points(team1, team_result2), 25.65)
        
    def test_lost_game_with_no_goals_scored(self):
        self.assertAlmostEqual(calculate_points.get_team_points(team1, team_result3), 7.45)
        
if __name__ == '__main__':
    unittest.main()        

1 ответ
1

Я не думаю, что твой Scoring class — отличное место для хранения констант. (Даже если бы это было так, обычный класс со статикой подошел бы лучше, чем одноэлементный класс данных.) Если вы хотите сделать что-то подобное, создайте модуль вместо класса, чтобы получить дешевое пространство имен. Учитывая, как используются эти цифры, я предлагаю просто переместить их в строку.

Приятно видеть, что вы применяете псевдонимы для PlayerId и т. д. Если вы хотите сделать еще один шаг в безопасности типов, вместо простого псевдонима вы можете использовать NewType.

Я не понимаю почему club является собственностью плеера. Разве это не собственность команды? С club Предполагается, что это свойство игрока, почему оно также связано с объектом результата?

Имея is_captain и is_vice_captain as booleans для игрока проблематично, потому что вы можете сделать несколько капитанов команд, что, вероятно, невозможно. Более надежный вариант — просто включить в командный объект капитана и заместителей.

Я считаю, что «TeamResult» более понятно как «TeamGame», поскольку он относится к объекту команды, а не сохраняет строку клуба. Кроме того, некоторые из этих списков должны быть наборами с учетом того, как они используются.

То, как вы выполняете мутацию на месте для apply_captaincy вводит проблемы — более сложный для отладки код и объекты, достоверность которых труднее гарантировать. Вместо этого возвращайте номера точек из методов и не сохраняйте их ни в одном из объектов класса.

Ваш points_factory это несколько неудобный удар по полиморфизму, где более традиционная модель наследования полиморфных классов упростит задачу, а также сократит много повторяющегося кода в calculate_* методы. Даже если бы вы сохранили этот шаблон, передача позиций в виде строк не является хорошей идеей, и вместо этого они должны быть перечислениями.

team1 и т. д. в вашем тестовом модуле могут быть исключены из глобального пространства имен и перемещены, например, в статику вашего тестового класса. Переменные результата следует переместить в отдельные методы тестирования, поскольку они используются только один раз.

Ссылки на ваши плееры, а не строки с полными именами, лучше представить в виде идентификаторов — для этого и нужны идентификаторы.

В вашей логике есть элемент, которого я не понимаю: вы всегда добавлять scoring.played60 независимо от того, действительно ли данный игрок появлялся в вашем played60 коллекция. Я показал (закомментированную) реализацию, которая не добавляет этот элемент оценки, если игрок не появился в этой коллекции. Хотя это закомментировано, результаты, которые я показал, идентичны вашим.

Ваши тестовые данные немного странные — у вас большие пробелы в определении вашей команды и не хватает многих игроков, упомянутых в ваших результатах. Может быть, это нормально; пока вы не подтвердите, что ссылки в ваших объектах результатов появляются в экземпляре группы, и тогда это не нормально.

Предложенный

from dataclasses import dataclass
from numbers import Real
from typing import NewType, Iterable, Tuple, ClassVar, Set, Sequence
import unittest
from unittest import TestCase


PlayerId = NewType('PlayerId', int)
PlayerName = NewType('PlayerName', str)
Club = NewType('Club', str)
Points = NewType('Points', Real)


@dataclass
class Player:
    """
    Represents a player in Fantasy Football.
    """
    p_id: PlayerId
    full_name: PlayerName
    shot_bonus: ClassVar[Points] = 0.4
    clean_sheet_bonus: ClassVar[Points] = 4
    assist_bonus: ClassVar[Points] = 3
    goal_bonus: ClassVar[Points]

    @staticmethod
    def booked_points(was_booked: bool) -> Points:
        if was_booked:
            return -1  # yellow_card
        return 0

    @classmethod
    def clean_sheet_points(cls, goals_against: int) -> Points:
        if goals_against == 0:
            return cls.clean_sheet_bonus
        return -(goals_against//2)

    @staticmethod
    def playtime_points(played_60: bool, finished_game: bool) -> Points:
        # if played_60:
        return 2
        # return 0

    @classmethod
    def goal_points(cls, goals: int) -> Points:
        return cls.goal_bonus * goals

    @classmethod
    def assist_points(cls, assists: int) -> Points:
        return assists * cls.assist_bonus

    @classmethod
    def shot_points(cls, shots_on: int, scored_goals: int) -> Points:
        return cls.shot_bonus*(shots_on - scored_goals)

    def captaincy_bonus(self, team: 'Team') -> Points:
        if team.captain is self:
            return 2
        if team.vice_captain is self:
            return 1.5
        return 1

    def get_points_before_captaincy(self, game: 'TeamGame') -> Points:
        return (
            self.booked_points(self.p_id in game.got_booked)
            + self.clean_sheet_points(game.goals_against)
            + game.impact
            + self.playtime_points(
                self.p_id in game.played60,
                self.p_id in game.finished_game,
            )
            + self.goal_points(
                game.scored_goals.count(self.p_id)
            )
            + self.assist_points(
                game.made_assist.count(self.p_id)
            )
            + self.shot_points(
                game.made_shots_on_tg.count(self.p_id),
                game.scored_goals.count(self.p_id),
            )
        )

    def get_points(self, game: 'TeamGame') -> Points:
        return self.get_points_before_captaincy(game) * self.captaincy_bonus(game.team)


class GoalKeeper(Player):
    shot_bonus = 0
    goal_bonus = 0
    assist_bonus = 0

    def get_points_before_captaincy(self, game: 'TeamGame') -> Points:
        return (
            super().get_points_before_captaincy(game)
            + game.saves * 0.5
        )


class Defender(Player):
    shot_bonus = 0.6
    goal_bonus = 6


class FrontLine(Player):
    @staticmethod
    def playtime_points(played_60: bool, finished_game: bool) -> Points:
        p = Player.playtime_points(played_60, finished_game)
        if finished_game:
            p += 1
        return p


class Midfielder(FrontLine):
    clean_sheet_bonus = 1
    goal_bonus = 5

    @classmethod
    def clean_sheet_points(cls, goals_against: int) -> Points:
        if goals_against == 0:
            return cls.clean_sheet_bonus
        return 0


class Forward(FrontLine):
    goal_bonus = 4

    @classmethod
    def clean_sheet_points(cls, goals_against: int) -> Points:
        return 0


class Team:
    def __init__(
        self,
        club: Club,
        players: Iterable[Player],
        vice_captain: Player,
        captain: Player,
    ) -> None:
        self.club, self.vice_captain, self.captain = club, vice_captain, captain
        self.players = {p.p_id: p for p in players}


@dataclass
class TeamGame:
    """
    Represents the result of a particular team with its name, goals scored,
    goals conceded, players who scored goals and made assists and the number of
    saves made by the goalkeeper.
    """
    team: Team
    goals_for: int
    goals_against: int
    saves: int
    scored_goals: Sequence[PlayerId]
    made_assist: Sequence[PlayerId]
    made_shots_on_tg: Sequence[PlayerId]
    played60: Set[PlayerId]
    finished_game: Set[PlayerId]
    got_booked: Set[PlayerId]

    @property
    def points_by_player(self) -> Iterable[Tuple[Player, Points]]:
        for player in self.team.players.values():
            yield player, player.get_points(self)

    @property
    def won(self) -> bool: return self.goals_for > self.goals_against
    @property
    def lost(self) -> bool: return self.goals_for < self.goals_against
    @property
    def draw(self) -> bool: return self.goals_for == self.goals_against

    @property
    def impact(self) -> Points:
        """
        Calculates impact for a team based on whether it won, lost or drew.
        """
        if self.won: return 0.3
        if self.lost: return -0.3
        return 0

    @property
    def points(self) -> Points:
        """
        Returns how many points the given team earned with the given team result.
        """
        return sum(points for player, points in self.points_by_player)


class TestGetTeamPoints(TestCase):
    pickford_id, shaw_id, maguire_id, mount_id, kane_id = (
        PlayerId(i) for i in (
            204597, 213442, 204614, 204615, 204617,
        )
    )
    phillips_id = PlayerId(99999)  # ???

    pickford = GoalKeeper(
        p_id=pickford_id, full_name=PlayerName('Jordan Pickford'),
    )
    shaw = Defender(
        p_id=shaw_id, full_name=PlayerName('Luke Shaw'),
    )

    team1 = Team(
        club=Club('ENG'),
        captain=pickford,
        vice_captain=shaw,
        players=(
            pickford, shaw,
            Defender(p_id=maguire_id, full_name=PlayerName('Harry Maguire')),
            Midfielder(p_id=mount_id, full_name=PlayerName('Mason Mount')),
            Forward(p_id=kane_id, full_name=PlayerName('Harry Kane')),
        ),
    )

    def test_won_game_with_cleansheet(self) -> None:
        team_result1 = TeamGame(
            team=self.team1,
            goals_for=1,
            goals_against=0,
            saves=3,
            scored_goals=[self.kane_id],
            made_assist=[self.phillips_id],
            played60={
                self.pickford_id, self.shaw_id, self.maguire_id, self.kane_id, self.phillips_id,
            },
            finished_game={
                self.pickford_id, self.shaw_id, self.maguire_id, self.kane_id, self.phillips_id, self.mount_id,
            },
            got_booked=set(),
            made_shots_on_tg=[
                self.kane_id, self.kane_id, self.mount_id, self.kane_id,
            ],
        )

        # self.assertAlmostEqual(team_result1.points, Points(44.15))
        team_result1.points

    def test_won_game_with_conceded_goal(self) -> None:
        team_result2 = TeamGame(
            team=self.team1,
            goals_for=2,
            goals_against=1,
            scored_goals=[self.mount_id],
            made_assist=[self.shaw_id],
            played60={self.pickford_id, self.shaw_id, self.maguire_id, self.phillips_id, self.mount_id, self.kane_id},
            finished_game={self.pickford_id, self.shaw_id, self.maguire_id},
            got_booked={self.pickford_id},
            made_shots_on_tg=[self.kane_id, self.mount_id, self.mount_id, self.kane_id],
            saves=2,
        )

        # self.assertAlmostEqual(team_result2.points, Points(25.65))
        team_result2.points

    def test_lost_game_with_no_goals_scored(self) -> None:
        team_result3 = TeamGame(
            team=self.team1,
            goals_for=0,
            goals_against=2,
            scored_goals=[],
            made_assist=[],
            played60={self.pickford_id, self.shaw_id, self.maguire_id, self.phillips_id, self.kane_id},
            finished_game={self.pickford_id, self.shaw_id, self.maguire_id, self.phillips_id, self.kane_id},
            got_booked={self.shaw_id, self.mount_id},
            made_shots_on_tg=[self.kane_id],
            saves=2,
        )

        # self.assertAlmostEqual(team_result3.points, Points(7.45))
        team_result3.points


if __name__ == '__main__':
    unittest.main()

Хотя это действительно выходит за рамки вашего вопроса, учитывая ваши приоритеты, вам вообще не следует использовать генераторы или классы. Это пример, который должен помочь вам начать путь к векторизации; это не совсем то же самое, что и вы, потому что в некоторых местах у вас есть кусочные операции и разделение полов. Чем меньше вы этого сделаете, тем лучше.

    positions = np.array(
        (
            # Goalkeep defender midfield forward
            (-1.0, -1.0, -1.0, -1.0),  # yellow-card booked
            (-0.5, -0.5,  0.0,  0.0),  # goals-against
            ( 0.0,  0.0,  1.0,  1.0),  # finished game
            ( 0.0,  6-0.6, 5-0.4, 4-0.4),  # goals, subtracting shot coefficient
            ( 0.5,  0.0,  0.0,  0.0),  # saves
            ( 0.0,  3.0,  3.0,  3.0),  # assists
            ( 0.0,  0.6,  0.4,  0.4),  # shots
        )
    )

    players = np.array(
        (
            # pickford shaw maguire mount kane
            (1.0, 0.0, 0.0, 0.0, 0.0),  # goalkeep
            (0.0, 1.0, 1.0, 0.0, 0.0),  # defender
            (0.0, 0.0, 0.0, 1.0, 0.0),  # midfield
            (0.0, 0.0, 0.0, 0.0, 1.0),  # forward
        )
    )

    result2 = np.array(
        (
            # pickford shaw maguire mount kane
            (1, 0, 0, 0, 0),  # yellow-card booked
            (1, 1, 1, 1, 1),  # goals against (whole team, broadcast)
            (1, 1, 1, 0, 0),  # finished game
            (0, 0, 0, 1, 0),  # goals
            (2, 2, 2, 2, 2),  # saves (whole team, broadcast)
            (0, 1, 0, 0, 0),  # assists
            (0, 0, 0, 2, 2),  # shots
        )
    )

    impact = 0.3
    played60 = 2
    captain = np.array((2, 1.5, 1, 1, 1))
    points = (positions @ players) * result2
    player_points = captain*(np.sum(points, axis=0) + impact + played60)
    game_points = np.sum(player_points)

  • Спасибо за обзор! 1. club является собственностью игрока, потому что фэнтезийная команда может состоять из игроков из разных клубов; 2. У меня было капитанское звание Enum в другой версии этой программы, хотя это не является серьезной проблемой; 3. Я использовал мутацию на месте в apply_captaincy чтобы сохранить некоторые вызовы функций и использовать его как метод класса в другой версии; 4. То же самое и с «points_factory», просто попытался сэкономить некоторые накладные расходы на вызов функции; 5. test_points.py только для демонстрационных целей;

    – Konstantin Kostanzhoglo


  • 6. scoring.played60 на будущее, пока можно оставить; 7. Многие игроки отсутствуют, потому что я создал только одну команду для демонстрационных целей.

    – Konstantin Kostanzhoglo

  • Если вы настолько заботитесь о микрооптимизации, что накладные расходы на вызов функций являются проблемой, вы используете совершенно неправильный стек и хотели бы перейти к numpy.

    — Райндериен

  • Я собираюсь предположить, что это преждевременная оптимизация.

    — Райндериен

  • На самом деле это не так, я успешно использую это в течение нескольких месяцев, тем не менее, я хотел бы сделать это быстрее, чтобы запускать более крупные симуляции в течение нескольких минут, а не в течение часа или двух.

    – Konstantin Kostanzhoglo

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *