feat(796-2a): 수식 탭 화면 — 공통 수식 부품 · M01 수식 탭(첫 탭) · 고침 · 변수 창 · 옵션 가로
- ui_template_equation(.ts · _line.ts · .css): 분수 · 첨자 · 괄호 · % · 조건 칩 · 하위 로직 블록(접힘) · 결과명 = 이름 식 = 값 식 = 결과 + 변수 풀이 · 부품 모음 견본 한 줄 - M01 LogicLab_Equation: 옵션 가로(도구줄 + 값 칸 · 찾기형 · 말줄임) · 줄 고르면 식 칸 + 숨은 아이콘 줄 · 서버 미리 셈 다시 그림 · 고침 목록 캐시 → [수식 저장](개정 확인) · 떠나기 전 버림 물음 - 변수 창(이름 · 기호 · 위 · 아래첨자 · 단위 · 값 · 보이는 자리) · 변수 더함 · 지움(쓰는 곳 있으면 서버 까닭 그대로) - 보기 고르기 = 수식 첫 탭 · 단가산출 상세 · 시트 · 인력재료경비 · 시험계산 · 텍스트 수식은 뒤로(걷지 않음) - test_796_2_equation_screen 새로 · test_794_1 기대 갱신(첫 탭 수식 · LogicLab 700 줄 상한 — 수식 이음 14 줄) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
/* =============================================================================
|
||||
* M01_MasterData/logic/M01_Logic_Equation_Model.ts
|
||||
* 수식 탭 계산(796-2 · 화면 · fetch 없음) — 줄 → 고침 자리 · 식 칸 아이콘 끼움 · 옵션 값 꼴 · 변수 고침 요청.
|
||||
* 서버 고침 꼴 = `master_equation_edit.py` 머리(할일 식 · 더함 · 지움 · 변수 · 표시) — 여기서는 요청 목록만 만듦
|
||||
* 셈 · 검사는 서버 한 벌(③ 서버 단독) — 브라우저는 모양만
|
||||
* ========================================================================== */
|
||||
|
||||
import type { EqLine } from "@ui/ui_template_equation";
|
||||
|
||||
export interface EqEdit {
|
||||
할일: "식" | "더함" | "지움" | "변수" | "표시";
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/** 식 줄의 고침 자리(`중간:<열쇠>` · `결과` · `호표:<n>` · `덧줄:<n>`) */
|
||||
export const spotOf = (line: EqLine): string =>
|
||||
line.갈래 === "호표" || line.갈래 === "덧줄"
|
||||
? `${line.갈래}:${line.차례 ?? 0}`
|
||||
: line.갈래 === "결과"
|
||||
? "결과"
|
||||
: `중간:${line.열쇠}`;
|
||||
|
||||
export const formulaEdit = (line: EqLine, text: string): EqEdit => ({
|
||||
할일: "식",
|
||||
자리: spotOf(line),
|
||||
식: text,
|
||||
});
|
||||
|
||||
/** 아이콘 줄 — 식 칸 글에 끼우는 꼴 */
|
||||
export type InsertKind = "frac" | "paren" | "sub" | "sup" | "percent";
|
||||
|
||||
/** 선택 영역 `[from, to)` 를 아이콘 꼴로 바꾼 글 · 커서 자리 */
|
||||
export function insertInto(
|
||||
kind: InsertKind,
|
||||
text: string,
|
||||
from: number,
|
||||
to: number,
|
||||
): { text: string; caret: number } {
|
||||
const head = text.slice(0, from);
|
||||
const pick = text.slice(from, to);
|
||||
const tail = text.slice(to);
|
||||
const put = (mid: string, caret: number): { text: string; caret: number } => ({
|
||||
text: head + mid + tail,
|
||||
caret: head.length + caret,
|
||||
});
|
||||
switch (kind) {
|
||||
case "frac": // 분수 = (위) / (아래) — 고른 글이 위 · 커서는 아래 괄호 안
|
||||
return pick ? put(`(${pick}) / ()`, pick.length + 6) : put("() / ()", 1);
|
||||
case "paren":
|
||||
return pick ? put(`(${pick})`, pick.length + 2) : put("()", 1);
|
||||
case "sub":
|
||||
return put(`${pick}_`, pick.length + 1);
|
||||
case "sup":
|
||||
return put(`${pick}^`, pick.length + 1);
|
||||
case "percent":
|
||||
return put(`${pick} / 100`, pick.length + 6);
|
||||
}
|
||||
}
|
||||
|
||||
/** 옵션 값 — 수 꼴 글은 수로(엔진 입력 꼴) · 빈 값은 안 보냄(자동값) */
|
||||
export function inputsOf(values: Record<string, string>): Record<string, number | string> {
|
||||
const out: Record<string, number | string> = {};
|
||||
for (const [name, raw] of Object.entries(values)) {
|
||||
if (raw === "") continue;
|
||||
out[name] = /^-?\d+(\.\d+)?$/.test(raw) ? Number(raw) : raw;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export interface VarForm {
|
||||
열쇠: string;
|
||||
이름: string;
|
||||
기호: string;
|
||||
위: string;
|
||||
아래: string;
|
||||
단위: string;
|
||||
갈래?: "입력" | "중간";
|
||||
설명?: string;
|
||||
기본값?: string;
|
||||
식?: string;
|
||||
/** 보이는 자리 글(중간 줄 · 빈 글 = 전체) */
|
||||
표시?: string;
|
||||
}
|
||||
|
||||
/** 변수 고침 창 → 요청 목록(바꾼 칸만) — `보이는 자리`(중간 줄) = 0~6 · 빈 칸 = 전체 자리(`표시` 지움) */
|
||||
export function varEdits(before: VarForm, now: VarForm): EqEdit[] {
|
||||
const out: EqEdit = { 할일: "변수", 열쇠: before.열쇠 };
|
||||
let changed = false;
|
||||
for (const k of ["이름", "기호", "위", "아래", "단위"] as const)
|
||||
if (now[k] !== before[k]) {
|
||||
out[k] = now[k];
|
||||
changed = true;
|
||||
}
|
||||
const list: EqEdit[] = changed ? [out] : [];
|
||||
if (now.표시 !== before.표시) {
|
||||
const digits = now.표시 === "" || now.표시 === undefined ? null : Number(now.표시);
|
||||
list.push({ 할일: "표시", 열쇠: before.열쇠, 표시: digits });
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/** 변수 더함 창 → 요청 — 빈 칸은 안 보냄 */
|
||||
export function addEdit(form: VarForm, after?: string): EqEdit {
|
||||
const out: EqEdit = { 할일: "더함", 갈래: form.갈래 ?? "입력", 열쇠: form.열쇠.trim() };
|
||||
for (const k of ["이름", "기호", "위", "아래", "단위", "설명"] as const) {
|
||||
const v = (form[k] ?? "").trim();
|
||||
if (v) out[k] = v;
|
||||
}
|
||||
if (form.갈래 === "중간") {
|
||||
out.식 = form.식 || "0";
|
||||
if (after !== undefined) out.뒤 = after;
|
||||
} else if (form.기본값) out.기본값 = form.기본값;
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user