Files
Aislo/resources/tester/test_137_design_pick.py
T
eomsangdonandClaude Opus 5.5 f6f0f74be5 feat(b06): 보라 설계선 고름 — 직선 조각 · 가림 뺌 · 치수 라벨 · 구역 판정 · 고름 하나만(137-2 · 137-3)
- 새 B06_Section_UI_Cross_Design_Pick.ts — 조각 합침 · 벽 · 본체 밖 조각 · 투명 판정 선 · 치수 · crossZoneAt(139-6 용) · 페이지 한 칸 고름
- 폴리곤 자르기 = A00_Common/b_polygon_clip.ts 공용(B07 Cross_Overlay 에서 옮김 · 바깥 조각 갈래)
- 카드 배선: 선 고르면 벽 · 본체 · 면적 풂 + 카드 고름 · 면적 고름도 본체 · 선 풂
- 시험 test_137_design_pick.py + helper_137_design_pick.cjs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jonfdxn1Xit9bdkNJpE4G
2026-10-09 15:00:12 +09:00

111 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""PLAN 137-2 · 137-3 — B06 보라 선 고름: 직선 조각 · 가림 · 치수 · 구역 · 판정 선 · 페이지 한 칸.
짝: `B06_Section/B06_Section_UI_Cross_Design_Pick.ts` · `A00_Common/b_polygon_clip.ts`(B07 에서 옮김) ·
`B06_Section_UI_Cross_View.ts`(배선 · 하나만). 실제 TS 를 `helper_137_design_pick.cjs` 가 Node 로 돌린다.
"""
from __future__ import annotations
import json
import os
import subprocess
import pytest
HERE = os.path.dirname(__file__)
ROOT = os.path.join(HERE, "..", "..")
pytestmark = pytest.mark.skipif(
not os.path.isdir(os.path.join(ROOT, "config", "node_modules")),
reason="프론트엔드 의존성 미설치",
)
@pytest.fixture(scope="module")
def out() -> dict:
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", os.path.join(HERE, "helper_137_design_pick.cjs")],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def _src(rel: str) -> str:
with open(os.path.join(ROOT, rel), encoding="utf-8") as f:
return f.read()
def test_같은_방향_토막은_직선_조각_하나(out) -> None:
"""0.5 m 토막 25개 → 성토 사면 · 노면 둘(가운데 꺾임) · 측구 · 절토 사면 = 다섯 · 거꾸로 그린 토막도 합침."""
assert out["merge"]["segments"] == 25
assert out["merge"]["pieces"] == [[-6.5, -2.5], [-2.5, 0], [0, 2.5], [2.5, 3], [3, 6]]
assert out["mergeStructure"] == 2 # 구조물 선은 설계선과 안 합침
def test_벽에_가린_부분은_빼고_보이는_조각만(out) -> None:
assert out["occlude"]["pieces"] == [[3, 4], [4.5, 6]]
assert out["occlude"]["covered"] == 0
def test_치수_사면길이_수평_높이_구배(out) -> None:
fill = out["measure"]["fill"]
assert (fill["horizontalM"], fill["heightM"], fill["grade"]) == (3, 2, "1:1.50")
assert abs(fill["lengthM"] - 13**0.5) < 1e-9
assert out["measure"]["road"]["grade"] == "2.0%" # 노면 = %
assert out["measure"]["flatSlope"] == "0.0%"
assert out["label"]["fill"] == "사면길이 3.61m · 수평 3.00m · 높이 2.00m · 1:1.50"
assert out["label"]["road"] == "길이 2.50m · 수평 2.50m · 높이 0.05m · 2.0%"
def test_구역_도로_절토_성토(out) -> None:
zone = out["zone"]
assert zone["road"] == {"zone": "road", "side": "left"}
assert zone["roadEdge"] == "road"
assert zone["ditch"] == {"zone": "cut", "side": "left"} # 측구 = 절토
assert zone["cutSlope"] == {"zone": "cut", "side": "left"}
assert zone["fillSlope"] == {"zone": "fill", "side": "right"}
assert zone["structure"] == "fill" # 구조물 트림 선 = 성토
assert zone["rightCutDitch"] == "cut"
assert zone["bothFill"] == "fill"
assert zone["pieceZones"] == ["fill", "road", "road", "cut", "cut"]
def test_실제_배관_측점_조각과_판정_선(out) -> None:
real = out["real"]
assert real["pieces"] < real["designLines"] # 토막이 조각으로 합쳐짐
assert real["structurePieces"] > 0 # 구조물 트림 선도 고름 대상
assert real["hits"] == real["pieces"]
assert real["wallCount"] == 2 and real["insideWall"] == 0 # 벽 안 조각 없음
assert real["hitsBelowStructure"] is True # 구조물 판정면이 위
assert real["picked"] == [0] and real["stopped"] is True # 카드 고름으로 안 번짐
assert real["activeCount"] == 1 and real["activeIndex"] == 1
assert real["labelOn"]["hidden"] is False and real["labelOn"]["text"].startswith("사면길이 ")
assert real["labelOff"] == {"hidden": True, "text": ""}
assert set(real["zones"]) <= {"road", "cut", "fill"}
def test_페이지_한_칸_고름(out) -> None:
assert out["slot"] == {"a1": 2, "a2": None, "b": 1, "cleared": None}
def test_카드_배선_하나만() -> None:
"""137-3 — 선을 고르면 벽 · 본체 · 면적을 풀고 카드도 고름 · 다른 고름은 선을 풂."""
view = _src("B06_Section/B06_Section_UI_Cross_View.ts")
assert "const pickLine = (index: number): void => {" in view
assert "if (!isSelected) onSelect(section.station_id);" in view
assert view.count("dropLine();") >= 4 # 본체 · 벽 · 카드 풂 · 면적
assert "setLineActive(pickedLineAt(section.station_id));" in view # 다시 그려도 되살림
assert "zoomBar.prepend(linePick.label);" in view # 치수 = [+ − ⤢] 왼쪽
css = _src("B06_Section/B06_Section_UI_Style_Cross_Areas.css")
assert ".b06-chart__design-hit.is-active {" in css
def test_폴리곤_자르기는_공용_한_벌() -> None:
b07 = _src("B07_DesignDetail/B07_DesignDetail_Cross_Overlay.ts")
assert "function clipSegment(" not in b07 and "function pointInPolygon(" not in b07
assert 'from "../A00_Common/b_polygon_clip"' in b07