fix(M01): 흐름 로직의 시험 계산 입력 칸 = 흐름의 설계 때 정할 것(변수 · 고르기 · 범위 · 단위)

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 08:01:58 +09:00
co-authored by Claude Opus 5.5
parent 937661c573
commit 54fc4f1b1f
2 changed files with 29 additions and 4 deletions
+10 -4
View File
@@ -41,6 +41,7 @@ import { tl } from "./M01_MasterData_UI_LogicLab_Text";
import {
buildSplit,
emptyFlow,
designFields,
examplesOf,
fetchFlow,
fetchFlowFor,
@@ -86,6 +87,11 @@ interface Opened extends Draft {
/** 줄의 흐름(있으면 흐름도로 셈) */
const flowOf = (row: LogicRow | null): CfLogic | null => (row?.흐름 as CfLogic | undefined) ?? null;
const OWN_FILE = "로직_자체.json";
/** 시험 계산에 넘길 줄 — 흐름 로직은 입력 칸을 흐름의 「설계 때 정할 것」으로(옛 식 칸은 서버가 지움) */
const calcRow = (row: LogicRow | null): LogicRow | null => {
const f = flowOf(row);
return f && row ? { ...row, 입력: designFields(f) } : row;
};
const cacheKey = "m01_logic_drafts_lab";
const ownHost = (): HTMLElement => el("div", { className: "m01lab__own" });
@@ -169,7 +175,7 @@ export async function mountM01LogicLab(
else drafts[opened.id] = pick(opened, clone(opened.row));
persist();
if (!flowOf(opened.row)) scheduleFlow(opened); // 왼쪽 편집기로 고침 — 오른쪽 흐름도도 따라감
const inputs = JSON.stringify(opened.row.입력 ?? []);
const inputs = JSON.stringify(calcRow(opened.row)?.입력 ?? []);
if (inputs !== calcInputs) drawCalc();
if (isOwnLogic(opened.row)) {
// 자체 로직 — 고친 뒤 잠시 쉬면 다시 계산해 호표 소계와 텍스트 수식을 새로 그림
@@ -192,11 +198,11 @@ export async function mountM01LogicLab(
return;
}
const current = opened;
calcInputs = JSON.stringify(current.row?.입력 ?? []);
calcInputs = JSON.stringify(calcRow(current.row)?.입력 ?? []);
buildCalc(calc, {
savedKey: current.origKey,
file: current.file,
row: current.row as LogicRow,
row: calcRow(current.row) as LogicRow,
prices: current.prices,
dirty: () => current.id in drafts,
values: current.values,
@@ -309,7 +315,7 @@ export async function mountM01LogicLab(
/** 흐름 예시값 → 왼쪽 시험 계산 입력(이름이 있는 칸만) · 바뀌면 왼쪽을 다시 그리고 셈 */
const syncLeft = (o: Opened, ex: Record<string, string>): void => {
const names = new Set((o.row?.입력 ?? []).map((x) => x.이름));
const names = new Set((calcRow(o.row)?.입력 ?? []).map((x) => x.이름));
const changed = Object.entries(ex).filter(([k, v]) => names.has(k) && o.values[k] !== v);
if (!changed.length) return;
quiet = true;
@@ -195,6 +195,25 @@ export function withExamples(lg: CfLogic, vals: Record<string, string>): CfLogic
return next;
}
/** 흐름 로직의 시험 계산 입력 칸 — 「설계 때 정할 것」(변수 · 고르기 · 범위 · 단위) · 이름이 겹치면 하나 */
export function designFields(
lg: CfLogic,
): { 이름: string; 단위?: string; 고르기?: (string | number)[]; 범위?: [number, number] }[] {
const seen = new Set<string>();
return varsOf(lg).flatMap((v) => {
if (!v.name || seen.has(v.name)) return [];
seen.add(v.name);
return [
{
이름: v.name,
...(v.unit && v.unit !== "-" ? { 단위: v.unit } : {}),
...(v.type === "choice" && v.choices?.length ? { 고르기: v.choices } : {}),
...(v.range ? { 범위: v.range } : {}),
},
];
});
}
/** 예시값만 다른가 — 그 밖이 같으면 고친 것으로 안 셈 */
export function sameShape(a: CfLogic, b: CfLogic): boolean {
const strip = (lg: CfLogic): string => {