feat(m01-sl): 표 상자 이음매 — 블록은 표 알약 칸부터 · 줄면 옛 줄 지움 · 머리 줄 바뀜 알림
- 표 블록 왼위 = 그 표 상자의 「표」 바깥 값 알약 칸(A1 · E1 무엇이든) · applyOutside 가 그 칸부터 머리 줄 포함 채움 - 표가 줄었으면 블록 열 아래 남은 옛 값 칸을 지움(찾기 판 수식은 블록 열 밖이라 그대로) - answersToValues(cells, 답, sl) — 시트 머리 줄과 받은 머리 줄이 다르면 쉬운 말 - addNode(table) = 빈 시트(Table 이 블록 · 찾기 판 · 알약을 채움 — 틀 칸이 블록과 겹치지 않게) - 시험 15개(Table_Build 와 잇는 시험 더함) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk
This commit is contained in:
@@ -222,7 +222,7 @@ def test_바깥값_칸목록과_표_덩어리() -> None:
|
||||
]
|
||||
assert (e1, f2, e3, f3) == ({"값": "뒷길이"}, {"값": 0.15}, {"값": 30}, None)
|
||||
assert lg == {"결과": 12.5}
|
||||
assert "「메쌓기 표」의 입력 알약 「조건」이 비어 있음" in check
|
||||
assert check == []
|
||||
|
||||
|
||||
def test_알약_정하기_이름바꾸면_선이_따라감() -> None:
|
||||
@@ -361,3 +361,53 @@ def test_항목_틀은_Item_노무_틀과_같은_칸() -> None:
|
||||
["단가", "B5"], ["금액", "B6"], ["노무비", "B7"], ["재료비", "B8"], ["경비", "B9"], ["사용 수량", "B10"],
|
||||
] # fmt: skip
|
||||
assert ref == '{"what":"노무"}'
|
||||
|
||||
|
||||
# 표 상자 이음매 — Table_Build(sub3) 가 짠 품셈 표 상자에 서버 꼴 블록(머리 줄 + 줄 · A1 부터)을 넣고 찾기
|
||||
TABLE = r"""
|
||||
const T = loadTs(path.join(ROOT, "M01_MasterData", "SheetLogic", "M01_SL_Table_Build.ts"));
|
||||
let sl = M.newLogic("표 시험");
|
||||
let r = M.addNode(sl, "table", "메쌓기"); sl = r.sl; const tb = r.node;
|
||||
const info = { key: "QF000421", name: "메쌓기", base: "1㎡", source: "", no: "13-4-1",
|
||||
conds: { 뒷길이: "수", 돌: "고르기" }, vals: { 석공: "인" }, rule: null, notes: [],
|
||||
rows: [{ 뒷길이: 25, 돌: "깬잡석", 석공: 0.15 }, { 뒷길이: 30, 돌: "깬돌", 석공: 0.26 },
|
||||
{ 뒷길이: 35, 돌: "깬돌", 석공: 0.3 }] };
|
||||
sl = T.applyTable(sl, tb.id, info, { cond: ["뒷길이", "돌"], out: ["석공"] },
|
||||
{ ref: "QF000421", fillBlock: false, outside: true }).sl;
|
||||
r = M.addNode(sl, "input", "뒷길이"); sl = r.sl; const len = r.node;
|
||||
r = M.addNode(sl, "input", "돌"); sl = r.sl; const stone = r.node;
|
||||
sl = E.applyOutside(sl, [{ node: len.id, cell: "B2", value: 35 }, { node: stone.id, cell: "B2", value: "깬돌" }]);
|
||||
sl = link(sl, len, "뒷길이", sl.nodes.find(n => n.id === tb.id), "뒷길이");
|
||||
sl = link(sl, stone, "돌", sl.nodes.find(n => n.id === tb.id), "돌");
|
||||
const ROWS = [["뒷길이", "돌", "석공"], [25, "깬잡석", 0.15], [30, "깬돌", 0.26], [35, "깬돌", 0.3]];
|
||||
const cells = E.outsideCells(sl);
|
||||
"""
|
||||
|
||||
|
||||
def test_표_상자_바깥값_블록_찾기_줄면_옛줄_지움_머리바뀜_알림() -> None:
|
||||
got = _run(
|
||||
TABLE
|
||||
+ "const first = E.answersToValues(cells, [{ id: cells[0].id, ok: true, rows: ROWS }], sl);\n"
|
||||
"const s1 = E.applyOutside(sl, first.values);\n"
|
||||
"const shrink = E.answersToValues(cells, [{ id: cells[0].id, ok: true, rows: ROWS.slice(0, 3) }], s1);\n"
|
||||
"const s2 = E.applyOutside(s1, shrink.values);\n"
|
||||
"const moved = E.answersToValues(cells, [{ id: cells[0].id, ok: true,"
|
||||
" rows: [['돌', '뒷길이', '석공'], ['깬돌', 30, 0.26]] }], s1);\n"
|
||||
"out([cells, first.errors, E.evalLogic(s1).pills[tb.id], shrink.errors, sheet(s2, tb.id).칸.A4 ?? null,"
|
||||
" sheet(s2, tb.id).칸.C4 ?? null, E.evalLogic(s2).pills[tb.id], moved.errors]);"
|
||||
)
|
||||
cells, first_err, found, shrink_err, a4, c4, gone, moved_err = got
|
||||
assert cells == [
|
||||
{
|
||||
"id": "n1!A1",
|
||||
"node": "n1",
|
||||
"cell": "A1",
|
||||
"kind": "table",
|
||||
"ref": "QF000421",
|
||||
"source": {"kind": "표", "table": "QF000421"},
|
||||
}
|
||||
]
|
||||
assert first_err == [] and found["석공"] == 0.3 and found["표"] == "뒷길이"
|
||||
assert shrink_err == [] and a4 is None and c4 is None
|
||||
assert gone["석공"] == "#N/A"
|
||||
assert moved_err == ["「표 · 메쌓기」 표 머리 줄이 바뀜 — 표를 다시 골라야 함"]
|
||||
|
||||
Reference in New Issue
Block a user