import type { AisTarget } from '../../../entities/aisTarget/model/types'; import type { LegacyVesselInfo } from '../../../entities/legacyVessel/model/types'; import { SIGNAL_KIND, SIGNAL_SOURCE_AIS, type LiveShipFeature, type SignalKindCode } from '../model/liveShip.types'; function mapVesselTypeToSignalKind(vesselType: string | undefined): SignalKindCode { if (!vesselType) return SIGNAL_KIND.NORMAL; const vt = vesselType.toLowerCase(); if (vt.includes('fishing')) return SIGNAL_KIND.FISHING; if (vt.includes('passenger')) return SIGNAL_KIND.PASSENGER; if (vt.includes('cargo')) return SIGNAL_KIND.CARGO; if (vt.includes('tanker')) return SIGNAL_KIND.TANKER; if (vt.includes('military') || vt.includes('law') || vt.includes('government')) return SIGNAL_KIND.GOV; if (vt.includes('buoy')) return SIGNAL_KIND.BUOY; return SIGNAL_KIND.NORMAL; } function mapLegacyShipCodeToSignalKind(shipCode: string | undefined): SignalKindCode { if (!shipCode) return SIGNAL_KIND.NORMAL; if (shipCode === 'FC') return SIGNAL_KIND.CARGO; return SIGNAL_KIND.FISHING; } export function toLiveShipFeature(target: AisTarget, legacy: LegacyVesselInfo | undefined | null): LiveShipFeature { const targetId = String(target.mmsi); const signalKindCode = legacy ? mapLegacyShipCodeToSignalKind(legacy.shipCode) : mapVesselTypeToSignalKind(target.vesselType); return { mmsi: target.mmsi, featureId: `${SIGNAL_SOURCE_AIS}${targetId}`, targetId, originalTargetId: targetId, signalSourceCode: SIGNAL_SOURCE_AIS, signalKindCode, shipName: (target.name || '').trim(), longitude: target.lon, latitude: target.lat, sog: Number.isFinite(target.sog) ? target.sog : 0, cog: Number.isFinite(target.cog) ? target.cog : 0, heading: Number.isFinite(target.heading) ? target.heading : 0, messageTimestamp: target.messageTimestamp || target.receivedDate || new Date().toISOString(), nationalCode: legacy ? 'CN' : '', vesselType: target.vesselType, raw: target, }; } export function toLiveShipFeatures( targets: AisTarget[], legacyHits?: Map | null, ): LiveShipFeature[] { const out: LiveShipFeature[] = []; for (const target of targets) { if (!target) continue; if (!Number.isFinite(target.mmsi)) continue; if (!Number.isFinite(target.lon) || !Number.isFinite(target.lat)) continue; out.push(toLiveShipFeature(target, legacyHits?.get(target.mmsi) ?? null)); } return out; }