Atlas-Install/source/mkw/Track/AbstractTrack.py
Faraphel 99287bbd56 started making a AbstractTrack class to implement more type of "track".
Removed get_suffix and get_prefix to replace them with get_tag_template and tags_template in mod_config.json
2022-08-10 22:33:10 +02:00

103 lines
No EOL
3.9 KiB
Python

from abc import ABC, abstractmethod
from typing import Generator
from source.mkw import Slot, Tag, ModConfig
class TrackForbiddenCustomAttribute(Exception):
def __init__(self, attribute_name: str):
super().__init__(f"Forbidden track attribute : {attribute_name!r}")
class AbstractTrack(ABC):
music: Slot
special: Slot
tags: list[Tag]
weight: int
def __init__(self, music: Slot = "T11", special: Slot = "T11", tags: list[Tag] = None, weight: int = 1, **kwargs):
self.music = music
self.special = special
self.tags = tags if tags is not None else []
self.weight = weight
# others not mandatory attributes
for key, value in kwargs.items():
# if the attribute start with __, this is a magic attribute, and it should not be modified
if "__" in key or hasattr(self, key): raise TrackForbiddenCustomAttribute(key)
setattr(self, key, value)
def __repr__(self):
return f"<{self.__class__.__name__} {id(self)}>"
def get_tracks(self) -> Generator["AbstractTrack", None, None]:
"""
Return all the track itself or the subtracks if available
:return: all the track itself or the subtracks if available
"""
for _ in range(self.weight):
yield self
def get_tag_template(self, mod_config: "ModConfig", template_name: str, default: any = None) -> any:
"""
Return the tag template found in templates. If not found, return default
:param mod_config: mod configuration
:param template_name: name of the template of the tags
:param default: default value if no tag template is found
:return: formatted representation of the tag
"""
for tag in filter(lambda tag: tag in mod_config.tags_template[template_name], self.tags):
return mod_config.multiple_safe_eval(mod_config.tags_template[template_name][tag], env={"tag": tag})
return default
def repr_format(self, mod_config: "ModConfig", template: str) -> str:
"""
return the representation of the track from the format
:param template: template for the way the text will be represented
:param mod_config: configuration of the mod
:return: formatted representation of the track
"""
return mod_config.multiple_safe_eval(template, env={"track": self, "get_tag_template": self.get_tag_template})
@abstractmethod
def get_filename(self, mod_config: "ModConfig") -> str:
"""
Return the filename of the track
:param mod_config: the mod_config object
:return: the filename of the track
"""
...
@abstractmethod
def is_new(self, mod_config: "ModConfig") -> bool:
"""
Return if the track should be considered as new for random selection
:param mod_config: mod configuration
:return: is the track new
"""
...
def get_ctfile(self, mod_config: "ModConfig", template: str, hidden: bool = False) -> str:
"""
return the ctfile of the track
:hidden: if the track is in a group
:template: format of the track's name
:return: ctfile
"""
category: str = "H" if hidden else "T"
name: str = self.repr_format(mod_config=mod_config, template=template)
filename: str = self.get_filename(mod_config=mod_config)
flags: int = (
(0x04 if hidden else 0) |
(0x01 if self.is_new(mod_config) else 0)
)
return (
f'{category} ' # category (is the track hidden, visible, an arena, ...)
f'{self.music}; ' # music
f'{self.special}; ' # property of the tracks
f'{flags:#04x}; ' # lecode flags
f'{filename!r}; ' # filename
f'{name!r}; ' # name of the track in the menu
f'{filename!r}\n' # unique identifier for each track
)