Source code for gnomish_army_knife.database.event
"""
A module implementing interfaces for combat log events.
"""
# built-in
from datetime import datetime
from logging import INFO
from time import strptime
from typing import Callable, NamedTuple
# third-party
from runtimepy.message import JsonMessage
from vcorelib.logging import LoggerType
# internal
from gnomish_army_knife.enums.events import LogEvent
CombatLogEventHandler = Callable[["CombatLogEvent"], None]
[docs]
def parse_timestamp(data: str) -> datetime:
"""Parse a timestamp string from a combat log line."""
# Parse the timestamp.
datetime_raw, millis = data.split(".")
# Ignore timezone suffix (non-standard).
millis = millis.split("-")[0].split("+")[0]
timestamp = datetime(
*strptime(datetime_raw, "%m/%d/%Y %H:%M:%S")[:6],
microsecond=int(millis) * 1000,
)
return timestamp
[docs]
class CombatLogEvent(NamedTuple):
"""A simple container for combat log events."""
timestamp: datetime
name: str
data: list[str]
line: str
[docs]
def as_json(self) -> JsonMessage:
"""Create a JSON serializable dictionary from this instance."""
return {
"timestamp": str(self.timestamp),
"name": self.name,
# This complex data structure is not parsed correctly for some
# events.
"data": (
self.data if not self.name == LogEvent.COMBATANT_INFO else []
),
"line": self.line,
}
[docs]
@staticmethod
def from_json(data: JsonMessage) -> "CombatLogEvent":
"""Create an event from JSON message data."""
return CombatLogEvent(
datetime.fromisoformat(data["timestamp"]),
data["name"],
data["data"],
data["line"],
)
[docs]
@staticmethod
def from_line(line: str) -> "CombatLogEvent":
"""Create an event from a string line."""
timestamp_raw, event_raw = line.rstrip().split(" ", 1)
event_items = event_raw.split(",")
return CombatLogEvent(
parse_timestamp(timestamp_raw),
event_items[0],
event_items[1:],
line,
)
[docs]
def log(self, logger: LoggerType, level: int = INFO) -> None:
"""Log this event."""
logger.log(level, "(%s) %s: %s.", self.timestamp, self.name, self.data)
[docs]
@staticmethod
def log_handler(logger: LoggerType) -> CombatLogEventHandler:
"""Create a simple event handler."""
def handler(event: CombatLogEvent) -> None:
"""A simple event handler that logs."""
event.log(logger)
return handler