커밋 그래프

28 커밋

작성자 SHA1 메시지 날짜
d15039ce18 fix: vessel_store _last_bucket 타임존 오류 수정
snpdb time_bucket은 tz-naive KST인데 UTC tzinfo를 강제 부여하여
incremental fetch WHERE time_bucket > %s 비교 시 미래 시간으로 해석,
항상 0 rows 반환 → 1h 어구 그룹이 점진적으로 소멸하는 버그.

tz-naive 그대로 유지하도록 수정 (load_initial, merge_incremental 3곳).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 05:53:14 +09:00
b04e96c457 fix: 1h 활성 판정을 parent_name 전체 합산 기준으로 변경
서브클러스터 분리 후 개별 서브그룹의 1h 멤버가 2개 미만이더라도,
parent_name 전체(모든 서브클러스터 합산)에서 1h 활성 멤버 >= 2이면
resolution='1h'로 저장하여 라이브 현황에 표시.

결과: 라이브 1h 그룹 5개 → 927개 정상 복구

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:47:01 +09:00
98d173701e fix: 라이브 어구 현황에서 fallback 그룹 제외
- 1h 실제 활성 멤버 < 2일 때 resolution='1h-fb' (fallback)로 저장
- LATEST_GROUPS_SQL은 resolution='1h'만 필터 → fallback 자동 제외
- 리플레이 history API는 1h-fb 포함 (리플레이/일치율 추적 유지)
- 프론트 리플레이: '1h' + '1h-fb' 모두 1h 프레임으로 처리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:22:59 +09:00
a7eb706839 fix: FLEET 타입에 resolution='1h' 누락 — 라이브 현황 API에서 선단 그룹 미표시
FLEET 스냅샷에 resolution 필드를 설정하지 않아 DB default '6h'로 저장됨.
LATEST_GROUPS_SQL이 resolution='1h' 필터를 사용하므로 FLEET 전부 누락.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:17:27 +09:00
71d607e499 feat: 어구 그룹 1h/6h 듀얼 폴리곤 + 리플레이 컨트롤러 개선
- Python: 1h/6h 듀얼 스냅샷 생성 (polygon_builder), 1h 멤버 기반 일치율 후보 (gear_correlation)
- DB: resolution 컬럼 추가 (011_polygon_resolution.sql)
- Backend: resolution 필드 지원 (DTO/Service/Controller)
- Frontend: 6h identity 레이어 독립 구현 (폴리곤/아이콘/라벨/항적/센터)
- 리플레이 컨트롤러: 프로그레스바 통합, 1h/6h 스냅샷 표시, A-B 구간 반복
- 리치 툴팁: 클릭 고정 + 멤버 호버 강조 + 선박/어구/모델 소속 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 11:52:38 +09:00
f09186a187 feat: 어구 리플레이 서브클러스터 분리 렌더링 + 일치율 감쇠 개선
- 서브클러스터별 독립 폴리곤/센터/center trail 렌더링
- 반경 밖 이탈 선박 강제 감쇠 (OUT_OF_RANGE)
- Backend correlation API에 sub_cluster_id 추가
- 모델 패널 5개 항상 표시, 드롭다운 기본값 70%
- DISPLAY_STALE_SEC (time_bucket 기반) 폴리곤 노출 필터
- AIS 수집 bbox 122~132E/31~39N 확장
- historyActive 시 deck.gl 이중 렌더링 수정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 09:01:03 +09:00
6f4044ce39 feat: MapLibre → deck.gl 전면 전환 + 어구 서브클러스터 구조 개선
- 실시간 선박 13K: MapLibre symbol → deck.gl IconLayer (useShipDeckLayers + shipDeckStore)
- 선단/어구 폴리곤: MapLibre Source/Layer → deck.gl GeoJsonLayer (useFleetClusterDeckLayers)
- 선박 팝업: MapLibre Popup → React 오버레이 (ShipPopupOverlay + ShipHoverTooltip)
- 리플레이 집중 모드 (focusMode), 라벨 클러스터링, fontScale 연동
- Python: group_key 고정 + sub_cluster_id 분리, 한국 국적 어구 오탐 제외
- DB: sub_cluster_id 컬럼 추가 + 기존 '#N' 데이터 마이그레이션
- Backend: DISTINCT ON CTE로 서브클러스터 중복 제거, subClusterId DTO 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:44:09 +09:00
8631546142 fix: 트랙 API DB 접속 버그 수정 (context manager)
- kcgdb.get_conn()을 with문 없이 사용 → cursor 에러
- with kcgdb.get_conn() as conn: 으로 수정
- 디버그 로그 추가 (rows 수, track 매칭 수, vessel_store 크기)
- 결과: 47 vessels, 47 with track data (25567#1 그룹)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:03:33 +09:00
8eacbb2c91 feat: 트랙 API 전체 모델 확장 + 개별 선박 on/off → 폴리곤 반영
Prediction API:
- /correlation/{group}/tracks: is_default=TRUE 제거 → 모든 활성 모델 조회
- 응답에 models: {modelName: score} 딕셔너리 추가 (모델별 점수)
- MMSI 기준 중복 제거, 최고 점수 유지

Frontend:
- CorrelationVesselTrack 타입: models 필드 추가, type 필드 추가
- 오퍼레이셔널 폴리곤: enabledVessels 기반 on/off 제어
  (score 임계값 → 개별 체크박스 토글로 전환)
- identity OFF 시 폴리곤 base points에서 멤버 위치 제외

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 08:40:31 +09:00
bbbc326e38 refactor: FleetClusterLayer 10파일 분리 + deck.gl 리플레이 기반 구축
FleetClusterLayer.tsx 2357줄 → 10개 파일 분리:
- fleetClusterTypes/Utils/Constants: 타입, 기하 함수, 모델 상수
- useFleetClusterGeoJson: 27개 useMemo GeoJSON 훅
- FleetClusterMapLayers: MapLibre Source/Layer JSX
- CorrelationPanel/HistoryReplayController: 패널 서브컴포넌트
- GearGroupSection/FleetGearListPanel: 좌측 목록 (DRY)
- FleetClusterLayer: 오케스트레이터 524줄

deck.gl + Zustand 리플레이 기반 (Phase 0~2):
- zustand 5.0.12, @deck.gl/geo-layers 9.2.11 설치
- gearReplayStore: Zustand + rAF 애니메이션 루프
- gearReplayPreprocess: TripsLayer 전처리 + cursor O(1) 보간
- useGearReplayLayers: deck.gl 레이어 빌더 (10fps 스로틀)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 07:44:07 +09:00
812a78f636 feat: 어구 연관성 멀티모델 패턴 추적 시스템 (Phase 1 Core)
- gear_correlation.py: 적응형 EMA + freeze + shadow + 배치 최적화
- 5개 글로벌 모델 병렬 추적 (default/aggressive/conservative/proximity-heavy/visit-pattern)
- 어구 중심 점수 체계: 어구 비활성 시 FREEZE, 선박 shadow 추적
- 유형별 메트릭: 어구-선박(proximity+visit+activity), 선박-선박(DTW+SOG+COG)
- DB: correlation_param_models + raw_metrics(일별 파티션) + scores + system_config
- partition_manager: 일별 파티션 생성/정리 (system_config hot-reload)
- track_similarity: SOG상관 + COG동조 + 근접비 3개 메트릭 추가
- scheduler Step 4.7 통합, fleet_tracker MMSI 점수 이전
- chat/tools: query_gear_correlation 도구

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 10:36:43 +09:00
e797beaac6 feat(chat): Ollama Qwen3 기반 AI 해양분석 채팅 구축
- Ollama Docker(14b/32b) + Redis 컨텍스트 캐싱 + 대화 히스토리
- Python SSE 채팅 엔드포인트 + 사전 쿼리 + Tool Calling
- 도메인 지식(해양법/어업협정/알고리즘) + DB 스키마 가이드
- Frontend SSE 스트리밍 + 타이머 + thinking 접기 + 확장 UI
2026-03-26 09:03:05 +09:00
1bf70f46ac feat: 분석 용어/색상 통일 + 경량 분석 + 항적 미니맵
- AI분석/현장분석/보고서 위험도 용어 통일 (HIGH→WATCH, MEDIUM→MONITOR, LOW→NORMAL)
- 공통 riskMapping.ts: ALERT_COLOR/EMOJI/LEVELS, RISK_TO_ALERT, STATS_KEY_MAP
- deck.gl 오버레이 색상 현장분석 팔레트로 통일
- Python 경량 분석: 파이프라인 미통과 412* 선박에 위치 기반 간이 AnalysisResult 생성
- 현장분석 fallback 제거: classifyStateFallback/classifyFishingZone → Python 결과 전용
- 보고서 위험 평가: Python riskCounts 실데이터 기반으로 전면 교체
- 현장분석 우측 패널: 항적 미니맵 (72시간, fetchVesselTrack API)
- 현장분석 좌측 패널: 위험도 점수 기준 섹션 추가
2026-03-25 12:39:22 +09:00
8f9b347e1f feat: 폴리곤 히스토리 애니메이션 + 어구 추적 안정화
- FleetClusterLayer: 12시간 타임라인 기반 폴리곤 재생 애니메이션
  - 중심 이동 궤적 (점선) + 어구별 개별 궤적 (실선)
  - 가상 어구/선박 아이콘 COG 회전 + 스냅샷 동기화
  - 재생 컨트롤러: 재생/일시정지 + 프로그레스 바 (드래그/클릭)
  - 신호없음 구간: 마지막 유효 스냅샷 유지 + 회색 점선 표시
  - 히스토리 모드 시 현재 강조 레이어 (deck.gl + MapLibre) 숨김
  - ESC 키: 히스토리 닫기 + 선택 해제
- polygon_builder: STALE_SEC 3600→21600 (6시간, 어구 P75 갭 3.5h 커버)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 07:33:48 +09:00
7573c84e91 fix: 분석 파이프라인 정확도 개선 + 캐시 증분 갱신 + TTS 프록시
- MIN_TRAJ_POINTS 100→20 (16척→684척, 파이프라인 병목 해소)
- risk.py: SOG 급변 count를 위험도 점수에 반영 (+5/+10)
- spoofing.py: BD09 오프셋 중국 MMSI(412*) 예외 (좌표계 노이즈 제거)
- fishing_pattern.py: 마지막 조업 세그먼트 누락 버그 수정
- VesselAnalysisService: 인메모리 캐시 + 증분 갱신 (warmup 2h → incremental)
- nginx: /api/gtts 프록시 추가 (Google TTS CORS 우회)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 06:48:27 +09:00
433141a3e8 feat: AI 분석 통계 서버사이드 전환 + 어구/선단 UI 개선
- Backend: /api/vessel-analysis 응답에 stats 집계 필드 추가
- Backend: GroupPolygonService.getGearStats() 어구 SQL 집계
- Frontend: 클라이언트 사이드 stats/gearStats 계산 로직 완전 제거
- Frontend: 가상 선박 마커, 어구 겹침 팝업, 패널 아코디언
- Frontend: cnFishingSuspects에 모선 포함
- Python: vessel_store COG bearing 계산 (마지막 2점 기반)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:55:15 +09:00
4c22d5f1f9 fix(prediction): 어구그룹 탐지 — 전체 AIS 선박 대상으로 확장
- detect_gear_groups: vessel_dfs(분류 대상만) → vessel_store.get_all_latest_positions()(전체 14K선박)
- build_all_group_snapshots: 동일하게 all_positions 기반으로 전환
- vessel_store: get_all_latest_positions() 메서드 추가
- 결과: 0 gear groups → 210 gear groups (GEAR_IN_ZONE 57, GEAR_OUT_ZONE 45)
2026-03-24 14:17:44 +09:00
2441e3068a feat(prediction): 선단/어구그룹 폴리곤 서버사이드 생성 + PostGIS 저장
- DB migration 009: group_polygon_snapshots 테이블 (PostGIS geometry)
- polygon_builder.py: Shapely 기반 convex hull + buffer 폴리곤 생성
- scheduler.py: 5분 주기 분석 사이클에 폴리곤 생성 Step 4.5 통합
- fleet_tracker.py: get_company_vessels() 메서드 추가
- kcgdb.py: save_group_snapshots(), cleanup_group_snapshots() 추가
- requirements.txt: shapely>=2.0 추가
2026-03-24 13:30:31 +09:00
2511a33444 perf: 렌더링 성능 최적화 + 환적 Python 이관 + 중국어선감시 통합 (#158) 2026-03-23 13:16:24 +09:00
2f0ff22d1b feat: 한국 레이어 핵심 기능 통합 — 해외시설·현장분석·선단강조·버그수정 (#145) 2026-03-23 08:19:54 +09:00
bb99387168 feat: 선단 등록 DB + 어망/어구 정체성 추적 시스템
- DB 007: fleet_companies, fleet_vessels, gear_identity_log, fleet_tracking_snapshot
- 906척 선단 구성 데이터 적재 (497개 회사, 279쌍 PT)
- FleetTracker: 등록 선단 ↔ AIS 매칭(NAME_EXACT) + 어구 정체성 추적
- track_similarity.py: DTW 기반 궤적 유사도 (TRACK_SIMILAR 플래그)
- scheduler: fleet_tracker 통합 (기존 assign_fleet_roles 대체)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:07:15 +09:00
c09429b003 feat: 선단 탐지를 행동 패턴 매칭으로 전환 + 수역 위험도 가산
- fleet.py: DBSCAN/그리드 → PT 저인망(2척 3NM 유사속도방향) / PS 선망(3+척 2NM) / FC 환적(0.5NM 저속) 패턴 매칭
- risk.py: 특정어업수역 + 미허가 = +25점
- scheduler.py: cluster_id를 fleet 패턴 결과로 교체

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:46:10 +09:00
d13baf302f fix: 위험도 점수 수역 가산 + 클러스터 그리드 셀 방식 전환
- risk.py: 특정어업수역(ZONE_I~IV) 내 미허가 어선 +25점 가산
- fleet.py: DBSCAN → 고정 그리드 셀(5NM) 클러스터링 (체인 효과 차단)
  - max_cluster_size=20으로 거대 클러스터 방지

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:38:49 +09:00
a009534c35 fix: 점수 표시 8000→80 + 강조마커 위치 중앙정렬 + 클러스터 eps 3NM
- AnalysisStatsPanel: score*100 제거 (이미 0~100 정수)
- KoreaMap: 불법어선 펄스 링 position:relative+absolute로 선박 아이콘 중앙 오버레이
- fleet.py: DBSCAN spatial_eps_nm 10→3 (116척 단일 클러스터 해소)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:19:31 +09:00
746ddb7111 fix: numpy float → Python native 변환 — DB INSERT 시 np.float64 직렬화 오류 수정
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 13:40:16 +09:00
d4a35f546d feat: 특정어업수역 Ⅰ~Ⅳ 폴리곤 기반 수역 분류 — 경도 하드코딩 → point-in-polygon 교체
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:47:29 +09:00
a68dfb21b2 feat: Python 어선 분류기 + 배포 설정 + 백엔드 모니터링 프록시
- 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>
2026-03-20 12:10:21 +09:00
512020d6bb feat: 백엔드 Spring Boot + DB 스키마 + Python 분석서버 스켈레톤
- backend/: Spring Boot 3.2 + Java 17, Google OAuth + JWT 인증
  - AuthController/Service/Filter: id_token 검증 + gcsc.co.kr 도메인 제한
  - JPA Entity: users, login_history
  - 수집기 placeholder: GDELT, Google News, CENTCOM, Aircraft
  - ArticleClassifier: 프론트엔드 분류 정규식 이식
  - 프로파일: local / prod (PostgreSQL 211.208.115.83:5432/kcgdb)
- database/: 초기 스키마 (events, news, osint, users, login_history)
- prediction/: FastAPI placeholder (향후 해양 분석)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 13:54:58 +09:00