-1
\$\begingroup\$

Here is my first attempt at creating a full Champions League Simulation, including drawing the groups and subsequent games and playing all matches. The code is very, very long and I am sure there must be a more concise way of writing it.

One problem I could not get around was when drawing the groups not allowing a team from the same league to be in the same group and also ensuring that each team only appeared in one group.

Below is the code, I have tried to use as little unnecessary code as possible but a lot of the functions have just one or two differences. Let me know what you think and if I can solve any problems or reduce the code. Thanks!

from typing import Any
import math
import random

H_PARAMETER = 1.148698355
A_PARAMETER = 0.8705505633

class Team:
    def __init__(self, name, league, skill):
        self.name = name
        self.league = league
        self.skill = skill
        self.points = self.gf = self.ga = self.wins = self.draws = self.losses = self.mp = 0
        self.kohg = self.koag = self.qfhg = self.qfag = self.sfhg = self.sfag = 0
        self.kog = 0 # For knockout goals - so that they start from zero
        self.qfg = 0  # For quarter final goals - so that they start from zero
        self.sfg = 0  # For semi final goals - so that they start from zero
        self.fg = 0  # For final goals - so that they start from zero
        self.penalty = 0 # For penalty shootout in the final

pot_1 = []
pot_2 = []
pot_3 = []
pot_4 = []

group_a = []
group_b = []
group_c = []
group_d = []
group_e = []
group_f = []
group_g = []
group_h = []
groups = [group_a, group_b, group_c, group_d, group_e, group_f, group_g, group_h]

allocated_teams = []
qualified_for_knockouts = []
qualified_quarter_finals =[]
qualified_semi_finals =[]
qualified_final =[]

match_1_teams = []
match_2_teams = []
match_3_teams = []
match_4_teams = []
match_5_teams = []
match_6_teams = []
match_7_teams = []
match_8_teams = []
match_teams = [match_1_teams, match_2_teams, match_3_teams, match_4_teams, match_5_teams, match_6_teams,
               match_7_teams, match_8_teams]

quarter_final_1 = []
quarter_final_2 = []
quarter_final_3 = []
quarter_final_4 = []
quarter_finals =[quarter_final_1, quarter_final_2, quarter_final_3, quarter_final_4]

semi_final_1 = []
semi_final_2 = []
semi_finals = [semi_final_1, semi_final_2]


def group_selection(group):

    selection_1 = random.choice(pot_1)
    group.append(selection_1)
    pot_1.remove(selection_1)

    selection_2 = random.choice(pot_2)
    group.append(selection_2)
    pot_2.remove(selection_2)

    selection_3 = random.choice(pot_3)
    group.append(selection_3)
    pot_3.remove(selection_3)

    selection_4 = random.choice(pot_4)
    group.append(selection_4)
    pot_4.remove(selection_4)

def generate_random_goals(delta_skill, parameter):
    if delta_skill == 0:
        raise ValueError
    goals = 0
    lamb = parameter ** delta_skill
    z = random.random()
    while z > 0:
        z = z - (((lamb ** goals) * math.exp(-1 * lamb)) /
                 math.factorial(goals))
        goals += 1
    return goals - 1

def generate_random_score(home, away):
    delta_skill = (home.skill - away.skill) / 12
    return generate_random_goals(delta_skill, H_PARAMETER), generate_random_goals(delta_skill, A_PARAMETER)

def simulate_league(group):
    for home_team in group:
        print("=" * 50)
        print(home_team.name.upper() + "'S HOME GAMES: ")
        print("=" * 50)
        for away_team in group:
            if home_team == away_team:
                pass
            if home_team != away_team:
                home_score, away_score = generate_random_score(home_team, away_team)
                print(home_team.name, home_score, ":", away_score, away_team.name)
                home_team.gf += home_score
                away_team.gf += away_score
                home_team.ga += away_score
                away_team.ga += home_score
                home_team.mp += 1
                away_team.mp += 1
                if home_score == away_score:
                    home_team.draws += 1
                    away_team.draws += 1
                    home_team.points += 1
                    away_team.points += 1
                if home_score > away_score:
                    home_team.wins += 1
                    away_team.losses += 1
                    home_team.points += 3
                if away_score > home_score:
                    away_team.wins += 1
                    home_team.losses += 1
                    away_team.points += 3

