feat(b06): 횡단도 바로 반영 — 새로 놓거나 옮긴 관 · 구조물의 횡단 카드를 [저장] 전에 보임 (273-2)

- 서버: 읽기 전용 미리 뜨기 POST /section/preview-stations — 로그인 · 회사 · 프로젝트 권한 그대로 · 한 번에 60곳 · 파일 · DB 안 씀 · 저장과 같은 길(sample_structure_sections · compute_default_designs crosses)
- 화면: 초안이 심는 자리 중 횡단 없는 곳만 묻고 한 번 뜬 자리는 기억(B06_Section_Section_Drafts) · 카드 이름 · 관 그림 얹음 · 늦은 옛 응답 무시 · 배수 재계산이 관경을 정하면 카드 다시 얹음 · B06 관 옮김도 카드 다시
- [저장]은 지금처럼 서버가 같은 계산으로 정본에 씀 — 미리 본 카드와 같은 값
- 알림 글: 횡단도는 바로 보이고 세부 배수유역만 저장 뒤 다시 셈
- 시험: test_273_2 새로 · 177-3 헬퍼에 revealPick 자리 채움

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLCk2y5xE8YGVgjbTntWsY
This commit is contained in:
2026-10-11 20:48:32 +09:00
co-authored by Claude Opus 5.5
parent 887c89bbf8
commit dfd7427c46
14 changed files with 642 additions and 105 deletions
+14 -3
View File
@@ -582,9 +582,13 @@ def compute_default_designs(
chainages: list[float],
standard: dict[str, Any] | None = None,
carried: dict[float, dict[str, Any]] | None = None,
crosses: dict[float, dict[str, Any]] | None = None,
) -> list[tuple[float, dict[str, Any]]]:
"""미지정 측점들을 기본값(리핑암 + 암반 경계 0.5m/상단측 절토)으로 계산한 목록을 만든다.
`crosses`(누가거리 round 3 → 횡단 dict)가 오면 파일 대신 그 횡단으로 계산한다 — 아직 정본에
없는 B06 미리 뜨기 자리(273-2) · 상단측도 그 횡단 값(종단 정본에 측점이 없음).
standard가 오면(확정 요청의 패널 편집값) 그 값으로 표준단면 기하를 계산한다.
`carried`(누가거리 round 3 → `CARRY_INPUT_KEYS` 값)가 오면 그 측점은 기본값 대신 그 입력으로
계산한다 — 노선 [확인] 체인의 옛 설계 이월(PLAN 74-3). 결과 칸은 늘 새 계획고로 다시 낸다.
@@ -602,11 +606,13 @@ def compute_default_designs(
ford_drops = ford_surface_drops(root)
results: list[tuple[float, dict[str, Any]]] = []
for chainage_m in chainages:
cross = (crosses or {}).get(round(chainage_m, 3))
cross_path = find_cross_file(cross_dir, chainage_m)
if not cross_path.is_file():
if cross is None and not cross_path.is_file():
continue
try:
cross = json.loads(cross_path.read_text(encoding="utf-8"))
if cross is None:
cross = json.loads(cross_path.read_text(encoding="utf-8"))
samples = cross.get("samples")
if not isinstance(samples, list):
continue
@@ -617,7 +623,12 @@ def compute_default_designs(
samples,
design_elevation_from_longitudinal(longitudinal, chainage_m),
ground_type=str(user.get("ground_type") or "ripping_rock"),
section_mode=default_modes.get(round(chainage_m, 3), "left_cut"),
section_mode=default_modes.get(
round(chainage_m, 3),
f"{cross['uphill_side']}_cut"
if cross.get("uphill_side") in ("left", "right")
else "left_cut",
),
ditch_type=str(user.get("ditch_type") or "standard"),
# 포장은 사용자 구간 지정만 켠다 — 경사 제안은 경고로만 남는다(2026-08-28).
paved=paved_at(chainage_m, paved_ranges),