Files
Aislo/A00_Common/line_stack_why.ts
T
eomsangdonandClaude Opus 5.5 7cde7acf1c feat(804-12): 왼쪽 만약 식 = 결정된 식 + 근거 한 줄 · 고치면 굳음 + 표지(요구 695 · 696)
- 공식 줄 만약(IF) 식 = 지금 옵션 · 중간값으로 탄 갈래만(decide) · 만약이 낳은 0 · 1 접음 · 「a - -x」 → 「a + x」 · 셈은 그대로(판정 = 계산기 값)
- 바로 아래 근거 한 줄 — 옵션 비교 「지붕슬래브 「아님」 → 0」 · 수치 비교 「H = 9 > 7 → …」 · 규칙 보기 단추 없음(M01 도)
- 오른쪽 산출근거 = 같은 decide 한 벌(tex 의 만약 · 0 · 1 규칙을 걷고 decide 부름)
- 결정된 식을 고치면 그 글로 굳음(만약 사라짐 · 옵션 바꿔도 안 따라감) · 저장본에 만약이 있던 줄 = 「옵션 규칙이 풀렸음 · 되돌리려면 [되돌림]」 표지 · M01 · M02 같은 부품
- 1,518 전수 — 만약 든 388 문서 663 줄 · 결정된 식 값 = 원 식 = 셈 답 · 남은 만약 0 · 근거 1,062
- test_804_12 둘 · helper 「결정」 할일 · test_804_7 머리 단추 기대를 804-11 deleteButton 으로 고침(낡은 기대)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 16:04:16 +09:00

55 lines
2.1 KiB
TypeScript

/* =============================================================================
* line_stack_why.ts
* 결정된 식 근거 한 줄(요구 695 · 696) — 탄 길 위 만약마다 「조건 → 탄 갈래」
* 옵션 비교 = 「지붕슬래브 「아님」 아님 → 17」 · 수치 비교 = 「H = 9 > 7 → …」 · 그 밖 = 조건 글 + 아님
* 판정 · 결정은 `common_util_formula_doc_view` (decide · whyOf) — 여기는 글만
* ========================================================================== */
import { textOf, type Node } from "../common_util/common_util_formula_doc";
import { whyOf, type Values } from "../common_util/common_util_formula_doc_view";
import { lt } from "./line_stack_text";
export interface WhyCtx {
/** 옵션 기호 → 화면 이름(변수 이름) */
label: (id: string) => string;
/** 식 글 → 화면 글(표 값 별칭) */
shown: (text: string) => string;
/** 값 → 글 */
fmt: (v: unknown) => string;
}
const OP: Record<string, string> = {
"<": "<",
"<=": "≤",
">": ">",
">=": "≥",
"==": "=",
"!=": "≠",
};
function condText(c: Node, yes: boolean, vals: Values, x: WhyCtx): string {
const no = lt("If_Not");
if (c[0] === "bin" && (c[1] === "==" || c[1] === "!=")) {
const [v, s] =
c[2][0] === "var" && c[3][0] === "str"
? [c[2], c[3]]
: c[3][0] === "var" && c[2][0] === "str"
? [c[3], c[2]]
: [null, null];
if (v && s && typeof vals[v[1]] === "string")
return `${x.label(v[1])} 「${s[1]}」${(c[1] === "==" ? !yes : yes) ? no : ""}`;
}
if (c[0] === "bin" && OP[c[1]]) {
const side = (n: Node): string =>
n[0] === "var" ? `${x.shown(n[1])} = ${x.fmt(vals[n[1]])}` : x.shown(textOf(n));
return `${side(c[2])} ${OP[c[1]]} ${side(c[3])}${yes ? "" : no}`;
}
return `${x.shown(textOf(c))}${yes ? "" : no}`;
}
/** 근거 한 줄 — 만약 없으면 빈 글 */
export const whyText = (n: Node, vals: Values, x: WhyCtx): string =>
whyOf(n, vals)
.map((w) => `${condText(w.cond, w.yes, vals, x)} → ${x.shown(textOf(w.to))}`)
.join(" · ");