- components/ 서브디렉토리 재배치: common/, layers/, iran/, korea/ - App.tsx God Component 분해: 1,179줄 → 588줄 (50% 감소) - useIranData: 이란 데이터 로딩 + propagation + OSINT 병합 - useKoreaData: 한국 데이터 로딩 + propagation - useKoreaFilters: 감시 로직 (환적/다크베셀/케이블/독도) 분리 - getMarineTrafficCategory → utils/marineTraffic.ts 추출 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
48 lines
2.3 KiB
TypeScript
48 lines
2.3 KiB
TypeScript
// MarineTraffic-style ship classification
|
|
// Maps S&P STAT5CODE prefixes and our custom typecodes to MT categories
|
|
export function getMarineTrafficCategory(typecode?: string, category?: string): string {
|
|
if (!typecode) {
|
|
// Fallback to our internal category
|
|
if (category === 'tanker') return 'tanker';
|
|
if (category === 'cargo') return 'cargo';
|
|
if (category === 'destroyer' || category === 'warship' || category === 'carrier' || category === 'patrol') return 'military';
|
|
return 'unspecified';
|
|
}
|
|
const code = typecode.toUpperCase();
|
|
|
|
// Our custom typecodes
|
|
if (code === 'VLCC' || code === 'LNG' || code === 'LPG') return 'tanker';
|
|
if (code === 'CONT' || code === 'BULK') return 'cargo';
|
|
if (code === 'DDH' || code === 'DDG' || code === 'CVN' || code === 'FFG' || code === 'LCS' || code === 'MCM' || code === 'PC') return 'military';
|
|
|
|
// S&P STAT5CODE (IHS StatCode5) — first 2 chars determine main category
|
|
// A1x = Tankers (crude, products, chemical, LPG, LNG)
|
|
if (code.startsWith('A1')) return 'tanker';
|
|
// A2x = Bulk carriers
|
|
if (code.startsWith('A2')) return 'cargo';
|
|
// A3x = General cargo / Container / Reefer / Ro-Ro
|
|
if (code.startsWith('A3')) return 'cargo';
|
|
// B1x / B2x = Passenger / Cruise / Ferry
|
|
if (code.startsWith('B')) return 'passenger';
|
|
// C1x = Fishing
|
|
if (code.startsWith('C')) return 'fishing';
|
|
// D1x = Offshore (tugs, supply, etc.)
|
|
if (code.startsWith('D')) return 'tug_special';
|
|
// E = Other activities (research, cable layers, dredgers)
|
|
if (code.startsWith('E')) return 'tug_special';
|
|
// X = Non-propelled (barges)
|
|
if (code.startsWith('X')) return 'unspecified';
|
|
|
|
// S&P VesselType strings
|
|
const lower = code.toLowerCase();
|
|
if (lower.includes('tanker')) return 'tanker';
|
|
if (lower.includes('cargo') || lower.includes('container') || lower.includes('bulk')) return 'cargo';
|
|
if (lower.includes('passenger') || lower.includes('cruise') || lower.includes('ferry')) return 'passenger';
|
|
if (lower.includes('fishing')) return 'fishing';
|
|
if (lower.includes('tug') || lower.includes('supply') || lower.includes('offshore')) return 'tug_special';
|
|
if (lower.includes('high speed')) return 'high_speed';
|
|
if (lower.includes('pleasure') || lower.includes('yacht') || lower.includes('sailing')) return 'pleasure';
|
|
|
|
return 'unspecified';
|
|
}
|