import assert from 'node:assert/strict'; import test from 'node:test'; import { buildVehicleGrid, buildVehicleRanking, daysInclusive, filterVehicleRecordsByRadius, haversineKm, parseNearbyQuery, parseVehicleHeatmapQuery, summarizeVehicleRecords, vehicleGridPrecision, type VehicleHeatmapRecord, } from './vehicle-heatmap-model.js'; function record(overrides: Partial = {}): VehicleHeatmapRecord { return { date: '2026-07-01', vin: 'VIN-A', plate: '粤A00001', time: '2026-07-01 08:00:00', longitude: 120, latitude: 30, source: 'test', sourceRecordId: '1', ...overrides, }; } test('车辆热力图查询继续使用固定默认日期和原有字符串处理规则', () => { assert.deepEqual(parseVehicleHeatmapQuery({}), { startDate: '2026-01-01', endDate: '2026-07-13', query: '', batchModel: '', metric: 'locations', }); assert.deepEqual(parseVehicleHeatmapQuery({ startDate: '2026-06-01', endDate: 'invalid', query: ' 粤A ', batchModel: ' 190台冷链 ', metric: 'vehicles', }), { startDate: '2026-06-01', endDate: '2026-07-13', query: ' 粤A ', batchModel: '190台冷链', metric: 'vehicles', }); }); test('附近查询继续沿用经纬度 Number 语义和 5 至 200 公里半径限制', () => { assert.deepEqual(parseNearbyQuery({ lng: '', lat: '0', radiusKm: '0' }), { center: { lng: 0, lat: 0 }, radiusKm: 50, }); assert.deepEqual(parseNearbyQuery({ lng: '120', lat: '30', radiusKm: '-1' }), { center: { lng: 120, lat: 30 }, radiusKm: 5, }); assert.equal(parseNearbyQuery({ lng: '120', lat: '30', radiusKm: '500' }).radiusKm, 200); assert.equal(parseNearbyQuery({ lng: 'bad', lat: '30' }).center, null); }); test('网格精度继续按含首尾天数和筛选条件决定', () => { assert.equal(daysInclusive('2026-07-01', '2026-07-14'), 14); assert.equal(daysInclusive('2026-07-14', '2026-07-01'), 0); assert.equal(vehicleGridPrecision('2026-07-01', '2026-07-14', '', ''), 3); assert.equal(vehicleGridPrecision('2026-07-01', '2026-07-15', '', ''), 2); assert.equal(vehicleGridPrecision('2026-07-01', '2026-07-15', ' ', ''), 3); }); test('车辆网格继续区分位置次数和去重车辆数并保留插入顺序', () => { const records = [ record({ vin: 'VIN-A', longitude: 120.1231, latitude: 30.9878 }), record({ vin: 'VIN-A', longitude: 120.1232, latitude: 30.9879 }), record({ vin: 'VIN-B', longitude: 120.1233, latitude: 30.9877 }), record({ vin: 'VIN-C', longitude: 121, latitude: 31 }), ]; assert.deepEqual(buildVehicleGrid(records, 'locations', 3), { points: [ { lng: 120.123, lat: 30.988, count: 3 }, { lng: 121, lat: 31, count: 1 }, ], max: 3, }); assert.deepEqual(buildVehicleGrid(records, 'vehicles', 3), { points: [ { lng: 120.123, lat: 30.988, count: 2 }, { lng: 121, lat: 31, count: 1 }, ], max: 2, }); assert.deepEqual(buildVehicleGrid([], 'locations', 2), { points: [], max: 1 }); }); test('车辆排名继续按记录数、车牌排序并保留首末出现时间', () => { const records = [ record({ vin: 'VIN-B', plate: '', time: '2026-07-02 10:00:00' }), record({ vin: 'VIN-A', plate: '粤A00001', time: '2026-07-02 09:00:00' }), record({ vin: 'VIN-B', plate: '粤B00001', time: '2026-07-01 08:00:00' }), record({ vin: 'VIN-A', plate: '粤A00001', time: '2026-07-03 11:00:00' }), ]; assert.deepEqual(buildVehicleRanking(records), [ { vin: 'VIN-A', plateNumber: '粤A00001', locationCount: 2, firstSeen: '2026-07-02 09:00:00', lastSeen: '2026-07-03 11:00:00', }, { vin: 'VIN-B', plateNumber: '粤B00001', locationCount: 2, firstSeen: '2026-07-01 08:00:00', lastSeen: '2026-07-02 10:00:00', }, ]); assert.equal(buildVehicleRanking(records, 1).length, 1); }); test('车辆统计和附近筛选继续使用 VIN、自然日去重及 Haversine 距离', () => { const records = [ record({ vin: 'VIN-A', date: '2026-07-01' }), record({ vin: 'VIN-A', date: '2026-07-02', longitude: 120.01 }), record({ vin: 'VIN-B', date: '2026-07-02', longitude: 121 }), ]; assert.deepEqual(summarizeVehicleRecords(records), { locationCount: 3, vehicleCount: 2, dayCount: 2, }); assert.equal(haversineKm(120, 30, 120, 30), 0); assert.ok(Math.abs(haversineKm(0, 0, 0, 1) - 111.195) < 0.01); assert.deepEqual( filterVehicleRecordsByRadius(records, { lng: 120, lat: 30 }, 5).map(({ vin, date }) => ({ vin, date })), [ { vin: 'VIN-A', date: '2026-07-01' }, { vin: 'VIN-A', date: '2026-07-02' }, ], ); });