feat(ground): load ground_model.json and apply the pier-centre ground EL
- ground-model.ts: read and check schema 1 of the Python ground model. - ② 지반·지층 card: import the json, show the DTM value beside the excel value, and apply it only when the user presses the button (tracked as an override, revertible). - groundEl becomes an editable, tracked input; the project file keeps the imported model and checks it on open. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
304b350481
commit
c3606011b5
5 files changed
+208
-1
No files matched your search
@@ -19,6 +19,7 @@ export const EDITABLE_FIELDS = [
|
||||
{ key: 'copingH2Mm', label: '테이퍼 높이 h2', unit: 'mm' },
|
||||
{ key: 'levelWidthMm', label: 'Level 폭', unit: 'mm' },
|
||||
{ key: 'pileLengthMm', label: '말뚝 길이', unit: 'mm' },
|
||||
{ key: 'groundEl', label: '지반고 EL', unit: 'm' },
|
||||
] as const;
|
||||
|
||||
/** Inputs tracked for overrides and pending changes: the numeric cards plus 열별 본수 (an array, compared by value). */
|
||||
@@ -41,6 +42,7 @@ export const FIELD_LABELS: Record<EditableKey, string> = {
|
||||
copingH2Mm: '테이퍼 높이 h2',
|
||||
levelWidthMm: 'Level 폭',
|
||||
pileLengthMm: '말뚝 길이',
|
||||
groundEl: '지반고 EL',
|
||||
pileRows: '열별 본수',
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 지반 모델 결과 (RAG/pierzainer_ground의 ground_model.json, schema 1) 읽기.
|
||||
* 앱은 교각 중심의 지반고만 쓴다. 적용은 사용자가 누를 때만 하며, 자동으로 입력을 바꾸지 않는다.
|
||||
*/
|
||||
|
||||
/** Must match GROUND_MODEL_SCHEMA in the Python package. */
|
||||
export const GROUND_MODEL_SCHEMA = 1;
|
||||
|
||||
export interface GroundModelPier {
|
||||
/** 교각 이름 (입력의 name, 예: P1). */
|
||||
id: string;
|
||||
/** 지형 DTM으로 구한 교각 중심 지반고 (m). 자료 밖이면 null. */
|
||||
centerEl: number | null;
|
||||
/** 엑셀 지반고 (m). 없으면 null. */
|
||||
excelEl: number | null;
|
||||
}
|
||||
|
||||
export interface GroundModelFile {
|
||||
schema: number;
|
||||
generated: string;
|
||||
piers: GroundModelPier[];
|
||||
}
|
||||
|
||||
function numOrNull(v: unknown): number | null {
|
||||
return typeof v === 'number' && Number.isFinite(v) ? v : null;
|
||||
}
|
||||
|
||||
/** Checks the shape of a parsed ground_model.json. Throws with the first problem named in Korean. */
|
||||
export function checkGroundModel(raw: unknown): GroundModelFile {
|
||||
const obj = raw as Partial<GroundModelFile> | null;
|
||||
if (!obj || typeof obj !== 'object') throw new Error('지반 모델 파일 형식이 아닙니다.');
|
||||
if (obj.schema !== GROUND_MODEL_SCHEMA) {
|
||||
throw new Error(`지반 모델 형식 번호 ${String(obj.schema)}을(를) 읽을 수 없습니다 (지원: ${GROUND_MODEL_SCHEMA}).`);
|
||||
}
|
||||
if (!Array.isArray(obj.piers)) throw new Error('지반 모델 파일에 교각 목록(piers)이 없습니다.');
|
||||
const piers = obj.piers.map((p, i) => {
|
||||
const id = (p as { id?: unknown })?.id;
|
||||
if (typeof id !== 'string' || !id) throw new Error(`지반 모델 ${i + 1}번째 교각의 이름(id)이 없습니다.`);
|
||||
const ground = (p as { ground?: { center?: unknown; excel?: unknown } }).ground ?? {};
|
||||
return { id, centerEl: numOrNull(ground.center), excelEl: numOrNull(ground.excel) };
|
||||
});
|
||||
return { schema: obj.schema, generated: typeof obj.generated === 'string' ? obj.generated : '', piers };
|
||||
}
|
||||
|
||||
/** Parses the file text. Throws when it is not JSON or does not match the schema. */
|
||||
export function parseGroundModel(text: string): GroundModelFile {
|
||||
let raw: unknown;
|
||||
try {
|
||||
raw = JSON.parse(text);
|
||||
} catch {
|
||||
throw new Error('지반 모델 파일이 JSON으로 읽히지 않습니다.');
|
||||
}
|
||||
return checkGroundModel(raw);
|
||||
}
|
||||
|
||||
/** The DTM ground EL at the pier centre, or undefined when the model has no value for it. */
|
||||
export function groundElFor(model: GroundModelFile, pierName: string): number | undefined {
|
||||
return model.piers.find((p) => p.id === pierName)?.centerEl ?? undefined;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { FckByMember, Material } from './rebar/common';
|
||||
import { checkGroundModel, type GroundModelFile } from './ground-model';
|
||||
import type { PierInput } from './types';
|
||||
|
||||
/** Project file schema (spec §8). Bump only with a migration. */
|
||||
@@ -37,6 +38,8 @@ export interface ProjectFile {
|
||||
bearingDrawing?: Record<string, { no: number; elx: number; h1: number; h2: number }[]>;
|
||||
/** ② 부재별 fck (MPa). Absent in older files: every member uses the 공통 fck. */
|
||||
fckByMember?: FckByMember;
|
||||
/** 지반 모델 (ground_model.json)의 교각별 지반고. Absent = 불러오지 않음. Applied to a pier only by the user. */
|
||||
groundModel?: GroundModelFile;
|
||||
}
|
||||
|
||||
/** Serialises a project to the pretty-printed JSON stored in <교량명>_교각설계.pzr.json. */
|
||||
@@ -68,6 +71,7 @@ export function parseProject(text: string): ProjectFile {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obj.groundModel !== undefined) checkGroundModel(obj.groundModel);
|
||||
obj.piers.forEach((p, i) => {
|
||||
if (!p || typeof p.id !== 'string' || !p.input) throw new Error(`교각 ${i + 1}: id 또는 input이 없습니다.`);
|
||||
const input = p.input;
|
||||
|
||||
Reference in new issue
Block a user