# RocketTools Architecture ## Overview RocketTools is a single-page application (SPA) built with **React + Vite**, organized into logical layers: 1. **Pages** — Route-level components 2. **Components** — Reusable UI elements 3. **Hooks** — State management & business logic 4. **Engine** — Core calculations & algorithms 5. **App.jsx** — Router configuration ## Layer Responsibilities ### Pages (`src/pages/`) Each page is a route-level component that: - Uses one or more custom hooks for state - Composes domain-specific components - Manages local UI state (modals, tabs, etc.) **Pages:** - `Home.jsx` — Landing page with feature overview - `Solver.jsx` — Equation solver workspace - `EnginePage.jsx` — Engine design tools - `RocketPage.jsx` — Vehicle design tools - `TrajectoryPage.jsx` — Flight simulation - `DocsPage.jsx` — In-app documentation - `KnowledgebaseEquationsPage.jsx` — Equation reference - `KnowledgebaseFuelsPage.jsx` — Propellant database - `KnowledgebaseAblativesPage.jsx` — Ablative materials ### Components (`src/components/`) Pure, composable UI elements that accept props and render JSX. **Solver Components:** - `Workspace.jsx` — Drop zone for constraint cards - `VariablePalette.jsx` — Draggable variable list - `VariableCard.jsx` — Input field with unit conversion - `ResultsPanel.jsx` — Results table display **Engine/Rocket Components:** - `rocket/RocketModel3D.jsx` — Three.js 3D scene - `trajectory/TrajectoryPlot.jsx` — Canvas flight path chart - `trajectory/TimelineBar.jsx` — Playback controls ### Hooks (`src/hooks/`) Custom React hooks encapsulate domain state & logic. **State Hooks:** ``` useSolver() ├─ variables: Map ├─ constraints: Map ├─ dispatch(action) └─ results: Map useEngineDesign() ├─ engineInputs: {chamberPressure, fuels, ...} ├─ engineResults: {thrust, isp, ...} ├─ setEngineInputs() └─ structureResults: {wallThickness, mass, ...} useRocketDesign() ├─ rocketInputs: {outerRadius, tankConfig, ...} ├─ rocketResults: {totalMass, twr, ...} └─ setRocketInputs() useTrajectory() ├─ config: {vehicle, engine, atmosphere, ...} ├─ playback: {time, speed, isPlaying} ├─ events: [{type, time, data}] └─ runSimulation() ``` ### Engine (`src/engine/`) Pure JavaScript modules with **zero React dependencies**. These can be: - Unit tested independently - Reused in Node.js or other environments - Debugged without UI overhead **Module Breakdown:** | File | Purpose | |------|---------| | `variables.js` | Variable catalog (name, unit, type) | | `equations.js` | Equation definitions + solvers | | `solver.js` | Constraint propagation algorithm | | `numerics.js` | Math utilities (bisection, Mach) | | `engineDesignCalcs.js` | Combustion, ablation, structure | | `rocketDesignCalcs.js` | Tank geometry, mass budget | | `trajectoryCalcs.js` | RK4 integrator, event detection | | `knowledgebaseData.js` | Material & fuel databases | ## Data Flow Patterns ### Solver Workflow ``` User Input ↓ [VariableCard updates constraint] ↓ dispatch(setConstraint) → useSolver ↓ solver.solve() → [greedy propagation] ↓ useSolver state updates ↓ [VariableCard/ResultsPanel re-render] ``` ### Engine Design Workflow ``` User Input (EnginePage) ↓ useEngineDesign.setEngineInputs() ↓ engineDesignCalcs.calcCombustion() + engineDesignCalcs.calcCooling() + engineDesignCalcs.calcStructure() ↓ useSolver state updates (memoized) ↓ [EnginePage, RocketPage re-render] ``` ### Rocket Design Workflow ``` User Input (RocketPage) ↓ useRocketDesign.setRocketInputs() ↓ rocketDesignCalcs.calcTankGeometry() + rocketDesignCalcs.calcMassBudget() + rocketDesignCalcs.noseConeProfile() ↓ useRocketDesign state updates (memoized) ↓ [RocketModel3D, RocketPage re-render] ``` ### Trajectory Simulation Workflow ``` User Config (TrajectoryPage) ↓ useTrajectory.runSimulation() ↓ trajectoryCalcs.runSimulation() [RK4 integrator loop] [Event detection] ↓ states[] + events[] returned ↓ useTrajectory state updates ↓ [TrajectoryPlot, TimelineBar re-render] ``` ## Key Design Decisions ### 1. Separation of Concerns - **Engine layer**: Pure math, no React - **Hooks layer**: State management, memoization, side effects - **Component layer**: UI rendering only - **Page layer**: Route composition, layout **Benefit**: Engine code is testable, reusable, and maintainable independently of React. ### 2. Constraint Solver as Core The solver uses **greedy constraint propagation**: - User sets constraint on a variable - Solver finds equations referencing that variable - Solves for unknowns using math or bisection - Propagates newly-computed values (recursive) **Benefit**: Intuitive UI (users see automatic computation), flexible equation network. ### 3. Three.js via React Three Fiber Rather than direct Three.js imperative API: - Use ``, ``, etc. as React components - Hooks like `useFrame()` for animations - Drei helpers for common geometries **Benefit**: Declarative, composable, integrates with React state. ### 4. Canvas for Trajectory Plotting HTML5 Canvas instead of SVG: - Handles 1000s of points efficiently - Responsive to window resize - Custom click/hover interactions **Benefit**: Performance, flexibility. ## Memoization Strategy Use `useMemo()` to avoid re-computation: ```javascript // Hook definition const engineResults = useMemo(() => { return calcCombustion(engineInputs) // only runs when engineInputs changes }, [engineInputs]) ``` **Rule**: Memoize expensive calculations; skip for cheap operations. ## State Management (No Redux) React hooks provide sufficient state management for this app: - `useState()` for local UI state - Custom hooks + `useCallback()` for complex logic - `useMemo()` for expensive computations - Props drilling is acceptable for this size **Alternative**: Could migrate to Redux/Zustand if app grows significantly. ## 3D Rendering Pipeline ``` RocketModel3D.jsx (R3F Canvas) ↓ [useRocketDesign hook provides geometry] ↓ TankSection, NoseCone components ↓ THREE.CylinderGeometry, SphereGeometry, LatheGeometry ↓ Material (MeshStandardMaterial) ↓ Lighting, OrbitControls ↓ Canvas rendered to DOM ``` ## Testing Strategy No tests currently, but recommended: **Unit Tests** (Jest): ```javascript // src/engine/__tests__/solver.test.js import { solve } from '../solver.js' test('solves linear equation', () => { const eqs = [{var: 'x', fn: (x) => 2*x - 5}] const result = solve(eqs, {y: 10}) expect(result.x).toBeCloseTo(2.5) }) ``` **Integration Tests** (React Testing Library): ```javascript // src/pages/__tests__/Solver.test.jsx import { render, screen } from '@testing-library/react' import Solver from '../Solver' test('Solver page renders', () => { render() expect(screen.getByText(/Equation Solver/i)).toBeInTheDocument() }) ``` ## Performance Considerations 1. **Memoization** — Expensive calculations in `useMemo()` 2. **Lazy Loading** — Routes loaded on-demand (React Router) 3. **Canvas Rendering** — 60 FPS for trajectory animation 4. **Variable Updates** — Solver propagation is greedy (stops early) **Potential Bottlenecks:** - Large variable networks (100+ equations) - Complex 3D geometries (reduce polygon count) - Trajectory with 1000s of timesteps (reduce accuracy or cache) ## File Organization Best Practices - **One component per file** (except tiny helpers) - **Colocate tests** with source (`__tests__` subfolder) - **Group by domain** (rocket, trajectory, solver) not by type - **Keep hooks small** (< 50 lines of logic) - **Engine code** has zero dependencies on React or UI ## Extension Points ### Adding a New Page 1. Create `src/pages/NewPage.jsx` 2. Add route in `App.jsx` 3. Add NavLink if needed ### Adding a New Feature Module 1. Create hook: `src/hooks/useNewFeature.js` 2. Create components: `src/components/NewFeature*.jsx` 3. Add calculations to `src/engine/` if needed 4. Create page: `src/pages/NewFeaturePage.jsx` ### Adding Material Properties 1. Edit `src/engine/knowledgebaseData.js` 2. Add to `FUELS`, `ABLATIVES`, or `STRUCTURAL_MATERIALS` array 3. Auto-appears in UI --- **Last Updated**: 2025-02 | **Status**: Current (v3)