diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b6e4761 --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..98c208b --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# Racing Info CLI + +A CLI program to track information about various motor racing series, such as the teams, drivers, engine manufacturers, and championship standings. + +Current implementation includes the Formula One 2023 Championship. + +## Glossary of Terms + +*This glossary is listed in no particular order.* + +#### **Formula One / Formula 1 / F1** +An international motor racing series featuring open wheel racing. Currently, Formula One races are only street circuits or road courses. Famous Formula One drivers include Michael Schumacher, Lewis Hamilton, Max Verstappen, Fernando Alonso, and Sebastian Vettel. + +#### **Formula Two / Formula 2 / F2** +A junior series of Formula One. Similar to the relationship between Minor League Baseball and Major League Baseball. + +#### **Formula E** +The electric vehicle open wheel racing series governed by the FIA. + +#### **FIA / Fédération Internationale de l'Automobile** +The governing body of Formula One, and other related motor-racing series like Formula Two and Formula E. + +#### **IndyCar** +A series of open wheel racing based in the United States. Most race are in the United States, although drivers come from a variety of countries. The points and team structures of IndyCar are very different from the system used by Formula One. IndyCar tracks can be ovals, street circuits, or road courses. + +#### **Open Wheel Racing** +A type of vehicle in which the wheels are exposed. If you've seen Cars 2, think of the Italian race-car. Open wheel racing series include Formula One and IndyCar. This is in contrast to series like Nascar, in which the cars look very similar to regular street cars. + +## Usage + +### Set up environment + +From the root project directory (`final_project-platt-sam`) run the following commands: + + virtualenv -p python3 env + source env/bin/activate + +### Install required packages + + pip3 install -r requirements.txt + +### Run unit tests + + pytest tests + +All tests should pass. Please report any failed tests to the project maintainer. + +### Run the main program + + python3 main.py + +## Future Versions + +* include Team Principals as an attribute of a Team +* add other FIA series like Formula 2, Formula E, and WEC (World Endurance Championship) +* differentiate between reserve/test drivers and full-time drivers +* add support for IndyCar type series + * add support for calculating standings using IndyCar's points system + * create an abstract class for Teams, create concrete classes for IndyCar and Formula One teams \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py new file mode 100644 index 0000000..37c8efa --- /dev/null +++ b/main.py @@ -0,0 +1,278 @@ +from src.championship.championship import Championship +from src.driver.driver import Driver +from src.engine.engine import * +from src.race.race import Race +from src.race.raceResults import RaceResults +from src.series.series import Series +from src.team.team import Team +from src.team.teamFactory import TeamFactory + +def main(): + + # instantiate the Formula One Series + formula_one = Series("Formula One") + + # instantiate the 2023 Formula One Championship + formula_one_2023 = Championship(series = formula_one, year = 2023) + + # instantiate drivers + + alb = Driver(surname = "Albon", givenname = "Alexander", number = 23, nationality = "Thailand") + alo = Driver(surname = "Alonso", givenname = "Fernando", number = 14, nationality = "Spain") + bot = Driver(surname = "Bottas", givenname = "Valtteri", number = 77, nationality = "Finland") + dev = Driver(surname = "de Vries", givenname = "Nyck", number = 21, nationality = "Netherlands") + gas = Driver(surname = "Gasly", givenname = "Pierre", number = 10, nationality = "France") + ham = Driver(surname = "Hamilton", givenname = "Lewis", number = 44, nationality = "United Kingdom") + hul = Driver(surname = "Hülkenberg", givenname = "Nico", number = 27, nationality = "Germany") + lec = Driver(surname = "Leclerc", givenname = "Charles", number = 16, nationality = "Monaco") + mag = Driver(surname = "Magnussen", givenname = "Kevin", number = 20, nationality = "Denmark") + nor = Driver(surname = "Norris", givenname = "Lando", number = 4, nationality = "United Kingdom") + oco = Driver(surname = "Ocon", givenname = "Esteban", number = 31, nationality = "France") + per = Driver(surname = "Pérez", givenname = "Sergio", number = 11, nationality = "Mexico") + pia = Driver(surname = "Piastri", givenname = "Oscar", number = 81, nationality = "Australia") + rus = Driver(surname = "Russell", givenname = "George", number = 63, nationality = "United Kingdom") + sai = Driver(surname = "Sainz", suffix = "Jr.", givenname = "Carlos", number = 55, nationality = "Spain") + sar = Driver(surname = "Sargeant", givenname = "Logan", number = 2, nationality = "United States") + stroll = Driver(surname = "Stroll", givenname = "Lance", number = 18, nationality = "Canada") # str is a reserved word + tsu = Driver(surname = "Tsunoda", givenname = "Yuki", number = 22, nationality = "Japan") + ver = Driver(surname = "Verstappen", givenname = "Max", number = 1, nationality = "Netherlands") + zho = Driver(surname = "Zhou", givenname = "Guanyu", number = 24, nationality = "China", surname_first = True) + + # create teams using TeamFactory + + alfa_romeo = TeamFactory.createTeamFerrariEngine( + name = "Alfa Romeo", + country = "Switzerland", + drivers = [bot, zho] + ) + alphatauri = TeamFactory.createTeamHondaRBPTEngine( + name = "AlphaTauri", + country = "Italy", + drivers = [dev, tsu] + ) + alpine = TeamFactory.createTeamRenaultEngine( + name = "Alpine", + country = "France", + drivers = [gas, oco] + ) + aston_martin = TeamFactory.createTeamMercedesEngine( + name = "Aston Martin", + country = "United Kingdom", + drivers = [alo, stroll] + ) + ferrari = TeamFactory.createTeamFerrariEngine( + name = "Ferrari", # this is my second favorite team. They are terrible at strategy and there are multiple memes about how bad their strategy is + country = "Italy", + drivers = [lec, sai] + ) + haas = TeamFactory.createTeamFerrariEngine( + name = "Haas", + country = "United States", + drivers = [hul, mag] + ) + mclaren = TeamFactory.createTeamMercedesEngine( + name = "McLaren", + country = "United Kingdom", + drivers = [nor, pia] + ) + mercedes = TeamFactory.createTeamMercedesEngine( + name = "Mercedes", # this is my favorite team + country = "Germany", + drivers = [ham, rus] + ) + red_bull = TeamFactory.createTeamHondaRBPTEngine( + name = "Red Bull", # you're not going to believe this, but Red Bull is actually a better team right now than Ferrari + country = "Austria", + drivers = [per, ver] + ) + williams = TeamFactory.createTeamMercedesEngine( + name = "Williams", + country = "United Kingdom", + drivers = [alb, sar] + ) + + # add teams to championship + + formula_one_2023.addTeamToChampionship(team = alfa_romeo) + formula_one_2023.addTeamToChampionship(team = alphatauri) + formula_one_2023.addTeamToChampionship(team = alpine) + formula_one_2023.addTeamToChampionship(team = aston_martin) + formula_one_2023.addTeamToChampionship(team = ferrari) + formula_one_2023.addTeamToChampionship(team = haas) + formula_one_2023.addTeamToChampionship(team = mclaren) + formula_one_2023.addTeamToChampionship(team = mercedes) + formula_one_2023.addTeamToChampionship(team = red_bull) + formula_one_2023.addTeamToChampionship(team = williams) + + # add races and race results and print info + + # bahrain grand prix + + bahrain_gp = Race( + name = "Bahrain Grand Prix", + country = "Bahrain", + city = "Sakhir", + circuit = "Bahrain International Circuit" + ) + print(bahrain_gp.__str__()) + rr = RaceResults( + race = bahrain_gp, + rankings = [ + ver, per, alo, sai, ham, stroll, rus, bot, gas, alb, tsu, sar, mag, dev, hul, zho, nor, oco, lec, pia + ], + fastestLap = zho + ) + formula_one_2023.holdRace(rr) + print(rr.getPointsForDriver(driver = ver)) + + # saudi arabian grand prix + + saudi_gp = Race( + name = "Saudi Arabian Grand Prix", + country = "Saudi Arabia", + city = "Jeddah", + circuit = "Jeddah Corniche Circuit" + ) + print(saudi_gp.__str__()) + rr = RaceResults( + race = saudi_gp, + rankings = [ + per, ver, alo, rus, ham, sai, lec, oco, gas, mag, tsu, hul, zho, dev, pia, sar, nor, bot, alb, stroll + ], + fastestLap = ver + ) + formula_one_2023.holdRace(rr) + + # australian grand prix + + australian_gp = Race( + name = "Australian Grand Prix", + country = "Australia", + city = "Melbourne", + circuit = "Albert Park Circuit" + ) + print(australian_gp.__str__()) + rr = RaceResults( + race = australian_gp, + rankings = [ver, ham, alo, stroll, per, nor, hul, pia, zho, tsu, bot, sai, gas, oco, dev, sar, mag, rus, alb, lec], + fastestLap = per + ) + formula_one_2023.holdRace(rr) + print(rr.getPointsForDriver(driver = ver)) + + # azerbaijan sprint race + + # manually update standings with azerbaijan sprint race results + + formula_one_2023.driver_standings[per] += 8 + formula_one_2023.driver_standings[lec] += 7 + formula_one_2023.driver_standings[ver] += 6 + formula_one_2023.driver_standings[rus] += 5 + formula_one_2023.driver_standings[sai] += 4 + formula_one_2023.driver_standings[alo] += 3 + formula_one_2023.driver_standings[ham] += 2 + formula_one_2023.driver_standings[stroll] += 1 + + formula_one_2023.team_standings[aston_martin] += 4 + formula_one_2023.team_standings[ferrari] += 11 + formula_one_2023.team_standings[mercedes] += 7 + formula_one_2023.team_standings[red_bull] += 14 + + # azerbaijan grand prix + + azerbaijan_gp = Race( + name = "Azerbaijan Grand Prix", + country = "Azerbaijan", + city = "Baku", + circuit = "Baku City Circuit" + ) + print(azerbaijan_gp.__str__()) + rr = RaceResults( + race = azerbaijan_gp, + rankings = [per, ver, lec, alo, sai, ham, stroll, rus, nor, tsu, pia, alb, mag, gas, oco, sar, hul, bot, zho, dev], + fastestLap = rus + ) + formula_one_2023.holdRace(rr) + print(rr.getPointsForDriver(driver = ver)) + + # miami grand prix + + miami_gp = Race( + name = "Miami Grand Prix", + country = "United States", + city = "Miami", + circuit = "Miami International Autodrome" + ) + print(miami_gp.__str__()) + rr = RaceResults( + race = miami_gp, + rankings = [ver, per, alo, rus, sai, ham, lec, gas, oco, mag, tsu, stroll, bot, alb, hul, zho, nor, dev, pia, sar], + fastestLap = ver + ) + formula_one_2023.holdRace(rr) + print(rr.getPointsForDriver(driver = ver)) + + # monaco grand prix + + monaco_gp = Race( + name = "Monaco Grand Prix", + country = "Monaco", + city = "Monaco", + circuit = "Circuit de Monaco" + ) + print(monaco_gp.__str__()) + rr = RaceResults( + race = monaco_gp, + rankings = [ver, alo, oco, ham, rus, lec, gas, sai, nor, pia, bot, dev, zho, alb, tsu, per, hul, sar, mag, stroll], + fastestLap = ham + ) + formula_one_2023.holdRace(rr) + print(rr.getPointsForDriver(driver = ver)) + + # spanish grand prix + + spanish_gp = Race( + name = "Spanish Grand Prix", + country = "Spain", + city = "Barcelona", + circuit = "Circuit de Barcelona-Catalunya" + ) + print(spanish_gp.__str__()) + rr = RaceResults( + race = spanish_gp, + rankings = [ver, ham, rus, per, sai, stroll, alo, oco, zho, gas, lec, tsu, pia, dev, hul, alb, nor, mag, bot, sar], + fastestLap = ver + ) + formula_one_2023.holdRace(rr) + print(rr.getPointsForDriver(driver = ver)) + + # future races for the 2023 season + + canadian_gp = Race( + name = "Canadian Grand Prix", + country = "Canada", + city = "Montreal", + circuit = "Circuit Gilles Villeneuve" + ) + + austrian_gp = Race( + name = "Austrian Grand Prix", + country = "Austria", + city = "Spielberg", + circuit = "Red Bull Ring" + ) + + # TODO add the rest of the future races for 2023 (stretch goal) + + # print current standings to the console + + print("\nTeam Standings") + for x in formula_one_2023.getTeamStandings(): + print(x) + + print("\nDriver Standings") + for x in formula_one_2023.getDriverStandings(): + print(x) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c6ed6ca --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest +typing \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/championship/__init__.py b/src/championship/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/championship/championship.py b/src/championship/championship.py new file mode 100644 index 0000000..6ad67de --- /dev/null +++ b/src/championship/championship.py @@ -0,0 +1,150 @@ +from src.driver.driver import Driver +from src.race.race import Race +from src.race.raceResults import RaceResults +from src.series.series import Series +from src.team.team import Team +from typing import List + +class Championship(): + """ + a class to represent a series championship. + associated with a series (e.g. Formula One, IndyCar, Nascar) and a year (e.g. 2022, 2023) + """ + def __init__(self, series: Series, year: int): + if not isinstance(series, Series): + raise TypeError(f"{series} must be of type Series, not {type(series)}") + if not isinstance(year, int): + raise TypeError(f"{year} must be of type int, not {type(year)}") + + self.series = series + self.year = year + + self.race_results = list() # list of RaceResults objects + + self.driver_standings = dict() + self.team_standings = dict() + + def addDriverToChampionship(self, driver: Driver): + """ + adds a driver or a list of drivers to the championship + + params: + driver: Driver + """ + if not isinstance(driver, Driver): + raise TypeError(f"{driver} must be of type Driver, not {type(driver)}") + + if not self.driver_standings.get(driver): + self.driver_standings[driver] = 0 + + def addTeamToChampionship(self, team: Team): + """ + adds a team to the championship + + params: + team: Team + """ + if not isinstance(team, Team): + raise TypeError(f"{team} must be of type Team, not {type(team)}") + + self.team_standings[team] = 0 # add team to team standings, set points to 0 + + for d in team.drivers: # for each of the team's drivers + if not isinstance(d, Driver): + raise TypeError(f"{d} must be of type Driver, not {type(d)}") + + if not self.driver_standings.get(d): # if driver is not already in driver's championship + self.addDriverToChampionship(d) # add to driver's championship + + def removeTeamFromChampionship(self, team: Team): + """ + adds a team or a list of teams to the championship + + params: + team: Team + """ + if not isinstance(team, Team): + raise TypeError(f"{team} must be of type Team, not {type(team)}") + + if self.team_standings.get(team): + self.team_standings.pop(team) + + def getDriverStandings(self) -> List[str]: + ''' + get current driver standings + + returns: + List[str] + ''' + sorted_standings = sorted(self.driver_standings.items(), key=lambda x:x[1]) + sorted_standings.reverse() + + printable = list() + + for i in range(len(sorted_standings)): + printable.append(f"{str(i+1)}: {sorted_standings[i][0].__str__()} ({sorted_standings[i][1]} points)") + + return printable + + def getTeamStandings(self) -> List[str]: + ''' + get current team standings + + returns: + List[str] + ''' + sorted_standings = sorted(self.team_standings.items(), key=lambda x:x[1]) + sorted_standings.reverse() + + printable = list() + + for i in range(len(sorted_standings)): + printable.append(f"{str(i+1)}: {sorted_standings[i][0].name} ({sorted_standings[i][1]} points)") + + return printable + + def holdRace(self, race_results: RaceResults): + ''' + holds a race and updates standings given the results + + params: + race_results: RaceResults + ''' + + # type checking + + if not isinstance(race_results, RaceResults): + raise TypeError(f"{race_results} must be of type RaceResults, not {type(race_results)}") + + if not isinstance(race_results.race, Race): + raise TypeError(f"{race_results.race} must be of type Race, not {type(race_results.race)}") + + if not isinstance(race_results.results, dict): + raise TypeError(f"{race_results.results} must be of type dict, not {type(race_results.results)}") + + # update standings based on the results + + tms = list(self.team_standings.keys()) + + for i in range(len(tms)): + if not isinstance(tms[i], Team): + raise TypeError(f"") + + drs = list(tms[i].drivers) + + for j in range(len(drs)): + if not isinstance(drs[j], Driver): + raise TypeError(f"") + + new_points = race_results.getPointsForDriver(drs[j]) + + self.team_standings[tms[i]] += new_points + self.driver_standings[drs[j]] += new_points + + def __str__(self) -> str: + if not isinstance(self.series, Series): + raise TypeError(f"{self.series} must be of type Series, not {type(self.series)}") + if not isinstance(self.year, int): + raise TypeError(f"{self.year} must be of type int, not {type(self.year)}") + + return f"{self.series} {self.year} Championship" \ No newline at end of file diff --git a/src/driver/__init__.py b/src/driver/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/driver/driver.py b/src/driver/driver.py new file mode 100644 index 0000000..2e00b2c --- /dev/null +++ b/src/driver/driver.py @@ -0,0 +1,52 @@ + + +class Driver(): + """ + a class to represent a driver + """ + def __init__(self, surname: str, givenname: str, number: int, nationality: str, surname_first: bool = False, suffix: str = None): + + # type checking + + if not isinstance(surname, str): + raise TypeError(f"{surname} must be of type str, not {type(surname)}") + if not isinstance(givenname, str): + raise TypeError(f"{givenname} must be of type str, not {type(givenname)}") + if not isinstance(number, int): + raise TypeError(f"{number} must be of type int, not {type(number)}") + if not isinstance(nationality, str): + raise TypeError(f"{nationality} must be of type str, not {type(nationality)}") + if not isinstance(surname_first, bool): + raise TypeError(f"{surname_first} must be of type bool, not {type(surname_first)}") + if not isinstance(suffix, (str, type(None))): + raise TypeError(f"{suffix} must of type str or None, not {type(suffix)}") + + self.surname = surname + self.givenname = givenname + self.number = number + self.nationality = nationality + self.surname_first = surname_first + self.suffix = suffix + + def __str__(self) -> str: + ''' + formats the name of the driver as `LAST First` or `First LAST` depending on driver preference + + returns: + str + ''' + s = str() + + # add driver first and last names according to driver's preference in order + + if self.surname_first: + s += f"{self.surname.upper()} {self.givenname}" + else: + s += f"{self.givenname} {self.surname.upper()}" + + if self.suffix: # add suffix if applicable + s += f" {self.suffix}" + + s += f" #{self.number}" # add driver number + + return s \ No newline at end of file diff --git a/src/engine/__init__.py b/src/engine/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/engine/engine.py b/src/engine/engine.py new file mode 100644 index 0000000..b2fecdf --- /dev/null +++ b/src/engine/engine.py @@ -0,0 +1,62 @@ +from abc import ABC + +class EngineInt(ABC): + """ + an interface for engines + """ + def __str__(self) -> str: + pass + +class Engine(EngineInt): + """ + TODO + """ + def __init__(self, engine: str): + if not isinstance(engine, str): + raise TypeError(f"{engine} must be of type str, not {type(engine)}") + self.engine = engine + + def __str__(self) -> str: + return f"{self.engine} Engine" + +class FerrariEngine(EngineInt): + """ + a class to represent an Engine built by Ferrari. + """ + def __init__(self): + self.engine = "Ferrari" + + def __str__(self) -> str: + return f"{self.engine} Engine" + +class HondaRBPTEngine(EngineInt): + """ + a class to represent an Engine built by Honda Red Bull Power Trains. + """ + def __init__(self): + # I know, the name is far too long. + # I didn't choose it, Red Bull did + self.engine = "Honda Red Bull Power Trains" + +class MercedesEngine(EngineInt): + """ + a class to represent an engine built by Mercedes. + """ + def __init__(self): + self.engine = "Mercedes" + + def __str__(self) -> str: + return f"{self.engine} Engine" + +class RenaultEngine(EngineInt): + ''' + a class to represent an engine built by Renault. + + Fun Fact: Renault was one of the victims of WannaCry! + https://www.nbcnews.com/business/autos/european-car-plants-halted-wannacry-ransomware-attack-n759496 + ''' + def __init__(self): + self.engine = "Renault" + + def __str__(self) -> str: + return f"{self.engine} Engine" \ No newline at end of file diff --git a/src/race/__init__.py b/src/race/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/race/race.py b/src/race/race.py new file mode 100644 index 0000000..22b76fd --- /dev/null +++ b/src/race/race.py @@ -0,0 +1,23 @@ + + +class Race(): + """ + a class to represent a race + """ + def __init__(self, name: str, country: str, city: str, circuit: str): + if not isinstance(name, str): + raise TypeError(f"{name} must be of type str, not {type(name)}") + if not isinstance(country, str): + raise TypeError(f"{country} must be of type str, not {type(country)}") + if not isinstance(city, str): + raise TypeError(f"{city} must be of type str, not {type(city)}") + if not isinstance(circuit, str): + raise TypeError(f"{circuit} must be of type str, not {type(circuit)}") + + self.name = name + self.country = country + self.city = city + self.circuit = circuit + + def __str__(self) -> str: + return f"{self.name} ({self.circuit} in {self.city}, {self.country})" \ No newline at end of file diff --git a/src/race/raceResults.py b/src/race/raceResults.py new file mode 100644 index 0000000..d9e1025 --- /dev/null +++ b/src/race/raceResults.py @@ -0,0 +1,73 @@ +from src.driver.driver import Driver +from src.race.race import Race +from src.team.team import Team +from typing import List + +class RaceResults(): + """ + a class to store results associated with a Race + """ + def __init__(self, race: Race, rankings: List[Driver], fastestLap: Driver): + if not isinstance(race, Race): + raise TypeError(f"{race} must be of type Race, not {type(race)}") + if not isinstance(rankings, List): + raise TypeError(f"{rankings} must be of type List, not {type(rankings)}") + if not isinstance(fastestLap, Driver): + raise TypeError(f"{fastestLap} must be of type Driver, not {type(fastestLap)}") + + self.race = race + self.results = dict() # key = driver: Driver, value = points: int + + # calculate points + + points_system = [None, 25, 18, 15, 12, 10, 8, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + + rankings.insert(0, None) + + for i in range(1,21): + if i >= len(rankings): + break + if not isinstance(rankings[i], Driver): + raise TypeError(f"{rankings[i]} must be of type Driver, not {type(rankings[i])}") + + self.results[rankings[i]] = points_system[i] + + # if the driver who got the fastest lap finished in the points + if self.results[fastestLap] > 0: + # give the driver an extra point for fastest lap + self.results[fastestLap] += 1 + + + def getPointsForDriver(self, driver: Driver) -> int: + """ + get the points scored by a driver for a specific race + + params: + driver: Driver + + returns: + int + """ + if not isinstance(driver, Driver): + raise TypeError(f"{driver} must be of type Driver, not {type(driver)}") + + return self.results[driver] + + def getPointsForTeam(self, team: Team) -> int: + """ + get the points scored by all drivers in a team for a specific race + + params: + team: Team + + returns: + int + """ + if not isinstance(team, Team): + raise TypeError(f"{team} must be of type Team, not {type(team)}") + + points = 0 + for driver in team.drivers: + points += self.getPointsForDriver(driver) + + return points \ No newline at end of file diff --git a/src/series/__init__.py b/src/series/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/series/series.py b/src/series/series.py new file mode 100644 index 0000000..e39e7b4 --- /dev/null +++ b/src/series/series.py @@ -0,0 +1,17 @@ + + +class Series(): + """ + a class to represent a racing series + """ + def __init__(self, name: str): + if not isinstance(name, str): + raise TypeError(f"{name} must be of type str, not {type(name)}") + + self.name = name + + def __str__(self) -> str: + if not isinstance(self.name, str): + raise TypeError(f"{self.name} must be of type str, not {type(self.name)}") + + return self.name \ No newline at end of file diff --git a/src/team/__init__.py b/src/team/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/team/team.py b/src/team/team.py new file mode 100644 index 0000000..e9e3b1d --- /dev/null +++ b/src/team/team.py @@ -0,0 +1,57 @@ +from src.driver.driver import Driver +from src.engine.engine import * +from typing import List + +class Team(): + """ + a class to represent a racing team. + """ + def __init__(self, name: str, engine: EngineInt, country: str, drivers: List[Driver]): + if not isinstance(name, str): + raise TypeError(f"{name} must be of type str, not {type(name)}") + if not isinstance(engine, EngineInt): + raise TypeError(f"{engine} must be of type EngineInt or its subclasses, not {type(engine)}") + if not isinstance(country, str): + raise TypeError(f"{country} must be of type str, not {type(country)}") + if not isinstance(drivers, list): + raise TypeError(f"{drivers} must be of type list, not {type(drivers)}") + + self.name = name + self.engine = engine + self.country = country + self.drivers = list() + + # because the addDriverToTeam() method does type checking internally, + # we don't need to create an extra for loop to check each item in the list of prospective drivers. + # this saves processing time and memory! + for driver in drivers: + self.addDriverToTeam(driver = driver) + + def addDriverToTeam(self, driver: Driver): + """ + adds a driver to the team + + params: + driver: Driver + """ + if not isinstance(driver, Driver): + raise TypeError(f"{driver} must be of type Driver, not {type(driver)}") + + if driver not in self.drivers: + self.drivers.append(driver) + + def removeDriverFromTeam(self, driver: Driver): + """ + removes a driver from the team + + params: + driver: Driver + """ + if not isinstance(driver, Driver): + raise TypeError(f"{driver} must be of type Driver, not {type(driver)}") + + if driver in self.drivers: + self.drivers.remove(driver) + + def getDrivers(self) -> List[Driver]: + return self.drivers \ No newline at end of file diff --git a/src/team/teamFactory.py b/src/team/teamFactory.py new file mode 100644 index 0000000..45d79eb --- /dev/null +++ b/src/team/teamFactory.py @@ -0,0 +1,96 @@ +from src.driver.driver import Driver +from src.engine.engine import * +from src.team.team import Team +from typing import List + +class TeamFactory: + @staticmethod + def createTeam(name: str, engine: Engine | str, country: str, drivers: List[Driver]) -> Team: + """ + create a team with a custom engine + + params: + + name: str + engine: Engine | str + country: str + drivers: List(Driver) + + returns: + Team + """ + + # if the user entered a str instead of an Engine, use the str as the parameter to create an Engine + if isinstance(engine, str): + engine = Engine(engine = engine) + + return Team(name = name, engine = engine, country = country, drivers = drivers) + + @staticmethod + def createTeamFerrariEngine(name: str, country: str, drivers: List[Driver]) -> Team: + """ + create a team with a Ferrari engine + + params: + + name: str + country: str + drivers: List(Driver) + + returns: + Team + """ + + return Team(name = name, engine = FerrariEngine(), country = country, drivers = drivers) + + @staticmethod + def createTeamHondaRBPTEngine(name: str, country: str, drivers: List[Driver]) -> Team: + """ + create a team with a Honda Red Bull Power Trains engine + + params: + + name: str + country: str + drivers: List(Driver) + + returns: + Team + """ + + return Team(name = name, engine = HondaRBPTEngine(), country = country, drivers = drivers) + + @staticmethod + def createTeamMercedesEngine(name: str, country: str, drivers: List[Driver]) -> Team: + """ + create a team with a Mercedes engine + + params: + + name: str + country: str + drivers: List(Driver) + + returns: + Team + """ + + return Team(name = name, engine = MercedesEngine(), country = country, drivers = drivers) + + @staticmethod + def createTeamRenaultEngine(name: str, country: str, drivers: List[Driver]) -> Team: + """ + create a team with a Renault engine + + params: + + name: str + country: str + drivers: List(Driver) + + returns: + Team + """ + + return Team(name = name, engine = RenaultEngine(), country = country, drivers = drivers) + \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy_data.py b/tests/dummy_data.py new file mode 100644 index 0000000..c0c8ec8 --- /dev/null +++ b/tests/dummy_data.py @@ -0,0 +1,57 @@ +from src.championship.championship import Championship +from src.driver.driver import Driver +from src.engine.engine import Engine +from src.race.race import Race +from src.race.raceResults import RaceResults +from src.series.series import Series +from src.team.team import Team + +DUMMY_DRIVER = Driver( + surname = "Doe", + givenname = "John", + number = 0, + nationality = "Internet", + surname_first = False, + suffix = "Jr." +) + +DUMMY_DRIVER_TWO = Driver( + surname = "Tables", + givenname = "Bobby", + number = -1, + nationality = "SQL Land", + surname_first = False, + suffix = None +) + +DUMMY_ENGINE = Engine(engine = "Dummy") + +DUMMY_RACE = Race( + name = "Dummy Race", + country = "Internet", + city = "Internet City", + circuit = "Internet Circuit" +) + +DUMMY_SERIES = Series( + name = "Dummy Series" +) + +DUMMY_CHAMPIONSHIP = Championship( + series = DUMMY_SERIES, + year = 1011 +) + +DUMMY_TEAM = Team( + name = "Dummy Team", + engine = DUMMY_ENGINE, + country = "Internet", + drivers = [] +) + +DUMMY_TEAM_TWO = Team( + name = "Dummy Team Two", + engine = DUMMY_ENGINE, + country = "Internet", + drivers = [] +) \ No newline at end of file diff --git a/tests/test_championship.py b/tests/test_championship.py new file mode 100644 index 0000000..dd72032 --- /dev/null +++ b/tests/test_championship.py @@ -0,0 +1,256 @@ +from copy import deepcopy +import pytest +from src.championship.championship import Championship +from src.driver.driver import Driver +from src.race.race import Race +from src.race.raceResults import RaceResults +from src.team.team import Team +from tests.dummy_data import DUMMY_CHAMPIONSHIP, DUMMY_DRIVER, DUMMY_DRIVER_TWO, DUMMY_RACE, DUMMY_TEAM, DUMMY_TEAM_TWO + +# Fixtures + +@pytest.fixture +def championship_fixture(): + return deepcopy(DUMMY_CHAMPIONSHIP) + +@pytest.fixture +def driver_fixture(): + return deepcopy(DUMMY_DRIVER) + +@pytest.fixture +def driver_fixture_two(): + return deepcopy(DUMMY_DRIVER_TWO) + +@pytest.fixture +def race_fixture(): + return deepcopy(DUMMY_RACE) + +@pytest.fixture +def team_fixture(): + return deepcopy(DUMMY_TEAM) + +@pytest.fixture +def team_fixture_two(): + return deepcopy(DUMMY_TEAM_TWO) + +# Test Cases + +def test___str__(championship_fixture: Championship): + assert isinstance(championship_fixture, Championship) + + s = championship_fixture.__str__() + + assert isinstance(s, str) + assert s == "Dummy Series 1011 Championship" + +# addDriverToChampionship test cases + +def test_addDriverToChampionship(championship_fixture: Championship, driver_fixture: Driver): + assert isinstance(championship_fixture, Championship) + assert isinstance(driver_fixture, Driver) + + assert isinstance(championship_fixture.driver_standings, dict) + assert not bool(championship_fixture.driver_standings) # check if dict is empty + + championship_fixture.addDriverToChampionship(driver = driver_fixture) + + assert len(list(championship_fixture.driver_standings.keys())) == 1 # one key in dict + assert driver_fixture in championship_fixture.driver_standings.keys() # the key is correct + assert championship_fixture.driver_standings[driver_fixture] == 0 # the value for the key is correct + +def test_addDriverToChampionship_alreadyInChampionship(championship_fixture: Championship, driver_fixture: Driver): + assert isinstance(championship_fixture, Championship) + assert isinstance(driver_fixture, Driver) + + assert isinstance(championship_fixture.driver_standings, dict) + assert not bool(championship_fixture.driver_standings) # check if dict is empty + + championship_fixture.addDriverToChampionship(driver = driver_fixture) + + assert len(list(championship_fixture.driver_standings.keys())) == 1 # one key in dict + assert driver_fixture in championship_fixture.driver_standings.keys() # the key is correct + assert championship_fixture.driver_standings[driver_fixture] == 0 # the value for the key is correct + + # testing that there aren't now two different records for a single driver + + championship_fixture.addDriverToChampionship(driver = driver_fixture) + + assert len(list(championship_fixture.driver_standings.keys())) == 1 # one key in dict + assert driver_fixture in championship_fixture.driver_standings.keys() # the key is correct + assert championship_fixture.driver_standings[driver_fixture] == 0 # the value for the key is correct + +# when testing behavior of an object that can hold other objects, +# always test the behavior for when it's empty and not empty + +# addTeamToChampionship test cases + +def test_addTeamToChampionship_noDrivers(championship_fixture: Championship, team_fixture: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(team_fixture, Team) + + assert isinstance(championship_fixture.team_standings, dict) + assert not bool(championship_fixture.team_standings) # check if dict is empty + + championship_fixture.addTeamToChampionship(team = team_fixture) + + assert len(list(championship_fixture.team_standings.keys())) == 1 # one key in dict + assert team_fixture in championship_fixture.team_standings.keys() # the key is correct + assert championship_fixture.team_standings[team_fixture] == 0 # the value for the key is correct + +def test_addTeamToChampionship_hasDrivers(championship_fixture: Championship, driver_fixture: Driver, team_fixture: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(driver_fixture, Driver) + assert isinstance(team_fixture, Team) + + assert isinstance(championship_fixture.driver_standings, dict) + assert not bool(championship_fixture.driver_standings) # check if dict is empty + + assert isinstance(championship_fixture.team_standings, dict) + assert not bool(championship_fixture.team_standings) # check if dict is empty + + team_fixture.addDriverToTeam(driver = driver_fixture) + + championship_fixture.addTeamToChampionship(team = team_fixture) + + assert len(list(championship_fixture.team_standings.keys())) == 1 # one key in dict + assert team_fixture in championship_fixture.team_standings.keys() # the key is correct + assert championship_fixture.team_standings[team_fixture] == 0 # the value for the key is correct + + assert len(list(championship_fixture.driver_standings.keys())) == 1 # one key in dict + assert driver_fixture in championship_fixture.driver_standings.keys() # the key is correct + assert championship_fixture.driver_standings[driver_fixture] == 0 # the value for the key is correct + +def test_addTeamToChampionship_alreadyInChampionship(championship_fixture: Championship, team_fixture: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(team_fixture, Team) + + assert isinstance(championship_fixture.team_standings, dict) + + championship_fixture.addTeamToChampionship(team = team_fixture) + + assert len(list(championship_fixture.team_standings.keys())) == 1 # one key in dict + assert team_fixture in championship_fixture.team_standings.keys() # the key is correct + assert championship_fixture.team_standings[team_fixture] == 0 # the value for the key is correct + + # testing that there aren't now two different records for a single team + + championship_fixture.addTeamToChampionship(team = team_fixture) + + assert len(list(championship_fixture.team_standings.keys())) == 1 # one key in dict + assert team_fixture in championship_fixture.team_standings.keys() # the key is correct + assert championship_fixture.team_standings[team_fixture] == 0 # the value for the key is correct + +# removeTeamFromChampionship test cases + +def test_removeTeamFromChampionship_noDrivers(championship_fixture: Championship, team_fixture: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(team_fixture, Team) + + championship_fixture.addTeamToChampionship(team = team_fixture) + assert championship_fixture.team_standings[team_fixture] == 0 + + championship_fixture.removeTeamFromChampionship(team = team_fixture) + assert not championship_fixture.team_standings[team_fixture] + +def test_removeTeamFromChampionship_hasDrivers(championship_fixture: Championship, driver_fixture: Driver, team_fixture: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(team_fixture, Team) + assert isinstance(driver_fixture, Driver) + + team_fixture.addDriverToTeam(driver = driver_fixture) + assert team_fixture.drivers[0] == driver_fixture + + championship_fixture.addTeamToChampionship(team = team_fixture) + assert championship_fixture.team_standings[team_fixture] == 0 + + championship_fixture.removeTeamFromChampionship(team = team_fixture) + assert not championship_fixture.team_standings[team_fixture] + +def test_removeTeamFromChampionship_notInChampionship(championship_fixture: Championship, team_fixture: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(team_fixture, Team) + + with pytest.raises(KeyError): + championship_fixture.team_standings[team_fixture] + + championship_fixture.removeTeamFromChampionship(team = team_fixture) + + with pytest.raises(KeyError): + championship_fixture.team_standings[team_fixture] + +# getDriverStandings test cases + +def test_getDriverStandings(championship_fixture: Championship, driver_fixture: Driver, driver_fixture_two: Driver): + assert isinstance(championship_fixture, Championship) + assert isinstance(driver_fixture, Driver) + assert isinstance(driver_fixture_two, Driver) + + championship_fixture.addDriverToChampionship(driver = driver_fixture) + championship_fixture.addDriverToChampionship(driver = driver_fixture_two) + + championship_fixture.driver_standings[driver_fixture] = 2 + championship_fixture.driver_standings[driver_fixture_two] = 18 + + d_stand = championship_fixture.getDriverStandings() + assert isinstance(d_stand, list) + assert len(d_stand) == 2 + + assert d_stand[0] == f"1: {driver_fixture_two.__str__()} (18 points)" + assert d_stand[1] == f"2: {driver_fixture.__str__()} (2 points)" + +# getTeamStandings test cases + +def test_getTeamStandings(championship_fixture: Championship, team_fixture: Team, team_fixture_two: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(team_fixture, Team) + assert isinstance(team_fixture_two, Team) + + championship_fixture.addTeamToChampionship(team = team_fixture) + championship_fixture.addTeamToChampionship(team = team_fixture_two) + + championship_fixture.team_standings[team_fixture] = 2 + championship_fixture.team_standings[team_fixture_two] = 18 + + t_stand = championship_fixture.getTeamStandings() + assert isinstance(t_stand, list) + assert len(t_stand) == 2 + + assert t_stand[0] == "1: Dummy Team Two (18 points)" + assert t_stand[1] == "2: Dummy Team (2 points)" + +# holdRace test cases + +def test_holdRace(championship_fixture: Championship, driver_fixture: Driver, driver_fixture_two: Driver, race_fixture: Race, team_fixture: Team, team_fixture_two: Team): + assert isinstance(championship_fixture, Championship) + assert isinstance(driver_fixture, Driver) + assert isinstance(driver_fixture_two, Driver) + assert isinstance(team_fixture, Team) + assert isinstance(team_fixture_two, Team) + + team_fixture.addDriverToTeam(driver = driver_fixture) + championship_fixture.addTeamToChampionship(team = team_fixture) + + team_fixture_two.addDriverToTeam(driver = driver_fixture_two) + championship_fixture.addTeamToChampionship(team = team_fixture_two) + + dummy_race_results = RaceResults( + race = race_fixture, + rankings = [driver_fixture, driver_fixture_two], + fastestLap = driver_fixture + ) + + championship_fixture.holdRace(race_results = dummy_race_results) + + d_stand = championship_fixture.getDriverStandings() + t_stand = championship_fixture.getTeamStandings() + + assert isinstance(d_stand, list) + assert isinstance(t_stand, list) + assert len(d_stand) == 2 + assert len(t_stand) == 2 + + assert d_stand[0] == f"1: {driver_fixture.__str__()} (26 points)" + assert d_stand[1] == f"2: {driver_fixture_two.__str__()} (18 points)" + + assert t_stand[0] == f"1: {team_fixture.name} (26 points)" + assert t_stand[1] == f"2: {team_fixture_two.name} (18 points)" \ No newline at end of file diff --git a/tests/test_driver.py b/tests/test_driver.py new file mode 100644 index 0000000..0a8025b --- /dev/null +++ b/tests/test_driver.py @@ -0,0 +1,29 @@ +from copy import deepcopy +import pytest +from src.driver.driver import Driver +from tests.dummy_data import DUMMY_DRIVER + +@pytest.fixture +def driver_fixture(): + return deepcopy(DUMMY_DRIVER) + +def test___str___(driver_fixture: Driver): + + assert isinstance(driver_fixture, Driver) + + s = driver_fixture.__str__() + assert isinstance(s, str) + + assert s == "John DOE Jr. #0" + +def test___str___surname_first(driver_fixture: Driver): + + assert isinstance(driver_fixture, Driver) + + driver_fixture.surname_first = True + assert isinstance(driver_fixture, Driver) + + s = driver_fixture.__str__() + assert isinstance(s, str) + + assert s == "DOE John Jr. #0" \ No newline at end of file diff --git a/tests/test_engine.py b/tests/test_engine.py new file mode 100644 index 0000000..3052264 --- /dev/null +++ b/tests/test_engine.py @@ -0,0 +1,20 @@ +from copy import deepcopy +import pytest +from src.engine.engine import Engine +from tests.dummy_data import DUMMY_ENGINE + +# Fixtures + +@pytest.fixture +def engine_fixture(): + return deepcopy(DUMMY_ENGINE) + +# Test Cases + +def test___str__(engine_fixture: Engine): + assert isinstance(engine_fixture, Engine) + + s = engine_fixture.__str__() + + assert isinstance(s, str) + assert s == "Dummy Engine" \ No newline at end of file diff --git a/tests/test_race.py b/tests/test_race.py new file mode 100644 index 0000000..4b774fc --- /dev/null +++ b/tests/test_race.py @@ -0,0 +1,20 @@ +from copy import deepcopy +import pytest +from src.race.race import Race +from tests.dummy_data import DUMMY_RACE + +# Fixtures + +@pytest.fixture +def race_fixture(): + return deepcopy(DUMMY_RACE) + +# Test Cases + +def test___str__(race_fixture: Race): + assert isinstance(race_fixture, Race) + + s = race_fixture.__str__() + + assert isinstance(s, str) + assert s == f"Dummy Race (Internet Circuit in Internet City, Internet)" \ No newline at end of file diff --git a/tests/test_series.py b/tests/test_series.py new file mode 100644 index 0000000..f96dc42 --- /dev/null +++ b/tests/test_series.py @@ -0,0 +1,17 @@ +from copy import deepcopy +import pytest +from src.series.series import Series +from tests.dummy_data import DUMMY_SERIES +from typing import Any + +@pytest.fixture +def series_fixture(): + return deepcopy(DUMMY_SERIES) + +def test___str__(series_fixture: Series): + assert isinstance(series_fixture, Series) + + s = series_fixture.__str__() + + assert isinstance(s, str) + assert s == "Dummy Series" \ No newline at end of file diff --git a/tests/test_team.py b/tests/test_team.py new file mode 100644 index 0000000..058153d --- /dev/null +++ b/tests/test_team.py @@ -0,0 +1,68 @@ +from copy import deepcopy +import pytest +from src.driver.driver import Driver +from src.team.team import Team +from tests.dummy_data import DUMMY_DRIVER, DUMMY_DRIVER_TWO, DUMMY_TEAM + +# Fixtures + +@pytest.fixture +def driver_fixture(): + return deepcopy(DUMMY_DRIVER) + +@pytest.fixture +def driver_fixture_two(): + return deepcopy(DUMMY_DRIVER_TWO) + +@pytest.fixture +def team_fixture(): + return deepcopy(DUMMY_TEAM) + +# Test Cases + +def test_addDriverToTeam(team_fixture: Team, driver_fixture: Driver): + assert isinstance(team_fixture, Team) + assert isinstance(driver_fixture, Driver) + + assert len(team_fixture.drivers) == 0 + team_fixture.addDriverToTeam(driver_fixture) + + assert len(team_fixture.drivers) == 1 + assert team_fixture.drivers[0] == driver_fixture + + team_fixture.addDriverToTeam(driver_fixture) + assert len(team_fixture.drivers) == 1 + +def test_removeDriverFromTeam(team_fixture: Team, driver_fixture: Driver, driver_fixture_two: Driver): + team_fixture = team_fixture + + assert isinstance(driver_fixture, Driver) + assert isinstance(driver_fixture_two, Driver) + assert isinstance(team_fixture, Team) + + assert len(team_fixture.drivers) == 0 + team_fixture.addDriverToTeam(driver_fixture) + + assert len(team_fixture.drivers) == 1 + assert team_fixture.drivers[0] == driver_fixture + + team_fixture.removeDriverFromTeam(driver_fixture_two) + assert len(team_fixture.drivers) == 1 + + team_fixture.removeDriverFromTeam(driver_fixture) + assert len(team_fixture.drivers) == 0 + +def test_getDrivers(team_fixture: Team, driver_fixture: Driver): + assert isinstance(team_fixture, Team) + + assert len(team_fixture.getDrivers()) == 0 + + team_fixture.addDriverToTeam(driver = driver_fixture) + + drivers = team_fixture.getDrivers() + + assert isinstance(drivers, list) + assert len(drivers) == 1 + + assert isinstance(drivers[0], Driver) + assert drivers[0] == driver_fixture \ No newline at end of file diff --git a/tests/test_teamFactory.py b/tests/test_teamFactory.py new file mode 100644 index 0000000..0f00049 --- /dev/null +++ b/tests/test_teamFactory.py @@ -0,0 +1,116 @@ +from copy import deepcopy +import pytest +from src.engine.engine import * +from src.team.team import Team +from src.team.teamFactory import * +from tests.dummy_data import DUMMY_DRIVER, DUMMY_ENGINE, DUMMY_TEAM +from typing import Any + +# Fixtures + +@pytest.fixture +def driver_fixture(): + return deepcopy(DUMMY_DRIVER) + +@pytest.fixture +def engine_fixture(): + return deepcopy(DUMMY_ENGINE) + +# Helper Method + +def verify_teams(expected: Team, actual: Any): + assert type(expected) == type(actual) == Team + + assert expected.name == actual.name + + assert type(expected.engine) == type(actual.engine) and issubclass(type(expected.engine), EngineInt) + assert expected.engine == actual.engine + + assert expected.country == actual.country + + assert type(expected.drivers) == type(actual.drivers) == list + assert len(expected.drivers) == len(actual.drivers) + for i in range(len(expected.drivers)): + assert expected.drivers[i] == actual.drivers[i] + +# Test Cases + +def test_createTeam(engine_fixture: Engine): + assert isinstance(engine_fixture, Engine) + + t = TeamFactory.createTeam( + name = "Foo", + engine = engine_fixture, + country = "Foo", + drivers = [DUMMY_DRIVER] + ) + + assert isinstance(t, Team) + + verify_teams( + expected = Team(name = "Foo", engine = engine_fixture, country = "Foo", drivers = [DUMMY_DRIVER]), actual = t + ) + +def test_createTeamFerrariEngine(): + ferrari = FerrariEngine() + + t = TeamFactory.createTeam( + name = "Foo", + engine = ferrari, + country = "Foo", + drivers = [DUMMY_DRIVER] + ) + + assert isinstance(t, Team) + + verify_teams( + expected = Team(name = "Foo", engine = ferrari, country = "Foo", drivers = [DUMMY_DRIVER]), actual = t + ) + +def test_createTeamHondaRBPTEngine(): + hondarbpt = HondaRBPTEngine() + + t = TeamFactory.createTeam( + name = "Foo", + engine = hondarbpt, + country = "Foo", + drivers = [DUMMY_DRIVER] + ) + + assert isinstance(t, Team) + + verify_teams( + expected = Team(name = "Foo", engine = hondarbpt, country = "Foo", drivers = [DUMMY_DRIVER]), actual = t + ) + +def test_createTeamMercedesEngine(): + mercedes = MercedesEngine() + + t = TeamFactory.createTeam( + name = "Foo", + engine = mercedes, + country = "Foo", + drivers = [DUMMY_DRIVER] + ) + + assert isinstance(t, Team) + + verify_teams( + expected = Team(name = "Foo", engine = mercedes, country = "Foo", drivers = [DUMMY_DRIVER]), actual = t + ) + +def test_createTeamRenaultEngine(): + renault = RenaultEngine() + + t = TeamFactory.createTeam( + name = "Foo", + engine = renault, + country = "Foo", + drivers = [DUMMY_DRIVER] + ) + + assert isinstance(t, Team) + + verify_teams( + expected = Team(name = "Foo", engine = renault, country = "Foo", drivers = [DUMMY_DRIVER]), actual = t + ) \ No newline at end of file