- prediction/: FastAPI 7단계 분류 파이프라인 + 6개 탐지 알고리즘 - snpdb 궤적 조회 → 인메모리 캐시(13K척) → 분류 → kcgdb 저장 - APScheduler 5분 주기, Python 3.9 호환 - 버그 수정: @property last_bucket, SQL INTERVAL 바인딩, rollback, None 가드 - 보안: DB 비밀번호 하드코딩 제거 → env 환경변수 필수 - deploy/kcg-prediction.service: systemd 서비스 (redis-211, 포트 8001) - deploy.yml: prediction CI/CD 배포 단계 추가 (192.168.1.18:32023) - backend: PredictionProxyController (health/status/trigger 프록시) - backend: AppProperties predictionBaseUrl + AuthFilter 인증 예외 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
85 lines
2.0 KiB
Python
85 lines
2.0 KiB
Python
from dataclasses import dataclass, field
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass
|
|
class AnalysisResult:
|
|
"""vessel_analysis_results 테이블 28컬럼 매핑."""
|
|
|
|
mmsi: str
|
|
timestamp: datetime
|
|
|
|
# 분류 결과
|
|
vessel_type: str = 'UNKNOWN'
|
|
confidence: float = 0.0
|
|
fishing_pct: float = 0.0
|
|
cluster_id: int = -1
|
|
season: str = 'UNKNOWN'
|
|
|
|
# ALGO 01: 위치
|
|
zone: str = 'EEZ_OR_BEYOND'
|
|
dist_to_baseline_nm: float = 999.0
|
|
|
|
# ALGO 02: 활동 상태
|
|
activity_state: str = 'UNKNOWN'
|
|
ucaf_score: float = 0.0
|
|
ucft_score: float = 0.0
|
|
|
|
# ALGO 03: 다크 베셀
|
|
is_dark: bool = False
|
|
gap_duration_min: int = 0
|
|
|
|
# ALGO 04: GPS 스푸핑
|
|
spoofing_score: float = 0.0
|
|
bd09_offset_m: float = 0.0
|
|
speed_jump_count: int = 0
|
|
|
|
# ALGO 05+06: 선단
|
|
cluster_size: int = 0
|
|
is_leader: bool = False
|
|
fleet_role: str = 'NOISE'
|
|
|
|
# ALGO 07: 위험도
|
|
risk_score: int = 0
|
|
risk_level: str = 'LOW'
|
|
|
|
# 특징 벡터
|
|
features: dict = field(default_factory=dict)
|
|
|
|
# 메타
|
|
analyzed_at: Optional[datetime] = None
|
|
|
|
def __post_init__(self):
|
|
if self.analyzed_at is None:
|
|
self.analyzed_at = datetime.now(timezone.utc)
|
|
|
|
def to_db_tuple(self) -> tuple:
|
|
import json
|
|
return (
|
|
self.mmsi,
|
|
self.timestamp,
|
|
self.vessel_type,
|
|
self.confidence,
|
|
self.fishing_pct,
|
|
self.cluster_id,
|
|
self.season,
|
|
self.zone,
|
|
self.dist_to_baseline_nm,
|
|
self.activity_state,
|
|
self.ucaf_score,
|
|
self.ucft_score,
|
|
self.is_dark,
|
|
self.gap_duration_min,
|
|
self.spoofing_score,
|
|
self.bd09_offset_m,
|
|
self.speed_jump_count,
|
|
self.cluster_size,
|
|
self.is_leader,
|
|
self.fleet_role,
|
|
self.risk_score,
|
|
self.risk_level,
|
|
json.dumps(self.features),
|
|
self.analyzed_at,
|
|
)
|