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>
This commit is contained in:
htlee 2026-04-01 14:22:59 +09:00
부모 a7eb706839
커밋 98d173701e
2개의 변경된 파일11개의 추가작업 그리고 5개의 파일을 삭제

파일 보기

@ -180,7 +180,7 @@ export function FleetClusterLayer({ ships, analysisMap: analysisMapProp, onShipS
]); ]);
// 2. resolution별 분리 → 1h(primary) + 6h(secondary) // 2. resolution별 분리 → 1h(primary) + 6h(secondary)
const history1h = history.filter(h => h.resolution === '1h'); const history1h = history.filter(h => h.resolution === '1h' || h.resolution === '1h-fb');
const history6h = history.filter(h => h.resolution === '6h'); const history6h = history.filter(h => h.resolution === '6h');
// fallback: resolution 필드 없는 기존 데이터는 6h로 취급 // fallback: resolution 필드 없는 기존 데이터는 6h로 취급
const effective1h = history1h.length > 0 ? history1h : history; const effective1h = history1h.length > 0 ? history1h : history;

파일 보기

@ -423,12 +423,16 @@ def build_all_group_snapshots(
continue continue
# ── 1h 활성 멤버 필터 ── # ── 1h 활성 멤버 필터 ──
display_members_1h = [ active_members_1h = [
gm for gm in gear_members gm for gm in gear_members
if _get_time_bucket_age(gm.get('mmsi'), all_positions, now) <= DISPLAY_STALE_SEC if _get_time_bucket_age(gm.get('mmsi'), all_positions, now) <= DISPLAY_STALE_SEC
] ]
# fallback: 1h < 2이면 time_bucket 최신 2개 유지 (폴리곤 형태 보존) active_count_1h = len(active_members_1h)
if len(display_members_1h) < 2 and len(gear_members) >= 2:
# fallback: 1h < 2이면 time_bucket 최신 2개 유지 (리플레이/일치율 추적용)
# 라이브 현황에서는 active_count_1h로 필터 (fallback 그룹 제외)
display_members_1h = active_members_1h
if active_count_1h < 2 and len(gear_members) >= 2:
sorted_by_age = sorted( sorted_by_age = sorted(
gear_members, gear_members,
key=lambda gm: _get_time_bucket_age(gm.get('mmsi'), all_positions, now), key=lambda gm: _get_time_bucket_age(gm.get('mmsi'), all_positions, now),
@ -443,7 +447,9 @@ def build_all_group_snapshots(
display_members_6h = gear_members display_members_6h = gear_members
# ── resolution별 스냅샷 생성 ── # ── resolution별 스냅샷 생성 ──
for resolution, members_for_snap in [('1h', display_members_1h), ('6h', display_members_6h)]: # 1h-fb: fallback (실제 1h 활성 < 2) — 리플레이/일치율 추적용, 라이브 현황에서 제외
res_1h = '1h' if active_count_1h >= 2 else '1h-fb'
for resolution, members_for_snap in [(res_1h, display_members_1h), ('6h', display_members_6h)]:
if len(members_for_snap) < 2: if len(members_for_snap) < 2:
continue continue
# 6h: 최신 적재가 STALE_SEC(6h) 초과 시 스킵 # 6h: 최신 적재가 STALE_SEC(6h) 초과 시 스킵