Spaces:
Sleeping
Sleeping
Add DispatchSimulation engine, geometry helpers, caller text templates, and observation renderer
07473e9 | """Helper functions for distance, ETA, lookup tables, caller text generation.""" | |
| from __future__ import annotations | |
| import math | |
| from typing import List | |
| import numpy as np | |
| from models import ( | |
| EmergencyCall, | |
| EmergencyType, | |
| EmergencyUnit, | |
| Position, | |
| Severity, | |
| UnitType, | |
| ) | |
| # ---------------------------------------------------------------------------- | |
| # Geometry | |
| # ---------------------------------------------------------------------------- | |
| def calculate_distance(a: Position, b: Position) -> float: | |
| """Euclidean distance in km.""" | |
| return math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2) | |
| def calculate_eta(unit: EmergencyUnit, destination: Position) -> float: | |
| """ETA in minutes assuming constant speed.""" | |
| distance_km = calculate_distance(unit.position, destination) | |
| return (distance_km / unit.speed_kmh) * 60.0 | |
| # ---------------------------------------------------------------------------- | |
| # Capability lookups | |
| # ---------------------------------------------------------------------------- | |
| CAPABLE_UNITS = { | |
| EmergencyType.CARDIAC_ARREST: [UnitType.ALS_AMBULANCE, UnitType.BLS_AMBULANCE], | |
| EmergencyType.TRAUMA: [UnitType.ALS_AMBULANCE, UnitType.BLS_AMBULANCE], | |
| EmergencyType.STROKE: [UnitType.ALS_AMBULANCE, UnitType.BLS_AMBULANCE], | |
| EmergencyType.FIRE: [UnitType.FIRE_ENGINE], | |
| EmergencyType.BREATHING: [UnitType.ALS_AMBULANCE, UnitType.BLS_AMBULANCE], | |
| EmergencyType.MINOR_INJURY: [UnitType.BLS_AMBULANCE, UnitType.ALS_AMBULANCE], | |
| EmergencyType.MENTAL_HEALTH: [UnitType.POLICE, UnitType.ALS_AMBULANCE], | |
| } | |
| OPTIMAL_UNIT = { | |
| EmergencyType.CARDIAC_ARREST: UnitType.ALS_AMBULANCE, | |
| EmergencyType.TRAUMA: UnitType.ALS_AMBULANCE, | |
| EmergencyType.STROKE: UnitType.ALS_AMBULANCE, | |
| EmergencyType.FIRE: UnitType.FIRE_ENGINE, | |
| EmergencyType.BREATHING: UnitType.ALS_AMBULANCE, | |
| EmergencyType.MINOR_INJURY: UnitType.BLS_AMBULANCE, | |
| EmergencyType.MENTAL_HEALTH: UnitType.POLICE, | |
| } | |
| def get_capable_units(emergency_type: EmergencyType) -> List[UnitType]: | |
| return CAPABLE_UNITS[emergency_type] | |
| def get_optimal_unit(emergency_type: EmergencyType) -> UnitType: | |
| return OPTIMAL_UNIT[emergency_type] | |
| # ---------------------------------------------------------------------------- | |
| # Caller description templates | |
| # ---------------------------------------------------------------------------- | |
| CALLER_TEMPLATES = { | |
| EmergencyType.CARDIAC_ARREST: [ | |
| "Man collapsed on the sidewalk, he's not breathing! Please hurry!", | |
| "My husband just grabbed his chest and fell down, he's turning blue!", | |
| "Someone collapsed at the bus stop, no pulse, people are trying CPR!", | |
| "Elderly woman found unconscious in her apartment, not responding!", | |
| ], | |
| EmergencyType.TRAUMA: [ | |
| "Car accident on the main road, driver is bleeding from the head!", | |
| "Construction worker fell from scaffolding, conscious but can't move his legs!", | |
| "Two-wheeler hit a pedestrian, person on the road with a broken leg!", | |
| "Fight broke out, one person stabbed, lots of blood!", | |
| ], | |
| EmergencyType.STROKE: [ | |
| "My mother's face is drooping on one side and she can't speak properly!", | |
| "Colleague suddenly can't move his right arm, speech is slurred!", | |
| "Old man at the temple suddenly confused, can't walk straight!", | |
| ], | |
| EmergencyType.FIRE: [ | |
| "Kitchen fire in our apartment, smoke everywhere, we're on the 3rd floor!", | |
| "Warehouse on fire near the industrial area, flames visible from outside!", | |
| "Electrical fire in the office building, fire alarm going off!", | |
| "Grass fire spreading toward houses near the park!", | |
| ], | |
| EmergencyType.MINOR_INJURY: [ | |
| "I slipped on the stairs and twisted my ankle, it's swollen.", | |
| "Small cut on my hand from a knife, bleeding a bit but not too bad.", | |
| "Child fell off bicycle, scraped knee and elbow, crying but alert.", | |
| "Bumped my head on a low beam, small bump, feeling a bit dizzy.", | |
| ], | |
| EmergencyType.BREATHING: [ | |
| "My asthma is really bad, can't catch my breath, inhaler isn't working!", | |
| "Allergic reaction, my throat is swelling up, hard to breathe!", | |
| "Elderly patient with COPD, oxygen levels dropping, very short of breath!", | |
| ], | |
| EmergencyType.MENTAL_HEALTH: [ | |
| "My neighbor is threatening to hurt himself, he's very distressed!", | |
| "Person on the building ledge, seems very agitated, won't come down!", | |
| "Family member having a severe panic attack, can't calm down, hyperventilating!", | |
| ], | |
| } | |
| MISREPORT_TEMPLATES = { | |
| (EmergencyType.MENTAL_HEALTH, EmergencyType.CARDIAC_ARREST): [ | |
| "Someone is clutching their chest and can't breathe! I think it's a heart attack!", | |
| ], | |
| (EmergencyType.MINOR_INJURY, EmergencyType.TRAUMA): [ | |
| "Bad accident! Person is hurt, there's some blood!", | |
| ], | |
| (EmergencyType.BREATHING, EmergencyType.STROKE): [ | |
| "My father can't talk properly and is struggling, please come fast!", | |
| ], | |
| (EmergencyType.CARDIAC_ARREST, EmergencyType.MENTAL_HEALTH): [ | |
| "He's holding his chest and crying, very upset, hyperventilating!", | |
| ], | |
| (EmergencyType.TRAUMA, EmergencyType.MINOR_INJURY): [ | |
| "Someone fell off a ladder, looks like a small bump but they're complaining a lot.", | |
| ], | |
| } | |
| def generate_caller_text( | |
| true_type: EmergencyType, | |
| reported_type: EmergencyType, | |
| rng: np.random.RandomState, | |
| ) -> str: | |
| """Generate a caller description string from templates.""" | |
| if true_type != reported_type: | |
| key = (true_type, reported_type) | |
| if key in MISREPORT_TEMPLATES: | |
| return rng.choice(MISREPORT_TEMPLATES[key]) | |
| return rng.choice(CALLER_TEMPLATES[reported_type]) | |
| # ---------------------------------------------------------------------------- | |
| # Severity helpers | |
| # ---------------------------------------------------------------------------- | |
| def severity_from_int(s: int) -> Severity: | |
| return Severity(int(s)) | |