/* ============================================================================= * M02_MasterTemplete_Inputs_Model.ts * 「선택 입력」 카드의 셈(화면 없음) — 입력 키 · 알약 키 · 자리 고름 · 줄 만들기 · 알약 목록. * 값 글 · 값 칸 규칙은 `M02_Labor_Values_Model.ts`(일위대가 입력 모달과 한 벌 · 여기서 다시 내보냄). * 약속 = PLAN 25-1b: 입력 키 `{로직키}|{입력이름}` · 알약 키 `입력|{로직키}|{입력이름}` · * 같은 이름의 입력도 로직마다 따로. 처음은 모두 「안 씀」 — 프로그램이 추측해 나누지 않음. * ========================================================================== */ import type { LinkItem } from "../A00_Common/spreadsheet/spreadsheet_links"; import type { InputLine, InputLinks, InputSeat, ItemInput, ItemInputs, } from "./M02_MasterTemplete_Api_Fetch"; /** 화면 글 ↔ 자리 — 「안 씀」 = 빈 글 */ export const SEAT_OPTIONS: { value: "" | InputSeat; label: string }[] = [ { value: "", label: "안 씀" }, { value: "면적", label: "면적산출 알약" }, { value: "재료", label: "재료산출 알약" }, { value: "선택", label: "선택" }, ]; export const inputKey = (logic: string, name: string): string => `${logic}|${name}`; export const pillKey = (logic: string, name: string): string => `입력|${logic}|${name}`; /** 자리 고름 표 — 키 = 입력 키 · 값 = 자리(안 쓰면 키 없음) */ export type SeatMap = Map; export function seatsOf(links: InputLinks | null): SeatMap { const out: SeatMap = new Map(); for (const line of links?.줄 ?? []) if (line.자리) out.set(inputKey(line.로직, line.입력), line.자리); return out; } /** 저장할 줄 — 자리를 고른 것만(없는 것 = 안 씀) · 면적 · 재료는 알약 키를 같이 */ export function linesOf(list: ItemInputs, seats: SeatMap): InputLine[] { const out: InputLine[] = []; for (const logic of list.로직) for (const input of logic.입력) { const seat = seats.get(inputKey(logic.로직, input.이름)); if (!seat) continue; out.push({ 로직: logic.로직, 입력: input.이름, 자리: seat, ...(seat === "선택" ? {} : { 알약: pillKey(logic.로직, input.이름) }), }); } return out; } export const countOf = (list: ItemInputs): { logics: number; inputs: number } => ({ logics: list.로직.length, inputs: list.로직.reduce((sum, logic) => sum + logic.입력.length, 0), }); /** 그 시트(면적산출 · 재료산출)의 알약 — 고른 자리가 그 시트인 입력만 · 「로직 이름 · 입력 이름」 */ export function pillsOf( list: ItemInputs, links: InputLinks | null, seat: "면적" | "재료", ): LinkItem[] { const seats = seatsOf(links); const out: LinkItem[] = []; for (const logic of list.로직) for (const input of logic.입력) { if (seats.get(inputKey(logic.로직, input.이름)) !== seat) continue; out.push({ 키: pillKey(logic.로직, input.이름), 이름: `${logic.이름} · ${input.이름}`, ...(input.단위 ? { 단위: input.단위 } : {}), 고정: true, }); } return out; } /* ── 값 함수 — 일위대가 입력 모달과 한 벌(39-3 · `M02_Labor_Values_Model.ts` 로 옮김 · 옛 이름 그대로 내보냄) ── */ export { autoText, choicesOf, rangeOf, valueHint, type ValueDoc } from "./M02_Labor_Values_Model"; /* ── 프로젝트에서 값 받기(PLAN 25-2d) — 자리 「선택」 인 입력만 로직마다 묶어 값 · 확인 표시 ── */ /** 자리가 「선택」 인 입력만 로직 차례로 묶음 — 값 받기 카드가 보이는 입력 */ export function pickedGroups( list: ItemInputs, links: InputLinks | null, ): { logic: ItemInputs["로직"][number]; inputs: ItemInput[] }[] { const picked = new Set( [...seatsOf(links)].filter(([, seat]) => seat === "선택").map(([key]) => key), ); return list.로직 .map((logic) => ({ logic, inputs: logic.입력.filter((input) => picked.has(inputKey(logic.로직, input.이름))), })) .filter((group) => group.inputs.length > 0); }