def simulate_knockout(knockout_match_teams):
    for home_team in knockout_match_teams:
        print("=" * 50)
        print(home_team.name.upper() + "'S HOME GAME: ")
        print("=" * 50)
        for away_team in knockout_match_teams:
            if home_team == away_team:
                pass
            if home_team != away_team:
                home_score, away_score = generate_random_score(home_team, away_team)
                print(home_team.name, home_score, ":", away_score, away_team.name)
                home_team.kog += home_score
                away_team.kog += away_score
                away_team.koag += away_score

def simulate_quarters(quarter_finals_teams):
    for home_team in quarter_finals_teams:
        print("=" * 50)
        print(home_team.name.upper() + "'S HOME GAME: ")
        print("=" * 50)
        for away_team in quarter_finals_teams:
            if home_team == away_team:
                pass
            if home_team != away_team:
                home_score, away_score = generate_random_score(home_team, away_team)
                print(home_team.name, home_score, ":", away_score, away_team.name)
                home_team.qfg += home_score
                away_team.qfg += away_score
                away_team.qfag += away_score

def simulate_semis(semi_finals_teams):
    for home_team in semi_finals_teams:
        print("=" * 50)
        print(home_team.name.upper() + "'S HOME GAME: ")
        print("=" * 50)
        for away_team in semi_finals_teams:
            if home_team == away_team:
                pass
            if home_team != away_team:
                home_score, away_score = generate_random_score(home_team, away_team)
                print(home_team.name, home_score, ":", away_score, away_team.name)
                home_team.sfg += home_score
                away_team.sfg += away_score
                away_team.sfag += away_score

def simulate_final(team_1, team_2):
    home_score, away_score = generate_random_score(team_1, team_2)
    print(team_1.name, home_score, ":", away_score, team_2.name)
    team_1.fg += home_score
    team_2.fg += away_score
    if team_1.fg == team_2.fg:
        penalty_shootout(team_1, team_2)
    if team_1.fg > team_2.fg:
        print("=" * 50)
        print(team_1.name, "have won the UEFA Champions League")
    if team_2.fg > team_1.fg:
        print("=" * 50)
        print(team_2.name, "have won the UEFA Champions League")


def penalty_shootout(team_1, team_2):
    print("The game has ended with the scores level!\n")
    print("This means the game has gone to a penalty shootout!\n")
    input("Press enter to start the penalty shootout.\n")
    team_1.penalty += random.randint(1,1000)
    team_2.penalty += random.randint(1,1000)
    if team_1.penalty > team_2.penalty:
        print(team_1.name, "have won the penalty shootout\n")
        print(team_1.name, "are the winners of the UEFA Champions League.")
    if team_1.penalty < team_2.penalty:
        print(team_2.name, "have won the penalty shootout\n")
        print(team_2.name, "are the winners of the UEFA Champions League.")
    if team_1.penalty == team_2.penalty:
        team_1_decider = random.randint(1,1000)
        team_2_decider = random.randint(1,1000)
        if team_1_decider > team_2_decider:
            print(team_1.name, "have won the penalty shootout\n")
            print(team_1.name, "are the winners of the UEFA Champions League.")
        if team_2_decider > team_1_decider:
            print(team_1.name, "have won the penalty shootout\n")
            print(team_1.name, "are the winners of the UEFA Champions League.")







