mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-11 20:15:32 +08:00
feat(websim): browser A320 cockpit to test /live-atc without MSFS (WIP)
Flight model (ground/air physics, SELECTED/NAV/APPR/AUTOLAND autopilot with STAR sequencing and ILS capture), bridge client that feeds the existing /api/bridge/* endpoints so /live-atc can't tell it apart from a real bridge, and the cockpit UI (PFD reuse, FCU, radio panel, Leaflet ND, three.js exterior, spawn presets at EDDF/EDDS). Design doc: docs/plans/2026-07-16-websim-design.md. Also adds a local-dev-only auto-login (/dev-login, server/api/dev/login.post.ts) that bypasses the invite-only login and MongoDB entirely via a fixed in-memory user, so require-auth pages are reachable for local testing even when the dev DB is unreachable. Hard-disabled outside development. Status: unit tests green (yarn test) and typecheck clean (yarn typecheck). Browser walkthrough of the actual cockpit (flying a preset, confirming telemetry reaches /live-atc) is not yet done — picking up from a fresh dev server + /dev-login?redirect=/flightlab/websim confirmed the spawn screen renders past auth, but full instrument/map/exterior verification is still outstanding. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
35
tests/shared/geo.test.ts
Normal file
35
tests/shared/geo.test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { angleDiffDeg, bearingDeg, destinationPoint, distanceNm, normalizeHeading } from '../../shared/utils/geo.ts'
|
||||
|
||||
test('normalizeHeading wraps into [0, 360)', () => {
|
||||
assert.equal(normalizeHeading(370), 10)
|
||||
assert.equal(normalizeHeading(-10), 350)
|
||||
assert.equal(normalizeHeading(0), 0)
|
||||
})
|
||||
|
||||
test('angleDiffDeg returns the shortest signed turn', () => {
|
||||
assert.equal(angleDiffDeg(350, 10), 20)
|
||||
assert.equal(angleDiffDeg(10, 350), -20)
|
||||
assert.equal(Math.abs(angleDiffDeg(0, 180)), 180) // antipodal turn: sign is ambiguous
|
||||
})
|
||||
|
||||
test('destinationPoint then distanceNm round-trips the requested distance', () => {
|
||||
const start = { lat: 50.04, lon: 8.57 }
|
||||
const dest = destinationPoint(start.lat, start.lon, 70, 10)
|
||||
const measured = distanceNm(start.lat, start.lon, dest.lat, dest.lon)
|
||||
assert.ok(Math.abs(measured - 10) < 0.01, `expected ~10nm, got ${measured}`)
|
||||
})
|
||||
|
||||
test('bearingDeg from destinationPoint matches the requested bearing', () => {
|
||||
const start = { lat: 48.68, lon: 9.21 }
|
||||
const dest = destinationPoint(start.lat, start.lon, 145, 30)
|
||||
const measured = bearingDeg(start.lat, start.lon, dest.lat, dest.lon)
|
||||
assert.ok(Math.abs(angleDiffDeg(145, measured)) < 0.01, `expected ~145deg, got ${measured}`)
|
||||
})
|
||||
|
||||
test('destinationPoint at bearing 0 moves north (lat increases, lon unchanged)', () => {
|
||||
const dest = destinationPoint(50, 8, 0, 60) // 60nm = ~1 degree latitude
|
||||
assert.ok(dest.lat > 50.9 && dest.lat < 51.1)
|
||||
assert.ok(Math.abs(dest.lon - 8) < 0.001)
|
||||
})
|
||||
Reference in New Issue
Block a user