fix(rebar): 부재 fck 되돌리기가 교각도 기본값으로 돌아가고, 기본과 다르면 주황색 표시
- IMPORTED_FCK(기둥 40, 코핑 40, 확대기초 27)와 fckChanged 추가, 테스트 4건 - 되돌리기는 공통 fck가 아니라 교각도 기본값으로 돌아감 (기둥·코핑은 기존에 27로 돌아가던 문제) - 기본과 다르면 입력 카드를 주황색으로 표시. "변경 n건"에는 넣지 않음 (배근에만 반영) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9a338614a6
commit
70fa0be86f
3 files changed
+41
-8
No files matched your search
@@ -91,6 +91,15 @@ export const FCK_MEMBERS: readonly FckMember[] = ['column', 'coping', 'footing']
|
|||||||
/** Per-member fck (MPa). A member without an entry uses the ③ 공통 설정 fck. */
|
/** Per-member fck (MPa). A member without an entry uses the ③ 공통 설정 fck. */
|
||||||
export type FckByMember = Partial<Record<FckMember, number>>;
|
export type FckByMember = Partial<Record<FckMember, number>>;
|
||||||
|
|
||||||
|
/** 교각도 기준 부재별 기본 fck (MPa). 되돌리기는 이 값으로 돌아가고, 이 값과 다르면 주황색으로 표시합니다. */
|
||||||
|
export const IMPORTED_FCK: Record<FckMember, number> = { column: 40, coping: 40, footing: 27 };
|
||||||
|
|
||||||
|
/** True when the member's fck is set and differs from its imported default. An unset member is not changed. */
|
||||||
|
export function fckChanged(byMember: FckByMember, member: FckMember): boolean {
|
||||||
|
const value = byMember[member];
|
||||||
|
return value !== undefined && value !== IMPORTED_FCK[member];
|
||||||
|
}
|
||||||
|
|
||||||
/** The material a member is designed with: its own fck when set, otherwise the 공통 value. fy stays common. */
|
/** The material a member is designed with: its own fck when set, otherwise the 공통 value. fy stays common. */
|
||||||
export function materialFor(common: Material, byMember: FckByMember, member: FckMember): Material {
|
export function materialFor(common: Material, byMember: FckByMember, member: FckMember): Material {
|
||||||
return { ...common, fck: byMember[member] ?? common.fck };
|
return { ...common, fck: byMember[member] ?? common.fck };
|
||||||
|
|||||||
+9
-8
@@ -14,7 +14,7 @@ import { pileGeometry } from './core/geometry';
|
|||||||
import { rebarSummary, type RebarRow } from './core/rebar/summary';
|
import { rebarSummary, type RebarRow } from './core/rebar/summary';
|
||||||
import { shearSegments } from './core/rebar/coping';
|
import { shearSegments } from './core/rebar/coping';
|
||||||
import { buildRebar3D, type RebarColorMode, type RebarScene } from './view/rebar3d';
|
import { buildRebar3D, type RebarColorMode, type RebarScene } from './view/rebar3d';
|
||||||
import { DEFAULT_MATERIAL, FCK_MEMBERS, fyOf, GRADE_CHOICES, isAssumedMaterial, materialFrom, type BendFactors, type FckByMember, type FckMember, type GradeKey, type Material } from './core/rebar/common';
|
import { DEFAULT_MATERIAL, FCK_MEMBERS, fckChanged, fyOf, GRADE_CHOICES, IMPORTED_FCK, isAssumedMaterial, materialFrom, type BendFactors, type FckByMember, type FckMember, type GradeKey, type Material } from './core/rebar/common';
|
||||||
import { buildQuantity, quantityRows, type Quantity, type QuantityLine } from './core/rebar/quantity';
|
import { buildQuantity, quantityRows, type Quantity, type QuantityLine } from './core/rebar/quantity';
|
||||||
import { parseDrawingRows } from './core/drawing-import';
|
import { parseDrawingRows } from './core/drawing-import';
|
||||||
import { groundElFor, parseGroundModel, strataRowsFor, type GroundModelFile } from './core/ground-model';
|
import { groundElFor, parseGroundModel, strataRowsFor, type GroundModelFile } from './core/ground-model';
|
||||||
@@ -125,7 +125,7 @@ const state = {
|
|||||||
/** ③ 공통 설정 (fck · fy). */
|
/** ③ 공통 설정 (fck · fy). */
|
||||||
material: { ...DEFAULT_MATERIAL } as Material,
|
material: { ...DEFAULT_MATERIAL } as Material,
|
||||||
/** ② 부재별 fck. A member without an entry uses the 공통 fck (③). Initial values from 교각도 (025·026, 승인 2026-10-27): 기둥·코핑 40, 기초 27. */
|
/** ② 부재별 fck. A member without an entry uses the 공통 fck (③). Initial values from 교각도 (025·026, 승인 2026-10-27): 기둥·코핑 40, 기초 27. */
|
||||||
fckByMember: { column: 40, coping: 40, footing: 27 } as FckByMember,
|
fckByMember: { ...IMPORTED_FCK } as FckByMember,
|
||||||
/** Bar highlighted on ③ after [보기] (시안 ③ 알림). */
|
/** Bar highlighted on ③ after [보기] (시안 ③ 알림). */
|
||||||
/** Bars selected on ③ (철근표 checkboxes, 3D click, [보기]). */
|
/** Bars selected on ③ (철근표 checkboxes, 3D click, [보기]). */
|
||||||
rebarSelection: new Set<string>(),
|
rebarSelection: new Set<string>(),
|
||||||
@@ -1897,7 +1897,8 @@ function renderMaterial(): void {
|
|||||||
function setMemberFck(member: FckMember, raw: string): void {
|
function setMemberFck(member: FckMember, raw: string): void {
|
||||||
const next = { ...state.fckByMember };
|
const next = { ...state.fckByMember };
|
||||||
if (raw.trim() === '') {
|
if (raw.trim() === '') {
|
||||||
delete next[member];
|
// 되돌리기: back to the imported default, not to the 공통 value.
|
||||||
|
next[member] = IMPORTED_FCK[member];
|
||||||
} else {
|
} else {
|
||||||
const value = Number(raw);
|
const value = Number(raw);
|
||||||
if (!Number.isFinite(value) || value <= 0) {
|
if (!Number.isFinite(value) || value <= 0) {
|
||||||
@@ -1915,8 +1916,9 @@ function setMemberFck(member: FckMember, raw: string): void {
|
|||||||
/** fck row on a ② card for a member that has its own fck: value, the 공통 value beside it, and a revert when set. */
|
/** fck row on a ② card for a member that has its own fck: value, the 공통 value beside it, and a revert when set. */
|
||||||
function renderMemberFck(box: HTMLDivElement, member: FckMember): void {
|
function renderMemberFck(box: HTMLDivElement, member: FckMember): void {
|
||||||
const own = state.fckByMember[member];
|
const own = state.fckByMember[member];
|
||||||
// Not the orange "changed" style: fck changes only the rebar, so it is not a pending shape change (변경 n건).
|
// Orange = differs from the imported default. fck changes only the rebar, so it is not counted in 변경 n건.
|
||||||
const row = el('div', undefined, 'edit-row');
|
const changed = fckChanged(state.fckByMember, member);
|
||||||
|
const row = el('div', undefined, changed ? 'edit-row changed' : 'edit-row');
|
||||||
const id = `member-fck-${member}`;
|
const id = `member-fck-${member}`;
|
||||||
const label = el('label', 'fck (MPa)');
|
const label = el('label', 'fck (MPa)');
|
||||||
label.htmlFor = id;
|
label.htmlFor = id;
|
||||||
@@ -1926,9 +1928,8 @@ function renderMemberFck(box: HTMLDivElement, member: FckMember): void {
|
|||||||
input.step = 'any';
|
input.step = 'any';
|
||||||
input.value = String(own ?? state.material.fck);
|
input.value = String(own ?? state.material.fck);
|
||||||
input.addEventListener('change', () => setMemberFck(member, input.value));
|
input.addEventListener('change', () => setMemberFck(member, input.value));
|
||||||
const note = own === undefined ? `공통 ${state.material.fck}` : `공통 ${state.material.fck} · 배근에만 반영`;
|
row.append(label, input, el('span', `기본 ${IMPORTED_FCK[member]} · 배근에만 반영`, 'muted small'));
|
||||||
row.append(label, input, el('span', note, 'muted small'));
|
if (changed) {
|
||||||
if (own !== undefined) {
|
|
||||||
const revert = el('button', '되돌리기', 'btn small');
|
const revert = el('button', '되돌리기', 'btn small');
|
||||||
revert.type = 'button';
|
revert.type = 'button';
|
||||||
revert.addEventListener('click', () => setMemberFck(member, ''));
|
revert.addEventListener('click', () => setMemberFck(member, ''));
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { fckChanged, IMPORTED_FCK } from '../src/core/rebar/common';
|
||||||
|
|
||||||
|
describe('IMPORTED_FCK (교각도 기준 부재별 기본 fck)', () => {
|
||||||
|
it('is 40 for 기둥·코핑 and 27 for 확대기초', () => {
|
||||||
|
expect(IMPORTED_FCK).toEqual({ column: 40, coping: 40, footing: 27 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fckChanged (기본과 다르면 주황색)', () => {
|
||||||
|
it('is false at the imported default', () => {
|
||||||
|
expect(fckChanged({ column: 40, coping: 40, footing: 27 }, 'coping')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is true when the member differs from its imported default', () => {
|
||||||
|
expect(fckChanged({ coping: 42 }, 'coping')).toBe(true);
|
||||||
|
expect(fckChanged({ footing: 30 }, 'footing')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is false when the member has no value yet', () => {
|
||||||
|
expect(fckChanged({}, 'column')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user