Files
Aislo/M02_MasterTemplete/CostFlow/M02_CF_Model.ts
T
eomsangdonandClaude Opus 5.5 2e66b0a6ce feat(m02-cf): 단가산출 다이어그램 Model · Eval 타입 · 함수 머리 올림
CfLogic · CfBox · CfInput · CfVariable · CfFunc · CfOutput · CfPort · CfLink · CfElementRef · CfUserElement · CfPill · CfKind · CfGroup · CfCost · CfValue · CfValues · CfEvalResult
newLogic · addBox · removeBox · moveBox · setColor · setUnit · portsOut · portsIn · link · unlink · evalLogic · checkLogic (속은 준비 중)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk
2026-10-01 15:59:53 +09:00

165 lines
4.3 KiB
TypeScript

/* =============================================================================
* 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();
}