Compare commits

..

No commits in common. "b678f1ecaa03513f67bb00dd2ec92e5d146514c7" and "fc5a7ed31b562a46f4e9f3efa0466f48eeb9de48" have entirely different histories.

View file

@ -539,7 +539,6 @@ const liveMarkers = new Map(); // imei → maplibregl.Marker (individual vehicl
const clusterMarkers = new Map(); // cluster_id → maplibregl.Marker (count bubbles) const clusterMarkers = new Map(); // cluster_id → maplibregl.Marker (count bubbles)
let liveFeatures = []; // deduped (one device per vehicle) — see dedupeLiveFeatures let liveFeatures = []; // deduped (one device per vehicle) — see dedupeLiveFeatures
let cluster = null; // Supercluster index of the currently-filtered fleet let cluster = null; // Supercluster index of the currently-filtered fleet
let liveSpecialists = []; // crane/motorbike/pick-up — drawn individually, never clustered
const CLUSTER_RADIUS = 60; // px cluster radius const CLUSTER_RADIUS = 60; // px cluster radius
const CLUSTER_MAXZOOM = 11; // above this, clusters disband into individual pins (~city zoom) const CLUSTER_MAXZOOM = 11; // above this, clusters disband into individual pins (~city zoom)
const VEHICLE_META = new Map(); // plate → {cost_centre, assigned_city} const VEHICLE_META = new Map(); // plate → {cost_centre, assigned_city}
@ -736,22 +735,12 @@ function filteredLiveFeatures() {
}); });
} }
// A vehicle is exempt from clustering exactly when it carries a specialist icon
// (crane / motorbike / pick-up) — keyed off the feed's vehicle_type / fleet_segment.
function isSpecialist(p) {
return !!(p && (SPECIALIST_ICONS[p.vehicle_type] || p.fleet_segment === 'specialist'));
}
// Load the filtered fleet into supercluster, redraw bubbles+pins, recompute KPIs. // Load the filtered fleet into supercluster, redraw bubbles+pins, recompute KPIs.
function applyLiveFilters() { function applyLiveFilters() {
if (mode !== 'live') return; if (mode !== 'live') return;
const filtered = filteredLiveFeatures(); const filtered = filteredLiveFeatures();
// Specialists are never clustered — they always render as individual icons so
// they stand out. Only the rest of the fleet feeds supercluster.
liveSpecialists = filtered.filter(f => isSpecialist(f.properties));
const clusterable = filtered.filter(f => !isSpecialist(f.properties));
cluster = new Supercluster({ radius: CLUSTER_RADIUS, maxZoom: CLUSTER_MAXZOOM }); cluster = new Supercluster({ radius: CLUSTER_RADIUS, maxZoom: CLUSTER_MAXZOOM });
cluster.load(clusterable.map(f => ({ cluster.load(filtered.map(f => ({
type: 'Feature', type: 'Feature',
properties: { ...f.properties }, properties: { ...f.properties },
geometry: { type: 'Point', coordinates: f.geometry.coordinates }, geometry: { type: 'Point', coordinates: f.geometry.coordinates },
@ -810,12 +799,6 @@ function renderClusters() {
upsertLiveMarker(it.properties, c, it); upsertLiveMarker(it.properties, c, it);
} }
}); });
// Specialists: always drawn individually, at every zoom (never clustered).
liveSpecialists.forEach(f => {
if (!Array.isArray(f.geometry && f.geometry.coordinates)) return;
seenVeh.add(f.properties.imei);
upsertLiveMarker(f.properties, f.geometry.coordinates, f);
});
for (const [imei, m] of liveMarkers) { if (!seenVeh.has(imei)) { m.remove(); liveMarkers.delete(imei); } } for (const [imei, m] of liveMarkers) { if (!seenVeh.has(imei)) { m.remove(); liveMarkers.delete(imei); } }
for (const [id, m] of clusterMarkers) { if (!seenClu.has(id)) { m.remove(); clusterMarkers.delete(id); } } for (const [id, m] of clusterMarkers) { if (!seenClu.has(id)) { m.remove(); clusterMarkers.delete(id); } }
// If the popped-open vehicle got absorbed into a cluster, close its popup. // If the popped-open vehicle got absorbed into a cluster, close its popup.