From 8555e693ac43f3dca5902dd08313472311bdba61 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 8 Sep 2026 09:36:23 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06):=20=EA=B4=80=20=EA=B8=B8=EC=9D=B4?= =?UTF-8?q?=EB=A5=BC=20**=EC=86=8C=EC=9C=A0=20=EC=B8=A1=EC=A0=90=EC=97=90?= =?UTF-8?q?=EB=A7=8C**=20=EC=8B=A3=EA=B2=8C=20=E2=80=94=20=EA=B0=99?= =?UTF-8?q?=EC=9D=80=20=EA=B4=80=EC=9D=84=20=EB=91=90=20=EB=B2=88=20?= =?UTF-8?q?=EC=85=80=20=EB=BB=94=ED=95=9C=20=EC=9E=90=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pipe_length_m` 을 넣고 실화면 [저장]으로 확인하다 드러남 — **관 9개인데 값이 10곳**에 실렸음. 까닭은 `attach_culvert_sets` 가 세트를 **폭의 절반까지 옆 측점에도** 붙이기 때문임(3D·카드가 이어 그리려고). 그 자리에 길이를 실으면 수량이 **같은 관을 두 번** 셈. - 스펙에 **놓인 누가거리(`chainage_m`)** 를 함께 얹음 — 파이썬 `attach_culvert_sets` · TS `attachCulvertSets` **둘 다**(한쪽만 얹으면 세트 거울 시험이 깨짐. 실제로 깨져서 알았음). - 길이는 그 값과 측점이 같을 때만 실음. - 옛 값 정리 — 이미 실려 있던 이웃 측점 4곳(260.0·800.0·900.0·980.0)에서 지웠음. **파생값이라 병합만으로는 안 지워짐**(merge 는 키를 얹기만 함). ⚠ **따로 드러난 것 — 관 3개(439.55·620.43·720.37)는 측점 행 자체가 없음.** 그 관들은 횡단 설계도 수량도 통째로 빠져 있음. 별건으로 조사할 것(계획서에 적음). 실측 결과 — 관 길이가 실린 측점 **6곳**(85.05→10.0 · 258.12→11.0 · 534.49→9.0 · 804.30→9.0 · 901.24→10.0 · 984.18→10.0m). 나머지 셋이 위 별건임. 시험 7건(소유 측점 판정 한 건 추가) · 전체 507 passed · 17 skipped. Co-Authored-By: Claude Opus 5 (1M context) --- B06_Section/B06_Section_Api_Types.ts | 3 +++ B06_Section/B06_Section_Engine_Culvert.py | 8 +++++++- B06_Section/B06_Section_Structure_Layouts.ts | 10 +++++++++- common_util/common_util_culvert_sets.ts | 8 +++++++- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/B06_Section/B06_Section_Api_Types.ts b/B06_Section/B06_Section_Api_Types.ts index d5f83b05..45a7dab6 100644 --- a/B06_Section/B06_Section_Api_Types.ts +++ b/B06_Section/B06_Section_Api_Types.ts @@ -218,6 +218,9 @@ export interface CulvertSideSpec { /** 배수관 측점의 세트(배관·기슭막이·보호공) 제원 — 횡단 카드 오버레이 입력. */ export interface CulvertSet { type: "pipe"; + /** 이 시설이 **놓인** 누가거리(m) — 세트는 옆 측점에도 붙으므로 소유 측점을 가리는 열쇠다. + * (2026-09-08 — 없을 때 관 길이가 이웃 측점에도 실려 같은 관을 두 번 셀 뻔했다.) */ + chainage_m?: number; pipe_kind: string | null; diameter_m: number; /** 관 위 최소 토피(m) — 별표2 교량·암거 복토 50㎝ 교차 참조. B05 하향 차단 기준. */ diff --git a/B06_Section/B06_Section_Engine_Culvert.py b/B06_Section/B06_Section_Engine_Culvert.py index b513afd5..865df085 100644 --- a/B06_Section/B06_Section_Engine_Culvert.py +++ b/B06_Section/B06_Section_Engine_Culvert.py @@ -435,7 +435,13 @@ def attach_culvert_sets(project_root: Path, cross_sections: list[dict[str, Any]] if abs(chainage - pipe_chainage) <= reach: # 세월교·BOX암거·물넘이는 배수관과 그림이 달라 키를 나눈다 — 소비처가 섞이지 않는다. kind = spec.get("type") - section[_SECTION_KEYS.get(str(kind), "culvert")] = spec + # ⚠ 스펙에 **그 시설이 놓인 누가거리**를 함께 얹는다(2026-09-08). 세트는 폭의 + # 절반까지 옆 측점에도 붙으므로, 이것이 없으면 소비처가 「소유 측점」을 못 가려 + # **같은 시설을 여러 측점에서 센다**(관 9개에 길이가 10곳 실렸던 자리). + section[_SECTION_KEYS.get(str(kind), "culvert")] = { + **spec, + "chainage_m": pipe_chainage, + } attached += 1 break return attached diff --git a/B06_Section/B06_Section_Structure_Layouts.ts b/B06_Section/B06_Section_Structure_Layouts.ts index 57ba09c3..8a61f7b8 100644 --- a/B06_Section/B06_Section_Structure_Layouts.ts +++ b/B06_Section/B06_Section_Structure_Layouts.ts @@ -132,7 +132,15 @@ function areaRowOf( if (!layouts) return null; // 관 길이는 면적과 **따로** 낸다 — 폐회로 면적을 못 내는 측점(설계선이 모자란 자리)에도 // 관은 서 있고, 수량은 그 길이를 필요로 한다(2026-09-08). - const pipeLengthM = layouts.culvert?.pipe?.lengthM; + // + // ⚠ **관을 가진 측점(소유)에만 싣는다.** 옆 측점도 그 관 구간에 걸리면 레이아웃을 만들지만 + // (`culvertLinkFor` — 3D·카드가 이어 그리려고), 그 자리에 길이를 실으면 **같은 관을 두 번** + // 세게 된다. 실측에서 관 9개에 값이 10곳 실렸던 자리다. + const pipeOwner = + !!section.culvert && + (typeof section.culvert.chainage_m !== "number" || + Math.abs(section.culvert.chainage_m - section.chainage_m) <= CHAINAGE_TOLERANCE_M); + const pipeLengthM = pipeOwner ? layouts.culvert?.pipe?.lengthM : undefined; const pipeRow: Record | null = typeof pipeLengthM === "number" && pipeLengthM > 0 ? { chainage_m: section.chainage_m, pipe_length_m: Number(pipeLengthM.toFixed(4)) } diff --git a/common_util/common_util_culvert_sets.ts b/common_util/common_util_culvert_sets.ts index 368d7af2..1b67957e 100644 --- a/common_util/common_util_culvert_sets.ts +++ b/common_util/common_util_culvert_sets.ts @@ -331,7 +331,13 @@ export function attachCulvertSets( let reach = CHAINAGE_TOLERANCE_M; if (SPAN_LINKED_TYPES.has(String(spec.type))) reach += (num(spec.span_m, 0) ?? 0) / 2; if (Math.abs(chainage - pipeChainage) <= reach) { - section[SECTION_KEYS[String(spec.type)] ?? "culvert"] = spec; + // ⚠ 스펙에 **그 시설이 놓인 누가거리**를 함께 얹는다(2026-09-08, 짝: 파이썬 + // `attach_culvert_sets`). 세트는 폭의 절반까지 옆 측점에도 붙으므로, 이것이 없으면 + // 소비처가 「소유 측점」을 못 가려 **같은 시설을 여러 측점에서 센다**. + section[SECTION_KEYS[String(spec.type)] ?? "culvert"] = { + ...spec, + chainage_m: pipeChainage, + }; attached += 1; break; }