Premier League Simulation

woody101298

New Coder
Aug 6, 2019
3
0
1
So I've created a simulator for the Premier League, which takes in all of the 20 teams and plays them against each other, recording the results and outputting a table at the end.
The skill levels are based off a prediction in an article by The Telegraph (link at the end).
I am wondering whether or not my code can be improved, condensed or even added to with other features. Very new to coding so expecting lots of repetition/errors... Thank you for any help!

Here is my code:
Python:
import math, random



# HIGHER RATED TEAM

higher = 1.148698355

# LOWER RATED TEAM

lower = 0.8705505633





# DEFINING THE TEAM CLASS

class Team:

    def __init__(self, name, skill):

        self.name = name

        self.skill = skill

        self.points = self.gf = self.ga = self.wins = self.draws = self.losses = 0



    def add_goals(self, goals):

        self.gf += goals

      



# INITIALISING ALL OF THE TEAMS - NAMES AND SKILL LEVELS

arsenal = Team("Arsenal", 16)

aston_villa = Team("Aston Villa", 6)

bournemouth = Team("AFC Bournemouth", 8)

brighton = Team("Brighton and Hove Albion", 5)

burnley = Team("Burnley", 4)

chelsea = Team("Chelsea", 17)

crystal_palace = Team("Crystal Palace", 11)

everton = Team("Everton", 14)

leicester = Team("Leicester City", 12)

liverpool = Team("Liverpool", 19)

man_city = Team("Manchester City", 20)

man_united = Team("Manchester United", 15)

newcastle = Team("Newcastle United", 3)

norwich = Team("Norwich City", 2)

sheffield_united = Team("Sheffield United", 1)

southampton = Team("Southampton", 7)

tottenham = Team("Tottenham Hotspur", 18)

watford = Team("Watford", 9)

west_ham = Team("West Ham United", 10)

wolves = Team("Wolverhampton Wanderers", 13)



# HOME/AWAY TEAMS FOR PLAYING EACH TIME AGAINST EACH OTHER

teams = [arsenal, aston_villa, bournemouth, brighton, burnley, chelsea,

         crystal_palace, everton, leicester, liverpool, man_city, man_united,

         newcastle, norwich, sheffield_united, southampton, tottenham, watford,

         west_ham, wolves]



# PRINT ALL TEAMS' NAME AND SKILL

for team in teams:

    print(team.name, team.skill)



# RANDOM SYSTEM FOR HOME GOALS

def home_score(home, away):

    homeSkill = home.skill / 3

    awaySkill = away.skill / 3

 

    if homeSkill == awaySkill:

        raise ValueError

 

    if homeSkill > awaySkill:

        homeGoals = 0

        lambHome = higher ** (homeSkill - awaySkill)

        z = random.random()

        while z > 0:

            z = z - (((lambHome ** homeGoals) * math.exp(-1 * lambHome)) /

                     math.factorial(homeGoals))

            homeGoals += 1

        return (homeGoals - 1)



    if homeSkill < awaySkill:

        homeGoals = 0

        lambHome = higher ** (homeSkill - awaySkill)

        z = random.random()

        while z > 0:

            z = z - (((lambHome ** homeGoals) * math.exp(-1 * lambHome)) /

                     math.factorial(homeGoals))

            homeGoals += 1



        return (homeGoals - 1)



# RANDOM SYSTEM FOR AWAY GOALS

def away_score(home, away):

    homeSkill = home.skill / 3

    awaySkill = away.skill / 3



    if homeSkill == awaySkill:

        return "Teams cannot play themselves!!!"



    if awaySkill > homeSkill:

        awayGoals = 0

        lambAway = lower ** (homeSkill - awaySkill)

        x = random.random()

        while x > 0:

           x = x - (((lambAway ** awayGoals) * math.exp(-1 * lambAway)) /

                    math.factorial(awayGoals))

           awayGoals += 1

        return (awayGoals - 1)



    if awaySkill < homeSkill:

        awayGoals = 0

        lambAway = lower ** (homeSkill - awaySkill)

        x = random.random()

        while x > 0:

           x = x - (((lambAway ** awayGoals) * math.exp(-1 * lambAway)) /

                    math.factorial(awayGoals))

           awayGoals += 1

        return (awayGoals - 1)