if __name__ == "__main__":

    print("UEFA Champions League Simulator")
    print("Are you ready to play your very own UEFA Champions League?")
    input("Press the enter key to begin. \n")

    all_teams = [
        Team("Chelsea", "Premier League", 87), Team("Liverpool", "Premier League", 91),
        Team("Manchester City", "Premier League", 106), Team("Barcelona", "La Liga", 138),
        Team("Bayern Munich", "Bundesliga", 128), Team("Juventus", "Serie A", 124), Team("PSG", "Ligue 1", 103),
        Team("Zenit", "Russian Premier League", 72), Team("Tottenham Hotspur", "Premier League", 78),
        Team("Real Madrid", "La Liga", 146), Team("Atletico Madrid", "La Liga", 127), Team("Valencia", "La Liga", 37),
        Team("Borussia Dortmund", "Bundesliga", 85), Team("Bayer Leverkusen", "Bundesliga", 61),
        Team("RB Leipzig", "Bundesliga", 22), Team("Napoli", "Serie A", 80.1), Team("Inter Milan", "Serie A", 31.1),
        Team("Atalanta", "Serie A", 14.945), Team("Olimpique Lyon", "Ligue 1", 61.5),
        Team("LOSC Lille", "Ligue 1", 11.699), Team("Locomotiv Moskva", "Russian Premier League", 28.5),
        Team("Shakhtar Donetsk", "Ukrainian Premier League", 80),
        Team("FC Red Bull Salzburg", "Austrian Bundesliga", 54.51), Team("Benfica", "Primeira Liga", 68),
        Team("K.R.C. Genk", "Belgian First Division", 25), Team("Galatasaray", "Super Lig", 22.5),
        Team("Ajax", "Eredivisie", 70.5), Team("Celtic", "Scottish Premiership", 31),
        Team("Porto", "Primeira Liga", 93), Team("Dynamo Kyiv", "Ukrainian Premier League", 65),
        Team("PAOK", "Super League Greece", 23.5), Team("Basel", "Swiss Super League", 54.5)
    ]

    skill_sorted_teams = sorted(all_teams, key=lambda t: t.skill, reverse=True)

    for team in all_teams[:8]:
        pot_1.append(team)
    for team in pot_1:
        allocated_teams.append(team)
    for team in skill_sorted_teams:
        if len(pot_2) < 8 and team not in pot_1:
            pot_2.append(team)
            allocated_teams.append(team)
    for team in skill_sorted_teams:
        if len(pot_3) < 8 and team not in allocated_teams:
            pot_3.append(team)
            allocated_teams.append(team)
    for team in skill_sorted_teams:
        if len(pot_4) < 8 and team not in allocated_teams:
            pot_4.append(team)
            allocated_teams.append(team)

    print("First, pots will be arranged to complete the draw.")
    input("Press the enter key to see the pots.\n")

    print("\n")
    print("Pot 1:")
    print("=" * 40)
    for team in pot_1:
        print(team.name, "|", team.league, "|", team.skill)
    print("=" * 40)
    print("\n")
    print("Pot 2:")
    print("=" * 40)
    for team in pot_2:
        print(team.name, "|", team.league, "|", team.skill)
    print("=" * 40)
    print("\n")
    print("Pot 3:")
    print("=" * 40)
    for team in pot_3:
        print(team.name, "|", team.league, "|", team.skill)
    print("=" * 40)
    print("\n")
    print("Pot 4:")
    print("=" * 40)
    for team in pot_4:
        print(team.name, "|", team.league, "|", team.skill)
    print("=" * 40)
    print("\n")

    group_selection(group_a)
    group_selection(group_b)
    group_selection(group_c)
    group_selection(group_d)
    group_selection(group_e)
    group_selection(group_f)
    group_selection(group_g)
    group_selection(group_h)

    print("It's time to do the group stage draw.")
    input("Press the enter key to see the groups. \n")

    print("=" * 20)
    print("Group A:")
    print("=" * 20)
    for team in group_a:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group B:")
    print("=" * 20)
    for team in group_b:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group C:")
    print("=" * 20)
    for team in group_c:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group D:")
    print("=" * 20)
    for team in group_d:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group E:")
    print("=" * 20)
    for team in group_e:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group F:")
    print("=" * 20)
    for team in group_f:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group G:")
    print("=" * 20)
    for team in group_g:
        print(team.name)
    print("\n")
    print("=" * 20)
    print("Group H:")
    print("=" * 20)
    for team in group_h:
        print(team.name)
    print("=" * 20)
    print("\n")

    print("Now it's time to play the group stage matches.")
    input("Press the enter key to see the results.\n")

    for group in groups:
        simulate_league(group)

    print("\n")
    input("Press the enter key to see the standings.\n")

    sorted_group_a = sorted(group_a, key=lambda t: t.points, reverse=True)
    sorted_group_b = sorted(group_b, key=lambda t: t.points, reverse=True)
    sorted_group_c = sorted(group_c, key=lambda t: t.points, reverse=True)
    sorted_group_d = sorted(group_d, key=lambda t: t.points, reverse=True)
    sorted_group_e = sorted(group_e, key=lambda t: t.points, reverse=True)
    sorted_group_f = sorted(group_f, key=lambda t: t.points, reverse=True)
    sorted_group_g = sorted(group_g, key=lambda t: t.points, reverse=True)
    sorted_group_h = sorted(group_h, key=lambda t: t.points, reverse=True)
    sorted_groups = [sorted_group_a, sorted_group_b, sorted_group_c, sorted_group_d, sorted_group_e, sorted_group_f,
                     sorted_group_g, sorted_group_h]

    for group in sorted_groups:
        print(
        "| {:<20} | {:^4} | {:^3} | {:^3} | {:^3} | {:^4} | {:^4} | {:^6} |".format("CLUB", "MP", "W", "D",
                                                                                            "L", "GF",
                                                                                            "GA", "PTS"))
        for team in group:
            print("| {:<20} | {:^4} | {:^3} | {:^3} | {:^3} | {:^4} | {:^4} | {:^6} |".format(team.name, team.mp,
                                                                                                  team.wins,
                                                                                                  team.draws,
                                                                                                  team.losses,
                                                                                                  team.gf,
                                                                                                  team.ga,
                                                                                                  team.points))
        print("\n")

    input("Press the enter key to see which teams have made it through to the knockout stages of the competition.\n")

    for group in sorted_groups:
            qualified_for_knockouts.append(group[0])
            qualified_for_knockouts.append(group[1])


    for team in qualified_for_knockouts:
        print(team.name)

    print("\n")
    input("Press the enter key to see the results of the round of 16.\n")

    for match in match_teams:
        selection_1 = random.choice(qualified_for_knockouts)
        match.append(selection_1)
        qualified_for_knockouts.remove(selection_1)
        selection_2 = random.choice(qualified_for_knockouts)
        match.append(selection_2)
        qualified_for_knockouts.remove(selection_2)

    for matches in match_teams:
        simulate_knockout(matches)
        print("\n")

    for match in match_teams:
        if match[0].kog > match[1].kog:
            qualified_quarter_finals.append(match[0])
        elif match[0].kog < match[1].kog:
            qualified_quarter_finals.append(match[1])
        elif match[0].kog == match[1].kog:
            if match[0].koag > match[1].koag:
                qualified_quarter_finals.append(match[0])
            elif match[0].koag < match[1].koag:
                qualified_quarter_finals.append(match[1])
            else:
                winner = random.randint(0,1)
                qualified_quarter_finals.append(match[winner])

    input("Press the enter key to see which teams have made it through to the quarter finals of the competition.\n")

    for team in qualified_quarter_finals:
        print(team.name)
    print("\n")

    for quarter_final in quarter_finals:
        selection_1 = random.choice(qualified_quarter_finals)
        quarter_final.append(selection_1)
        qualified_quarter_finals.remove(selection_1)
        selection_2 = random.choice(qualified_quarter_finals)
        quarter_final.append(selection_2)
        qualified_quarter_finals.remove(selection_2)

    input("Press the enter key to see the results of the quarter finals.\n")

    for quarter_final in quarter_finals:
        simulate_quarters(quarter_final)
        print("\n")

    for match in quarter_finals:
        if match[0].qfg > match[1].qfg:
            qualified_semi_finals.append(match[0])
        elif match[0].qfg < match[1].qfg:
            qualified_semi_finals.append(match[1])
        elif match[0].qfg == match[1].qfg:
            if match[0].qfag > match[1].qfag:
                qualified_semi_finals.append(match[0])
            elif match[0].qfag < match[1].qfag:
                qualified_semi_finals.append(match[1])
            else:
                winner = random.randint(0,1)
                qualified_semi_finals.append(match[winner])

    input("Press the enter key to see which teams have made it through to the semi finals of the competition.\n")

    for team in qualified_semi_finals:
        print(team.name)
    print("\n")

    for semi_final in semi_finals:
        selection_1 = random.choice(qualified_semi_finals)
        semi_final.append(selection_1)
        qualified_semi_finals.remove(selection_1)
        selection_2 = random.choice(qualified_semi_finals)
        semi_final.append(selection_2)
        qualified_semi_finals.remove(selection_2)

    input("Press the enter key to see the results of the quarter finals.\n")

    for semi_final in semi_finals:
        simulate_semis(semi_final)
        print("\n")

    for match in semi_finals:
        if match[0].sfg > match[1].sfg:
            qualified_final.append(match[0])
        elif match[0].sfg < match[1].sfg:
            qualified_final.append(match[1])
        elif match[0].sfg == match[1].sfg:
            if match[0].sfag > match[1].sfag:
                qualified_final.append(match[0])
            elif match[0].sfag < match[1].sfag:
                qualified_final.append(match[1])
            else:
                winner = random.randint(0,1)
                qualified_final.append(match[winner])

    input("Press the enter key to see which teams have made it through to the final of the competition.\n")

    for team in qualified_final:
        print(team.name)
    print("\n")

    print("Presenting the final of the UEFA Champions League.\n")
    print("="*50)
    print(qualified_final[0].name, "VS", qualified_final[1].name)
    print("="*50)
    print("\n")
    input("Press the enter key to see which team has won the Champions League.\n")

    simulate_final(qualified_final[0], qualified_final[1])

