76 lines
2.0 KiB
TypeScript
76 lines
2.0 KiB
TypeScript
import { normalizeShipName } from "./normalizeShipName";
|
|
import type { LegacyVesselInfo } from "../model/types";
|
|
|
|
export type LegacyVesselIndex = {
|
|
byName: Map<string, LegacyVesselInfo>;
|
|
byMmsi: Map<number, LegacyVesselInfo>;
|
|
};
|
|
|
|
function score(v: LegacyVesselInfo) {
|
|
// Prefer records that were merged from more sources.
|
|
return Number(!!v.sources.permittedList) + Number(!!v.sources.checklist) + Number(!!v.sources.fleet906);
|
|
}
|
|
|
|
export function buildLegacyVesselIndex(vessels: LegacyVesselInfo[]): LegacyVesselIndex {
|
|
const byName = new Map<string, LegacyVesselInfo>();
|
|
const byMmsi = new Map<number, LegacyVesselInfo>();
|
|
|
|
for (const v of vessels) {
|
|
const keys = new Set<string>();
|
|
if (v.shipNameRoman) keys.add(normalizeShipName(v.shipNameRoman));
|
|
if (v.shipNameCn) keys.add(normalizeShipName(v.shipNameCn));
|
|
if (v.callSign) keys.add(normalizeShipName(v.callSign));
|
|
|
|
for (const k of keys) {
|
|
if (!k) continue;
|
|
const prev = byName.get(k);
|
|
if (!prev) {
|
|
byName.set(k, v);
|
|
continue;
|
|
}
|
|
if (score(v) > score(prev)) byName.set(k, v);
|
|
}
|
|
|
|
for (const m of v.mmsiList || []) {
|
|
if (!Number.isFinite(m)) continue;
|
|
const prev = byMmsi.get(m);
|
|
if (!prev) {
|
|
byMmsi.set(m, v);
|
|
continue;
|
|
}
|
|
if (score(v) > score(prev)) byMmsi.set(m, v);
|
|
}
|
|
}
|
|
|
|
return { byName, byMmsi };
|
|
}
|
|
|
|
export type LegacyMatchable = {
|
|
mmsi?: number;
|
|
name?: string;
|
|
callsign?: string;
|
|
};
|
|
|
|
export function matchLegacyVessel(t: LegacyMatchable, idx: LegacyVesselIndex): LegacyVesselInfo | null {
|
|
const mmsi = t.mmsi;
|
|
if (typeof mmsi === "number") {
|
|
const hit = idx.byMmsi.get(mmsi);
|
|
if (hit) return hit;
|
|
}
|
|
|
|
const nameKey = t.name ? normalizeShipName(t.name) : "";
|
|
if (nameKey) {
|
|
const hit = idx.byName.get(nameKey);
|
|
if (hit) return hit;
|
|
}
|
|
|
|
const csKey = t.callsign ? normalizeShipName(t.callsign) : "";
|
|
if (csKey) {
|
|
const hit = idx.byName.get(csKey);
|
|
if (hit) return hit;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|