Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

Python Premier League Simulation

woody101298

New Coder
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:
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.
 
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.
 
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.
 

New Threads

Latest posts

Buy us a coffee!

Back
Top Bottom