Merge remote-tracking branch 'origin/sub_laptop_8' into main_laptop_1
This commit is contained in:
@@ -229,6 +229,42 @@ def _enforce_stored_designs(
|
||||
enforce_ford_surface_drops(longitudinal, sections, project_root, standard)
|
||||
|
||||
|
||||
def refresh_alignment(longitudinal: dict[str, Any]) -> dict[str, Any] | None:
|
||||
"""종단 경고를 저장 입력(base_pvi · 편집 · 정책 · 기준)으로 지금 코드가 다시 셈 — 옛 코드가
|
||||
쓴 경고가 남지 않게(472 덧 · 요구 272). 기하(계획고 · 곡선 · 표본 · 위반)는 저장값 그대로 —
|
||||
저장값이 6 자리 반올림이라 통째로 다시 쓰면 끝자리가 흔들림(계획고 1e-6 m → 면적 1e-4 ㎡).
|
||||
반환 = 요약(`grade_summary`) · 선형이 없는 옛 종단이면 None(그대로)."""
|
||||
from B05_Profile.B05_Profile_Engine_Grade_Profile import rebuild_alignment_profile
|
||||
|
||||
stored = longitudinal.get("profile_alignment")
|
||||
if not isinstance(stored, dict) or not stored.get("base_pvi"):
|
||||
return None
|
||||
fresh, profile = rebuild_alignment_profile(longitudinal, stored.get("edits"))
|
||||
stored["warnings"] = fresh["warnings"]
|
||||
profiles = longitudinal.get("design_profiles")
|
||||
if isinstance(profiles, list) and profiles and isinstance(profiles[0], dict):
|
||||
profile = profiles[0]
|
||||
profile.setdefault("summary", {})["warnings"] = fresh["warnings"]
|
||||
else:
|
||||
longitudinal["design_profiles"] = [profile]
|
||||
return {"id": profile.get("id"), **profile["summary"]}
|
||||
|
||||
|
||||
def _refresh_alignment_file(project_root: Path, relative: str) -> dict[str, Any] | None:
|
||||
"""종단 정본 파일의 선형을 다시 셈 · 바뀐 때만 씀. 파일 · 선형이 없으면 None."""
|
||||
from common_util.common_util_json import atomic_write_json
|
||||
|
||||
path = project_root / relative
|
||||
if not path.is_file():
|
||||
return None
|
||||
longitudinal = json.loads(path.read_text(encoding="utf-8"))
|
||||
before = json.dumps(longitudinal, sort_keys=True, default=str)
|
||||
summary = refresh_alignment(longitudinal)
|
||||
if summary is not None and json.dumps(longitudinal, sort_keys=True, default=str) != before:
|
||||
atomic_write_json(path, longitudinal)
|
||||
return summary
|
||||
|
||||
|
||||
async def recompute_server_side(project_id: UUID | str, route_id: int) -> int:
|
||||
"""포장 구간·세월교 노면 하강 보정에 더해 구조물 면적·유토곡선까지 Node 로 만들어 저장한다.
|
||||
|
||||
@@ -240,19 +276,40 @@ async def recompute_server_side(project_id: UUID | str, route_id: int) -> int:
|
||||
|
||||
|
||||
async def _recompute(project_id: UUID | str, route_id: int) -> int:
|
||||
from B05_Profile.B05_Profile_Repository import update_longitudinal_grade_summary
|
||||
from B06_Section.B06_Section_Router import get_section_detail
|
||||
|
||||
project_uuid = UUID(str(project_id))
|
||||
marks = [("시작", time.perf_counter())]
|
||||
# 상세 만들기(파일 읽기 위주)와 DB 두 건은 서로 기다릴 이유가 없다 — 같이 보낸다.
|
||||
# 원격 DB 라 순차로 내면 왕복이 그대로 더해진다(질의 하나 약 12ms, 2026-09-06 실측).
|
||||
# 원격 DB 라 순차로 내면 왕복이 그대로 더해진다(질의 하나 약 12ms, 2026-09-06 실측) — 같이 보냄.
|
||||
pool = get_db_pool()
|
||||
# 구조물 몫(채집석 공제·구조물 잔토)도 함께 받아 온다 — **B08 이 낸 값**이고, 안 넘기면
|
||||
# 통로만 있고 값이 안 흐른다(2026-09-09 실측: 공제가 늘 `None` 이라 사토가 안 줄었다).
|
||||
response, stored_path, longitudinal_row, haul_inputs, surface = await asyncio.gather(
|
||||
get_section_detail(project_uuid, route_id),
|
||||
stored_path, longitudinal_row = await asyncio.gather(
|
||||
run_with_connection(get_project_storage_relative_path, project_uuid),
|
||||
run_with_connection(get_longitudinal_section, project_uuid, route_id),
|
||||
)
|
||||
project_root = Path(resolve_stored_project_path(stored_path))
|
||||
# 종단 경고 먼저 — 저장 입력으로 다시 셈(472 덧) · 아래 상세가 새 경고를 읽음
|
||||
summary = await asyncio.to_thread(
|
||||
_refresh_alignment_file,
|
||||
project_root,
|
||||
str((longitudinal_row or {}).get("longitudinal_file_path") or ""),
|
||||
)
|
||||
if summary is not None:
|
||||
async with pool.acquire() as connection:
|
||||
await connection.begin()
|
||||
try:
|
||||
await update_longitudinal_grade_summary(
|
||||
connection, route_id=route_id, grade_summary=summary
|
||||
)
|
||||
await connection.commit()
|
||||
except Exception:
|
||||
await connection.rollback()
|
||||
raise
|
||||
marks.append(("종단 선형 다시 셈", time.perf_counter()))
|
||||
# 구조물 몫(채집석 공제·구조물 잔토)도 함께 받아 온다 — **B08 이 낸 값**이고, 안 넘기면
|
||||
# 통로만 있고 값이 안 흐른다(2026-09-09 실측: 공제가 늘 `None` 이라 사토가 안 줄었다).
|
||||
response, haul_inputs, surface = await asyncio.gather(
|
||||
get_section_detail(project_uuid, route_id),
|
||||
haul_inputs_for(project_uuid),
|
||||
run_with_connection(get_surface_confirmation_params, str(project_uuid)),
|
||||
)
|
||||
@@ -262,7 +319,6 @@ async def _recompute(project_id: UUID | str, route_id: int) -> int:
|
||||
raise RuntimeError(f"서버 재계산: 종횡단 상세를 못 받음 (route_id={route_id})")
|
||||
detail = payload(mode="json")
|
||||
sections = detail.get("cross_sections") or []
|
||||
project_root = Path(resolve_stored_project_path(stored_path))
|
||||
from B06_Section.B06_Section_Router_Design import stored_standard_cross_section
|
||||
|
||||
standard = stored_standard_cross_section(longitudinal_row)
|
||||
|
||||
Reference in New Issue
Block a user