Files
g0v0-server/app/database/matchmaking.py
2025-11-22 13:15:24 +00:00

110 lines
3.6 KiB
Python

from datetime import datetime
from typing import TYPE_CHECKING, Any, Optional
from app.models.model import UTCBaseModel
from app.models.mods import APIMod
from sqlalchemy import Column, DateTime, ForeignKey, Index, SmallInteger
from sqlmodel import (
JSON,
BigInteger,
Field,
Relationship,
SQLModel,
func,
)
if TYPE_CHECKING:
from .beatmap import Beatmap
from .user import User
class MatchmakingUserStatsBase(SQLModel, UTCBaseModel):
user_id: int = Field(
default=None,
sa_column=Column(BigInteger, ForeignKey("lazer_users.id"), primary_key=True),
)
pool_id: int = Field(
default=None,
sa_column=Column(ForeignKey("matchmaking_pools.id"), primary_key=True, nullable=True),
)
first_placements: int = Field(default=0, ge=0)
total_points: int = Field(default=0, ge=0)
elo_data: dict[str, Any] | None = Field(default=None, sa_column=Column(JSON))
created_at: datetime | None = Field(
default=None,
sa_column=Column(DateTime(timezone=True), server_default=func.now()),
)
updated_at: datetime | None = Field(
default=None,
sa_column=Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()),
)
class MatchmakingUserStats(MatchmakingUserStatsBase, table=True):
__tablename__: str = "matchmaking_user_stats"
__table_args__ = (
Index("matchmaking_user_stats_pool_first_idx", "pool_id", "first_placements"),
Index("matchmaking_user_stats_pool_points_idx", "pool_id", "total_points"),
)
user: "User" = Relationship(back_populates="matchmaking_stats", sa_relationship_kwargs={"lazy": "joined"})
pool: "MatchmakingPool" = Relationship()
class MatchmakingPoolBase(SQLModel, UTCBaseModel):
id: int | None = Field(default=None, primary_key=True)
ruleset_id: int = Field(
default=0,
sa_column=Column(SmallInteger, nullable=False),
)
name: str = Field(max_length=255)
active: bool = Field(default=True)
lobby_size: int = Field(default=8)
rating_search_radius: int = Field(default=20)
rating_search_radius_exp: int = Field(default=15)
created_at: datetime | None = Field(
default=None,
sa_column=Column(DateTime(timezone=True), server_default=func.now()),
)
updated_at: datetime | None = Field(
default=None,
sa_column=Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()),
)
class MatchmakingPool(MatchmakingPoolBase, table=True):
__tablename__: str = "matchmaking_pools"
__table_args__ = (Index("matchmaking_pools_ruleset_active_idx", "ruleset_id", "active"),)
beatmaps: list["MatchmakingPoolBeatmap"] = Relationship(
back_populates="pool",
# sa_relationship_kwargs={
# "lazy": "selectin",
# },
)
class MatchmakingPoolBeatmapBase(SQLModel, UTCBaseModel):
id: int | None = Field(default=None, primary_key=True)
pool_id: int = Field(
default=None,
sa_column=Column(ForeignKey("matchmaking_pools.id"), nullable=False, index=True),
)
beatmap_id: int = Field(
default=None,
sa_column=Column(ForeignKey("beatmaps.id"), nullable=False),
)
mods: list[APIMod] | None = Field(default=None, sa_column=Column(JSON))
rating: int | None = Field(default=1500)
selection_count: int = Field(default=0)
class MatchmakingPoolBeatmap(MatchmakingPoolBeatmapBase, table=True):
__tablename__: str = "matchmaking_pool_beatmaps"
pool: MatchmakingPool = Relationship(back_populates="beatmaps")
beatmap: Optional["Beatmap"] = Relationship(
# sa_relationship_kwargs={"lazy": "joined"},
)