fix(drone-airspace): show FAA times-of-use line breaks as separators

FAA marks line breaks in TIMESOFUSE with a literal %, which 56 live
restricted-area cards showed verbatim ("SAT - SUN; %OTHER TIMES BY NOTAM").
Read each marker as a '; ' separator, absorbing a semicolon already before
it.
This commit is contained in:
Sameh Khamis committed 2026-11-03 14:36:57 -08:00
1 parent add905e6b9
commit 266825eddb
2 files changed
+38 -1

No files matched your search

+9 -1
View File
@@ -18,6 +18,14 @@ const textOrNull = (value) => {
return text ? text : null;
};
/** FAA marks line breaks in TIMESOFUSE with `%`; read them as `; ` separators. */
const timesOfUseOrNull = (value) =>
textOrNull(
typeof value === 'string'
? value.replace(/\s*;?\s*%\s*/g, '; ').replace(/^[;\s]+|[;\s]+$/g, '')
: value,
);
function validRing(ring) {
if (!Array.isArray(ring) || ring.length < 4) return false;
for (const position of ring) {
@@ -116,7 +124,7 @@ export function normalizeDroneAirspaceSnapshot(geojson) {
properties.UPPER_UOM,
properties.UPPER_CODE,
),
timesOfUse: textOrNull(properties.TIMESOFUSE),
timesOfUse: timesOfUseOrNull(properties.TIMESOFUSE),
agency: textOrNull(properties.CONT_AGENT),
city: textOrNull(properties.CITY),
state: textOrNull(properties.STATE),
+29
View File
@@ -133,3 +133,32 @@ test('duplicate ids and a missing collection reject or skip as documented', () =
assert.equal(droneAirspaceTypeLabel('R'), 'Restricted');
assert.equal(droneAirspaceTypeLabel('MOA'), null);
});
test("FAA's % line-break markers in times of use read as separators", () => {
const timesOfUse = (TIMESOFUSE) =>
normalizeDroneAirspaceSnapshot({
features: [
feature({
properties: {
NAME: 'R-2508',
TYPE_CODE: 'R',
OBJECTID: 400,
TIMESOFUSE,
},
}),
],
})[0].timesOfUse;
// The shape 56 live records carry: a marker after the semicolon.
assert.equal(
timesOfUse(
'0700 - 2200 MON - FRI; 0800 - 1600 SAT - SUN; %OTHER TIMES BY NOTAM',
),
'0700 - 2200 MON - FRI; 0800 - 1600 SAT - SUN; OTHER TIMES BY NOTAM',
);
assert.equal(
timesOfUse('SR - SS DAILY %OTHER TIMES BY NOTAM'),
'SR - SS DAILY; OTHER TIMES BY NOTAM',
);
assert.equal(timesOfUse('%CONTINUOUS%'), 'CONTINUOUS');
assert.equal(timesOfUse(' % '), null);
});