```
\$\endgroup\$

closed as off-topic by πάντα ῥεῖ, dfhwze, 200_success, pacmaninbw, AlexV Aug 20 at 17:00

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – πάντα ῥεῖ, dfhwze, 200_success, pacmaninbw, AlexV
If this question can be reworded to fit the rules in the help center, please edit the question.

2
\$\begingroup\$

Don't shorten variable names. It's really annoying having to scroll back to the top of the page and read a comment to know what 'kog' or kohg' stands for. The interpreter doesn't care how long variable names are, but humans do.

Use meaningful names. What the heck is H_PARAMATER and A_PARAMATER? Most of the time 1 letter variable names are also meaningless, such as z.

Arrays are very useful. No need to have group_a - group_h or pot_1 - pot_4 (whatever the heck pot means. This will be a maintenance nightmare.

Your indentation is off in a couple places, such as here:

for group in sorted_groups:
    print(
    "| {:<20} | {:^4} | {:^3} | {:^3} | {:^3} | {:^4} | {:^4} | {:^6} |".format("CLUB", "MP", "W", "D",
                                                                                        "L", "GF",
                                                                                        "GA", "PTS"))
    for team in group:
        print("| {:<20} | {:^4} | {:^3} | {:^3} | {:^3} | {:^4} | {:^4} | {:^6} |".

Use method names that make sense. penalty_shootout isn't really a method name. All your methods also seem to be doing many things, I suggest creating more methods, each only doing 1 thing.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.