from typing import TYPE_CHECKING from sqlmodel import ( Session, Relationship, Field, ) from . import mixin from .base import ( BaseSQLModel, DocumentedStrEnum, DocumentedIntFlag, DocumentedStrFlagType, auto_enum, ) if TYPE_CHECKING: from .event import Event # region # Hike ################################################################ class HikeTeamPage(DocumentedIntFlag): ROUTE = auto_enum() # Route steps info QUESTIONS = auto_enum() # Visible questions VISITED_PLACES = auto_enum() # Places the team has been CURRENT_PLACE = auto_enum() # Place where the team currently is UNVISITED_PLACES = auto_enum() # Places the team still neat to visit PLACES = VISITED_PLACES | CURRENT_PLACE | UNVISITED_PLACES # All the places TRAVEL_TIME = auto_enum() # Total travel time TRAVEL_FREE_TIME = auto_enum() # Total travel time PLACE_TIME = auto_enum() # Total place time CALCULATE_TIME = auto_enum() # Total time calculated based on hike settings # TODO: Think about time between oter teams PLACE_POINTS = auto_enum() # Points scored on a place TOTAL_PLACE_POINTS = auto_enum() # All points got on all places ASSIST_POINTS = auto_enum() # Minus points for assistants # TODO: Think about place in classement ASSIST_LOG = auto_enum() # Assisted items ASSIST_LATTER = auto_enum() # ??? # ############################################################################## class HikeTimeCalculation(DocumentedIntFlag): TRAVEL_TIME = auto_enum() # Time traveling # TODO: Think about time groups (in this model we have 2, free and non free) TRAVEL_FREE_TIME = auto_enum() # Time that is excluded from traveling but not at a place PLACE_TIME = auto_enum() # Time checked in at a place TOTAL_TIME = TRAVEL_TIME | TRAVEL_FREE_TIME | PLACE_TIME # ############################################################################## class HikeBase( mixin.Name, mixin.Contact, BaseSQLModel, ): tracker_interval: int | None = Field( default=None, nullable=True, description="Is GPS button available, value will be the interval", ) is_multi_day: bool = Field( default=False, nullable=False, description="Show datetime in stead of time only", ) team_page: HikeTeamPage = Field( default=HikeTeamPage.PLACES | HikeTeamPage.ROUTE | HikeTeamPage.QUESTIONS, nullable=False, description="Show all the places of the route inside the teams page", sa_type=DocumentedStrFlagType(HikeTeamPage), ) time_calculation: HikeTimeCalculation = Field( default=HikeTimeCalculation.TRAVEL_TIME, nullable=False, description="Wath should we calculate inside the total time", sa_type=DocumentedStrFlagType(HikeTimeCalculation), ) min_time_points: int | None = Field( default=0, ge=0, # TODO: le: max_time_points description="Min points for time", ) max_time_points: int | None = Field( default=100, ge=0, # TODO: ge > min_time_points description="Max points for time", ) max_question_points: int | None = Field( default=None, description="None: Calculate from answers (no max), Positive: Set as max for dynamic range", ) # Properties to receive via API on creation class HikeCreate(HikeBase): pass # Properties to receive via API on update, all are optional class HikeUpdate(HikeBase): is_multi_day: bool | None = Field(default=None) # type: ignore team_page: HikeTeamPage | None = Field(default=None) # type: ignore time_calculation: HikeTimeCalculation | None = Field(default=None) # type: ignore class Hike(mixin.RowId, HikeBase, table=True): # --- database only items -------------------------------------------------- # --- read only items ------------------------------------------------------ # --- back_populates links ------------------------------------------------- # --- CRUD actions --------------------------------------------------------- @classmethod def create(cls, *, session: Session, create_obj: HikeCreate) -> "Hike": data_obj = create_obj.model_dump(exclude_unset=True) db_obj = cls.model_validate(data_obj) session.add(db_obj) session.commit() session.refresh(db_obj) return db_obj @classmethod def update( cls, *, session: Session, db_obj: "Hike", in_obj: HikeUpdate ) -> "Hike": data_obj = in_obj.model_dump(exclude_unset=True) db_obj.sqlmodel_update(data_obj) session.add(db_obj) session.commit() session.refresh(db_obj) return db_obj # Properties to return via API, id is always required class HikePublic(mixin.RowIdPublic, HikeBase): pass class HikesPublic(BaseSQLModel): data: list[HikePublic] count: int # endregion # region # Hike / Route ######################################################## class RouteType(DocumentedStrEnum): START_FINISH = auto_enum() # Start at the start and end at the finish CIRCULAR = auto_enum() # Start some ware, finish at the last new place CIRCULAR_BACK_TO_START = auto_enum() # Start and finish on the same random place (CIRCULAR + next to start) # ############################################################################## # endregion