/* ============================================================================= * M02_CF_Model.ts * 단가산출 다이어그램 Model — 입력 · 함수 · 출력 상자를 선으로 이음 · 함수 상자 = 시트 하나(출력 하나) * DOM 없음 · 모양은 `docs/raw/M01_쉬운단가/원가다이어그램_정함.md` 「상자 · 선 약속」 그대로 * ========================================================================== */ import type { Sheet } from "../../A00_Common/spreadsheet/spreadsheet_types"; export type CfKind = "input" | "function" | "output"; export type CfGroup = "인력" | "재료" | "유가전력" | "기계" | "소요량" | "계수" | "환율" | "요율"; export type CfCost = "노무비" | "재료비" | "경비" | "값"; /** 입력 상자가 고른 요소 — ref = 마스터 키 또는 사용자 요소 id */ export interface CfElementRef { ref: string; name: string; spec: string; unit: string; } /** 변수(입력 정의) — 그룹 밖 정보(면적 · 길이 …) · 함수 상자의 받는 값 */ export interface CfVariable { name: string; type: "number" | "choice" | "text"; unit: string; choices?: (string | number)[]; range?: [number, number]; example: number | string | null; /** 함수 상자 안 변수의 칸(「B2」) — 입력 상자 변수는 없음 */ cell?: string; } export interface CfInput { mode: "group" | "variable"; group?: CfGroup; elements: CfElementRef[]; /** 소요량 · 계수 = 표(row 가 있으면 그 한 줄) */ table?: { key: string; row?: number }; variables: CfVariable[]; } export interface CfFunc { /** 우리 스프레드시트 시트 하나 */ sheet: Sheet; /** 받는 알약 → 칸 */ inputs: { port: string; cell: string }[]; variables: CfVariable[]; /** 내보내는 알약 하나 */ output: { cell: string; name: string; unit: string }; } export interface CfOutput { cost: CfCost; unit: string; } export interface CfBox { id: string; kind: CfKind; name: string; color: string; /** 오른쪽 위 단위 — 기본 「-」 */ unit: string; x: number; y: number; input?: CfInput; func?: CfFunc; output?: CfOutput; } /** 알약 한쪽 끝 */ export interface CfPort { box: string; name: string; } export interface CfLink { id: string; from: CfPort; to: CfPort; } /** 사용자 요소 — 그룹에 없는 새 요소(마스터에 안 씀 · `_data` 에 저장) */ export interface CfUserElement { id: string; group: CfGroup; name: string; spec: string; unit: string; value: number | null; } export interface CfLogic { key: string | null; name: string; resultUnit: string; boxes: CfBox[]; links: CfLink[]; userElements: CfUserElement[]; } /** 알약 하나의 모습 */ export interface CfPill { name: string; unit: string; } const notReady = (): never => { throw new Error("준비 중"); }; export function newLogic(_name?: string, _resultUnit?: string): CfLogic { return notReady(); } /** 상자 더하기 — 종류별 기본 색 · 단위 「-」 · 함수는 빈 시트 하나 · 출력은 노무비 */ export function addBox( _lg: CfLogic, _kind: CfKind, _x: number, _y: number, ): { lg: CfLogic; box: CfBox } { return notReady(); } /** 상자 지우기 — 이어진 선도 지움 */ export function removeBox(_lg: CfLogic, _id: string): CfLogic { return notReady(); } export function moveBox(_lg: CfLogic, _id: string, _x: number, _y: number): CfLogic { return notReady(); } export function setColor(_lg: CfLogic, _id: string, _color: string): CfLogic { return notReady(); } export function setUnit(_lg: CfLogic, _id: string, _unit: string): CfLogic { return notReady(); } /** 내보내는 알약 — 입력 = 요소 · 표 · 변수마다 · 함수 = 출력 하나 · 출력 = 없음 */ export function portsOut(_box: CfBox): CfPill[] { return notReady(); } /** 받는 알약 — 함수 = 입력 알약 · 출력 = 하나 · 입력 = 없음 */ export function portsIn(_box: CfBox): CfPill[] { return notReady(); } /** 선 잇기 — 규칙에 어긋나면 막고 까닭(쉬운 말) */ export function link( _lg: CfLogic, _from: CfPort, _to: CfPort, ): { lg: CfLogic; why: string | null } { return notReady(); } export function unlink(_lg: CfLogic, _id: string): CfLogic { return notReady(); }