From f593cbd29a43a514d841114a050367432e310194 Mon Sep 17 00:00:00 2001 From: Kilian Hofmann Date: Wed, 16 Jul 2025 01:34:34 +0200 Subject: [PATCH] Initial NG --- .gitignore | 4 +- .vscode/launch.json | 14 +- TODO.md | 22 +- browser/eslint.config.js | 6 + browser/package.json | 6 +- browser/pnpm-lock.yaml | 141 +++++- .../{ => ProcedureLegs}/TermID_10394.json | 0 .../{ => ProcedureLegs}/TermID_10395.json | 0 .../{ => ProcedureLegs}/TermID_10475.json | 0 .../{ => ProcedureLegs}/TermID_10480.json | 0 .../{ => ProcedureLegs}/TermID_10482.json | 0 .../{ => ProcedureLegs}/TermID_10485.json | 0 .../{ => ProcedureLegs}/TermID_10653.json | 0 .../{ => ProcedureLegs}/TermID_10654.json | 0 .../{ => ProcedureLegs}/TermID_10657.json | 0 .../{ => ProcedureLegs}/TermID_10659.json | 0 .../{ => ProcedureLegs}/TermID_10679.json | 0 .../{ => ProcedureLegs}/TermID_11798.json | 0 .../{ => ProcedureLegs}/TermID_11909.json | 0 .../{ => ProcedureLegs}/TermID_12765.json | 0 .../{ => ProcedureLegs}/TermID_67790.json | 0 .../{ => ProcedureLegs}/TermID_67794.json | 0 browser/public/navdata/README.MD | 1 + browser/src/App.tsx | 97 ++-- browser/src/components/Map.tsx | 197 ++++++++ browser/src/components/ProcedureSelect.tsx | 125 +++++ browser/src/components/map/Map.tsx | 95 ---- browser/src/hooks/useNavigraphAuth.tsx | 53 +++ browser/src/lib/navigraph.ts | 21 + browser/src/main.tsx | 5 +- browser/src/parser/node.ts | 17 - browser/src/parser/parser.ts | 434 +++++++++--------- .../pathGenerators/generateOverflyArc.ts | 2 +- .../pathGenerators/generatePerformanceArc.ts | 4 +- .../pathGenerators/generateTangentArc.ts | 2 +- .../parser/pathGenerators/handleTurnAtFix.ts | 4 +- browser/src/parser/terminators/AF.ts | 4 +- browser/src/parser/terminators/CA.ts | 6 +- browser/src/parser/terminators/CD.ts | 4 +- browser/src/parser/terminators/CF.ts | 4 +- browser/src/parser/terminators/CI.ts | 8 +- browser/src/parser/terminators/CR.ts | 7 +- browser/src/parser/terminators/DF.ts | 4 +- browser/src/parser/terminators/FA.ts | 6 +- browser/src/parser/terminators/FC.ts | 6 +- browser/src/parser/terminators/FD.ts | 4 +- browser/src/parser/terminators/FM.ts | 4 +- browser/src/parser/terminators/IF.ts | 2 +- browser/src/parser/terminators/RF.ts | 6 +- browser/src/parser/terminators/TF.ts | 4 +- browser/src/parser/terminators/VA.ts | 6 +- browser/src/parser/terminators/VD.ts | 4 +- browser/src/parser/terminators/VI.ts | 8 +- browser/src/parser/terminators/VM.ts | 4 +- browser/src/parser/terminators/VR.ts | 6 +- browser/src/parser/utils/computeSpeed.ts | 2 +- .../utils/getCourseAndFixForIntercepts.ts | 5 + browser/src/types/leaflet.d.ts | 1 - browser/src/types/types.d.ts | 11 +- browser/src/vite-env.d.ts | 13 + browser/tsconfig.app.json | 1 + browser/tsconfig.node.json | 1 + browser/vite.config.ts | 3 + 63 files changed, 929 insertions(+), 455 deletions(-) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10394.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10395.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10475.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10480.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10482.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10485.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10653.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10654.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10657.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10659.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_10679.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_11798.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_11909.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_12765.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_67790.json (100%) rename browser/public/navdata/{ => ProcedureLegs}/TermID_67794.json (100%) create mode 100644 browser/public/navdata/README.MD create mode 100644 browser/src/components/Map.tsx create mode 100644 browser/src/components/ProcedureSelect.tsx delete mode 100644 browser/src/components/map/Map.tsx create mode 100644 browser/src/hooks/useNavigraphAuth.tsx create mode 100644 browser/src/lib/navigraph.ts delete mode 100644 browser/src/parser/node.ts diff --git a/.gitignore b/.gitignore index 54f07af..3b0b403 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,6 @@ dist-ssr *.ntvs* *.njsproj *.sln -*.sw? \ No newline at end of file +*.sw? + +.env \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 5d1283b..2321b76 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,17 +5,11 @@ "version": "0.2.0", "configurations": [ { - "type": "node", + "type": "chrome", "request": "launch", - "name": "Launch Parser Node", - "skipFiles": ["/**"], - "args": [ - "--experimental-strip-types", - "${workspaceFolder}\\browser\\src\\parser\\node.ts" - ], - "cwd": "${workspaceFolder}\\browser\\", - "outFiles": ["${workspaceFolder}/**/*.js"], - "console": "integratedTerminal" + "name": "Launch Chrome against localhost", + "url": "http://localhost:3000", + "webRoot": "${workspaceFolder}/browser" } ] } diff --git a/TODO.md b/TODO.md index 3e81768..f2c2737 100644 --- a/TODO.md +++ b/TODO.md @@ -1,16 +1,6 @@ -How to use: - -- Select Airport by ICAO -- List runways for selected airport -- List SID for selected runway - - List transitions for selected SID - - Parse SID and transition - - Display -- List STAR for selected runway - - List transitions for selected STAR - - Parse STAR and transition - - Display -- List IAPs for selected runway - - List transitions for selected IAP - - Parse IAP and transition - - Display \ No newline at end of file +Revise list of charts to only show those applicable to the selected procedure (so terminal itself and all transitions accompanied) +Revise image overlay + - Find center of full page + - Find center of georeferenced area + - Calculate skew parameters + - Skew geobounds \ No newline at end of file diff --git a/browser/eslint.config.js b/browser/eslint.config.js index 931e224..d901eda 100644 --- a/browser/eslint.config.js +++ b/browser/eslint.config.js @@ -21,6 +21,12 @@ export default tseslint.config([ }, rules: { '@typescript-eslint/no-shadow': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + destructuredArrayIgnorePattern: '^_+$', + }, + ], }, }, ]); diff --git a/browser/package.json b/browser/package.json index 3238fbd..500e74d 100644 --- a/browser/package.json +++ b/browser/package.json @@ -4,18 +4,21 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --port 3000 --host", "build": "tsc -b && vite build", "lint": "eslint . --ext .ts,.tsx --fix", "preview": "vite preview", "parser": "node --experimental-strip-types src/parser/node.ts" }, "dependencies": { + "browser-image-manipulation": "^0.4.0", "geojson": "^0.5.0", "geolib": "^3.3.4", "leaflet": "^1.9.4", "leaflet-svg-shape-markers": "^1.4.0", "magvar": "^2.0.0", + "navigraph": "^1.4.1", + "qrcode.react": "^4.2.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-leaflet": "^5.0.0", @@ -25,7 +28,6 @@ "@eslint/js": "^9.31.0", "@tailwindcss/vite": "^4.1.11", "@types/leaflet": "^1.9.20", - "@types/node": "^24.0.14", "@types/object-hash": "^3.0.6", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", diff --git a/browser/pnpm-lock.yaml b/browser/pnpm-lock.yaml index 53b83ad..253c84f 100644 --- a/browser/pnpm-lock.yaml +++ b/browser/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + browser-image-manipulation: + specifier: ^0.4.0 + version: 0.4.0 geojson: specifier: ^0.5.0 version: 0.5.0 @@ -23,6 +26,12 @@ importers: magvar: specifier: ^2.0.0 version: 2.0.0 + navigraph: + specifier: ^1.4.1 + version: 1.4.1 + qrcode.react: + specifier: ^4.2.0 + version: 4.2.0(react@19.1.0) react: specifier: ^19.1.0 version: 19.1.0 @@ -45,9 +54,6 @@ importers: '@types/leaflet': specifier: ^1.9.20 version: 1.9.20 - '@types/node': - specifier: ^24.0.14 - version: 24.0.14 '@types/object-hash': specifier: ^3.0.6 version: 3.0.6 @@ -331,6 +337,25 @@ packages: '@jridgewell/trace-mapping@0.3.29': resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@navigraph/amdb@1.1.0': + resolution: {integrity: sha512-/LhFxZckcOfreVHDWJh14jp+GUkeN7rIpZmUig5ttrABrvj9kQpMj6I9j1sjA5Rt3qaky2TJeReNKgOKLEHtdg==} + + '@navigraph/app@1.4.0': + resolution: {integrity: sha512-TS7G1Qx9Le7RkwkL6CfDVqBjYj+a2m3jOlNrF5yVbXkuo285xoCg4jt1kdueXefolxWS4Q1kP50WNlZu23vGEw==} + + '@navigraph/auth@2.6.0': + resolution: {integrity: sha512-/YNckuJeoKvwe/ujLasMbrvVwEYxc/AnOdlb4ioI2Q/f48At3Zp9L5mGtHD7MwpdiFyGbIg8IHnmJkz1pRCh4w==} + engines: {node: '>=10'} + + '@navigraph/charts@2.1.0': + resolution: {integrity: sha512-SOjNjmCe2aqUxA9wz85iVhIdv7qY+gTbrxwkGLVSBFeDTb3aqywesWygpCsb8VsxLIVnP/ePvgEoPRbthZFOAw==} + + '@navigraph/packages@1.1.0': + resolution: {integrity: sha512-0rTTs+DuamcyXVKzqCOp+a9KMVhZUwtvGUWqmtC+AfgZRCQ63TvFyjTWaXdyeodbaxf02qpa3I5KK8qGNPWHgg==} + + '@navigraph/weather@2.1.0': + resolution: {integrity: sha512-fa5u69o9cJQKEL7AnI+UF7uT67zaLrgF7OpDhWCcQ/+Ax8NxuS9nIjZoyc2VnZ5XIZ2oVcNoKhC3s76NKe83xA==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -731,6 +756,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + blueimp-canvas-to-blob@3.29.0: + resolution: {integrity: sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -741,6 +769,9 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browser-image-manipulation@0.4.0: + resolution: {integrity: sha512-SYNoVBnbozWA8jIcQJUShYYHpoEimONcoEnYBuDEUvcXgJT6042oTb+zkQry1RN/MmU8jd8ssMOp2RrNPky8VQ==} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -923,6 +954,9 @@ packages: resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} engines: {node: '>=18'} + glur@1.1.2: + resolution: {integrity: sha512-l+8esYHTKOx2G/Aao4lEQ0bnHWg4fWtJbVoZZT9Knxi01pB8C80BR85nONLFwkkQoFRCmXY+BUcGZN3yZ2QsRA==} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -1102,6 +1136,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multimath@2.0.0: + resolution: {integrity: sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1110,6 +1147,13 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + navigraph@1.4.1: + resolution: {integrity: sha512-cmgDLx12zI6/1jt81NCeqo1II+gqsPTIe3iLQGqj4NNAwzy/7x2C94DcMcq5xWIKL2jmkprD08pnmaKeMCSdkg==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -1138,6 +1182,9 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + pica@9.0.1: + resolution: {integrity: sha512-v0U4vY6Z3ztz9b4jBIhCD3WYoecGXCQeCsYep+sXRefViL+mVVoTL+wqzdPeE+GpBFsRUtQZb6dltvAt2UkMtQ==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1149,6 +1196,9 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + piexifjs@1.0.6: + resolution: {integrity: sha512-0wVyH0cKohzBQ5Gi2V1BuxYpxWfxF3cSqfFXfPIpl5tl9XLS5z4ogqhUCD20AbHi0h9aJkqXNJnkVev6gwh2ag==} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -1237,6 +1287,11 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qrcode.react@4.2.0: + resolution: {integrity: sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1292,6 +1347,9 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + stackblur-canvas@2.2.0: + resolution: {integrity: sha512-5Gf8dtlf8k6NbLzuly2NkGrkS/Ahh+I5VUjO7TnFizdJtgpfpLLEdQlLe9umbcnZlitU84kfYjXE67xlSXfhfQ==} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -1387,6 +1445,9 @@ packages: yaml: optional: true + webworkify@1.5.0: + resolution: {integrity: sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1564,6 +1625,32 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.4 + '@navigraph/amdb@1.1.0': + dependencies: + '@navigraph/app': 1.4.0 + '@navigraph/auth': 2.6.0 + + '@navigraph/app@1.4.0': {} + + '@navigraph/auth@2.6.0': + dependencies: + '@navigraph/app': 1.4.0 + + '@navigraph/charts@2.1.0': + dependencies: + '@navigraph/app': 1.4.0 + '@navigraph/auth': 2.6.0 + + '@navigraph/packages@1.1.0': + dependencies: + '@navigraph/app': 1.4.0 + '@navigraph/auth': 2.6.0 + + '@navigraph/weather@2.1.0': + dependencies: + '@navigraph/app': 1.4.0 + '@navigraph/auth': 2.6.0 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1780,6 +1867,7 @@ snapshots: '@types/node@24.0.14': dependencies: undici-types: 7.8.0 + optional: true '@types/object-hash@3.0.6': {} @@ -1913,6 +2001,8 @@ snapshots: balanced-match@1.0.2: {} + blueimp-canvas-to-blob@3.29.0: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -1926,6 +2016,13 @@ snapshots: dependencies: fill-range: 7.1.1 + browser-image-manipulation@0.4.0: + dependencies: + blueimp-canvas-to-blob: 3.29.0 + pica: 9.0.1 + piexifjs: 1.0.6 + stackblur-canvas: 2.2.0 + callsites@3.1.0: {} chalk@4.1.2: @@ -2133,6 +2230,8 @@ snapshots: globals@16.3.0: {} + glur@1.1.2: {} + graceful-fs@4.2.11: {} graphemer@1.4.0: {} @@ -2267,10 +2366,26 @@ snapshots: ms@2.1.3: {} + multimath@2.0.0: + dependencies: + glur: 1.1.2 + object-assign: 4.1.1 + nanoid@3.3.11: {} natural-compare@1.4.0: {} + navigraph@1.4.1: + dependencies: + '@navigraph/amdb': 1.1.0 + '@navigraph/app': 1.4.0 + '@navigraph/auth': 2.6.0 + '@navigraph/charts': 2.1.0 + '@navigraph/packages': 1.1.0 + '@navigraph/weather': 2.1.0 + + object-assign@4.1.1: {} + object-hash@3.0.0: {} optionator@0.9.4: @@ -2298,12 +2413,21 @@ snapshots: path-key@3.1.1: {} + pica@9.0.1: + dependencies: + glur: 1.1.2 + multimath: 2.0.0 + object-assign: 4.1.1 + webworkify: 1.5.0 + picocolors@1.1.1: {} picomatch@2.3.1: {} picomatch@4.0.2: {} + piexifjs@1.0.6: {} + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -2327,6 +2451,10 @@ snapshots: punycode@2.3.1: {} + qrcode.react@4.2.0(react@19.1.0): + dependencies: + react: 19.1.0 + queue-microtask@1.2.3: {} react-dom@19.1.0(react@19.1.0): @@ -2389,6 +2517,8 @@ snapshots: source-map-js@1.2.1: {} + stackblur-canvas@2.2.0: {} + strip-json-comments@3.1.1: {} supports-color@7.2.0: @@ -2438,7 +2568,8 @@ snapshots: typescript@5.8.3: {} - undici-types@7.8.0: {} + undici-types@7.8.0: + optional: true uri-js@4.4.1: dependencies: @@ -2458,6 +2589,8 @@ snapshots: jiti: 2.4.2 lightningcss: 1.30.1 + webworkify@1.5.0: {} + which@2.0.2: dependencies: isexe: 2.0.0 diff --git a/browser/public/navdata/TermID_10394.json b/browser/public/navdata/ProcedureLegs/TermID_10394.json similarity index 100% rename from browser/public/navdata/TermID_10394.json rename to browser/public/navdata/ProcedureLegs/TermID_10394.json diff --git a/browser/public/navdata/TermID_10395.json b/browser/public/navdata/ProcedureLegs/TermID_10395.json similarity index 100% rename from browser/public/navdata/TermID_10395.json rename to browser/public/navdata/ProcedureLegs/TermID_10395.json diff --git a/browser/public/navdata/TermID_10475.json b/browser/public/navdata/ProcedureLegs/TermID_10475.json similarity index 100% rename from browser/public/navdata/TermID_10475.json rename to browser/public/navdata/ProcedureLegs/TermID_10475.json diff --git a/browser/public/navdata/TermID_10480.json b/browser/public/navdata/ProcedureLegs/TermID_10480.json similarity index 100% rename from browser/public/navdata/TermID_10480.json rename to browser/public/navdata/ProcedureLegs/TermID_10480.json diff --git a/browser/public/navdata/TermID_10482.json b/browser/public/navdata/ProcedureLegs/TermID_10482.json similarity index 100% rename from browser/public/navdata/TermID_10482.json rename to browser/public/navdata/ProcedureLegs/TermID_10482.json diff --git a/browser/public/navdata/TermID_10485.json b/browser/public/navdata/ProcedureLegs/TermID_10485.json similarity index 100% rename from browser/public/navdata/TermID_10485.json rename to browser/public/navdata/ProcedureLegs/TermID_10485.json diff --git a/browser/public/navdata/TermID_10653.json b/browser/public/navdata/ProcedureLegs/TermID_10653.json similarity index 100% rename from browser/public/navdata/TermID_10653.json rename to browser/public/navdata/ProcedureLegs/TermID_10653.json diff --git a/browser/public/navdata/TermID_10654.json b/browser/public/navdata/ProcedureLegs/TermID_10654.json similarity index 100% rename from browser/public/navdata/TermID_10654.json rename to browser/public/navdata/ProcedureLegs/TermID_10654.json diff --git a/browser/public/navdata/TermID_10657.json b/browser/public/navdata/ProcedureLegs/TermID_10657.json similarity index 100% rename from browser/public/navdata/TermID_10657.json rename to browser/public/navdata/ProcedureLegs/TermID_10657.json diff --git a/browser/public/navdata/TermID_10659.json b/browser/public/navdata/ProcedureLegs/TermID_10659.json similarity index 100% rename from browser/public/navdata/TermID_10659.json rename to browser/public/navdata/ProcedureLegs/TermID_10659.json diff --git a/browser/public/navdata/TermID_10679.json b/browser/public/navdata/ProcedureLegs/TermID_10679.json similarity index 100% rename from browser/public/navdata/TermID_10679.json rename to browser/public/navdata/ProcedureLegs/TermID_10679.json diff --git a/browser/public/navdata/TermID_11798.json b/browser/public/navdata/ProcedureLegs/TermID_11798.json similarity index 100% rename from browser/public/navdata/TermID_11798.json rename to browser/public/navdata/ProcedureLegs/TermID_11798.json diff --git a/browser/public/navdata/TermID_11909.json b/browser/public/navdata/ProcedureLegs/TermID_11909.json similarity index 100% rename from browser/public/navdata/TermID_11909.json rename to browser/public/navdata/ProcedureLegs/TermID_11909.json diff --git a/browser/public/navdata/TermID_12765.json b/browser/public/navdata/ProcedureLegs/TermID_12765.json similarity index 100% rename from browser/public/navdata/TermID_12765.json rename to browser/public/navdata/ProcedureLegs/TermID_12765.json diff --git a/browser/public/navdata/TermID_67790.json b/browser/public/navdata/ProcedureLegs/TermID_67790.json similarity index 100% rename from browser/public/navdata/TermID_67790.json rename to browser/public/navdata/ProcedureLegs/TermID_67790.json diff --git a/browser/public/navdata/TermID_67794.json b/browser/public/navdata/ProcedureLegs/TermID_67794.json similarity index 100% rename from browser/public/navdata/TermID_67794.json rename to browser/public/navdata/ProcedureLegs/TermID_67794.json diff --git a/browser/public/navdata/README.MD b/browser/public/navdata/README.MD new file mode 100644 index 0000000..59ec6d2 --- /dev/null +++ b/browser/public/navdata/README.MD @@ -0,0 +1 @@ +Copy over contents of `Data/Primary` retaining the structure. \ No newline at end of file diff --git a/browser/src/App.tsx b/browser/src/App.tsx index fbe3cef..4bd634a 100644 --- a/browser/src/App.tsx +++ b/browser/src/App.tsx @@ -1,44 +1,77 @@ -import { useEffect, useState } from 'react'; -import { Map } from './components/map/Map'; +import type { DeviceFlowParams } from 'navigraph/auth'; +import { QRCodeSVG } from 'qrcode.react'; +import { useState } from 'react'; +import { ProcedureSelect } from './components//ProcedureSelect'; +import { Map } from './components/Map'; +import { useNavigraphAuth } from './hooks/useNavigraphAuth'; import Parser from './parser/parser'; const parser = await Parser.instance(); -const terminals = [10394, 10395, 10475, 10480, 10482, 10485, 10653, 10654, 10657, 10659, 10679, 11798, 11909, 12765]; - function App() { - const [selectedTerminal, setSelectedTerminal] = useState(terminals[0]); - const [procedures, setProcedures] = useState([]); + const [selectedAirport, setSelectedAirport] = useState(); + const [selectedRunway, setSelectedRunway] = useState(); + const [selectedTerminal, setSelectedTerminal] = useState(); + const [procedures, setProcedures] = useState<{ name: string; data: object }[]>([]); + const [params, setParams] = useState(null); - useEffect(() => { - (async () => { - setProcedures(await parser.parse(selectedTerminal)); - })(); - }, [selectedTerminal]); + const { user, signIn, initialized } = useNavigraphAuth(); + + const handleSignIn = () => signIn((p) => setParams(p)); return ( -
- -
-
- {terminals.map((terminal) => ( -
setSelectedTerminal(terminal)} - > - - {(() => { - const t = parser.terminals.find(({ ID }) => ID === terminal); - return `${t?.ICAO} - ${t?.FullName}`; - })()} - -
({terminal})
-
- ))} + <> + {procedures.length === 0 ? ( +
+ {!initialized &&
Loading...
} + + {initialized && !params && !user && } + + {params?.verification_uri_complete && !user && ( + <> + + + Open sign in page + + + )} + {user && ( + + setProcedures( + selectedTransitions.map((transition) => ({ + name: transition, + data: parser.parse(selectedRunway!, transition), + })) + ) + } + /> + )}
-
-
+ ) : ( +
+ {procedures.length > 0 && selectedAirport && selectedTerminal ? ( + { + setSelectedTerminal(undefined); + setProcedures([]); + }} + /> + ) : ( +

Error

+ )} +
+ )} + ); } diff --git a/browser/src/components/Map.tsx b/browser/src/components/Map.tsx new file mode 100644 index 0000000..08fcb06 --- /dev/null +++ b/browser/src/components/Map.tsx @@ -0,0 +1,197 @@ +import BrowserImageManipulation from 'browser-image-manipulation'; +import { default as L, type LatLngBoundsExpression } from 'leaflet'; +import 'leaflet-svg-shape-markers'; +import { type Chart } from 'navigraph/charts'; +import { createRef, useEffect, useState, type FC } from 'react'; +import { GeoJSON, ImageOverlay, MapContainer, TileLayer } from 'react-leaflet'; +import { charts } from '../lib/navigraph'; + +interface MapProps { + airport: Airport; + terminal: Terminal; + procedures: { name: string; data: object }[]; + backAction: () => void; +} + +export const Map: FC = ({ airport, terminal, procedures, backAction }) => { + const [selectedProcedure, setSelectedProcedure] = useState(procedures[0]); + const [chartIndex, setChartIndex] = useState([]); + const [selectedChart, setSelectedChart] = useState<{ + data: string; + index_number: string; + bounds: LatLngBoundsExpression; + }>(); + + const mapRef = createRef(); + const imageRef = createRef(); + + useEffect(() => { + (async () => { + setChartIndex((await charts.getChartsIndex({ icao: airport.ICAO, version: 'STD' })) ?? []); + })(); + }, []); + + return ( + <> + + + { + _mapRef?.attributionControl.setPosition('topright'); + _mapRef?.zoomControl.setPosition('topright'); + mapRef.current = _mapRef; + }} + > + + + {selectedChart && selectedChart.bounds && ( + { + if (_imageRef) { + mapRef.current?.fitBounds(_imageRef.getBounds(), { + padding: [-50, -50], + }); + } + imageRef.current = _imageRef; + }} + /> + )} + + ({ + color: '#ff00ff', + stroke: true, + weight: 5, + opacity: 1, + dashArray: properties.isManual ? '20, 20' : undefined, + })} + filter={(feature) => feature.geometry.type !== 'Point'} + /> + { + if (properties.isFlyOver) + return L.shapeMarker(latlng, { + shape: 'triangle', + radius: 6, + }); + if (properties.isIntersection) return L.circleMarker(latlng, { radius: 6 }); + + return L.shapeMarker(latlng, { + shape: 'star-4', + radius: 10, + rotation: 45, + }); + }} + onEachFeature={({ geometry, properties }, layer) => { + if (geometry.type === 'Point') { + layer.bindPopup( + `${properties.name}
+ ${properties.altitude} ft
+ ${properties.speed} kts
+ CNSTR: + ${properties.altitudeConstraint ?? ''} + ${properties.speedConstraint ?? ''}
` + ); + } + }} + filter={(feature) => feature.geometry.type === 'Point'} + /> +
+ +
+
+ Procedures: + {procedures.map((procedure) => ( + + ))} +
+
+ Charts: +
+ {chartIndex + .filter((chart) => chart.is_georeferenced) + .map((chart) => ( + + ))} +
+
+
+ + ); +}; diff --git a/browser/src/components/ProcedureSelect.tsx b/browser/src/components/ProcedureSelect.tsx new file mode 100644 index 0000000..f840689 --- /dev/null +++ b/browser/src/components/ProcedureSelect.tsx @@ -0,0 +1,125 @@ +import { createRef, useMemo, useState, type Dispatch, type FC, type SetStateAction } from 'react'; +import Parser from '../parser/parser'; + +const parser = await Parser.instance(); + +interface ProcedureSelectProps { + selectedAirport: Airport | undefined; + selectedRunway: Runway | undefined; + selectedTerminal: Terminal | undefined; + setSelectedAirport: Dispatch>; + setSelectedRunway: Dispatch>; + setSelectedTerminal: Dispatch>; + handleSelection: (transitions: string[]) => void; +} + +export const ProcedureSelect: FC = ({ + selectedAirport, + selectedRunway, + selectedTerminal, + setSelectedAirport, + setSelectedRunway, + setSelectedTerminal, + handleSelection, +}) => { + const inputRef = createRef(); + const [error, setError] = useState(); + + const runways = useMemo( + () => parser.runways.filter(({ AirportID }) => AirportID === selectedAirport?.ID), + [selectedAirport] + ); + const terminals = useMemo( + () => + parser.terminals.filter( + ({ AirportID, RwyID }) => AirportID === selectedAirport?.ID && (!RwyID || RwyID === selectedRunway?.ID) + ), + [selectedAirport, selectedRunway] + ); + + return ( +
+ {selectedAirport && ( + + )} + + {!selectedAirport && ( +
+

Enter Airport ICAO

+ { + if (e.target.value.length <= 4) e.target.value = e.target.value.toUpperCase(); + else e.target.value = e.target.value.slice(0, 4); + }} + > + + {error && {error}} +
+ )} + {selectedAirport && !selectedRunway && ( +
+

Select Runway

+ {runways.map((runway) => ( + + ))} +
+ )} + {selectedAirport && selectedRunway && !selectedTerminal && ( +
+

Select Procedure

+ {terminals.map((terminal) => ( + + ))} +
+ )} +
+ ); +}; diff --git a/browser/src/components/map/Map.tsx b/browser/src/components/map/Map.tsx deleted file mode 100644 index 8353b3b..0000000 --- a/browser/src/components/map/Map.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { default as L } from 'leaflet'; -import 'leaflet-svg-shape-markers'; -import hash from 'object-hash'; -import { createRef, Fragment, useEffect, type FC } from 'react'; -import { GeoJSON, MapContainer, TileLayer } from 'react-leaflet'; - -interface MapProps { - procedures: object[]; -} - -export const Map: FC = ({ procedures }) => { - const mapRef = createRef(); - const layerRef = createRef(); - - useEffect(() => { - if (layerRef.current && mapRef.current) { - mapRef.current.flyToBounds(layerRef.current.getBounds(), { - animate: false, - padding: [50, 50], - }); - } - }); - - return ( - - - {procedures.map((procedure) => ( - - ({ - color: '#ff00ff', - stroke: true, - weight: 5, - opacity: 1, - dashArray: properties.isManual ? '20, 20' : undefined, - })} - filter={(feature) => feature.geometry.type !== 'Point'} - ref={layerRef} - /> - { - if (properties.isFlyOver) - return L.shapeMarker(latlng, { - shape: 'triangle', - radius: 6, - }); - if (properties.isIntersection) return L.circleMarker(latlng, { radius: 6 }); - - return L.shapeMarker(latlng, { - shape: 'star-4', - radius: 10, - rotation: 45, - }); - }} - onEachFeature={({ geometry, properties }, layer) => { - if (geometry.type === 'Point') { - layer.bindPopup( - `${properties.name}
- ${properties.altitude} ft
- ${properties.speed} kts
- CNSTR: - ${properties.altitudeConstraint ?? ''} - ${properties.speedConstraint ?? ''}
` - ); - } - }} - filter={(feature) => feature.geometry.type === 'Point'} - /> -
- ))} -
- ); -}; diff --git a/browser/src/hooks/useNavigraphAuth.tsx b/browser/src/hooks/useNavigraphAuth.tsx new file mode 100644 index 0000000..64a8c8a --- /dev/null +++ b/browser/src/hooks/useNavigraphAuth.tsx @@ -0,0 +1,53 @@ +import { type User } from 'navigraph/auth'; +import React, { createContext, useContext, useEffect, useState } from 'react'; +import { auth } from '../lib/navigraph'; + +interface NavigraphAuthContext { + initialized: boolean; + user: User | null; + signIn: typeof auth.signInWithDeviceFlow; +} + +const authContext = createContext({ + initialized: false, + user: null, + signIn: () => Promise.reject('Not initialized'), +}); + +// Provider hook that creates auth object and handles state +function useProvideAuth() { + const [user, setUser] = useState(null); + const [initialized, setinitialized] = useState(false); + + // Subscribe to user on mount + // Because this sets state in the callback it will cause any + // component that utilizes this hook to re-render with the latest auth object. + useEffect(() => { + const unsubscribe = auth.onAuthStateChanged((u) => { + if (!initialized) setinitialized(true); + setUser(u); + }); + // Cleanup subscription on unmount + return () => unsubscribe(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return { + user, + initialized, + signIn: auth.signInWithDeviceFlow, + }; +} + +// Provider component that wraps your app and makes auth object +// available to any child component that calls useAuth(). +export function NavigraphAuthProvider({ children }: { children: React.ReactNode }) { + const auth = useProvideAuth(); + return {children}; +} + +// Hook for child components to get the auth object +// and re-render when it changes. +export const useNavigraphAuth = () => { + return useContext(authContext); +}; diff --git a/browser/src/lib/navigraph.ts b/browser/src/lib/navigraph.ts new file mode 100644 index 0000000..51220d5 --- /dev/null +++ b/browser/src/lib/navigraph.ts @@ -0,0 +1,21 @@ +import { initializeApp, Scope, type NavigraphApp } from 'navigraph/app'; +import { getAuth } from 'navigraph/auth'; +import { getChartsAPI } from 'navigraph/charts'; + +const config: NavigraphApp = { + clientId: import.meta.env.VITE_NG_CLIENT_ID, + clientSecret: import.meta.env.VITE_NG_CLIENT_SECRET, + scopes: [Scope.CHARTS], +}; + +initializeApp(config); + +export const auth = getAuth({ + storage: { + // Optional + getItem: (key) => localStorage.getItem('NG' + key), + setItem: (key, value) => localStorage.setItem('NG' + key, value), + }, +}); + +export const charts = getChartsAPI(); diff --git a/browser/src/main.tsx b/browser/src/main.tsx index 9262461..17006d0 100644 --- a/browser/src/main.tsx +++ b/browser/src/main.tsx @@ -3,9 +3,12 @@ import { createRoot } from 'react-dom/client'; import App from './App.tsx'; import 'leaflet/dist/leaflet.css'; +import { NavigraphAuthProvider } from './hooks/useNavigraphAuth.tsx'; createRoot(document.getElementById('root')!).render( - + + + ); diff --git a/browser/src/parser/node.ts b/browser/src/parser/node.ts deleted file mode 100644 index f248a12..0000000 --- a/browser/src/parser/node.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Parser from './parser.ts'; -import { prompting } from './utils/prompting.ts'; - -// mutate fetch to be local - -// @ts-expect-error Global override -// eslint-disable-next-line no-global-assign -fetch = async (path: string) => { - const fs = await import('fs'); - return { - json: () => JSON.parse(fs.readFileSync(`public/${path}`) as unknown as string), - }; -}; - -const parser = await Parser.instance(); - -console.log(JSON.stringify(await parser.parse(Number.parseInt((await prompting('Terminal ID')) ?? '')))); diff --git a/browser/src/parser/parser.ts b/browser/src/parser/parser.ts index 8012838..eac10d4 100644 --- a/browser/src/parser/parser.ts +++ b/browser/src/parser/parser.ts @@ -1,26 +1,25 @@ import geojson from 'geojson'; import * as geolib from 'geolib'; -import { TerminatorsAF } from './terminators/AF.ts'; -import { TerminatorsCA } from './terminators/CA.ts'; -import { TerminatorsCD } from './terminators/CD.ts'; -import { TerminatorsCF } from './terminators/CF.ts'; -import { TerminatorsCI } from './terminators/CI.ts'; -import { TerminatorsCR } from './terminators/CR.ts'; -import { TerminatorsDF } from './terminators/DF.ts'; -import { TerminatorsFA } from './terminators/FA.ts'; -import { TerminatorsFC } from './terminators/FC.ts'; -import { TerminatorsFD } from './terminators/FD.ts'; -import { TerminatorsFM } from './terminators/FM.ts'; -import { TerminatorsIF } from './terminators/IF.ts'; -import { TerminatorsRF } from './terminators/RF.ts'; -import { TerminatorsTF } from './terminators/TF.ts'; -import { TerminatorsVA } from './terminators/VA.ts'; -import { TerminatorsVD } from './terminators/VD.ts'; -import { TerminatorsVI } from './terminators/VI.ts'; -import { TerminatorsVM } from './terminators/VM.ts'; -import { TerminatorsVR } from './terminators/VR.ts'; -import './utils/extensions.ts'; -import { prompting } from './utils/prompting.ts'; +import { TerminatorsAF } from './terminators/AF'; +import { TerminatorsCA } from './terminators/CA'; +import { TerminatorsCD } from './terminators/CD'; +import { TerminatorsCF } from './terminators/CF'; +import { TerminatorsCI } from './terminators/CI'; +import { TerminatorsCR } from './terminators/CR'; +import { TerminatorsDF } from './terminators/DF'; +import { TerminatorsFA } from './terminators/FA'; +import { TerminatorsFC } from './terminators/FC'; +import { TerminatorsFD } from './terminators/FD'; +import { TerminatorsFM } from './terminators/FM'; +import { TerminatorsIF } from './terminators/IF'; +import { TerminatorsRF } from './terminators/RF'; +import { TerminatorsTF } from './terminators/TF'; +import { TerminatorsVA } from './terminators/VA'; +import { TerminatorsVD } from './terminators/VD'; +import { TerminatorsVI } from './terminators/VI'; +import { TerminatorsVM } from './terminators/VM'; +import { TerminatorsVR } from './terminators/VR'; +import './utils/extensions'; /* Runway IDs for LIED @@ -31,15 +30,19 @@ Runway IDs for LIED class Parser { private static _instance: Parser; + private _airports: Airport[]; private _waypoints: Waypoint[]; private _runways: Runway[]; private _terminals: Terminal[]; + private _procedures: TerminalEntry[] = []; + public static AC_SPEED = 250; public static AC_BANK = 30; public static AC_VS = 1400; - private constructor(waypoints: Waypoint[], runways: Runway[], terminals: Terminal[]) { + private constructor(airports: Airport[], waypoints: Waypoint[], runways: Runway[], terminals: Terminal[]) { + this._airports = airports; this._waypoints = waypoints; this._runways = runways; this._terminals = terminals; @@ -47,16 +50,20 @@ class Parser { public static instance = async () => { if (!Parser._instance) { + const airports = await (await fetch('NavData/Airports.json')).json(); const waypoints = await (await fetch('NavData/Waypoints.json')).json(); const runways = await (await fetch('NavData/Runways.json')).json(); const terminals = await (await fetch('NavData/Terminals.json')).json(); - Parser._instance = new Parser(waypoints, runways, terminals); + Parser._instance = new Parser(airports, waypoints, runways, terminals); } return Parser._instance; }; + public get airports() { + return this._airports; + } public get terminals() { return this._terminals; } @@ -67,212 +74,199 @@ class Parser { return this._runways; } - public parse = async (terminalID: number) => { - // Get Procedure main - const terminal = this.terminals.find(({ ID }) => ID === terminalID); - if (!terminal) throw new Error('Procedure does not exists'); - // Get runway this procedure is for - let runway = this.runways.find(({ ID }) => ID === terminal.RwyID); - if (!runway) { - const id = Number.parseInt((await prompting('Runway ID')) ?? ''); - runway = this.runways.find(({ ID }) => ID === id); - if (!runway) throw new Error('Procedure links to non existent Runway'); - } - // Load procedure - const procedures = (await (await fetch(`NavData/TermID_${terminalID}.json`)).json()) as TerminalEntry[]; - // Split into transitions - const transitions = new Set(procedures.map((proc) => proc.Transition)); + public get procedures() { + return this._procedures; + } - const output: object[] = []; + public loadTerminal = async (terminalID: number) => { + this._procedures = (await ( + await fetch(`NavData/ProcedureLegs/TermID_${terminalID}.json`) + ).json()) as TerminalEntry[]; + }; + + public parse = (runway: Runway, transition: string) => { + // Private functions + /** + * @param line Line segments + */ + const updateLastCourse = (line: LineSegment[]) => { + lastCourse = geolib.getGreatCircleBearing( + { + latitude: line.at(-2)![1], + longitude: line.at(-2)![0], + }, + { + latitude: line.at(-1)![1], + longitude: line.at(-1)![0], + } + ); + }; + + /** + * @param fix New fix + * @param line New line + * @param options Options for line rendering + */ + const update = (fix?: NavFix, line?: LineSegment[], options?: Record) => { + if (fix) navFixes.push(fix); + if (line) { + lineSegments.push({ line, ...options }); + updateLastCourse(line); + } + }; + + // Output variables + const navFixes: NavFix[] = []; + const lineSegments: { line: LineSegment[]; [x: string]: unknown }[] = []; + + // Initials + navFixes.push({ + latitude: runway.Latitude, + longitude: runway.Longitude, + altitude: runway.Elevation, + speed: 0, + name: runway.Ident, + }); + let lastCourse = runway.TrueHeading; + const procedure = this._procedures.filter(({ Transition }) => !Transition || Transition === transition); // Main - transitions.forEach((transition) => { - // Private functions - /** - * @param line Line segments - */ - const updateLastCourse = (line: LineSegment[]) => { - lastCourse = geolib.getGreatCircleBearing( - { - latitude: line.at(-2)![1], - longitude: line.at(-2)![0], - }, - { - latitude: line.at(-1)![1], - longitude: line.at(-1)![0], - } - ); - }; + for (let index = 0; index < procedure.length; index++) { + const leg = procedure[index]; + const previousFix = navFixes.at(-1)!; + const waypoint = this.waypoints.filter(({ ID }) => ID === leg.WptID)[0]; - /** - * @param fix New fix - * @param line New line - * @param options Options for line rendering - */ - const update = (fix?: NavFix, line?: LineSegment[], options?: Record) => { - if (fix) navFixes.push(fix); - if (line) { - lineSegments.push({ line, ...options }); - updateLastCourse(line); + switch (leg.TrackCode) { + case 'AF': { + const [fixToAdd, lineToAdd] = TerminatorsAF(leg as AFTerminalEntry, previousFix, waypoint); + update(fixToAdd, lineToAdd); + break; } - }; - - // Output variables - const navFixes: NavFix[] = []; - const lineSegments: { line: LineSegment[]; [x: string]: unknown }[] = []; - - // Initials - navFixes.push({ - latitude: runway.Latitude, - longitude: runway.Longitude, - altitude: runway.Elevation, - speed: 0, - name: runway.Ident, - }); - let lastCourse = runway.TrueHeading; - - const procedure = procedures.filter((proc) => proc.Transition === transition); - for (let index = 0; index < procedure.length; index++) { - const leg = procedure[index]; - const previousFix = navFixes.at(-1)!; - const waypoint = this.waypoints.filter(({ ID }) => ID === leg.WptID)[0]; - - switch (leg.TrackCode) { - case 'AF': { - const [fixToAdd, lineToAdd] = TerminatorsAF(leg as AFTerminalEntry, previousFix, waypoint); - update(fixToAdd, lineToAdd); - break; - } - case 'CA': { - const [fixToAdd, lineToAdd] = TerminatorsCA(leg as CATerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'CD': { - const [fixToAdd, lineToAdd] = TerminatorsCD(leg as CDTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'CF': { - const [fixToAdd, lineToAdd] = TerminatorsCF(leg as CFTerminalEntry, previousFix, lastCourse, waypoint); - update(fixToAdd, lineToAdd); - break; - } - case 'CI': { - const [fixToAdd, lineToAdd] = TerminatorsCI( - leg as CITerminalEntry, - procedure[index + 1], - previousFix, - lastCourse - ); - update(fixToAdd, lineToAdd); - break; - } - case 'CR': { - const [fixToAdd, lineToAdd] = TerminatorsCR(leg as CRTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'DF': { - const [fixToAdd, lineToAdd] = TerminatorsDF(leg as DFTerminalEntry, previousFix, lastCourse, waypoint); - update(fixToAdd, lineToAdd); - break; - } - case 'FA': { - const [fixToAdd, lineToAdd] = TerminatorsFA(leg as FATerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'FC': { - const [fixToAdd, lineToAdd] = TerminatorsFC(leg as FCTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'FD': { - const [fixToAdd, lineToAdd] = TerminatorsFD(leg as FDTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'FM': { - const [fixToAdd, lineToAdd] = TerminatorsFM(leg as FMTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd, { isManual: true }); - break; - } - case 'HA': - case 'HF': - case 'HM': - console.error('Unknown TrackCode', leg.TrackCode); - break; - case 'IF': { - const fixToAdd = TerminatorsIF(leg as RFTerminalEntry, waypoint); - navFixes.length = 0; - navFixes.push(fixToAdd); - break; - } - case 'PI': - console.error('Unknown TrackCode', leg.TrackCode); - break; - case 'RF': { - const [fixToAdd, lineToAdd] = TerminatorsRF( - leg as RFTerminalEntry, - procedure[index + 1], - previousFix, - lastCourse, - waypoint - ); - update(fixToAdd, lineToAdd); - break; - } - case 'TF': { - const [fixToAdd, lineToAdd] = TerminatorsTF(leg as TFTerminalEntry, previousFix, lastCourse, waypoint); - update(fixToAdd, lineToAdd); - break; - } - case 'VA': { - const [fixToAdd, lineToAdd] = TerminatorsVA(leg as VATerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'VD': { - const [fixToAdd, lineToAdd] = TerminatorsVD(leg as VDTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - case 'VI': { - const [fixToAdd, lineToAdd] = TerminatorsVI( - leg as VITerminalEntry, - procedure[index + 1], - previousFix, - lastCourse - ); - update(fixToAdd, lineToAdd); - break; - } - case 'VM': { - const [fixToAdd, lineToAdd] = TerminatorsVM(leg as VMTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd, { isManual: true }); - break; - } - case 'VR': { - const [fixToAdd, lineToAdd] = TerminatorsVR(leg as VRTerminalEntry, previousFix, lastCourse); - update(fixToAdd, lineToAdd); - break; - } - default: - console.error('Unknown TrackCode', leg.TrackCode); - break; + case 'CA': { + const [fixToAdd, lineToAdd] = TerminatorsCA(leg as CATerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; } + case 'CD': { + const [fixToAdd, lineToAdd] = TerminatorsCD(leg as CDTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'CF': { + const [fixToAdd, lineToAdd] = TerminatorsCF(leg as CFTerminalEntry, previousFix, lastCourse, waypoint); + update(fixToAdd, lineToAdd); + break; + } + case 'CI': { + const [fixToAdd, lineToAdd] = TerminatorsCI( + leg as CITerminalEntry, + procedure[index + 1], + previousFix, + lastCourse + ); + update(fixToAdd, lineToAdd); + break; + } + case 'CR': { + const [fixToAdd, lineToAdd] = TerminatorsCR(leg as CRTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'DF': { + const [fixToAdd, lineToAdd] = TerminatorsDF(leg as DFTerminalEntry, previousFix, lastCourse, waypoint); + update(fixToAdd, lineToAdd); + break; + } + case 'FA': { + const [fixToAdd, lineToAdd] = TerminatorsFA(leg as FATerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'FC': { + const [fixToAdd, lineToAdd] = TerminatorsFC(leg as FCTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'FD': { + const [fixToAdd, lineToAdd] = TerminatorsFD(leg as FDTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'FM': { + const [fixToAdd, lineToAdd] = TerminatorsFM(leg as FMTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd, { isManual: true }); + break; + } + case 'HA': + case 'HF': + case 'HM': + console.error('Unknown TrackCode', leg.TrackCode); + break; + case 'IF': { + const fixToAdd = TerminatorsIF(leg as RFTerminalEntry, waypoint); + navFixes.length = 0; + navFixes.push(fixToAdd); + break; + } + case 'PI': + console.error('Unknown TrackCode', leg.TrackCode); + break; + case 'RF': { + const [fixToAdd, lineToAdd] = TerminatorsRF( + leg as RFTerminalEntry, + procedure[index + 1], + previousFix, + lastCourse, + waypoint + ); + update(fixToAdd, lineToAdd); + break; + } + case 'TF': { + const [fixToAdd, lineToAdd] = TerminatorsTF(leg as TFTerminalEntry, previousFix, lastCourse, waypoint); + update(fixToAdd, lineToAdd); + break; + } + case 'VA': { + const [fixToAdd, lineToAdd] = TerminatorsVA(leg as VATerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'VD': { + const [fixToAdd, lineToAdd] = TerminatorsVD(leg as VDTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + case 'VI': { + const [fixToAdd, lineToAdd] = TerminatorsVI( + leg as VITerminalEntry, + procedure[index + 1], + previousFix, + lastCourse + ); + update(fixToAdd, lineToAdd); + break; + } + case 'VM': { + const [fixToAdd, lineToAdd] = TerminatorsVM(leg as VMTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd, { isManual: true }); + break; + } + case 'VR': { + const [fixToAdd, lineToAdd] = TerminatorsVR(leg as VRTerminalEntry, previousFix, lastCourse); + update(fixToAdd, lineToAdd); + break; + } + default: + console.error('Unknown TrackCode', leg.TrackCode); + break; } + } - output.push( - geojson.parse([...navFixes, ...lineSegments], { - LineString: 'line', - Point: ['latitude', 'longitude'], - }) - ); + return geojson.parse([...navFixes, ...lineSegments], { + LineString: 'line', + Point: ['latitude', 'longitude'], }); - - return output; }; } diff --git a/browser/src/parser/pathGenerators/generateOverflyArc.ts b/browser/src/parser/pathGenerators/generateOverflyArc.ts index bc266c9..b1061b6 100644 --- a/browser/src/parser/pathGenerators/generateOverflyArc.ts +++ b/browser/src/parser/pathGenerators/generateOverflyArc.ts @@ -1,5 +1,5 @@ import * as geolib from 'geolib'; -import { generatePerformanceArc } from './generatePerformanceArc.ts'; +import { generatePerformanceArc } from './generatePerformanceArc'; /** * @param crsIntoEndpoint Course into arc endpoint diff --git a/browser/src/parser/pathGenerators/generatePerformanceArc.ts b/browser/src/parser/pathGenerators/generatePerformanceArc.ts index af56a02..16817b8 100644 --- a/browser/src/parser/pathGenerators/generatePerformanceArc.ts +++ b/browser/src/parser/pathGenerators/generatePerformanceArc.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import Parser from '../parser.ts'; -import { computeTurnRate } from '../utils/computeTurnRate.ts'; +import Parser from '../parser'; +import { computeTurnRate } from '../utils/computeTurnRate'; /** * @param crsIntoEndpoint Course into arc endpoint diff --git a/browser/src/parser/pathGenerators/generateTangentArc.ts b/browser/src/parser/pathGenerators/generateTangentArc.ts index 15d17e7..8fd6d08 100644 --- a/browser/src/parser/pathGenerators/generateTangentArc.ts +++ b/browser/src/parser/pathGenerators/generateTangentArc.ts @@ -1,5 +1,5 @@ import * as geolib from 'geolib'; -import { computeIntersection } from '../utils/computeIntersection.ts'; +import { computeIntersection } from '../utils/computeIntersection'; /** * @param crsIntoEndpoint Course into arc endpoint diff --git a/browser/src/parser/pathGenerators/handleTurnAtFix.ts b/browser/src/parser/pathGenerators/handleTurnAtFix.ts index d9b7d5a..3420022 100644 --- a/browser/src/parser/pathGenerators/handleTurnAtFix.ts +++ b/browser/src/parser/pathGenerators/handleTurnAtFix.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { generatePerformanceArc } from './generatePerformanceArc.ts'; -import { generateTangentArc } from './generateTangentArc.ts'; +import { generatePerformanceArc } from './generatePerformanceArc'; +import { generateTangentArc } from './generateTangentArc'; /** * @param crsIntoEndpoint Course into endpoint diff --git a/browser/src/parser/terminators/AF.ts b/browser/src/parser/terminators/AF.ts index 35d4362..ae4ee73 100644 --- a/browser/src/parser/terminators/AF.ts +++ b/browser/src/parser/terminators/AF.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { generateAFArc } from '../pathGenerators/generateAFArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateAFArc } from '../pathGenerators/generateAFArc'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsAF = ( leg: AFTerminalEntry, diff --git a/browser/src/parser/terminators/CA.ts b/browser/src/parser/terminators/CA.ts index 620c97e..0ebb51b 100644 --- a/browser/src/parser/terminators/CA.ts +++ b/browser/src/parser/terminators/CA.ts @@ -1,7 +1,7 @@ import * as geolib from 'geolib'; -import Parser from '../parser.ts'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import Parser from '../parser'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsCA = ( leg: CATerminalEntry, diff --git a/browser/src/parser/terminators/CD.ts b/browser/src/parser/terminators/CD.ts index df03108..ee80e92 100644 --- a/browser/src/parser/terminators/CD.ts +++ b/browser/src/parser/terminators/CD.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; // NOTE: Distance not adjusted for altitude in this demo export const TerminatorsCD = ( diff --git a/browser/src/parser/terminators/CF.ts b/browser/src/parser/terminators/CF.ts index e8b426d..c907d44 100644 --- a/browser/src/parser/terminators/CF.ts +++ b/browser/src/parser/terminators/CF.ts @@ -1,5 +1,5 @@ -import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsCF = ( leg: CFTerminalEntry, diff --git a/browser/src/parser/terminators/CI.ts b/browser/src/parser/terminators/CI.ts index 388da6c..318ec8a 100644 --- a/browser/src/parser/terminators/CI.ts +++ b/browser/src/parser/terminators/CI.ts @@ -1,7 +1,7 @@ -import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix.ts'; -import { computeIntersection } from '../utils/computeIntersection.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; -import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts.ts'; +import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix'; +import { computeIntersection } from '../utils/computeIntersection'; +import { computeSpeed } from '../utils/computeSpeed'; +import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts'; export const TerminatorsCI = ( leg: CITerminalEntry, diff --git a/browser/src/parser/terminators/CR.ts b/browser/src/parser/terminators/CR.ts index e9756b2..7353cdd 100644 --- a/browser/src/parser/terminators/CR.ts +++ b/browser/src/parser/terminators/CR.ts @@ -1,6 +1,6 @@ -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeIntersection } from '../utils/computeIntersection.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeIntersection } from '../utils/computeIntersection'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsCR = ( leg: CRTerminalEntry, @@ -28,6 +28,7 @@ export const TerminatorsCR = ( speedConstraint: leg.SpeedLimit, altitudeConstraint: leg.Alt, }; + line.push([interceptFix.longitude, interceptFix.latitude]); return [interceptFix, line]; diff --git a/browser/src/parser/terminators/DF.ts b/browser/src/parser/terminators/DF.ts index e7b27ba..1db746b 100644 --- a/browser/src/parser/terminators/DF.ts +++ b/browser/src/parser/terminators/DF.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsDF = ( leg: DFTerminalEntry, diff --git a/browser/src/parser/terminators/FA.ts b/browser/src/parser/terminators/FA.ts index c83c9f3..f15c29f 100644 --- a/browser/src/parser/terminators/FA.ts +++ b/browser/src/parser/terminators/FA.ts @@ -1,7 +1,7 @@ import * as geolib from 'geolib'; -import Parser from '../parser.ts'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import Parser from '../parser'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsFA = ( leg: FATerminalEntry, diff --git a/browser/src/parser/terminators/FC.ts b/browser/src/parser/terminators/FC.ts index be612ce..40a898a 100644 --- a/browser/src/parser/terminators/FC.ts +++ b/browser/src/parser/terminators/FC.ts @@ -1,7 +1,7 @@ import * as geolib from 'geolib'; -import Parser from '../parser.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; -import { computeTurnRate } from '../utils/computeTurnRate.ts'; +import Parser from '../parser'; +import { computeSpeed } from '../utils/computeSpeed'; +import { computeTurnRate } from '../utils/computeTurnRate'; // NOTE: Distance not adjusted for altitude in this demo export const TerminatorsFC = ( diff --git a/browser/src/parser/terminators/FD.ts b/browser/src/parser/terminators/FD.ts index 0a7e618..55df3b1 100644 --- a/browser/src/parser/terminators/FD.ts +++ b/browser/src/parser/terminators/FD.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; // NOTE: Distance not adjusted for altitude in this demo export const TerminatorsFD = ( diff --git a/browser/src/parser/terminators/FM.ts b/browser/src/parser/terminators/FM.ts index 9d0f7cf..9d8ada5 100644 --- a/browser/src/parser/terminators/FM.ts +++ b/browser/src/parser/terminators/FM.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsFM = ( leg: FMTerminalEntry, diff --git a/browser/src/parser/terminators/IF.ts b/browser/src/parser/terminators/IF.ts index bcd0559..18941af 100644 --- a/browser/src/parser/terminators/IF.ts +++ b/browser/src/parser/terminators/IF.ts @@ -1,4 +1,4 @@ -import Parser from '../parser.ts'; +import Parser from '../parser'; export const TerminatorsIF = (leg: IFTerminalEntry, waypoint?: Waypoint): NavFix => { const targetFix: NavFix = { diff --git a/browser/src/parser/terminators/RF.ts b/browser/src/parser/terminators/RF.ts index 42def2c..3b32707 100644 --- a/browser/src/parser/terminators/RF.ts +++ b/browser/src/parser/terminators/RF.ts @@ -1,6 +1,6 @@ -import { generateRFArc } from '../pathGenerators/generateRFArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; -import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts.ts'; +import { generateRFArc } from '../pathGenerators/generateRFArc'; +import { computeSpeed } from '../utils/computeSpeed'; +import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts'; export const TerminatorsRF = ( leg: RFTerminalEntry, diff --git a/browser/src/parser/terminators/TF.ts b/browser/src/parser/terminators/TF.ts index 656e509..b4c668c 100644 --- a/browser/src/parser/terminators/TF.ts +++ b/browser/src/parser/terminators/TF.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import Parser from '../parser.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import Parser from '../parser'; +import { computeSpeed } from '../utils/computeSpeed'; export const TerminatorsTF = ( leg: TFTerminalEntry, diff --git a/browser/src/parser/terminators/VA.ts b/browser/src/parser/terminators/VA.ts index e9b2e55..15a834b 100644 --- a/browser/src/parser/terminators/VA.ts +++ b/browser/src/parser/terminators/VA.ts @@ -1,7 +1,7 @@ import * as geolib from 'geolib'; -import Parser from '../parser.ts'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import Parser from '../parser'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; // NOTE: No wind adjustments to be made, no clue how *that* would draw export const TerminatorsVA = ( diff --git a/browser/src/parser/terminators/VD.ts b/browser/src/parser/terminators/VD.ts index 1906bb8..36b64f3 100644 --- a/browser/src/parser/terminators/VD.ts +++ b/browser/src/parser/terminators/VD.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeSpeed } from '../utils/computeSpeed'; // NOTE: No wind adjustments to be made, no clue how *that* would draw // NOTE: Distance not adjusted for altitude in this demo diff --git a/browser/src/parser/terminators/VI.ts b/browser/src/parser/terminators/VI.ts index f051df6..905c059 100644 --- a/browser/src/parser/terminators/VI.ts +++ b/browser/src/parser/terminators/VI.ts @@ -1,7 +1,7 @@ -import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix.ts'; -import { computeIntersection } from '../utils/computeIntersection.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; -import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts.ts'; +import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix'; +import { computeIntersection } from '../utils/computeIntersection'; +import { computeSpeed } from '../utils/computeSpeed'; +import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts'; // NOTE: No wind adjustments to be made, no clue how *that* would draw export const TerminatorsVI = ( diff --git a/browser/src/parser/terminators/VM.ts b/browser/src/parser/terminators/VM.ts index a0498ff..069cf8f 100644 --- a/browser/src/parser/terminators/VM.ts +++ b/browser/src/parser/terminators/VM.ts @@ -1,6 +1,6 @@ import * as geolib from 'geolib'; -import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { handleTurnAtFix } from '../pathGenerators/handleTurnAtFix'; +import { computeSpeed } from '../utils/computeSpeed'; // NOTE: No wind adjustments to be made, no clue how *that* would draw export const TerminatorsVM = ( diff --git a/browser/src/parser/terminators/VR.ts b/browser/src/parser/terminators/VR.ts index df9abd7..94f14a8 100644 --- a/browser/src/parser/terminators/VR.ts +++ b/browser/src/parser/terminators/VR.ts @@ -1,6 +1,6 @@ -import { generateOverflyArc } from '../pathGenerators/generateOverflyArc.ts'; -import { computeIntersection } from '../utils/computeIntersection.ts'; -import { computeSpeed } from '../utils/computeSpeed.ts'; +import { generateOverflyArc } from '../pathGenerators/generateOverflyArc'; +import { computeIntersection } from '../utils/computeIntersection'; +import { computeSpeed } from '../utils/computeSpeed'; // NOTE: No wind adjustments to be made, no clue how *that* would draw export const TerminatorsVR = ( diff --git a/browser/src/parser/utils/computeSpeed.ts b/browser/src/parser/utils/computeSpeed.ts index 292d0fb..c065e44 100644 --- a/browser/src/parser/utils/computeSpeed.ts +++ b/browser/src/parser/utils/computeSpeed.ts @@ -1,4 +1,4 @@ -import Parser from '../parser.ts'; +import Parser from '../parser'; export const computeSpeed = (leg: TerminalEntry, previousFix: NavFix) => { if (leg.SpeedLimit) return leg.SpeedLimit; diff --git a/browser/src/parser/utils/getCourseAndFixForIntercepts.ts b/browser/src/parser/utils/getCourseAndFixForIntercepts.ts index 4512180..5c021dd 100644 --- a/browser/src/parser/utils/getCourseAndFixForIntercepts.ts +++ b/browser/src/parser/utils/getCourseAndFixForIntercepts.ts @@ -32,6 +32,11 @@ export const getCourseAndFixForIntercepts = (leg: TerminalEntry, origin: NavFix) const fix = { latitude: _leg.WptLat, longitude: _leg.WptLon }; return [_leg.Course.reciprocalCourse().toTrue(fix), fix]; } + case 'DF': { + const _leg = leg as FMTerminalEntry; + const fix = { latitude: _leg.WptLat, longitude: _leg.WptLon }; + return [-1, fix]; + } default: { return [-1, origin]; } diff --git a/browser/src/types/leaflet.d.ts b/browser/src/types/leaflet.d.ts index 23091e2..1db1a03 100644 --- a/browser/src/types/leaflet.d.ts +++ b/browser/src/types/leaflet.d.ts @@ -1,4 +1,3 @@ - import 'leaflet'; declare module 'leaflet' { diff --git a/browser/src/types/types.d.ts b/browser/src/types/types.d.ts index 9dedfb5..a776733 100644 --- a/browser/src/types/types.d.ts +++ b/browser/src/types/types.d.ts @@ -6,6 +6,7 @@ export declare global { type Runway = { ID: number; + AirportID: number; Latitude: number; Longitude: number; Elevation: number; @@ -70,8 +71,9 @@ export declare global { type Terminal = { ID: number; - FullName: string; + AirportID: number; ICAO: string; + FullName: string; RwyID?: number; }; @@ -90,4 +92,11 @@ export declare global { }; type LineSegment = [number, number]; + + type Airport = { + ID: number; + ICAO: string; + Latitude: number; + Longitude: number; + }; } diff --git a/browser/src/vite-env.d.ts b/browser/src/vite-env.d.ts index 11f02fe..909b702 100644 --- a/browser/src/vite-env.d.ts +++ b/browser/src/vite-env.d.ts @@ -1 +1,14 @@ /// + +interface ViteTypeOptions { + strictImportMetaEnv: unknown; +} + +interface ImportMetaEnv { + readonly VITE_NG_CLIENT_ID: string; + readonly VITE_NG_CLIENT_SECRET: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/browser/tsconfig.app.json b/browser/tsconfig.app.json index 9965de5..3e13340 100644 --- a/browser/tsconfig.app.json +++ b/browser/tsconfig.app.json @@ -15,6 +15,7 @@ "moduleDetection": "force", "noEmit": true, "jsx": "react-jsx", + "sourceMap": true, /* Linting */ "strict": true, diff --git a/browser/tsconfig.node.json b/browser/tsconfig.node.json index 3d1e7ee..e229da9 100644 --- a/browser/tsconfig.node.json +++ b/browser/tsconfig.node.json @@ -13,6 +13,7 @@ "verbatimModuleSyntax": true, "moduleDetection": "force", "noEmit": true, + "sourceMap": true, /* Linting */ "strict": true, diff --git a/browser/vite.config.ts b/browser/vite.config.ts index 1850c1b..9614aba 100644 --- a/browser/vite.config.ts +++ b/browser/vite.config.ts @@ -5,4 +5,7 @@ import { defineConfig } from 'vite'; // https://vite.dev/config/ export default defineConfig({ plugins: [tailwindcss(), react()], + build: { + sourcemap: true, + }, });