chore: initial project setup (README, index.html, package.json, vite.config, .gitignore, .oxlintrc.json, public, src, .hermes)

This commit is contained in:
JARVIS
2026-07-27 17:56:10 +00:00
parent c449352d3c
commit 42cc719e24
30 changed files with 4407 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
@@ -0,0 +1,200 @@
# Product Requirements Document (PRD)
## Scientific Calculator with Conversion & History
**Version:** 1.0.0
**Date:** 2026-07-26
**Prepared by:** Turing (Documentation Specialist, Hermes Agent)
**Based on:** Ideation output from Steve (Feasibility/Viability Research)
**Stakeholder:** Shreyas Kamat (SRMIST CSE Student, Hybrutos Racing & vACC Leadership)
---
## 1. Executive Summary
This document outlines the requirements for a standalone scientific calculator application built to evaluate the Hermes Agent multi-agent framework. The calculator will provide advanced mathematical operations, unit conversions, currency conversions, and calculation history tracking with a modern, animated dark-theme UI. It is intended as a local testing utility only, with no planned integration into existing projects (Hybrutos Battery Cart, vACC event management, or homelab systems).
**Primary Goal:** Validate the Hermes Agent multi-agent architecture by delivering a feature-rich, polished ReactJS application through the prescribed phased development process (Ideation → Planning → Orchestration → Development → Independent Test & Review → Deployment).
---
## 2. Functional Requirements
### 2.1 Core Calculation Engine
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| F1.1 | Support basic arithmetic: addition, subtraction, multiplication, division | Must | Standard infix notation |
| F1.2 | Support scientific functions: sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, exp, log (base 10), ln (natural), sqrt, cbrt, abs, ceil, floor, round, random | Must | Standard mathematical implementations |
| F1.3 | Support combinatorial functions: factorial (n!), nCr (combinations), nPr (permutations) | Must | Factorial limited to n ≤ 170 to prevent overflow |
| F1.4 | Support parentheses for order of operations | Must | Standard precedence rules |
| F1.5 | Support decimal point input and floating-point arithmetic | Must | Standard calculator behavior |
| F1.6 | Handle division by zero gracefully (display "Error") | Must | Prevent application crash |
| F1.7 | Support persistent calculation history (store last 50 operations) | Should | Saved to localStorage, retrievable across sessions |
| F1.8 | Allow reuse of history items in new calculations | Should | Click-to-insert functionality |
| F1.9 | Provide clear (AC) and backspace (CE) functionality | Must | Standard calculator controls |
### 2.2 Conversion Systems
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| F2.1 | Support unit conversions for: length (mm, cm, m, km, in, ft, yd, mi), mass (mg, g, kg, oz, lb), temperature (°C, °F, K), volume (ml, l, tsp, tbsp, fl oz, cup, pt, qt, gal) | Should | Bidirectional conversion between all units in category |
| F2.2 | Support currency conversions for: INR, USD, GBP, EUR, JPY, CAD, AUD | Should | Manual exchange rate input (no live API calls for framework testing) |
| F2.3 | Allow chaining of conversions (e.g., convert 5 ft to inches, then to cm) | Could | Optional enhancement |
| F2.4 | Display conversion results with appropriate precision (typically 4 decimal places) | Should | Consistent formatting |
### 2.3 User Interface & Experience
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| F3.1 | Implement dark theme as default (with optional light theme toggle) | Must | Dark background (#121212), light text (#E0E0E0), accent color (#FF9800) |
| F3.2 | Provide fluid, animated UI transitions (button presses, screen changes) | Must | Using Framer Motion or CSS animations (200-300ms duration) |
| F3.3 | Support full keyboard input: numbers (0-9), operators (+,-,*,/,=,.), Enter (=), Escape (AC), Backspace (CE) | Must | Standard calculator keyboard mapping |
| F3.4 | Implement responsive layout: functional on mobile (≥320px width), tablet, and desktop | Should | Single-column keypad on narrow screens, grid on wider |
| F3.5 | Display current expression/formula in a secondary line above main result (optional) | Could | For complex multi-step calculations |
| F3.6 | Provide visual feedback for invalid operations (e.g., shaking display, error color) | Should | Enhances usability |
### 2.4 Application Behavior
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| F4.1 | Launch directly to calculator interface (no splash screen or onboarding) | Must | Immediate usability for testing |
| F4.2 | Preserve state (display, history, theme) on page refresh/revisit | Should | Via localStorage |
| F4.3 | Provide reset function to clear all state (history, display, theme to default) | Could | Advanced user option |
| F4.4 | Ensure no external network calls during operation (fully offline capable) | Must | Critical for security and framework isolation testing |
---
## 3. Non-Functional Requirements
### 3.1 Performance
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| NF1.1 | Maintain 60 FPS during animations and interactions | Must | Smooth user experience |
| NF1.2 | Calculation result latency < 100ms for standard operations | Must | Imperceptible delay |
| NF1.3 | Initial load time < 3s on mid-tier device (simulated via throttling) | Should | Acceptable for testing utility |
### 3.2 Security & Reliability
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| NF2.1 | Sanitize all user input to prevent XSS/injection attacks | Must | Critical for Gilfoyle's security review (expression parser) |
| NF2.2 | Validate all numerical inputs for finiteness (no NaN/Infinity propagation unless intentional) | Must | Prevent calculation errors |
| NF2.3 | LocalStorage usage limited to history and theme preferences (<50KB) | Should | Minimal storage footprint |
| NF2.4 | Application state recoverable from localStorage corruption (fallback to defaults) | Should | Graceful degradation |
### 3.3 Maintainability & Extensibility
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| NF3.1 | Modular code structure: separate modules for math, conversion, history, UI, theme | Must | Enables parallel development by specialists |
| NF3.2 | Clear separation of concerns: calculation logic independent of UI | Must | Facilitates testing and replacement |
| NF3.3 | Consistent code style (ESLint + Prettier configuration) | Should | Team collaboration readiness |
| NF3.4 | Comprehensive JSDoc comments for all public functions and components | Should | Onboarding and maintenance aid |
### 3.4 Compatibility
| ID | Requirement | Priority | Notes |
|----|-------------|----------|-------|
| NF4.1 | Support latest stable versions of Chrome, Firefox, Safari, Edge | Must | Broad accessibility for testing |
| NF4.2 | Require JavaScript ES2020+ support | Should | Modern language features |
| NF4.3 | No dependencies on native mobile features (pure web app) | Must | Framework isolation guarantee |
---
## 4. Assumptions & Dependencies
### 4.1 Assumptions
- User is familiar with basic calculator operations and scientific notation
- Manual currency exchange rate input is acceptable for framework testing purpose
- LocalStorage availability is guaranteed in target testing environments
- No accessibility compliance (WCAG) required beyond basic keyboard support (per scope)
- Theme toggle (dark/light) is optional; dark theme is mandatory default
### 4.2 Dependencies
| Dependency | Version | Purpose | License |
|------------|---------|---------|---------|
| React | 18.2.0 | UI library | MIT |
| Vite | 4.3.0 | Build tool & dev server | MIT |
| Framer Motion | 10.12.0 | Animations | MIT |
| CSS Modules | Built-in (via Vite) | Scoped styling | MIT |
| (Optional) date-fns | 2.29.3 | Date formatting for history timestamps | MIT |
*Note: Exact versions to be finalized during planning phase; all dependencies must be free/OSS compliant.*
### 4.3 Excluded Features (Out of Scope)
- Live currency exchange rate API calls (to avoid network dependencies and API key management)
- Graphing capabilities
- Base conversion (binary, octal, hexadecimal)
- Statistical functions (mean, median, standard deviation)
- Programmable macros or user-defined functions
- Cloud synchronization or account-based features
- Voice input/output
- Printing or export functionality
---
## 5. Acceptance Criteria
The implementation will be considered complete and ready for independent review when:
### 5.1 Functional Verification
- [ ] All core calculation operations (F1.1-F1.5) produce correct results for test suite
- [ ] Scientific functions (F1.2) match JavaScript Math object precision within 1e-10
- [ ] Factorial/nCr/nPr (F1.3) handle edge cases (0, 1, large numbers) correctly
- [ ] History system (F1.7-F1.8) stores, retrieves, and re-uses entries accurately
- [ ] Unit conversions (F2.1) are accurate to 4 decimal places for standard conversions
- [ ] Currency conversions (F2.2) use manual rates correctly
- [ ] Keyboard support (F3.3) maps all required keys to appropriate functions
- [ ] Dark theme (F3.1) is default with correct color palette
- [ ] Animations (F3.2) are present and smooth (no jank)
- [ ] Responsiveness (F3.4) maintains usability at 320px width
- [ ] No external network requests occur during operation (verified via DevTools)
### 5.2 Security Verification (Gilfoyle's Mandatory Review)
- [ ] Expression parser sanitizes all non-numeric/non-operator input
- [ ] No use of `eval()` or equivalent unsafe evaluation methods
- [ ] All user-inputted strings are properly escaped before DOM insertion
- [ ] LocalStorage keys are namespaced to prevent collisions
- [ ] Error messages do not leak stack traces or system information
### 5.3 Performance Verification
- [ ] Animation frame rate ≥ 55 FPS during continuous FPS (measured via Chrome DevTools)
- [ ] 95th percentile calculation latency < 50ms for operations ≤ 20 characters
- [ ] Initial load time < 2.5s on Moto G4 (Simulated 3G) throttling profile
### 5.4 Usability Verification
- [ ] All core functions accessible via keyboard alone
- [ ] Touch targets ≥ 48x48px on mobile layouts
- [ ] Clear visual distinction between operator and operand buttons
- [ ] History panel accessible via intuitive gesture/click
- [ ] Error states provide clear recovery path (e.g., "Press AC to reset")
### 5.5 Code Quality Verification (Satya/Sundar's Independent Review)
- [ ] No ESLint errors (configured for React best practices)
- [ ] Test coverage ≥ 80% for utility functions (math, conversion, history)
- [ ] All components have corresponding unit tests
- [ ] Code follows consistent formatting (Prettier)
- [ ] No console warnings/errors in development mode
---
## 6. Open Questions & Risks
| ID | Question/Risk | Impact | Mitigation Strategy |
|----|---------------|--------|---------------------|
| OQ1 | Should currency conversion support automatic rate fetching via API? | Low (explicitly out of scope per user) | Document as future enhancement; current design uses manual input |
| OQ2 | Is animation library (Framer Motion) acceptable, or should we use CSS-only for minimal dependencies? | Medium | Evaluate during planning; CSS-only fallback available |
| OQ3 | What precision should be displayed for irrational results (e.g., pi, sqrt(2))? | Low | Display 10 significant figures; full precision available in history |
| OQ4 | Should history support search/filter functionality? | Low | Document as potential Phase 2 enhancement |
| Risk1 | Expression parser complexity introducing bugs | High | Implement comprehensive unit tests; use Shunting Yard algorithm for robustness |
| Risk2 | Animation performance on low-end devices | Medium | Provide reduced-motion preference; test on throttled profiles |
| Risk3 | LocalStorage quota exceeded with heavy history use | Low | Implement history limit (50 entries) with FIFO eviction |
---
## 7. References & Related Documents
- [Ideation Notes] Steve's feasibility assessment (Telegram log: 2026-07-26_202906_deleg_380b1ff7)
- [Framework Constraints] Hermes Agent Multi-Agent Architecture Specification
- [Technical Spike] Initial React/Vite setup validation (calculator prototype in /root/calculator/)
- [Security Guidelines] OWASP JavaScript Security Cheat Sheet (input sanitization focus)
---
**Approval Status:**
✅ **PRD Complete** - Awaiting review transition to Ada (Design & Planning Specialist) for iterative back-and-forth until plan is fully detailed, followed by formal stakeholder approval before proceeding to Woz (Orchestrator) for specialist task distribution.
*This document satisfies Turing's documentation responsibility per the Hermes Agent multi-agent architecture. Subsequent phases will follow the prescribed gated process with explicit user approvals at each transition.*
---
*End of PRD*
@@ -0,0 +1,997 @@
# Solution Architecture Document (SAD)
## Scientific Calculator with Conversion & History
**Version:** 1.0.0
**Date:** 2026-07-27
**Prepared by:** Turing (Documentation Specialist, Hermes Agent)
**Based on:** Approved Technical Implementation Plan by Ada (Design & Planning Specialist)
**Stakeholder:** Shreyas Kamat (SRMIST CSE Student, Hybrutos Racing & vACC Leadership)
---
## 1. Introduction
This document describes the solution architecture for a standalone scientific calculator application designed to evaluate the Hermes Agent multi-agent framework. The calculator provides advanced mathematical operations (including numerical methods), unit conversions, currency conversions, and calculation history tracking with a modern, animated dark-theme UI.
**Primary Purpose**: Validate the Hermes Agent multi-agent architecture by delivering a feature-rich, polished ReactJS application through the prescribed phased development process (Ideation → Planning → Orchestration → Development → Independent Test & Review → Deployment).
**Scope**: Local testing utility only—no planned integration into existing projects (Hybrutos Battery Cart, vACC event management, or homelab systems).
---
## 2. System Architecture Overview
### 2.1 Architectural Style
- **Single-Page Application (SPA)** built with React 18
- **Client-side only** application with zero server dependencies
- **Modular, component-based architecture** with clear separation of concerns
- **Unidirectional data flow** principles applied where beneficial (state updates via Context API)
### 2.2 Key Architectural Decisions
| Decision | Rationale |
|----------|-----------|
| **React 18 + Vite** | Modern, performant stack with fast refresh; ideal for framework evaluation |
| **Context API for State Management** | Stakeholder preference; avoids external libraries (Redux/Zustand) for appropriate scope |
| **CSS Modules for Styling** | Scoped styling eliminates class collisions; no runtime overhead |
| **Framer Motion for Animations** | Best balance of features, bundle size, and ease of use for complex UI motions |
| **localStorage Persistence** | Simple, reliable persistence for history/theme; matches stakeholder requirements |
| **Expression Parser First** | Security-critical component developed with Gilfoyle's review embedded from start |
| **Unified `convert()` Syntax** | Reduces cognitive overload; single function for unit/currency conversions |
| **Keyboard-First UI/UX** | Matches stakeholder's workflow preferences for efficiency |
| **Pure JS Core Modules** | Math engine, conversion systems, history manager are testable in isolation |
### 2.3 System Boundaries
- **In Scope**:
- Mathematical expression evaluation (scientific functions + numerical methods)
- Unit conversion (8 predefined categories)
- Currency conversion (manual-rate based)
- Calculation history (persistent, click-to-reuse)
- Dark/light theme system with animations
- Full keyboard support
- Responsive layout (mobile/tablet/desktop)
- **Out of Scope**:
- Live API calls (currency rates, unit databases)
- User accounts or cloud synchronization
- Graphing capabilities
- Programmable macros or user-defined functions
- Printing or export functionality
- Base conversion (binary/octal/hex)
- Voice input/output
---
## 3. Component Architecture
### 3.1 High-Level Component Diagram
```
┌─────────────────────────────────────────────────────┐
│ Calculator App │
├───────────────┬─────────────────────────────────────┤
│ Contexts │ UI │
│ ┌─────────┐ │ ┌─────────────────────────────┐ │
│ │ThemeCtx │ │ │ Display Bar │ │
│ │ModeCtx │ │ │ (expression + result) │ │
│ │CalcCtx │ │ │ Keypad Grid │ │
│ └─────────┘ │ │ ┌───────────────────────┐ │ │
│ │ │ │ Standard Mode │ │ │
│ ┌─────────┐ │ │ │ Scientific Mode │ │ │
│ │ Core │ │ │ │ Unit Conv. Mode │ │ │
│ │ Math Eng│ │ │ │ Currency Conv. Mode │ │ │
│ │Conver. │ │ │ └───────────────────────┘ │ │
│ │History │ │ │ History Panel │ │
│ └─────────┘ │ │ (slide-in / modal) │ │
│ └─────────┘ └─────────────────────────────┬─┴─────────────────────────────┬─┘
│ │ │ │
└─────────────────┴─────────────┴─────────────────┘
│ │ │
┌─────┴─────┐ ┌───────┴───────┐ ┌─────┴─────┐
│ Utils │ │ Animations │ │ Styles │
│ Keyboard │ │ Button Press │ │ CSS Mods │
│ Validator │ │ Screen Trans. │ │ Theme Vars│
│ Formatter │ │ Toast │ │ Resp. Breakpts│
└───────────┘ └───────────────┘ └───────────┘
```
### 3.2 Core Module Specifications
#### 3.2.1 Math Engine (`src/core/math/`)
- **ExpressionParser.js**:
- Input: Raw user expression string
- Process:
1. Allowlist validation (digits, `.`, `+-*/()`, whitespace, `e`, `pi`, whitelisted func names)
2. Constant substitution (`pi`→`Math.PI`, `e`→`Math.E`, `ans`→history value)
3. Function whitelisting + replacement (`sin(`→`Math.sin(`)
4. Safe evaluation via `Function` constructor on sanitized string
- Output: `{value: number, error: string}` or `{value: null, error: string}`
- Security: Single validation/sanitization point; no `eval`; Gilfoyle-reviewable
- **ScientificFunctions.js**:
- Export: Object mapping function names to implementations
- Includes: Trig, hyperbolic, exp/log, sqrt/cbrt, abs/ceil/floor/round, factorial/nCr/nPr, random
- **NumericalMethods.js** (extends core):
- `derivative(expr, var, [h])`: Central difference with `h=1e-5` default
- `integral(expr, var, a, b, [n])`: Adaptive Simpson's Rule, `tol=1e-6`, `maxSubdiv=2^10`
- `solve(expr, var, [guess])`: Newton-Raphson with secant fallback, `maxIter=100`, `tol=1e-10`
#### 3.2.2 Conversion Systems (`src/core/conversion/`)
- **UnitConverter.js**:
- Input: `value`, `fromUnit`, `toUnit`
- Process:
1. Validate units against category-specific whitelist
2. Lookup conversion factor from hardcoded table
3. Compute: `value × (factor_to / factor_from)`
4. Special handling: Temperature offset scales (K↔°C↔°F)
- Output: Converted value (number) or error string
- **CurrencyConverter.js**:
- Input: `value`, `fromCurrency`, `toCurrency`
- Process:
1. Validate 3-letter uppercase currency codes
2. Lookup rate from internal table (manual entry)
3. Compute: `value × (rate_to / rate_from)`
4. Auto-handles inverse rates
- Output: Converted value (number) or error string
- **ExchangeRateService.js**:
- Manages rate table in localState with timestamps
- Provides: getRate, setRate, getDefaultRates, isRateStale
- **UnitDefinitions.js**:
- Hardcoded conversion factors for all units in each category
- Organized by category (electrical, mechanical, etc.)
#### 3.2.3 History Manager (`src/core/history/`)
- **HistoryManager.js**:
- Storage: `localStorage` keyed as `calc_history`
- Structure: Array of `{expression: string, result: string|number, timestamp: number}`
- Capacity: Fixed at 50 entries (FIFO eviction on overflow)
- Operations: addEntry, getHistory, clearHistory, removeEntry(index)
- Corruption Recovery:
- On read: Validate JSON structure and types
- On failure: Return empty array (fresh start)
- On version mismatch: Reset to defaults (if versioning added later)
- **useHistory.js** (custom hook):
- Provides: `history`, `addToHistory`, `clearHistory`, `removeFromHistory`
- Auto-saves to localStorage on update
#### 3.2.4 Theme System (`src/theme/`)
- **ThemeContext.js**:
- State: `{theme: 'dark'|'light', transitioning: boolean}`
- Provider: Wraps app to distribute theme state
- Updater: `setTheme` + `startTransition`/`endTransition` for animations
- **themes.js**:
- Defines CSS variables for both themes:
- Dark: `--bg-primary: #121212; --text-primary: #E0E0E0; --accent: #FF9800;`
- Light: `--bg-primary: #FFFFFF; --text-primary: #212121; --accent: #FB8C00;`
- **useTheme.js** (custom hook):
- Returns: `[theme, setTheme, isTransitioning]`
- Handles transition state for motion coordination
#### 3.2.5 Mode System (`src/contexts/`)
- **ModeContext.js**:
- State: `'standard'|'scientific'|'unit'|'currency'`
- Determines: Which keypad mode to render
- Updater: `setMode` (called by mode-switching buttons)
### 3.3 UI Component Specifications
#### 3.3.1 Display Bar (`src/components/display/`)
- **Display.jsx**:
- Props: `expression`, `result`, `isError`, `highlightSyntax` (boolean)
- Features:
- Main result display (large, monospace font)
- Optional secondary expression line (smaller, muted)
- Real-time syntax highlighting (valid=green, invalid=red)
- Error state: Shows "Error" + optional shake animation
- Accessibility: `role="textbox"`, `aria-live="polite"` for result changes
- **Display.module.css**:
- Base styling: Dark background, light text, monospace font
- Animation: Shake keyframes for error feedback
- Responsive: Font size scales with viewport width
#### 3.3.2 Button System (`src/components/button/`)
- **Button.jsx**:
- Props: `label`, `variant` (`number`|`operator`|`function`|`conversion`|`special`), `onClick`, `isDisabled`
- Features:
- Consistent sizing (aspect ratio 1:1, border-radius 50%)
- Variant-based styling (colors, hover effects)
- Press animation (scale + background change)
- Tooltip support (via `title` prop or separate Tooltip component)
- Accessibility: `aria-label` derived from label or prop
- **Button.module.css**:
- Shared styles: Transition effects, hover/active states
- Variants:
- `number`: `#fff` background, `#333` text
- `operator`: `#ff9500` background, `#fff` text
- `function`: `#e0e0e0` background, `#333` text
- `conversion`: `#90caf9` background, `#0d47a0` text (distinct but harmonious)
- `special` (AC/CE): `#f44336` background, `#fff` text
#### 3.3.3 Keypad System (`src/components/keypad/`)
- **Keypad.jsx**:
- Props: `mode` (from ModeContext), `onButtonPress` (callback)
- Function: Renders appropriate mode-specific keypad grid
- Modes:
- `Standard`: Basic arithmetic + AC/CE
- `Scientific`: Trig, log, exp, sqrt, x^y, parentheses, ans
- `Unit`: Common unit conversions (predefined pairs)
- `Currency`: Common currency conversions (predefined pairs)
- Layout: Responsive CSS grid (auto-adapts columns based on viewport)
- **mode-specific files** (`StandardMode.jsx` etc.):
- Define button labels and variants for that mode
- Easy to extend/modify per category
#### 3.3.4 History Panel (`src/components/history/`)
- **HistoryPanel.jsx**:
- Props: `history` (array), `onHistorySelect` (callback)
- Features:
- Slide-in panel from right (desktop ≥768px)
- Full-screen modal (mobile <768px)
- List of history items (most recent first)
- Each item: Shows full expression and result
- Interactions: Tap to re-use, swipe/slide to delete
- Header: "History" + clear all button
- Empty state: "No history yet"
- **HistoryItem.jsx**:
- Displays: `{expression} = {result}` with timestamp (with optional: Copy to clipboard icon
- **HistoryPanel.module.css**:
- Slide-in animation (Framer Motion or CSS)
- List styling with dividers
- Action buttons (re-use, delete)
- Responsive adjustments for mobile/fullscreen
### 3.4 Utility Modules
#### 3.4.1 Keyboard Handler (`src/utils/KeyboardHandler.js`)
- Responsibilities:
- Maps physical keys to calculator actions
- Handles: numbers 0-9, operators (+-*/=.), Enter (=), Escape (AC), Backspace (CE)
- Advanced: Arrow keys for history navigation (↑/↓)
- Prevents default behavior where appropriate (e.g., Enter in form)
- Output: Calls registered callbacks for:
- `onDigit(char)`
- `onOperator(char)`
- `onDecimal()`
- `onEnter()` → triggers `=`
- `onEscape()` → triggers `AC`
- `onBackspace()` → triggers `CE`
- `onArrowUp()` → history previous
- `onArrowDown()` → history next
#### 3.4.2 Validator (`src/utils/Validator.js`)
- Centralized validation logic (though expression parser handles its own)
- Includes:
- `isValidUnit(unit, category)` → boolean
- `isValidCurrencyCode(code)` → boolean (regex: `^[A-Z]{3}$`)
- `isValidExpressionChars(str)` → boolean (expression allowlist check)
#### 3.4.3 Formatter (`src/utils/Formatter.js`)
- Formats numbers for display:
- `formatNumber(num, opts)` → string
- Options: `precision` (significant figures), `notation` (`standard`|`scientific`), `unit` (string)
- Handles: Large/small numbers (scientific notation threshold)
- Ensures: Consistent decimal/comma handling per locale (if needed later)
### 3.5 Animation System (`src/animations/`)
- **index.js**: Exports all animation variants for easy import
- **buttonPress.js**:
- `pressVariant`: { scale: [1, 0.95, 1], backgroundColor: ['#fff', '#e9e9e9', '#fff'] }
- `pressVariantOperator`: { scale: [...], backgroundColor: ['#ff9500', '#ffb14d', '#ff9500'] }
- **screenTransition.js**:
- `fadeIn`: { opacity: [0, 1], transition: { duration: 0.3 } }
- `slideInRight`: { x: ['100%', '0%'], transition: { duration: 0.3, type: 'spring', stiffness: 300 } }
- `slideOutLeft`: { x: ['0%', '-100%'], transition: { duration: 0.3, type: 'spring', stiffness: 300 } }
- **toastNotification.js**:
- For temporary feedback (e.g., "Rate updated", "History cleared")
- Variants: `slideUp`, `fade`, `scale`
### 3.6 Styles (`src/styles/`)
- **globals.css**:
- Base styles: box-sizing, font-smoothing, root font-size
- CSS variable definitions (referenced by themes.js)
- Reset: margin, padding, list-style
- **themes.js**:
- Defines `:root` and `[data-theme="dark"]` variable overrides
- Enables theme switching via document.documentElement.dataset.theme
- **responsive.css**:
- Media queries for breakpoints: 480px (phone), 768px (tablet/desktop)
- Adjusts: keypad grid columns, display font sizes, panel dimensions
- Touch target enhancements: ≥48px for mobile
### 3.7 Application Entry Points
- **src/main.jsx**:
- React 18 entry point
- Wraps `<App />` in:
- `React.StrictMode` (for development helper warnings)
- `ThemeContext.Provider`
- `ModeContext.Provider`
- `CalculationContext.Provider`
- **src/App.jsx**:
- Top-level layout
- Structure:
```jsx
function App() {
return (
<div className={styles.app}>
<ThemeConsumer>
{({ theme, isTransitioning }) => (
<>
<Header theme={theme} isTransitioning={isTransitioning} />
<MainContent theme={theme} />
<Footer theme={theme} />
</>
)}
</ThemeConsumer>
</div>
);
}
```
- `MainContent` contains: Display Bar, Keypad Grid, History Panel (conditionally rendered)
- `Header`: Optional app name/logo/theme toggle
- `Footer`: Version info, credits, links to documentation
---
## 4. Data Flow
### 4.1 Data Flow Principles
- **State as Single Source of Truth**: All UI derives from React state (local + context)
- **Immutable Updates**: State never mutated directly; always replaced via setState/useReducer
- **Unidirectional where possible**: User action → state update → UI re-render
- **Local Effects**: Side effects (localStorage, animations) handled in useEffect/useLayoutEffect
- **No Prop Drilling Deeply**: Context used for truly global state (theme, mode, calc/history)
### 4.2 Detailed Data Flows
#### 4.2.1 Expression Evaluation Flow
```mermaid
sequenceDiagram
participant User
participant UI as UI Layer (Display/Keypad)
participant Expr as Expression Parser
participant Calc as Calculation Context
participant Hist as History Manager
participant LS as localStorage
User->>UI: Types "2+2*3" or clicks buttons
UI->>Expr: sendRawInput("2+2*3")
Expr->>Expr: validateAllowlist(input) → true/false
alt valid
Expr->>Expr: substituteConstants(input) → "2+2*3"
Expr->>Expr: replaceFunctions(input) → "2+2*3" (no funcs here)
Expr->>Expr: evaluateViaFunction(sanitized) → {value: 8, error: null}
Expr->>Calc: sendResult({value: 8, error: null})
Calc->>Calc: updateState({display: "8", history: [...]} )
Calc->>Hist: addToHistory({expr: "2+2*3", result: "8"})
Hist->>LS: writeHistory(historyArray)
Calc->>UI: updateDisplay("8")
UI->>User: Show "8" in display
else invalid
Expr->>Calc: sendError("Invalid expression")
Calc->>UI: showErrorState()
UI->>User: Show "Error" + shake animation
end
```
#### 4.2.2 Unit Conversion Flow
```mermaid
sequenceDiagram
participant User
participant UI as UI Layer
participant Conv as UnitConverter
participant Calc as Calculation Context
participant Hist as History Manager
participant LS as localStorage
User->>UI: Types "convert(100, 'V', 'mV')"
UI->>Conv: sendRawInput("convert(100, 'V', 'mV')")
Conv->>Conv: parseConvertInput(input) → {value:100, from:'V', to:'mV'}
Conv->>Conv: validateUnits('V', 'mV') → true (both in Electrical)
Conv->>Conv: lookupFactor('V') → 1
Conv->>Conv: lookupFactor('mV') → 0.001
Conv->>Conv: compute → 100 * (0.001 / 1) = 0.1 → wait, correction:
actually: value * (factor_to / factor_from)
= 100 * (0.001 / 1) = 0.1? No:
Factor definition: 1 V = 1000 mV → factor_V = 1, factor_mV = 0.001?
Better: Store factor as "units per base unit"
Let base = 1 V
Then: factor_V = 1 (1 V per base V)
factor_mV = 1000 (1000 mV per base V)
Conversion: value_in_from * (factor_from / factor_to)
100 V * (1 / 1000) = 0.1 kV? Still wrong.
Correct approach:
Define factor as "multiplier to get to base unit"
Let base = 1 V
Then: 1 V = 1 * base → factor_V = 1
1 mV = 0.001 * base → factor_mV = 0.001
To convert from V to mV:
value_in_base = value_from * factor_from
value_to = value_in_base / factor_to
Example: 100 V
value_in_base = 100 * 1 = 100 V-base
value_to = 100 / 0.001 = 100,000 mV
So: result = value * (factor_from / factor_to)
For V→mV: 100 * (1 / 0.001) = 100,000 ✓
Conv->>Conv: computeResult → 100000
Conv->>Calc: sendResult({value: 100000, error: null})
Calc->>Calc: updateState({display: "100000", history: [...]})
Calc->>Hist: addToHistory({expr: "convert(100, 'V', 'mV')", result: "100000"})
Hist->>LS: writeHistory(historyArray)
Calc->>UI: updateDisplay("100000")
UI->>User: Show "100000" in display
```
#### 4.2.3 History Re-use Flow
```mermaid
sequenceDiagram
participant User
participant UI as UI Layer (HistoryPanel)
participant Hist as History Manager
participant Calc as Calculation Context
User->>UI: Clicks history item "derivative(sin(x), x, 0) = 1"
UI->>Hist: getHistoryItem(index) → {expr: "derivative(sin(x), x, 0)", result: "1"}
UI->>Calc: sendHistorySelect(expr: "derivative(sin(x), x, 0)")
Calc->>Calc: insertAtCursor("derivative(sin(x), x, 0)")
Calc->>UI: updateDisplay("derivative(sin(x), x, 0)")
UI->>User: Shows "derivative(sin(x), x, 0)" in expression bar
User->>User: Continues typing or presses "="
```
#### 4.2.4 Theme Toggle Flow
```mermaid
sequenceDiagram
participant User
participant UI as UI Layer (Theme Toggle Button)
participant TCtx as Theme Context
participant Doc as Document Object
participant UIComp as UI Components
User->>UI: Clicks theme toggle button
UI->>TCtx: dispatch(setTheme('light')) // if was dark
TCtx->>TCtx: updateState({theme: 'light', transitioning: true})
TCtx->>UIComp: propagate new theme state
UIComp->>UIComp: re-render with light theme styles
TCtx->>Doc: set document.documentElement.dataset.theme = 'light'
Doc->>Doc: Apply CSS variable overrides from [data-theme="light"]
TCtx->>TCtx: After 300ms (CSS transition duration), set transitioning: false
TCtx->>UIPropagate: final state (transitioning: false)
```
---
## 5. Technology Stack Justification
### 5.1 Core Choices
| Technology | Choice | Justification |
|------------|--------|---------------|
| **React 18** | ✅ | Industry standard, concurrent rendering features, rich ecosystem, matches stakeholder's implicit web focus |
| **Vite 4.3** | ✅ | Lightning-fast dev server, native ES modules, optimized build; superior to CRA for iteration speed |
| **CSS Modules** | ✅ | Scoped styling eliminates global CSS issues; no runtime overhead; excellent IDE support |
| **Framer Motion 10.12** | ✅ | Declarative animations, gesture support, layout sharing, smaller than alternatives (e.g., react-spring) |
| **localStorage** | ✅ | Simple, reliable, no setup; matches stakeholder's "NO" to complex persistence; 5MB limit sufficient for history/theme |
| **JavaScript (ES2020+)** | ✅ | Modern language features (optional chaining, nullish coalescing, etc.); all target browsers support |
### 5.2 Why Not Alternatives?
- **Redux Toolkit / Zustand**: Overkill for this scope; Context API + useReducer sufficient for 3-4 global state slices
- **Styled Components**: Runtime overhead; CSS Modules provide same scoping with build-time extraction
- **Tailwind CSS**: Utility-first approach less suitable for complex component states and themes
- **Fusion/Zustand for Animation**: Framer Motion specifically designed for UI animations with React
- **IndexedDB**: Overly complex for simple history/theme persistence; localStorage adequate
- **Express.js Backend**: Violates stakeholder's "standalone utility" and "no integration" requirements; adds unnecessary complexity
### 5.3 Dependency Audit (All OSS/Free)
| Dependency | Version | License | Purpose |
|------------|---------|---------|---------|
| react | 18.2.0 | MIT | UI library |
| react-dom | 18.2.0 | MIT | DOM bindings |
| vite | 4.3.0 | MIT | Build tool & dev server |
| framer-motion | 10.12.0 | MIT | Animations |
| (CSS Modules via Vite) | built-in | MIT | Scoped styling |
| (Optional) date-fns | 2.29.3 | MIT | Date formatting for history timestamps |
*All dependencies are free, open-source, and commercially friendly—no licensing concerns for framework evaluation.*
---
## 6. Security Architecture
### 6.1 Threat Model
**Assets to Protect**:
- User input data (expressions, conversion parameters)
- LocalStorage contents (history, theme, rates)
- DOM integrity (prevent XSS)
- Application logic integrity (prevent code injection)
**Threat Agents**:
- Malicious user (attempting XSS, code injection)
- Compromised localStorage (corruption, tampering)
- Supply chain (dependency vulnerabilities—mitigated by OSS audit)
### 6.2 Security Controls
#### 6.2.1 Input Sanitization (Primary Defense)
- **Single Point of Validation**: All user input flows through the Expression Parser's allowlist
- **Allowlist Approach**:
- Permitted: `[0-9]`, `.`, `+-*/()`, whitespace, `e`, `pi`, whitelisted function names
- **Everything else rejected immediately**
- No attempt to "filter out bad"—default deny
- **Function Whitelisting**:
- Only predefined mathematical/scientific functions allowed
- Replacement with safe `Math.func` equivalents before evaluation
- **Constant Safety**:
- `pi` and `e` mapped to immutable `Math.PI`/`Math.E`
- `ans` validated as numeric before substitution
- **Evaluation Context**:
- `Function` constructor used **only** on fully sanitized string
- Never `eval`; never direct string execution
- Wrapped in `try/catch` to prevent leak of stack traces
#### 6.2.2 LocalStorage Protection
- **Namespace Isolation**:
- History: `calc_history`
- Theme: `calc_theme`
- Conversion Rates: `conv_rates`
- Prevents collision with other apps on same domain
- **Integrity Validation on Read**:
- `JSON.parse` with try/catch
- Type checking: Is history an array? Are entries objects with correct fields?
- Structure validation: Expression string, result (string/number), timestamp (number)
- On failure: Reset to safe default (empty history, light theme, default rates)
- **Size Limits**:
- History capped at 50 entries (FIFO)
- Theme: Simple string ('dark'|'light')
- Rates: Small JSON object (≤10 currencies)
#### 6.2.3 Output Encoding (XSS Prevention)
- **textContent Over innerHTML**:
- All dynamic values inserted via `textContent` or safe templating
- `innerHTML` **never** used with user-controlled data
- **Attribute Safety**:
- URLs (if any) validated before use
- No JavaScript: URLs or event handlers from input
- **Error Messages**:
- Generated internally (e.g., "Invalid expression", "Unknown unit")
- Never reflect raw user input
#### 6.2.4 Dependency Security
- **OSS Selection**: All dependencies from npm with MIT licenses (commercially friendly)
- **Version Pinning**: Exact versions in package.json (no floating ranges)
- **Audit Ready**: `npm audit` passes with zero vulnerabilities (at time of writing)
- **No Native Modules**: Zero risk from binary dependencies
#### 6.2.5 Runtime Protections
- **Strict Mode**: React 18 StrictMode enabled in development (helps detect unsafe practices)
- **No Dangerous APIs**:
- No `eval`, `Function` with user input, `setTimeout(string, ...)`, etc.
- No `document.write()`, `innerHTML` with user data
- No `localStorage.key()` iteration without validation
- **Content Security Policy**: Not implemented (local dev), but note:
- Would default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' (for CSS Modules transition)
- Can be added easily for production hardening
### 6.3 Gilfoyle's Review Focus Points
The security architecture is designed for straightforward review:
1. **ExpressionParser.js**: Single file to review for allowlist, function replacement, constant substitution, safe evaluation
2. **Input Flow Diagram**: Clear trace from UI → parser → evaluation → state → UI
3. **LocalStorage Handling**: Validation/recovery logic in HistoryManager and ThemeContext
4. **No Hidden Complexity**: No metaprogramming, no proxies, no eval anywhere
5. **Minimal Attack Surface**: Conversion systems use same validation pattern (lookup-based, no eval)
---
## 7. Performance Architecture
### 7.1 Performance Goals
| Metric | Target | Measurement Method |
|--------|--------|---------------------|
| Animation Frame Rate | ≥55 FPS | Chrome DevTools Performance tab |
| Calculation Latency | < 50ms (std ops)<br>< 100ms (numerical methods) | console.time() around evaluation |
| Initial Load Time | < 2.5s (Moto G4 3G throttling) | Lighthouse / DevTools Network throttling |
| Memory Usage | < 50MB peak | Chrome Task Manager |
| Bundle Size | < 150KB gzipped | `vite build` + `gzip-size` |
| Input Latency | < 16ms (1 frame) | DevTools Input Latency metric |
### 7.2 Optimization Strategies
#### 7.2.1 Rendering Performance
- **Component Memoization**:
- `React.memo` on pure components: Display, Button, HistoryItem
- Prevents unnecessary re-renders when props unchanged
- **Stable References**:
- `useCallback` for event handlers passed down as props
- `useMemo` for expensive computations (e.g., conversion factor tables)
- **Virtual Scrolling**:
- History panel uses virtual scroll if >20 items (though capped at 50)
- Renders only visible items + buffer
- **Layout Thrashing Avoidance**:
- DOM reads/writes batched via requestAnimationFrame where beneficial
- Avoid forced synchronous layouts
#### 7.2.2 Calculation Performance
- **Expression Parser Optimization**:
- Allowlist check: Single regex pass `/^[0-9+\\-*/().\\s epi]+$/i` (case-insensitive for e/pi)
- Tokenization: Simple linear scan (not full AST unless needed later)
- Function replacement: Single pass over string with regex per function (acceptable for short expressions)
- Evaluation: `Function` constructor JIT-compiled once per unique sanitized string (V8 optimizes well)
- **Numerical Methods**:
- Derivative: Central difference with fixed h (no iteration unless oscillation detected)
- Integral: Adaptive Simpson with early termination on error tolerance
- Solve: Newton-Raphson with secant fallback, `maxIter=100`, `tol=1e-10`
- All avoid expensive operations in loops (e.g., no regex inside hot loops)
#### 7.2.3 Animation Performance
- **Framer Motion Benefits**:
- Uses `requestAnimationFrame` by default
- Layout animations use FLIP technique (First, Last, Invert, Play)
- Shared layout transitions minimize paint costs
- **Reduced Motion Support**:
- Respects `prefers-reduced-motion` media query
- Falls back to instant transitions or fades when preferred
- **Layer Promotion**:
- Animated elements implicitly promoted to compositor layer (opacity/transform)
- Minimizes main thread work
#### 7.2.4 Bundle Optimization
- **Code Splitting**:
- Dynamic import() for rare features (e.g., "Manage Rates" panel)
- Main bundle: Core calculator + UI + essential utils
- **Tree Shaking**:
- ES modules + Vite = dead code elimination
- Only used functions/modules included in bundle
- **Asset Optimization**:
- Inline critical CSS (if any)
- Optimize any SVGs/icons (though currently text/icon-only via CSS)
- No large image dependencies
#### 7.2.5 Memory Management
- **History Bounding**: Fixed at 50 entries (FIFO) prevents unbounded growth
- **LocalStorage Pruning**:
- On start: If history > 50, truncate to most recent 50
- Rates: Only store user-modified rates; defaults not stored
- **Event Listener Cleanup**:
- All `addEventListener` paired with `removeEffect` in `useEffect` cleanup
- No lingering listeners on unmount
- **React 18 Benefits**:
- Automatic batching of state updates
- Concurrent rendering features (when used via startTransition)
### 7.3 Performance Testing & Validation
- **Unit Tests**:
- Math engine: Benchmark extreme cases (large numbers, deep nesting)
- Conversion: Boundary values, invalid inputs
- **Manual Profiling**:
- DevTools Performance panel: Record typical usage scenarios
- Flamegraph to identify hot paths
- Check for layout thrashing, forced sync layout, long tasks
- **Device Testing**:
- Moto G4 / Galaxy A10 (low-end Android) via BrowserStack
- iPhone SE / iPad mini (low-end iOS)
- Desktop Chrome/Firefox (reference)
- **Continuous Integration**:
- Lighthouse CI for performance budgets
- Bundle size alerts on PRs
---
## 8. Development Workflow (NEW SECTION)
### 8.1 Specialist Development Process
Each specialist follows this workflow for their assigned modules:
1. **Code Implementation**: Implement the assigned functionality according to the SAD and technical specifications
2. **Local Commit**:
- Commit changes locally with a descriptive message following conventional commits format
- Commit message structure: `<type>(<scope>): <description>`
- Example: `feat(math-engine): add derivative function with central difference method`
- Include relevant issue/ticket references if applicable
3. **Change Notification**:
- Immediately after committing, notify Turing via the designated communication channel
- Notification includes: commit hash, branch name, and brief description of changes
4. **Turing's Response**:
- Turing generates a small commit changes document explaining:
- What files were modified
- What functionality was added/changed
- How it relates to the overall architecture
- Any notable considerations or assumptions
- Document is saved in `.hermes/docs/commits/` with timestamp and commit hash
5. **Push to Repository**:
- After local validation and Turing's documentation, push changes to the designated GitHub/Gitea repository
- Push includes all local commits since last push
6. **Repeat**: Continue with next bite-sized task
### 8.2 Commit Changes Document Format
Turing's generated document follows this template:
```
# Commit Changes Document
**Commit:** <commit_hash>
**Branch:** <branch_name>
**Timestamp:** <ISO_timestamp>
**Specialist:** <specialist_name>
**Module:** <affected_module>
## Summary
<brief_description_of_changes>
## Files Modified
- <file1>: <change_description>
- <file2>: <change_description>
- ...
## Impact
- [ ] New feature
- [ ] Bug fix
- [ ] Refactor
- [ ] Documentation
- [ ] Performance improvement
- [ ] Security enhancement
## Related To
- [ ] Math Engine
- [ ] Unit Conversion
- [ ] Currency Conversion
- [ ] History System
- [ ] Theme System
- [ ] Mode System
- [ ] UI Components
- [ ] Utils
- [ ] Animation System
## Notes
<any_additional_considerations>
```
### 8.3 Workflow Benefits
- **Transparency**: Clear record of what each specialist contributed
- **Knowledge Sharing**: Turing's documents help team members understand changes across modules
- **Audit Trail**: Complete history of development process for framework evaluation
- **Quality Assurance**: Early detection of inconsistencies or integration issues
- **Documentation Compliance**: Ensures all changes are properly documented per stakeholder requirements
---
## 9. Deployment Architecture
### 9.1 Target Environment
- **Platform**: Web browser (standalone utility)
- **Deployment Model**: Static file hosting (no server-side code)
- **Required Features**:
- ES2020+ JavaScript support
- localStorage API
- requestAnimationFrame
- CSS CSS Variables
- DOM Level 2 Events
- **Supported Browsers** (latest stable):
- Chrome ≥109
- Firefox ≥109
- Safari ≥16
- Edge ≥109
- **Excluded**:
- Internet Explorer (no longer supported)
- Very old browsers lacking ES2020 features
### 9.2 Build Artifacts
- **Development**:
- `vite dev` → Serves via Vite dev server (HMR, source maps)
- Output: Unminimized, readable code with warnings
- **Production**:
- `vite build` → Outputs to `/dist/` directory
- Contents:
- `index.html` (shell)
- `assets/index-[hash].js` (minimized bundle)
- `assets/index-[hash].css` (minimized styles)
- `assets/[name]-[hash].svg` (any optimized assets)
- Features:
- Minification (Terser)
- Code splitting (Rollup)
- Asset hashing for cache busting
- Source maps optional (disabled for smallest bundle)
- **Deployment Target**:
- Any static host: Netlify, Vercel, GitHub Pages, AWS S3+CloudFront, traditional web host
- No build step required on host—just serve `/dist/` as static files
### 9.3 Environment Configuration
- **No Build-Time Env Vars**:
- Application is fully self-contained; no API keys or endpoints to configure
- All configuration (defaults, limits) in code or localStorage
- **Runtime Configuration**:
- Theme preference: localStorage (`calc_theme`)
- History limit: Hardcoded 50 (changeable in code)
- Default conversion rates: Editable in `ExchangeRateService.js` (user would fork/rebuild to change)
- Numerical method tolerances: Editable in `NumericalMethods.js`
- **Feature Flags**:
- None planned (simple application)
- If needed: Could add via `import.meta.env.VITE_FEATURE_X` (Vite supports this)
### 9.4 Security Hardening for Deployment
- **Content Security Policy (CSP)**:
- Recommended header for production:
```
Content-Security-Policy: default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
font-src 'self';
```
- Notes:
- `'unsafe-inline'` required for CSS Modules (styles injected via JS)
- Can be tightened with nonce/hashes if needed
- `img-src data:` allows embedded SVGs/icons if added later
- **HTTP Security Headers** (server-side):
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `Referrer-Policy: strict-origin-when-cross-origin`
- `Permissions-Policy: geolocation=(), microphone=(), camera=()`
- **Subresource Integrity (SRI)**:
- If using CDN for Vite-built assets (unlikely for self-host), add integrity hashes
- **Service Workers**:
- Not included (would add complexity; optional PWA upgrade later)
- If added: Cache-first strategy, background sync for rate updates (manual only)
---
## 10. Extension Points
While designed as a standalone testing utility, the architecture includes clean extension points for future enhancement:
### 10.1 Core Extensions
- **Add Scientific Function**:
1. Add to `ScientificFunctions.js` mapping
2. Add to ExpressionParser whitelist
3. Add unit tests
4. (Optional) Add to keypad in ScientificMode
- **Add Unit Category**:
1. Define conversion factors in `UnitDefinitions.js` under new category
2. Add category to `UnitConverter.js` validation logic
3. Add unit tests
4. (Optional) Add to unit converter keypad mode
- **Add Currency**:
1. Add to default rates in `ExchangeRateService.js` (user would edit)
2. Add to validation regex in `CurrencyConverter.js` (if extending beyond 3-letter)
3. Add unit tests
4. (Optional) Add to currency converter keypad mode
- **Add Numerical Method**:
1. Implement in `NumericalMethods.js` (pure JS function)
2. Add to exposed API in math engine
3. Add unit tests
4. (Optional) Add to expression parser as first-class function (would require allowing new keyword in allowlist)
### 10.2 UI/UX Extensions
- **Add Keypad Mode**:
1. Create new mode file (e.g., `GraphingMode.jsx`)
2. Add to `ModeContext.js` possible values
3. Add conditional rendering in `Keypad.jsx`
4. Add mode-switching button UI
- **Add Theme**:
1. Add new theme to `themes.js` (CSS variable overrides)
2. Add selection to theme toggle UI
- **Add Animation Variant**:
1. Create new variant in `animations/` directory
2. Export in `index.js`
3. Use in component via `<motion.div variants={newVariant}>`
### 10.3 Infrastructure Extensions
- **Persistence Backend**:
- Replace localStorage calls in `HistoryManager.js` and `ThemeContext.js` with adapter
- Could support: IndexedDB, remote sync (with conflict resolution), optional encryption
- **Rate Updates**:
- Replace manual entry in `ExchangeRateService.js` with optional polling
- Would require: API key management, cache layer, background fetch (opt-in)
- **Expression Enhancements**:
- Add support for:
- Base conversion prefixes (`0b`, `0o`, `0x`)
- Physical unit awareness (track units through calculations)
- Symbolic algebra (would require replacing core parser with CAS lite)
- **Testing & Quality**:
- Add end-to-end tests (Cypress/Playwright)
- Add visual regression testing (Chromatic/Storybook)
- Add performance budget enforcement in CI
---
## 11. Constraints & Assumptions
### 11.1 Hard Constraints (From Stakeholder)
- ✅ **Standalone Utility**: No integration with existing projects (Hybrutos, vACC, homelab)
- ✅ **No Live API Calls**: Currency rates manually entered only (framework isolation)
- ✅ **Dark Theme Mandatory**: User preference for default appearance
- ✅ **Keyboard Efficiency Priority**: Direct syntax typing preferred over mode switching
- ✅ **Gilfoyle's Security Review Mandatory**: Expression parser must be auditable
- ✅ **Gated Workflow Adherence**:
- Ideation (Steve) → Documentation PRD (Turing) →
- Design & Planning (Ada) →
- **Stakeholder Approval of Technical Plan** →
- Documentation SAD (Turing) →
- **Stakeholder Approval of SAD** →
- Orchestration (Woz) →
- Development (Specialists) →
- Pre-development Review (Stakeholder) →
- Independent Review (Satya & Sundar) →
- **Stakeholder Final Approval** →
- Deployment (Jenson)
### 11.2 Technical Assumptions
- ✅ **Browser Environment**:
- Modern browser with ES2020+ support
- localStorage available and not blocked by privacy settings
- requestAnimationFrame available for animations
- ✅ **User Competency**:
- Familiar with basic calculator operations
- Understands scientific notation and unit concepts
- Comfortable with keyboard-driven interfaces
- ✅ **Data Volumes**:
- History: ≤50 entries (trivial storage)
- Conversion rates: ≤20 currencies (trivial storage)
- Expression length: <200 characters (prevents DoS via huge input)
- ✅ **Usage Patterns**:
- Interactive use (not automated/batch processing)
- Sessions typically <1 hour (no need for aggressive memory cleanup)
- Infrequent rate updates (manual, per user initiative)
### 11.3 Explicitly Out of Scope
- ❌ **Network Dependencies**:
- No API keys, no endpoint configuration, no CORS concerns
- Offline-first by design
- ❌ **Multi-User / Collaboration**:
- Single-user device-local experience
- No real-time sync, conflict resolution, or user accounts
- ❌ **Accessibility Beyond Keyboard**:
- While keyboard support is complete,
- Screen reader optimization and ARIA completeness
- are prioritized but not exhaustive WCAG AAA
- Color contrast meets AA, not necessarily AAA
- ❌ **Internationalization (i18n)**:
- English-only interface
- Number formatting uses invariant locale (dot decimal)
- Future i18n would require:
- Message extraction (format.js/i18next)
- Right-to-left layout support
- Locale-specific number/date formatting
- ❌ **Advanced Numerics**:
- No arbitrary precision arithmetic (uses JS Number)
- No symbolic mathematics (expression parser is syntactic, not semantic)
- No matrix/tensor operations
- No statistical distributions beyond basic random()
---
## 12. Conclusion
This Solution Architecture Document specifies a secure, performant, and maintainable scientific calculator application designed to evaluate the Hermes Agent multi-agent framework.
**Key Strengths**:
- **Security-First Design**: Single sanitization point, no `eval`, input validation, error containment—ready for Gilfoyle's review
- **Stakeholder-Centric**: Reflects all agreed-upon requirements from iterative design phase (state management, math engine, conversions, UI/UX)
- **Framework Evaluation Ready**:
- Uses all core Hermes Agent lanes (Lane A: NVIDIA NIM for JARVIS/Ada/Steve/Sully/Lewis/Ananta; Lane B: OpenRouter for Turing/Zaha/Linus/Sergey/Gilfoyle/Satya/Sundar/Jenson/Maria; Lane C: NVIDIA NIM for Woz/Ananta overflow)
- Modular structure enables parallel specialist work
- Clear gates and review processes match the prescribed workflow
- **Engineering Utility**:
- Numerical methods (derivative/integral/solve) directly applicable to Battery Cart FEA and vACC flight planning
- Unit/currency systems tailored to stakeholder's project domains
- Keyboard-efficient workflow matches professional workflows
- **Production Quality**:
- Performance targets met via memoization, virtual scrolling, efficient algorithms
- Maintainability via modularity, tested core, clear extension points
- Accessibility and responsiveness addressed from the start
**New Development Workflow Enhancement**:
- Specialists follow structured commit, notify, document, push cycle
- Turing generates commit changes documents for transparency and knowledge sharing
- Ensures full traceability of changes for framework evaluation purposes
**Next Steps Upon Stakeholder Approval of this SAD**:
1. Proceed to **Phase 5: Orchestration (Woz)**
- Woz distributes tasks to specialists with Gilfoyle's security review embedded from the start
- Development begins under stakeholder oversight
2. Proceed to **Phase 6: Development (Specialists)**
- Regular commits after each bite-sized task (2-5 min focus)
- After each local commit: notify Turing → Turing generates commit changes document → push to GitHub/Gitea
- Stakeholder approval required before moving to review phase
3. Proceed to **Phase 7: Independent Review (Satya & Sundar)**
- Satya (Review): Code quality, spec compliance, best practices
- Sundar (Test): Functional testing, edge cases, performance, accessibility
- Work independently as specified
4. Proceed to **Phase 8: Deployment (Jenson)**
- Release to target (local testing environment)
- Stakeholder final go/no-go
This architecture provides a solid foundation for evaluating the Hermes Agent framework while delivering a genuinely useful tool for the stakeholder's engineering and project management workflows.
---
*End of SAD*
@@ -0,0 +1,41 @@
# Commit Changes Document
**Commit:** c449352
**Branch:** master
**Timestamp:** 2026-07-27T10:45:00Z
**Specialist:** Linus (Backend Specialist)
**Module:** Math Engine - Numerical Methods
## Summary
Implemented the numerical methods module for the scientific calculator, providing derivative, integral, and equation solving capabilities as first-class syntax functions.
## Files Modified
- `src/core/math/NumericalMethods.js`: Created new file containing:
- `derivative(expr, var, [h])`: Computes numerical derivative using central difference method with default h=1e-5
- `integral(expr, var, a, b, [n])`: Computes definite integral using adaptive Simpson's rule with error tolerance 1e-6
- `solve(expr, var, [guess])`: Finds roots using Newton-Raphson with secant-method fallback, max 100 iterations, tolerance 1e-10
## Impact
- [x] New feature
- [ ] Bug fix
- [ ] Refactor
- [ ] Documentation
- [ ] Performance improvement
- [ ] Security enhancement
## Related To
- [x] Math Engine
- [ ] Unit Conversion
- [ ] Currency Conversion
- [ ] History System
- [ ] Theme System
- [ ] Mode System
- [ ] UI Components
- [ ] Utils
- [ ] Animation System
## Notes
- All methods reuse the existing expression parser's sanitization and evaluation pipeline, maintaining the security guarantees of the allowlist-based approach.
- The implementation follows the specifications in the SAD section 3.1.4 Numerical Methods.
- Error handling includes: invalid expressions, non-convergence, and domain violations.
- The module is designed to be imported and used by the math engine's public API.
- No external dependencies; pure JavaScript implementation.
+42
View File
@@ -0,0 +1,42 @@
# Commit Changes Document
**Commit:** '${commit}'
**Branch:** master
**Timestamp:** $(git show -s --format=%ci ${commit})
**Specialist:** Linus (Backend Specialist)
**Module:** Math Engine - $(case ${commit} in 56bfb25) echo "Expression Parser" ;; 88db038) echo "Scientific Functions" ;; c449352) echo "Numerical Methods" ;; esac)
## Summary
Implemented the $(case ${commit} in 56bfb25) echo "ExpressionParser.js module" ;; 88db038) echo "ScientificFunctions.js module" ;; c449352) echo "NumericalMethods.js module" ;; esac) for the scientific calculator.
## Files Modified
- src/core/math/$(case ${commit} in 56bfb25) echo "ExpressionParser.js" ;; 88db038) echo "ScientificFunctions.js" ;; c449352) echo "NumericalMethods.js" ;; esac): $(case ${commit} in 56bfb25) echo "Created new file containing:" ;; 88db038) echo "Created new file containing:" ;; c449352) echo "Created new file containing:" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Allowlist validation for input sanitization" ;; 88db038) echo " - Export: Object mapping function names to implementations" ;; c449352) echo " - Implemented derivative, integral, and solve functions" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Constant substitution (pi→Math.PI, e→Math.E, ans→history value)" ;; 88db038) echo " - Includes: Trig, hyperbolic, exp/log, sqrt/cbrt, abs/ceil/floor/round, factorial/nCr/nPr, random" ;; c449352) echo " - Derivative: Central difference with h=1e-5 default" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Function whitelisting + replacement (sin(→Math.sin()" ;; 88db038) echo " - All implementations are pure JavaScript with no external dependencies" ;; c449352) echo " - Integral: Adaptive Simpson's Rule with error tolerance 1e-6" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Safe evaluation via Function constructor on sanitized string (never eval)" ;; 88db038) echo " - Ready for Gilfoyle's security review" ;; c449352) echo " - Solve: Newton-Raphson with secant fallback, max 100 iterations, tolerance 1e-10" ;; esac)
## Impact
- [x] New feature
- [ ] Bug fix
- [ ] Refactor
- [ ] Documentation
- [ ] Performance improvement
- [ ] Security enhancement
## Related To
- [x] Math Engine
- [ ] Unit Conversion
- [ ] Currency Conversion
- [ ] History System
- [ ] Theme System
- [ ] Mode System
- [ ] UI Components
- [ ] Utils
- [ ] Animation System
## Notes
- All methods reuse the existing expression parser's sanitization and evaluation pipeline, maintaining the security guarantees of the allowlist-based approach.
- The implementation follows the specifications in the SAD section 3.2.1 Math Engine.
- Error handling includes: invalid expressions, non-convergence, and domain violations.
- The module is designed to be imported and used by the math engine's public API.
- No external dependencies; pure JavaScript implementation.
+42
View File
@@ -0,0 +1,42 @@
# Commit Changes Document
**Commit:** '${commit}'
**Branch:** master
**Timestamp:** $(git show -s --format=%ci ${commit})
**Specialist:** Linus (Backend Specialist)
**Module:** Math Engine - $(case ${commit} in 56bfb25) echo "Expression Parser" ;; 88db038) echo "Scientific Functions" ;; c449352) echo "Numerical Methods" ;; esac)
## Summary
Implemented the $(case ${commit} in 56bfb25) echo "ExpressionParser.js module" ;; 88db038) echo "ScientificFunctions.js module" ;; c449352) echo "NumericalMethods.js module" ;; esac) for the scientific calculator.
## Files Modified
- src/core/math/$(case ${commit} in 56bfb25) echo "ExpressionParser.js" ;; 88db038) echo "ScientificFunctions.js" ;; c449352) echo "NumericalMethods.js" ;; esac): $(case ${commit} in 56bfb25) echo "Created new file containing:" ;; 88db038) echo "Created new file containing:" ;; c449352) echo "Created new file containing:" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Allowlist validation for input sanitization" ;; 88db038) echo " - Export: Object mapping function names to implementations" ;; c449352) echo " - Implemented derivative, integral, and solve functions" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Constant substitution (pi→Math.PI, e→Math.E, ans→history value)" ;; 88db038) echo " - Includes: Trig, hyperbolic, exp/log, sqrt/cbrt, abs/ceil/floor/round, factorial/nCr/nPr, random" ;; c449352) echo " - Derivative: Central difference with h=1e-5 default" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Function whitelisting + replacement (sin(→Math.sin()" ;; 88db038) echo " - All implementations are pure JavaScript with no external dependencies" ;; c449352) echo " - Integral: Adaptive Simpson's Rule with error tolerance 1e-6" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Safe evaluation via Function constructor on sanitized string (never eval)" ;; 88db038) echo " - Ready for Gilfoyle's security review" ;; c449352) echo " - Solve: Newton-Raphson with secant fallback, max 100 iterations, tolerance 1e-10" ;; esac)
## Impact
- [x] New feature
- [ ] Bug fix
- [ ] Refactor
- [ ] Documentation
- [ ] Performance improvement
- [ ] Security enhancement
## Related To
- [x] Math Engine
- [ ] Unit Conversion
- [ ] Currency Conversion
- [ ] History System
- [ ] Theme System
- [ ] Mode System
- [ ] UI Components
- [ ] Utils
- [ ] Animation System
## Notes
- All methods reuse the existing expression parser's sanitization and evaluation pipeline, maintaining the security guarantees of the allowlist-based approach.
- The implementation follows the specifications in the SAD section 3.2.1 Math Engine.
- Error handling includes: invalid expressions, non-convergence, and domain violations.
- The module is designed to be imported and used by the math engine's public API.
- No external dependencies; pure JavaScript implementation.
+42
View File
@@ -0,0 +1,42 @@
# Commit Changes Document
**Commit:** '${commit}'
**Branch:** master
**Timestamp:** $(git show -s --format=%ci ${commit})
**Specialist:** Linus (Backend Specialist)
**Module:** Math Engine - $(case ${commit} in 56bfb25) echo "Expression Parser" ;; 88db038) echo "Scientific Functions" ;; c449352) echo "Numerical Methods" ;; esac)
## Summary
Implemented the $(case ${commit} in 56bfb25) echo "ExpressionParser.js module" ;; 88db038) echo "ScientificFunctions.js module" ;; c449352) echo "NumericalMethods.js module" ;; esac) for the scientific calculator.
## Files Modified
- src/core/math/$(case ${commit} in 56bfb25) echo "ExpressionParser.js" ;; 88db038) echo "ScientificFunctions.js" ;; c449352) echo "NumericalMethods.js" ;; esac): $(case ${commit} in 56bfb25) echo "Created new file containing:" ;; 88db038) echo "Created new file containing:" ;; c449352) echo "Created new file containing:" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Allowlist validation for input sanitization" ;; 88db038) echo " - Export: Object mapping function names to implementations" ;; c449352) echo " - Implemented derivative, integral, and solve functions" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Constant substitution (pi→Math.PI, e→Math.E, ans→history value)" ;; 88db038) echo " - Includes: Trig, hyperbolic, exp/log, sqrt/cbrt, abs/ceil/floor/round, factorial/nCr/nPr, random" ;; c449352) echo " - Derivative: Central difference with h=1e-5 default" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Function whitelisting + replacement (sin(→Math.sin()" ;; 88db038) echo " - All implementations are pure JavaScript with no external dependencies" ;; c449352) echo " - Integral: Adaptive Simpson's Rule with error tolerance 1e-6" ;; esac)
- $(case ${commit} in 56bfb25) echo " - Safe evaluation via Function constructor on sanitized string (never eval)" ;; 88db038) echo " - Ready for Gilfoyle's security review" ;; c449352) echo " - Solve: Newton-Raphson with secant fallback, max 100 iterations, tolerance 1e-10" ;; esac)
## Impact
- [x] New feature
- [ ] Bug fix
- [ ] Refactor
- [ ] Documentation
- [ ] Performance improvement
- [ ] Security enhancement
## Related To
- [x] Math Engine
- [ ] Unit Conversion
- [ ] Currency Conversion
- [ ] History System
- [ ] Theme System
- [ ] Mode System
- [ ] UI Components
- [ ] Utils
- [ ] Animation System
## Notes
- All methods reuse the existing expression parser's sanitization and evaluation pipeline, maintaining the security guarantees of the allowlist-based approach.
- The implementation follows the specifications in the SAD section 3.2.1 Math Engine.
- Error handling includes: invalid expressions, non-convergence, and domain violations.
- The module is designed to be imported and used by the math engine's public API.
- No external dependencies; pure JavaScript implementation.
@@ -0,0 +1,247 @@
# Unit & Currency Conversion Systems - Design Proposal
## ✅ Context: Continuing Our Iterative Design Phase (Ada's Role)
Having finalized the math engine design through our collaborative back-and-forth, we now proceed to the next topic: **Unit & Currency Conversion Systems**. This proposal incorporates:
- Your project context (Hybrutos Racing Battery Cart, vACC event management, homelab)
- Security-first principles (Gilfoyle's review focus)
- Your UI/UX preferences (keyboard efficiency, dark theme, animations)
- Framework testing constraints (no live API calls, local-only)
---
## 🔄 **Proposed Conversion System Architecture**
### 🎯 **Core Design Goals**
1. **Relevance**: Prioritize units used in your Battery Cart (electrochemistry, mechanics, thermal), vACC (aviation, event logistics), and homelab (self-hosted services, monitoring)
2. **Security**: Reuse the same sanitized expression parser framework—no new attack surface for Gilfoyle
3. **Keyboard Efficiency**: Primary access via expression syntax (e.g., `convert(100, "V", "mV")`), no mandatory mode switching
4. **Extensibility**: Easy to add new units/currencies later without breaking changes
5. **Isolation**: All conversions use manual input/data—zero external dependencies for framework purity
---
## 📏 **Unit Conversion System**
### ⚙️ **Approach: Categorized, Bidirectional Conversion**
We define conversion **categories**—each with its own set of interconvertible units. Within a category, any unit can convert to any other.
#### 🔋 **Recommended Categories (Based on Your Projects)**
| Category | Key Units | Relevance to Your Work |
|----------|-----------|------------------------|
| **Electrical** | V, mV, kV, μV; A, mA, μA, nA; Ω, kΩ, MΩ; F, μF, pF, nF; W, kW, MW; J, kWh, Wh; C, Ah, mAh | Battery voltage/current/resistance/capacitance/power/energy/charge; telemetry sensing; solar panel specs |
| **Mechanical** | N, kN; kgf, lbf; Pa, kPa, MPa, bar, psi; m/s, km/h, mph; m/s², g; Nm, ft·lb; Hz, RPM | Battery structural loads (Al 6061-T6); brake force; tire pressure; vehicle speed/acceleration; torque; vibration analysis |
| **Thermal** | K, °C, °F; J/(kg·K), J/(g·°C); W/(m·K); W, kW | Battery thermal management; heat dissipation in enclosures; ambient temperature effects; cooling system design |
| **Volume** | L, mL, μL, cm³, in³, ft³; tsp, tbsp, fl oz, cup, pt, qt, gal | Battery electrolyte volumes; coolant reservoirs; cleaning solution mixing |
| **Mass** | kg, g, mg, μg, lb, oz | Cell casing materials; sensor weights; payload calculations for drones (if applicable) |
| **Time** | s, ms, μs, ns; min, h, d; yr | Sampling rates; event timing (vACC); log timestamps; battery cycle life |
| **Frequency** | Hz, kHz, MHz, GHz; RPM | Clock speeds; signal processing; motor rotational speed; radio frequencies (homelab) |
| **Data** | bit, byte, KB, MB, GB, TB; KiB, MiB, GiB, TiB | Storage capacity (Gitea/Immich/Jellyfin); RAM usage; network bandwidth |
#### 🔐 **Security Integration (Gilfoyle's Focus)**
- **Same sanitization pipeline** as math engine:
- Input: `convert(100, "V", "mV")` →
- Validate: digits, decimal, commas, spaces, letters (only in unit strings), parentheses
- Whitelist allowed unit symbols (from predefined list per category)
- Convert to canonical form: `convert(100, "volt", "millivolt")` (case-insensitive, singular/plural handling)
- Evaluation: Pure mathematical operation (value × conversion factor)
- **No dynamic code execution**—conversion factors are hardcoded constants
- **Critical**: Unit strings are **never** evaluated as code—they're looked up in a map
- **Outcome**: Single, auditable validation point (same as math engine); zero added risk
#### ⚡ **Numerical Precision & Handling**
- Conversion factors stored as high-precision numbers (e.g., 1 inch = 0.0254 m exactly)
- Results rounded to **significant figures** based on input precision (or fixed 10 sig figs for display)
- Temperature: Special handling for offset scales (see below)
- Invalid unit pairs (e.g., "V → ): return error
#### 🌡️ **Temperature Special Handling**
Temperature requires offset scaling (not purely multiplicative):
- **Kelvin (K)**: Absolute scale
- **Celsius (°C)**: `T_K = T_°C + 273.15`
- **Fahrenheit (°F)**: `T_K = (T_°F + 459.67) × 5/9`
- Implementation:
- Convert input → Kelvin (using offset formula)
- Convert Kelvin → target unit (using inverse offset formula)
- Units: `K`, `C` or `°C`, `F` or `°F` (we'll normalize input)
#### ⌨️ **UI/UX for Exposure (Keyboard-First)**
- **Primary Access**: Direct syntax in expression bar:
- `convert(150, "psi", "kPa")` → `1034.21`
- `convert(25, "C", "F")` → `77`
- `convert(500, "mL", "L")` → `0.5`
- **Discoverability**:
- Tooltips on unit/category buttons showing examples
- History: `convert(100, "V", "mV") = 100000`
- Click-to-insert: tap history to reuse
- **Optional**:
- "Unit Converter" mode (like scientific/shift) for touch users—but **never required** for keyboard workflow
- Favorite conversions panel (user-pinnable frequent pairs)
#### 📐 **Example Conversions Relevant to You**
| Use Case | Conversion | Result |
|----------|------------|--------|
| Battery Cart: Voltage sensing | `convert(3.7, "V", "mV")` | `3700` |
| Battery Cart: Current shunt | `convert(50, "mA", "A")` | `0.05` |
| Battery Cart: Capacitance | `convert(470, "μF", "F")` | `0.00047` |
| vACC: Runway length | `convert(8000, "ft", "m")` | `2438.4` |
| vACC: Fuel flow | `convert(12, "gal/h", "L/s")` | `0.126` |
| Homelab: Disk space | `convert(4, "TB", "GB")` | `4096` |
| Homelab: Network speed | `convert(100, "Mbps", "MB/s")` | `12.5` |
| Thermodynamics: Battery temp | `convert(25, "C", "K")` | `298.15` |
| Electrochemistry: Charge | `convert(2, "Ah", "C")` | `7200` |
---
## 💱 **Currency Conversion System**
### 🌍 **Approach: Manual-Rate Based (For Framework Isolation)**
Per your requirement for a standalone utility testing the Hermes agent framework, we **exclude live API calls**. Instead:
- User manually enters exchange rates (updated as needed)
- System stores rates with timestamps
- All conversions use these fixed rates
- Zero external dependencies → perfect for isolated framework testing
### 💰 **Supported Currencies (Per Your Request: INR, USD, GBP, etc.)**
We'll start with your requested set plus common pairs for travel/trading:
| Currency | Code | Symbol | Notes |
|----------|------|--------|-------|
| Indian Rupee | INR | ₹ | Your home currency |
| US Dollar | USD | $ | Global reserve currency |
| British Pound | GBP | £ | Common for international events |
| Euro | EUR | € | Widely used |
| Japanese Yen | JPY | ¥ | Tech hardware pricing |
| Canadian Dollar | CAD | $ | North American trade |
| Australian Dollar | AUD | $ | Asia-Pacific relevant |
| Swiss Franc | CHF | CHF | Optional (financial hub) |
| Chinese Yuan | CNY | ¥ | Manufacturing costs |
### 🔐 **Security Integration**
- **Same pattern**:
- Input: `convert(1000, "INR", "USD")` →
- Validate: numbers, currency codes (3-letter uppercase whitelist)
- Lookup rate from internal table (no eval)
- Compute: `amount × (rate_to / rate_from)`
- **No risk**: Currency codes are lookup keys, never evaluated as code
- **Rate storage**: Simple JSON object in localState (e.g., `{ "USD_INR": 83.5, "EUR_USD": 1.08 }`)
### 📈 **Rate Management**
- **Manual Entry**:
- "Manage Rates" panel (optional, not required for basic use)
- Table: From ▼ [USD] → To ▼ [INR] | Rate: ______ | [Update]
- Auto-calculates inverse (if USD→INR = 83.5, then INR→USD = 1/83.5)
- **Timestamp**: Each rate stores last-updated time (user sees "Rate updated: 2h ago")
- **Default Rates**: Pre-populated with approximate values (clearly marked as "defaults—update for accuracy")
- **Validation**: Reject non-numeric/negative rates; warn if suspiciously far from market (optional)
### ⌨️ **UI/UX for Exposure**
- **Primary Access**: Direct syntax:
- `convert(1000, "INR", "USD")` → `12.01` (if 1 USD = 83.5 INR)
- `convert(50, "EUR", "GBP")` → `43.10`
- **Discoverability**:
- Tooltips showing example pairs
- History: `convert(1000, "INR", "USD") = 12.01 USD`
- Click-to-insert
- **Optional**: Currency converter mode (toggle via UI—but keyboard syntax always works)
### 💱 **Example Conversions Relevant to You**
| Use Case | Conversion | Result (at 1 USD = 83.5 INR, 1 EUR = 1.08 USD) |
|----------|------------|------------------------------------------------|
| vACC Event: Budget | `convert(50000, "INR", "USD")` | `598.80` |
| vACC Event: Fuel cost | `convert(150, "EUR", "INR")` | `13522.50` |
| Hardware: Component cost | `convert(299, "USD", "INR")` | `24966.50` |
| Subscription: Service fee | `convert(9.99, "USD", "INR")` | `834.17` |
---
## 🔄 **Integration with Calculator Core**
### 🧮 **Unified Expression Syntax**
Both unit and currency conversions use the **same function** to maintain simplicity:
```
convert(<value>, <from_unit>, <to_unit>)
```
- **Units**:
- Unit conversion: `"V"`, `"mA"`, `"°C"`, `"L"`, `"kg"` etc.
- Currency conversion: `"INR"`, `"USD"`, `"GBP"` etc.
- **Disambiguation**:
- System checks if arguments match known unit categories first
- If not found, checks currency codes
- Error if neither (or ambiguous—e.g., if we had a unit named "USD", but we won't)
- **Examples**:
- `convert(5, "ft", "m")` → `1.524` (unit)
- `convert(5, "USD", "EUR")` → `4.63` (currency)
- `convert(100, "V", "mV")` → `100000` (unit)
### 📜 **History & Re-use**
- All conversions appear in history with full expression:
- `convert(100, "V", "mV") = 100000`
- `convert(1000, "INR", "USD") = 11.98`
- Click-to-insert: reuse past conversions in new expressions
- Chain conversions: `convert(convert(100, "USD", "INR"), "INR", "JPY")`
### 🎨 **UI/UX Consistency**
- Shares the **same theme** (dark/light) and **animation system** (Framer Motion) as calculator
- Conversion results appear in the **same display** as calculations
- Input uses the **same expression bar**—no context switching
- Tooltips, hover effects, and feedback patterns match calculator buttons
---
## 📋 **Summary: Conversion System Proposal**
| Component | Specification | Status |
|-----------|---------------|--------|
| **Unit Categories** | Electrical, Mechanical, Thermal, Volume, Mass, Time, Frequency, Data (others addable) | ⏳ Proposed |
| **Key Units** | Tailored to your Battery Cart, vACC, homelab projects (see tables above) | ⏳ Proposed |
| **Conversion Method** | `convert(<value>, <from>, <to>)` syntax | ⏳ Proposed |
| **Security** | Reuses math engine sanitizer; unit/currency as lookup keys (no eval) | ⏳ Proposed (Gilfoyle-safe) |
| **Temperature** | Special offset handling (K↔°C↔°F) | ⏳ Proposed |
| **Currency** | Manual rate input only (INR, USD, GBP, EUR, JPY, CAD, AUD +); timestamps | ⏳ Proposed |
| **UI/UX** | Direct syntax typing; tooltips; history display; click-to-insert; optional mode | ⏳ Proposed |
| **Persistence** | Rates & favorites in localState (separate from calc history) | ⏳ Proposed |
| **Defaults** | Pre-populated approximate rates (user-overridable) | ⏳ Proposed |
---
## 🔄 **Next Step: Your Feedback Requested**
Please confirm or adjust:
### 📏 **Unit Conversion**
1. **Categories**:
- Are the proposed 8 categories aligned with your project needs?
- Any missing categories critical for your work (e.g., luminous intensity for lighting projects, radiation dose for experiments)?
- Should we prioritize certain categories for initial implementation?
2. **Specific Units**:
- Any units you frequently convert that aren't listed (e.g., for battery capacity: Ah, mAh; for airflow: CFM, m³/s; for pressure: Torr, mmHg)?
- Temperature: Any preference for unit symbols (we propose `K`, `C`, `F`—should we accept `°C`, `°F` as aliases)?
- Data: Use SI (kB = 1000 B) or binary (KiB = 1024 B)? (We propose SI for consistency with storage marketing, but note binary is common in OS)
3. **Syntax & UX**:
- Is the `convert(value, "from", "to")` syntax intuitive for your workflow?
- Should we add aliases (e.g., `conv()` shorthand)?
- Any preferences for how complex conversions appear in history?
### 💱 **Currency Conversion**
1. **Currencies**:
- Is the proposed set (INR, USD, GBP, EUR, JPY, CAD, AUD) sufficient?
- Any others you'd like to include initially (e.g., CHF, CNY, SGD)?
2. **Rate Management**:
- Preferred default source for initial rates (e.g., xe.com, Google Finance, or manual entry only)?
- How often would you expect to update rates for your use cases (daily, weekly, per trip)?
3. **Syntax**:
- Same `convert()` function for units and currency—does this cause confusion, or is the context clear from the arguments?
### 🧪 **Validation & Testing**
- Should we add any sanity checks (e.g., warn if converting electron volts to joules yields unexpected scale)?
- Any edge cases you've encountered in your projects that we should handle gracefully?
Once you confirm the conversion system design, we'll have completed the **full technical plan** for your formal approval. After that:
1. Turing writes the **SAD** (Solution Architecture Document) based on this agreed plan
2. You review and approve the **SAD**
3. Woz distributes tasks to specialists (with Gilfoyle's security review embedded from the start)
4. Development proceeds under your oversight
Your guidance on the conversion system is now awaited—this is our collaborative design phase in action. I await your input to refine this to your exact satisfaction.
@@ -0,0 +1,160 @@
# Math Engine Design - Agreed Specifications
## ✅ Fully Agreed Upon (Per Iterative Design Phase)
### 1. State Management
- **Approach**: React Context API with `useReducer` for global state (theme, mode, calculation/history)
- **Persistence**: localStorage for history and theme preference
- **Corruption Handling**: On localStorage corruption/Session corruption/data mismatch, restore last known good state
- **Rationale**: Avoids external libraries (Redux/Zustand), keeps bundle size appropriate for scope, matches user's "NO" to additional persistence requirements
### 2. Core Expression Processor
- **Input Sanitization** (Gilfoyle's Security Focus):
- Strict allowlist: digits (`0-9`), decimal (`.`), operators (`+-*/().`), whitespace
- Constants: `e` (Euler's number), `pi` (π)
- Whitelisted function names: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `exp`, `log` (base 10), `ln` (natural), `sqrt`, `cbrt`, `abs`, `ceil`, `floor`, `round`, `random`, `factorial`, `nCr`, `nPr`
- Constant substitution: `pi` → `Math.PI`, `e` → `Math.E`
- Special handling: `ans` → last valid history value (if numeric)
- Function replacement: `sin(` → `Math.sin(` (etc.) before evaluation
- **Evaluation**: `Function` constructor **only** on fully sanitized string (never `eval`)
- **Error Handling**: Returns `{value: null, error: string}` for invalid expressions
- **Outcome**: Single, auditable sanitization point for Gilfoyle's review
### 3. Scientific Functions (Standard Set)
- Trigonometric: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`
- Hyperbolic: `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`
- Exponential/Logarithmic: `exp`, `log` (base 10), `ln` (natural)
- Root/Power: `sqrt`, `cbrt`, `**` (exponentiation)
- Absolute/Rounding: `abs`, `ceil`, `floor`, `round`
- Combinatorics: `factorial` (n!), `nCr` (combinations), `nPr` (permutations)
- Random: `random` ([0,1) uniform distribution)
- Constants: `e` (Euler's number), `pi` (π)
---
## 🔢 **Agreed Extensions (Per User Confirmation)**
### ➕ **Additional Mathematical Constants**
*(User confirmed: "Yes, add constants")*
All defined as pure numbers (unit awareness deferred to later phase per user request):
| Symbol | Value | Description |
|--------|-------|-------------|
| `c` | 299792458 | Speed of light (m/s) |
| `g` | 9.80665 | Standard gravity (m/s²) |
| `NA` | 6.02214076e23 | Avogadro's number (mol⁻¹) |
| `R` | 8.314462618 | Molar gas constant (J/(mol·K)) |
| `q_e` | 1.602176634e-19 | Elementary charge (C) *[Note: `e` reserved for Euler's number]* |
| `kB` | 1.380649e-23 | Boltzmann constant (J/K) |
| `atm` | 101325 | Standard atmosphere (Pa) |
**Rationale**: Covers mechanics (`g`), electrochemistry (`NA`, `q_e`), thermodynamics (`R`, `kB`), and gas laws (`atm`, `c`) relevant to:
- Hybrutos Racing: Battery thermal management, electrochemical reactions, structural mechanics
- vACC: Pressure conversions, timing calculations
- Homelab: Sensor calibration, thermodynamic monitoring
### ➕ **Numerical Methods as First-Class Syntax**
*(User confirmed interest in "basic numerical calculation" via earlier context; specific parameters approved below)*
All methods reuse the **sanitized expression parser**—no additional attack surface for Gilfoyle.
#### 1. `derivative(expr, var, [h])`
- **Purpose**: Approximate derivative of `expr` w.r.t. `var`
- **Method**: Central difference: `[f(var+h) - f(var-h)] / (2h)` (O(h²) accuracy)
- **Defaults**: `h = 1e-5` (optimal for double-precision precision)
- **Error Handling**:
- Invalid expression → returns error
- Non-numeric result after substitution → error
- Oscillation detected (discontinuity) → error with suggestion
- Max 20 iterations for adaptive step refinement (if needed)
- **Examples**:
- `derivative(x^2, x, 3)` → `6.0`
- `derivative(sin(x), x, 0)` → `1.0` (cos(0))
- `derivative(log(x), x, 1)` → `1.0`
#### 2. `integral(expr, var, a, b, [n])`
- **Purpose**: Approximate definite integral of `expr` from `a` to `b` w.r.t. `var`
- **var, Simpson's Rule with error-controlled subdivision
- **Defaults**: Target relative error `1e-6`, max subdivisions `2^10` (102. **Method**: Adaptive Simpson's Rule with error-controlled subdivision
- **Defaults**: Target relative error `1e-6`, max subdivisions `2^10` (1024)
- **Error Handling**:
- Requires `a < b` (automatically swaps & negates if reversed)
- Divergent integrals (e.g., `1/x` on `[0,1]`) → error
- Function evaluation cap prevents hanging
- **Examples**:
- `integral(x, x, 0, 2)` → `2.0`
- `integral(1, x, 0, 5)` → `5.0`
- `integral(exp(-x^2), x, -20, 20)` → `√π ≈ 1.7724538509` (Gaussian integral)
#### 3. `solve(expr, var, [guess])`
- **Purpose**: Find root of `expr ≈ 0` (solve for `var`)
- **Method**: Newton-Raphson with secant-method fallback (avoids needing analytical derivative)
- **Defaults**: `guess = 0`, max iterations `100`, tolerance `1e-10`
- **Error Handling**:
- Failure to converge → error with suggestion to adjust guess
- Derivative too small → error (avoids division by near-zero)
- May return one root if multiple exist (dependent on initial guess)
- **Examples**:
- `solve(x^2-4, x)` → `2.0` or `-2.0` (depends on guess)
- `solve(sin(x), x, 3)` → `3.1415926535` (π)
- `solve(exp(x)-2, x)` → `0.69314718056` (ln(2))
**Parameter Justification**:
- `h=1e-5`: Balances truncation and round-off error for double precision
- `tol=1e-6` (integral): Sufficient for engineering accuracy (0.0001% error)
- `maxIter=100` (solve): More than enough for well-behaved functions; prevents infinite loops
- These are standard defaults in numerical libraries (NumPy, SciPy, MATLAB)
### ⌨️ **UI/UX for Numerical Methods Exposure**
*(User confirmed keyboard-efficient workflow preference)*
- **Primary Access**: Direct syntax typing (e.g., `derivative(sin(x), x, 0)`)
- Always available in expression input (no mode switching required)
- Matches user's workflow for engineering calculations
- **Discoverability & Assistance**:
- Tooltips on function buttons showing syntax (e.g., hover over "deriv" → `derivative(expr, var, [h])`)
- History entries display full expression: `derivative(sin(x), x, 0) = 1.000000`
- Click-to-insert: Tap any history item to insert it at cursor position
- Optional: "f(x)=?" helper pane showing syntax examples (collapsible)
- **Validation**: Real-time syntax highlighting as user types (valid operators/functions in green, invalid in red)
---
## 📋 **Summary: Math Engine Design Complete**
| Component | Specification | Status |
|-----------|---------------|--------|
| State Management | Context API + `useReducer`; localStorage; corruption → last good state | ✅ Agreed |
| Core Processor | Allowlist sanitization; function whitelist; safe `Function` eval | ✅ Agreed |
| Standard Functions | Trig, log, exp, sqrt, abs, rounding, factorial, nCr, nPr, random | ✅ Agreed |
| **Constants** | `c`, `g`, `NA`, `R`, `q_e`, `kB`, `atm` (pure numbers) | ✅ **Agreed** (per user confirmation) |
| **Numerical Methods** | `derivative`, `integral`, `solve` as first-class syntax | ✅ **Agreed** (per user confirmation + parameter approval) |
| Constant Naming | `e` = Euler's number; electron charge = `q_e` | ✅ Agreed (avoids conflict) |
| Unit Awareness | Deferred (treat as pure numbers now; add later) | ✅ Agreed (per user request) |
| UI/UX | Direct syntax typing; tooltips; history display; click-to-insert | ✅ Agreed (per workflow preference) |
**Next Step**: With the math engine design now fully agreed upon, we proceed to our next iterative topic:
**Unit & Currency Conversion Systems** (including your requested INR, USD, GBP, etc.).
I propose the following structure for our discussion:
1. **Unit Conversion**:
- Categories: Length, mass, temperature, volume, time, speed, pressure, energy, power
- Bidirectional conversion within each category
- Temperature special handling (offset scales)
- Common units: mm, cm, m, km, in, ft, yd, mi; mg, g, kg, oz, lb; °C, °F, K; ml, l, tsp, tbsp, fl oz, cup, pt, qt, gal; etc.
2. **Currency Conversion**:
- Manual rate input (no live API calls for framework isolation/testing)
- Supported currencies: INR, USD, GBP, EUR, JPY, CAD, AUD, CNY (user-extendable)
- Base currency selection + rate table
- Timestamp for rate validity (user-managed)
3. **Integration**:
- Conversion modes accessible via keypad (like scientific/shift layers)
- Expression syntax: `convert(100, "in", "cm")` or similar
- History tracking for conversions
- Shared number formatting with calculator
Please confirm if this approach aligns with your expectations, or share any specific preferences/conversions you'd prioritize for your projects (e.g., battery capacity units, airflow rates for vACC, etc.).
Once we agree on the conversion system design, we'll finalize the full technical plan for your formal approval before proceeding to the SAD (Turing) and specialist task distribution (Woz).
Your guidance on the conversion system is now awaited.
@@ -0,0 +1,150 @@
# Updated Math Engine Proposal (Post-Iteration Feedback)
## ✅ Agreed Decisions So Far
1. **State Management**: React Context API with `useReducer` for global state (theme, mode, calculation/history). localStorage for history/theme preference; on corruption, restore last known good state.
2. **Core Expression Parser**:
- Strict allowlist: digits, decimal, operators (`+-*/().`), whitespace, `e`, `pi`, and whitelisted function names
- Function whitelisting + safe replacement (e.g., `sin(` → `Math.sin(`)
- Constant substitution: `pi`→`Math.PI`, `e`→`Math.E`, `ans`→history value (if valid number)
- Safe evaluation via `Function` constructor **only** on fully sanitized string (never `eval`)
- Error handling: return `{value: null, error: string}` for invalid expressions
3. **Scientific Functions**: Standard trig, log, exp, root, abs, rounding, combinatorics (factorial, nCr, nPr), random
## 🔢 **Updated: Extended Math Engine with Numerical Methods & Constants**
### ➕ **Additional Constants (Per User Request: "Yes, add constants")**
We propose the following engineering/physics-relevant constants. All are pure numbers (unit awareness deferred to later phase):
| Constant | Symbol | Value | Description | Relevance to Your Projects |
|----------|--------|-------|-------------|----------------------------|
| Speed of light | `c` | 299792458 | m/s | Useful for EM simulations, timing analysis |
| Gravitational acceleration | `g` | 9.80665 | m/s² | Battery Cart mechanical analysis, brake force calculations |
| Avogadro's number | `NA` | 6.02214076e23 | mol⁻¹ | Electrochemistry (battery reactions) |
| Gas constant | `R` | 8.314462618 | J/(mol·K) | Thermodynamics (battery thermal management) |
| Electron charge | `e` | 1.602176634e-19 | C | Already reserved for Euler's number → we'll use `electronCharge` or `q_e` to avoid conflict |
| Planck's constant | `h` | 6.62607015e-34 | J·s | Quantum effects (less likely in current projects) |
| Boltzmann constant | `kB` | 1.380649e-23 | J/K | Statistical mechanics, thermal noise |
| Standard atmosphere | `atm` | 101325 | Pa | Pressure conversions, vacuum systems |
| Electron mass | `m_e` | 9.1093837015e-31 | kg | Particle physics (unlikely needed) |
| Proton mass | `m_p` | 1.67262192369e-27 | kg | Nucleon mass (unlikely needed) |
**Naming Note**: To avoid conflict with Euler's number (`e`), we will **not** expose `e` as electron charge. Instead:
- Keep `e` = Euler's number (2.71828...) as standard
- Provide electron charge as `q_e` or `electronCharge` (user preference)
- Similarly, we'll avoid other single-letter conflicts where possible (e.g., `m` for meters is problematic; we'll use explicit names)
**Proposed Constant Set for Initial Implementation**:
- `c` = 299792458 (speed of light)
- `g` = 9.80665 (gravitational acceleration)
- `NA` = 6.02214076e23 (Avogadro's number)
- `R` = 8.314462618 (gas constant)
- `q_e` = 1.602176634e-19 (electron charge)
- `kB` = 1.380649e-23 (Boltzmann constant)
- `atm` = 101325 (standard atmosphere)
We can add more later; this covers mechanics, electrochemistry, thermodynamics, and gas laws relevant to your Battery Cart and homelab projects.
### ➕ **Numerical Methods (Per User Selection: "Full scientific + basic numerical calc")**
We will implement three higher-order functions that accept expressions as arguments, enabling engineering calculations like those in your FEA work.
#### 1. `derivative(expr, var, [h])`
- **Purpose**: Approximate derivative of `expr` with respect to `var`
- **Method**: Central difference: `[f(var+h) - f(var-h)] / (2h)` (O(h²) accuracy)
- **Defaults**: `h = 1e-5` (adjustable via optional third argument)
- **Error Handling**:
- Returns error if `expr` is invalid or non-numeric after substitution
- Stops if oscillation detected (likely discontinuity)
- Max 20 iterations for adaptive step refinement (if needed)
- **Examples**:
- `derivative(x^2, x, 3)` → `6.0`
- `derivative(sin(x), x, 0)` → `1.0` (cos(0))
- `derivative(log(x), x, 1)` → `1.0`
#### 2. `integral(expr, var, a, b, [n])`
- **Purpose**: Approximate definite integral of `expr` from `a` to `b` with respect to `var`
- **Method**: Adaptive Simpson's Rule with error tolerance
- **Defaults**: Target relative error `1e-6`, max subdivisions `2^10` (1024)
- **Error Handling**:
- Requires `a < b` (swaps and negates if reversed)
- Returns error if integral diverges or fails to converge
- Limits function evaluations to prevent hanging
- **Examples**:
- `integral(x, x, 0, 2)` → `2.0`
- `integral(1, x, 0, 5)` → `5.0`
- `integral(exp(-x^2), x, -20, 20)` → `√π ≈ 1.77245` (Gaussian integral)
#### 3. `solve(expr, var, [guess])`
- **Purpose**: Find root of `expr ≈ 0` (solve for `var`)
- **Method**: Newton-Raphson with secant-method fallback (avoids needing analytical derivative)
- **Defaults**: `guess = 0`, max iterations `100`, tolerance `1e-10`
- **Error Handling**:
- Returns error if fails to converge or derivative too small
- May return one root if multiple exist (dependent on initial guess)
- **Examples**:
- `solve(x^2-4, x)` → `2.0` or `-2.0` (depends on guess)
- `solve(sin(x), x, 3)` → `3.14159...` (π)
- `solve(exp(x)-2, x)` → `0.693147...` (ln(2))
### 🛡️ **Security Integration (Gilfoyle's Focus)**
All numerical methods **reuse the same sanitized expression parser** as the core calculator:
- The `expr` argument undergoes identical allowlist validation, function replacement, and constant substitution
- Numerical methods contain **no dynamic code evaluation of raw user input**—they:
- Parse the expression once into a tokenized form (or evaluate the already-sanitized string via `Function` constructor in a safe context)
- Perform pure arithmetic loops (e.g., summing rectangles, finite differences)
- Never reconstruct or re-evaluate unsanitized strings
- Example: For `derivative("sin(x)*x", x, 0)`:
1. Validate `"sin(x)*x"` → allowed characters only`
2. Replace → `"Math.sin(x)*x"`
3. For sample points `x = -h, 0, h`:
- Evaluate `"Math.sin(x)*x"` with `x` set to sample value → pure math operation
4. Compute finite difference → return result
This ensures the **attack surface remains identical** to the core expression parser—Gilfoyle reviews one sanitizer, not multiple.
### ⌨️ **UI/UX for Exposure (Per User Keyboard Preference)**
To honor your strong preference for keyboard efficiency and fluid interaction:
- **First-class syntax**: Users type expressions directly: `derivative(sin(x), x, 0)` and press `=`
- **Discoverability**:
- Tooltips on function buttons showing syntax examples (e.g., hover over "deriv" shows `derivative(expr, var, [h])`)
- History entries display full expression: `derivative(sin(x), x, 0) = 1.000`
- Click-to-insert: tap a history item to insert it into the current expression
- **No mandatory mode switching**: Unlike traditional calculators with shift/2nd functions, these are always available in the expression syntax (consistent with your workflow)
---
## 📋 **Summary of Agreed & Proposed Elements**
| Element | Decision | Status |
|---------|----------|--------|
| State Management | Context API + `useReducer`, localStorage, corruption → last good state | ✅ Agreed |
| Core Expression Parser | Allowlist, function whitelist, constant sub, safe `Function` eval | ✅ Agreed |
| Standard Scientific Functions | Trig, log, exp, sqrt, abs, rounding, factorial, nCr, nPr, random | ✅ Agreed |
| **Additional Constants** | `c`, `g`, `NA`, `R`, `q_e`, `kB`, `atm` (pure numbers) | 🟡 Proposed (await confirmation) |
| **Numerical Methods** | `derivative`, `integral`, `solve` as first-class syntax | 🟡 Proposed (await confirmation) |
| Constant Naming | `e` = Euler's number; electron charge = `q_e` | 🟡 Proposed (avoid conflict) |
| Unit Awareness | Deferred to later phase (treat as pure numbers now) | ✅ Agreed |
| UI Exposure | Direct syntax typing, tooltip/history support, click-to-insert | 🟡 Proposed (await confirmation) |
---
## 🔄 **Next Step: Your Feedback Requested**
Please confirm or adjust:
1. **Constants**:
- Does the proposed set (`c`, `g`, `NA`, `R`, `q_e`, `kB`, `atm`) cover your needs for Hybrutos Racing, vACC, and homelab projects?
- Are there any other constants you'd like to prioritize (e.g., electron mass, proton mass, Faraday constant, etc.)?
- Any naming preferences (e.g., `electronCharge` vs `q_e`, `avogadro` vs `NA`)?
2. **Numerical Methods**:
- Are the default parameters (`h=1e-5`, tolerance `1e-6`, max iterations `100`) reasonable for your engineering calculations?
- Should we add any safeguards (e.g., max domain size for integrals to prevent hanging)?
- Any other numerical methods you'd find useful (e.g., `sum`, `product`, `minimization`)?
3. **UI/UX**:
- Is the direct syntax approach (`derivative(...)`) aligned with your keyboard-efficient workflow?
- Any preferences for how these appear in history or tooltips?
Once you confirm these points, we'll mark the math engine design as complete and move to our next iterative topic: **Unit & Currency Conversion Systems** (including your requested INR, USD, GBP, etc.).
Your turn—this is our collaborative design phase in action. I await your guidance to refine this to your exact satisfaction.
@@ -0,0 +1,420 @@
# Technical Implementation Plan
## Scientific Calculator with Conversion & History
**Version:** 1.0.0
**Date:** 2026-07-27
**Prepared by:** Ada (Design & Planning Specialist, Hermes Agent)
**Based on:** Iterative design phase with stakeholder (Shreyas Kamat)
**Approvals:**
- State Management: ✅ Confirmed
- Math Engine Design: ✅ Confirmed
- Unit Conversion System: ✅ Confirmed
- Currency Conversion System: ✅ Confirmed
---
## 1. Executive Summary
This document specifies the technical implementation for a standalone scientific calculator application built to evaluate the Hermes Agent multi-agent framework. The calculator provides advanced mathematical operations (including numerical methods), unit conversions, currency conversions, and calculation history tracking with a modern, animated dark-theme UI. It is intended as a local testing utility only, with no planned integration into existing projects.
**Primary Goal:** Validate the Hermes Agent multi-agent architecture by delivering a feature-rich, polished ReactJS application through the prescribed phased development process.
---
## 2. Architecture Overview
### 2.1 High-Level Structure
- **Single-Page Application (SPA)** built with React 18 + Vite
- **Modular component architecture** with clear separation of concerns:
- `core/`: Math engine, conversion systems, history manager (pure JS, testable in isolation)
- `ui/`: Presentational components (display, buttons, panels, theme)
- `hooks/`: Custom React hooks for state/logic encapsulation
- `context/`: Global state (theme, calculation mode, history) via React Context API
- `utils/`: Cross-cutting concerns (keyboard handler, formatter, validator)
- `animations/`: Framer Motion variants and presets
- `styles/`: CSS modules, theme variables, responsive breakpoints
### 2.2 State Management Strategy
- **Local component state** (`useState`, `useReducer`): UI state (input focus, animation states, modal visibility)
- **Global state via Context API** (chosen per stakeholder preference):
- `ThemeContext`: dark/light mode, transition state
- `CalculationContext`: current expression, history stack, memory registers
- `ModeContext`: active calculator mode (standard, scientific, unit conversion, currency conversion)
- **Persistence**: `localStorage` for history and theme preference (with corruption recovery to last known good state)
- **No external libraries** (Redux/Zustand) to keep bundle size appropriate for scope
### 2.3 Security Approach (Gilfoyle's Focus)
- **Single sanitization point**: All user input (expressions, unit/currency conversions) flows through the same strict allowlist validator
- **Expression Parser**:
- Allowlist: digits, decimal, operators (`+-*/().`), whitespace, `e`, `pi`, whitelisted function names
- Function whitelisting + safe replacement (e.g., `sin(` → `Math.sin(`)
- Constant substitution: `pi`→`Math.PI`, `e`→`Math.E`, `ans`→history value (if valid number)
- Safe evaluation via `Function` constructor **only** on fully sanitized string (never `eval`)
- Error handling: returns `{value: null, error: string}` for invalid expressions
- **Unit/Currency Conversion**:
- Input validation against predefined whitelists (unit symbols, currency codes)
- Lookup-based conversion using hardcoded factors/rates (no dynamic code evaluation)
- Temperature: Special offset handling (K↔°C↔°F)
- **Zero attack surface added** beyond the core expression parser
---
## 3. Functional Specifications
### 3.1 Core Calculation Engine
#### 3.1.1 Expression Parser & Evaluation
- **Input Sanitization**:
- Allowlist: `[0-9]`, `.`, `+-*/()`, whitespace, `e`, `pi`, and whitelisted function names
- Reject all other characters immediately
- Normalize whitespace (collapse, trim)
- **Constant Substitution**:
- `pi` → `Math.PI`
- `e` → `Math.E` (Euler's number)
- `ans` → last valid history value (if numeric)
- **Function Whitelisting & Replacement**:
- Trigonometric: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`
- Exponential/Logarithmic: `exp`, `log` (base 10), `ln` (natural)
- Root/Power: `sqrt`, `cbrt`, `**` (exponentiation)
- Absolute/Rounding: `abs`, `ceil`, `floor`, `round`
- Combinatorics: `factorial` (n!), `nCr`, `nPr`
- Other: `random`
- **Evaluation`:
- Replace whitelisted functions with `Math.func` equivalents
- Evaluate via: `Function("use strict"; return (${sanitizedString}))()` inside try/catch
- Return `{value: number, error: null}` on success, `{value: null, error: string}` on failure
#### 3.1.2 Standard Scientific Functions
All standard mathematical functions return JavaScript Math precision:
- Trigonometric: `sin(x)`, `cos(x)`, `tan(x)`, etc.
- Hyperbolic: `sinh(x)`, `cosh(x)`, `tanh(x)`, etc.
- Exponential/Logarithmic: `exp(x)`, `log10(x)`, `ln(x)`
- Root/Power: `sqrt(x)`, `cbrt(x)`, `x^y`
- Absolute/Rounding: `abs(x)`, `ceil(x)`, `floor(x)`, `round(x)`
- Combinatorics: `factorial` (n!), `nCr` (n choose r), `nPr` (n permute r)
- Random: `random()` → [0,1) uniform distribution
#### 3.1.3 Agreed Mathematical Constants
All defined as pure numbers (unit awareness deferred):
- `c` = 299792458 (speed of light, m/s)
- `g` = 9.80665 (standard gravity, m/s²)
- `NA` = 6.02214076e23 (Avogadro's number, mol⁻¹)
- `R` = 8.314462618 (molar gas constant, J/(mol·K))
- `q_e` = 1.602176634e-19 (elementary charge, C)
- `kB` = 1.380649e-23 (Boltzmann constant, J/K)
- `atm` = 101325 (standard atmosphere, Pa)
- **Note**: `e` reserved for Euler's number; electron charge = `q_e`
#### 3.1.4 Numerical Methods (First-Class Syntax)
All methods reuse the sanitized expression parser—no additional attack surface.
- **`derivative(expr, var, [h])`**:
- Purpose: Approximate derivative of `expr` w.r.t. `var`
- Method: Central difference: `[f(var+h) - f(var-h)] / (2h)` (O(h²))
- Defaults: `h = 1e-5`
- Error Handling: Invalid expr → error; oscillation → error; max 20 adaptive steps
- Examples: `derivative(x^2, x, 3)` → `6.0`; `derivative(sin(x), x, 0)` → `1.0`
- **`integral(expr, var, a, b, [n])`**:
- Purpose: Approximate definite integral of `expr` from `a` to `b` w.r.t. `var`
- Method: Adaptive Simpson's Rule with error-controlled subdivision
- Defaults: Target relative error `1e-6`, max subdivisions `2^10` (1024)
- Error Handling: Requires `a < b` (auto-swap & negate); divergent integrals → error
- Examples: `integral(x, x, 0, 2)` → `2.0`; `integral(exp(-x^2), x, -20, 20)` → `√π ≈ 1.77245`
- **`solve(expr, var, [guess])`**:
- Purpose: Find root of `expr ≈ 0` (solve for `var`)
- Method: Newton-Raphson with secant-method fallback
- Defaults: `guess = 0`, max iterations `100`, tolerance `1e-10`
- Error Handling: Failure to converge → error; derivative too small → error
- Examples: `solve(x^2-4, x)` → `2.0` or `-2.0`; `solve(sin(x), x, 3)` → `π`
### 3.2 Conversion Systems
#### 3.2.1 Unit Conversion System
- **Approach**: Categorized, bidirectional conversion within categories
- **Categories** (based on stakeholder projects):
- **Electrical**: V, mV, kV, μV; A, mA, μA, nA; Ω, kΩ, MΩ; F, μF, pF, nF; W, kW, MW; J, kWh, Wh; C, Ah, mAh
- **Mechanical**: N, kN; kgf, lbf; Pa, kPa, MPa, bar, psi; m/s, km/h, mph; m/s², g; Nm, ft·lb; Hz, RPM
- **Thermal**: K, °C, °F; J/(kg·K), J/(g·°C); W/(m·K); W, kW
- **Volume**: L, mL, μL, cm³, in³, ft³; tsp, tbsp, fl oz, cup, pt, qt, gal
- **Mass**: kg, g, mg, μg, lb, oz
- **Time**: s, ms, μs, ns; min, h, d; yr
- **Frequency**: Hz, kHz, MHz, GHz; RPM
- **Data**: bit, byte, KB, MB, GB, TB (user to specify SI/binary preference)
- **Conversion Syntax**: `convert(<value>, <from_unit>, <to_unit>)`
- Examples: `convert(5, "ft", "m")` → `1.524`; `convert(25, "C", "F")` → `77`
- **Security**:
- Input validation against unit whitelists per category
- Lookup-based conversion using hardcoded factors (no eval)
- Temperature: Special offset handling (K↔°C↔°F)
- **UI/UX**:
- Primary access: Direct syntax in expression bar (keyboard-efficient)
- Discoverability: Tooltips, history display (`convert(100, "V", "mV") = 100000`), click-to-insert
- Optional mode: Unit converter panel (never required for keyboard workflow)
#### 3.2.2 Currency Conversion System
- **Approach**: Manual-rate based (for framework isolation—no live API calls)
- **Supported Currencies**: INR, USD, GBP, EUR, JPY, CAD, AUD (user-extendable)
- **Conversion Syntax**: `convert(<value>, <from_currency>, <to_currency>)`
- Examples: `convert(1000, "INR", "USD")` → `11.98` (if 1 USD = 83.5 INR)
- **Security**:
- Input validation: 3-letter uppercase currency code whitelist
- Lookup-based conversion using manually entered rates (no eval)
- Rate storage: Simple JSON in localState with timestamps
- **Rate Management**:
- Manual entry via optional "Manage Rates" panel
- Auto-calculates inverse rates
- Timestamp for each rate (user sees "Rate updated: X time ago")
- Default rates pre-populated (clearly marked as approximations)
- **UI/UX**:
- Primary access: Direct syntax
- Discoverability: Tooltips, history display, click-to-insert
- Optional mode: Currency converter panel (never required for keyboard workflow)
#### 3.2.3 Integration with Core
- **Unified Syntax**: Both unit and currency conversions use `convert(<value>, <from>, <to>)`
- System checks if arguments match known unit categories first
- If not found, checks currency codes
- Error if neither (or ambiguous—avoided by distinct naming)
- **History & Re-use**:
- All conversions appear in history with full expression
- Click-to-insert: reuse past conversions in new expressions
- Chain conversions: `convert(convert(100, "USD", "INR"), "INR", "JPY")`
- **UI/UX Consistency**:
- Shares theme (dark/light) and animation system (Framer Motion)
- Results appear in same display as calculations
- Uses same expression bar—no context switching
- Consistent tooltips, hover effects, and feedback patterns
### 3.3 History System
- **Storage**: Persistent via localStorage (last 50 operations, FIFO eviction)
- **Structure**: `{ expression: string, result: string | number, timestamp: number }`
- **Features**:
- Save after each successful calculation/conversion
- Load on startup (with corruption recovery to last good state)
- Re-use: Click any history item to insert at cursor position
- Delete: Swipe/slide to remove individual items
- Clear all: Optional function to reset history
- **Display**: Shows full expression and result (e.g., `derivative(sin(x), x, 0) = 1.000`)
- **Security**:
- Sanitize on read (JSON.parse with type validation)
- Reject malformed data; fall back to defaults
### 3.4 User Interface & Experience
#### 3.4.1 Theme System
- **Default**: Dark theme (mandatory per stakeholder preference per stakeholder)
- **Optional**: Light theme toggle
- **Implementation**: CSS variables (`--bg-primary`, `--text-primary`, `--accent`, etc.) in `:root`
- **Transitions**: Smooth via `transition: background-color 0.3s, color 0.3s`
- **Colors**:
- Dark: Background `#121212`, Text `#E0E0E0`, Accent `#FF9800`
- Light: Background `#FFFFFF`, Text `#212121`, Accent `#FB8C00`
#### 3.4.2 Keypad & Button System
- **Layout**: Responsive grid adapting to mode (standard/scientific/unit/conversion/currency)
- **Button Variants**:
- Numbers: Standard styling
- Operators (+,-,*,/,=): Accent color (`#FF9800`)
- Functions (sin, log, etc.): Secondary accent
- Conversion: Distinct styling (to be finalized)
- Special (AC, CE): Warning color
- **Styling**: CSS Modules (scoped, no runtime overhead)
- **Animations** (Framer Motion):
- Button press: `scale` and `backgroundColor` transition (200ms)
- Screen transitions: Fade and slide (300ms)
- History panel: Slide-in from right (desktop) / full-screen modal (mobile)
- **Responsiveness**:
- Mobile-first: `<480px` (phone), `480-768px` (tablet/desktop)
- Keypad: 4-column grid on tablet+/desktop, 2-column on phone (scrollable if needed)
- Display: Font size scales with viewport
- **Accessibility**:
- All buttons: `aria-label` (e.g., "sine", "clear all", "delete last")
- Keyboard navigation: logical tab order, visible focus rings
- Screen reader live regions for error/history updates
- Color contrast: WCAG AA minimum (4.5:1 for text, 3:1 for large text/UI)
#### 3.4.3 Display & Input
- **Primary Expression Bar**:
- Shows current input/output
- Font: `Space Mono` (monospace) for calculation clarity
- Features: Real-time syntax highlighting (valid in green, invalid in red)
- **Secondary Line** (optional):
- Shows full expression for multi-step calculations
- Smaller font, muted color
- **Error Handling**:
- Display "Error" for invalid expressions/conversions
- Optional: Shake animation + red border feedback
- Recovery: "Press AC to reset" hint in error state
### 3.5 Keyboard Support
- **Comprehensive Mapping**:
- Numbers 0-9: Digits
- Operators: `+` (plus), `-` (minus), `*` (asterisk), `/` (slash), `=` or `Enter` (equals)
- Decimal: `.` (period) or `,` (comma, locale-dependent)
- Backspace: `Backspace` (delete last char)
- Escape: `Escape` (clear all / AC)
- Arrow keys: History navigation (up/down for previous/next)
- **Advanced Functions**:
- Type directly: `derivative(sin(x), x, 0)`, `convert(100, "V", "mV")`
- No mode switching required for keyboard workflow
- **Validation**: Real-time feedback as user types
### 3.6 Performance Targets
- **Animation**: Maintain ≥55 FPS during interactions
- **Calculation Latency**: < 50ms for standard operations (<100ms for numerical methods)
- **Initial Load**: < 2.5s on mid-tier device (simulated 3G throttling)
- **Memory**: < 50MB peak usage (history/localStorage bounded)
- **Bundle Size**: Target <150KB gzipped (React + Framer Motion ~80KB; rest ~70KB)
---
## 4. Non-Functional Requirements
### 4.1 Security & Reliability (Gilfoyle's Focus)
- **Input Sanitization**: Single allowlist validator for all user input
- **No `eval()`**: Never use `eval` or equivalent; only sanitized `Function` constructor
- **LocalStorage Safety**:
- Validate on read (type checking, structure verification)
- Namespace keys to prevent collisions (`calc_history`, `calc_theme`, `conv_rates`)
- Corruption recovery: Restore last known good state or defaults
- **Error Containment**:
- Errors return controlled states (never expose stack traces)
- Malformed history/data discarded safely
- **XSS Prevention**:
- All dynamic content escaped before DOM insertion
- innerHTML never used with user input; use textContent or safe templating
### 4.2 Maintainability & Extensibility
- **Modularity**: Clear separation of math, conversion, history, UI, theme
- **Consistent Code Style**: ESLint (React best practices) + Prettier
- **Documentation**: JSDoc for all public functions and components
- **Extensibility**:
- Add new scientific functions: Extend whitelist + replacement map
- Add new units: Define category + conversion factors
- Add new currencies: Extend code list + default rate
- Add new UI modes: Extend ModeContext + keypad layout
### 4.3 Compatibility
- **Browsers**: Chrome, Firefox, Safari, Edge (latest stable)
- **JavaScript**: ES2020+ support required
- **Dependencies**:
- React 18.2.0 (MIT)
- Vite 4.3.0 (MIT)
- Framer Motion 10.12.0 (MIT)
- CSS Modules (built-in via Vite, MIT)
- All dependencies free/OSS compliant
### 4.4 Testing Strategy
- **Unit Tests** (Jest + React Testing Library):
- Math engine: 100% coverage (edge cases, invalid inputs, large numbers)
- Conversion engines: Bidirectional accuracy, boundary values
- History manager: add/remove/reuse, persistence, limits
- Custom hooks: `useHistory`, `useKeyboard`, `useTheme`, `useFormatting`
- **Integration Tests**:
- Full calculation flow: input → operator → equals → history update
- Mode switching preserves state appropriately
- History item re-use inserts correctly
- Chain conversions work correctly
- **Target**: ≥90% unit test coverage on `core/` and `utils/`; ≥70% on UI interactions
- **Security Tests**:
- Attempt XSS/injection vectors → verify sanitization blocks
- Fuzz testing on expression parser
### 4.5 Accessibility
- **Keyboard**: All functions accessible via keyboard alone
- **Touch Targets**: ≥48x48px on mobile layouts
- **Focus Management**: Clear visible focus rings, logical tab order
- **Screen Reader**: ARIA labels, live regions for dynamic updates
- **Color Contrast**: WCAG AA compliance for text and UI elements
- **Reduced Motion**: Respect `prefers-reduced-motion` media query (animation fallback)
---
## 5. Development Phases & Gates (Per Stakeholder Workflow)
### 5.1 Phase 1: Ideation (Steve) ✅ COMPLETE
- Feasibility/viability research via Q&A
- Finalized exact requirements: standalone utility, scientific calculations, unit/currency conversion, history, dark theme, keyboard support, animations
- Output: Requirements baseline for Turing
### 5.2 Phase 2: Documentation (Turing) ✅ COMPLETE
- PRD written based on Steve's output
- Saved as: `.hermes/docs/PRD-2026-07-26-scientific-calculator.md`
- **Gate**: Ready for Ada's design/planning phase
### 5.3 Phase 3: Design & Planning (Ada) ✅ COMPLETE (PER THIS DOCUMENT)
- Iterative back-and-forth with stakeholder to refine technical plan
- **All elements confirmed**:
- State management: Context API + useReducer, localStorage, corruption recovery
- Math engine: Expression parser, scientific functions, agreed constants, numerical methods
- Conversion systems: Unit (categorized) and currency (manual-rate) with `convert()` syntax
- UI/UX: Dark theme, keyboard support, fluid animations, responsive layout
- Security: Single sanitization point, no `eval()`, Gilfoyle-safe design
- **Output**: This technical plan (Ada's deliverable)
- **Gate**: **STAKEHOLDER APPROVAL REQUIRED** before proceeding to Woz
### 5.4 Phase 4: Documentation (Turing) ⏳ PENDING
- SAD (Solution Architecture Document) written based on Ada's approved plan
- To be saved as: `.hermes/docs/SAD-2026-07-27-scientific-calculator.md`
- **Gate**: Stakeholder approval required before proceeding to specialists
### 5.5 Phase 5: Orchestration (Woz) ⏳ PENDING
- Task distribution to specialists (Linus, Sergey, Zaha, Craig, Gilfoyle, etc.)
- Gilfoyle's security review embedded from start (not afterthought)
- Development proceeds in iterations with stakeholder checkpoints
### 5.6 Phase 6: Development (Specialists) ⏳ PENDING
- Implementation per approved plan and SAD
- Regular commits after each bite-sized task (2-5 min focus)
- Stakeholder approval required before moving to review phase
### 5.7 Phase 7: Independent Review (Satya & Sundar) ⏳ PENDING
- **Satya (Review Specialist)**: Code quality, spec compliance, best practices
- **Sundar (Test Specialist)**: Functional testing, edge cases, performance, accessibility
- **Work Independently**: As specified by stakeholder
- **Gate**: Stakeholder final approval required before deployment
### 5.8 Phase 8: Deployment (Jenson) ⏳ PENDING
- Release to target (local testing environment)
- Stakeholder final go/no-go
---
## 6. Summary: All Elements Agreed Upon
| Component | Specification | Status |
|-----------|---------------|--------|
| State Management | Context API + `useReducer`; localStorage; corruption → last good state | ✅ Agreed |
| Core Processor | Allowlist sanitization; function whitelist; safe `Function` eval | ✅ Agreed |
| Standard Functions | Trig, log, exp, sqrt, abs, rounding, factorial, nCr, nPr, random | ✅ Agreed |
| **Constants** | `c`, `g`, `NA`, `R`, `q_e`, `q_e`,kB`,atm` (pure numbers) | ✅ Agreed |
| **Numerical Methods** | `derivative`, `integral`, `solve` as first-class syntax | ✅ Agreed |
| Unit Conversion | Categorized (8 categories), `convert()` syntax, temp offset | ✅ Agreed |
| Currency Conversion | Manual rates (INR,USD,GBP,EUR,JPY,CAD,AUD), `convert()` syntax | ✅ Agreed |
| History System | Persistent localStorage (last 50), FIFO, click-to-reuse | ✅ Agreed |
| UI/UX | Dark theme, keyboard, animations (Framer Motion), responsive | ✅ Agreed |
| Security (Gilfoyle) | Single sanitizer, no `eval()`, input validation, error containment | ✅ Agreed |
| Performance | Target: ≥55 FPS, <50ms calc latency, <2.5s load, <150KB bundle | ✅ Agreed |
---
## ✅ Current Status: Ready for Stakeholder Approval
This document represents the **complete technical plan** for the scientific calculator with conversion and history features, incorporating all agreements from our iterative design phase.
**Gates Completed**:
- ✅ Ideation (Steve) - Requirements finalized via Q&A
- ✅ Documentation PRD (Turing) - Based on Steve's output
- ✅ Design & Planning (Ada) - Iterative refinement → **Fully detailed plan**
**Current Gate**:
- ⏳ **Awaiting Stakeholder Approval** of this technical plan (this document)
**Once Approved**:
1. Turing will write the **SAD** (Solution Architecture Document) based on this approved plan
2. You will review and approve the **SAD** (gate before specialist distribution)
3. Woz will distribute tasks to specialists (with Gilfoyle's security review embedded from the start)
4. Development will proceed under your oversight
5. Pre-development review (your approval) → Independent review)
→ Deployment (Please review this technical plan. If you have any adjustments or clarifications needed, please specify them now so we can incorporate them before finalizing the plan.
Your formal approval is required to maintain the prescribed gated workflow. I await your guidance to proceed to the SAD phase.
JARVIS, at your service.
+64
View File
@@ -0,0 +1,64 @@
# Task Distribution Plan: Scientific Calculator Project
This plan outlines the distribution of development tasks across specialists, based on the approved Solution Architecture Document (SAD).
## 1. Specialist Assignments by Module
Tasks are assigned to specialists across lanes (A, B, C) to ensure modular parallel development and a strict security review process.
### Phase 1: Core Logic & Security (Highest Priority)
*Critical path: The Math Engine must be secure and functional before UI integration.*
| Module | Files/Components | Assigned Specialist | Lane | Responsibility |
| :--- | :--- | :--- | :--- | :--- |
| **Expression Parser** | `src/core/math/ExpressionParser.js` | **Gilfoyle** | B | Implement allowlist validation, constant substitution, and safe evaluation. **(Security Lead)** |
| **Scientific Functions**| `src/core/math/ScientificFunctions.js`| **Linus** | B | Implement trig, hyperbolic, exp/log, and other standard scientific functions. |
| **Numerical Methods** | `src/core/math/NumericalMethods.js` | **Sergey** | B | Implement `derivative`, `integral`, and `solve` (Newton-Raphson). |
### Phase 2: Specialized Systems
| Module | Files/Components | Assigned Specialist | Lane | Responsibility |
| :--- | :--- | :--- | :--- | :--- |
| **Unit Conversion** | `src/core/conversion/UnitConverter.js`, `UnitDefinitions.js` | **Zaha** | B | Implement category-based conversion logic and unit factor tables. |
| **Currency Conversion**| `src/core/conversion/CurrencyConverter.js`, `ExchangeRateService.js` | **Craig** | B | Implement 3-letter code validation and manual rate management. |
| **History Manager** | `src/core/history/HistoryManager.js`, `useHistory.js` | **Maria** | B | Implement localStorage persistence, FIFO eviction (50 entries), and corruption recovery. |
### Phase 3: Application State & Theme
| Module | Files/Components | Assigned Specialist | Lane | Responsibility |
| :--- | :--- | :--- | :--- | :--- |
| **Theme System** | `src/theme/ThemeContext.js`, `themes.js`, `useTheme.js` | **Ada** | C | Implement dark/light theme switching and CSS variable management. |
| **Mode System** | `src/contexts/ModeContext.js` | **Steve** | C | Implement mode switching state (`standard`, `scientific`, `unit`, `currency`). |
| **Keyboard Handler** | `src/utils/KeyboardHandler.js` | **Woz** | C | Map physical keys to calculator actions and history navigation. |
### Phase 4: UI Components & Animations
| Module | Files/Components | Assigned Specialist | Lane | Responsibility |
| :--- | :--- | :--- | :--- | :--- |
| **Display Bar** | `src/components/display/Display.jsx`, `.module.css` | **Ananta** | C | Implement main result display, syntax highlighting, and error shake animation. |
| **Button System** | `src/components/button/Button.jsx`, `.module.css` | **Sully** | A | Create variant-based button components with press animations. |
| **Keypad System** | `src/components/keypad/Keypad.jsx`, `StandardMode.jsx` etc. | **Lewis** | A | Implement responsive grid layouts for all four operational modes. |
| **History Panel** | `src/components/history/HistoryPanel.jsx`, `HistoryItem.jsx` | **Dinesh** | B | Implement slide-in panel, mobile modal, and click-to-reuse logic. |
| **Animations & Utils**| `src/animations/`, `src/utils/Validator.js`, `Formatter.js` | **Satya** | B | Implement Framer Motion variants and centralized number formatting. |
---
## 2. Development Workflow (The "Gated" Process)
Every specialist must adhere to the following loop for every bite-sized task:
1. **Implement**: Write code according to the SAD specs.
2. **Local Commit**: Commit changes locally.
* **Format**: `<type>(<scope>): <description>`
* *Example*: `feat(math-engine): add derivative function with central difference method`
3. **Notify Turing**: Immediately notify **Turing** (Documentation Specialist) with the commit hash and a brief description.
4. **Documentation Step**: Turing generates a **Commit Changes Document** in `.hermes/docs/commits/` mapping the change to the architecture.
5. **Push**: Push the validated commit to the GitHub/Gitea repository.
---
## 3. Quality Assurance & Integration Gates
| Gate | Actor | Focus | Requirement |
| :--- | :--- | :--- | :--- |
| **Security Audit** | Gilfoyle | Input Sanitization | No `eval`, strict allowlist, safe `Function` usage. |
| **Code Review** | Satya | Quality & Spec | Adherence to React 18 best practices and SAD specs. |
| **Functional Test** | Sundar | Edge Cases | Validating numerical accuracy and responsive UI. |
| **Deployment** | Jenson | Final Release | Production build via Vite and static hosting. |
+8
View File
@@ -0,0 +1,8 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["react", "oxc"],
"rules": {
"react/rules-of-hooks": "error",
"react/only-export-components": ["warn", { "allowConstantExport": true }]
}
}
+16
View File
@@ -0,0 +1,16 @@
# React + Vite
This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
## React Compiler
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
## Expanding the Oxlint configuration
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and Oxlint's TypeScript related rules in your project.
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Scientific Calculator</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
+1332
View File
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
{
"name": "scientific-calculator",
"version": "1.0.0",
"description": "A scientific calculator with unit and currency conversion, history, and animations",
"main": "index.html",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"framer-motion": "^10.12.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.0.0",
"vite": "^4.3.0"
}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.3 KiB

+24
View File
@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="bluesky-icon" viewBox="0 0 16 17">
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
</symbol>
<symbol id="discord-icon" viewBox="0 0 20 19">
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
</symbol>
<symbol id="documentation-icon" viewBox="0 0 21 20">
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
</symbol>
<symbol id="github-icon" viewBox="0 0 19 19">
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
</symbol>
<symbol id="social-icon" viewBox="0 0 20 20">
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
</symbol>
<symbol id="x-icon" viewBox="0 0 19 19">
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
</symbol>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

+184
View File
@@ -0,0 +1,184 @@
.counter {
font-size: 16px;
padding: 5px 10px;
border-radius: 5px;
color: var(--accent);
background: var(--accent-bg);
border: 2px solid transparent;
transition: border-color 0.3s;
margin-bottom: 24px;
&:hover {
border-color: var(--accent-border);
}
&:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
}
.hero {
position: relative;
.base,
.framework,
.vite {
inset-inline: 0;
margin: 0 auto;
}
.base {
width: 170px;
position: relative;
z-index: 0;
}
.framework,
.vite {
position: absolute;
}
.framework {
z-index: 1;
top: 34px;
height: 28px;
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
scale(1.4);
}
.vite {
z-index: 0;
top: 107px;
height: 26px;
width: auto;
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
scale(0.8);
}
}
#center {
display: flex;
flex-direction: column;
gap: 25px;
place-content: center;
place-items: center;
flex-grow: 1;
@media (max-width: 1024px) {
padding: 32px 20px 24px;
gap: 18px;
}
}
#next-steps {
display: flex;
border-top: 1px solid var(--border);
text-align: left;
& > div {
flex: 1 1 0;
padding: 32px;
@media (max-width: 1024px) {
padding: 24px 20px;
}
}
.icon {
margin-bottom: 16px;
width: 22px;
height: 22px;
}
@media (max-width: 1024px) {
flex-direction: column;
text-align: center;
}
}
#docs {
border-right: 1px solid var(--border);
@media (max-width: 1024px) {
border-right: none;
border-bottom: 1px solid var(--border);
}
}
#next-steps ul {
list-style: none;
padding: 0;
display: flex;
gap: 8px;
margin: 32px 0 0;
.logo {
height: 18px;
}
a {
color: var(--text-h);
font-size: 16px;
border-radius: 6px;
background: var(--social-bg);
display: flex;
padding: 6px 12px;
align-items: center;
gap: 8px;
text-decoration: none;
transition: box-shadow 0.3s;
&:hover {
box-shadow: var(--shadow);
}
.button-icon {
height: 18px;
width: 18px;
}
}
@media (max-width: 1024px) {
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
li {
flex: 1 1 calc(50% - 8px);
}
a {
width: 100%;
justify-content: center;
box-sizing: border-box;
}
}
}
#spacer {
height: 88px;
border-top: 1px solid var(--border);
@media (max-width: 1024px) {
height: 48px;
}
}
.ticks {
position: relative;
width: 100%;
&::before,
&::after {
content: '';
position: absolute;
top: -4.5px;
border: 5px solid transparent;
}
&::before {
left: 0;
border-left-color: var(--border);
}
&::after {
right: 0;
border-right-color: var(--border);
}
}
+41
View File
@@ -0,0 +1,41 @@
import React from 'react';
import { ThemeContext } from './theme/ThemeContext';
import { ModeContext } from './contexts/ModeContext';
import { CalculationContext } from './core/math/CalculationContext';
import Display from './components/display/Display';
import Keypad from './components/keypad/Keypad';
import HistoryPanel from './components/history/HistoryPanel';
import { useTheme } from './theme/useTheme';
import { useMode } from './contexts/useMode';
import { useCalculation } from './core/math/useCalculation';
import styles from './styles/App.module.css';
function App() {
const { theme, isTransitioning, toggleTheme } = useTheme();
const { mode, setMode } = useMode();
const { expression, result, isError, history, addToHistory, clearHistory } = useCalculation();
return (
<ThemeContext.Provider value={{ theme, isTransitioning, toggleTheme }}>
<ModeContext.Provider value={{ mode, setMode }}>
<CalculationContext.Provider value={{ expression, result, isError, history, addToHistory, clearHistory }}>
<div className={styles.app}>
<header className={styles.header}>
<h1>Scientific Calculator</h1>
<button onClick={toggleTheme} className={styles.themeToggle}>
{theme === 'dark' ? '☀️' : '🌙'}
</button>
</header>
<main className={styles.main}>
<Display expression={expression} result={result} isError={isError} />
<Keypad />
<HistoryPanel />
</main>
</div>
</CalculationContext.Provider>
</ModeContext.Provider>
</ThemeContext.Provider>
);
}
export default App;
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.5 KiB

+88
View File
@@ -0,0 +1,88 @@
import React, { useState } from 'react';
import styles from './Calculator.module.css';
import { calculate } from '../utils/calculatorLogic';
const Calculator = () => {
const [display, setDisplay] = useState('0');
const [waitingForSecondOperand, setWaitingForSecondOperand] = useState(false);
const [operator, setOperator] = useState(null);
const [firstOperand, setFirstOperand] = useState(null);
const inputDigit = (digit) => {
if (waitingForSecondOperand) {
setDisplay(digit);
setWaitingForSecondOperand(false);
} else {
setDisplay(display === '0' ? digit : display + digit);
}
};
const inputDecimal = (dot) => {
if (waitingForSecondOperand) {
setDisplay('0.');
setWaitingForSecondOperand(false);
return;
}
if (!display.includes(dot)) {
setDisplay(display + dot);
}
};
const handleOperator = (nextOperator) => {
const inputValue = parseFloat(display);
if (firstOperand === null) {
setFirstOperand(inputValue);
} else if (operator) {
const currentValue = firstOperand || 0;
const result = calculate(currentValue, operator, display);
setDisplay(String(result));
setFirstOperand(result);
}
setWaitingForSecondOperand(true);
setOperator(nextOperator);
};
const resetCalculator = () => {
setDisplay('0');
setWaitingForSecondOperand(false);
setOperator(null);
setFirstOperand(null);
};
const handleEquals = () => {
if (operator && firstOperand !== null) {
const result = calculate(firstOperand, operator, display);
setDisplay(String(result));
setWaitingForSecondOperand(true);
setOperator(null);
setFirstOperand(null);
}
};
return (
<div className={styles.calculator}>
<div className={styles.display}>{display}</div>
<div className={styles.keypad}>
<button className={styles.button} onClick={() => resetCalculator()}>AC</button>
<button className={styles.button} onClick={() => handleOperator('/')}>÷</button>
<button className={styles.button} onClick={() => handleOperator('*')}>×</button>
<button className={styles.button} onClick={() => handleOperator('-')}>−</button>
<button className={styles.button} onClick={() => inputDigit('7')}>7</button>
<button className={styles.button} onClick={() => inputDigit('8')}>8</button>
<button className={styles.button} onClick={() => inputDigit('9')}>9</button>
<button className={styles.button} onClick={() => handleOperator('+')}>+</button>
<button className={styles.button} onClick={() => inputDigit('4')}>4</button>
<button className={styles.button} onClick={() => inputDigit('5')}>5</button>
<button className={styles.button} onClick={() => inputDigit('6')}>6</button>
<button className={styles.button} onClick={() => inputDigit('1')}>1</button>
<button className={styles.button} onClick={() => inputDigit('2')}>2</button>
<button className={styles.button} onClick={() => inputDigit('3')}>3</button>
<button className={styles.button} onClick={() => inputDecimal('.')}>.</button>
<button className={styles.button} onClick={() => inputDigit('0')}>0</button>
<button className={styles.button} onClick={() => handleEquals()}> = </button>
</div>
</div>
);
};
export default Calculator;
+101
View File
@@ -0,0 +1,101 @@
.calculator {
width: 320px;
margin: 2rem auto;
padding: 1.5rem;
background: #1e1e1e;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.display {
width: 100%;
height: 70px;
margin-bottom: 1.5rem;
padding: 0 1rem;
font-size: 2.5rem;
text-align: right;
background: #2c2c2c;
color: #fff;
border: none;
border-radius: 8px;
font-family: 'Space Mono', monospace;
letter-spacing: 0.5px;
}
.keypad {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
.button {
width: 100%;
aspect-ratio: 1 / 1;
font-size: 1.25rem;
font-weight: 600;
border: none;
border-radius: 50%;
background: #fff;
color: #333;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.button:hover {
background: #e9e9e9;
transform: scale(1.05);
}
.button:active {
transform: scale(0.95);
}
.button.operator {
background: #ff9500;
color: white;
}
.button.operator:hover {
background: #ffb14d;
}
.button.equal {
background: #ff9500;
color: white;
grid-column: span 2;
border-radius: 50px;
}
.button.equal:hover {
background: #ffb14d;
}
.button.zero {
grid-column: span 2;
border-radius: 50px;
}
/* Responsive adjustments */
@media (max-width: 400px) {
.calculator {
width: 90%;
margin: 1rem auto;
padding: 1rem;
}
.display {
height: 50px;
font-size: 1.8rem;
}
.button {
font-size: 1.1rem;
}
.button.zero {
width: 105px;
}
}
+111
View File
@@ -0,0 +1,111 @@
:root {
--text: #6b6375;
--text-h: #08060d;
--bg: #fff;
--border: #e5e4e7;
--code-bg: #f4f3ec;
--accent: #aa3bff;
--accent-bg: rgba(170, 59, 255, 0.1);
--accent-border: rgba(170, 59, 255, 0.5);
--social-bg: rgba(244, 243, 236, 0.5);
--shadow:
rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
--sans: system-ui, 'Segoe UI', Roboto, sans-serif;
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
--mono: ui-monospace, Consolas, monospace;
font: 18px/145% var(--sans);
letter-spacing: 0.18px;
color-scheme: light dark;
color: var(--text);
background: var(--bg);
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@media (max-width: 1024px) {
font-size: 16px;
}
}
@media (prefers-color-scheme: dark) {
:root {
--text: #9ca3af;
--text-h: #f3f4f6;
--bg: #16171d;
--border: #2e303a;
--code-bg: #1f2028;
--accent: #c084fc;
--accent-bg: rgba(192, 132, 252, 0.15);
--accent-border: rgba(192, 132, 252, 0.5);
--social-bg: rgba(47, 48, 58, 0.5);
--shadow:
rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
}
#social .button-icon {
filter: invert(1) brightness(2);
}
}
body {
margin: 0;
}
#root {
width: 1126px;
max-width: 100%;
margin: 0 auto;
text-align: center;
border-inline: 1px solid var(--border);
min-height: 100svh;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
h1,
h2 {
font-family: var(--heading);
font-weight: 500;
color: var(--text-h);
}
h1 {
font-size: 56px;
letter-spacing: -1.68px;
margin: 32px 0;
@media (max-width: 1024px) {
font-size: 36px;
margin: 20px 0;
}
}
h2 {
font-size: 24px;
line-height: 118%;
letter-spacing: -0.24px;
margin: 0 0 8px;
@media (max-width: 1024px) {
font-size: 20px;
}
}
p {
margin: 0;
}
code,
.counter {
font-family: var(--mono);
display: inline-flex;
border-radius: 4px;
color: var(--text-h);
}
code {
font-size: 15px;
line-height: 135%;
padding: 4px 8px;
background: var(--code-bg);
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
+13
View File
@@ -0,0 +1,13 @@
export const calculate = (num1, operator, num2) => {
const n1 = parseFloat(num1);
const n2 = parseFloat(num2);
switch (operator) {
case '+': return n1 + n2;
case '-': return n1 - n2;
case '*': return n1 * n2;
case '/':
if (n2 === 0) return 'Error';
return n1 / n2;
default: return null;
}
};
+14
View File
@@ -0,0 +1,14 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
},
build: {
outDir: 'dist',
assetsDir: 'assets',
},
});