fix(노선추천): 351-1 저장 빈틈 넷 — 재확정 체인 끝 미리 셈 · 기본값 · 저장된 제약 결과는 「최근 2벌」 정리에서 따로 셈 · 저장된 제약으로도 미리 셈 · B01 사용 범위 바꾸면 예상노선 다시 씀 + 미리 셈
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
키 = 후보 묶음 지문(`_pool_key` — 지형 · 예상노선 · 계류 · 상한 · 최소 R · 이격 · 고름 · 목표
|
||||
기울기) + 갈래 · 비중 · 종단 반영 · 설계속도 · `ALGO_VERSION`. 관 지점은 뺀다 — 덮개 수는 꺼낼 때
|
||||
다시 센다. 추천 결과를 바꾸는 코드 고침은 `ALGO_VERSION` 을 올린다(옛 파일은 다른 키라 안 쓰임).
|
||||
기본값 · 저장된 제약 결과(`default`)는 「최근 벌」을 따로 센다(351-1).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -77,12 +78,26 @@ def request_fingerprint(
|
||||
|
||||
|
||||
def is_default(
|
||||
mode: str, weights: dict[str, float] | None, criteria: dict[str, Any] | None, terrain: Any
|
||||
mode: str,
|
||||
weights: dict[str, float] | None,
|
||||
criteria: dict[str, Any] | None,
|
||||
terrain: Any,
|
||||
saved: dict[str, Any] | None = None,
|
||||
) -> bool:
|
||||
"""기본값 결과 — 빈 제약 · 50/25/25 · 설계 지형. 표시일 뿐 지우는 데 쓰지 않음."""
|
||||
empty = not any(value is not None for value in (criteria or {}).values())
|
||||
plain = mode != "weighted" or resolve_weights(mode, weights) == DEFAULT_WEIGHTS
|
||||
return empty and plain and terrain is None
|
||||
"""지킬 결과 — 기본값(빈 제약 · 50/25/25 · 설계 지형) 또는 저장된 제약(`initial_choice`) 그대로.
|
||||
|
||||
모달이 여는 값이라 「최근 2벌」 정리에서 따로 센다(351-1 · 사용자 시도에 안 밀림).
|
||||
"""
|
||||
if terrain is not None:
|
||||
return False
|
||||
filled = {key: value for key, value in (criteria or {}).items() if value is not None}
|
||||
used = resolve_weights(mode, weights)
|
||||
if not filled and (mode != "weighted" or used == DEFAULT_WEIGHTS):
|
||||
return True
|
||||
saved = saved or {}
|
||||
return filled == (saved.get("criteria") or {}) and (
|
||||
mode != "weighted" or used == saved.get("weights")
|
||||
)
|
||||
|
||||
|
||||
def read_stored(project_root: Path, key: str) -> dict[str, Any] | None:
|
||||
@@ -125,23 +140,26 @@ def write_stored(
|
||||
"result": result,
|
||||
},
|
||||
)
|
||||
prune_stored(project_root, request)
|
||||
prune_stored(project_root, request, default)
|
||||
return True
|
||||
|
||||
|
||||
def _kind(request: Any) -> tuple[Any, Any]:
|
||||
def _kind(request: Any, default: Any) -> tuple[Any, Any, bool]:
|
||||
request = request if isinstance(request, dict) else {}
|
||||
return request.get("mode"), request.get("terrain")
|
||||
return request.get("mode"), request.get("terrain"), bool(default)
|
||||
|
||||
|
||||
def prune_stored(project_root: Path, request: dict[str, Any]) -> int:
|
||||
"""같은 종류(갈래 · 지형) 저장본을 최근 `KEEP_PER_KIND` 벌만 남기고 지운다. 지운 수."""
|
||||
kind = _kind(request)
|
||||
def prune_stored(project_root: Path, request: dict[str, Any], default: bool = False) -> int:
|
||||
"""같은 종류(갈래 · 지형 · 기본값 여부) 저장본을 최근 `KEEP_PER_KIND` 벌만 남기고 지운다.
|
||||
|
||||
기본값 · 저장된 제약 결과(`default`)는 따로 셈 — 사용자 시도가 밀어내지 않음(351-1). 지운 수.
|
||||
"""
|
||||
kind = _kind(request, default)
|
||||
same: list[tuple[int, Path]] = []
|
||||
for path in store_dir(project_root).glob("*.json"):
|
||||
try:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if _kind(data.get("request")) == kind:
|
||||
if _kind(data.get("request"), data.get("default")) == kind:
|
||||
same.append((path.stat().st_mtime_ns, path))
|
||||
except (OSError, ValueError, AttributeError):
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user