from abc import ABC, abstractmethod from dataclasses import dataclass from typing import ClassVar, Optional from ...data.fish_data import FishItem from ...strings.fish_names import Fish location_prefix = "Fishsanity: " def to_location_name(fish: str) -> str: return location_prefix + fish def extract_fish_from_location_name(location_name: str) -> Optional[str]: if not location_name.startswith(location_prefix): return None return location_name[len(location_prefix):] @dataclass(frozen=True) class FishsanityFeature(ABC): is_enabled: ClassVar[bool] randomization_ratio: float = 1 to_location_name = staticmethod(to_location_name) extract_fish_from_location_name = staticmethod(extract_fish_from_location_name) @property def is_randomized(self) -> bool: return self.randomization_ratio != 1 @abstractmethod def is_included(self, fish: FishItem) -> bool: ... class FishsanityNone(FishsanityFeature): is_enabled = False def is_included(self, fish: FishItem) -> bool: return False class FishsanityLegendaries(FishsanityFeature): is_enabled = True def is_included(self, fish: FishItem) -> bool: return fish.legendary class FishsanitySpecial(FishsanityFeature): is_enabled = True included_fishes = { Fish.angler, Fish.crimsonfish, Fish.glacierfish, Fish.legend, Fish.mutant_carp, Fish.blobfish, Fish.lava_eel, Fish.octopus, Fish.scorpion_carp, Fish.ice_pip, Fish.super_cucumber, Fish.dorado } def is_included(self, fish: FishItem) -> bool: return fish.name in self.included_fishes class FishsanityAll(FishsanityFeature): is_enabled = True def is_included(self, fish: FishItem) -> bool: return True class FishsanityExcludeLegendaries(FishsanityFeature): is_enabled = True def is_included(self, fish: FishItem) -> bool: return not fish.legendary class FishsanityExcludeHardFish(FishsanityFeature): is_enabled = True def is_included(self, fish: FishItem) -> bool: return fish.difficulty < 80 class FishsanityOnlyEasyFish(FishsanityFeature): is_enabled = True def is_included(self, fish: FishItem) -> bool: return fish.difficulty < 50