feat(771-1·771-2): B05 예정노선 수정 — 중간 노드에서 긋기 · 닿은 노드 사이 갈음 · 지움 뒤 긋기 Esc = 지움 전
- 771-2: 한 선 페이지(B05) 중간 노드 누름 = 그 노드에서 긋기 · 같은 선 다른 노드에 닿으면 그 사이 갈음(rejoinSpan · 거꾸로 됨 · 한 줄) · 같은 노드 · 안 닿고 끝냄 = 꼴 그대로 + 안내 · 되돌리기 한 걸음 · D03 는 중간 꺾임점 = 갈래 그대로 - 771-1: 긋기 Esc = 긋기 직전 꼴 · 지움(노드 · 토막 · 구역 · 전체 · 잇단 지움) 바로 뒤 긋기면 지움 전 꼴(D03 같은 부품) - 시험: test_771_2_rejoin_span 새로 · test_626_3 의 lineLimitBlock 줄 문자열 대조를 새 꼴(branches 변수)로 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -86,7 +86,8 @@ def test_D03_긋기_고르기_메뉴_속성판_그대로_한_선():
|
||||
assert 'createElement("button")' not in ui
|
||||
# 숨김 = 기능 표 읽기(635-1 · 플래그 없음)
|
||||
draw = _src(D03 / "D03_PlanAnalysis_UI_Draw.ts")
|
||||
assert 'featureOn(params.page, "branch") ? null : lineLimitBlock(target.kind, network)' in draw
|
||||
assert 'const branches = featureOn(params.page, "branch");' in draw
|
||||
assert "branches ? null : lineLimitBlock(target.kind, network)" in draw
|
||||
assert 'markButton.hidden = !featureOn(opts.page, "years");' in _src(
|
||||
D03 / "D03_PlanAnalysis_UI_DrawPanel.ts"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
"""B05 중간 노드에서 긋기(PLAN 771-2 · 요구 613) — TS `logic/D03_PlanAnalysis_Span.ts` `rejoinSpan`.
|
||||
|
||||
중간 노드에서 그은 점이 같은 선 다른 노드에 닿음 = 두 노드 사이 옛 구간을 새 점으로 갈음 · 한 줄 그대로 ·
|
||||
거꾸로(앞 노드에 닿음) = 점 차례 뒤집어 넣음 · 같은 노드 = 까닭 글(꼴 그대로) · 끝점에 닿음 = 끝까지 갈음 ·
|
||||
노드 기록 = 꼭짓점과 같은 길이.
|
||||
|
||||
./venv/Scripts/python.exe -m pytest resources/tester/test_771_2_rejoin_span.py -q
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
TS_FILE = ROOT / "D03_PlanAnalysis" / "logic" / "D03_PlanAnalysis_Span.ts"
|
||||
TSC = ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc"
|
||||
|
||||
_RUNNER = """
|
||||
import { writeFileSync } from "node:fs";
|
||||
import * as plan from "./D03_PlanAnalysis/logic/D03_PlanAnalysis_Plan.js";
|
||||
import * as span from "./D03_PlanAnalysis/logic/D03_PlanAnalysis_Span.js";
|
||||
let n = plan.newLine(plan.emptyNetwork(), [0, 0]);
|
||||
for (const p of [[100, 0], [200, 0], [300, 0], [400, 0]]) n = plan.appendVertex(n, 0, p);
|
||||
const L = span.nodeRecord("length", 20, 9);
|
||||
const S = span.nodeRecord("slope", 20, 9);
|
||||
writeFileSync(
|
||||
process.argv[2],
|
||||
JSON.stringify({
|
||||
forward: span.rejoinSpan(n, 0, 1, 3, [[150, 50], [250, 50]]),
|
||||
backward: span.rejoinSpan(n, 0, 3, 1, [[250, 50], [150, 50]]),
|
||||
same: span.rejoinSpan(n, 0, 2, 2, [[150, 50]]),
|
||||
head: span.rejoinSpan(n, 0, 2, 0, [[100, -50]]),
|
||||
tail: span.rejoinSpan(n, 0, 2, 4, [[300, 50]]),
|
||||
recorded: span.rejoinSpan(n, 0, 3, 1, [[250, 50], [150, 50]], [L, S]),
|
||||
same_text: span.REJOIN_SAME,
|
||||
}),
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
def _run_ts(tmp_path: Path) -> dict:
|
||||
out = tmp_path / "js"
|
||||
subprocess.run( # noqa: S603 — 고정 실행 파일
|
||||
[
|
||||
"node",
|
||||
str(TSC),
|
||||
str(TS_FILE),
|
||||
"--outDir",
|
||||
str(out),
|
||||
"--rootDir",
|
||||
str(ROOT),
|
||||
"--module",
|
||||
"esnext",
|
||||
"--target",
|
||||
"es2022",
|
||||
"--moduleResolution",
|
||||
"bundler",
|
||||
"--ignoreConfig",
|
||||
],
|
||||
cwd=str(ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
for emitted in out.rglob("*.js"):
|
||||
emitted.write_text(
|
||||
re.sub(r'(from\s+"\.\.?/[^"]+)"', r'\1.js"', emitted.read_text(encoding="utf-8")),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(out / "runner.mjs").write_text(_RUNNER, encoding="utf-8")
|
||||
result = tmp_path / "out.json"
|
||||
subprocess.run( # noqa: S603
|
||||
["node", str(out / "runner.mjs"), str(result)],
|
||||
cwd=str(ROOT),
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
return json.loads(result.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def _vertices(network: dict) -> list:
|
||||
assert len(network["lines"]) == 1 # 한 줄 그대로
|
||||
return network["lines"][0]["vertices"]
|
||||
|
||||
|
||||
def test_forward_and_backward(tmp_path: Path) -> None:
|
||||
r = _run_ts(tmp_path)
|
||||
want = [[0, 0], [100, 0], [150, 50], [250, 50], [300, 0], [400, 0]]
|
||||
assert _vertices(r["forward"]) == want
|
||||
assert _vertices(r["backward"]) == want # 거꾸로 그어도 선 차례로
|
||||
|
||||
|
||||
def test_same_node_and_ends(tmp_path: Path) -> None:
|
||||
r = _run_ts(tmp_path)
|
||||
assert r["same"] == r["same_text"]
|
||||
assert "같은 노드" in r["same"]
|
||||
assert _vertices(r["head"]) == [[0, 0], [100, -50], [200, 0], [300, 0], [400, 0]]
|
||||
assert _vertices(r["tail"]) == [[0, 0], [100, 0], [200, 0], [300, 50], [400, 0]]
|
||||
|
||||
|
||||
def test_backward_records(tmp_path: Path) -> None:
|
||||
line = _run_ts(tmp_path)["recorded"]["lines"][0]
|
||||
nodes = line["nodes"]
|
||||
assert len(nodes) == len(line["vertices"]) == 6 # 서버 400 막음
|
||||
# 선 차례 [150,50] 앞 토막 = 닿은 자리(자유 · null) · [250,50] 앞 토막 = 둘째 찍은 점 기록(S) · 끝 노드 = 자유
|
||||
assert nodes[2] is None
|
||||
assert nodes[3]["kind"] == "slope"
|
||||
assert nodes[4]["kind"] == "free"
|
||||
Reference in New Issue
Block a user