From c6e60fc88d7da713c9e748b0b24e04dac2063da6 Mon Sep 17 00:00:00 2001 From: itsrubberduck Date: Sun, 15 Feb 2026 10:49:41 +0100 Subject: [PATCH] feat(classroom): extend Scenario with emergency/abnormal fields Adds soulsOnBoard, fuelMinutes, positionDescription, holding pattern data (fix, inbound, turn, legTime, EFC), and crossing restriction data (two fixes with altitudes and restriction types) to the scenario generator. Co-Authored-By: Claude Opus 4.6 --- shared/learn/scenario.ts | 49 +++++++++++++++++++++++++++++++++++++++- shared/learn/types.ts | 18 +++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/shared/learn/scenario.ts b/shared/learn/scenario.ts index f54cbfa..130f672 100644 --- a/shared/learn/scenario.ts +++ b/shared/learn/scenario.ts @@ -373,6 +373,36 @@ export function createBaseScenario(): Scenario { ] const emergencyProblem = choice(emergencyProblems) const emergencyIntent = choice(emergencyIntentOptions) + + // Emergency / abnormal extensions + const soulsOnBoard = randInt(87, 224) + const soulsOnBoardWords = digitsToWords(soulsOnBoard.toString()) + const fuelMinutes = randInt(25, 180) + const fuelMinutesWords = minutesToWords(fuelMinutes) + const positionDistance = randInt(10, 60) + const positionDirection = choice(['north', 'south', 'east', 'west', 'northeast', 'northwest', 'southeast', 'southwest']) + const positionFix = choice([...airport.transitions, ...(destination.arrivalTransitions ?? destination.transitions)]) + const positionDescription = `${positionDistance} miles ${positionDirection} of ${positionFix}` + + const holdingFixOptions = [...airport.transitions, ...(destination.arrivalTransitions ?? destination.transitions)] + const holdingFix = choice(holdingFixOptions) + const holdingInbound = (randInt(0, 35) * 10).toString().padStart(3, '0') + const holdingTurn = choice(['right', 'left'] as const) + const holdingLegTime = choice(['1', '1.5', '2']) + const holdingEfcNow = new Date() + const holdingEfcMinutes = randInt(10, 45) + const efcTime = new Date(holdingEfcNow.getTime() + holdingEfcMinutes * 60000) + const holdingEfc = `${efcTime.getUTCHours().toString().padStart(2, '0')}${efcTime.getUTCMinutes().toString().padStart(2, '0')}` + + const crossingFixOptions = [...(destination.arrivalTransitions ?? destination.transitions)] + const crossingFix1 = crossingFixOptions[0] ?? 'LIPSO' + const crossingFix2 = crossingFixOptions.length > 1 ? crossingFixOptions[1] : 'VAMPS' + const crossingAlt1Raw = choice([8000, 9000, 10000, 11000]) + const crossingAlt2Raw = choice([5000, 6000, 7000]) + const crossingAlt1 = crossingAlt1Raw.toString() + const crossingAlt2 = crossingAlt2Raw.toString() + const crossingRestriction1 = choice(['at or above', 'at', 'at or below'] as const) + const now = new Date() const minute = Math.floor(now.getUTCMinutes() / 5) * 5 const timestamp = `${now.getUTCDate().toString().padStart(2, '0')}${now @@ -523,7 +553,24 @@ export function createBaseScenario(): Scenario { transLevel: airport.transLevel, remarks, emergencyProblem, - emergencyIntent + emergencyIntent, + soulsOnBoard, + soulsOnBoardWords, + fuelMinutes, + fuelMinutesWords, + positionDescription, + holdingFix, + holdingInbound, + holdingTurn, + holdingLegTime, + holdingEfc, + crossingFix1, + crossingAlt1, + crossingAlt1Words: altitudeToWords(crossingAlt1Raw), + crossingRestriction1, + crossingFix2, + crossingAlt2, + crossingAlt2Words: altitudeToWords(crossingAlt2Raw), } } diff --git a/shared/learn/types.ts b/shared/learn/types.ts index 81e38b0..f1e3064 100644 --- a/shared/learn/types.ts +++ b/shared/learn/types.ts @@ -140,6 +140,24 @@ export type Scenario = { remarks: string emergencyProblem: string emergencyIntent: string + // Emergency / abnormal extensions + soulsOnBoard: number + soulsOnBoardWords: string + fuelMinutes: number + fuelMinutesWords: string + positionDescription: string + holdingFix: string + holdingInbound: string + holdingTurn: string + holdingLegTime: string + holdingEfc: string + crossingFix1: string + crossingAlt1: string + crossingAlt1Words: string + crossingRestriction1: string + crossingFix2: string + crossingAlt2: string + crossingAlt2Words: string } export type LessonField = {