* 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 generatorc891bcd159ande25041ad3b* 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>
59 lines
1.8 KiB
Python
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
|