import type { AisTarget } from '../../../entities/aisTarget/model/types'; import type { LegacyVesselInfo } from '../../../entities/legacyVessel/model/types'; import { isFiniteNumber, toSafeNumber } from './setUtils'; export function formatNm(value: number | null | undefined) { if (!isFiniteNumber(value)) return '-'; return `${value.toFixed(2)} NM`; } export function getLegacyTag(legacyHits: Map | null | undefined, mmsi: number) { const legacy = legacyHits?.get(mmsi); if (!legacy) return null; return `${legacy.permitNo} (${legacy.shipCode})`; } export function getTargetName( mmsi: number, targetByMmsi: Map, legacyHits: Map | null | undefined, ) { const legacy = legacyHits?.get(mmsi); const target = targetByMmsi.get(mmsi); return ( (target?.name || '').trim() || legacy?.shipNameCn || legacy?.shipNameRoman || `MMSI ${mmsi}` ); } export function getShipTooltipHtml({ mmsi, targetByMmsi, legacyHits, }: { mmsi: number; targetByMmsi: Map; legacyHits: Map | null | undefined; }) { const legacy = legacyHits?.get(mmsi); const t = targetByMmsi.get(mmsi); const name = getTargetName(mmsi, targetByMmsi, legacyHits); const sog = isFiniteNumber(t?.sog) ? t.sog : null; const cog = isFiniteNumber(t?.cog) ? t.cog : null; const msg = t?.messageTimestamp ?? null; const vesselType = t?.vesselType || ''; const legacyHtml = legacy ? `
CN Permit · ${legacy.shipCode} · ${legacy.permitNo}
유효범위: ${legacy.workSeaArea || '-'}
` : ''; return { html: `
${name}
MMSI: ${mmsi}${vesselType ? ` · ${vesselType}` : ''}
SOG: ${sog ?? '?'} kt · COG: ${cog ?? '?'}°
${msg ? `
${msg}
` : ''} ${legacyHtml}
`, }; } export function getPairLinkTooltipHtml({ warn, distanceNm, aMmsi, bMmsi, legacyHits, targetByMmsi, }: { warn: boolean; distanceNm: number | null | undefined; aMmsi: number; bMmsi: number; legacyHits: Map | null | undefined; targetByMmsi: Map; }) { const d = formatNm(distanceNm); const a = getTargetName(aMmsi, targetByMmsi, legacyHits); const b = getTargetName(bMmsi, targetByMmsi, legacyHits); const aTag = getLegacyTag(legacyHits, aMmsi); const bTag = getLegacyTag(legacyHits, bMmsi); return { html: `
쌍 연결
${aTag ?? `MMSI ${aMmsi}`}
↔ ${bTag ?? `MMSI ${bMmsi}`}
거리: ${d} · 상태: ${warn ? '주의' : '정상'}
${a} / ${b}
`, }; } export function getFcLinkTooltipHtml({ suspicious, distanceNm, fcMmsi, otherMmsi, legacyHits, targetByMmsi, }: { suspicious: boolean; distanceNm: number | null | undefined; fcMmsi: number; otherMmsi: number; legacyHits: Map | null | undefined; targetByMmsi: Map; }) { const d = formatNm(distanceNm); const a = getTargetName(fcMmsi, targetByMmsi, legacyHits); const b = getTargetName(otherMmsi, targetByMmsi, legacyHits); const aTag = getLegacyTag(legacyHits, fcMmsi); const bTag = getLegacyTag(legacyHits, otherMmsi); return { html: `
환적 연결
${aTag ?? `MMSI ${fcMmsi}`}
→ ${bTag ?? `MMSI ${otherMmsi}`}
거리: ${d} · 상태: ${suspicious ? '의심' : '일반'}
${a} / ${b}
`, }; } export function getRangeTooltipHtml({ warn, distanceNm, aMmsi, bMmsi, legacyHits, }: { warn: boolean; distanceNm: number | null | undefined; aMmsi: number; bMmsi: number; legacyHits: Map | null | undefined; }) { const d = formatNm(distanceNm); const aTag = getLegacyTag(legacyHits, aMmsi); const bTag = getLegacyTag(legacyHits, bMmsi); const radiusNm = toSafeNumber(distanceNm); return { html: `
쌍 연결범위
${aTag ?? `MMSI ${aMmsi}`}
↔ ${bTag ?? `MMSI ${bMmsi}`}
범위: ${d} · 반경: ${formatNm(radiusNm == null ? null : radiusNm / 2)} · 상태: ${warn ? '주의' : '정상'}
`, }; } export function getFleetCircleTooltipHtml({ ownerKey, ownerLabel, count, }: { ownerKey: string; ownerLabel?: string; count: number; }) { const displayOwner = ownerLabel && ownerLabel.trim() ? ownerLabel : ownerKey; return { html: `
선단 범위
소유주: ${displayOwner || '-'}
선박 수: ${count}
`, }; }