Files
g0v0-server/app/calculators/performance/_base.py
MingxuanGame 33f321952d feat(custom-rulesets): support custom rulesets (#23)
* feat(custom_ruleset): add custom rulesets support

* feat(custom-ruleset): add version check

* feat(custom-ruleset): add LegacyIO API to get ruleset hashes

* feat(pp): add check for rulesets whose pp cannot be calculated

* docs(readme): update README to include support for custom rulesets

* fix(custom-ruleset): make `rulesets` empty instead of throw a error when version check is disabled

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore(custom-ruleset): apply the latest changes of generator

c891bcd159

and

e25041ad3b

* feat(calculator): add fallback performance calculation for unsupported modes

* fix(calculator): remove debug print

* fix: resolve reviews

* feat(calculator): add difficulty calculation checks

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-26 21:10:36 +08:00

59 lines
1.8 KiB
Python

import abc
from typing import TYPE_CHECKING, NamedTuple
from app.models.mods import APIMod
from app.models.performance import DifficultyAttributes, PerformanceAttributes
from app.models.score import GameMode
if TYPE_CHECKING:
from app.database.score import Score
class CalculateError(Exception):
"""An error occurred during performance calculation."""
class DifficultyError(CalculateError):
"""The difficulty could not be calculated."""
class ConvertError(DifficultyError):
"""A beatmap cannot be converted to the specified game mode."""
class PerformanceError(CalculateError):
"""The performance could not be calculated."""
class AvailableModes(NamedTuple):
has_performance_calculator: set[GameMode]
has_difficulty_calculator: set[GameMode]
class PerformanceCalculator(abc.ABC):
@abc.abstractmethod
async def get_available_modes(self) -> AvailableModes:
raise NotImplementedError
@abc.abstractmethod
async def calculate_performance(self, beatmap_raw: str, score: "Score") -> PerformanceAttributes:
raise NotImplementedError
@abc.abstractmethod
async def calculate_difficulty(
self, beatmap_raw: str, mods: list[APIMod] | None = None, gamemode: GameMode | None = None
) -> DifficultyAttributes:
raise NotImplementedError
async def can_calculate_performance(self, gamemode: GameMode) -> bool:
modes = await self.get_available_modes()
return gamemode in modes.has_performance_calculator
async def can_calculate_difficulty(self, gamemode: GameMode) -> bool:
modes = await self.get_available_modes()
return gamemode in modes.has_difficulty_calculator
async def init(self) -> None:
"""Initialize the calculator (if needed)."""
pass