"""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] = []