# LEAGUE SIZE AND SETTING UP THE LEAGUE

league_size = 20

POINTS = []

GOALS_FOR = []

GOALS_AGAINST = []

WINS =[]

DRAWS = []

LOSSES = []

for x in range(league_size):

    POINTS += [0]

    GOALS_FOR += [0]

    GOALS_AGAINST += [0]

    WINS += [0]

    DRAWS += [0]

    LOSSES += [0]



# PLAYING ALL TEAMS AGAINST EACH OTHER AND UPDATING STATISTICS

for x in range(league_size):

    print("========================================")

    print(teams[x].name + "'s home games: ")

    print("========================================")

    for y in range(league_size):

        error = 0

        try:

            homeScore = home_score(teams[x], teams[y])

        except ValueError:

            pass

            error += 1

        try:

            awayScore = away_score(teams[x], teams[y])

        except ValueError:

            pass

        if error == 0:

            print(teams[x].name, homeScore, ":", awayScore, teams[y].name)

            GOALS_FOR[x] += homeScore

            GOALS_FOR[y] += awayScore

            GOALS_AGAINST[x] += awayScore

            GOALS_AGAINST[y] += homeScore

            if homeScore > awayScore:

                WINS[x] += 1

                LOSSES[y] += 1

                POINTS[x] += 3

            elif homeScore == awayScore:

                DRAWS[x] += 1

                DRAWS[y] += 1

                POINTS[x] += 1

                POINTS[y] += 1

            else:

                WINS[y] += 1

                LOSSES[x] += 1

                POINTS[y] += 3

        else:

            pass



# ASSIGNING STATISTICS TO EACH TEAM

for x in range(league_size):

    teams[x].points = POINTS[x]

    teams[x].gf = GOALS_FOR[x]

    teams[x].ga = GOALS_AGAINST[x]

    teams[x].wins = WINS[x]

    teams[x].draws = DRAWS[x]

    teams[x].losses = LOSSES[x]



sorted_teams = sorted(teams, key=lambda t: t.points, reverse=True)





# PRITNING THE FINAL LEAGUE TABLE

print("| TEAM                      | POINTS | WINS | DRAWS | LOSSES | GOALS FOR | GOALS AGAINST |")

for team in sorted_teams:

    print("|",team.name," "*(24 - len(team.name)),"|  ",team.points," "*(3 - len(str(team.points))),"| ",team.wins," "*(2 - len(str(team.wins))),"|  ",

          team.draws," "*(2 - len(str(team.draws))),"|  ",team.losses," "*(3 - len(str(team.losses))),"|    ",team.gf," "*(4 - len(str(team.gf))),"|     ",

          team.ga," "*(7 - len(str(team.ga))),"|")
 
Last edited:

Dan-Kode

Well-Known Coder
May 24, 2019
433
119
53
github.com
Hey, @woody101298.

I'm just Posting this to let you know that you haven't formatted the Code to be in a Code-Snippet which in return, makes it un-readable.

Please refer to what @Malcolm has mentioned, in the Python Board Guidelines(Which also applies to all other Boards)
  1. Insert all your code within </> Code and or >_ Inline Code bbcode feature. This allows others to easily view your code and be able to understand and or give you better support. You can do this by hovering and clicking the three (3) dots, where then you'll be able to insert many different options including the Code and Inline Code bbcode.


Please do what was quoted above. Doing so will make your Code much easier to read.
 
  • Like
Reactions: Malcolm

woody101298

New Coder
Aug 6, 2019
3
0
1
Hey, @woody101298.

I'm just Posting this to let you know that you haven't formatted the Code to be in a Code-Snippet which in return, makes it un-readable.

