Source code for kyu_5.sports_league_table_ranking.compute_ranks

#  Created by Egor Kostan.
#  GitHub: https://github.com/ikostan
#  LinkedIn: https://www.linkedin.com/in/egor-kostan/

from typing import Dict


[docs]def compute_ranks(number: int, games: list) -> list: """ organize a sports league in a round-robin-system. Each team meets all other teams. In your league a win gives a team 2 points, a draw gives both teams 1 point. After some games you have to compute the order of the teams in your league. You use the following criteria to arrange the teams: Points Scoring differential (the difference between goals scored and those conceded) Goals scored First you sort the teams by their points. If two or more teams reached the same number of points, the second criteria comes into play and so on. Finally, if all criteria are the same, the teams share a place. :param number: :param games: :return: """ if not games: return [1] * number teams: Dict = dict() numbers = [i for i in range(number)] for scores in games: team_a = scores[0] team_b = scores[1] calc_teams_score(team_a, team_b, teams, scores, number) process_not_played_games(teams, number) calc_gd(teams) calc_rank(teams) return [teams[i]['Rank'] for i in numbers]
[docs]def process_not_played_games(teams: dict, number: int) -> None: """ Set default values for teams who did not play a single game :param teams: :param number: :return: """ for n in range(number): if n not in teams: test_if_team_registered(n, teams, number)
[docs]def calc_teams_score(team_a, team_b, teams, team, number) -> None: """ Calculate following: For : Against Points Set default values for team as well :param team_a: :param team_b: :param teams: :param team: :param number: :return: """ test_if_team_registered(team_a, teams, number) calc_for_against(teams, team_a, team[2], team[3]) calc_team_points(team_a, teams, team[2], team[3]) test_if_team_registered(team_b, teams, number) calc_for_against(teams, team_b, team[3], team[2]) calc_team_points(team_b, teams, team[3], team[2])
[docs]def test_if_team_registered(team, teams, number) -> None: """ Check if team data was processed. Set default values otherwise. :param team: :param teams: :param number: :return: """ if team not in teams: teams[team] = dict() teams[team]["GD"] = 0 teams[team]["For:Against"] = [0, 0] teams[team]["Points"] = 0 teams[team]['Rank'] = number
[docs]def calc_team_points(team, teams, score_a, score_b) -> None: """ Calculates team points :param team: :param teams: :param score_a: :param score_b: :return: """ if score_a > score_b: teams[team]['Points'] += 2 elif score_a == score_b: teams[team]['Points'] += 1
[docs]def calc_for_against(teams, team, team_1, team_2) -> None: """ Collect "For:Against" data :param teams: :param team: :param team_1: :param team_2: :return: """ teams[team]["For:Against"][0] += team_1 teams[team]["For:Against"][1] += team_2
[docs]def calc_gd(teams) -> None: """ Calculates "GD" :param teams: :return: """ for team in teams: teams[team]["GD"] = teams[team]["For:Against"][0] - teams[team]["For:Against"][1]
[docs]def calc_rank(teams: dict) -> None: """ Calculates Rank First you sort the teams by their points. If two or more teams reached the same number of points, the second criteria comes into play and so on. Finally, if all criteria are the same, the teams share a place. :param teams: :return: """ for team_a in teams: for team_b in teams: if team_a != team_b: if teams[team_a]['Points'] > teams[team_b]['Points']: teams[team_a]['Rank'] -= 1 elif teams[team_a]['Points'] == teams[team_b]['Points'] and \ (teams[team_a]['GD'] > teams[team_b]['GD']): teams[team_a]['Rank'] -= 1 elif teams[team_a]['Points'] == teams[team_b]['Points'] and \ (teams[team_a]['GD'] == teams[team_b]['GD']) and \ (teams[team_a]["For:Against"][0] > teams[team_b]["For:Against"][0]): teams[team_a]['Rank'] -= 1 elif teams[team_a]['Points'] == teams[team_b]['Points'] and \ (teams[team_a]['GD'] == teams[team_b]['GD']) and \ (teams[team_a]["For:Against"][0] == teams[team_b]["For:Against"][0]): teams[team_a]['Rank'] -= 1