- 단위 규칙 한 벌(common_util_line_stack_unit) — 왼쪽 값 칸 · 식 줄 · 옵션 · 오른쪽 산출근거 · 기계 제어 구역 · 기계 보기가 같이 씀 · 메타 단위(구분 따름 · 수(…) · 원문 단위 없음) 안 그림 · %(설명) = % · 10^-7 = 10⁻⁷ · 기계 칸 연결 = 기계 표 칸 단위 · 코드 값 쉼표 없음 - 비목 · 금액 줄 = 「단가 원/단위 × (수량 식) 단위 = 금액 원」 · 소계 · 합계 · 계 = 원 · 단가 · 수량 한 덩이(줄 바뀜에 단위 안 떨어짐) - 기계경비식 겹분수 → 중간 줄(상여 · 휴지 · 손료계수 · common_util_line_stack_frac) · 한 줄 분수 한 층 - 기계 제어 구역 단위 = 칸 밖 바로 뒤 · 기계 보기 오른쪽 = 박기 전 기계 칸 단위 - 휴대폰 폭(560 px 밑) 산출근거 금액 칸 넷 걷음(가로 넘침 0) · 분수 줄 위아래 여유 - 전수 1,520 표시 탓 43,218 → 0 · 기계 겹분수 2 층 넘는 줄 1,040 → 0 · 금액 · 식 · 문서 자료 불변(그리기만) - 시험 test_845_2_unit_show(차린 줄 글 전수 지킴) · shownUnit 걷음(규칙 한 벌로) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
89 lines
4.1 KiB
TypeScript
89 lines
4.1 KiB
TypeScript
/* =============================================================================
|
||
* common_util_line_stack_unit.ts
|
||
* 단가산출 단위 그리는 규칙 한 벌(PLAN 845-2 · 요구 880) — 왼쪽 편집 · 오른쪽 산출근거 · 기계 제어 구역 · 기계 보기가 같이 씀
|
||
* ㉠ 값 줄 = 값 뒤 단위(`varUnit`) ㉡ 식 줄 = 결과 값 뒤만(식 가운데 숫자 뒤 없음)
|
||
* ㉢ 비목 · 금액 줄 = 「단가 원/단위 × (수량 식) 단위 = 금액 원」(`moneyUnits` — 수량이 식이면 괄호로 식 전체에 단위) ·
|
||
* 소계 · 합계 = 원(머리 [원/㎥] = 결과 하나당)
|
||
* ㉣ 무차원 = 빈 칸 ㉤ 율 = %(「%(인력품 대비)」 등 설명 괄호 뗌) ㉥ 왼쪽 값 칸 = 칸 바로 뒤 한 자리
|
||
* 메타 단위(「구분 따름」 · 「줄 따름」 · 「수(…)」 · 「원문 단위 없음」) = 단위 아님 → 안 그림 · 「10^-7」 = 10⁻⁷
|
||
* 기계 칸 연결(요소 `EQ:` 칸) 변수 = 변수 단위가 빈 칸이면 기계 표 칸 단위(`MACHINE_UNIT` — 기계 표 빌더 · 내 기계와 같은 글)
|
||
* 그리기만 — 자료 · 식 · 금액 불변 · 화면 없음(시험이 Node 로 돌림)
|
||
* ========================================================================== */
|
||
|
||
import type { DocVar, MoneyLine, Node } from "./common_util_formula_doc";
|
||
|
||
/** 기계 표 칸 단위(`build_기계_건설품셈.py` UNIT · `M02_MyMachine.py` UNITS 와 같은 글) */
|
||
export const MACHINE_UNIT: Record<string, string> = {
|
||
가격: "천원",
|
||
내용시간: "시간",
|
||
연간표준가동시간: "시간",
|
||
상각비계수: "10^-7/시간",
|
||
정비비계수: "10^-7/시간",
|
||
관리비계수: "10^-7/시간",
|
||
손료계수: "10^-7/시간",
|
||
주연료: "ℓ/hr",
|
||
전력: "kWh/hr",
|
||
잡재료율: "%",
|
||
잡품: "%",
|
||
조종원: "인/일",
|
||
인력: "인/일",
|
||
노무비: "원/시간",
|
||
재료비: "원/시간",
|
||
경비: "원/시간",
|
||
};
|
||
|
||
/** 금액 · 소계 · 합계 단위 */
|
||
export const AMOUNT_UNIT = "원";
|
||
|
||
/** 자료 단위 글 → 화면 단위(메타 = 빈 글) */
|
||
export function unitText(u: unknown): string {
|
||
const s = String(u ?? "").trim();
|
||
if (!s || /따름|원문 단위 없음/.test(s) || /^수(\(| 또는|$)/.test(s)) return "";
|
||
return s.replace(/^%\(.*\)$/, "%").replace(/10\^-7/g, "10⁻⁷");
|
||
}
|
||
|
||
/** 기계 칸 이름의 화면 단위 */
|
||
export const machineUnit = (col: string): string => unitText(MACHINE_UNIT[col]);
|
||
|
||
/** 변수 화면 단위 — 변수 단위 › 기계 칸 연결이면 기계 표 칸 단위 */
|
||
export function varUnit(v: DocVar | undefined): string {
|
||
const own = unitText(v?.단위);
|
||
if (own) return own;
|
||
const k = v?.연결;
|
||
return k?.갈래 === "요소" && /^EQ:/.test(String(k.키 ?? "")) && k.칸 ? machineUnit(k.칸) : "";
|
||
}
|
||
|
||
const HIDE = new Set(["반올림", "올림", "버림"]);
|
||
/** 한 덩이(기호 · 수 · 칸 — 감싸개 안 한 덩이 포함) */
|
||
export function isAtom(n: Node | null | undefined): boolean {
|
||
if (!n) return false;
|
||
if (n[0] === "call" && HIDE.has(n[1]) && n[2].length >= 1 && n[2].length <= 2)
|
||
return isAtom(n[2][0]);
|
||
return n[0] === "var" || n[0] === "num" || n[0] === "field" || n[0] === "str";
|
||
}
|
||
|
||
export interface MoneyUnits {
|
||
/** 단가 뒤(원/시간 · 원/인 …) — 단가가 한 덩이이고 수량이 있을 때만 */
|
||
price: string;
|
||
/** 수량 식 뒤 */
|
||
qty: string;
|
||
/** 수량 식을 괄호로 감쌈(식이고 단위가 있을 때) */
|
||
wrap: boolean;
|
||
}
|
||
|
||
/** 금액 줄 단위 자리(㉢) — `priceVar` = 단가 기호 변수 · `sub` = 묶음 · 단가산출 줄이 부르는 문서 */
|
||
export function moneyUnits(
|
||
line: MoneyLine,
|
||
price: Node | null,
|
||
qty: Node | null,
|
||
priceVar?: DocVar,
|
||
sub?: { 결과단위?: string } | null,
|
||
): MoneyUnits {
|
||
const has = line.수량 !== undefined && line.수량 !== null && line.수량 !== "";
|
||
const q = has ? unitText(line.단위) : "";
|
||
const wrap = !!q && !!qty && !isAtom(qty);
|
||
const own = [sub?.결과단위, priceVar?.단위].map(unitText).find((u) => u.startsWith("원"));
|
||
const p = has && isAtom(price) ? (own ?? (q ? `${AMOUNT_UNIT}/${q}` : "")) : "";
|
||
return { price: p, qty: q, wrap };
|
||
}
|