import { create } from 'zustand'; import type { PileCapGeometry, LoadInputs, MaterialProperties, DesignParameters, ReinforcementConfig, CalculationResults } from '../types/pileCap'; import { calculatePileReactions } from '../calculations/pileReactions'; import { performShearChecks } from '../calculations/shearChecks'; import { performFlexuralDesign } from '../calculations/flexuralDesign'; import { calculateLoadCombinations, getGoverningCombination } from '../calculations/loadCombinations'; import { performBearingChecks } from '../calculations/bearingChecks'; import { performColumnDesign } from '../calculations/columnDesign'; interface PileCapState { geometry: PileCapGeometry; loads: LoadInputs; materials: MaterialProperties; design: DesignParameters; reinforcement: ReinforcementConfig; results: CalculationResults | null; setGeometry: (updates: Partial) => void; setLoads: (updates: Partial) => void; setMaterials: (updates: Partial) => void; setDesign: (updates: Partial) => void; setReinforcement: (updates: Partial) => void; calculate: () => void; // Diagram State diagramState: { isLocked: boolean; labelPositions: Record; }; setDiagramLocked: (isLocked: boolean) => void; updateLabelPosition: (id: string, x: number, y: number) => void; } const defaultGeometry: PileCapGeometry = { length: 8, width: 8, depth: 24, // in soilCover: 2, columnLength: 16, columnWidth: 16, columnOffsetX: 0, columnOffsetZ: 0, pileRows: 3, pileColumns: 3, pileSpacingX: 3, pileSpacingY: 3, pileType: 'Round', pileSize: 12, pileEdgeDistance: 1.5, pileTopEmbed: 6, accidentalOffset: 3, pileCompressionCapacity: 50, pileTensionCapacity: 25, pileLateralCapacity: 10, coverTop: 3, coverBottom: 3 }; const defaultLoads: LoadInputs = { cases: [ { id: 'case-1', name: 'Load Case 1', deadLoad: 100, liveLoad: 60, roofLiveLoad: 0, snowLoad: 0, rainLoad: 0, seismicLoad: 0, windLoad: 0, momentX: 0, momentY: 0, shearX: 0, shearY: 0 } ], activeLoadCase: 'case-1' }; const defaultMaterials: MaterialProperties = { fc: 4000, fy: 60000, phiFlexure: 0.9, phiShear: 0.75, phiBearing: 0.65 }; const defaultDesign: DesignParameters = { designMethod: 'LRFD', loadCombination: '1.2D + 1.6L', codeYear: 'ACI 318-19' }; const defaultReinforcement: ReinforcementConfig = { hasTopMat: true, topConcreteCover: 3, topXBarSize: '#8', topXBarCount: 8, topXBarHooks: false, topZBarSize: '#8', topZBarCount: 8, topZBarHooks: false, hasBottomMat: true, bottomConcreteCover: 3, bottomXBarSize: '#8', bottomXBarCount: 8, bottomXBarHooks: true, bottomZBarSize: '#8', bottomZBarCount: 8, bottomZBarHooks: true, columnBarSize: '#9', columnBarCount: 8 }; export const usePileCapStore = create((set, get) => ({ geometry: defaultGeometry, loads: defaultLoads, materials: defaultMaterials, design: defaultDesign, reinforcement: defaultReinforcement, results: null, setGeometry: (updates) => { set((state) => ({ geometry: { ...state.geometry, ...updates } })); setTimeout(() => get().calculate(), 0); }, setLoads: (updates) => { set((state) => ({ loads: { ...state.loads, ...updates } })); setTimeout(() => get().calculate(), 0); }, setMaterials: (updates) => { set((state) => ({ materials: { ...state.materials, ...updates } })); setTimeout(() => get().calculate(), 0); }, setDesign: (updates) => { set((state) => ({ design: { ...state.design, ...updates } })); setTimeout(() => get().calculate(), 0); }, setReinforcement: (updates) => { set((state) => ({ reinforcement: { ...state.reinforcement, ...updates } })); }, calculate: () => { const { geometry, loads, materials, design, reinforcement } = get(); try { // Calculate all load combinations const combinations = calculateLoadCombinations(loads.cases); const governingLoad = getGoverningCombination(combinations); const pileReactions = calculatePileReactions(geometry, governingLoad, design); const maxPileReaction = Math.max(...pileReactions.map(p => p.reaction)); const minPileReaction = Math.min(...pileReactions.map(p => p.reaction)); const shearChecks = performShearChecks(geometry, pileReactions, materials, design); const { flexuralX, flexuralY } = performFlexuralDesign(geometry, pileReactions, materials, reinforcement); const bearingChecks = performBearingChecks(geometry, pileReactions, materials, governingLoad); const columnDesign = performColumnDesign(geometry, materials, reinforcement, governingLoad); const overallPass = shearChecks.every((check: { pass: boolean }) => check.pass) && flexuralX.pass && flexuralY.pass && maxPileReaction <= geometry.pileCompressionCapacity && bearingChecks.columnBearing.pass && bearingChecks.pileBearing.pass && columnDesign.pass; set({ results: { pileReactions, maxPileReaction, minPileReaction, shearChecks, flexuralX, flexuralY, bearingChecks, columnDesign, governingCombination: governingLoad.combinationName, governingCaseId: governingLoad.caseId, overallPass } }); } catch (error) { console.error('Calculation error:', error); } }, diagramState: { isLocked: true, labelPositions: {} }, setDiagramLocked: (isLocked) => { set((state) => ({ diagramState: { ...state.diagramState, isLocked } })); }, updateLabelPosition: (id, x, y) => { set((state) => ({ diagramState: { ...state.diagramState, labelPositions: { ...state.diagramState.labelPositions, [id]: { x, y } } } })); } }));