init
This commit is contained in:
121
models.py
Normal file
121
models.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Any, Optional
|
||||
from enum import Enum
|
||||
import re
|
||||
|
||||
|
||||
class EventType(Enum):
|
||||
RESONATOR_DEPLOYED = "RESONATOR_DEPLOYED"
|
||||
RESONATOR_DESTROYED = "RESONATOR_DESTROYED"
|
||||
PORTAL_CAPTURED = "PORTAL_CAPTURED"
|
||||
PORTAL_NEUTRALIZED = "PORTAL_NEUTRALIZED"
|
||||
PORTAL_UNDER_ATTACK = "PORTAL_UNDER_ATTACK"
|
||||
LINK_CREATED = "LINK_CREATED"
|
||||
LINK_DESTROYED = "LINK_DESTROYED"
|
||||
CONTROL_FIELD_CREATED = "CONTROL_FIELD_CREATED"
|
||||
UNKNOWN = "UNKNOWN"
|
||||
|
||||
|
||||
EVENT_TYPE_KEYWORDS = {
|
||||
EventType.RESONATOR_DEPLOYED: ["deployed a Resonator on"],
|
||||
EventType.RESONATOR_DESTROYED: ["destroyed a Resonator on"],
|
||||
EventType.LINK_DESTROYED: ["destroyed the", "Link"],
|
||||
EventType.PORTAL_CAPTURED: ["captured"],
|
||||
EventType.PORTAL_NEUTRALIZED: ["neutralized by"],
|
||||
EventType.PORTAL_UNDER_ATTACK: ["is under attack by"],
|
||||
EventType.LINK_CREATED: ["linked from"],
|
||||
EventType.CONTROL_FIELD_CREATED: ["created a Control Field"],
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Markup:
|
||||
type: str
|
||||
plain: str
|
||||
team: str = ""
|
||||
name: str = ""
|
||||
address: str = ""
|
||||
latE6: int = 0
|
||||
lngE6: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class Plext:
|
||||
id: str
|
||||
timestamp: int
|
||||
text: str
|
||||
team: str
|
||||
plext_type: str
|
||||
categories: int
|
||||
markup: List[Markup]
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: List[Any]) -> "Plext":
|
||||
plext_data = data[2]["plext"]
|
||||
markup_data = plext_data["markup"]
|
||||
|
||||
markup = []
|
||||
for m in markup_data:
|
||||
markup_type = m[0]
|
||||
markup_details = m[1]
|
||||
markup.append(
|
||||
Markup(
|
||||
type=markup_type,
|
||||
plain=markup_details.get("plain", ""),
|
||||
team=markup_details.get("team", ""),
|
||||
name=markup_details.get("name", ""),
|
||||
address=markup_details.get("address", ""),
|
||||
latE6=markup_details.get("latE6", 0),
|
||||
lngE6=markup_details.get("lngE6", 0),
|
||||
)
|
||||
)
|
||||
|
||||
return cls(
|
||||
id=data[0],
|
||||
timestamp=data[1],
|
||||
text=plext_data["text"],
|
||||
team=plext_data["team"],
|
||||
plext_type=plext_data["plextType"],
|
||||
categories=plext_data["categories"],
|
||||
markup=markup,
|
||||
)
|
||||
|
||||
def get_event_type(self) -> EventType:
|
||||
for event_type, keywords in EVENT_TYPE_KEYWORDS.items():
|
||||
if all(keyword in self.text for keyword in keywords):
|
||||
# A special case for "captured", to avoid matching "destroyed"
|
||||
if event_type == EventType.PORTAL_CAPTURED and "destroyed" in self.text:
|
||||
continue
|
||||
return event_type
|
||||
return EventType.UNKNOWN
|
||||
|
||||
def get_player_name(self) -> str:
|
||||
for m in self.markup:
|
||||
if m.type == "PLAYER":
|
||||
return m.plain
|
||||
# If player name is not in markup, try to extract from text
|
||||
if "agent" in self.text:
|
||||
match = re.search(r"agent (\w+)", self.text)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return ""
|
||||
|
||||
def get_portal_name(self) -> str:
|
||||
for m in self.markup:
|
||||
if m.type == "PORTAL":
|
||||
return m.name
|
||||
# If portal name is not in markup, try to extract from text
|
||||
match = re.search(r"(?:deployed|destroyed|captured|linked from|created a Control Field @) (.+?) \(", self.text)
|
||||
if not match:
|
||||
match = re.search(r"Your Portal (.+?) is under attack by", self.text)
|
||||
if not match:
|
||||
match = re.search(r"Your Portal (.+?) neutralized by", self.text)
|
||||
if match:
|
||||
return match.group(1).strip()
|
||||
return ""
|
||||
|
||||
def get_event_coordinates(self) -> Optional[tuple[int, int]]:
|
||||
for m in self.markup:
|
||||
if m.type == "PORTAL":
|
||||
return m.latE6, m.lngE6
|
||||
return None
|
||||
Reference in New Issue
Block a user