From 2e66b0a6ce68f04ed594d4747f4b2bf589b40b03 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 1 Oct 2026 15:59:53 +0900 Subject: [PATCH] =?UTF-8?q?feat(m02-cf):=20=EB=8B=A8=EA=B0=80=EC=82=B0?= =?UTF-8?q?=EC=B6=9C=20=EB=8B=A4=EC=9D=B4=EC=96=B4=EA=B7=B8=EB=9E=A8=20Mod?= =?UTF-8?q?el=20=C2=B7=20Eval=20=ED=83=80=EC=9E=85=20=C2=B7=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=A8=B8=EB=A6=AC=20=EC=98=AC=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk --- M02_MasterTemplete/CostFlow/M02_CF_Eval.ts | 44 ++++++ M02_MasterTemplete/CostFlow/M02_CF_Model.ts | 164 ++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 M02_MasterTemplete/CostFlow/M02_CF_Eval.ts create mode 100644 M02_MasterTemplete/CostFlow/M02_CF_Model.ts diff --git a/M02_MasterTemplete/CostFlow/M02_CF_Eval.ts b/M02_MasterTemplete/CostFlow/M02_CF_Eval.ts new file mode 100644 index 000000000..1cd3f877b --- /dev/null +++ b/M02_MasterTemplete/CostFlow/M02_CF_Eval.ts @@ -0,0 +1,44 @@ +/* ============================================================================= + * M02_CF_Eval.ts + * 단가산출 다이어그램 계산 · 검사 — 함수 상자는 차례대로 시트를 우리 스프레드시트 엔진으로 셈 + * (받는 칸에 앞 값을 넣음) · 출력 상자를 비용 종류별로 모아 원가 · DOM 없음 + * ========================================================================== */ + +import type { CfLogic } from "./M02_CF_Model"; + +/** 알약 값 — 수 · 글 · 참거짓 · 빈 값 · 표(머리 줄 포함 칸 덩어리) */ +export type CfValue = number | string | boolean | null | (number | string | null)[][]; + +/** 입력 값 묶음 — 상자 id → 알약 이름 → 값(입력 상자 요소 값 · 표 · 변수 값 · 함수 상자 변수 값) */ +export type CfValues = Record>; + +export interface CfEvalResult { + /** 상자 id → 내보내는 알약 이름 → 값 */ + ports: Record>; + /** 출력 상자 id → 값 */ + outputs: Record; + cost: { + 노무비: number; + 재료비: number; + 경비: number; + /** 비용 아닌 출력(값) — 출력 상자 이름 → 값 */ + 값들: Record; + 계: number; + }; + /** 쉬운 말 */ + errors: string[]; +} + +const notReady = (): never => { + throw new Error("준비 중"); +}; + +/** 화면 계산 */ +export function evalLogic(_lg: CfLogic, _values: CfValues = {}): CfEvalResult { + return notReady(); +} + +/** 검사 — 빈 받는 자리 · 출력 하나 아님 · 순환 · 오류(쉬운 말 목록) */ +export function checkLogic(_lg: CfLogic, _values: CfValues = {}): string[] { + return notReady(); +} diff --git a/M02_MasterTemplete/CostFlow/M02_CF_Model.ts b/M02_MasterTemplete/CostFlow/M02_CF_Model.ts new file mode 100644 index 000000000..bc61a1ae1 --- /dev/null +++ b/M02_MasterTemplete/CostFlow/M02_CF_Model.ts @@ -0,0 +1,164 @@ +/* ============================================================================= + * 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(); +}