From 14b222dcb531c45acdfc9cc4502e5fee1de53d5e Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 1 Oct 2026 19:38:49 +0900 Subject: [PATCH 1/2] auto: 2026-10-01 19:38 (ESD_LAPTOP) --- docs/raw/M01_쉬운단가/흐름도_정함.md | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/raw/M01_쉬운단가/흐름도_정함.md diff --git a/docs/raw/M01_쉬운단가/흐름도_정함.md b/docs/raw/M01_쉬운단가/흐름도_정함.md new file mode 100644 index 000000000..25134226b --- /dev/null +++ b/docs/raw/M01_쉬운단가/흐름도_정함.md @@ -0,0 +1,38 @@ +# 단가산출 흐름도 시험판 — 정함 (PLAN 35-9 · 브레인 · 10-01 17시 무렵) + +사용자 지시(그대로): 「전체에 대해 너가 제어해서 시험판을 하나 만들어봐. 이때 이전에 검토하였던 단가산출 다이어그램(시험)을 제외한 다른 시험판 들은 삭제해줘. 이번에 만드는 시험판도 신규 폴더에 넣어서 작업해줘. 필요없으면 바로 삭제할수 있게. … 너가 끝까지 구현하고 검증까지 진행해봐. 다시말하지만 자유도 높고 내가 이해하기 쉬운 화면을 만드는게 중요해.」 · 「데이터의 흐름과 값의 연결에 집중해야해. 이것만 잘 연결되면 단가산출 로직들을 만드는건 쉽게 해결될거야.」 +계획 = PLAN.md 35-8(a~o) 전체 · 근거 = 같은 폴더 `원가다이어그램_정함.md`(1판 약속 — 그대로 이어받음). + +## 목적 + +값 하나가 **어디서 생겨(출처) · 어떤 길과 규칙을 지나(선 · 선 규칙 · 함수) · 어디로 가는지(도착)** 를 사용자가 자유롭게 만들고 · 한눈에 따라가고 · 고칠 수 있게. 원가 숫자가 아니라 이 흐름이 검증 기준. + +## 정함 + +1. 폴더 `M02_MasterTemplete/DataFlow/` · 파일 머리 `M02_DF_` · 서버 길 `/api/m02/df/*` · 키 `DF-0001` · 저장 · 임시 = `_data/`(git 밖) · 견본 = `_sample/` · 단위 · 금액 표준 처음 값 = `_standard/` · 폴더째 지우면 끝. 1판(CostFlow)을 옮겨 시작하되 import 로 기대지 않음(CostFlow 는 그대로 남음). +2. 들어가는 곳 = 단가산출 막대 「시험판 ▾」 목록의 「단가산출 흐름도(시험)」 · 전체 화면 페이지. +3. 옛 시험판 셋(EasyCalc · LogicBuilder · SheetLogic) 폴더 · 그 시험 파일 · 막대 목록 항목 · 서버 등록 줄을 지움(사용자 지시) · `로직_자체.json` 의 사용자 로직(GX)은 마스터 자료라 그대로. +4. **흐름 넷** — ① 출처: 입력 상자(그룹 요소 · 표 · 변수 · **재료 자리** · **다른 로직**) ② 길: 선(알약 → 받는 자리) + **선 규칙** 하나(표에서 찾기 · 조건 통과 · 바꾸기 · 끝수) ③ 처리: 함수 상자(엑셀 · 출력 하나) ④ 도착: 출력 상자(비용 종류 · 값) · 다른 로직의 입력 · 「설계 때 정할 것」. +5. **재료 요소 방식 셋**(재료만) — 고정(품목 하나) · 선택 자리(범위 = 구분 · 상세구분 · 찾는 말 · 기본 품목 · 검증 칸 · 프로젝트에서 고름) · 조건 찾기(범위 + 「규격 / 이름에 [알약] 포함 / 같음」 · 맞음 0 · 여럿 알림) · 알약 이름 = 자리 이름. 다른 그룹은 상자를 늘림. +6. **다른 로직 입력** — 저장한 흐름도 로직(또는 견본)을 입력 상자로 불러 그 출력(비용 · 값)을 내보내는 알약으로 · 그 로직의 「설계 때 정할 것」(변수 · 재료 자리)은 이 상자의 받는 알약으로(이어 주지 않으면 그 로직의 예시값). +7. **선 규칙**(선 하나에 하나 · 없으면 그대로) — 표에서 찾기(조건 칸마다 맞출 알약 · 꺼낼 칸) · 조건 통과(알약 · 같음 · 다름 · 이상 · 이하 · 초과 · 미만 · 값 — 아니면 넘기지 않음) · 바꾸기(× · ÷ · +% · −% · 단위 바꾸기 계수) · 끝수(자리 · 반올림 / 올림 / 버림). 규칙은 받는 칸의 엑셀 수식으로 바뀌어 엔진 한 벌 · 선 위 규칙 글 늘 보임 · 한 알약에서 나간 조건 선의 겹침 · 어느 것도 안 맞음을 알림. +8. **흐름 따라가기** — 알약 · 선을 고르면 그 값이 온 길(출처 사슬)과 가는 길을 다이어그램에서 칠하고 상세 내용에 줄로 · 끊긴 곳(빈 받는 자리 · 통과 안 된 조건 · 표에 없는 조건 · 맞는 재료 없음)을 상자 · 선 위에 표시. +9. **상세 내용**(옛 「고른 상자」) — 상자 · 알약 · 선 무엇을 골라도 바뀜 · 머리 왼쪽 「상세 내용」 · 오른쪽 고른 상자 제목 · 알약이면 그 옆에 알약 이름 · 칸 차례 = 머리 · 설정 · 본문 · 경고. +10. **단위는 고르기** — 치면 걸러진 목록 · 고르기는 사용자 · 손글 안 받음 · 목록 = 단위 표준 + 마스터 결과단위 + 원 · 「-」 = 없음. +11. **단위 표준 · 금액 단위 표준** — 산림품셈 1-2-2(원문 `resources/knowledge/original/원가계산/산림_표준품셈/본문/제01장_적용기준/1-02_설계_및_수량.md`) 「설계서의 단위 및 소수의 표준」(종목 · 규격 단위 · 소수자리 · 단위수량 단위 · 소수자리 · 비고 · 주 ①~③ · 소수자리 「-」 = 0 · 단위 「-」 = 없음) + 「금액의 단위표준」(총액 1,000원 · 소계 · 금액란 · 일위대가표 계금 1원 · 일위대가표 금액란 0.1원 · 미만 버림) · 시험판 안에서 표로 보고 고침(사용자가 원문 흠을 고침 · 저장 `_data`). +12. **끝수** — 함수 출력 · 출력 상자 · 선 규칙에 소수자리 · 방법 · 단위를 고르면 단위 표준에서 자리 제안(주 ① 반올림 · ② 항목 값 우선) · 출력(비용) 기본 = 일위대가표 금액란 0.1원 미만 버림 · 원가 합계 기본 = 계금 1원 미만 버림. +13. **화면** — 자유 배치 다이어그램(위 · 크게) · 판 옮기기 = 가운데 단추 끌기 · 고르기 = 왼쪽 누름 · 왼쪽 끌기로 글자 선택 안 됨 · 상자 옮기기 = 상자 머리 왼쪽 끌기 · 아래 상세 내용 · 오른쪽 아래 검증 칸(예시값 + 재료 자리 + 다른 로직의 설계 때 정할 것) · 단추 · 칸은 공용 작은 크기(createButton size "sm" · 덮어쓰기 금지) · 쉬운 말 · 밝음 · 어두움. +14. 보고 · 검증 기준 = 흐름(값이 어디서 와서 · 어떤 규칙을 지나 · 어디로 가는지가 화면에서 따라가지는지 · 끊긴 곳이 보이는지 · 몇 걸음에 만드나). 원가 숫자는 내부 확인만. + +## 파일 · 창 + +| 창 | 맡음 | +| --- | --- | +| sub7 | 0걸음: CostFlow → DataFlow 옮기기(이름 · 길 · 키 · 폴더 · 시험 사본) · 그다음 Model · Eval 넓히기(정함 5 · 6 · 7 · 8 · 12 · 설계 때 정할 것 목록) — 타입 먼저 | +| sub4 | 서버(정함 5 · 6 · 11 · 12) — 재료 자리 · 조건 찾기 단가 · 자재 찾기(쪽 · 띄어쓰기 AND · 규격) · 다른 로직 값 · 설계 때 정할 것 · 표준 표 읽기 · 쓰기 · 저장 다시 셈의 끝수 | +| sub8 | 다이어그램(정함 7 · 8 · 13) — 선 위 규칙 글 · 선 고르기 · 흐름 길 칠하기 · 끊긴 곳 표시 · 마우스 | +| sub2 | 상세 내용 판(정함 7 · 9 · 10 · 12 · 13) — 선 규칙 판 · 알약 판 · 함수 판 손질(작은 단추) · 단위 고르기 공용 파일 `M02_DF_UnitPick.ts` · 끝수 고르기 | +| sub3 | 입력 판(정함 5 · 6 · 10) — 재료 방식 셋 · 범위 · 조건 · 기본 품목 · 자재 찾기 고침 · 다른 로직 입력 | +| sub5 | 출력 판 · 검증 칸(정함 5 · 6 · 11 · 12) — 재료 자리 고르기 · 다른 로직 설계 값 · 출력 끝수 · 금액 표준 기본 · 끊긴 곳 목록 | +| sub6 | 표준 표 · 견본(정함 11 · 견본) — `_standard/단위표준.json` · `금액단위표준.json` · 시험판 안 표 보기 · 고치기 판 · 견본 넷(메쌓기 · 지반 가르기 · 흄관 조건 찾기 · 다른 로직 잇기) | +| sub1 | 옛 시험판 지우기(정함 3) · 막대 목록 · 들어가는 페이지 · 상세 내용 머리 · 잇기 · 끝 검증(흐름 기준) | From 6008a1e7aeb4cae60385cffcd6dcb97cf359c3be Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 1 Oct 2026 19:39:48 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat(m02-df):=20=ED=9D=90=EB=A6=84=EB=8F=84?= =?UTF-8?q?=20Model=20=EB=84=93=ED=9E=8C=20=ED=83=80=EC=9E=85=20=C2=B7=20?= =?UTF-8?q?=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 - 재료 요소 mode(fixed · choice · rule) · scope · rule{field · op · from} · default · slot - 입력 갈래 logic + CfLogicRef{key · name · outputs · designs} - 선 규칙 CfLink.rule — lookup · gate · scale · round · CfRound(func.output.round · output.round) - 흐름 CfStep · CfDesign · traceBack · traceForward · designInputs · Eval CfBreak · breaks - M02_DF_Rule.ts — ruleLabel · applyRule · applyRound (속은 준비 중) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk --- M02_MasterTemplete/DataFlow/M02_DF_Eval.ts | 22 ++++ M02_MasterTemplete/DataFlow/M02_DF_Model.ts | 106 +++++++++++++++++++- M02_MasterTemplete/DataFlow/M02_DF_Rule.ts | 33 ++++++ 3 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 M02_MasterTemplete/DataFlow/M02_DF_Rule.ts diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Eval.ts b/M02_MasterTemplete/DataFlow/M02_DF_Eval.ts index b955c2d61..f471e0145 100644 --- a/M02_MasterTemplete/DataFlow/M02_DF_Eval.ts +++ b/M02_MasterTemplete/DataFlow/M02_DF_Eval.ts @@ -208,3 +208,25 @@ export function checkLogic(lg: CfLogic, values: CfValues = {}): string[] { out.push(tl("NoValue", { box: b.name, pill })); return [...out, ...ev.errors]; } + +/** 끊긴 곳 하나 — 상자 · 알약 · 선 위에 표시할 것 */ +export interface CfBreak { + kind: + | "빈 받는 자리" + | "통과 안 됨" + | "표에 없는 조건" + | "맞는 재료 없음" + | "조건 겹침" + | "조건 안 맞음" + | "오류"; + box: string; + port?: string; + link?: string; + /** 쉬운 말 */ + text: string; +} + +/** 끊긴 곳 목록(넓힘 · 준비 중) */ +export function breaks(_lg: CfLogic, _values: CfValues = {}): CfBreak[] { + throw new Error("준비 중"); +} diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Model.ts b/M02_MasterTemplete/DataFlow/M02_DF_Model.ts index 3613bf589..6191c361d 100644 --- a/M02_MasterTemplete/DataFlow/M02_DF_Model.ts +++ b/M02_MasterTemplete/DataFlow/M02_DF_Model.ts @@ -1,7 +1,8 @@ /* ============================================================================= * M02_DF_Model.ts - * 단가산출 다이어그램 Model — 입력 · 함수 · 출력 상자를 선으로 이음 · 함수 상자 = 시트 하나(출력 하나) - * DOM 없음 · 모양은 `docs/raw/M01_쉬운단가/원가다이어그램_정함.md` 「상자 · 선 약속」 그대로 + * 단가산출 흐름도 Model — 입력 · 함수 · 출력 상자를 선으로 이음 · 함수 상자 = 시트 하나(출력 하나) + * 선 규칙(표에서 찾기 · 조건 통과 · 바꾸기 · 끝수) · 재료 방식 셋 · 다른 로직 입력 · 흐름 따라가기 · 설계 때 정할 것 + * DOM 없음 · 모양은 `docs/raw/M01_쉬운단가/흐름도_정함.md` 4~8 · 12 · 1판 약속 `원가다이어그램_정함.md` * ========================================================================== */ import { currentLanguageIndex } from "@ui/ui_template_locale"; @@ -11,12 +12,36 @@ export type CfKind = "input" | "function" | "output"; export type CfGroup = "인력" | "재료" | "유가전력" | "기계" | "소요량" | "계수" | "환율" | "요율"; export type CfCost = "노무비" | "재료비" | "경비" | "값"; -/** 입력 상자가 고른 요소 — ref = 마스터 키 또는 사용자 요소 id */ +/** 재료 요소 방식 — 고정(품목 하나) · 선택 자리(프로젝트에서 고름) · 조건 찾기(규격 / 이름에 알약 값) */ +export type CfMaterialMode = "fixed" | "choice" | "rule"; + +/** 재료 찾을 범위 */ +export interface CfScope { + 구분?: string; + 상세구분?: string; + 찾는말?: string; +} + +/** 재료 조건 찾기 — 품목의 규격 / 이름에 [알약 값] 이 포함 · 같음 */ +export interface CfMaterialRule { + field: "규격" | "이름"; + op: "포함" | "같음"; + from: CfPort; +} + +/** 입력 상자가 고른 요소 — ref = 마스터 키 또는 사용자 요소 id + * 재료면 mode · scope · rule · default · slot(알약 이름 = 자리 이름 · 없으면 name) */ export interface CfElementRef { ref: string; name: string; spec: string; unit: string; + mode?: CfMaterialMode; + scope?: CfScope; + rule?: CfMaterialRule; + /** 기본 품목 키(선택 자리 · 조건 찾기) */ + default?: string; + slot?: string; } /** 변수(입력 정의) — 그룹 밖 정보(면적 · 길이 …) · 함수 상자의 받는 값 */ @@ -31,13 +56,31 @@ export interface CfVariable { cell?: string; } +/** 다른 로직 입력 — 저장 로직(DF-…) · 견본 id · outputs · designs 는 고를 때 그 로직에서 읽어 둔 것 */ +export interface CfLogicRef { + key: string; + name?: string; + /** 내보내는 알약 = 그 로직 출력 상자 이름(비용 · 값) */ + outputs: CfPill[]; + /** 받는 알약 = 그 로직의 「설계 때 정할 것」(변수 · 재료 자리) */ + designs: CfPill[]; +} + export interface CfInput { - mode: "group" | "variable"; + mode: "group" | "variable" | "logic"; group?: CfGroup; elements: CfElementRef[]; /** 소요량 · 계수 = 표(row 가 있으면 그 한 줄) */ table?: { key: string; row?: number }; variables: CfVariable[]; + /** mode "logic" */ + logic?: CfLogicRef; +} + +/** 끝수 — 소수 자리 · 방법 */ +export interface CfRound { + places: number; + method: "반올림" | "올림" | "버림"; } export interface CfFunc { @@ -47,12 +90,13 @@ export interface CfFunc { inputs: { port: string; cell: string }[]; variables: CfVariable[]; /** 내보내는 알약 하나 */ - output: { cell: string; name: string; unit: string }; + output: { cell: string; name: string; unit: string; round?: CfRound }; } export interface CfOutput { cost: CfCost; unit: string; + round?: CfRound; } export interface CfBox { @@ -75,10 +119,41 @@ export interface CfPort { name: string; } +export type CfGateOp = "=" | "≠" | "≥" | "≤" | ">" | "<"; + +/** 선 규칙(선 하나에 하나 · 없으면 그대로) — 받는 칸의 엑셀 수식으로 바뀌어 엔진 한 벌로 셈 + * lookup = 보낸 표에서 조건 칸마다 맞출 알약 · 꺼낼 칸(범위 칸은 「이름·아래」 「이름·위」) + * gate = 알약 값이 조건을 통과할 때만 보냄 · scale = × ÷ +% -% · round = 끝수 */ +export type CfRule = + | { kind: "lookup"; conds: { col: string; from: CfPort }[]; col: string } + | { kind: "gate"; from: CfPort; op: CfGateOp; value: number | string } + | { kind: "scale"; op: "×" | "÷" | "+%" | "-%"; value: number } + | ({ kind: "round" } & CfRound); + export interface CfLink { id: string; from: CfPort; to: CfPort; + rule?: CfRule; +} + +/** 흐름 한 걸음 — 그 알약 · 그 알약으로 들어온(나간) 선의 규칙 */ +export interface CfStep { + box: string; + port: string; + dir: "in" | "out"; + link?: string; + rule?: CfRule; +} + +/** 설계 때 정할 것 — 변수 · 재료 자리 · 다른 로직의 받는 알약(선이 없을 때) */ +export interface CfDesign { + box: string; + port: string; + kind: "변수" | "재료 자리" | "다른 로직"; + unit: string; + variable?: CfVariable; + element?: CfElementRef; } /** 사용자 요소 — 그룹에 없는 새 요소(마스터에 안 씀 · `_data` 에 저장) */ @@ -327,3 +402,24 @@ export function unlink(lg: CfLogic, id: string): CfLogic { const inputs = box.func.inputs.filter((i) => i !== port); return updateBox(next, box.id, { func: { ...box.func, inputs } }); } + +/* ── 흐름(넓힘 · 준비 중) ───────────────────────────────────────────────── */ + +const notReady = (): never => { + throw new Error("준비 중"); +}; + +/** 그 알약 값이 온 길 — 출처 사슬(가까운 것부터) */ +export function traceBack(_lg: CfLogic, _port: CfPort): CfStep[] { + return notReady(); +} + +/** 그 알약 값이 가는 길 */ +export function traceForward(_lg: CfLogic, _port: CfPort): CfStep[] { + return notReady(); +} + +/** 설계 때 정할 것 — 변수 · 재료 자리(선택) · 다른 로직의 받는 알약(선이 없을 때) */ +export function designInputs(_lg: CfLogic): CfDesign[] { + return notReady(); +} diff --git a/M02_MasterTemplete/DataFlow/M02_DF_Rule.ts b/M02_MasterTemplete/DataFlow/M02_DF_Rule.ts new file mode 100644 index 000000000..e8f410de8 --- /dev/null +++ b/M02_MasterTemplete/DataFlow/M02_DF_Rule.ts @@ -0,0 +1,33 @@ +/* ============================================================================= + * M02_DF_Rule.ts + * 선 규칙 · 끝수 → 엑셀 수식 — 우리 스프레드시트 엔진 한 벌로 셈 · 선 위 규칙 글(쉬운 말) · DOM 없음 + * ========================================================================== */ + +import type { CfRound, CfRule } from "./M02_DF_Model"; + +/** 규칙을 지난 값 — 통과 안 됨 · 표에 없는 조건 · 둘 이상 맞음은 value null + why */ +export interface CfRuleResult { + value: number | string | boolean | null; + why: "통과 안 됨" | "표에 없는 조건" | "표에 여럿 맞음" | "오류" | null; + /** 받는 칸에 들어갈 엑셀 수식(보이기 · 시험) */ + formula: string; +} + +/** 선 위에 늘 보일 규칙 글 */ +export function ruleLabel(_rule: CfRule): string { + throw new Error("준비 중"); +} + +/** 규칙 적용 — value = 보낸 알약 값(표면 머리 줄 포함 칸 덩어리) · conds = 조건 알약 값(lookup · gate) */ +export function applyRule( + _rule: CfRule, + _value: unknown, + _conds: Record = {}, +): CfRuleResult { + throw new Error("준비 중"); +} + +/** 끝수 적용 — 엔진 ROUND · ROUNDUP · ROUNDDOWN */ +export function applyRound(_round: CfRound, _value: number): number { + throw new Error("준비 중"); +}