911 / src /models.py
Abhinav31122006
feat: exploit analysis, architecture docs, observation depth, citation
0b2675d
"""Pydantic typed contracts for the 911 dispatch supervisor environment."""
from enum import StrEnum
from pydantic import BaseModel, Field
class IncidentType(StrEnum):
STRUCTURE_FIRE = "STRUCTURE_FIRE"
CARDIAC_ARREST = "CARDIAC_ARREST"
MULTI_VEHICLE_ACCIDENT = "MULTI_VEHICLE_ACCIDENT"
SHOOTING = "SHOOTING"
OVERDOSE = "OVERDOSE"
BUILDING_COLLAPSE = "BUILDING_COLLAPSE"
HAZMAT_SPILL = "HAZMAT_SPILL"
MISSING_PERSON = "MISSING_PERSON"
class IncidentSeverity(StrEnum):
PRIORITY_1 = "PRIORITY_1"
PRIORITY_2 = "PRIORITY_2"
PRIORITY_3 = "PRIORITY_3"
class UnitType(StrEnum):
ENGINE = "ENGINE"
LADDER = "LADDER"
MEDIC = "MEDIC"
PATROL = "PATROL"
SUPERVISOR = "SUPERVISOR"
HAZMAT = "HAZMAT"
class UnitStatus(StrEnum):
AVAILABLE = "AVAILABLE"
DISPATCHED = "DISPATCHED"
ON_SCENE = "ON_SCENE"
TRANSPORTING = "TRANSPORTING"
OUT_OF_SERVICE = "OUT_OF_SERVICE"
class IncidentStatus(StrEnum):
PENDING = "PENDING"
RESPONDING = "RESPONDING"
ON_SCENE = "ON_SCENE"
RESOLVED = "RESOLVED"
ESCALATED = "ESCALATED"
class DispatchAction(StrEnum):
DISPATCH = "DISPATCH"
UPGRADE = "UPGRADE"
DOWNGRADE = "DOWNGRADE"
MUTUAL_AID = "MUTUAL_AID"
CANCEL = "CANCEL"
REASSIGN = "REASSIGN"
STAGE = "STAGE"
class Action(BaseModel):
"""Structured dispatcher command."""
model_config = {"extra": "forbid"}
action_type: DispatchAction
unit_id: str = Field(..., min_length=1, max_length=20)
incident_id: str = Field(..., min_length=1, max_length=20)
notes: str | None = None
priority_override: IncidentSeverity | None = None
class Observation(BaseModel):
"""Environment response to a dispatch action."""
model_config = {"extra": "forbid"}
result: str = Field(..., min_length=1)
score: float = Field(..., ge=0.0, le=1.0)
protocol_ok: bool = False
issues: list[str] = Field(default_factory=list)
reward_breakdown: dict[str, float] | None = None
phraseology_score: float = 0.0
active_p1_count: int = 0
units_available: int = 0
step_count: int = 0
episode_done: bool = False
class UnitState(BaseModel):
"""City-wide unit state."""
model_config = {"extra": "forbid"}
unit_id: str = Field(..., min_length=1, max_length=20)
unit_type: UnitType
status: UnitStatus
location_x: float = Field(..., ge=0.0)
location_y: float = Field(..., ge=0.0)
assigned_incident_id: str | None = None
eta_seconds: float = Field(default=0.0, ge=0.0)
crew_count: int = Field(default=1, ge=0)
class IncidentState(BaseModel):
"""Incident state tracked by dispatch."""
model_config = {"extra": "forbid"}
incident_id: str = Field(..., min_length=1, max_length=20)
incident_type: IncidentType
severity: IncidentSeverity
location_x: float = Field(..., ge=0.0)
location_y: float = Field(..., ge=0.0)
reported_at_step: int = Field(default=0, ge=0)
units_assigned: list[str] = Field(default_factory=list)
status: IncidentStatus
survival_clock: float = Field(default=0.0, ge=0.0)
class State(BaseModel):
"""Full environment state."""
model_config = {"extra": "forbid"}
units: dict[str, UnitState] = Field(default_factory=dict)
incidents: dict[str, IncidentState] = Field(default_factory=dict)
episode_id: str = Field(..., min_length=1)
step_count: int = Field(default=0, ge=0)
task_id: str = Field(..., min_length=1)
city_time: float = Field(default=0.0, ge=0.0)
metadata: dict = Field(default_factory=dict)