feat(rebar): per-member fck on ② for column, coping and footing

Each member can take its own fck on its ② card. A member without one uses the ③ 공통 fck, and fy stays common.
The rebar table and the 3D model both read the resolved value. The I02 note stays until every fck member has its
own value. The project file stores the values as optional fckByMember and refuses a bad value on open.
Changing the fck is not a shape change, so it is not counted in the pending changes.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-23 08:53:39 +09:00
1 parent d8fd6adcf0
commit 7cf5835689
6 files changed
+175 -18

No files matched your search

+10 -1
View File
@@ -1,4 +1,4 @@
import type { Material } from './rebar/common';
import type { FckByMember, Material } from './rebar/common';
import type { PierInput } from './types';
/** Project file schema (spec §8). Bump only with a migration. */
@@ -31,6 +31,8 @@ export interface ProjectFile {
history: { version: string; note: string; at: string }[];
/** ③ 공통 설정 (fck · fy). Absent in older files: the defaults are used. */
common?: Material;
/** ② 부재별 fck (MPa). Absent in older files: every member uses the 공통 fck. */
fckByMember?: FckByMember;
}
/** Serialises a project to the pretty-printed JSON stored in <교량명>_교각설계.pzr.json. */
@@ -55,6 +57,13 @@ export function parseProject(text: string): ProjectFile {
throw new Error(`지원하지 않는 파일 버전입니다 (schemaVersion ${String(obj.schemaVersion)}, 지원: ${SCHEMA_VERSION}).`);
}
if (!Array.isArray(obj.piers)) throw new Error('piers 목록이 없습니다.');
if (obj.fckByMember !== undefined) {
for (const [member, value] of Object.entries(obj.fckByMember)) {
if (!['column', 'coping', 'footing'].includes(member) || typeof value !== 'number' || !(value > 0)) {
throw new Error(`부재별 fck 값이 맞지 않습니다 (${member}: ${String(value)}).`);
}
}
}
obj.piers.forEach((p, i) => {
if (!p || typeof p.id !== 'string' || !p.input) throw new Error(`교각 ${i + 1}: id 또는 input이 없습니다.`);
const input = p.input;