Add initial (untested) race guess points calculation
This commit is contained in:
@ -1,5 +1,159 @@
|
||||
from typing import Dict, List, overload
|
||||
import numpy as np
|
||||
|
||||
from formula10.domain.domain_model import Model
|
||||
from formula10.domain.model.driver import NONE_DRIVER
|
||||
from formula10.domain.model.race_guess import RaceGuess
|
||||
from formula10.domain.model.race_result import RaceResult
|
||||
|
||||
RACE_GUESS_OFFSET_POINTS: Dict[int, int] = {
|
||||
3: 1,
|
||||
2: 3,
|
||||
1: 6,
|
||||
0: 10
|
||||
}
|
||||
RACE_GUESS_DNF_POINTS: int = 10
|
||||
|
||||
SEASON_GUESS_HOT_TAKE_POINTS: int = 10
|
||||
SEASON_GUESS_P2_POINTS: int = 10
|
||||
SEASON_GUESS_OVERTAKES_POINTS: int = 10
|
||||
SEASON_GUESS_DNF_POINTS: int = 10
|
||||
SEASON_GUESS_GAINED_POINTS: int = 10
|
||||
SEASON_GUESS_LOST_POINTS: int = 10
|
||||
SEASON_GUESS_TEAMWINNER_CORRECT_POINTS: int = 3
|
||||
SEASON_GUESS_TEAMWINNER_FALSE_POINTS: int = -3
|
||||
SEASON_GUESS_PODIUMS_CORRECT_POINTS: int = 3
|
||||
SEASON_GUESS_PODIUMS_FALSE_POINTS: int = -2
|
||||
|
||||
STANDING_2023: Dict[str, int] = {
|
||||
"Max Verstappen": 1,
|
||||
"Sergio Perez": 2,
|
||||
"Lewis Hamilton": 3,
|
||||
"Fernando Alonso": 4,
|
||||
"Charles Leclerc": 5,
|
||||
"Lando Norris": 6,
|
||||
"Carlos Sainz": 7,
|
||||
"George Russel": 8,
|
||||
"Oscar Piastri": 9,
|
||||
"Lance Stroll": 10,
|
||||
"Pierre Gasly": 11,
|
||||
"Esteban Ocon": 12,
|
||||
"Alexander Albon": 13,
|
||||
"Yuki Tsunoda": 14,
|
||||
"Valtteri Bottas": 15,
|
||||
"Nico Hulkenberg": 16,
|
||||
"Daniel Ricciardo": 17,
|
||||
"Zhou Guanyu": 18,
|
||||
"Kevin Magnussen": 19,
|
||||
"Logan Sargeant": 21
|
||||
}
|
||||
|
||||
def standing_points(race_guess: RaceGuess, race_result: RaceResult) -> int:
|
||||
guessed_driver_position: int | None = race_result.driver_standing_position(driver=race_guess.pxx_guess)
|
||||
if guessed_driver_position is None:
|
||||
return 0
|
||||
|
||||
position_offset: int = abs(guessed_driver_position - race_guess.race.place_to_guess)
|
||||
if position_offset not in RACE_GUESS_OFFSET_POINTS:
|
||||
return 0
|
||||
|
||||
return RACE_GUESS_OFFSET_POINTS[position_offset]
|
||||
|
||||
def dnf_points(race_guess: RaceGuess, race_result: RaceResult) -> int:
|
||||
if race_guess.dnf_guess in race_result.initial_dnf:
|
||||
return RACE_GUESS_DNF_POINTS
|
||||
|
||||
if race_guess.dnf_guess == NONE_DRIVER and len(race_result.initial_dnf) == 0:
|
||||
return RACE_GUESS_DNF_POINTS
|
||||
|
||||
return 0
|
||||
|
||||
class PointsModel(Model):
|
||||
"""
|
||||
This class bundles all data + functionality required to do points calculations.
|
||||
"""
|
||||
|
||||
_points_per_step: Dict[str, List[int]] | None = None
|
||||
|
||||
def __init__(self):
|
||||
Model.__init__(self)
|
||||
Model.__init__(self)
|
||||
|
||||
def points_per_step(self) -> Dict[str, List[int]]:
|
||||
"""
|
||||
Returns a dictionary of lists, containing points per race for each user.
|
||||
"""
|
||||
if self._points_per_step is None:
|
||||
self._points_per_step = dict()
|
||||
for user in self.all_users():
|
||||
self._points_per_step[user.name] = [0] * 24 # Start at index 1, like the race numbers
|
||||
|
||||
for race_guess in self.all_race_guesses():
|
||||
user_name: str = race_guess.user.name
|
||||
race_number: int = race_guess.race.number
|
||||
race_result: RaceResult | None = self.race_result_by(race_name=race_guess.race.name)
|
||||
|
||||
if race_result is None:
|
||||
continue
|
||||
|
||||
self._points_per_step[user_name][race_number] = standing_points(race_guess, race_result) + dnf_points(race_guess, race_result)
|
||||
|
||||
return dict()
|
||||
|
||||
return self._points_per_step
|
||||
|
||||
def points_per_step_cumulative(self) -> Dict[str, List[int]]:
|
||||
"""
|
||||
Returns a dictionary of lists, containing cumulative points per race for each user.
|
||||
"""
|
||||
points_per_step_cumulative: Dict[str, List[int]] = dict()
|
||||
for user_name, points in self.points_per_step().items():
|
||||
points_per_step_cumulative[user_name] = np.cumsum(points).tolist()
|
||||
|
||||
return points_per_step_cumulative
|
||||
|
||||
@overload
|
||||
def points_by(self, *, user_name: str) -> List[int]:
|
||||
"""
|
||||
Returns a list of points per race for a specific user.
|
||||
"""
|
||||
return self.points_by(user_name=user_name)
|
||||
|
||||
@overload
|
||||
def points_by(self, *, race_name: str) -> Dict[str, int]:
|
||||
"""
|
||||
Returns a dictionary of points per user for a specific race.
|
||||
"""
|
||||
return self.points_by(race_name=race_name)
|
||||
|
||||
@overload
|
||||
def points_by(self, *, user_name: str, race_name: str) -> int:
|
||||
"""
|
||||
Returns the points for a specific race for a specific user.
|
||||
"""
|
||||
return self.points_by(user_name=user_name, race_name=race_name)
|
||||
|
||||
def points_by(self, *, user_name: str | None = None, race_name: str | None = None) -> List[int] | Dict[str, int] | int:
|
||||
if user_name is not None and race_name is None:
|
||||
return self.points_per_step()[user_name]
|
||||
|
||||
if user_name is None and race_name is not None:
|
||||
race_number: int = self.race_by(race_name=race_name).number
|
||||
points_by_race: Dict[str, int] = dict()
|
||||
|
||||
for _user_name, points in self.points_per_step().items():
|
||||
points_by_race[_user_name] = points[race_number]
|
||||
|
||||
return points_by_race
|
||||
|
||||
if user_name is not None and race_name is not None:
|
||||
race_number: int = self.race_by(race_name=race_name).number
|
||||
|
||||
return self.points_per_step()[user_name][race_number]
|
||||
|
||||
raise Exception("points_by received an illegal combination of arguments")
|
||||
|
||||
def total_points_by(self, user_name: str) -> int:
|
||||
"""
|
||||
Returns the total number of points for a specific user.
|
||||
"""
|
||||
return sum(self.points_by(user_name=user_name))
|
||||
|
Reference in New Issue
Block a user