From a6b92ae3414f503bf50facf2b8eb13f18fcfa7e6 Mon Sep 17 00:00:00 2001 From: ypshim Date: Fri, 23 Oct 2026 14:58:12 +0900 Subject: [PATCH] fix(view): pick the solplate table's header by its row (L, W, T, T1, T2), not by the first "S(%)" label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The drawing has two "S(%)" labels; the first one in the file belonged to another table, so the solplate header was missing. The header is now the S(%) label with the most solplate column names on its row. The full 운곡교 교각도(2) DXF reads all ten solplate rows; a test adds a stray label. Co-Authored-By: Claude Haiku 5.5 --- src/core/dxf-table.ts | 9 +++++++-- tests/dxf-table.test.ts | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/dxf-table.ts b/src/core/dxf-table.ts index 9e0e8dc..0bc4e80 100644 --- a/src/core/dxf-table.ts +++ b/src/core/dxf-table.ts @@ -118,8 +118,13 @@ export interface SolplateTableRow { * their headers, as in the bearing ELEVATION table. */ export function parseSolplateTable(texts: DxfText[]): { rows: SolplateTableRow[]; errors: string[] } { - const sHeader = texts.find((t) => norm(t.text) === 's(%)' || norm(t.text) === 's%'); - if (!sHeader) return { rows: [], errors: ['솔플레이트 TABLE의 S(%) 머리글을 찾지 못했습니다.'] }; + // The drawing has more than one "S(%)" label: the header is the one with L, W, T, T1 and T2 on its row. + const SOL_NAMES = ['l', 'w', 't', 't1', 't2']; + const solScore = (t: DxfText) => texts.filter((u) => Math.abs(u.y - t.y) <= 60 && SOL_NAMES.includes(norm(u.text))).length; + const sCandidates = texts.filter((t) => norm(t.text) === 's(%)' || norm(t.text) === 's%'); + const sBest = sCandidates.map((t) => ({ t, score: solScore(t) })).sort((a, b) => b.score - a.score)[0]; + if (!sBest || sBest.score < 5) return { rows: [], errors: ['솔플레이트 TABLE의 머리글(NO, L, W, T, T1, T2)이 모두 있어야 합니다.'] }; + const sHeader = sBest.t; const headerY = sHeader.y; const headerRow = texts.filter((t) => Math.abs(t.y - headerY) <= 60); const key = (name: string) => headerRow.find((t) => norm(t.text) === name); diff --git a/tests/dxf-table.test.ts b/tests/dxf-table.test.ts index d232afc..0314260 100644 --- a/tests/dxf-table.test.ts +++ b/tests/dxf-table.test.ts @@ -47,6 +47,12 @@ import { SOLPLATE_REF } from '../src/core/bearing-ref'; describe('솔플레이트 TABLE 읽기 (승인 2026-10-23)', () => { const sp = JSON.parse(readFileSync(new URL('./fixtures/solplate-table-texts.json', import.meta.url), 'utf-8')) as DxfText[]; + it('a stray "S(%)" label elsewhere on the drawing does not replace the solplate header', () => { + const r = parseSolplateTable([{ x: 16000, y: 16200, text: 'S(%)' }, ...sp]); + expect(r.errors).toEqual([]); + expect(r.rows.length).toBe(10); + }); + it('reads S, L, W, T, T1 and T2 for all ten bearings, and they equal the reference values', () => { const r = parseSolplateTable(sp); expect(r.errors).toEqual([]);