- 공식 줄 만약(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>
55 lines
2.1 KiB
TypeScript
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(" · ");
|