fix(git): 병합이 떨군 파일 22개와 되돌아간 파일 35개를 되살림
무슨 일이 있었나 랩탑 줄의 병합 `20ba886c`(Merge origin/main_desktop_1·main_laptop_1·sub_desktop_1 into sub_laptop_1)가 우리 파일 22개를 떨구고 35개 파일의 내용을 옛것으로 되돌림. 손으로 지운 커밋은 없고 **병합 자체가 떨군 것**임. 그것이 `origin/dev`·`main_laptop_1`·`sub_laptop_1`· `CODEX` 까지 퍼졌고(데스크탑 둘만 무사), 이 창의 병합 `d92c1f2b` 로 들어옴. 잃었던 것 - 공용 — `common_util_provenance.py` · `ui_template_provenance.ts` - B08 — 근거 사전 · 좌측 패널 상자 모듈 · 토량환산계수 칸 - B09 — 근거 사전 셋 - B05 — 계획노선 편집 모듈 아홉 · 지형 라우터 · B04 지도 모듈 - 시험 셋과, 35개 파일 안의 최근 작업(환산계수 고르기 · 근거 호버 배선 등) 어떻게 되살렸나 `611a2b40`(병합 직전, 전부 온전)에서 `git show <커밋>:<경로>` 로 내용만 꺼내 되돌림. 이력은 안 건드림. ⚠ HEAD 에만 있던 「추가 816줄」은 랩탑의 새 작업이 아니라 **되살아난 옛 코드**였음(B05 편집은 모듈로 쪼개기 전 덩어리 · B08 라우터는 환산계수 고르기 전 옛 상수판). 되돌릴 시점 이후의 **진짜 새 커밋은 둘뿐**이라 그 둘만 패치로 다시 얹음 — `9f827bf6`(리로드 빌드 고리 끊기, 데스크탑 보조) · `b9bca6b3`(B06 조정창 1px, 랩탑). 위키 여덟은 코덱스 몫이라 손대지 않음. 자체검증 — 양쪽 작업이 다 살아 있음을 짚어 확인: `main.py` 의 「개발 서버는 살려 둔다」 · `B05_Profile_Engine_Grade.py` 의 `plan_curve_length_limit_m` · `B08_..._EarthworkGrid.ts` 의 `attachProvenance`. `tsc --noEmit` 통과 · `pytest -q` **1317 passed, 28 skipped** (되살리기 전에는 시험 둘이 수집 단계에서 깨져 있었음). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RANEBHns1S4tkmsYwewtk
This commit is contained in:
@@ -36,6 +36,10 @@ from pathlib import Path
|
||||
from typing import Any, Iterable
|
||||
|
||||
from common_util.common_util_json import atomic_write_json
|
||||
from config.config_system_design import (
|
||||
EARTHWORK_CONVERSION_C_RANGES,
|
||||
EARTHWORK_CONVERSION_FACTORS,
|
||||
)
|
||||
|
||||
SETTINGS_FILENAME = "project_settings.json"
|
||||
SCHEMA_VERSION = 1
|
||||
@@ -258,6 +262,62 @@ def concrete_placing_method(settings: dict[str, Any]) -> tuple[str, bool]:
|
||||
return DEFAULT_CONCRETE_PLACING_METHOD, True
|
||||
|
||||
|
||||
def earthwork_conversion_factors(settings: dict[str, Any]) -> dict[str, dict[str, float]]:
|
||||
"""이 프로젝트가 쓸 토량환산계수 — **기본값 위에 고른 값만 얹는다.**
|
||||
|
||||
⚠ 정의처는 여전히 `config_system_design.EARTHWORK_CONVERSION_FACTORS` 한 곳이다.
|
||||
여기서 값을 새로 적지 않고, 설계자가 고른 갈래만 갈아 끼운다. 안 고른 갈래는
|
||||
키 자체가 없어 정본이 그대로 선다 — 기본값을 복사해 넣지 않는 까닭은 이 파일
|
||||
머리글 `*_override` 규칙과 같다.
|
||||
|
||||
⚠ 이 값은 토적표만 쓰는 것이 아니다 — 유토곡선(B06)·운반표·기초단가가 같이 읽는다.
|
||||
그래서 읽는 자리마다 상수를 직접 들지 말고 **이 함수를 거친다.**
|
||||
|
||||
고른 값의 모양 — `conversion_factors_override`
|
||||
`{"ripping_rock": {"compacted": 1.0, "reason": "토질시험 값"}}`
|
||||
`reason` 은 품셈 범위 밖을 골랐을 때 남기는 사유이고 계산에 안 쓴다.
|
||||
"""
|
||||
resolved = {kind: dict(entry) for kind, entry in EARTHWORK_CONVERSION_FACTORS.items()}
|
||||
override = settings.get("conversion_factors_override")
|
||||
if not isinstance(override, dict):
|
||||
return resolved
|
||||
for kind, entry in override.items():
|
||||
if kind not in resolved or not isinstance(entry, dict):
|
||||
continue
|
||||
value = entry.get("compacted")
|
||||
if isinstance(value, (int, float)) and not isinstance(value, bool) and float(value) > 0:
|
||||
resolved[kind]["compacted"] = float(value)
|
||||
return resolved
|
||||
|
||||
|
||||
def earthwork_conversion_choices(settings: dict[str, Any]) -> dict[str, dict[str, Any]]:
|
||||
"""갈래별 「무엇을 골랐나」 — 화면이 기본값과 고른 값을 갈라 보이는 데 쓴다.
|
||||
|
||||
`{갈래: {"compacted", "default", "chosen", "in_range", "range", "reason"}}`.
|
||||
`chosen` 이 거짓이면 기본값이 선 것이고, `in_range` 가 거짓이면 품셈 범위 밖이라
|
||||
사유가 있어야 하는 자리다. **범위 밖이라고 막지 않는다**(품셈 원칙이 토질시험이다).
|
||||
"""
|
||||
override = settings.get("conversion_factors_override")
|
||||
override = override if isinstance(override, dict) else {}
|
||||
resolved = earthwork_conversion_factors(settings)
|
||||
choices: dict[str, dict[str, Any]] = {}
|
||||
for kind, entry in resolved.items():
|
||||
default = float(EARTHWORK_CONVERSION_FACTORS[kind]["compacted"])
|
||||
value = float(entry["compacted"])
|
||||
low, high = EARTHWORK_CONVERSION_C_RANGES.get(kind, (None, None))
|
||||
entry_override = override.get(kind)
|
||||
reason = entry_override.get("reason") if isinstance(entry_override, dict) else None
|
||||
choices[kind] = {
|
||||
"compacted": value,
|
||||
"default": default,
|
||||
"chosen": value != default,
|
||||
"in_range": low is None or low <= value <= high,
|
||||
"range": [low, high] if low is not None else None,
|
||||
"reason": str(reason) if reason else None,
|
||||
}
|
||||
return choices
|
||||
|
||||
|
||||
def application_ratio(settings: dict[str, Any], key: str) -> float:
|
||||
"""반영률을 0~1 로. 없으면 100 %(=1.0) — 실무 관측치를 기본값으로 쓰지 않는다."""
|
||||
raw = (settings.get("application_ratios_pct") or {}).get(key, 100)
|
||||
|
||||
Reference in New Issue
Block a user