Files
Pier_v1/src/core/copy.ts
T
ypshimandClaude Haiku 5.5 26a5aff517 feat(ground): 하상 selectable; 설계홍수위 and 세굴 깊이 for 하상
- shape-options: a per-option "confirmed" flag; 하상 is confirmed, 해상 is not.
- The 위치 chips store the choice in the pier's draft; 선택 shows it.
- 하상: the groundwater inputs give way to 설계홍수위 DHWL (floodLevelEl) and
  세굴 깊이 (scourDepthM). The groundwater value is kept (남겨두기).
- Checks: G07 DHWL missing, G08 DHWL below the 지반고, G09 scour negative or
  the scour line below the footing bottom. The groundwater check is skipped for 하상.
- Section: the DHWL as a solid line and the 세굴선 dashed.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-26 11:06:10 +09:00

65 lines
2.7 KiB
TypeScript

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' | 'ground-position';
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<CopyItem, ItemRule> = {
'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 },
'ground-position': { label: '지반 위치·지하수위', keys: ['groundPosition', 'groundWaterOn', 'groundWaterEl', 'floodLevelEl'], defaultOn: false, pileItem: false },
};
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<string, unknown> = { ...target };
for (const c of plan.changes) next[c.key] = c.to;
return next as unknown as PierInput;
}