/** * analysisApi (flat shape) → vesselAnalysisApi (nested VesselAnalysisItem) 변환. * 기존 컴포넌트가 nested shape에 의존하므로 서비스 교체 후에도 컴포넌트 최소 수정으로 재사용할 수 있게 어댑터를 둔다. */ import type { VesselAnalysis } from './analysisApi'; import type { VesselAnalysisItem } from './vesselAnalysisApi'; export function toVesselItem(v: VesselAnalysis): VesselAnalysisItem { return { mmsi: v.mmsi, timestamp: v.analyzedAt, classification: { vesselType: v.vesselType ?? 'UNKNOWN', confidence: Number(v.confidence ?? 0), fishingPct: Number(v.fishingPct ?? 0), clusterId: v.clusterId ?? 0, season: v.season ?? 'UNKNOWN', }, algorithms: { location: { zone: v.zoneCode ?? 'EEZ_OR_BEYOND', distToBaselineNm: Number(v.distToBaselineNm ?? 0), }, activity: { state: v.activityState ?? 'UNKNOWN', ucafScore: Number(v.ucafScore ?? 0), ucftScore: Number(v.ucftScore ?? 0), }, darkVessel: { isDark: v.isDark ?? false, gapDurationMin: v.gapDurationMin ?? 0, }, gpsSpoofing: { spoofingScore: Number(v.spoofingScore ?? 0), bd09OffsetM: Number(v.bd09OffsetM ?? 0), speedJumpCount: v.speedJumpCount ?? 0, }, cluster: { clusterId: v.fleetClusterId ?? 0, clusterSize: 0, }, fleetRole: { isLeader: v.fleetIsLeader ?? false, role: v.fleetRole ?? 'NONE', }, riskScore: { score: v.riskScore ?? 0, level: v.riskLevel ?? 'LOW', }, transship: { isSuspect: v.transshipSuspect ?? false, pairMmsi: v.transshipPairMmsi ?? '', durationMin: v.transshipDurationMin ?? 0, }, }, }; }