Source code for gnomish_army_knife.database.writer

"""
A module implementing an arena-match file-writing interface.
"""

# built-in
from typing import Optional

# third-party
import aiofiles
from vcorelib.io import ARBITER
from vcorelib.logging import LoggerMixin
from vcorelib.paths import Pathlike, normalize, rel

# internal
from gnomish_army_knife.database.event import CombatLogEvent
from gnomish_army_knife.database.meta import ArenaMatchMetadata
from gnomish_army_knife.enums.events import LogEvent


[docs] class ArenaMatchWriter(LoggerMixin): """A class capable of writing individual arena match events to disk.""" def __init__(self, root: Pathlike) -> None: """Initialize this instance.""" super().__init__() self.root = normalize(root) self.start_event: Optional[CombatLogEvent] = None self.bucket: list[str] = [] self.meta = ArenaMatchMetadata() self._reset() def _reset(self) -> None: """Reset internal state.""" # Could check for dropped events/loss at some point. self.bucket = [] self.start_event = None self.meta.reset() async def _end_match(self) -> None: """Handle the end of a match.""" path = self.meta.file_path(self.root) if self.bucket and path is not None and not path.is_file(): path.parent.mkdir(parents=True, exist_ok=True) # Write event file. with self.log_time( "Writing '%s' (%d events) to '%s'", self.meta.summary, len(self.bucket), str(rel(path, base=self.root)), ): async with aiofiles.open(path, mode="w") as path_fd: await path_fd.writelines(self.bucket) # Write metadata. with self.log_time("Writing metadata JSON"): await ARBITER.encode_async( path.with_suffix(".json"), self.meta.data ) self._reset()
[docs] async def handle(self, event: CombatLogEvent) -> bool: """Returns true if the arena-match-writer consumed the event.""" # Always check for a new start event. if event.name == LogEvent.MATCH_START: self.start_event = event # Have a reference to a start event, this new event will # always be written. result = self.start_event is not None if result: self.bucket.append(event.line) if self.meta.handle(event): await self._end_match() return result