adeem6's picture
Upload 52 files
f492127 verified
"""
HaramGuard — Shared Data Models
================================
All dataclasses used across agents. Import from here to avoid circular imports.
"""
import numpy as np
from dataclasses import dataclass, field
@dataclass
class FrameResult:
"""Output of PerceptionAgent for a single frame."""
frame_id: int
timestamp: float
person_count: int
density_score: float
avg_spacing: float
boxes: list # [{'x1','y1','x2','y2','conf'}]
annotated: np.ndarray # frame with drawn boxes (BGR)
guardrail_flags: list = field(default_factory=list)
track_ids: list = field(default_factory=list) # YOLO tracking IDs for this frame
occupation_pct: float = 0.0 # Σ(box areas) / frame area × 100
# Condition-based features
compression_ratio: float = 0.0 # 0.0-1.0: how compressed the crowd is
flow_velocity: float = 0.0 # pixels/frame: average movement speed
distribution_score: float = 0.0 # 0.0-1.0: spatial distribution (clustered vs spread)
# Spatial grid — UQU Haram research (local hotspot detection)
grid_counts: list = field(default_factory=list) # 3×3 nested list of per-cell counts
grid_max: int = 0 # max persons in any single cell
hotspot_zone: str = '' # e.g. 'center', 'top-left', 'bottom-right'
@dataclass
class RiskResult:
"""Output of RiskAgent for current sliding window."""
frame_id: int
timestamp: float
risk_score: float # 0.0 - 1.0
risk_level: str # HIGH / MEDIUM / LOW
trend: str # rising / stable / falling
level_changed: bool # True -> trigger OperationsAgent
window_avg: float
window_max: int
density_ema: float = 0.0 # EMA of peak person_count (smoothed)
density_pct: float = 0.0 # density_ema / 50 * 100 (percentage, capped at 150)
@dataclass
class Decision:
"""Single operational decision from OperationsAgent."""
frame_id: int
timestamp: str
context: str
priority: str # P0 / P1 / P2
actions: list # Arabic action strings (filled by CoordinatorAgent)
risk_score: float
risk_level: str
justification: str = "" # Arabic reasoning behind chosen actions (filled by CoordinatorAgent)
selected_gates: list = field(default_factory=list) # gate names chosen by LLM