"""
Full FSAE competition with scoring logic.
"""
from typing import Tuple
import numpy as np
import numpy.typing as npt
from ..track import *
from ..vehicle import Car
from .lap import lapsim
from .models import *
from .utils import *
[docs]
class Competition:
def __init__(
self,
mycar: Car,
accel: Track,
skidpad: Track,
autoX: Track,
endurance: Track,
scoring: CompetitionScoring,
**kwargs,
):
self.mycar = mycar
self.accel = accel # accel track
self.skidpad = skidpad # skidpad track
self.autoX = autoX # autoX track
self.endurance = endurance # endurance track
self.scoring = scoring
[docs]
def to_data(self) -> CompetitionData:
"""
Serialize the Competition to a CompetitionData model for Pydantic serialization.
Returns
-------
CompetitionData
"""
return CompetitionData(
vehicle_model=self.mycar.params,
accel=self.accel.to_data(),
skidpad=self.skidpad.to_data(),
autoX=self.autoX.to_data(),
endurance=self.endurance.to_data(),
scoring=self.scoring,
)
[docs]
def accel_event(self, extract_internal_data: bool = False) -> EventResults:
"""
Simulates the acceleration event in the competition.
Parameters
----------
extract_internal_data : bool, optional
Whether to extract internal data during the simulation, by default False.
Returns
-------
EventResults
The results of the acceleration event simulation.
"""
original_drs_status = self.mycar.params.aero.drs.drs_present
self.mycar.params.aero.drs.drs_present = False
lapsim_results = lapsim(
mycar=self.mycar,
track=self.accel,
initial_velocity=0.5,
extract_internal_data=extract_internal_data,
)
tyour = lapsim_results.lap_t[-1]
points = compute_event_points(self.scoring.accel, tyour)
self.mycar.car_reset()
self.mycar.params.aero.drs.drs_present = original_drs_status
return EventResults(
points=points,
tyour=tyour,
lapsim_results=lapsim_results,
)
[docs]
def skidpad_event(self, extract_internal_data: bool = False) -> EventResults:
"""
Simulates the skidpad event in the competition.
Parameters
----------
extract_internal_data : bool, optional
Whether to extract internal data during the simulation, by default False.
Returns
-------
EventResults
The results of the skidpad event simulation.
"""
lapsim_results = lapsim(
mycar=self.mycar,
track=self.skidpad,
multilap=False, # TODO: FIX THIS!
extract_internal_data=extract_internal_data,
)
tyour = lapsim_results.lap_t[-1]
points = compute_event_points(self.scoring.skidpad, tyour)
self.mycar.car_reset()
return EventResults(
points=points,
tyour=tyour,
lapsim_results=lapsim_results,
)
[docs]
def autoX_event(self, extract_internal_data: bool = False) -> EventResults:
"""
Simulates the autocross event in the competition.
Parameters
----------
extract_internal_data : bool, optional
Whether to extract internal data during the simulation, by default False.
Returns
-------
EventResults
The results of the autocross event simulation.
"""
lapsim_results = lapsim(
mycar=self.mycar,
track=self.autoX,
initial_velocity=1.0,
# timer uses transponder at back of car, so you effectively get
# ~1 wheelbase of rollout.
extract_internal_data=extract_internal_data,
)
tyour = lapsim_results.lap_t[-1]
points = compute_event_points(self.scoring.autoX, tyour)
self.mycar.car_reset()
return EventResults(
points=points,
tyour=tyour,
lapsim_results=lapsim_results,
)
[docs]
def endurance_event(
self, extract_internal_data: bool = False, use_coast: bool = True
) -> EventResults:
"""
Simulates the endurance event in the competition.
Parameters
----------
extract_internal_data : bool, optional
Whether to extract internal data during the simulation, by default False.
Returns
-------
EventResults
The results of the endurance event simulation.
"""
lapsim_results = lapsim(
mycar=self.mycar,
track=self.endurance,
multilap=False,
initial_velocity=1.0, # same reason as in autoX
use_coast=use_coast,
extract_internal_data=extract_internal_data,
)
tyour = 22 * lapsim_results.lap_t[-1]
points = compute_event_points(self.scoring.endurance, tyour)
self.mycar.car_reset()
return EventResults(
points=points,
tyour=tyour,
lapsim_results=lapsim_results,
)
[docs]
def efficiency_endurance_event(
self, extract_internal_data: bool = False
) -> Tuple[EventResults, float]:
"""
Simulates the endurance event in the competition, and also calculates efficiency points.
Parameters
----------
extract_internal_data : bool, optional
Whether to extract internal data during the simulation, by default False.
Returns
-------
Tuple[EventResults, float]
The results of the endurance event simulation and efficiency points.
"""
endu_res = self.endurance_event(extract_internal_data=extract_internal_data)
_, _, consumed_energy = energy_data(
endu_res.lapsim_results.lap_t, endu_res.lapsim_results.lap_powers
)
eff_points = compute_efficiency_points(
self.scoring.efficiency,
consumed_energy,
endu_res.tyour,
)
return endu_res, eff_points
[docs]
def run(
self,
extract_internal_data: bool = False,
) -> CompetitionResults:
"""
Runs all competition events and returns their results.
Parameters
----------
extract_internal_data : bool, optional
Whether to extract internal data during the simulation, by default False.
Returns
-------
CompetitionResults
Results from all competition events including efficiency points.
"""
accel_results = self.accel_event(extract_internal_data=extract_internal_data)
skidpad_results = self.skidpad_event(
extract_internal_data=extract_internal_data
)
autoX_results = self.autoX_event(extract_internal_data=extract_internal_data)
endurance_results, efficiency_points = self.efficiency_endurance_event(
extract_internal_data=extract_internal_data
)
return CompetitionResults(
accel=accel_results,
skidpad=skidpad_results,
autoX=autoX_results,
endurance=endurance_results,
efficiency_points=efficiency_points,
)