Please refer to what @Malcolm has mentioned, in the Python Board Guidelines(Which also applies to all other Boards)


Please do what was quoted above. Doing so will make your Code much easier to read.
Thank you! @Malcolm
 

Weboogle

Active Coder
Apr 13, 2019
194
42
28
31
So I've created a simulator for the Premier League, which takes in all of the 20 teams and plays them against each other, recording the results and outputting a table at the end.
The skill levels are based off a prediction in an article by The Telegraph (link at the end).
I am wondering whether or not my code can be improved, condensed or even added to with other features. Very new to coding so expecting lots of repetition/errors... Thank you for any help!

Here is my code:
Python:
import math, random



# HIGHER RATED TEAM

higher = 1.148698355

# LOWER RATED TEAM

lower = 0.8705505633





# DEFINING THE TEAM CLASS

class Team:

    def __init__(self, name, skill):

        self.name = name

        self.skill = skill

        self.points = self.gf = self.ga = self.wins = self.draws = self.losses = 0



    def add_goals(self, goals):

        self.gf += goals

     



# INITIALISING ALL OF THE TEAMS - NAMES AND SKILL LEVELS

arsenal = Team("Arsenal", 16)

aston_villa = Team("Aston Villa", 6)

bournemouth = Team("AFC Bournemouth", 8)

brighton = Team("Brighton and Hove Albion", 5)

burnley = Team("Burnley", 4)

chelsea = Team("Chelsea", 17)

crystal_palace = Team("Crystal Palace", 11)

everton = Team("Everton", 14)

leicester = Team("Leicester City", 12)

liverpool = Team("Liverpool", 19)

man_city = Team("Manchester City", 20)

man_united = Team("Manchester United", 15)

newcastle = Team("Newcastle United", 3)

norwich = Team("Norwich City", 2)

sheffield_united = Team("Sheffield United", 1)

southampton = Team("Southampton", 7)

tottenham = Team("Tottenham Hotspur", 18)

watford = Team("Watford", 9)

west_ham = Team("West Ham United", 10)

wolves = Team("Wolverhampton Wanderers", 13)



# HOME/AWAY TEAMS FOR PLAYING EACH TIME AGAINST EACH OTHER

teams = [arsenal, aston_villa, bournemouth, brighton, burnley, chelsea,

         crystal_palace, everton, leicester, liverpool, man_city, man_united,

         newcastle, norwich, sheffield_united, southampton, tottenham, watford,

         west_ham, wolves]



# PRINT ALL TEAMS' NAME AND SKILL

for team in teams:

    print(team.name, team.skill)



# RANDOM SYSTEM FOR HOME GOALS

def home_score(home, away):

    homeSkill = home.skill / 3

    awaySkill = away.skill / 3



    if homeSkill == awaySkill:

        raise ValueError



    if homeSkill > awaySkill:

        homeGoals = 0

        lambHome = higher ** (homeSkill - awaySkill)

        z = random.random()

        while z > 0:

            z = z - (((lambHome ** homeGoals) * math.exp(-1 * lambHome)) /

                     math.factorial(homeGoals))

            homeGoals += 1

        return (homeGoals - 1)



    if homeSkill < awaySkill:

        homeGoals = 0

        lambHome = higher ** (homeSkill - awaySkill)

        z = random.random()

        while z > 0:

            z = z - (((lambHome ** homeGoals) * math.exp(-1 * lambHome)) /

                     math.factorial(homeGoals))

            homeGoals += 1



        return (homeGoals - 1)



# RANDOM SYSTEM FOR AWAY GOALS

