Trajectories
This commit is contained in:
308
docs/ARCHITECTURE.md
Normal file
308
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# 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<id, value>
|
||||
├─ constraints: Map<id, constraint>
|
||||
├─ dispatch(action)
|
||||
└─ results: Map<id, solvedValue>
|
||||
|
||||
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 `<Canvas>`, `<Mesh>`, 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(<Solver />)
|
||||
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)
|
||||
Reference in New Issue
Block a user