import { create } from 'zustand'; import type { BeamDesignState, SteelProperties, BeamGeometry, ConcreteProperties, CompositeSettings, LateralBracing, LoadConfig, LoadCombinations } from '../types/beam'; import { getSectionByDesignation } from '../data/steelSections'; const defaultSteelProperties: SteelProperties = { designation: 'W18X35', fy: 50.0, e: 29000, useStiffnessFactor: false, depth: 17.7, width: 6.0, tw: 0.30, tf: 0.425, sx: 57.6, ix: 510, zx: 66.5, weight: 35 }; const defaultGeometry: BeamGeometry = { numberOfSupports: 2, spans: [{ id: 1, length: 15.0 }], supports: [ { id: 1, type: 'Pinned' }, { id: 2, type: 'Pinned' } ], leftCantilever: false, leftCantileverLength: 0, rightCantilever: false, rightCantileverLength: 0 }; const defaultConcrete: ConcreteProperties = { fc: 3000, density: 150, slabThickness: 5.0, beamSpacing: 5.0, beamPosition: 'Interior' }; const defaultComposite: CompositeSettings = { isComposite: true, temporaryShoring: false, metalDeck: { manufacturer: 'VULCRAFT', type: '2 VLI', orientation: 'Transverse' }, shearStuds: { diameter: '3/4"', length: 4.5, fu: 65.0, studsPerRib: 1 }, partialComposite: 'calculated' }; const defaultLateralBracing: LateralBracing = { type: 'Continuous (Top)', cbFactor: 'Calculated' }; const defaultLoads: LoadConfig = { segment: 1, uniformLoads: [ { id: 'w1', full: false, start: 0, end: 0, tributaryWidth: 1.0, dead: 0, live: 0, rLive: 0, snow: 0, wind: 0, seismic: 0 } ], variableLoads: [], concentratedLoads: [], momentLoads: [], calculateSelfweight: true }; const defaultLoadCombinations: LoadCombinations = { type: 'asdip-combinations', designMethod: 'LRFD' }; export const useBeamStore = create((set, get) => ({ steel: defaultSteelProperties, geometry: defaultGeometry, concrete: defaultConcrete, composite: defaultComposite, lateralBracing: defaultLateralBracing, loads: defaultLoads, loadCombinations: defaultLoadCombinations, results: undefined, setSteelProperties: (steel) => { const current = get().steel; const updated = { ...current, ...steel }; // If designation changed, update section properties if (steel.designation && steel.designation !== current.designation) { const section = getSectionByDesignation(steel.designation); if (section) { updated.depth = section.depth; updated.width = section.width; updated.tw = section.tw; updated.tf = section.tf; updated.sx = section.sx; updated.ix = section.ix; updated.zx = section.zx; updated.weight = section.weight; } } set({ steel: updated }); }, setGeometry: (geometry) => { const current = get().geometry; const updated = { ...current, ...geometry }; // Auto-update supports and spans based on numberOfSupports if (geometry.numberOfSupports !== undefined && geometry.numberOfSupports !== current.numberOfSupports) { const numSupports = geometry.numberOfSupports; const numSpans = numSupports - 1; // Update supports const supports = Array.from({ length: numSupports }, (_, i) => ({ id: i + 1, type: (i === 0 || i === numSupports - 1) ? 'Pinned' as const : 'Pinned' as const })); // Update spans const spans = Array.from({ length: numSpans }, (_, i) => ({ id: i + 1, length: i < current.spans.length ? current.spans[i].length : 0 })); updated.supports = supports; updated.spans = spans; } set({ geometry: updated }); }, setConcreteProperties: (concrete) => { set({ concrete: { ...get().concrete, ...concrete } }); }, setCompositeSettings: (composite) => { set({ composite: { ...get().composite, ...composite } }); }, setLateralBracing: (bracing) => { set({ lateralBracing: { ...get().lateralBracing, ...bracing } }); }, setLoads: (loads) => { set({ loads: { ...get().loads, ...loads } }); }, setLoadCombinations: (combinations) => { set({ loadCombinations: { ...get().loadCombinations, ...combinations } }); }, calculate: () => { // This will trigger the calculation engine // For now, we'll set a placeholder result const state = get(); // Simple mock calculation for demonstration const mockResults = { reactions: [3.1, 3.1], shearValues: [[0, 3.1, -3.1, 0]], momentValues: [[0, 5.8, 11.7, 0]], deflections: [ { loadCase: 'CL', deflection: 0.0, lOverD: 9999, limit: 360, ratio: 0.04, pass: true }, { loadCase: 'CD+CL', deflection: 0.02, lOverD: 7856, limit: 240, ratio: 0.03, pass: true }, { loadCase: 'L', deflection: 0.0, lOverD: 9999, limit: 360, ratio: 0.04, pass: true }, { loadCase: 'D+L', deflection: 0.10, lOverD: 1768, limit: 240, ratio: 0.14, pass: true }, { loadCase: 'Lr, S, W', deflection: 0.0, lOverD: 9999, limit: 360, ratio: 0.04, pass: true } ], shear: { cv: 1.0, maxShear: 3.1, designStrength: 143.4, ratio: 0.02, pass: true }, flexureNonComposite: { lateralBracing: 'Continuous (Top)', maxMoment: 10.0, cbFactor: 3.0, designStrength: 249.4, ratio: 0.04, limitState: 'Yielding', pass: true }, flexureComposite: state.composite.isComposite ? { shearStudLength: 4.5, requiredStuds: 12, partialComposite: 25, maxMoment: 11.7, designStrength: 327.1, ratio: 0.04, pass: true } : undefined, overallPass: true }; set({ results: mockResults }); } }));