Compare commits

..

2 Commits

Author SHA1 Message Date
09203d9390 Update season guess calculation
All checks were successful
Build Formula10 Docker Image / build-docker (push) Successful in 14s
2024-03-02 21:49:47 +01:00
5dcebab545 Allow enabling debug endpoints with env var 2024-03-02 21:49:39 +01:00
3 changed files with 122 additions and 39 deletions

View File

@ -4,9 +4,12 @@ from flask_sqlalchemy import SQLAlchemy
# Load local ENV variables (can be set when calling the executable)
ENABLE_TIMING: bool = False if os.getenv("DISABLE_TIMING") == "True" else True
ENABLE_DEBUG_ENDPOINTS: bool = True if os.getenv("ENABLE_DEBUG_ENDPOINTS") == "True" else False
print("Running Formula10 with:")
if not ENABLE_TIMING:
print("- Disabled timing constraints")
if ENABLE_DEBUG_ENDPOINTS:
print("- Enabled debug endpoints")
app: Flask = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///formula10.db"

View File

@ -2,11 +2,12 @@ from typing import List
from urllib.parse import unquote
from flask import redirect, render_template, request
from werkzeug import Response
from formula10.controller.error_controller import error_redirect
from formula10.database.update_queries import update_race_result, update_user
from formula10.database.import_export import export_dynamic_data, reload_season_guess_result_data, reload_static_data
from formula10.database.import_export import export_dynamic_data, reload_dynamic_data, reload_season_guess_result_data, reload_static_data
from formula10.domain.template_model import TemplateModel
from formula10 import app
from formula10 import ENABLE_DEBUG_ENDPOINTS, app
@app.route("/save/all")
@ -15,11 +16,14 @@ def save() -> Response:
return redirect("/")
# @app.route("/load/all")
# def load() -> Response:
# reload_static_data()
# reload_dynamic_data()
# return redirect("/")
@app.route("/load/all")
def load() -> Response:
if not ENABLE_DEBUG_ENDPOINTS:
return error_redirect("Debug endpoints are disabled!")
reload_static_data()
reload_dynamic_data()
return redirect("/")
@app.route("/load/static")
@ -34,10 +38,13 @@ def load_season_results() -> Response:
return redirect("/")
# @app.route("/load/dynamic")
# def load_dynamic() -> Response:
# reload_dynamic_data()
# return redirect("/")
@app.route("/load/dynamic")
def load_dynamic() -> Response:
if not ENABLE_DEBUG_ENDPOINTS:
return error_redirect("Debug endpoints are disabled!")
reload_dynamic_data()
return redirect("/")
@app.route("/result")

View File

