From 610d91b92e850e254674012cfa2723471f39a36d Mon Sep 17 00:00:00 2001 From: Domhnall Morrissey Date: Sat, 4 Jan 2025 18:35:46 +0000 Subject: [PATCH] V0.14.0 --- src/pw_controller/race_controller.py | 6 +-- .../race_weekend/race_weekend_window.py | 2 +- src/pw_view/race_weekend/results_window.py | 24 ++++++---- src/pw_view/staff_page/staff_page.py | 6 ++- src/pw_view/standings_page.py | 6 +-- .../commentary.py | 0 .../grand_prix_model.py | 37 +++++--------- .../particpant_model.py | 2 +- .../practice_model.py | 0 .../qualy_model.py | 6 +-- .../race_model_enums.py | 6 ++- .../race_weekend_model.py} | 14 +++--- .../session_model.py | 6 +-- src/race_weekend_model/starting_grid.py | 48 +++++++++++++++++++ .../timed_session_model.py | 16 +++---- src/tests/create_model.py | 4 +- src/tests/test_model/car/test_car_model.py | 4 +- src/tests/test_race_model/test_grid_order.py | 32 +++++++++++++ .../test_race_model/test_pit_strategies.py | 20 +++++--- src/tests/test_race_model/test_race_model.py | 16 ++++--- .../race_weekend/test_results_page.py | 9 +++- 21 files changed, 184 insertions(+), 80 deletions(-) rename src/{race_model => race_weekend_model}/commentary.py (100%) rename src/{race_model => race_weekend_model}/grand_prix_model.py (90%) rename src/{race_model => race_weekend_model}/particpant_model.py (99%) rename src/{race_model => race_weekend_model}/practice_model.py (100%) rename src/{race_model => race_weekend_model}/qualy_model.py (71%) rename src/{race_model => race_weekend_model}/race_model_enums.py (73%) rename src/{race_model/race_model.py => race_weekend_model/race_weekend_model.py} (85%) rename src/{race_model => race_weekend_model}/session_model.py (96%) create mode 100644 src/race_weekend_model/starting_grid.py rename src/{race_model => race_weekend_model}/timed_session_model.py (89%) create mode 100644 src/tests/test_race_model/test_grid_order.py diff --git a/src/pw_controller/race_controller.py b/src/pw_controller/race_controller.py index 4ca463e..9ca9e0e 100644 --- a/src/pw_controller/race_controller.py +++ b/src/pw_controller/race_controller.py @@ -3,8 +3,8 @@ import threading from typing import TYPE_CHECKING -from race_model import race_model -from race_model.race_model_enums import SessionNames +from race_weekend_model import race_weekend_model +from race_weekend_model.race_model_enums import SessionNames if TYPE_CHECKING: from pw_controller.pw_controller import Controller @@ -15,7 +15,7 @@ def __init__(self, controller: Controller): self.view = controller.view if self.controller.model.season.current_track_model is not None: # None indicates the season is over, no more races this season - self.race_model = race_model.RaceModel("UI", self.controller.model, self.controller.model.season.current_track_model) + self.race_model = race_weekend_model.RaceWeekendModel("UI", self.controller.model, self.controller.model.season.current_track_model) def simulate_session(self, session: SessionNames) -> None: diff --git a/src/pw_view/race_weekend/race_weekend_window.py b/src/pw_view/race_weekend/race_weekend_window.py index 66cd198..444a74e 100644 --- a/src/pw_view/race_weekend/race_weekend_window.py +++ b/src/pw_view/race_weekend/race_weekend_window.py @@ -5,7 +5,7 @@ import flet as ft from pw_view.custom_widgets import custom_container, custom_buttons -from race_model.race_model_enums import SessionNames +from race_weekend_model.race_model_enums import SessionNames if TYPE_CHECKING: from pw_view.view import View diff --git a/src/pw_view/race_weekend/results_window.py b/src/pw_view/race_weekend/results_window.py index 44ed06a..786ffde 100644 --- a/src/pw_view/race_weekend/results_window.py +++ b/src/pw_view/race_weekend/results_window.py @@ -7,7 +7,7 @@ import pandas as pd from flet.matplotlib_chart import MatplotlibChart -from race_model.race_model_enums import SessionNames +from race_weekend_model.race_model_enums import SessionNames from pw_view import view from pw_view.custom_widgets import custom_container, custom_buttons @@ -90,7 +90,7 @@ def update_page(self, data: dict) -> None: self.update_buttons_row(timed_session) self.setup_classification_table(standings_df, current_session) - self.classification_list_view = ft.ListView(expand=True, spacing=10, padding=20, auto_scroll=True) + self.classification_list_view = ft.ListView(expand=True, spacing=10, padding=20, auto_scroll=False) self.classification_list_view.controls.append(self.classification_container) self.content_column = ft.Column( @@ -104,7 +104,7 @@ def update_page(self, data: dict) -> None: self.view.results_background_image, self.content_column, ], - expand=False, + expand=True, ) contents = [ @@ -150,7 +150,8 @@ def setup_classification_table(self, standings_df: pd.DataFrame, current_session columns = [] for col in standings_df.columns: - columns.append(ft.DataColumn(ft.Text(col))) + column_content = custom_container.HeaderContainer(self.view, col) + columns.append(ft.DataColumn(column_content)) data = standings_df.values.tolist() rows = [] @@ -162,12 +163,16 @@ def setup_classification_table(self, standings_df: pd.DataFrame, current_session rows.append(ft.DataRow(cells=cells)) - self.results_table = ft.DataTable(columns=columns, rows=rows, data_row_max_height=30, data_row_min_height=30) + self.results_table = ft.DataTable(columns=columns, rows=rows, data_row_max_height=30, data_row_min_height=30, heading_row_color=ft.Colors.PRIMARY) self.classification_container = custom_container.CustomContainer(self.view, self.results_table, expand=False) def setup_pitstops_table(self, pit_stop_summary: dict) -> None: - columns = [ft.DataColumn(ft.Text("Driver")), ft.DataColumn(ft.Text("Stops")), ft.DataColumn(ft.Text("Laps"))] + columns = [] + for col in ["Driver", "Stops", "Laps"]: + column_content = custom_container.HeaderContainer(self.view, col) + columns.append(ft.DataColumn(column_content)) + rows = [] for driver in pit_stop_summary.keys(): @@ -181,9 +186,12 @@ def setup_pitstops_table(self, pit_stop_summary: dict) -> None: rows.append(ft.DataRow(cells=cells)) - self.pitstops_table = ft.DataTable(columns=columns, rows=rows, data_row_max_height=30, data_row_min_height=30) + self.pitstops_table = ft.DataTable(columns=columns, rows=rows, data_row_max_height=30, data_row_min_height=30, heading_row_color=ft.Colors.PRIMARY) self.pitstops_container = custom_container.CustomContainer(self.view, self.pitstops_table, expand=False) + + self.pitstops_list_view = ft.ListView(expand=True, spacing=10, padding=20, auto_scroll=False) + self.pitstops_list_view.controls.append(self.pitstops_container) def setup_lap_chart(self) -> None: px = 1/plt.rcParams['figure.dpi'] # pixel in inches @@ -267,7 +275,7 @@ def display_pitstops(self, e: ft.ControlEvent) -> None: self.reset_tab_buttons() self.pitstops_btn.style = self.view.clicked_button_style - self.content_column.controls=[self.buttons_container, self.pitstops_container, self.continue_container] + self.content_column.controls=[self.buttons_container, self.pitstops_list_view, self.continue_container] self.view.main_app.update() def display_lap_chart(self, e: ft.ControlEvent) -> None: diff --git a/src/pw_view/staff_page/staff_page.py b/src/pw_view/staff_page/staff_page.py index fdfb58c..49bf246 100644 --- a/src/pw_view/staff_page/staff_page.py +++ b/src/pw_view/staff_page/staff_page.py @@ -343,7 +343,11 @@ def setup_staff_value_progress_bars(self, data: dict) -> ft.Container: row = ft.Row( controls=[ ft.Text(f"{team_name} ({staff_value}):", width=100), - ft.ProgressBar(value=staff_value/max_staff, width=500, expand=True, bar_height=28) + ft.Container( + content=ft.ProgressBar(value=staff_value/max_staff, width=500, expand=True, bar_height=28), + height=28, + expand=True + ) ], expand=True, ) diff --git a/src/pw_view/standings_page.py b/src/pw_view/standings_page.py index 2105bd1..b2e16f5 100644 --- a/src/pw_view/standings_page.py +++ b/src/pw_view/standings_page.py @@ -91,7 +91,7 @@ def update_standings(self, drivers_standings_df: pd.DataFrame, constructors_stan self.drivers_table = ft.DataTable(columns=columns, rows=rows, data_row_max_height=30, data_row_min_height=30, heading_row_color=ft.Colors.PRIMARY) - self.scrollable_drivers_table = ft.ListView(expand=1, auto_scroll=True) + self.scrollable_drivers_table = ft.ListView(expand=True, auto_scroll=False) self.scrollable_drivers_table.controls.append(custom_container.CustomContainer(self.view, self.drivers_table, expand=False)) # CONSTRUCTORS @@ -142,13 +142,13 @@ def arrange_controls(self, mode: str) -> None: assert mode in ["drivers", "constructors"] if mode == "drivers": - container = custom_container.CustomContainer(self.view, self.scrollable_drivers_table, expand=False) + container = custom_container.CustomContainer(self.view, self.scrollable_drivers_table, expand=True) elif mode == "constructors": container = custom_container.CustomContainer(self.view, self.scrollable_constructors_table, expand=False) column = ft.Column( controls=[self.buttons_container, container], - expand=False, + expand=True, spacing=20 ) diff --git a/src/race_model/commentary.py b/src/race_weekend_model/commentary.py similarity index 100% rename from src/race_model/commentary.py rename to src/race_weekend_model/commentary.py diff --git a/src/race_model/grand_prix_model.py b/src/race_weekend_model/grand_prix_model.py similarity index 90% rename from src/race_model/grand_prix_model.py rename to src/race_weekend_model/grand_prix_model.py index a24e834..331c51d 100644 --- a/src/race_model/grand_prix_model.py +++ b/src/race_weekend_model/grand_prix_model.py @@ -1,11 +1,12 @@ import random from typing import Tuple -from race_model import session_model, commentary -from race_model.race_model_enums import SessionNames, SessionStatus +from race_weekend_model import session_model, commentary +from race_weekend_model.race_model_enums import SessionNames, SessionStatus, SessionMode from pw_model.pw_base_model import Model -from race_model.particpant_model import ParticpantModel +from race_weekend_model.particpant_model import ParticpantModel +from race_weekend_model.session_model import SessionModel class GrandPrixModel(session_model.SessionModel): def __init__(self, model: Model): @@ -24,22 +25,8 @@ def leader(self) -> str: return str(self.standings_df.iloc[0]["Driver"]) def setup_grid_order(self) -> None: - qualy_results = self.race_model.results[SessionNames.QUALIFYING.value]["results"] - grid_order = qualy_results["Driver"] + self.standings_df = self.race_model.starting_grid.apply_grid_order_to_standings(self.standings_df) - self.standings_df.set_index('Driver', inplace=True, drop=False) - self.standings_df = self.standings_df.loc[grid_order] - self.refresh_standings_column() - - for idx, row in self.standings_df.iterrows(): - driver = row["Driver"] - participant = self.race_model.get_particpant_model_by_name(driver) - - # update position in participant class - participant.starting_position = idx + 1 - # update Grid column in dataframe - self.standings_df.loc[self.standings_df["Driver"] == driver, "Grid"] = idx + 1 - def setup_participant_start_fuel_and_tyres(self) -> None: for p in self.race_model.participants: p.setup_start_fuel_and_tyres() @@ -54,7 +41,7 @@ def setup_participant_start_fuel_and_tyres(self) -> None: def advance(self, mode: str) -> None: self.mode = mode if self.status == SessionStatus.PRE_SESSION: - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_race_start_message()) self.calculate_start() self.status = SessionStatus.RUNNING @@ -68,7 +55,7 @@ def advance(self, mode: str) -> None: self.current_lap += 1 if self.current_lap > self.race_model.track_model.number_of_laps or self.current_lap == 999: - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_race_over_message(self.leader)) self.status = SessionStatus.POST_SESSION self.post_race_actions() @@ -118,7 +105,7 @@ def calculate_run_to_turn1(self) -> list[Tuple[float, ParticpantModel]]: [[12.761, ], [13.124, ], [13.68, ],] ''' - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_lead_after_turn1_message(order_after_turn1[0][1].name)) return order_after_turn1 @@ -188,7 +175,7 @@ def calculate_lap(self) -> None: # IF RETIRED THIS LAP if participant.status == "retired": - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_retirement_message(participant.name)) self.retirements.append(participant.name) # self.log_event(f"{participant.name} retires") @@ -196,7 +183,7 @@ def calculate_lap(self) -> None: else: if participant.status == "pitting in": - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_entering_pit_lane_message(participant.name)) # print(laptime_ahead) @@ -206,12 +193,12 @@ def calculate_lap(self) -> None: if gap_ahead + delta <= 500 and participant_ahead.status not in ["pitting in", "retired"]: # if car ahead is about to pit, don't handle for overtaking # self.log_event(f"{driver} Attacking {participant_ahead.name}") - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_attacking_message(driver, participant_ahead.name)) if random.randint(0, 100) < 25: # overtake successfull # self.log_event(f"{participant.name} passes {participant_ahead.name}") - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_overtake_message(participant.name, participant_ahead.name)) # add some random time to overtaking car, held up when passing diff --git a/src/race_model/particpant_model.py b/src/race_weekend_model/particpant_model.py similarity index 99% rename from src/race_model/particpant_model.py rename to src/race_weekend_model/particpant_model.py index 3894712..4a3d6e9 100644 --- a/src/race_model/particpant_model.py +++ b/src/race_weekend_model/particpant_model.py @@ -45,7 +45,7 @@ def setup_variables_for_session(self) -> None: self.positions_by_lap: list[int] = [] # not zero indexed self.tyre_wear_by_lap: list[int] = [] # not zero indexed self.number_of_pitstops = 0 - self.starting_position = None # not zero indexed + self.starting_position = None # not zero indexed, set in StartingGrid class self.status = "in_pit" self.attacking = False diff --git a/src/race_model/practice_model.py b/src/race_weekend_model/practice_model.py similarity index 100% rename from src/race_model/practice_model.py rename to src/race_weekend_model/practice_model.py diff --git a/src/race_model/qualy_model.py b/src/race_weekend_model/qualy_model.py similarity index 71% rename from src/race_model/qualy_model.py rename to src/race_weekend_model/qualy_model.py index 8269766..01de320 100644 --- a/src/race_model/qualy_model.py +++ b/src/race_weekend_model/qualy_model.py @@ -1,13 +1,13 @@ from __future__ import annotations from typing import TYPE_CHECKING -from race_model import timed_session_model +from race_weekend_model import timed_session_model if TYPE_CHECKING: - from race_model.race_model import RaceModel + from race_weekend_model.race_weekend_model import RaceWeekendModel class QualyModel(timed_session_model.TimedSessionModel): - def __init__(self, model: RaceModel, session_time: int): + def __init__(self, model: RaceWeekendModel, session_time: int): super().__init__(model, session_time) self.generate_practice_runs() diff --git a/src/race_model/race_model_enums.py b/src/race_weekend_model/race_model_enums.py similarity index 73% rename from src/race_model/race_model_enums.py rename to src/race_weekend_model/race_model_enums.py index 5dc8fdd..4766df2 100644 --- a/src/race_model/race_model_enums.py +++ b/src/race_weekend_model/race_model_enums.py @@ -9,4 +9,8 @@ class SessionNames(Enum): class SessionStatus(Enum): PRE_SESSION = "Pre Session" RUNNING = "Green" - POST_SESSION = "Post Session" \ No newline at end of file + POST_SESSION = "Post Session" + +class SessionMode(Enum): + SIMULATE = "simulate" + \ No newline at end of file diff --git a/src/race_model/race_model.py b/src/race_weekend_model/race_weekend_model.py similarity index 85% rename from src/race_model/race_model.py rename to src/race_weekend_model/race_weekend_model.py index 4a04586..f35f349 100644 --- a/src/race_model/race_model.py +++ b/src/race_weekend_model/race_weekend_model.py @@ -12,11 +12,12 @@ from pw_model import pw_base_model from pw_model.track import track_model -from race_model import qualy_model, grand_prix_model -from race_model import particpant_model -from race_model.race_model_enums import SessionNames, SessionStatus +from race_weekend_model import qualy_model, grand_prix_model +from race_weekend_model import particpant_model +from race_weekend_model.starting_grid import StartingGrid +from race_weekend_model.race_model_enums import SessionNames, SessionStatus, SessionMode -class RaceModel: +class RaceWeekendModel: def __init__(self, mode: str, model: pw_base_model.Model, track_model: track_model.TrackModel): assert mode in ["UI", "headless"], f"Unsupported Mode {mode}" # headless is model only, UI means were using the GUI @@ -49,7 +50,7 @@ def setup_practice(self, session_time: int, session_name: str) -> None: self.setup_session() def setup_qualifying(self, - session_time: None,# in seconds e.g. 60*60 for 1 hr + session_time: int,# in seconds e.g. 60*60 for 1 hr session_type: Enum) -> None: assert session_type == SessionNames.QUALIFYING # session is a variable for future development of Q1, Q2, Q3, for the 1998 1hr qualfy @@ -58,6 +59,7 @@ def setup_qualifying(self, self.setup_session() def setup_race(self) -> None: + self.starting_grid = StartingGrid(self) self.current_session_name = SessionNames.RACE.value self.current_session = grand_prix_model.GrandPrixModel(self) self.setup_session() @@ -72,5 +74,5 @@ def update_player_drivers_strategy(self, driver1_data, driver2_data) -> None: def simulate_session(self) -> None: while self.current_session.status != SessionStatus.POST_SESSION: - self.current_session.advance("simulate") + self.current_session.advance(SessionMode.SIMULATE) diff --git a/src/race_model/session_model.py b/src/race_weekend_model/session_model.py similarity index 96% rename from src/race_model/session_model.py rename to src/race_weekend_model/session_model.py index 4e116da..57b8e74 100644 --- a/src/race_model/session_model.py +++ b/src/race_weekend_model/session_model.py @@ -8,13 +8,13 @@ from typing import Optional, TYPE_CHECKING import pandas as pd -from race_model.race_model_enums import SessionStatus +from race_weekend_model.race_model_enums import SessionStatus if TYPE_CHECKING: - from race_model.race_model import RaceModel + from race_weekend_model.race_weekend_model import RaceWeekendModel class SessionModel: - def __init__(self, race_model: RaceModel): + def __init__(self, race_model: RaceWeekendModel): self.race_model = race_model self.setup_standings() diff --git a/src/race_weekend_model/starting_grid.py b/src/race_weekend_model/starting_grid.py new file mode 100644 index 0000000..6a2d5fa --- /dev/null +++ b/src/race_weekend_model/starting_grid.py @@ -0,0 +1,48 @@ +''' +A specific class to holds the starting grid positions for each driver. +It updates each participant model's starting_position variable +It is also responsible for applying the grid order to the GrandPrixModel's standings dataframe +''' +from __future__ import annotations +from typing import TYPE_CHECKING + +import pandas as pd + +from race_weekend_model.race_model_enums import SessionNames +if TYPE_CHECKING: + from race_weekend_model.race_weekend_model import RaceWeekendModel + +class StartingGrid: + def __init__(self, race_weekend_model: RaceWeekendModel): + self.race_weekend_model = race_weekend_model + + self.setup_grid_order() + self.update_participants() + + def setup_grid_order(self) -> None: + qualy_results = self.race_weekend_model.results[SessionNames.QUALIFYING.value]["results"] + self.grid_order = qualy_results["Driver"] + + def update_participants(self) -> None: + ''' + Update starting position variable in eeach participant + ''' + for idx, driver in enumerate(self.grid_order): + participant = self.race_weekend_model.get_particpant_model_by_name(driver) + + # update position in participant class + participant.starting_position = idx + 1 + + def apply_grid_order_to_standings(self, standings_df: pd.DataFrame) -> pd.DataFrame: + standings_df.set_index('Driver', inplace=True, drop=False) + standings_df = standings_df.loc[self.grid_order] + + standings_df.reset_index(drop=True, inplace=True) + standings_df["Position"] = standings_df.index + 1 + + for idx, row in standings_df.iterrows(): + driver = row["Driver"] + standings_df.loc[standings_df["Driver"] == driver, "Grid"] = idx + 1 + + return standings_df + diff --git a/src/race_model/timed_session_model.py b/src/race_weekend_model/timed_session_model.py similarity index 89% rename from src/race_model/timed_session_model.py rename to src/race_weekend_model/timed_session_model.py index 2b0fd01..8e9bf3e 100644 --- a/src/race_model/timed_session_model.py +++ b/src/race_weekend_model/timed_session_model.py @@ -7,15 +7,15 @@ import copy from typing import TYPE_CHECKING -from race_model import session_model -from race_model import commentary -from race_model.race_model_enums import SessionStatus +from race_weekend_model import session_model +from race_weekend_model import commentary +from race_weekend_model.race_model_enums import SessionStatus, SessionMode if TYPE_CHECKING: - from race_model.race_model import RaceModel + from race_weekend_model.race_weekend_model import RaceWeekendModel class TimedSessionModel(session_model.SessionModel): - def __init__(self, race_model: RaceModel, session_time: int): + def __init__(self, race_model: RaceWeekendModel, session_time: int): super().__init__(race_model) self.session_time = session_time @@ -36,13 +36,13 @@ def setup_session(self) -> None: def advance(self, mode: str) -> None: - assert mode in ["UI", "simulate"] # simulate prevents any commentart messages from being generated + assert mode in ["UI", SessionMode.SIMULATE] # simulate prevents any commentart messages from being generated self.mode = mode if self.status == SessionStatus.PRE_SESSION: self.status = SessionStatus.RUNNING - if mode != "simulate": + if mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_practice_start_message()) # self.update_participants_in_practice() @@ -92,7 +92,7 @@ def find_particpants_leaving_pit_lane(self) -> None: is_leaving = p.check_leaving_pit_lane(self.time_left) if is_leaving is True: - if self.mode != "simulate": + if self.mode != SessionMode.SIMULATE: self.commentary_to_process.append(commentary.gen_leaving_pit_lane_message(p.name)) # Update standings diff --git a/src/tests/create_model.py b/src/tests/create_model.py index c0abf01..70bd3b8 100644 --- a/src/tests/create_model.py +++ b/src/tests/create_model.py @@ -1,6 +1,6 @@ import os from pw_model import pw_base_model -from race_model import race_model +from race_weekend_model import race_weekend_model def create_model(mode="normal", auto_save=True): @@ -12,4 +12,4 @@ def create_model(mode="normal", auto_save=True): return pw_base_model.Model(roster, run_directory, mode=mode, auto_save=auto_save) def create_race_model(model): - return race_model.RaceModel("headless", model, model.tracks[0]) + return race_weekend_model.RaceWeekendModel("headless", model, model.tracks[0]) diff --git a/src/tests/test_model/car/test_car_model.py b/src/tests/test_model/car/test_car_model.py index 0390811..5730f1b 100644 --- a/src/tests/test_model/car/test_car_model.py +++ b/src/tests/test_model/car/test_car_model.py @@ -1,7 +1,7 @@ import pytest from tests import create_model -from race_model import race_model +from race_weekend_model import race_weekend_model from tests.test_model.track import test_track_model def test_update_car_speed(): @@ -32,7 +32,7 @@ def test_update_car_speed(): def test_fuel_consumption(): model = create_model.create_model(mode="headless") track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) schumacher_model = _race_model.get_particpant_model_by_name("Michael Schumacher") diff --git a/src/tests/test_race_model/test_grid_order.py b/src/tests/test_race_model/test_grid_order.py new file mode 100644 index 0000000..c968726 --- /dev/null +++ b/src/tests/test_race_model/test_grid_order.py @@ -0,0 +1,32 @@ +import random + +import pandas as pd + +from tests import create_model +from race_weekend_model import race_weekend_model +from race_weekend_model.race_model_enums import SessionNames +from tests.test_model.track import test_track_model + +def test_grid_order(): + model = create_model.create_model(mode="headless") + + # Make Jorg Muller the 2nd Ferrari driver, will do check to ensure he is in the participants and Irvine is not + ferrari_model = model.get_team_model("Ferrari") + ferrari_model.driver2 = "Jorg Muller" + + track = test_track_model.create_dummy_track() + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) + + # SETUP DUMMY GRID ORDER + grid_order = random.shuffle([p.name for p in _race_model.participants]) + + _race_model.results[SessionNames.QUALIFYING.value]= {} + _race_model.results[SessionNames.QUALIFYING.value]["results"] = pd.DataFrame(columns=["Driver"], data=grid_order) + + _race_model.setup_race() + _race_model.current_session.setup_grid_order() + + for idx, row in _race_model.current_session.standings_df.iterrows(): + assert row["Driver"] == grid_order[idx - 1] + participant_model = _race_model.get_particpant_model_by_name(row["Driver"]) + assert participant_model.starting_position == idx \ No newline at end of file diff --git a/src/tests/test_race_model/test_pit_strategies.py b/src/tests/test_race_model/test_pit_strategies.py index b883fa6..671144d 100644 --- a/src/tests/test_race_model/test_pit_strategies.py +++ b/src/tests/test_race_model/test_pit_strategies.py @@ -1,16 +1,16 @@ import pytest from tests import create_model -from race_model import race_model +from race_weekend_model import race_weekend_model from tests.test_model.track import test_track_model -from race_model.race_model_enums import SessionStatus +from race_weekend_model.race_model_enums import SessionStatus, SessionNames, SessionMode def test_pit_strategy_setup(): # check planned pit stop laps are in expected range (based on a 71 lap race) model = create_model.create_model() track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) schumacher_model = _race_model.get_particpant_model_by_name("Michael Schumacher") @@ -50,7 +50,11 @@ def test_starting_fuel(): model = create_model.create_model() track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) + + # Run qualy to establish a grid order + _race_model.setup_qualifying(60*60, SessionNames.QUALIFYING) + _race_model.simulate_session() schumacher_model = _race_model.get_particpant_model_by_name("Michael Schumacher") schumacher_model.number_of_planned_stops = 1 @@ -68,7 +72,11 @@ def test_starting_fuel(): def test_pitstops(): model = create_model.create_model() track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) + + # Run qualy to establish a grid order + _race_model.setup_qualifying(60*60, SessionNames.QUALIFYING) + _race_model.simulate_session() _race_model.setup_race() @@ -81,7 +89,7 @@ def test_pitstops(): schumacher_model.pit3_lap = 30 while _race_model.current_session.status != SessionStatus.POST_SESSION: - _race_model.current_session.advance(mode="simulate") + _race_model.current_session.advance(mode=SessionMode.SIMULATE) if _race_model.current_session.current_lap in [11, 21, 31]: assert schumacher_model.car_model.tyre_wear == 0 # check tyres were changed diff --git a/src/tests/test_race_model/test_race_model.py b/src/tests/test_race_model/test_race_model.py index 5218b2c..78a2581 100644 --- a/src/tests/test_race_model/test_race_model.py +++ b/src/tests/test_race_model/test_race_model.py @@ -1,6 +1,6 @@ from tests import create_model -from race_model import race_model -from race_model.race_model_enums import SessionNames +from race_weekend_model import race_weekend_model +from race_weekend_model.race_model_enums import SessionNames, SessionMode from pw_model.track import track_model from tests.test_model.track import test_track_model @@ -13,7 +13,7 @@ def test_participants_creation(): ferrari_model.driver2 = "Jorg Muller" track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) assert len(_race_model.participants) == 22 @@ -35,7 +35,7 @@ def test_session_setup(): model = create_model.create_model(mode="headless") track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) _race_model.setup_qualifying(60*60, SessionNames.QUALIFYING) @@ -51,10 +51,14 @@ def test_session_setup(): def test_run_to_turn_1(): model = create_model.create_model(mode="headless") track = test_track_model.create_dummy_track() - _race_model = race_model.RaceModel("headless", model, track) + _race_model = race_weekend_model.RaceWeekendModel("headless", model, track) + # Run qualy to establish a grid order + _race_model.setup_qualifying(60*60, SessionNames.QUALIFYING) + _race_model.simulate_session() + _race_model.setup_race() - _race_model.current_session.mode = "simulate" + _race_model.current_session.mode = SessionMode.SIMULATE order_after_turn1 = _race_model.current_session.calculate_run_to_turn1() assert len(order_after_turn1) == 22 diff --git a/src/tests/test_view/race_weekend/test_results_page.py b/src/tests/test_view/race_weekend/test_results_page.py index b088708..e0a6d4e 100644 --- a/src/tests/test_view/race_weekend/test_results_page.py +++ b/src/tests/test_view/race_weekend/test_results_page.py @@ -1,8 +1,10 @@ import pytest from unittest.mock import Mock import pandas as pd +import matplotlib.pyplot as plt + from pw_view.race_weekend.results_window import ResultsWindow -from race_model.race_model_enums import SessionNames +from race_weekend_model.race_model_enums import SessionNames import flet as ft @pytest.fixture @@ -21,6 +23,11 @@ def mock_view(): def results_window(mock_view): return ResultsWindow(mock_view) +@pytest.fixture(autouse=True) +def cleanup_figures(): + yield + plt.close("all") # Close all figures after each test + def test_initialization(results_window): # Test if the ResultsWindow initializes correctly assert results_window.header_text.value == "Results"