1/** 2 * Loads asset data from /data/assets/. 3 * loadAssetsForMap() â returns slim summary objects from index.json (1 request). 4 * loadAsset(id) â returns full asset record on demand (1 request per call). 5 * loadAllAssets() â legacy: fetches every full asset file (100 requests, kept for finance-wizard). 6 */ 7 8const BASE = ''; 9 10export async function loadAssetsIndex() { 11 const res = await fetch(`${BASE}/data/assets/index.json`); 12 if (!res.ok) throw new Error(`Failed to load assets index: ${res.status}`); 13 const raw = await res.json(); 14 // index.json is a flat array of full asset objects 15 return Array.isArray(raw) ? raw : (raw.assets ?? []); 16} 17 18/** 19 * Returns asset objects shaped for map display, popups, filters, and 20 * aggregation â no individual asset fetches needed. 21 * Full record is loaded lazily via loadAsset(id) when detail/finance is needed. 22 */ 23export async function loadAssetsForMap() { 24 const index = await loadAssetsIndex(); 25 return index.map(item => { 26 // index.json contains full asset objects with nested structure 27 const cp = item.cost_paths ?? {}; 28 const baseline = cp.baseline ?? null; 29 const cc = cp.code_compliant ?? null; 30 const bbb = cp.build_back_better ?? null; 31 const baselineFs = item.financing_structures?.baseline ?? {}; 32 const financingClass = 33 baselineFs._financing_class ?? 34 ((baselineFs.grant_pct ?? 0) >= 50 ? 'grant_led' : 'mixed'); 35 36 return { 37 asset_id: item.asset_id, 38 name: { 39 en: item.name?.en ?? item.asset_id, 40 uk: item.name?.uk ?? item.name?.en ?? item.asset_id, 41 }, 42 location: { 43 lat: item.location?.lat, 44 lon: item.location?.lon, 45 oblast: item.location?.oblast ?? '', 46 }, 47 sector: item.sector, 48 wartime_status: { 49 lifecycle: item.wartime_status?.lifecycle, 50 rebuildability: item.wartime_status?.rebuildability, 51 }, 52 damage: { 53 destruction_level: item.damage?.destruction_level, 54 re_damage_count: item.damage?.re_damage_count ?? 0, 55 }, 56 cost_paths: { 57 pending_methodology: cp.pending_methodology ?? false, 58 baseline, 59 code_compliant: cc, 60 build_back_better: bbb, 61 }, 62 financing_structures: { 63 baseline: { _financing_class: financingClass }, 64 code_compliant: { _financing_class: financingClass }, 65 build_back_better: { _financing_class: financingClass }, 66 }, 67 _slim: true, 68 }; 69 }); 70} 71 72export async function loadAsset(id) { 73 const res = await fetch(`${BASE}/data/assets/${encodeURIComponent(id)}.json`); 74 if (!res.ok) throw new Error(`Failed to load asset ${id}: ${res.status}`); 75 return res.json(); 76} 77 78export async function loadAllAssets() { 79 const index = await loadAssetsIndex(); 80 // index.json is already the full asset objects; no need for individual fetches 81 return index; 82} 83 84export async function loadOblastsGeoJSON() { 85 const res = await fetch(`${BASE}/data/geo/ua_oblasts.geojson`); 86 if (!res.ok) throw new Error(`Failed to load oblasts GeoJSON: ${res.status}`); 87 return res.json(); 88}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.