refactor: modularize application domains
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
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> = {}): 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' },
|
||||
],
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user