const assert = require('node:assert/strict'); const test = require('node:test'); const { PassengerTelemetryAggregator } = require('../src/services/passengerTelemetryAggregator'); const NOW = new Date('2026-05-20T12:30:00Z'); const routeRows = [{ id: 1, route_number: '12', name: 'Route 12', type: 'bus', color: '#0066CC', stops: [ { stop_id: 1, sequence: 1, latitude: 55.485, longitude: 28.768 }, { stop_id: 2, sequence: 2, latitude: 55.485, longitude: 28.778 } ] }]; function createPool(rows = routeRows) { return { async query(sql, params = []) { if (params.length > 0) { return { rows: rows.filter((row) => row.id === params[0]) }; } return { rows }; } }; } function createAggregator(options = {}) { return new PassengerTelemetryAggregator({ pool: createPool(options.rows), nowProvider: () => NOW, ...options }); } async function ingestCluster(aggregator, accuracyM = 18) { await aggregator.ingest({ session_id: 'session-a', latitude: 55.48502, longitude: 28.7700, accuracy_m: accuracyM, speed_kmh: 31, heading: 90, observed_at: '2026-05-20T12:29:55Z', route_id: 1 }); await aggregator.ingest({ session_id: 'session-b', latitude: 55.48498, longitude: 28.77015, accuracy_m: accuracyM, speed_kmh: 33, heading: 92, observed_at: '2026-05-20T12:29:58Z', route_id: 1 }); } test('one passenger point does not create a virtual vehicle', async () => { const aggregator = createAggregator(); const result = await aggregator.ingest({ session_id: 'session-a', latitude: 55.485, longitude: 28.770, accuracy_m: 18, speed_kmh: 32, heading: 90, observed_at: '2026-05-20T12:29:55Z', route_id: 1 }); assert.equal(result.accepted, true); assert.equal(result.matched, true); assert.deepEqual(result.virtualVehicles, []); assert.deepEqual(await aggregator.getVirtualVehiclesForRoute(1), []); }); test('nearby points from distinct sessions create a virtual crowdsourced vehicle', async () => { const aggregator = createAggregator(); await ingestCluster(aggregator); const vehicles = await aggregator.getVirtualVehiclesForRoute(1); assert.equal(vehicles.length, 1); assert.match(vehicles[0].vehicle_id, /^crowd:1:/); assert.equal(vehicles[0].source, 'crowdsourced'); assert.equal(vehicles[0].source_ref, null); assert.equal(vehicles[0].is_estimated, true); assert.equal('session_id' in vehicles[0], false); assert.equal('session_key' in vehicles[0], false); }); test('poor accuracy lowers crowdsourced confidence', async () => { const goodAggregator = createAggregator(); await ingestCluster(goodAggregator, 15); const [goodVehicle] = await goodAggregator.getVirtualVehiclesForRoute(1); const poorAggregator = createAggregator(); await ingestCluster(poorAggregator, 150); const [poorVehicle] = await poorAggregator.getVirtualVehiclesForRoute(1); assert.ok(goodVehicle.confidence > poorVehicle.confidence); assert.equal(poorVehicle.source, 'crowdsourced'); }); test('points outside route geometry are accepted but ignored', async () => { const aggregator = createAggregator(); const result = await aggregator.ingest({ session_id: 'session-a', latitude: 56.0, longitude: 29.5, accuracy_m: 20, observed_at: '2026-05-20T12:29:55Z', route_id: 1 }); assert.equal(result.accepted, true); assert.equal(result.matched, false); assert.deepEqual(await aggregator.getVirtualVehiclesForRoute(1), []); }); test('official telemetry suppresses nearby crowdsourced virtual vehicle', async () => { const aggregator = createAggregator(); await ingestCluster(aggregator); const [vehicle] = await aggregator.getVirtualVehiclesForRoute(1); assert.ok(vehicle); const suppressed = await aggregator.getVirtualVehiclesForRoute(1, { officialVehicles: [{ vehicle_id: 99, latitude: vehicle.latitude, longitude: vehicle.longitude, is_online: true }] }); assert.deepEqual(suppressed, []); });