from __future__ import annotations from typing import Dict, Any, TypeVar, Type, cast from datetime import datetime from uuid import uuid4 T = TypeVar("T", bound="WarEvent") EVENT_REGISTRY: Dict[str, Type["WarEvent"]] = {} def register_event(cls: Type[T]) -> Type[T]: EVENT_REGISTRY[cls.TYPE] = cls return cls class WarEvent: TYPE = "WarEvent" def __init__(self, participant_id: str | None, context_type: str, context_id: str): self.id: str = str(uuid4()) self.participant_id: str | None = participant_id self.context_type = context_type # battle, round, campaign, war self.context_id = context_id self.timestamp: datetime = datetime.now() def set_id(self, new_id: str) -> None: self.id = new_id def set_participant(self, new_war_part_id: str | None) -> None: self.participant_id = new_war_part_id def set_timestamp(self, new_timestamp: datetime) -> None: self.timestamp = new_timestamp def toDict(self) -> Dict[str, Any]: return { "type": self.TYPE, "id": self.id, "participant_id": self.participant_id, "context_type": self.context_type, "context_id": self.context_id, "timestamp": self.timestamp.isoformat(), } @classmethod def _base_fromDict(cls: Type[T], ev: T, data: Dict[str, Any]) -> T: ev.id = data["id"] ev.participant_id = data["participant_id"] ev.context_type = data["context_type"] ev.context_id = data["context_id"] ev.timestamp = datetime.fromisoformat(data["timestamp"]) return ev @staticmethod def fromDict(data: Dict[str, Any]) -> "WarEvent": ev_type = data["type"] cls = cast(Type[WarEvent], EVENT_REGISTRY.get(ev_type)) if cls is None: raise ValueError(f"Unknown event type: {ev_type}") return cls.fromDict(data) @register_event class TieResolved(WarEvent): TYPE = "TieResolved" def __init__( self, participant_id: str | None, context_type: str, context_id: str, score_value: int | None = None, ): super().__init__(participant_id, context_type, context_id) self.score_value = score_value def toDict(self) -> Dict[str, Any]: d = super().toDict() d.update( { "score_value": self.score_value or None, } ) return d @classmethod def fromDict(cls, data: Dict[str, Any]) -> TieResolved: ev = cls( data["participant_id"] or None, data["context_type"], data["context_id"], data["score_value"] or None, ) return cls._base_fromDict(ev, data) @register_event class InfluenceGained(WarEvent): TYPE = "InfluenceGained" def __init__( self, participant_id: str, amount: int, context_type: str, context_id: str ): super().__init__(participant_id, context_type, context_id) self.amount = amount def toDict(self) -> Dict[str, Any]: d = super().toDict() d.update( { "amount": self.amount, } ) return d @classmethod def fromDict(cls, data: Dict[str, Any]) -> InfluenceGained: ev = cls( data["participant_id"], int(data["amount"]), data["context_type"], data["context_id"], ) return cls._base_fromDict(ev, data) @register_event class InfluenceSpent(WarEvent): TYPE = "InfluenceSpent" def __init__( self, participant_id: str, amount: int, context_type: str, context_id: str ): super().__init__(participant_id, context_type, context_id) self.amount = amount def toDict(self) -> Dict[str, Any]: d = super().toDict() d.update( { "amount": self.amount, } ) return d @classmethod def fromDict(cls, data: Dict[str, Any]) -> InfluenceSpent: ev = cls( data["participant_id"], int(data["amount"]), data["context_type"], data["context_id"], ) return cls._base_fromDict(ev, data)