feat: scenario picker, flow chaining UX, reliable frequency checks

Scenario picker & completion:
- Login → scenario selection screen with complete chains + individual phases
- Completion screen with "fly again / try opposite / back to scenarios"
- Scenario.airport ('dep'|'arr') drives which airport frequencies to fetch;
  arrival scenarios (vfr-arrival, circuit-landing, taxi-in) use arr ICAO

Backend session integration:
- createSession forwards no_chain; response carries active_flow + session_complete
- Pass all six airport frequency variables to session so every chained flow
  has the real airport values from creation
- fetchAirportFrequencies now runs before session creation so resolved
  frequencies are included in backendVariables

Wrong-frequency check:
- airportFreqMap computed (from airportFrequencies, always up-to-date)
  used as primary source in expectedFrequencyForState — immune to flow
  snapshot switches
- setActiveFlow called when response.active_flow changes so local engine
  cursor moves to the correct flow's states after a chain
- Wrong-freq ATC reply appended to communication log (offSchema entry)

Engine fixes (communicationsEngine.ts):
- patchVariables / patchFlags: write directly to the internal reactive
  store, bypassing readonly(ref) which silently blocked all (vars as any)
  .value[k] = v mutations
- appendLogEntry: push ATC speech (and wrong-freq replies) into comm log
- ATC controller_say_rendered appended to comm log after every transmission
This commit is contained in:
leubeem
2026-06-08 13:03:55 +02:00
parent f334332635
commit 59e35aa087
3 changed files with 405 additions and 45 deletions

View File

@@ -10,6 +10,7 @@ export interface RadioSessionResponse {
export interface RadioTransmitResponse {
session_id: string
next_state_id: string
active_flow: string
controller_say_template: string | null
controller_say_rendered: string | null
expected_pilot_template: string | null
@@ -19,6 +20,8 @@ export interface RadioTransmitResponse {
fallback_used: boolean
fallback_reason: string | null
auto_advanced_states?: string[]
/** True when the full chain is done — show the completion screen. */
session_complete?: boolean
}
export function useRadioBackend() {
@@ -31,10 +34,11 @@ export function useRadioBackend() {
async function createSession(
flowSlug: string,
variables?: Record<string, any>,
noChain: boolean = false,
): Promise<RadioSessionResponse> {
return await $fetch<RadioSessionResponse>(`${baseUrl()}/api/radio/session`, {
method: 'POST',
body: { flow_slug: flowSlug, variables: variables ?? null },
body: { flow_slug: flowSlug, variables: variables ?? null, no_chain: noChain },
})
}