From ddaff8a6b8c98aab11ffcdfc51528b0d5b8975a9 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 1 Oct 2026 12:59:19 +0900 Subject: [PATCH] =?UTF-8?q?feat(m01-sl):=20=EC=8B=9C=ED=8A=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20Model=20=C2=B7=20Eval=20=ED=83=80=EC=9E=85=20=C2=B7?= =?UTF-8?q?=20=ED=95=A8=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 SheetLogic · SlNode · SlPill · SlEdge · SlOutside · SlKind · SlEnd · SlUserTable · SlValue · SlOutsideValue · SlEvalResult newLogic · addNode · removeNode · connect · disconnect · setPill · removePill · outsideCells · applyOutside · evalLogic · checkLogic (속은 준비 중) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk --- M01_MasterData/SheetLogic/M01_SL_Eval.ts | 49 ++++++++ M01_MasterData/SheetLogic/M01_SL_Model.ts | 133 ++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 M01_MasterData/SheetLogic/M01_SL_Eval.ts create mode 100644 M01_MasterData/SheetLogic/M01_SL_Model.ts diff --git a/M01_MasterData/SheetLogic/M01_SL_Eval.ts b/M01_MasterData/SheetLogic/M01_SL_Eval.ts new file mode 100644 index 000000000..00dec78e7 --- /dev/null +++ b/M01_MasterData/SheetLogic/M01_SL_Eval.ts @@ -0,0 +1,49 @@ +/* ============================================================================= + * M01_SL_Eval.ts + * 시트 로직 화면 계산 — 바깥 값 넣기 → 우리 스프레드시트 엔진(브라우저) → 출력 알약 · 결과 읽기 · 검사 + * 저장 때는 서버가 같은 엔진을 Node 로(정함 5) · DOM 없음 + * ========================================================================== */ + +import type { SheetLogic, SlOutside } from "./M01_SL_Model"; + +/** 알약 값 — 수 · 글 · 참거짓 · 빈 칸 */ +export type SlValue = number | string | boolean | null; + +/** 바깥 값 하나 — 표는 칸 덩어리(cell 이 왼위) */ +export interface SlOutsideValue { + node: string; + cell: string; + value: SlValue | SlValue[][]; +} + +export interface SlEvalResult { + /** 상자 id → 출력 알약 이름 → 값 */ + pills: Record>; + result: { 노무비: number | null; 재료비: number | null; 경비: number | null; 계: number | null }; + /** 쉬운 말 */ + errors: string[]; +} + +const notReady = (): never => { + throw new Error("준비 중"); +}; + +/** 바깥 값 칸 목록 — 화면 · 서버가 이 칸에 값을 넣음 */ +export function outsideCells(_sl: SheetLogic): SlOutside[] { + return notReady(); +} + +/** 바깥 값 넣기 — 새 시트 로직(받은 것은 안 바꿈) */ +export function applyOutside(_sl: SheetLogic, _values: SlOutsideValue[]): SheetLogic { + return notReady(); +} + +/** 화면 계산 */ +export function evalLogic(_sl: SheetLogic): SlEvalResult { + return notReady(); +} + +/** 검사 — 빈 입력 알약 · 순환 · 오류 칸(쉬운 말 목록) */ +export function checkLogic(_sl: SheetLogic): string[] { + return notReady(); +} diff --git a/M01_MasterData/SheetLogic/M01_SL_Model.ts b/M01_MasterData/SheetLogic/M01_SL_Model.ts new file mode 100644 index 000000000..dc6d86f02 --- /dev/null +++ b/M01_MasterData/SheetLogic/M01_SL_Model.ts @@ -0,0 +1,133 @@ +/* ============================================================================= + * M01_SL_Model.ts + * 시트 로직 Model — 로직 한 벌 = 통합문서 하나 · 상자 하나 = 시트 하나 · 알약 = 이름 붙은 칸 + * 선 = 받는 입력 알약 칸에 「'시트 이름'!칸」 참조 수식 · DOM 없음 + * 모양은 `docs/raw/M01_쉬운단가/시트로직_정함.md` 정함 1~5 그대로 + * ========================================================================== */ + +import type { Workbook } from "../../A00_Common/spreadsheet/spreadsheet_types"; + +/** 상자 종류 — 입력값 · 고정값 · 표 · 계산 · 항목 · 다른 로직 · 결과 */ +export type SlKind = "input" | "const" | "table" | "calc" | "item" | "logic" | "result"; + +/** 알약 = 이름 붙은 칸 */ +export interface SlPill { + name: string; + /** 「B3」 */ + cell: string; + unit?: string; + /** 바깥 값 칸 — 열 때 · 저장 때 마스터에서 넣음 */ + outside?: boolean; +} + +/** 상자 = 시트 하나 */ +export interface SlNode { + id: string; + kind: SlKind; + name: string; + sheetId: string; + pillsIn: SlPill[]; + pillsOut: SlPill[]; + /** 표 키 · 요소 · 기존 로직 키 · 내 표 id */ + ref?: string; + /** 띠 단계 — 0 입력값 · 1 표 · 2 계산 · 3 항목 · 4 결과 */ + stage: number; +} + +/** 선 — 출력 알약 → 입력 알약 */ +export interface SlEdge { + id: string; + from: { node: string; pill: string }; + to: { node: string; pill: string }; +} + +/** 바깥 값 칸 */ +export interface SlOutside { + node: string; + cell: string; + kind: "table" | "price" | "logic"; + ref: string; +} + +/** 내 표 — 품셈에 없는 표(사용자가 만듦) */ +export interface SlUserTable { + id: string; + name: string; + cols: string[]; + rows: (number | string | null)[][]; +} + +export interface SheetLogic { + key: string | null; + name: string; + resultUnit: string; + workbook: Workbook; + nodes: SlNode[]; + edges: SlEdge[]; + userTables?: SlUserTable[]; +} + +/** 알약 한쪽 끝 */ +export interface SlEnd { + node: string; + pill: string; +} + +const notReady = (): never => { + throw new Error("준비 중"); +}; + +/** 빈 시트 로직 */ +export function newLogic(_name?: string, _resultUnit?: string): SheetLogic { + return notReady(); +} + +/** 상자 더하기 — 그 종류 틀(칸 A 이름 · B 값 · C 설명)로 시트를 만듦 */ +export function addNode( + _sl: SheetLogic, + _kind: SlKind, + _name: string, +): { sl: SheetLogic; node: SlNode } { + return notReady(); +} + +/** 상자 지우기 — 시트 · 이어진 선 · 받던 참조 수식을 함께 지움 */ +export function removeNode(_sl: SheetLogic, _node: string): SheetLogic { + return notReady(); +} + +/** 선 잇기 — 받는 알약 칸에 참조 수식 · 순환 · 없는 알약이면 막고 까닭(쉬운 말) */ +export function connect( + _sl: SheetLogic, + _from: SlEnd, + _to: SlEnd, +): { sl: SheetLogic; why: string | null } { + return notReady(); +} + +/** 선 끊기 — 그 참조를 받는 칸 수식에서 뺌 */ +export function disconnect(_sl: SheetLogic, _edge: string): SheetLogic { + return notReady(); +} + +/** 알약 정하기 — 같은 칸이나 같은 이름이 있으면 바꿈 */ +export function setPill( + _sl: SheetLogic, + _node: string, + _cell: string, + _dir: "in" | "out", + _name: string, + _extra?: Pick, +): SheetLogic { + return notReady(); +} + +/** 알약 빼기 — 이어진 선도 끊음 */ +export function removePill( + _sl: SheetLogic, + _node: string, + _dir: "in" | "out", + _name: string, +): SheetLogic { + return notReady(); +}