Files
Aislo/common_util/common_util_machine_crew.ts
T
eomsangdonandClaude Opus 5.5 2c6e49f92c fix(842-3): 범위 잡재료율 기계 둘 · 수식 빌더가 저장본 문서를 조용히 빼던 흠
- 원인: 옮김에서 펌프 준설선 EQ000552 · 553 잡재료율 「13∼18」 이 사라짐 → 옛 엔진 멈춤 · 새 계산기 셈(빈 잡품)
  → GC000268 옵션 「다름」 → 저장 밖 → 그 식을 부르는 문서 320 개가 저장본에서 지워짐(1,520 → 1,200)
- 범위 글 = 잡품 율 글 그대로(from_old · TS fromOld · check 허용) · 두 대 다시 옮김 → 까닭 「범위」 옛 칸과 같음
- 빌더 = 저장본 문서가 저장 밖으로 빠지면 멈춤 · 안 씀 · 키와 까닭 알림(lost) · 시험 802_2 에 lost 0
- 시험 822_2 범위 까닭 기대 되돌림 · 842_3 거울에 범위 값 더함
- 확인: 빌더 --check 저장 1,520 · 기본 다름 0 · 옵션 다름 3(채택) · 저장본 · 목록 같음 · 655 대 시간당(옛 자료 대 새 자료) 다름 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-15 19:25:43 +09:00

81 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
* common_util_machine_crew.ts
* 기계 한 대 인력 줄 · 잡품 줄(PLAN 842-3 · 요구 849 · 853 · 867 · 868 · 870) — 기계 줄 값 칸 꼴 · 읽는 법
* 꼴(기계 줄 `값`) — 인력 = [{키: 'LB:<인력 원문번호>'(빈 글 = 직종 고르기), 인, 이름?}] ·
* 잡품 = [{줄: '주연료' | '전력' | 키: 재료 요소 키, 이름?, 수량?, 율 %}] · 옛 칸(조종원 · 조종원직종 · 잡재료율) 없음
* 읽기(`crewView`) = 식이 읽는 조종원 수(인 합) · 직종(첫 직종) · 잡재료율(첫 줄 율)을 목록에서 셈(저장 안 함) · 옛 꼴 = 그대로
* 옛 꼴 → 새 꼴(`fromOld`)
* 파이썬 · TS 짝 — 짝 = resources/master_data/scripts/master_machine_crew.py · 거울 시험 test_842_3_machine_crew.py
* · 화면 · DOM · fetch 없음
* ========================================================================== */
import type { CrewRow, MiscRow } from "./common_util_formula_doc_cover";
export const CREW = "인력";
export const MISC = "잡품";
export const LISTS = [CREW, MISC];
export const OLD = ["조종원", "조종원직종", "잡재료율"];
/** 잡품 줄 기본 = 이 재료 줄(값 있음 · 0 아님) */
export const BASE = ["주연료", "전력"];
type Vals = Record<string, unknown>;
const isNum = (v: unknown): v is number => typeof v === "number" && Number.isFinite(v);
/** 노임 키 → 인력 원문번호(`LB:1048` → 1048 · 빈 글 = 직종 고르기) */
export const code = (key: unknown): string => {
const t = String(key ?? "");
return t.startsWith("LB:") ? t.slice(3) : t;
};
/** 새 꼴(옛 칸 없음) 기계 값 */
export const isNew = (vals: unknown): boolean =>
!!vals &&
typeof vals === "object" &&
!Array.isArray(vals) &&
!OLD.some((k) => k in (vals as Vals));
export const crewOf = (vals: Vals | undefined): CrewRow[] | undefined =>
Array.isArray(vals?.[CREW]) ? (vals[CREW] as CrewRow[]) : undefined;
export const miscOf = (vals: Vals | undefined): MiscRow[] | undefined =>
Array.isArray(vals?.[MISC]) ? (vals[MISC] as MiscRow[]) : undefined;
/** 식이 읽는 값 — 새 꼴이면 옛 칸 셋을 목록에서 셈해 더한 새 묶음 · 그 밖 = 그대로 */
export function crewView(vals: Vals): Vals {
if (!isNew(vals)) return vals;
const crew = crewOf(vals);
const misc = miscOf(vals);
const jobs = (crew ?? []).map((r) => code(r?.키)).filter((c) => c);
const rate = (misc ?? []).find((r) => r && r.줄)?.율;
return {
...vals,
조종원: crew === undefined ? null : crew.reduce((a, r) => a + (Number(r?.인) || 0), 0),
조종원직종: jobs.length ? jobs[0] : null,
잡재료율: misc === undefined ? null : (rate ?? 0),
};
}
/** 옛 꼴 값 → 새 꼴(옛 칸 셋 → 인력 · 잡품) — 옛 칸 없음 = 그대로 */
export function fromOld(vals: Vals, base?: string[]): Vals {
if (isNew(vals)) return vals;
const out: Vals = Object.fromEntries(Object.entries(vals).filter(([k]) => !OLD.includes(k)));
const n = vals.조종원;
const job = vals.조종원직종;
const rate = vals.잡재료율;
if (isNum(n)) out[CREW] = n > 0 ? [{ 키: job ? `LB:${String(job)}` : "", 인: n }] : [];
const b = base ?? BASE.filter((k) => ![undefined, null, "", 0].includes(vals[k] as never));
if (isNum(rate)) out[MISC] = rate > 0 && b.length ? b.map((줄) => ({ 줄, 율: rate })) : [];
else if (typeof rate === "string" && rate.includes("∼") && b.length)
out[MISC] = b.map((줄) => ({ 줄, 율: rate as unknown as number })); // 원문 범위 글 그대로
return out;
}
/** 목록 요약 글(M01 기계 목록 열) — 「1048 1인 · 잡품 주연료 22%」 */
export function crewSummary(vals: Vals | undefined, jobName?: (code: string) => string): string {
const crew = (crewOf(vals) ?? []).map((r) => {
const c = code(r.키);
return `${r.이름 || (c ? (jobName?.(c) ?? c) : "직종 고르기")} ${r.인}인`;
});
const misc = (miscOf(vals) ?? []).map((r) => `${r.이름 || r.줄 || r.키} ${r.율}%`);
return [...crew, ...(misc.length ? [`잡품 ${misc.join(", ")}`] : [])].join(" · ");
}