mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Merge pull request #487 from bilawalsidhu/refactor/portable-firms-csv
refactor: expose portable FIRMS CSV helpers
This commit is contained in:
7 files changed
+83
-4
No files matched your search
@@ -91,6 +91,8 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Expose existing FIRMS CSV parsing and UTC time-window helpers through a portable package export, with shared contract fixtures.
|
||||||
|
|
||||||
- Separate map source factories from switching and resource ownership; retain current source IDs, attribution and fallbacks.
|
- Separate map source factories from switching and resource ownership; retain current source IDs, attribution and fallbacks.
|
||||||
|
|
||||||
- Separate radio directory loading, station selection, globe presentation and playback into composed components with an explicit metadata source.
|
- Separate radio directory loading, station selection, globe presentation and playback into composed components with an explicit metadata source.
|
||||||
|
|||||||
@@ -144,9 +144,14 @@ reconstruction mechanics with injectable acquisition dependencies.
|
|||||||
`gods-eye-view/sources/traffic` exports tile math and budget calculations.
|
`gods-eye-view/sources/traffic` exports tile math and budget calculations.
|
||||||
`gods-eye-view/sources/gbfs` exports host/path acceptance and cache-header rules.
|
`gods-eye-view/sources/gbfs` exports host/path acceptance and cache-header rules.
|
||||||
These entries import no Node middleware, application configuration or rendering.
|
These entries import no Node middleware, application configuration or rendering.
|
||||||
Callers retain their request admission and transport policy. FIRMS CSV parsing
|
Callers retain their request admission and transport policy.
|
||||||
remains an owned dependency of the FIRMS Node provider. The boundary gate
|
|
||||||
checks each entry independently.
|
`gods-eye-view/sources/firms-csv` exports the existing CSV parser, header
|
||||||
|
recognition, acquisition-time conversion and trailing-day filter independently
|
||||||
|
of the Node middleware. It imports no Node, DOM, rendering or network code.
|
||||||
|
The Node provider continues using the same implementation; contract fixtures
|
||||||
|
cover malformed rows, acquisition times, empty feeds and the inclusive time
|
||||||
|
window. The boundary gate checks each entry independently.
|
||||||
|
|
||||||
Browser terrain sampling, traffic matching/drawing, fire overlays and bike-share
|
Browser terrain sampling, traffic matching/drawing, fire overlays and bike-share
|
||||||
layer lifecycle remain in their current modules. This extraction changes no
|
layer lifecycle remain in their current modules. This extraction changes no
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# God's Eye View Current State
|
# God's Eye View Current State
|
||||||
|
|
||||||
|
The `sources/firms-csv` package export exposes existing FIRMS CSV parsing and
|
||||||
|
UTC acquisition-window helpers without Node middleware or rendering dependencies.
|
||||||
|
The standalone FIRMS provider, source defaults and parsing behavior are unchanged.
|
||||||
|
|
||||||
CLI tools and development launchers accept `GEV_PROJECT_ROOT` to select the project environment, dependencies and output directory. Their default remains this checkout; bundled tool resources and source checks stay relative to the script installation. The setup doctor also accepts an explicit `rootDir`.
|
CLI tools and development launchers accept `GEV_PROJECT_ROOT` to select the project environment, dependencies and output directory. Their default remains this checkout; bundled tool resources and source checks stay relative to the script installation. The setup doctor also accepts an explicit `rootDir`.
|
||||||
|
|
||||||
Application composition now uses shared scene/control/catalog/tool constructors and allowlisted HTML component templates. The standalone entry supplies settings and the default sources. Terrain, boundaries, weather, regional context and summaries use configurable services; renderer/action owners remain page-scoped. Annotation proximity guards remain on by default and allow distant targets only for explicit navigation.
|
Application composition now uses shared scene/control/catalog/tool constructors and allowlisted HTML component templates. The standalone entry supplies settings and the default sources. Terrain, boundaries, weather, regional context and summaries use configurable services; renderer/action owners remain page-scoped. Annotation proximity guards remain on by default and allow distant targets only for explicit navigation.
|
||||||
|
|||||||
@@ -148,6 +148,7 @@
|
|||||||
"./aircraft": "./src/layers/aircraft/index.js",
|
"./aircraft": "./src/layers/aircraft/index.js",
|
||||||
"./layers/vessels": "./src/layers/vessels/index.js",
|
"./layers/vessels": "./src/layers/vessels/index.js",
|
||||||
"./layers/earthquakes": "./src/layers/earthquakes/index.js",
|
"./layers/earthquakes": "./src/layers/earthquakes/index.js",
|
||||||
|
"./sources/firms-csv": "./src/data/firmsCsv.js",
|
||||||
"./layers/firms": "./src/layers/firms/index.js",
|
"./layers/firms": "./src/layers/firms/index.js",
|
||||||
"./layers/satellites": "./src/layers/satellites/index.js",
|
"./layers/satellites": "./src/layers/satellites/index.js",
|
||||||
"./layers/launches": "./src/layers/launches/index.js",
|
"./layers/launches": "./src/layers/launches/index.js",
|
||||||
|
|||||||
@@ -115,6 +115,11 @@
|
|||||||
"modules": ["src/data/tomtomTiles.js"],
|
"modules": ["src/data/tomtomTiles.js"],
|
||||||
"external": []
|
"external": []
|
||||||
},
|
},
|
||||||
|
"firms-csv": {
|
||||||
|
"exports": ["./sources/firms-csv"],
|
||||||
|
"modules": ["src/data/firmsCsv.js"],
|
||||||
|
"external": []
|
||||||
|
},
|
||||||
"firms-provider": {
|
"firms-provider": {
|
||||||
"runtime": "node",
|
"runtime": "node",
|
||||||
"exports": ["./server/providers/firms"],
|
"exports": ["./server/providers/firms"],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
filterTrailing24h,
|
filterTrailing24h,
|
||||||
isLikelyCsv,
|
isLikelyCsv,
|
||||||
parseFirmsCsv,
|
parseFirmsCsv,
|
||||||
} from './firmsCsv.js';
|
} from 'gods-eye-view/sources/firms-csv';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const FIXTURE = fs.readFileSync(
|
const FIXTURE = fs.readFileSync(
|
||||||
@@ -144,3 +144,21 @@ test('filterTrailing24h on the fixture keeps everything for a same-night now', (
|
|||||||
const kept = filterTrailing24h(records, Date.UTC(2026, 6, 17, 2, 0));
|
const kept = filterTrailing24h(records, Date.UTC(2026, 6, 17, 2, 0));
|
||||||
assert.equal(kept.length, records.length);
|
assert.equal(kept.length, records.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const contractCases = JSON.parse(
|
||||||
|
fs.readFileSync(
|
||||||
|
path.join(__dirname, 'fixtures', 'firms-csv-cases.json'),
|
||||||
|
'utf8',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
for (const fixture of contractCases) {
|
||||||
|
test(`portable FIRMS CSV contract: ${fixture.name}`, () => {
|
||||||
|
const records = parseFirmsCsv(fixture.csv);
|
||||||
|
assert.equal(records === null ? null : records.length, fixture.parsedCount);
|
||||||
|
const recent = filterTrailing24h(records, Date.parse(fixture.now));
|
||||||
|
assert.deepEqual(
|
||||||
|
recent.map((record) => record.acqTime),
|
||||||
|
fixture.recentTimes,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "categorical confidence and unpadded midnight time",
|
||||||
|
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-16,45,n,12\n",
|
||||||
|
"now": "2026-07-16T12:00:00Z",
|
||||||
|
"parsedCount": 1,
|
||||||
|
"recentTimes": ["45"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "truncated rows are omitted",
|
||||||
|
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-16,1200\n",
|
||||||
|
"now": "2026-07-16T12:00:00Z",
|
||||||
|
"parsedCount": 0,
|
||||||
|
"recentTimes": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "invalid acquisition hour does not roll into tomorrow",
|
||||||
|
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-15,2400,n,12\n",
|
||||||
|
"now": "2026-07-16T12:00:00Z",
|
||||||
|
"parsedCount": 1,
|
||||||
|
"recentTimes": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inclusive trailing day and two-hour forward slack",
|
||||||
|
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-15,1200,n,12\n30,-97,2026-07-15,1159,n,12\n30,-97,2026-07-16,1400,h,12\n30,-97,2026-07-16,1401,l,12\n",
|
||||||
|
"now": "2026-07-16T12:00:00Z",
|
||||||
|
"parsedCount": 4,
|
||||||
|
"recentTimes": ["1200", "1400"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "upstream error is different from an empty catalog",
|
||||||
|
"csv": "Invalid MAP_KEY",
|
||||||
|
"now": "2026-07-16T12:00:00Z",
|
||||||
|
"parsedCount": null,
|
||||||
|
"recentTimes": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "header-only catalog is successful and empty",
|
||||||
|
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n",
|
||||||
|
"now": "2026-07-16T12:00:00Z",
|
||||||
|
"parsedCount": 0,
|
||||||
|
"recentTimes": []
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in new issue
Block a user