fix(M01): 시험 입력 한 벌 — 왼쪽 시험 계산 입력 ↔ 흐름 변수 예시값

- 로직을 열 때 왼쪽 시험 계산 입력(자동값 포함)을 이름이 같은 흐름 변수 예시값으로
- 왼쪽 입력을 바꾸면 흐름 예시값도 · 흐름 검증 칸 예시값을 바꾸면 왼쪽 입력도 바꾸고 다시 셈
- 예시값만 바뀐 것은 고친 것(drafts)으로 안 셈(sameShape)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
2026-10-02 01:38:24 +09:00
co-authored by Claude Opus 5.5
parent 2b3ba84fe5
commit f30bc9e82f
2 changed files with 88 additions and 4 deletions
@@ -150,6 +150,40 @@ export async function emptyFlow(name: string, unit: string): Promise<CfLogic> {
return (await import("../M02_MasterTemplete/DataFlow/M02_DF_Model")).newLogic(name, unit);
}
/* ── 시험 입력 한 벌 — 왼쪽 시험 계산 입력 ↔ 흐름 변수 예시값(이름이 같은 변수끼리) ── */
const varsOf = (lg: CfLogic) =>
lg.boxes.flatMap((b) => [...(b.input?.variables ?? []), ...(b.func?.variables ?? [])]);
/** 흐름 변수 예시값 — 이름 → 글(빈 값은 뺌) */
export function examplesOf(lg: CfLogic): Record<string, string> {
const out: Record<string, string> = {};
for (const v of varsOf(lg))
if (v.example !== null && v.example !== undefined && v.example !== "")
out[v.name] = String(v.example);
return out;
}
/** 예시값을 넣은 새 흐름 — 수처럼 생긴 글은 수로 · 빈 값은 그대로 둠 */
export function withExamples(lg: CfLogic, vals: Record<string, string>): CfLogic {
const next = JSON.parse(JSON.stringify(lg)) as CfLogic;
for (const v of varsOf(next)) {
const raw = (vals[v.name] ?? "").trim();
if (raw) v.example = /^-?\d+(\.\d+)?$/.test(raw) ? Number(raw) : raw;
}
return next;
}
/** 예시값만 다른가 — 그 밖이 같으면 고친 것으로 안 셈 */
export function sameShape(a: CfLogic, b: CfLogic): boolean {
const strip = (lg: CfLogic): string => {
const c = JSON.parse(JSON.stringify(lg)) as CfLogic;
for (const v of varsOf(c)) v.example = null;
return JSON.stringify(c);
};
return strip(a) === strip(b);
}
export interface LogicFlowOpts {
split: SplitHandle;
flow: CfLogic;
@@ -168,6 +202,8 @@ export interface LogicFlow {
set(lg: CfLogic): void;
/** 왼쪽만 다시(왼쪽 화면을 새로 그린 뒤) */
redrawLeft(): void;
/** 왼쪽 시험 계산 입력이 바뀜 — 같은 이름 변수의 예시값으로(고친 것 아님) */
setExamples(vals: Record<string, string>): void;
destroy(): void;
}
@@ -253,6 +289,14 @@ export async function mountLogicFlow(opts: LogicFlowOpts): Promise<LogicFlow> {
refresh();
},
redrawLeft: left,
setExamples: (vals) => {
const next = withExamples(lg, vals);
if (JSON.stringify(next) === JSON.stringify(lg)) return;
lg = next;
panel.set(next);
left();
refresh();
},
destroy: () => {
gone = true;
panel.destroy();