/* ============================================================================= * M02_MasterTemplete_Hopyo_Unit.ts — 확인 창 대상 이름 옆 「단위 환산」 칸의 보이기 판정(PLAN 784-2 · 요구 635-2). * 순수 계산(화면 · fetch 없음) — 숨김 조건 · 두 단위 글 재료 · 추정 두께. * · same = 배 1 · 단위 같음(서버 갈래 같음 · 두 단위 · 단위표 1) → 칸 숨김 · 「단위 같음 ×1」 * · quota = 배가 몫(0.1)과 같음 → 칸 숨김 · 「몫 0.1」 만 * · input = 빈칸 · 추정 · 그 밖 → 입력 칸 「엑셀 1 ㎡ = 우리 [ ] 본」 * 값 자체(배)는 안 바꿈 — 서버 `Match.factor` 가 낸 배 · 갈래를 보이기만 다르게. * ========================================================================== */ export interface UnitPart { 배: number | null; 몫?: number | null; 환산?: { 배: number | null; 갈래: string } | null; 단위?: string | null; } export type UnitMode = "same" | "quota" | "input"; export interface UnitView { mode: UnitMode; /** 엑셀 단위 · 우리 단위(빈 글 = 모름) */ from: string; to: string; /** 추정 갈래 — 두께 m(㎡ → ㎥ 일 때만 · 아니면 null) */ thick: number | null; estimated: boolean; } const plain = (u: string | null | undefined): string => String(u ?? "") .replace(/\s+/g, "") .replace("㎡", "m2") .replace("㎥", "m3") .toLowerCase(); const close = (a: number, b: number): boolean => Math.abs(a - b) < 1e-9; export function unitView( p: UnitPart, from: string | null | undefined, to?: string | null, ): UnitView { const f = String(from ?? "").trim(); const t = String(to ?? p.단위 ?? "").trim(); const quota = p.몫 != null && p.몫 !== 1; // 몫 1 = 몫 없음과 같음 const kind = p.환산?.갈래; const unitSame = kind ? kind === "같음" || kind === "두 단위" || (kind === "단위표" && p.환산?.배 === 1) : plain(f) !== "" && plain(f) === plain(t); const at = quota ? (p.몫 as number) : 1; const hidden = p.배 !== null && close(p.배, at) && unitSame; const estimated = kind === "추정"; const thick = estimated && plain(f) === "m2" && plain(t) === "m3" && p.환산?.배 != null ? p.환산.배 : null; return { mode: hidden ? (quota ? "quota" : "same") : "input", from: f, to: t, thick, estimated, }; }