From e95987950059dc12ebde471156d8e8484c911e34 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Fri, 28 Aug 2026 19:41:02 +0900 Subject: [PATCH] =?UTF-8?q?fix(B05,B06):=20=EB=8F=85=EB=A6=BD=20=EA=B8=B0?= =?UTF-8?q?=EC=8A=AD=EB=A7=89=EC=9D=B4=20=EA=B5=AC=EA=B0=84=EA=B0=92?= =?UTF-8?q?=EC=9D=B4=20=EC=A1=B0=EC=A0=95=EC=B0=BD=20=ED=82=A4=EC=99=80=20?= =?UTF-8?q?=EC=96=B4=EA=B8=8B=EB=82=98=20=EB=A6=AC=EC=85=8B=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=EA=B2=83=EC=9D=84=20=EA=B3=A0=EC=B9=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit B06 조정창은 구간값(길이·전/후)을 `{role}_revet_length_m` 등 배관 기슭막이와 같은 키로 pipe_points에 저장한다. 그런데 독립 기슭막이만 백엔드가 전용 키(`length_m`· `before_m`·`after_m`)를 읽어, 조정창에서 바꾼 값이 저장돼도 매번 원래 값으로 되돌아왔다(실데이터 확인: 234.1m에 두 벌의 키가 따로 존재). 배관과 옵션 키를 한 벌로 합쳐 원천을 하나로 만든다 — 이제 두 기슭막이의 차이는 관 유무(hidden_pipe)뿐이다. - B06_Section_Engine_Culvert `_revet_side`: `{role}_revet_*` 우선, 없으면 옛 전용 키로 폴백(구 저장분 호환) - B05_Profile_UI_Drainage_Facility: 독립 기슭막이 폼이 OUTLET_REVET_KEYS를 쓰고 저장 시 inlet_revet_* 에도 같이 싣는다. 읽기는 legacyRevetOptions로 옛 키 폴백 검증: tmp/tests/test_revet_span_source.py 3건 통과, tsc --noEmit 통과, load_culvert_sets 실데이터로 234.1m 유입 10.5/5/5.5 · 유출 42/21/21 반영 확인. Co-Authored-By: Claude Opus 5 (1M context) --- .../B05_Profile_UI_Drainage_Facility.ts | 41 ++++++++++++++++--- B06_Section/B06_Section_Engine_Culvert.py | 22 ++++++---- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_Drainage_Facility.ts b/B05_Profile/B05_Profile_UI_Drainage_Facility.ts index c8046944..1c25fc4b 100644 --- a/B05_Profile/B05_Profile_UI_Drainage_Facility.ts +++ b/B05_Profile/B05_Profile_UI_Drainage_Facility.ts @@ -235,10 +235,30 @@ export function createFacilityOptionsForm( revetSide.value = "양쪽"; const revetTiers = numberInput("1", "1"); revetTiers.value = "1"; - const standaloneRevet = createRevetmentFields( - { form: "form", length: "length_m", height: "height_m", before: "before_m", after: "after_m" }, - { ...REVET_COMMON_DEFAULTS, form: "돌쌓기(메)" }, - ); + // 옵션 키는 배관 유출 기슭막이와 **같은 한 벌**을 쓴다 — B06 조정창의 구간값도 이 키로 + // 저장되므로 원천이 하나여야 한다(2026-08-28: 전용 키 `length_m`을 쓰던 동안 조정창 + // 값이 매번 되돌아갔다). 읽을 때만 옛 전용 키를 폴백으로 본다. + const standaloneRevet = createRevetmentFields(OUTLET_REVET_KEYS, { + ...REVET_COMMON_DEFAULTS, + form: "돌쌓기(메)", + }); + /** 옛 전용 키(`form`·`length_m`…)로 저장된 값을 배관 키 자리로 옮겨 읽는다. */ + const legacyRevetOptions = ( + options: Record, + ): Record => { + const merged = { ...options }; + const pairs: Array<[string, string]> = [ + ["outlet_revet_form", "form"], + ["outlet_revet_length_m", "length_m"], + ["outlet_revet_height_m", "height_m"], + ["outlet_revet_before_m", "before_m"], + ["outlet_revet_after_m", "after_m"], + ]; + for (const [key, legacy] of pairs) { + if (merged[key] === undefined && options[legacy] !== undefined) merged[key] = options[legacy]; + } + return merged; + }; revetGroup.body.append( grid(labeled("설치 측", revetSide), standaloneRevet.formField), ...standaloneRevet.rows, @@ -472,7 +492,7 @@ export function createFacilityOptionsForm( fordSlope.value = text("ford_slope_pct"); revetSide.value = text("side") || "양쪽"; revetTiers.value = text("tiers") || "1"; - standaloneRevet.write(options); + standaloneRevet.write(legacyRevetOptions(options)); // 월류 폭 기본값 — 세월교 10m·물넘이 포장 5m(2026-08-18 사용자 확정, config 정의처). if (!fordWidth.value && (facility === "ford_pavement" || facility === "ford_bridge")) { fordWidth.value = String( @@ -524,6 +544,17 @@ export function createFacilityOptionsForm( const tiers = Number.parseInt(revetTiers.value, 10); if (Number.isFinite(tiers) && tiers >= 1) options.tiers = tiers; standaloneRevet.read(options); + // 양쪽 벽은 같은 한 벌이 정본 — 유입 키에도 같은 값을 실어 벽 둘이 갈리지 않게 한다. + for (const [inletKey, outletKey] of [ + [INLET_REVET_KEYS.form, OUTLET_REVET_KEYS.form], + [INLET_REVET_KEYS.length, OUTLET_REVET_KEYS.length], + [INLET_REVET_KEYS.height, OUTLET_REVET_KEYS.height], + [INLET_REVET_KEYS.before, OUTLET_REVET_KEYS.before], + [INLET_REVET_KEYS.after, OUTLET_REVET_KEYS.after], + ] as Array<[string | undefined, string | undefined]>) { + if (inletKey && outletKey && options[outletKey] !== undefined) + options[inletKey] = options[outletKey]; + } } return options; }, diff --git a/B06_Section/B06_Section_Engine_Culvert.py b/B06_Section/B06_Section_Engine_Culvert.py index de13eb45..acb8f872 100644 --- a/B06_Section/B06_Section_Engine_Culvert.py +++ b/B06_Section/B06_Section_Engine_Culvert.py @@ -217,19 +217,27 @@ def _culvert_set(options: dict[str, Any] | None) -> dict[str, Any]: def _revet_side(values: dict[str, Any], role: str) -> dict[str, Any]: """독립 기슭막이 한쪽 벽 제원 — 배관 유입/유출 벽과 같은 스펙 모양으로 만든다. - 독립 기슭막이는 형태·높이·길이·전후를 한 벌만 가지므로 양쪽 벽에 같은 값을 싣는다. - 실제로 어느 쪽(좌/우)을 세울지는 측점 방향을 아는 B06이 `side`로 가린다. + 옵션 키도 배관 벽과 **같은 한 벌**(`{role}_revet_*`)을 쓴다 — B06 조정창의 구간값 + (길이·전/후)이 그 키로 저장되므로, 여기서 다른 키를 읽으면 조정값이 매번 되돌아온다 + (2026-08-28 화면 실측: 조정창 길이 10.5가 저장돼도 10으로 리셋). 역할 키가 없으면 + B05 폼이 한 벌로 담던 옛 키(`length_m`…)로 폴백한다. """ - height = _number(values.get("height_m"), None) - form = values.get("form") + height = _number(values.get(f"{role}_revet_height_m"), _number(values.get("height_m"), None)) + form = values.get(f"{role}_revet_form") or values.get("form") spec: dict[str, Any] = { "role": role, "structure": "기슭막이", "revet_form": str(form) if form else None, "revet_height_m": height, - "revet_length_m": _number(values.get("length_m"), None), - "revet_before_m": _number(values.get("before_m"), None), - "revet_after_m": _number(values.get("after_m"), None), + "revet_length_m": _number( + values.get(f"{role}_revet_length_m"), _number(values.get("length_m"), None) + ), + "revet_before_m": _number( + values.get(f"{role}_revet_before_m"), _number(values.get("before_m"), None) + ), + "revet_after_m": _number( + values.get(f"{role}_revet_after_m"), _number(values.get("after_m"), None) + ), "face_slope": REVET_FACE_SLOPE, } if height is not None and height > 0: