iran prediction 47개 Python 파일을 prediction/ 디렉토리로 복제: - algorithms/ 14개 분석 알고리즘 (어구추론, 다크베셀, 스푸핑, 환적, 위험도 등) - pipeline/ 7단계 분류 파이프라인 - cache/vessel_store (24h 슬라이딩 윈도우) - db/ 어댑터 (snpdb 원본조회, kcgdb 결과저장) - chat/ AI 채팅 (Ollama, 후순위) - data/ 정적 데이터 (기선, 특정어업수역 GeoJSON) config.py를 kcgaidb로 재구성 (DB명, 사용자, 비밀번호) DB 연결 검증 완료 (kcgaidb 37개 테이블 접근 확인) Makefile에 dev-prediction / dev-all 타겟 추가 CLAUDE.md에 prediction 섹션 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta, timezone
|
|
from zoneinfo import ZoneInfo
|
|
|
|
from config import settings
|
|
|
|
_KST = ZoneInfo('Asia/Seoul')
|
|
_BUCKET_MINUTES = 5
|
|
|
|
|
|
def normalize_bucket_kst(bucket: datetime) -> datetime:
|
|
if bucket.tzinfo is None:
|
|
return bucket
|
|
return bucket.astimezone(_KST).replace(tzinfo=None)
|
|
|
|
|
|
def floor_bucket_kst(value: datetime, bucket_minutes: int = _BUCKET_MINUTES) -> datetime:
|
|
if value.tzinfo is None:
|
|
localized = value.replace(tzinfo=_KST)
|
|
else:
|
|
localized = value.astimezone(_KST)
|
|
floored_minute = (localized.minute // bucket_minutes) * bucket_minutes
|
|
return localized.replace(minute=floored_minute, second=0, microsecond=0)
|
|
|
|
|
|
def compute_safe_bucket(now: datetime | None = None) -> datetime:
|
|
current = now or datetime.now(timezone.utc)
|
|
if current.tzinfo is None:
|
|
current = current.replace(tzinfo=timezone.utc)
|
|
safe_point = current.astimezone(_KST) - timedelta(minutes=settings.SNPDB_SAFE_DELAY_MIN)
|
|
return floor_bucket_kst(safe_point).replace(tzinfo=None)
|
|
|
|
|
|
def compute_initial_window_start(hours: int, safe_bucket: datetime | None = None) -> datetime:
|
|
anchor = normalize_bucket_kst(safe_bucket or compute_safe_bucket())
|
|
return anchor - timedelta(hours=hours)
|
|
|
|
|
|
def compute_incremental_window_start(last_bucket: datetime) -> datetime:
|
|
normalized = normalize_bucket_kst(last_bucket)
|
|
return normalized - timedelta(minutes=settings.SNPDB_BACKFILL_BUCKETS * _BUCKET_MINUTES)
|