mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
refactor: move infrastructure data parsing into a portable source module
The datacenter and dam layers parsed their bundled GeoJSON Lines and built analyst records inside the Cesium-backed layer module. Move the data URLs, the line parser, mapAnalystRecord and layerTitle unchanged to src/sources/infrastructureData.js; the layer module imports them and still exports mapAnalystRecord. The consumer-build pin lists the new module.
This commit is contained in:
1 parent
0a454815cb
commit
a8e5ff9390
5 files changed
+120
-92
No files matched your search
@@ -10,7 +10,8 @@
|
|||||||
"src/data/localGeojsonCore.js",
|
"src/data/localGeojsonCore.js",
|
||||||
"src/data/localGeojsonLod.js",
|
"src/data/localGeojsonLod.js",
|
||||||
"src/data/inputOwnership.js",
|
"src/data/inputOwnership.js",
|
||||||
"src/data/infrastructureOverlayEntry.js"
|
"src/data/infrastructureOverlayEntry.js",
|
||||||
|
"src/sources/infrastructureData.js"
|
||||||
],
|
],
|
||||||
"external": ["cesium"]
|
"external": ["cesium"]
|
||||||
},
|
},
|
||||||
@@ -2034,7 +2035,8 @@
|
|||||||
"src/sources/requestDeadline.js",
|
"src/sources/requestDeadline.js",
|
||||||
"src/data/local_data/osm_military_names/names.json",
|
"src/data/local_data/osm_military_names/names.json",
|
||||||
"src/layers/installations/namedMarkers.js",
|
"src/layers/installations/namedMarkers.js",
|
||||||
"src/data/infrastructureOverlayEntry.js"
|
"src/data/infrastructureOverlayEntry.js",
|
||||||
|
"src/sources/infrastructureData.js"
|
||||||
],
|
],
|
||||||
"external": [
|
"external": [
|
||||||
"hls.js",
|
"hls.js",
|
||||||
@@ -2520,7 +2522,8 @@
|
|||||||
"src/sources/requestDeadline.js",
|
"src/sources/requestDeadline.js",
|
||||||
"src/data/local_data/osm_military_names/names.json",
|
"src/data/local_data/osm_military_names/names.json",
|
||||||
"src/layers/installations/namedMarkers.js",
|
"src/layers/installations/namedMarkers.js",
|
||||||
"src/data/infrastructureOverlayEntry.js"
|
"src/data/infrastructureOverlayEntry.js",
|
||||||
|
"src/sources/infrastructureData.js"
|
||||||
],
|
],
|
||||||
"external": [
|
"external": [
|
||||||
"hls.js",
|
"hls.js",
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import { createLocalGeoJsonLayer } from './localGeojsonCore.js';
|
import { createLocalGeoJsonLayer } from './localGeojsonCore.js';
|
||||||
|
import { INFRASTRUCTURE_DATA_URLS } from '../sources/infrastructureData.js';
|
||||||
|
|
||||||
// Resolved by Vite in builds and relative to this module in other consumers.
|
const datacentersUrl = INFRASTRUCTURE_DATA_URLS['local-datacenters'];
|
||||||
const datacentersUrl = new URL(
|
const damsUrl = INFRASTRUCTURE_DATA_URLS['local-dams'];
|
||||||
'./local_data/datacenters/datacenters.geojsonl',
|
|
||||||
import.meta.url,
|
|
||||||
).href;
|
|
||||||
const damsUrl = new URL('./local_data/dams/dams.geojsonl', import.meta.url)
|
|
||||||
.href;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create fresh datacenter and dam layers without starting or loading them.
|
* Create fresh datacenter and dam layers without starting or loading them.
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ test('consumer build includes only infrastructure code and resolves assets under
|
|||||||
const sources = Object.keys(entry.modules).filter((id) => id.endsWith('.js'));
|
const sources = Object.keys(entry.modules).filter((id) => id.endsWith('.js'));
|
||||||
assert.deepEqual(sources.map((id) => id.split('/').at(-1)).sort(), [
|
assert.deepEqual(sources.map((id) => id.split('/').at(-1)).sort(), [
|
||||||
'infrastructure.js',
|
'infrastructure.js',
|
||||||
|
'infrastructureData.js',
|
||||||
'infrastructureOverlayEntry.js',
|
'infrastructureOverlayEntry.js',
|
||||||
'localGeojsonCore.js',
|
'localGeojsonCore.js',
|
||||||
'localGeojsonLod.js',
|
'localGeojsonLod.js',
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import * as Cesium from 'cesium';
|
import * as Cesium from 'cesium';
|
||||||
|
import {
|
||||||
|
layerTitle,
|
||||||
|
mapAnalystRecord,
|
||||||
|
parseGeojsonLines,
|
||||||
|
} from '../sources/infrastructureData.js';
|
||||||
import { createInfrastructureOverlayEntry } from './infrastructureOverlayEntry.js';
|
import { createInfrastructureOverlayEntry } from './infrastructureOverlayEntry.js';
|
||||||
import { isPointerFree } from './inputOwnership.js';
|
import { isPointerFree } from './inputOwnership.js';
|
||||||
import {
|
import {
|
||||||
@@ -86,78 +91,6 @@ export function localInfrastructureOverlayCopy(properties, layerId) {
|
|||||||
return { title, details };
|
return { title, details };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Map one local infrastructure feature to a JSON-safe analyst record
|
|
||||||
* (analyst query engine seam). Pure — no Cesium types. Missing/unknown
|
|
||||||
* fields are null, never NaN/undefined. Layer-specific fields that do not
|
|
||||||
* apply (river/output on datacenters, capacity on dams) stay null so a
|
|
||||||
* shared compact payload can copy them without inventing values.
|
|
||||||
* Names are unclamped — overlay cards shorten for paint; queries need the
|
|
||||||
* full source string ("Usina Hidrelétrica de Itaipu").
|
|
||||||
* @param {Object|null|undefined} raw - {id, lat, lon, properties}.
|
|
||||||
* @param {string} [layerId] Local layer id (`local-datacenters` / `local-dams`).
|
|
||||||
* @returns {{id: string, name: string|null, lat: number|null, lon: number|null,
|
|
||||||
* operator: string|null, capacity: string|null, river: string|null,
|
|
||||||
* output: string|null}}
|
|
||||||
*/
|
|
||||||
export function mapAnalystRecord(raw, layerId = '') {
|
|
||||||
const num = (v) => (Number.isFinite(v) ? v : null);
|
|
||||||
const text = (v) => {
|
|
||||||
const t = String(v ?? '').trim();
|
|
||||||
return t && t !== 'undefined' && t !== 'null' ? t : null;
|
|
||||||
};
|
|
||||||
const props =
|
|
||||||
raw?.properties &&
|
|
||||||
typeof raw.properties === 'object' &&
|
|
||||||
!Array.isArray(raw.properties)
|
|
||||||
? raw.properties
|
|
||||||
: {};
|
|
||||||
const tags =
|
|
||||||
props.tags && typeof props.tags === 'object' && !Array.isArray(props.tags)
|
|
||||||
? props.tags
|
|
||||||
: {};
|
|
||||||
const name =
|
|
||||||
text(props.name) ||
|
|
||||||
text(tags.name) ||
|
|
||||||
text(tags['name:en']) ||
|
|
||||||
text(tags.official_name) ||
|
|
||||||
null;
|
|
||||||
const operator =
|
|
||||||
text(tags.operator) ||
|
|
||||||
text(props.operator) ||
|
|
||||||
text(tags['operator:short']) ||
|
|
||||||
null;
|
|
||||||
const capacity =
|
|
||||||
layerId === 'local-datacenters'
|
|
||||||
? text(tags['capacity:it_load']) ||
|
|
||||||
text(tags.it_load) ||
|
|
||||||
text(tags.capacity) ||
|
|
||||||
text(props.capacity)
|
|
||||||
: null;
|
|
||||||
const river =
|
|
||||||
layerId === 'local-dams'
|
|
||||||
? text(tags.associated_river) ||
|
|
||||||
text(props.associated_river) ||
|
|
||||||
text(tags.river) ||
|
|
||||||
text(props.river) ||
|
|
||||||
text(tags['river:name'])
|
|
||||||
: null;
|
|
||||||
const output =
|
|
||||||
layerId === 'local-dams'
|
|
||||||
? text(props.output) || text(tags['plant:output:electricity'])
|
|
||||||
: null;
|
|
||||||
return {
|
|
||||||
id: name || text(raw?.id) || layerTitle(layerId),
|
|
||||||
name,
|
|
||||||
lat: num(raw?.lat),
|
|
||||||
lon: num(raw?.lon),
|
|
||||||
operator,
|
|
||||||
capacity,
|
|
||||||
river,
|
|
||||||
output,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce one normalized-contract input owned by a local infrastructure layer.
|
* Produce one normalized-contract input owned by a local infrastructure layer.
|
||||||
* The host revalidates the authoritative `source` value while normalizing it.
|
* The host revalidates the authoritative `source` value while normalizing it.
|
||||||
@@ -664,11 +597,7 @@ export function createLocalGeoJsonLayer(
|
|||||||
}
|
}
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
if (_destroyed) return;
|
if (_destroyed) return;
|
||||||
const lines = text
|
features = parseGeojsonLines(text);
|
||||||
.split('\n')
|
|
||||||
.filter((l) => l.trim().length > 0);
|
|
||||||
|
|
||||||
features = lines.map((line) => JSON.parse(line));
|
|
||||||
_cachedFeatures = features;
|
_cachedFeatures = features;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1360,8 +1289,4 @@ function clampCardLine(value) {
|
|||||||
return text.length > 48 ? `${text.slice(0, 45)}...` : text;
|
return text.length > 48 ? `${text.slice(0, 45)}...` : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function layerTitle(layerId) {
|
export { mapAnalystRecord };
|
||||||
if (layerId === 'local-datacenters') return 'Datacenter';
|
|
||||||
if (layerId === 'local-dams') return 'Dam';
|
|
||||||
return 'Feature';
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Bundled OpenStreetMap infrastructure layers (datacenters and dams): their
|
||||||
|
* data files, line-delimited GeoJSON parsing and analyst records.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Resolved by Vite in builds and relative to this module in other consumers.
|
||||||
|
export const INFRASTRUCTURE_DATA_URLS = Object.freeze({
|
||||||
|
'local-datacenters': new URL(
|
||||||
|
'../data/local_data/datacenters/datacenters.geojsonl',
|
||||||
|
import.meta.url,
|
||||||
|
).href,
|
||||||
|
'local-dams': new URL(
|
||||||
|
'../data/local_data/dams/dams.geojsonl',
|
||||||
|
import.meta.url,
|
||||||
|
).href,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Parse GeoJSON Lines: one Feature per non-empty line. */
|
||||||
|
export function parseGeojsonLines(text) {
|
||||||
|
return String(text)
|
||||||
|
.split('\n')
|
||||||
|
.filter((line) => line.trim().length > 0)
|
||||||
|
.map((line) => JSON.parse(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The singular label for a local infrastructure layer. */
|
||||||
|
export function layerTitle(layerId) {
|
||||||
|
if (layerId === 'local-datacenters') return 'Datacenter';
|
||||||
|
if (layerId === 'local-dams') return 'Dam';
|
||||||
|
return 'Feature';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map one local infrastructure feature to a JSON-safe analyst record
|
||||||
|
* (analyst query engine seam). Pure — no Cesium types. Missing/unknown
|
||||||
|
* fields are null, never NaN/undefined. Layer-specific fields that do not
|
||||||
|
* apply (river/output on datacenters, capacity on dams) stay null so a
|
||||||
|
* shared compact payload can copy them without inventing values.
|
||||||
|
* Names are unclamped — overlay cards shorten for paint; queries need the
|
||||||
|
* full source string ("Usina Hidrelétrica de Itaipu").
|
||||||
|
* @param {Object|null|undefined} raw - {id, lat, lon, properties}.
|
||||||
|
* @param {string} [layerId] Local layer id (`local-datacenters` / `local-dams`).
|
||||||
|
* @returns {{id: string, name: string|null, lat: number|null, lon: number|null,
|
||||||
|
* operator: string|null, capacity: string|null, river: string|null,
|
||||||
|
* output: string|null}}
|
||||||
|
*/
|
||||||
|
export function mapAnalystRecord(raw, layerId = '') {
|
||||||
|
const num = (v) => (Number.isFinite(v) ? v : null);
|
||||||
|
const text = (v) => {
|
||||||
|
const t = String(v ?? '').trim();
|
||||||
|
return t && t !== 'undefined' && t !== 'null' ? t : null;
|
||||||
|
};
|
||||||
|
const props =
|
||||||
|
raw?.properties &&
|
||||||
|
typeof raw.properties === 'object' &&
|
||||||
|
!Array.isArray(raw.properties)
|
||||||
|
? raw.properties
|
||||||
|
: {};
|
||||||
|
const tags =
|
||||||
|
props.tags && typeof props.tags === 'object' && !Array.isArray(props.tags)
|
||||||
|
? props.tags
|
||||||
|
: {};
|
||||||
|
const name =
|
||||||
|
text(props.name) ||
|
||||||
|
text(tags.name) ||
|
||||||
|
text(tags['name:en']) ||
|
||||||
|
text(tags.official_name) ||
|
||||||
|
null;
|
||||||
|
const operator =
|
||||||
|
text(tags.operator) ||
|
||||||
|
text(props.operator) ||
|
||||||
|
text(tags['operator:short']) ||
|
||||||
|
null;
|
||||||
|
const capacity =
|
||||||
|
layerId === 'local-datacenters'
|
||||||
|
? text(tags['capacity:it_load']) ||
|
||||||
|
text(tags.it_load) ||
|
||||||
|
text(tags.capacity) ||
|
||||||
|
text(props.capacity)
|
||||||
|
: null;
|
||||||
|
const river =
|
||||||
|
layerId === 'local-dams'
|
||||||
|
? text(tags.associated_river) ||
|
||||||
|
text(props.associated_river) ||
|
||||||
|
text(tags.river) ||
|
||||||
|
text(props.river) ||
|
||||||
|
text(tags['river:name'])
|
||||||
|
: null;
|
||||||
|
const output =
|
||||||
|
layerId === 'local-dams'
|
||||||
|
? text(props.output) || text(tags['plant:output:electricity'])
|
||||||
|
: null;
|
||||||
|
return {
|
||||||
|
id: name || text(raw?.id) || layerTitle(layerId),
|
||||||
|
name,
|
||||||
|
lat: num(raw?.lat),
|
||||||
|
lon: num(raw?.lon),
|
||||||
|
operator,
|
||||||
|
capacity,
|
||||||
|
river,
|
||||||
|
output,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in new issue
Block a user