def away_score(home, away):

    homeSkill = home.skill / 3

    awaySkill = away.skill / 3



    if homeSkill == awaySkill:

        return "Teams cannot play themselves!!!"



    if awaySkill > homeSkill:

        awayGoals = 0

        lambAway = lower ** (homeSkill - awaySkill)

        x = random.random()

        while x > 0:

           x = x - (((lambAway ** awayGoals) * math.exp(-1 * lambAway)) /

                    math.factorial(awayGoals))

           awayGoals += 1

        return (awayGoals - 1)



    if awaySkill < homeSkill:

        awayGoals = 0

        lambAway = lower ** (homeSkill - awaySkill)

        x = random.random()

        while x > 0:

           x = x - (((lambAway ** awayGoals) * math.exp(-1 * lambAway)) /

                    math.factorial(awayGoals))

           awayGoals += 1

        return (awayGoals - 1)



# LEAGUE SIZE AND SETTING UP THE LEAGUE

league_size = 20

POINTS = []

GOALS_FOR = []

GOALS_AGAINST = []

WINS =[]

DRAWS = []

LOSSES = []

for x in range(league_size):

    POINTS += [0]

    GOALS_FOR += [0]

    GOALS_AGAINST += [0]

    WINS += [0]

    DRAWS += [0]

    LOSSES += [0]



# PLAYING ALL TEAMS AGAINST EACH OTHER AND UPDATING STATISTICS

for x in range(league_size):

    print("========================================")

    print(teams[x].name + "'s home games: ")

    print("========================================")

    for y in range(league_size):

        error = 0

        try:

            homeScore = home_score(teams[x], teams[y])

        except ValueError:

            pass

            error += 1

        try:

            awayScore = away_score(teams[x], teams[y])

        except ValueError:

            pass

        if error == 0:

            print(teams[x].name, homeScore, ":", awayScore, teams[y].name)

            GOALS_FOR[x] += homeScore

            GOALS_FOR[y] += awayScore

            GOALS_AGAINST[x] += awayScore

            GOALS_AGAINST[y] += homeScore

            if homeScore > awayScore:

                WINS[x] += 1

                LOSSES[y] += 1

                POINTS[x] += 3

            elif homeScore == awayScore:

                DRAWS[x] += 1

                DRAWS[y] += 1

                POINTS[x] += 1

                POINTS[y] += 1

            else:

                WINS[y] += 1

                LOSSES[x] += 1

                POINTS[y] += 3

        else:

            pass



# ASSIGNING STATISTICS TO EACH TEAM

for x in range(league_size):

    teams[x].points = POINTS[x]

    teams[x].gf = GOALS_FOR[x]

    teams[x].ga = GOALS_AGAINST[x]

    teams[x].wins = WINS[x]

    teams[x].draws = DRAWS[x]

    teams[x].losses = LOSSES[x]



sorted_teams = sorted(teams, key=lambda t: t.points, reverse=True)





# PRITNING THE FINAL LEAGUE TABLE

print("| TEAM                      | POINTS | WINS | DRAWS | LOSSES | GOALS FOR | GOALS AGAINST |")

for team in sorted_teams:

    print("|",team.name," "*(24 - len(team.name)),"|  ",team.points," "*(3 - len(str(team.points))),"| ",team.wins," "*(2 - len(str(team.wins))),"|  ",

          team.draws," "*(2 - len(str(team.draws))),"|  ",team.losses," "*(3 - len(str(team.losses))),"|    ",team.gf," "*(4 - len(str(team.gf))),"|     ",

          team.ga," "*(7 - len(str(team.ga))),"|")
I’m impressed. Well done.
 

Ghost

Active Coder
Moderator
Apr 19, 2019
303
140
43
To be honest, you should add the following stats (all per match and per team) based on this or last season to improve your simulation:
  1. % chance of injury - should alter the stats of team to affect simulated matches after the injury.
  2. Availability of good sub players for injury
  3. Average attempts at goal
  4. Actual goals scored compared to attempts
  5. Number of attempts a defense allows on average
  6. Number of goals given up on average
  7. Win rate for Home games
  8. Win rate for Away games
  9. First half performance stat
  10. Second half performance stat
I can think of more, but start with those. Integrate them in a way that allows much more realistic simulations. You will even be able to simulate seasons in which an underdog team goes far due to good teams facing injuries, and other specific results.