/* ============================================================================= * formula_doc_edit.ts * 수식 문서 고침(PLAN 802-3 · 802-4b-2) — 식 줄 · 금액 줄 · 값 식 숫자 고침을 문서에 얹음(화면 · fetch 없음) * 수식 화면(`formula_doc_screen.ts`)과 끊은 단가산출 블록(`formula_doc_sub.ts`)이 같은 고침을 씀 * ========================================================================== */ import { goodId, splitId, tidy, varId, type DocVar, type FormulaDoc, type MoneyLine, } from "../common_util/common_util_formula_doc"; import { swapLit } from "./formula_doc_render"; /** 머리 = 식 — 첫 「=」(비교 ==, <=, >=, != 빼고) */ export function splitLine(text: string): [string | null, string] { const m = /^([^=<>!]*?)\s*(?!=])=(?!=)\s*([\s\S]*)$/.exec(text); if (!m) return [null, text.trim()]; return [m[1].trim(), m[2].trim()]; } export const tidyText = (t: string): string => (t.trim() ? tidy(t.trim()) : ""); /** 기호 정의 — 없으면 「식」 갈래로 새로 */ export function ensureVar(d: FormulaDoc, id: string): DocVar { const have = (d.변수 ??= []).find((v) => varId(v) === id); if (have) return have; const [기호, 아래, 위] = splitId(id); const v: DocVar = { 열쇠: id, 기호, 아래, 위, 이름: "", 단위: "", 연결: { 갈래: "식" } }; d.변수.push(v); return v; } /** 식 줄 i 를 글로 — 빈 글 = 줄 지움 · 머리 바뀜 = 식 갈래 정의도 같이 */ export function editLine(d: FormulaDoc, i: number, text: string): void { const lines = (d.식 ??= []); const line = lines[i]; if (!line) return; if (!text.trim()) { lines.splice(i, 1); return; } const [h, body] = splitLine(text); const old = String(line.기호 ?? ""); if (h !== null && h !== old) { line.기호 = h; const was = (d.변수 ?? []).find((v) => varId(v) === old && (v.연결?.갈래 ?? "식") === "식"); if (was && goodId(h) && !(d.변수 ?? []).some((v) => varId(v) === h)) { const [기호, 아래, 위] = splitId(h); Object.assign(was, { 기호, 아래, 위 }); } } line.식 = tidyText(body); } /** 금액 줄 i 고침(null = 지움) — 단가 · 수량 글은 다듬음 · 빈 수량 = 칸 뺌 */ export function editMoney(d: FormulaDoc, i: number, patch: Partial | null): void { const lines = (d.금액 ??= []); if (!patch) { lines.splice(i, 1); return; } const line = lines[i]; if (!line) return; for (const [k, v] of Object.entries(patch)) { const text = typeof v === "string" && (k === "단가" || k === "수량") ? tidyText(v) : v; if (k === "수량" && text === "") delete line.수량; else (line as Record)[k] = text; } } /** 값 식 숫자 고침 — 식 줄 · 금액 줄 단가 · 수량 글의 at 번째 수 */ export function editLit( d: FormulaDoc, target: "line" | "price" | "qty", i: number, at: number, value: number, ): void { if (target === "line") { const line = d.식?.[i]; if (line) line.식 = swapLit(String(line.식 ?? ""), at, value); return; } const line = d.금액?.[i]; if (!line) return; const slot = target === "price" ? "단가" : "수량"; line[slot] = swapLit(String(line[slot] ?? ""), at, value); }