fix(b08): 관 지점 구조물 id 를 서버 id 로 맞춤 — 측점 셋째 자리 사본도 모달 조합 카드 보임(167-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
This commit is contained in:
@@ -58,6 +58,17 @@ export function linkedOnly<T extends PlacedItem>(
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 관 지점 구조물 id — 서버가 낸 id(사본 · 시설 · `pipe@{측점 셋째 자리}`) 가운데 같은 측점(±6mm)의 것 ·
|
||||
* 없으면 null. 관 지점 응답 측점은 둘째 자리라(B04 `round(…, 2)`) 셋째 자리 id 와 어긋남(167-1). */
|
||||
export function pipeOwnerId(chainage: number, ids: Iterable<string>): string | null {
|
||||
for (const id of ids) {
|
||||
const owner = id.split(GROUP_JOIN)[0];
|
||||
const at = Number(owner.slice("pipe@".length));
|
||||
if (owner.startsWith("pipe@") && Math.abs(at - chainage) <= 0.006) return owner;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 미연결 시설 한 칸(서버 `unlinked_facilities` · 154) — 본체 `group` = null. */
|
||||
export interface UnlinkedSlot {
|
||||
/** 사본 id(본체 = 시설 id · 그룹 = `{id}__{그룹}`) */
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
combosAt,
|
||||
comboId,
|
||||
linkedOnly,
|
||||
pipeOwnerId,
|
||||
summaryColumns,
|
||||
summaryStations,
|
||||
type ComboColumn,
|
||||
@@ -235,8 +236,13 @@ export async function renderStructureSummary(host: HTMLElement, projectId: strin
|
||||
return group ? { group, name: rest.join(" ") || group } : null;
|
||||
};
|
||||
const comboPath = (id: string): string | null => paths.get(id)?.join(" ") || null;
|
||||
// 관 지점 id = 서버가 낸 id 먼저(응답 측점은 둘째 자리 · id 는 셋째 자리 · 167-1)
|
||||
const ids = [...Object.keys(linked), ...(saved?.facilities ?? []).map((f) => f.id)];
|
||||
const placed = linkedOnly(
|
||||
pipes.map((point) => ({ ...point, structure_id: pipeStructureId(point.chainage_m) })),
|
||||
pipes.map((point) => ({
|
||||
...point,
|
||||
structure_id: pipeOwnerId(point.chainage_m, ids) ?? pipeStructureId(point.chainage_m),
|
||||
})),
|
||||
linked,
|
||||
);
|
||||
const mine = linkedOnly(structures.structures, linked);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""167-1 B08 구조물도 모달 — 일부 칸만 연결된 관 지점도 조합 카드가 뜸.
|
||||
|
||||
까닭 = 관 지점 응답 측점은 소수 둘째 자리(B04 `round(…, 2)` · 80.17) · 사본 id 는 셋째 자리
|
||||
(`pipe@80.167`) → 화면이 만든 id 가 사본과 어긋나 `linkedOnly` 가 빼고 `combosAt` 이 빈 배열.
|
||||
고침 = 서버가 낸 id(사본 · 시설) 가운데 같은 측점(±6mm)의 것을 씀(`pipeOwnerId`).
|
||||
`B08_Quantity_Summary_Data.ts` 를 node 로 돌림(61-1 시험과 같은 꼴).
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from test_61_1_b08_summary_table import _item, _run
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
# 검증_랩탑메인 재현 꼴 — 배관 네 칸 가운데 본체만 연결
|
||||
LINKED = {
|
||||
"pipe@80.167": {
|
||||
"항목": _item("SS55"),
|
||||
"폴더": "pipe@80.167",
|
||||
"부분": ["도면"],
|
||||
"경로": ["기슭막이"],
|
||||
}
|
||||
}
|
||||
FACILITY_IDS = ["pipe@80.167", "pipe@173.09", "st1"]
|
||||
POINT = {"chainage_m": 80.17, "summary_item": _item("SS55")} # 응답 = 둘째 자리
|
||||
|
||||
|
||||
def test_서버_id_를_씀():
|
||||
out = _run(
|
||||
f"\nconst ids = {json.dumps(list(LINKED) + FACILITY_IDS)};"
|
||||
"\nconsole.log(JSON.stringify({"
|
||||
" a: pipeOwnerId(80.17, ids), b: pipeOwnerId(173.09, ['pipe@173.09__gford']),"
|
||||
" c: pipeOwnerId(258.12, ids), d: pipeOwnerId(80.16, ['st1', 'pipe@80.165']) }));"
|
||||
)
|
||||
assert out == {"a": "pipe@80.167", "b": "pipe@173.09", "c": None, "d": "pipe@80.165"}
|
||||
|
||||
|
||||
def test_한_칸만_연결_때_조합_하나():
|
||||
out = _run(
|
||||
f"\nconst linked = {json.dumps(LINKED, ensure_ascii=False)};"
|
||||
f"\nconst p = {json.dumps(POINT, ensure_ascii=False)};"
|
||||
"\nconst old = linkedOnly([{ ...p, structure_id: 'pipe@80.17' }], linked);"
|
||||
"\nconst got = linkedOnly([{ ...p, structure_id: pipeOwnerId(p.chainage_m, Object.keys(linked)) }], linked);"
|
||||
"\nconsole.log(JSON.stringify({ old: combosAt(old, 80.167).length, got: combosAt(got, 80.167) }));"
|
||||
)
|
||||
assert out["old"] == 0 # 고치기 전 = 카드 없음
|
||||
assert len(out["got"]) == 1
|
||||
assert out["got"][0]["copyId"] == "pipe@80.167" and out["got"][0]["id"] == "system||SS55"
|
||||
|
||||
|
||||
def test_화면_연결():
|
||||
summary = (ROOT / "B08_Quantity/B08_Quantity_UI_Summary.ts").read_text(encoding="utf-8")
|
||||
assert "...(saved?.facilities ?? []).map((f) => f.id)" in summary
|
||||
assert "pipeOwnerId(point.chainage_m, ids) ?? pipeStructureId(point.chainage_m)" in summary
|
||||
Reference in New Issue
Block a user