Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 73 additions & 52 deletions airac-parser/common/airway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ export const extractAirways = async (
db: Promise<Database>
): Promise<{
data: Segment[][];
extras: number[];
extras: number[]; // all non-VT endpoints (unchanged semantics)
boundary: number[]; // NEW: non-VT endpoints directly connected to VT
enroute: number[];
}> => {
const filteredSegments = (await db).all<SegmentsDbData[]>(SQL`
const filteredSegments = (await db).all<SegmentsDbData[]>(SQL`
SELECT
airway.airway_name AS name,
airway.airway_fragment_no AS segment_no,
Expand All @@ -44,44 +45,63 @@ SELECT
T2.region AS region_to,
T1.waypoint_id AS id_from,
T2.waypoint_id AS id_to
FROM
airway
JOIN
waypoint T1 ON airway.from_waypoint_id = T1.waypoint_id
JOIN
waypoint T2 ON airway.to_waypoint_id = T2.waypoint_id
FROM airway
JOIN waypoint T1 ON airway.from_waypoint_id = T1.waypoint_id
JOIN waypoint T2 ON airway.to_waypoint_id = T2.waypoint_id
WHERE
(airway.airway_name, airway.airway_fragment_no) IN (
SELECT DISTINCT
airway_name,
airway_fragment_no
FROM
airway
JOIN
waypoint ON airway.from_waypoint_id = waypoint.waypoint_id
WHERE
region = 'VT'
UNION
SELECT DISTINCT
airway_name,
airway_fragment_no
FROM
airway
JOIN
waypoint ON airway.to_waypoint_id = waypoint.waypoint_id
WHERE
region = 'VT'
(
substr(airway.airway_name, 1, 1) IN ('H','J','V','W','Q','T','Y','Z')
AND EXISTS (
SELECT 1
FROM airway a2
JOIN waypoint f ON a2.from_waypoint_id = f.waypoint_id
JOIN waypoint t ON a2.to_waypoint_id = t.waypoint_id
WHERE a2.airway_name = airway.airway_name
AND a2.airway_fragment_no = airway.airway_fragment_no
AND f.region = 'VT'
AND t.region = 'VT' -- require at least one VT↔VT segment
)
)
ORDER BY
airway.airway_id ASC;
`);
OR
(
substr(airway.airway_name, 1, 1) IN ('A','B','G','R','L','M','N','P')
AND EXISTS (
SELECT 1
FROM airway a3
JOIN waypoint f2 ON a3.from_waypoint_id = f2.waypoint_id
JOIN waypoint t2 ON a3.to_waypoint_id = t2.waypoint_id
WHERE a3.airway_name = airway.airway_name
AND a3.airway_fragment_no = airway.airway_fragment_no
AND (f2.region = 'VT' OR t2.region = 'VT') -- touches VT anywhere
)
)
OR
(
substr(airway.airway_name, 1, 1) NOT IN ('H','J','V','W','Q','T','Y','Z','A','B','G','R','L','M','N','P')
AND EXISTS (
SELECT 1
FROM airway a4
JOIN waypoint f3 ON a4.from_waypoint_id = f3.waypoint_id
JOIN waypoint t3 ON a4.to_waypoint_id = t3.waypoint_id
WHERE a4.airway_name = airway.airway_name
AND a4.airway_fragment_no = airway.airway_fragment_no
AND (f3.region = 'VT' OR t3.region = 'VT') -- safe fallback
)
)
ORDER BY airway.airway_id ASC;
`);

const extras: number[] = [];

// use Sets to avoid duplicates while preserving insertion order via arrays later
const extrasSet = new Set<number>(); // all non-VT endpoints
const boundarySet = new Set<number>(); // non-VT endpoint when the other end is VT
const enroute: number[] = [];

const { data } = (await filteredSegments).reduce(
(prev, curr) => {
const { data: currData, ...others } = prev;

// Track enroute order the same way you did
if (
(prev.currentName !== curr.name ||
prev.currentFragment !== curr.segment_no ||
Expand All @@ -93,17 +113,19 @@ ORDER BY
if (enroute.indexOf(curr.id_to) === -1) {
enroute.push(curr.id_to);
}
if (curr.region_from !== 'VT') {
if (extras.indexOf(curr.id_from) === -1) {
extras.push(curr.id_from);
}
}
if (curr.region_to !== 'VT') {
if (extras.indexOf(curr.id_to) === -1) {
extras.push(curr.id_to);
}
}
const { id_from: _, id_to: __, ...out } = curr;

// Collect ALL non-VT endpoints in extras (unchanged)
if (curr.region_from !== 'VT') extrasSet.add(curr.id_from);
if (curr.region_to !== 'VT') extrasSet.add(curr.id_to);

// NEW: boundary = non-VT endpoint when the other side is VT
const fromIsVT = curr.region_from === 'VT';
const toIsVT = curr.region_to === 'VT';
if (fromIsVT && !toIsVT) boundarySet.add(curr.id_to); // VT → non-VT
if (!fromIsVT && toIsVT) boundarySet.add(curr.id_from); // non-VT → VT

// Build grouped segments (unchanged)
const { id_from: _a, id_to: _b, ...out } = curr;
if (
out.name !== prev.currentName ||
out.segment_no !== prev.currentFragment ||
Expand All @@ -115,11 +137,7 @@ ORDER BY
currentSequence: out.sequence_no,
data: [
...currData,
[
{
...out
}
]
[{ ...out }]
]
};
} else {
Expand All @@ -133,9 +151,7 @@ ORDER BY
...otherEle,
[
...lastEle,
{
...out
}
{ ...out }
]
]
};
Expand All @@ -148,5 +164,10 @@ ORDER BY
data: [] as Segment[][]
}
);
return { data, extras, enroute };

// Convert Sets to arrays (insertion order preserved by Set iteration)
const extras = Array.from(extrasSet);
const boundary = Array.from(boundarySet);

return { data, extras, boundary, enroute };
};
7 changes: 4 additions & 3 deletions airac-parser/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { extractWaypoints } from './waypoint';
const {
data: airways,
extras: extrasFromAirways,
boundary: boundaryFromAirways,
enroute: enrouteFixes
} = await extractAirways(db);

Expand All @@ -67,23 +68,23 @@ import { extractWaypoints } from './waypoint';

const buildNdbFile = resolve(buildPath, 'ndbs.json');

const ndbs = extractNdbs(db, extrasFromAirways);
const ndbs = extractNdbs(db, extrasFromAirways, boundaryFromAirways);

outputFileSync(buildNdbFile, JSON.stringify(await ndbs, null, 2));

console.log('Reading VORs...');

const buildVorFile = resolve(buildPath, 'vors.json');

const vors = extractVors(db, extrasFromAirways);
const vors = extractVors(db, extrasFromAirways, boundaryFromAirways);

outputFileSync(buildVorFile, JSON.stringify(await vors, null, 2));

console.log('Reading waypoints...');

const buildWaypointFile = resolve(buildPath, 'waypoints.json');

const waypoints = extractWaypoints(db, extrasFromAirways, enrouteFixes);
const waypoints = extractWaypoints(db, extrasFromAirways, boundaryFromAirways, enrouteFixes);

outputFileSync(buildWaypointFile, JSON.stringify(await waypoints, null, 2));

Expand Down
71 changes: 51 additions & 20 deletions airac-parser/common/ndb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,67 @@ interface NdbDbData {
lonx: number;
}

interface NdbDbExtraRow extends NdbDbData {
waypoint_id: number;
}

export const extractNdbs = async (
db: Promise<Database>,
extra: number[]
extra: number[],
boundary: number[]
): Promise<Ndb[]> => {

const boundarySet = new Set(boundary);

const addIsExtra =
(isExtra: boolean) =>
(s: NdbDbData[]): Ndb[] => {
return s.map((w) => {
const { ...others } = w;
return {
...others,
is_extra: isExtra
};
});
};

const ndbs: Promise<Ndb[]> = (await db).all<NdbDbData[]>(SQL`
SELECT
ident, name, frequency, laty, lonx
FROM
ndb
WHERE
region = 'VT'
`);
`)
.then(addIsExtra(false));

const ids = `(${extra.join(',')})`;
const extraNdbs: Promise<Ndb[]> = (await db).all<NdbDbData[]>(
SQL`
SELECT
N.ident, N.name, N.frequency, N.laty, N.lonx
FROM
(
waypoint W
INNER JOIN
ndb N
ON W.nav_id = N.ndb_id

const extraNdbs: Promise<Ndb[]> = (await db)
.all<NdbDbExtraRow[]>(
SQL`
SELECT
W.waypoint_id AS waypoint_id,
N.ident, N.name, N.frequency, N.laty, N.lonx
FROM
waypoint W
INNER JOIN ndb N ON W.nav_id = N.ndb_id
WHERE
W.waypoint_id IN
`.append(ids).append(SQL`
AND W.type = 'N'
`)
)
WHERE
w.waypoint_id IN
`.append(ids).append(SQL`
AND
W.type = 'N'
`)
);
.then((rows) =>
rows.map((r) => {
const { waypoint_id, ...rest } = r;
const isExtraFlag = !boundarySet.has(waypoint_id); // boundary-linked → NOT extra
return {
...rest,
is_extra: isExtraFlag
} as Ndb;
})
);

return (await ndbs).concat(await extraNdbs);
};
};
Loading