import type { EditableKey } from './changes'; import type { PierInput } from './types'; /** * 속성 복사 (spec §9 · plan C7). Copies chosen attributes from one pier to others. * Values the spec never copies (coordinates, IP, elevations, names) are not in any item, so they cannot be copied. */ export type CopyItem = 'coping-width' | 'coping-length' | 'pile-length' | 'pile-rows'; interface ItemRule { label: string; keys: EditableKey[]; /** Off by default (spec: 말뚝 길이·코핑 길이 기본 해제). */ defaultOn: boolean; /** Pile items only apply when the foundation type matches (spec §9 건너뜀). */ pileItem: boolean; } export const COPY_ITEMS: Record = { 'coping-width': { label: '코핑 폭', keys: ['copingWidthMm'], defaultOn: true, pileItem: false }, 'coping-length': { label: '코핑 길이 L', keys: ['copingLengthMm'], defaultOn: false, pileItem: false }, 'pile-length': { label: '말뚝 길이', keys: ['pileLengthMm'], defaultOn: false, pileItem: true }, 'pile-rows': { label: '열별 본수', keys: ['pileRows'], defaultOn: false, pileItem: true }, }; export const DEFAULT_COPY_ITEMS: CopyItem[] = (Object.keys(COPY_ITEMS) as CopyItem[]).filter((k) => COPY_ITEMS[k].defaultOn); export interface CopyChange { key: EditableKey; from: unknown; to: unknown; } export interface CopyPlan { changes: CopyChange[]; /** Items not applied to this target, with the reason shown in the preview. */ skipped: { item: CopyItem; reason: string }[]; } /** Preview for one target: what would change and what is skipped. Same values are not counted as changes. */ export function planCopy(source: PierInput, target: PierInput, items: CopyItem[]): CopyPlan { const changes: CopyChange[] = []; const skipped: CopyPlan['skipped'] = []; for (const item of items) { const rule = COPY_ITEMS[item]; if (rule.pileItem && source.foundationType !== target.foundationType) { skipped.push({ item, reason: `기초 형식이 다릅니다 (${target.foundationType})` }); continue; } for (const key of rule.keys) { if (JSON.stringify(source[key]) === JSON.stringify(target[key])) continue; changes.push({ key, from: target[key], to: source[key] }); } } return { changes, skipped }; } /** Applies a plan to a target input. Only the planned keys change. */ export function applyCopy(target: PierInput, plan: CopyPlan): PierInput { const next: Record = { ...target }; for (const c of plan.changes) next[c.key] = c.to; return next as unknown as PierInput; }