init commit
This commit is contained in:
0
mcp_servers/data/scenarios/__init__.py
Normal file
0
mcp_servers/data/scenarios/__init__.py
Normal file
123
mcp_servers/data/scenarios/crew_swap_ewr.py
Normal file
123
mcp_servers/data/scenarios/crew_swap_ewr.py
Normal file
@@ -0,0 +1,123 @@
|
||||
"""Scenario: EWR Crew Duty Limit — complex Part 117 crew swap needed.
|
||||
|
||||
Captain hitting duty limit in 2h, backup crew needed. Tests Handover IMMEDIATE action.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from mcp_servers.data.models import (
|
||||
CrewMember,
|
||||
CrewRole,
|
||||
DelayCause,
|
||||
FlightData,
|
||||
FlightStatus,
|
||||
MELItem,
|
||||
MPStatus,
|
||||
Passenger,
|
||||
RebookingCase,
|
||||
)
|
||||
|
||||
SCENARIO_ID = "crew_swap_ewr"
|
||||
SCENARIO_NAME = "EWR Crew Duty Limit"
|
||||
SCENARIO_DESCRIPTION = (
|
||||
"Captain on UA2180 hitting Part 117 duty limit in 1h 45min. "
|
||||
"Delay cascading. 2 crew swaps needed."
|
||||
)
|
||||
SCENARIO_HUBS = ["EWR"]
|
||||
|
||||
FLIGHTS: list[FlightData] = [
|
||||
FlightData(
|
||||
flight_id="UA2180", origin="EWR", destination="LAX",
|
||||
scheduled_departure=datetime(2026, 4, 11, 20, 0, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 23, 30, tzinfo=timezone.utc),
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=90,
|
||||
delay_cause=DelayCause.CREW,
|
||||
aircraft_tail="N81201",
|
||||
gate="C72",
|
||||
crew_ids=["CR-3001", "CR-3002", "CR-3010", "CR-3011"],
|
||||
passenger_count=210,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA2244", origin="EWR", destination="ORD",
|
||||
scheduled_departure=datetime(2026, 4, 11, 20, 30, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 22, 0, tzinfo=timezone.utc),
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=45,
|
||||
delay_cause=DelayCause.LATE_AIRCRAFT,
|
||||
aircraft_tail="N81202",
|
||||
gate="C87",
|
||||
crew_ids=["CR-3003", "CR-3004", "CR-3012"],
|
||||
passenger_count=178,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA2310", origin="EWR", destination="SFO",
|
||||
scheduled_departure=datetime(2026, 4, 11, 21, 0, tzinfo=timezone.utc),
|
||||
scheduled_arrival=datetime(2026, 4, 12, 0, 15, tzinfo=timezone.utc),
|
||||
status=FlightStatus.ON_TIME,
|
||||
aircraft_tail="N81203",
|
||||
gate="C90",
|
||||
crew_ids=["CR-3005", "CR-3006"],
|
||||
passenger_count=195,
|
||||
),
|
||||
]
|
||||
|
||||
CREW: list[CrewMember] = [
|
||||
# UA2180 — captain at limit
|
||||
CrewMember(crew_id="CR-3001", name="Capt. Mitchell", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=12.25, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=10.0, next_scheduled_flight="UA2180", base_hub="EWR"),
|
||||
CrewMember(crew_id="CR-3002", name="FO Vasquez", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=11.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=11.0, next_scheduled_flight="UA2180", base_hub="EWR"),
|
||||
# UA2244
|
||||
CrewMember(crew_id="CR-3003", name="Capt. Ali", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=8.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=14.0, next_scheduled_flight="UA2244", base_hub="EWR"),
|
||||
CrewMember(crew_id="CR-3004", name="FO Johansson", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=8.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=13.0, next_scheduled_flight="UA2244", base_hub="EWR"),
|
||||
# UA2310
|
||||
CrewMember(crew_id="CR-3005", name="Capt. Reed", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=4.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=20.0, next_scheduled_flight="UA2310", base_hub="EWR"),
|
||||
CrewMember(crew_id="CR-3006", name="FO Torres", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=4.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=18.0, next_scheduled_flight="UA2310", base_hub="EWR"),
|
||||
# FAs
|
||||
CrewMember(crew_id="CR-3010", name="FA Collins", role=CrewRole.FA,
|
||||
duty_hours_elapsed=11.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=10.0, next_scheduled_flight="UA2180", base_hub="EWR"),
|
||||
CrewMember(crew_id="CR-3011", name="FA Yamamoto", role=CrewRole.FA,
|
||||
duty_hours_elapsed=11.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=10.0, next_scheduled_flight="UA2180", base_hub="EWR"),
|
||||
CrewMember(crew_id="CR-3012", name="FA Petrov", role=CrewRole.FA,
|
||||
duty_hours_elapsed=7.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=15.0, next_scheduled_flight="UA2244", base_hub="EWR"),
|
||||
# Backup crew
|
||||
CrewMember(crew_id="CR-8812", name="Capt. Foster", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=0.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=28.0, next_scheduled_flight=None, base_hub="EWR"),
|
||||
CrewMember(crew_id="CR-8813", name="FO Chang", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=0.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=24.0, next_scheduled_flight=None, base_hub="EWR"),
|
||||
]
|
||||
|
||||
CREW_NOTES: dict[str, list[str]] = {
|
||||
"UA2180": [
|
||||
"Capt. Mitchell duty limit approaching — 1h 45min remaining.",
|
||||
"If departure slips past 22:15 ET, mandatory crew swap per Part 117 §117.19.",
|
||||
"Backup Capt. Foster (CR-8812) on standby at crew lounge, cleared and rested.",
|
||||
"FO Vasquez also approaching limit but has buffer until 23:00.",
|
||||
],
|
||||
"UA2244": [
|
||||
"Delay is cascading from late inbound aircraft, not crew-related.",
|
||||
"Gate conflict resolved — moved to C87.",
|
||||
],
|
||||
}
|
||||
|
||||
MAINTENANCE: dict[str, list[MELItem]] = {}
|
||||
REBOOKINGS: list[RebookingCase] = []
|
||||
PASSENGERS: list[Passenger] = []
|
||||
117
mcp_servers/data/scenarios/maintenance_delay_sfo.py
Normal file
117
mcp_servers/data/scenarios/maintenance_delay_sfo.py
Normal file
@@ -0,0 +1,117 @@
|
||||
"""Scenario: SFO Maintenance Delay — MEL issue cascading to 2 flights.
|
||||
|
||||
Aircraft N82301 has APU MEL, delay cascading. Tests FCE maintenance-caused
|
||||
delay explanation and Handover MEL flag section.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from mcp_servers.data.models import (
|
||||
CrewMember,
|
||||
CrewRole,
|
||||
DelayCause,
|
||||
FlightData,
|
||||
FlightStatus,
|
||||
MELItem,
|
||||
MPStatus,
|
||||
Passenger,
|
||||
RebookingCase,
|
||||
)
|
||||
|
||||
SCENARIO_ID = "maintenance_delay_sfo"
|
||||
SCENARIO_NAME = "SFO MEL Issue"
|
||||
SCENARIO_DESCRIPTION = (
|
||||
"Aircraft N82301 APU inoperative (MEL). Delay cascading to 2 flights. "
|
||||
"Route restriction if divert needed."
|
||||
)
|
||||
SCENARIO_HUBS = ["SFO"]
|
||||
|
||||
FLIGHTS: list[FlightData] = [
|
||||
FlightData(
|
||||
flight_id="UA712", origin="SFO", destination="EWR",
|
||||
scheduled_departure=datetime(2026, 4, 11, 19, 0, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 12, 3, 30, tzinfo=timezone.utc),
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=65,
|
||||
delay_cause=DelayCause.MAINTENANCE,
|
||||
aircraft_tail="N82301",
|
||||
gate="G4",
|
||||
crew_ids=["CR-4001", "CR-4002", "CR-4010"],
|
||||
passenger_count=198,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA724", origin="SFO", destination="DEN",
|
||||
scheduled_departure=datetime(2026, 4, 11, 20, 30, tzinfo=timezone.utc),
|
||||
scheduled_arrival=datetime(2026, 4, 11, 23, 45, tzinfo=timezone.utc),
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=30,
|
||||
delay_cause=DelayCause.LATE_AIRCRAFT,
|
||||
aircraft_tail="N82302",
|
||||
gate="G8",
|
||||
crew_ids=["CR-4003", "CR-4004"],
|
||||
passenger_count=165,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA760", origin="SFO", destination="LAX",
|
||||
scheduled_departure=datetime(2026, 4, 11, 18, 30, tzinfo=timezone.utc),
|
||||
scheduled_arrival=datetime(2026, 4, 11, 19, 45, tzinfo=timezone.utc),
|
||||
status=FlightStatus.ON_TIME,
|
||||
aircraft_tail="N82303",
|
||||
gate="G12",
|
||||
crew_ids=["CR-4005", "CR-4006"],
|
||||
passenger_count=140,
|
||||
),
|
||||
]
|
||||
|
||||
CREW: list[CrewMember] = [
|
||||
CrewMember(crew_id="CR-4001", name="Capt. Novak", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=6.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=16.0, next_scheduled_flight="UA712", base_hub="SFO"),
|
||||
CrewMember(crew_id="CR-4002", name="FO Agrawal", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=6.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=15.0, next_scheduled_flight="UA712", base_hub="SFO"),
|
||||
CrewMember(crew_id="CR-4003", name="Capt. Svensson", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=5.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=18.0, next_scheduled_flight="UA724", base_hub="SFO"),
|
||||
CrewMember(crew_id="CR-4004", name="FO Rivera", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=5.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=17.0, next_scheduled_flight="UA724", base_hub="SFO"),
|
||||
CrewMember(crew_id="CR-4005", name="Capt. Wallace", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=3.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=22.0, next_scheduled_flight="UA760", base_hub="SFO"),
|
||||
CrewMember(crew_id="CR-4006", name="FO Zhao", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=3.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=20.0, next_scheduled_flight="UA760", base_hub="SFO"),
|
||||
CrewMember(crew_id="CR-4010", name="FA Douglas", role=CrewRole.FA,
|
||||
duty_hours_elapsed=5.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=16.0, next_scheduled_flight="UA712", base_hub="SFO"),
|
||||
]
|
||||
|
||||
CREW_NOTES: dict[str, list[str]] = {
|
||||
"UA712": [
|
||||
"MEL item #47-3: APU inoperative on N82301.",
|
||||
"Maintenance team inspecting — estimated release in 45 min.",
|
||||
"APU MEL restricts routing to airports with ground power only.",
|
||||
"Current SFO→EWR route unaffected, but flag if divert to BDL or HPN needed.",
|
||||
],
|
||||
"UA724": [
|
||||
"Delay cascading from UA712 — shared gate G8 not available until UA712 pushes.",
|
||||
],
|
||||
}
|
||||
|
||||
MAINTENANCE: dict[str, list[MELItem]] = {
|
||||
"N82301": [
|
||||
MELItem(
|
||||
mel_id="MEL-SFO-473",
|
||||
aircraft_tail="N82301",
|
||||
system="APU",
|
||||
description="Auxiliary Power Unit inoperative. Aircraft requires external ground power for engine start and gate operations.",
|
||||
restriction="Routing restricted to airports with ground power availability. Cannot divert to airports without ground power units (e.g., BDL, HPN).",
|
||||
expires=datetime(2026, 4, 18, 0, 0, tzinfo=timezone.utc),
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
REBOOKINGS: list[RebookingCase] = []
|
||||
PASSENGERS: list[Passenger] = []
|
||||
85
mcp_servers/data/scenarios/manager.py
Normal file
85
mcp_servers/data/scenarios/manager.py
Normal file
@@ -0,0 +1,85 @@
|
||||
"""Scenario manager — loads and switches between operational scenarios."""
|
||||
|
||||
from importlib import import_module
|
||||
from typing import Any
|
||||
|
||||
SCENARIO_MODULES = {
|
||||
"normal_ops": "mcp_servers.data.scenarios.normal_ops",
|
||||
"weather_disruption_ord": "mcp_servers.data.scenarios.weather_disruption_ord",
|
||||
"maintenance_delay_sfo": "mcp_servers.data.scenarios.maintenance_delay_sfo",
|
||||
"crew_swap_ewr": "mcp_servers.data.scenarios.crew_swap_ewr",
|
||||
}
|
||||
|
||||
|
||||
class ScenarioManager:
|
||||
"""Manages the active scenario. Singleton — all MCP servers share one instance."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._active_id: str = "weather_disruption_ord"
|
||||
self._cache: dict[str, Any] = {}
|
||||
|
||||
@property
|
||||
def active_id(self) -> str:
|
||||
return self._active_id
|
||||
|
||||
def set_active(self, scenario_id: str) -> dict:
|
||||
if scenario_id not in SCENARIO_MODULES:
|
||||
raise ValueError(
|
||||
f"Unknown scenario: {scenario_id}. "
|
||||
f"Available: {', '.join(SCENARIO_MODULES.keys())}"
|
||||
)
|
||||
self._active_id = scenario_id
|
||||
return self.get_metadata()
|
||||
|
||||
def get_metadata(self, scenario_id: str | None = None) -> dict:
|
||||
mod = self._load(scenario_id or self._active_id)
|
||||
return {
|
||||
"scenario_id": mod.SCENARIO_ID,
|
||||
"name": mod.SCENARIO_NAME,
|
||||
"description": mod.SCENARIO_DESCRIPTION,
|
||||
"hubs": mod.SCENARIO_HUBS,
|
||||
"flight_count": len(mod.FLIGHTS),
|
||||
"disrupted_flights": sum(
|
||||
1 for f in mod.FLIGHTS if f.status != "ON_TIME"
|
||||
),
|
||||
}
|
||||
|
||||
def list_scenarios(self) -> list[dict]:
|
||||
return [self.get_metadata(sid) for sid in SCENARIO_MODULES]
|
||||
|
||||
def _load(self, scenario_id: str) -> Any:
|
||||
if scenario_id not in self._cache:
|
||||
self._cache[scenario_id] = import_module(SCENARIO_MODULES[scenario_id])
|
||||
return self._cache[scenario_id]
|
||||
|
||||
@property
|
||||
def _module(self) -> Any:
|
||||
return self._load(self._active_id)
|
||||
|
||||
@property
|
||||
def flights(self):
|
||||
return self._module.FLIGHTS
|
||||
|
||||
@property
|
||||
def crew(self):
|
||||
return self._module.CREW
|
||||
|
||||
@property
|
||||
def crew_notes(self) -> dict[str, list[str]]:
|
||||
return self._module.CREW_NOTES
|
||||
|
||||
@property
|
||||
def maintenance(self):
|
||||
return self._module.MAINTENANCE
|
||||
|
||||
@property
|
||||
def rebookings(self):
|
||||
return self._module.REBOOKINGS
|
||||
|
||||
@property
|
||||
def passengers(self):
|
||||
return self._module.PASSENGERS
|
||||
|
||||
|
||||
# Singleton
|
||||
scenario_manager = ScenarioManager()
|
||||
72
mcp_servers/data/scenarios/normal_ops.py
Normal file
72
mcp_servers/data/scenarios/normal_ops.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""Scenario: Normal Operations — all flights on time, clear weather, full crew.
|
||||
|
||||
Baseline scenario. Agents should produce minimal/calm output.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from mcp_servers.data.models import (
|
||||
CrewMember,
|
||||
CrewRole,
|
||||
FlightData,
|
||||
FlightStatus,
|
||||
MPStatus,
|
||||
Passenger,
|
||||
RebookingCase,
|
||||
MELItem,
|
||||
)
|
||||
|
||||
SCENARIO_ID = "normal_ops"
|
||||
SCENARIO_NAME = "Normal Operations"
|
||||
SCENARIO_DESCRIPTION = "All flights on time at ORD. Clear weather. No disruptions."
|
||||
SCENARIO_HUBS = ["ORD"]
|
||||
|
||||
FLIGHTS: list[FlightData] = [
|
||||
FlightData(
|
||||
flight_id="UA1440", origin="ORD", destination="SFO",
|
||||
scheduled_departure=datetime(2026, 4, 11, 18, 0, tzinfo=timezone.utc),
|
||||
scheduled_arrival=datetime(2026, 4, 11, 20, 30, tzinfo=timezone.utc),
|
||||
status=FlightStatus.ON_TIME, aircraft_tail="N79001", gate="H10",
|
||||
crew_ids=["CR-2001", "CR-2002"], passenger_count=175,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA1552", origin="ORD", destination="EWR",
|
||||
scheduled_departure=datetime(2026, 4, 11, 18, 30, tzinfo=timezone.utc),
|
||||
scheduled_arrival=datetime(2026, 4, 11, 21, 45, tzinfo=timezone.utc),
|
||||
status=FlightStatus.ON_TIME, aircraft_tail="N79002", gate="B12",
|
||||
crew_ids=["CR-2003", "CR-2004"], passenger_count=190,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA1678", origin="ORD", destination="DEN",
|
||||
scheduled_departure=datetime(2026, 4, 11, 19, 0, tzinfo=timezone.utc),
|
||||
scheduled_arrival=datetime(2026, 4, 11, 20, 30, tzinfo=timezone.utc),
|
||||
status=FlightStatus.ON_TIME, aircraft_tail="N79003", gate="C8",
|
||||
crew_ids=["CR-2005", "CR-2006"], passenger_count=160,
|
||||
),
|
||||
]
|
||||
|
||||
CREW: list[CrewMember] = [
|
||||
CrewMember(crew_id="CR-2001", name="Capt. Hayes", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=4.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=18.0, next_scheduled_flight="UA1440", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-2002", name="FO Park", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=4.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=16.0, next_scheduled_flight="UA1440", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-2003", name="Capt. Lewis", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=5.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=15.0, next_scheduled_flight="UA1552", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-2004", name="FO Sharma", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=5.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=14.0, next_scheduled_flight="UA1552", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-2005", name="Capt. Brown", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=3.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=20.0, next_scheduled_flight="UA1678", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-2006", name="FO Nguyen", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=3.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=19.0, next_scheduled_flight="UA1678", base_hub="ORD"),
|
||||
]
|
||||
|
||||
CREW_NOTES: dict[str, list[str]] = {}
|
||||
MAINTENANCE: dict[str, list[MELItem]] = {}
|
||||
REBOOKINGS: list[RebookingCase] = []
|
||||
PASSENGERS: list[Passenger] = []
|
||||
281
mcp_servers/data/scenarios/weather_disruption_ord.py
Normal file
281
mcp_servers/data/scenarios/weather_disruption_ord.py
Normal file
@@ -0,0 +1,281 @@
|
||||
"""Scenario: ORD Thunderstorms — active disruption at Chicago O'Hare.
|
||||
|
||||
Thunderstorm line causing GDP, 4 flights delayed, 1 cancelled.
|
||||
Tests FCE multi-flight notifications and Handover weather risk section.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from mcp_servers.data.models import (
|
||||
CrewMember,
|
||||
CrewRole,
|
||||
DelayCause,
|
||||
FlightData,
|
||||
FlightStatus,
|
||||
MELItem,
|
||||
MPStatus,
|
||||
Passenger,
|
||||
RebookingCase,
|
||||
)
|
||||
|
||||
SCENARIO_ID = "weather_disruption_ord"
|
||||
SCENARIO_NAME = "ORD Thunderstorms"
|
||||
SCENARIO_DESCRIPTION = (
|
||||
"Active thunderstorm line at ORD. GDP in effect. "
|
||||
"4 delays, 1 cancellation. 47 passengers need rebooking."
|
||||
)
|
||||
SCENARIO_HUBS = ["ORD"]
|
||||
|
||||
# --- Flights ---
|
||||
|
||||
FLIGHTS: list[FlightData] = [
|
||||
# Delayed flights
|
||||
FlightData(
|
||||
flight_id="UA432",
|
||||
origin="ORD", destination="SFO",
|
||||
scheduled_departure=datetime(2026, 4, 11, 17, 45, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 20, 15, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=55,
|
||||
delay_cause=DelayCause.WEATHER,
|
||||
aircraft_tail="N78501",
|
||||
gate="H14",
|
||||
inbound_flight="UA219",
|
||||
crew_ids=["CR-1001", "CR-1002", "CR-1010", "CR-1011"],
|
||||
passenger_count=186,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA881",
|
||||
origin="ORD", destination="LAX",
|
||||
scheduled_departure=datetime(2026, 4, 11, 18, 30, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 21, 0, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=40,
|
||||
delay_cause=DelayCause.WEATHER,
|
||||
aircraft_tail="N78502",
|
||||
gate="H22",
|
||||
crew_ids=["CR-1003", "CR-1004", "CR-1012", "CR-1013"],
|
||||
passenger_count=204,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA233",
|
||||
origin="ORD", destination="DEN",
|
||||
scheduled_departure=datetime(2026, 4, 11, 18, 0, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 19, 45, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=70,
|
||||
delay_cause=DelayCause.WEATHER,
|
||||
aircraft_tail="N78503",
|
||||
gate="C12",
|
||||
crew_ids=["CR-1005", "CR-1006", "CR-1014"],
|
||||
passenger_count=152,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA094",
|
||||
origin="ORD", destination="EWR",
|
||||
scheduled_departure=datetime(2026, 4, 11, 17, 15, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 20, 30, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.DELAYED,
|
||||
delay_minutes=35,
|
||||
delay_cause=DelayCause.WEATHER,
|
||||
aircraft_tail="N78504",
|
||||
gate="B8",
|
||||
crew_ids=["CR-1007", "CR-1008", "CR-1015"],
|
||||
passenger_count=178,
|
||||
),
|
||||
# Cancelled flight
|
||||
FlightData(
|
||||
flight_id="UA517",
|
||||
origin="ORD", destination="IAH",
|
||||
scheduled_departure=datetime(2026, 4, 11, 19, 0, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 21, 30, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.CANCELLED,
|
||||
delay_minutes=0,
|
||||
delay_cause=DelayCause.WEATHER,
|
||||
aircraft_tail="N78505",
|
||||
gate="C18",
|
||||
crew_ids=["CR-1009", "CR-1016"],
|
||||
passenger_count=47,
|
||||
),
|
||||
# On-time flights (normal ops happening alongside disruption)
|
||||
FlightData(
|
||||
flight_id="UA1220",
|
||||
origin="ORD", destination="IAD",
|
||||
scheduled_departure=datetime(2026, 4, 11, 20, 30, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 23, 15, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.ON_TIME,
|
||||
delay_minutes=0,
|
||||
delay_cause=None,
|
||||
aircraft_tail="N78506",
|
||||
gate="B15",
|
||||
crew_ids=["CR-1017", "CR-1018"],
|
||||
passenger_count=145,
|
||||
),
|
||||
FlightData(
|
||||
flight_id="UA788",
|
||||
origin="ORD", destination="SFO",
|
||||
scheduled_departure=datetime(2026, 4, 11, 21, 0, tzinfo=timezone.utc),
|
||||
actual_departure=None,
|
||||
scheduled_arrival=datetime(2026, 4, 11, 23, 30, tzinfo=timezone.utc),
|
||||
actual_arrival=None,
|
||||
status=FlightStatus.ON_TIME,
|
||||
delay_minutes=0,
|
||||
delay_cause=None,
|
||||
aircraft_tail="N78507",
|
||||
gate="H18",
|
||||
crew_ids=["CR-1019", "CR-1020"],
|
||||
passenger_count=192,
|
||||
),
|
||||
]
|
||||
|
||||
# --- Crew ---
|
||||
|
||||
CREW: list[CrewMember] = [
|
||||
# UA432 crew
|
||||
CrewMember(crew_id="CR-1001", name="Capt. Rodriguez", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=10.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=12.0, next_scheduled_flight="UA432", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-1002", name="FO Chen", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=10.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=11.0, next_scheduled_flight="UA432", base_hub="ORD"),
|
||||
# UA881 crew — captain approaching duty limit
|
||||
CrewMember(crew_id="CR-1003", name="Capt. Williams", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=12.25, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=10.0, next_scheduled_flight="UA881", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-1004", name="FO Patel", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=9.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=14.0, next_scheduled_flight="UA881", base_hub="ORD"),
|
||||
# UA233 crew
|
||||
CrewMember(crew_id="CR-1005", name="Capt. Johnson", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=8.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=16.0, next_scheduled_flight="UA233", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-1006", name="FO Kim", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=7.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=15.0, next_scheduled_flight="UA233", base_hub="ORD"),
|
||||
# UA094 crew
|
||||
CrewMember(crew_id="CR-1007", name="Capt. Davis", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=6.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=18.0, next_scheduled_flight="UA094", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-1008", name="FO Martinez", role=CrewRole.FIRST_OFFICER,
|
||||
duty_hours_elapsed=6.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=17.0, next_scheduled_flight="UA094", base_hub="ORD"),
|
||||
# UA517 crew (cancelled flight — available for reassignment)
|
||||
CrewMember(crew_id="CR-1009", name="Capt. Thompson", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=4.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=20.0, next_scheduled_flight=None, base_hub="ORD"),
|
||||
# Flight attendants
|
||||
CrewMember(crew_id="CR-1010", name="FA Brooks", role=CrewRole.FA,
|
||||
duty_hours_elapsed=10.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=12.0, next_scheduled_flight="UA432", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-1011", name="FA Lee", role=CrewRole.FA,
|
||||
duty_hours_elapsed=10.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=13.0, next_scheduled_flight="UA432", base_hub="ORD"),
|
||||
CrewMember(crew_id="CR-1012", name="FA Garcia", role=CrewRole.FA,
|
||||
duty_hours_elapsed=11.5, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=10.0, next_scheduled_flight="UA881", base_hub="ORD"),
|
||||
# Backup crew
|
||||
CrewMember(crew_id="CR-4421", name="Capt. Okafor", role=CrewRole.CAPTAIN,
|
||||
duty_hours_elapsed=0.0, duty_hours_limit=14.0,
|
||||
rest_hours_since_last=24.0, next_scheduled_flight=None, base_hub="ORD"),
|
||||
]
|
||||
|
||||
# --- Crew Notes ---
|
||||
|
||||
CREW_NOTES: dict[str, list[str]] = {
|
||||
"UA432": [
|
||||
"Ground stop at ORD — thunderstorm line moving NE across field.",
|
||||
"Inbound aircraft N78501 on ground, boarding paused at gate H14.",
|
||||
"Fresh crew on board, catering complete. Ready to board on release.",
|
||||
"Gate hold — no gate change expected per ops.",
|
||||
],
|
||||
"UA881": [
|
||||
"Capt. Williams approaching duty limit — monitor closely.",
|
||||
"If departure slips past 22:15 CT, mandatory crew swap required.",
|
||||
"Backup crew CR-4421 (Capt. Okafor) on standby, cleared and rested.",
|
||||
],
|
||||
"UA233": [
|
||||
"Extended delay due to weather at ORD and congestion at DEN.",
|
||||
"8 connecting passengers with tight connections at DEN — rebooking may be needed.",
|
||||
],
|
||||
"UA094": [
|
||||
"Moderate delay. EWR reporting clear conditions, delay is ORD-side only.",
|
||||
],
|
||||
"UA517": [
|
||||
"CANCELLED — thunderstorm forecast through departure window.",
|
||||
"47 passengers need rebooking. 8 Global Services pax — priority handling.",
|
||||
"Rebooking options loaded in system — supervisor approval pending.",
|
||||
],
|
||||
}
|
||||
|
||||
# --- Maintenance ---
|
||||
|
||||
MAINTENANCE: dict[str, list[MELItem]] = {
|
||||
"N78501": [
|
||||
MELItem(
|
||||
mel_id="MEL-ORD-001",
|
||||
aircraft_tail="N78501",
|
||||
system="WEATHER_RADAR",
|
||||
description="Weather radar intermittent — functions normally after reset cycle.",
|
||||
restriction=None,
|
||||
expires=datetime(2026, 4, 15, 0, 0, tzinfo=timezone.utc),
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
# --- Passengers needing rebooking (from cancelled UA517) ---
|
||||
|
||||
REBOOKINGS: list[RebookingCase] = [
|
||||
RebookingCase(pax_id="PAX-00341", name="J. Morrison",
|
||||
original_flight="UA517", mileage_plus_status=MPStatus.GLOBAL_SERVICES,
|
||||
destination="IAH", next_available="UA519", urgency="HIGH"),
|
||||
RebookingCase(pax_id="PAX-00342", name="S. Nakamura",
|
||||
original_flight="UA517", mileage_plus_status=MPStatus.GLOBAL_SERVICES,
|
||||
destination="IAH", next_available="UA519", urgency="HIGH"),
|
||||
RebookingCase(pax_id="PAX-00355", name="R. Okonkwo",
|
||||
original_flight="UA517", mileage_plus_status=MPStatus.K1,
|
||||
destination="IAH", next_available="UA519", urgency="HIGH"),
|
||||
RebookingCase(pax_id="PAX-00360", name="M. Fernandez",
|
||||
original_flight="UA517", mileage_plus_status=MPStatus.PLATINUM,
|
||||
destination="IAH", next_available=None, urgency="MEDIUM"),
|
||||
RebookingCase(pax_id="PAX-00371", name="K. Singh",
|
||||
original_flight="UA517", mileage_plus_status=MPStatus.GOLD,
|
||||
destination="IAH", next_available=None, urgency="MEDIUM"),
|
||||
RebookingCase(pax_id="PAX-00380", name="L. Anderson",
|
||||
original_flight="UA517", mileage_plus_status=MPStatus.GENERAL,
|
||||
destination="IAH", next_available=None, urgency="LOW"),
|
||||
]
|
||||
|
||||
# --- Passengers on disrupted flights (sample) ---
|
||||
|
||||
PASSENGERS: list[Passenger] = [
|
||||
# UA432 passengers
|
||||
Passenger(pax_id="PAX-10001", name="A. Kowalski",
|
||||
mileage_plus_status=MPStatus.GLOBAL_SERVICES, flight_id="UA432",
|
||||
destination="SFO", connection_flight="UA1892",
|
||||
connection_deadline=datetime(2026, 4, 11, 21, 30, tzinfo=timezone.utc)),
|
||||
Passenger(pax_id="PAX-10002", name="B. Tanaka",
|
||||
mileage_plus_status=MPStatus.K1, flight_id="UA432",
|
||||
destination="SFO"),
|
||||
Passenger(pax_id="PAX-10003", name="C. Dubois",
|
||||
mileage_plus_status=MPStatus.GENERAL, flight_id="UA432",
|
||||
destination="SFO", special_needs=["WCHR"]),
|
||||
# UA517 passengers (cancelled)
|
||||
Passenger(pax_id="PAX-00341", name="J. Morrison",
|
||||
mileage_plus_status=MPStatus.GLOBAL_SERVICES, flight_id="UA517",
|
||||
destination="IAH"),
|
||||
Passenger(pax_id="PAX-00342", name="S. Nakamura",
|
||||
mileage_plus_status=MPStatus.GLOBAL_SERVICES, flight_id="UA517",
|
||||
destination="IAH"),
|
||||
]
|
||||
Reference in New Issue
Block a user