@ -168,53 +168,129 @@ class PointsModel(Model):
return diff
def wdc_standing_by_position(self) -> Dict[int, str]:
standing: Dict[int, str] = dict()
def wdc_standing_by_position(self) -> Dict[int, List[str]]:
standing: Dict[int, List[str]] = dict()
for position in range(1, 21):
standing[position] = list()
position: int = 1
last_points: int = 0
comparator: Callable[[Tuple[str, int]], int] = lambda item: item[1]
for position, (driver_name, _) in enumerate(sorted(self.wdc_points().items(), key=comparator)):
standing[position] = driver_name
for driver_name, points in sorted(self.wdc_points().items(), key=comparator, reverse=True):
if points < last_points:
position += 1
standing[position].append(driver_name)
last_points = points
return standing
# @note Doesn't handle shared places (also applies to the following 3 method)
def wdc_standing_by_driver(self) -> Dict[str, int]:
standing: Dict[str, int] = dict()
position: int = 1
last_points: int = 0
comparator: Callable[[Tuple[str, int]], int] = lambda item: item[1]
for position, (driver_name, _) in enumerate(sorted(self.wdc_points().items(), key=comparator)):
for driver_name, points in sorted(self.wdc_points().items(), key=comparator, reverse=True):
if points < last_points:
position += 1
standing[driver_name] = position
last_points = points
return standing
def wcc_standing_by_position(self) -> Dict[int, str]:
standing: Dict[int, str] = dict()
def wcc_standing_by_position(self) -> Dict[int, List[str]]:
standing: Dict[int, List[str]] = dict()
for position in range (1, 11):
standing[position] = list()
position: int = 1
last_points: int = 0
comparator: Callable[[Tuple[str, int]], int] = lambda item: item[1]
for position, (team_name, _) in enumerate(sorted(self.wcc_points().items(), key=comparator)):
standing[position] = team_name
for team_name, points in sorted(self.wcc_points().items(), key=comparator, reverse=True):
if points < last_points:
position += 1
standing[position].append(team_name)
last_points = points
return standing
def wcc_standing_by_team(self) -> Dict[str, int]:
standing: Dict[str, int] = dict()
position: int = 1
last_points: int = 0
comparator: Callable[[Tuple[str, int]], int] = lambda item: item[1]
for position, (team_name, _) in enumerate(sorted(self.wcc_points().items(), key=comparator)):
for team_name, points in sorted(self.wcc_points().items(), key=comparator, reverse=True):
if points < last_points:
position += 1
standing[team_name] = position
last_points = points
return standing
def most_dnfs_name(self) -> str:
most_dnfs: Tuple[str, int] | None = None
def most_dnf_names(self) -> List[str]:
dnf_names: List[str] = list()
most_dnfs: int = 0
for dnfs in self.dnfs().values():
if dnfs > most_dnfs:
most_dnfs = dnfs
for driver_name, dnfs in self.dnfs().items():
if most_dnfs is None or dnfs > most_dnfs[1]:
most_dnfs = (driver_name, dnfs)
if dnfs == most_dnfs:
dnf_names.append(driver_name)
if most_dnfs is None:
raise Exception("Failed to find driver with most dnfs")
return dnf_names
return most_dnfs[0]
def most_gained_names(self) -> List[str]:
most_gained_names: List[str] = list()
most_gained: int = 0
for driver in self.all_drivers(include_none=False):
gained: int = self.wdc_diff_2023()[driver.name]
if gained > most_gained:
most_gained = gained
for driver in self.all_drivers(include_none=False):
gained: int = self.wdc_diff_2023()[driver.name]
if gained == most_gained:
most_gained_names.append(driver.name)
return most_gained_names
def most_lost_names(self) -> List[str]:
most_lost_names: List[str] = list()
most_lost: int = 100
for driver in self.all_drivers(include_none=False):
lost: int = self.wdc_diff_2023()[driver.name]
if lost < most_lost:
most_lost = lost
for driver in self.all_drivers(include_none=False):
lost: int = self.wdc_diff_2023()[driver.name]
if lost == most_lost:
most_lost_names.append(driver.name)
return most_lost_names
def points_per_step_cumulative(self) -> Dict[str, List[int]]:
"""
@ -335,10 +411,7 @@ class PointsModel(Model):
if season_guess is None or season_guess.p2_wcc is None:
return False
if 2 in self.wcc_standing_by_position():
return self.wcc_standing_by_position()[2] == season_guess.p2_wcc.name
return False
return season_guess.p2_wcc.name in self.wcc_standing_by_position()[2]
def overtakes_correct(self, user_name: str) -> bool:
season_guess_result: SeasonGuessResult | None = self.season_guess_result_by(user_name=user_name)
@ -351,7 +424,7 @@ class PointsModel(Model):
if season_guess is None or season_guess.most_dnfs is None:
return False
return season_guess.most_dnfs.name == self.most_dnfs_name()
return season_guess.most_dnfs.name in self.most_dnf_names()
def most_gained_correct(self, user_name: str) -> bool:
season_guess: SeasonGuess | None = self.season_guesses_by(user_name=user_name)
@ -359,8 +432,7 @@ class PointsModel(Model):
if season_guess is None or season_guess.most_wdc_gained is None:
return False
comparator: Callable[[Tuple[str, int]], int] = lambda item: item[1]
return season_guess.most_wdc_gained.name == max(self.wdc_diff_2023().items(), key=comparator)[0]
return season_guess.most_wdc_gained.name in self.most_gained_names()
def most_lost_correct(self, user_name: str) -> bool:
season_guess: SeasonGuess | None = self.season_guesses_by(user_name=user_name)
@ -368,14 +440,15 @@ class PointsModel(Model):
if season_guess is None or season_guess.most_wdc_lost is None:
return False
comparator: Callable[[Tuple[str, int]], int] = lambda item: item[1]
return season_guess.most_wdc_lost.name == min(self.wdc_diff_2023().items(), key=comparator)[0]
return season_guess.most_wdc_lost.name in self.most_lost_names()
def is_team_winner(self, driver: Driver) -> bool:
teammates: List[Driver] = self.drivers_by(team_name=driver.team.name)
teammate: Driver = teammates[0] if teammates[1] == driver else teammates[1]
return self.wdc_standing_by_driver()[driver.name] >= self.wdc_standing_by_driver()[teammate.name]
print(f"{driver.name} standing: {self.wdc_standing_by_driver()[driver.name]}, {teammate.name} standing: {self.wdc_standing_by_driver()[teammate.name]}")
return self.wdc_standing_by_driver()[driver.name] <= self.wdc_standing_by_driver()[teammate.name]
def has_podium(self, driver: Driver) -> bool:
for race_result in self.all_race_results():