"""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"), CrewMember(crew_id="CR-1013", name="FA Herrera", role=CrewRole.FA, duty_hours_elapsed=9.0, duty_hours_limit=14.0, rest_hours_since_last=11.0, next_scheduled_flight="UA881", base_hub="ORD"), CrewMember(crew_id="CR-1014", name="FA Novak", role=CrewRole.FA, duty_hours_elapsed=7.5, duty_hours_limit=14.0, rest_hours_since_last=15.0, next_scheduled_flight="UA233", base_hub="ORD"), CrewMember(crew_id="CR-1015", name="FA Park", role=CrewRole.FA, duty_hours_elapsed=6.0, duty_hours_limit=14.0, rest_hours_since_last=17.0, next_scheduled_flight="UA094", base_hub="ORD"), CrewMember(crew_id="CR-1016", name="FO Santos", role=CrewRole.FIRST_OFFICER, duty_hours_elapsed=4.0, duty_hours_limit=14.0, rest_hours_since_last=20.0, next_scheduled_flight=None, base_hub="ORD"), # On-time flight crew CrewMember(crew_id="CR-1017", name="Capt. Walsh", role=CrewRole.CAPTAIN, duty_hours_elapsed=3.0, duty_hours_limit=14.0, rest_hours_since_last=22.0, next_scheduled_flight="UA1220", base_hub="ORD"), CrewMember(crew_id="CR-1018", name="FO Lindgren", role=CrewRole.FIRST_OFFICER, duty_hours_elapsed=3.0, duty_hours_limit=14.0, rest_hours_since_last=21.0, next_scheduled_flight="UA1220", base_hub="ORD"), CrewMember(crew_id="CR-1019", name="Capt. Rivera", role=CrewRole.CAPTAIN, duty_hours_elapsed=2.0, duty_hours_limit=14.0, rest_hours_since_last=24.0, next_scheduled_flight="UA788", base_hub="ORD"), CrewMember(crew_id="CR-1020", name="FO Cheng", role=CrewRole.FIRST_OFFICER, duty_hours_elapsed=2.0, duty_hours_limit=14.0, rest_hours_since_last=22.0, next_scheduled_flight="UA788", 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"), ]