From e1f85e5d86d471f5845b8442a57045dc1d036e34 Mon Sep 17 00:00:00 2001 From: ypshim Date: Tue, 3 Nov 2026 18:05:32 +0900 Subject: [PATCH] =?UTF-8?q?refactor(abut):=20=EB=B2=BD=EC=B2=B4=C2=B7?= =?UTF-8?q?=ED=9D=89=EB=B2=BD=20=EC=B9=B4=EB=93=9C=EC=9D=98=20=EC=82=BD?= =?UTF-8?q?=EB=8F=84=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 형상 카드의 삽도 SVG 표시를 제거하고, 삽도 모듈(src/view/abut-section-svg.ts)과 테스트를 삭제 - 입력 격자, 구간 표, 확인 필요 노트는 그대로 둠 - 테스트 637건 통과, 타입 검사·빌드 통과. 브라우저 시각 확인은 미실시 Co-Authored-By: Claude Haiku 5.5 --- src/main.ts | 9 ------ src/style.css | 11 ++------ src/view/abut-section-svg.ts | 51 ---------------------------------- tests/abut-section-svg.test.ts | 34 ----------------------- 4 files changed, 2 insertions(+), 103 deletions(-) delete mode 100644 src/view/abut-section-svg.ts delete mode 100644 tests/abut-section-svg.test.ts diff --git a/src/main.ts b/src/main.ts index d64a6f2..ea32e80 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,7 +12,6 @@ import { applyAbutEdit, applyBearingEdit, applyShapeEdit, ABUT_EDIT_FIELDS, SHAP import { ABUT_SHAPE_DEFAULT, resolveShape } from './core/abut/shape'; import { abutShown, piersShown } from './core/abut/visibility'; import { abutMemberRows, ABUT_MEMBER_EDITABLE, type AbutMemberId } from './core/abut/member-list'; -import { abutSectionSvg } from './view/abut-section-svg'; import type { WingForm } from './core/abut/geometry'; import { buildMembers } from './core/abut/members'; import { buildWings } from './core/abut/wings'; @@ -791,14 +790,6 @@ function fillAbutSlot(slot: (typeof ABUT_SLOTS)[keyof typeof ABUT_SLOTS], rec: A wingBox.replaceChildren(); bearings.replaceChildren(); shape.replaceChildren(); - // 삽도 (벽체·흉벽 개략 단면): the values it names are the card's values, so the drawing follows each change. - const drawing = el('div', undefined, 'abut-section'); - drawing.innerHTML = abutSectionSvg( - resolveShape(rec.shape), - { ...ABUT_SHAPE_DEFAULT, ...(rec.shape ?? {}) }, - { seatEl: rec.seatEl, footingBottomEl: rec.foundationBottomEl, groundEl: rec.groundEl }, - ); - shape.append(drawing); msg.textContent = ''; const apply = (next: AbutRecord) => { state.abutments = state.abutments.map((a) => (a.name === next.name ? next : a)); diff --git a/src/style.css b/src/style.css index b5741c2..29b2dbe 100644 --- a/src/style.css +++ b/src/style.css @@ -869,13 +869,6 @@ body { background: #eef1f4; font-family: 'Noto Sans KR', system-ui, sans-serif; .quantity-total { margin-bottom: 16px; } /* 교대 삽도 (벽체·흉벽 개략 단면): fills the panel width; the labels follow the card's values. */ -.abut-section { margin-bottom: 12px; background: #f6f8fa; border: 1px solid #d5dbe2; border-radius: 6px; padding: 8px; } -.abut-section svg { display: block; width: 100%; height: auto; } -.abut-section text { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; fill: #18212b; } -.abut-section rect { stroke: #55606e; stroke-width: 1; } -.abut-section .abut-footing { fill: #b9c3ce; } -.abut-section .abut-wall { fill: #d8dee6; } -.abut-section .abut-parapet { fill: #9aa7b5; } /* ② 형상계획: with an abutment selected, only the abutment card shows; the pier cards are hidden (2026-11-03). */ #view-plan.abut-selected .members-title, @@ -890,9 +883,9 @@ body { background: #eef1f4; font-family: 'Noto Sans KR', system-ui, sans-serif; #view-plan.abut-selected #abut-members { display: block; } #abut-members .pier-name span:first-child { display: block; } -/* 교대 형상 입력: the 삽도 on top, then a 3-column grid of input · default (시안 ②), the 확인 필요 notes at the end (2026-11-03). */ +/* 교대 형상 입력: a 3-column grid of input · default (시안 ②), the 확인 필요 notes at the end (2026-11-03). */ #abut-panel-plan-shape, #abut-panel-shape { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr); gap: 6px 10px; align-items: center; } -#abut-panel-plan-shape > .abut-section, #abut-panel-shape > .abut-section, #abut-panel-plan-shape > .abut-qa { grid-column: 1 / -1; } +#abut-panel-plan-shape > .abut-qa { grid-column: 1 / -1; } .abut-qa { border-top: 1px solid #d5dbe2; padding-top: 8px; } .abut-qa p { margin: 3px 0; } diff --git a/src/view/abut-section-svg.ts b/src/view/abut-section-svg.ts deleted file mode 100644 index 2b41faf..0000000 --- a/src/view/abut-section-svg.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { type AbutShape, type ResolvedShape } from '../core/abut/shape'; - -/** EL values (m) the drawing names as read-only labels; they come from the record, not from this card. */ -export interface AbutLevels { - seatEl: number; - footingBottomEl: number; - groundEl: number; -} - -/** - * 벽체·흉벽 개략 단면 (시안 ② 삽도). Not to scale: the heights are fixed for legibility, - * and the labels show the card's values in mm, so the numbers the user types are what the drawing names. - * t runs along the 교대 직각 방향 (배면 −, 전면 +); the 교대축 is t = 0. - */ -export function abutSectionSvg(r: ResolvedShape, v: AbutShape, levels?: AbutLevels): string { - const S = 100; // px per m - const YMAX = 4.6; // highest drawn height (m above the footing bottom) - const tMin = r.footingBackM - 0.4; - const tMax = r.footingFrontM + 0.6; - const W = (tMax - tMin) * S; - const H = (YMAX + 0.8) * S; - const X = (t: number) => (t - tMin) * S; - const Y = (h: number) => (YMAX - h) * S; - const fT = r.footingThicknessM; - const wallTop = fT + 2.0; // illustrative wall height - const parapetTop = wallTop + 0.9; // illustrative parapet height - const rect = (t0: number, t1: number, h0: number, h1: number, cls: string) => - ``; - const text = (x: number, y: number, s: string, anchor = 'start') => - `${s}`; - const wallMid = (r.wallBackM + r.wallFrontM) / 2; - return [ - ``, - rect(r.footingBackM, r.footingFrontM, 0, fT, 'abut-footing'), - rect(r.wallBackM, r.wallFrontM, fT, wallTop, 'abut-wall'), - rect(r.parapetBackM, 0, wallTop, parapetTop, 'abut-parapet'), - text(4, Y(wallTop + 0.45), `흉벽 높이 ${v.parapetHeightMm}`), - text(X(r.parapetBackM) - 4, Y(parapetTop + 0.2), `흉벽 두께 ${v.parapetThicknessMm}`, 'start'), - text(X(wallMid), Y(fT + 1.0), `벽체 두께 ${v.wallThicknessMm}`, 'middle'), - text(X(r.wallFrontM) + 6, Y(wallTop - 0.3), `벽체 전면 ${v.wallFrontMm}`), - text(X(r.wallFrontM) + 6, Y(wallTop - 0.8), `브라켓 높이 ${v.bracketHeightMm}`), - text(X(r.wallFrontM) + 6, Y(fT + 0.4), `수축줄눈 ${v.shrinkJointCount}개`), - text(4, Y(fT / 2) + 4, `저판 두께 ${v.footingThicknessMm}`), - text(X(r.footingBackM), Y(0) + 18, `저판 뒷굽 ${v.footingBackMm}`), - text(X(r.footingFrontM), Y(0) + 18, `저판 앞굽 ${v.footingFrontMm}`, 'end'), - levels ? text(4, H - 44, `교좌면 ${levels.seatEl.toFixed(3)} · 기초 하단 ${levels.footingBottomEl.toFixed(3)} · 지반고 ${levels.groundEl.toFixed(3)} m`, 'start') : '', - text(4, H - 22, '개략 도시 · 축척 아님', 'start'), - text(4, H - 6, `흉벽 상단 Level 좌 ${v.parapetLevelLeftMm} · 우 ${v.parapetLevelRightMm} (계산 미사용, QA-4)`, 'start'), - '', - ].join(''); -} diff --git a/tests/abut-section-svg.test.ts b/tests/abut-section-svg.test.ts deleted file mode 100644 index f18bcbc..0000000 --- a/tests/abut-section-svg.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { ABUT_SHAPE_DEFAULT, resolveShape } from '../src/core/abut/shape'; -import { abutSectionSvg } from '../src/view/abut-section-svg'; - -describe('교대 삽도 (벽체·흉벽 개략 단면, 시안 ②)', () => { - it('names the card values in mm, including the new ones', () => { - const svg = abutSectionSvg(resolveShape(), ABUT_SHAPE_DEFAULT); - expect(svg).toContain('흉벽 높이 2500'); - expect(svg).toContain('벽체 두께 2400'); - expect(svg).toContain('저판 뒷굽 -1800'); - expect(svg).toContain('수축줄눈 1개'); - expect(svg).toContain('Level 좌 450 · 우 995'); - }); - - it('follows a changed value, and says it is not to scale', () => { - const v = { ...ABUT_SHAPE_DEFAULT, shrinkJointCount: 3, parapetHeightMm: 2200 }; - const svg = abutSectionSvg(resolveShape(v), v); - expect(svg).toContain('수축줄눈 3개'); - expect(svg).toContain('흉벽 높이 2200'); - expect(svg).toContain('축척 아님'); - }); - - it('names the 교좌면, 기초 하단 and 지반고 EL as read-only labels when given', () => { - const svg = abutSectionSvg(resolveShape(), ABUT_SHAPE_DEFAULT, { seatEl: 44.367, footingBottomEl: 40.895, groundEl: 33.984 }); - expect(svg).toContain('교좌면 44.367 · 기초 하단 40.895 · 지반고 33.984 m'); - }); - - it('draws the footing, wall and parapet as separate shapes', () => { - const svg = abutSectionSvg(resolveShape(), ABUT_SHAPE_DEFAULT); - expect(svg.match(/')).toBe(true); - }); -});