mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-01 14:16:05 +08:00
merge
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fa09610c1ef12eed0ca70878896f5873308ba1ab34b264d0d04d4eadafcfb89a
|
||||
size 2146902
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:40b406d3b31ded0eff41024e33b94d018e1449a0411ade3237e85b98002747ef
|
||||
size 2249127
|
||||
3
public/img/learn/missions/full-flight/briefing-hero.png
Normal file
3
public/img/learn/missions/full-flight/briefing-hero.png
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b0284350316cb391bec945b26d754c59fa378cd79b7d5d977c2498b8537121f2
|
||||
size 2005788
|
||||
3
public/img/learn/missions/full-flight/briefing-route.png
Normal file
3
public/img/learn/missions/full-flight/briefing-route.png
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ac94774ef63657715069069446592220163ae318eef81163e8a1fb34f2c8302a
|
||||
size 2186393
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:188c73efbd184f9a0f1cf4726e0ec62ba61cc482fd2867f70346dd2e86c5bae9
|
||||
size 2260863
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createBaseScenario, createScenarioSeries, formatTemp } from '~~/shared/learn/scenario'
|
||||
import type { ModuleDef } from '~~/shared/learn/types'
|
||||
import type { ModuleDef, Scenario } from '~~/shared/learn/types'
|
||||
|
||||
function gradientArt(colors: string[]): string {
|
||||
const stops = colors
|
||||
@@ -2194,6 +2194,18 @@ const decisionTreeLessons = [
|
||||
|
||||
const fullFlightScenario = createScenarioSeries()
|
||||
|
||||
export function seedFullFlightScenario(scenario: Scenario | null) {
|
||||
if (scenario) {
|
||||
fullFlightScenario.setScenario(scenario)
|
||||
} else {
|
||||
fullFlightScenario.setScenario(null)
|
||||
}
|
||||
}
|
||||
|
||||
export function peekFullFlightScenario(): Scenario | null {
|
||||
return fullFlightScenario.peek()
|
||||
}
|
||||
|
||||
const makeFullFlightGenerator = (reset = false) => () => {
|
||||
if (reset) {
|
||||
fullFlightScenario.reset()
|
||||
@@ -2950,6 +2962,12 @@ export const learnModules: ModuleDef[] = [
|
||||
id: 'full-flight',
|
||||
title: 'Full Flight · Gate to Gate',
|
||||
subtitle: 'One linked scenario from clearance to taxi-in',
|
||||
art: '/img/learn/modules/img6.jpeg',
|
||||
lessons: fullFlightLessons,
|
||||
meta: {
|
||||
flightPlan: true,
|
||||
briefingArt: '/img/learn/missions/full-flight/briefing-hero.png'
|
||||
}
|
||||
art: '/img/learn/modules/img12.jpeg',
|
||||
lessons: fullFlightLessons
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ function generateSquawk(): string {
|
||||
return code
|
||||
}
|
||||
|
||||
function digitsToWords(value: string): string {
|
||||
export function digitsToWords(value: string): string {
|
||||
return value
|
||||
.split('')
|
||||
.map(char => atcNumberWords[char] ?? char)
|
||||
@@ -207,7 +207,7 @@ function digitsToWords(value: string): string {
|
||||
.trim()
|
||||
}
|
||||
|
||||
function lettersToNato(value: string): string {
|
||||
export function lettersToNato(value: string): string {
|
||||
return value
|
||||
.toUpperCase()
|
||||
.split('')
|
||||
@@ -215,7 +215,7 @@ function lettersToNato(value: string): string {
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
function runwayToWords(runway: string): string {
|
||||
export function runwayToWords(runway: string): string {
|
||||
const digits = runway.replace(/[^0-9]/g, '').padStart(2, '0')
|
||||
const suffix = runway.replace(/[0-9]/g, '')
|
||||
const base = digits
|
||||
@@ -274,17 +274,17 @@ function visibilityToWords(vis: string): string {
|
||||
return vis
|
||||
}
|
||||
|
||||
function minutesToWords(minutes: number): string {
|
||||
export function minutesToWords(minutes: number): string {
|
||||
const value = Math.max(1, Math.round(minutes))
|
||||
const unit = value === 1 ? 'minute' : 'minutes'
|
||||
return `${digitsToWords(value.toString())} ${unit}`
|
||||
}
|
||||
|
||||
function speedToWords(speed: number): string {
|
||||
export function speedToWords(speed: number): string {
|
||||
return `${digitsToWords(Math.round(speed).toString())} knots`
|
||||
}
|
||||
|
||||
function altitudeToWords(value: number): string {
|
||||
export function altitudeToWords(value: number): string {
|
||||
const thousands = Math.floor(value / 1000)
|
||||
const remainder = value % 1000
|
||||
let words = thousands ? `${digitsToWords(thousands.toString())} thousand` : ''
|
||||
@@ -491,18 +491,38 @@ function cloneScenario(scenario: Scenario): Scenario {
|
||||
return JSON.parse(JSON.stringify(scenario)) as Scenario
|
||||
}
|
||||
|
||||
export type ScenarioGenerator = (() => Scenario) & { reset: () => void }
|
||||
export type ScenarioGenerator = (() => Scenario) & {
|
||||
reset: () => void
|
||||
setScenario: (scenario: Scenario | null) => void
|
||||
peek: () => Scenario | null
|
||||
}
|
||||
|
||||
export function createScenarioSeries(): ScenarioGenerator {
|
||||
export function createScenarioSeries(source?: () => Scenario): ScenarioGenerator {
|
||||
let cached: Scenario | null = null
|
||||
const generator = () => {
|
||||
let override: Scenario | null = null
|
||||
const resolveSource = () => {
|
||||
if (override) {
|
||||
return cloneScenario(override)
|
||||
}
|
||||
return source ? source() : createBaseScenario()
|
||||
}
|
||||
const generator = (() => {
|
||||
if (!cached) {
|
||||
cached = createBaseScenario()
|
||||
cached = resolveSource()
|
||||
}
|
||||
return cloneScenario(cached)
|
||||
}
|
||||
}) as ScenarioGenerator
|
||||
generator.reset = () => {
|
||||
cached = null
|
||||
cached = override ? cloneScenario(override) : null
|
||||
}
|
||||
generator.setScenario = (scenario: Scenario | null) => {
|
||||
override = scenario ? cloneScenario(scenario) : null
|
||||
cached = override ? cloneScenario(override) : null
|
||||
}
|
||||
generator.peek = () => {
|
||||
if (cached) return cloneScenario(cached)
|
||||
if (override) return cloneScenario(override)
|
||||
return null
|
||||
}
|
||||
return generator
|
||||
}
|
||||
|
||||
@@ -161,10 +161,16 @@ export type Lesson = {
|
||||
generate: () => Scenario
|
||||
}
|
||||
|
||||
export type ModuleMeta = {
|
||||
flightPlan?: boolean
|
||||
briefingArt?: string
|
||||
}
|
||||
|
||||
export type ModuleDef = {
|
||||
id: string
|
||||
title: string
|
||||
subtitle: string
|
||||
art: string
|
||||
lessons: Lesson[]
|
||||
meta?: ModuleMeta
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user