UNPKG

@plotinus/matrix-package-calculator

Version:

Calculator components for the Matrix framework - basic arithmetic operations with UI

176 lines (175 loc) 7.38 kB
import { BaseCommunicationComponent } from '@matrix/framework'; import { logInfo, logDebug } from '@matrix/logger'; export class CalculatorComponent extends BaseCommunicationComponent { constructor() { super(...arguments); this.calculatorState = { display: '0', currentValue: 0, previousValue: null, pendingOperation: null, waitingForNewValue: false, history: [] }; } onInit() { logInfo(`Calculator:${this.id}: Initialized with clean state.`); this.setState(this.calculatorState); } startExecution() { logInfo(`Calculator:${this.id}: Starting execution. Calculator is ready.`); this.emitEvent('CalculatorReady', { calculatorId: this.id }); } // DSL binding: onCalculate="calculateHandler" calculateHandler(calculation) { logInfo(`Calculator:${this.id}: Received calculate command.`); logDebug(`Calculator:${this.id}: Calculation details`, calculation); const result = this.performCalculation(calculation); this.setState(this.calculatorState); logInfo(`Calculator:${this.id}: Calculation completed. Result: ${this.calculatorState.display}`); this.emitEvent('CalculationComplete', { calculatorId: this.id, calculation, result: this.calculatorState.display, state: { ...this.calculatorState } }); return result; } // DSL binding: onNumberInput="numberInputHandler" numberInputHandler(data) { logInfo(`Calculator:${this.id}: Number input received: ${data.digit}`); if (this.calculatorState.waitingForNewValue) { this.calculatorState.display = data.digit.toString(); this.calculatorState.currentValue = data.digit; this.calculatorState.waitingForNewValue = false; } else { if (this.calculatorState.display === '0') { this.calculatorState.display = data.digit.toString(); } else { this.calculatorState.display += data.digit.toString(); } this.calculatorState.currentValue = parseFloat(this.calculatorState.display); } this.setState(this.calculatorState); this.emitEvent('DisplayUpdated', { calculatorId: this.id, display: this.calculatorState.display, value: this.calculatorState.currentValue }); } // DSL binding: onOperation="operationHandler" operationHandler(data) { logInfo(`Calculator:${this.id}: Operation received: ${data.operation}`); if (this.calculatorState.pendingOperation && !this.calculatorState.waitingForNewValue) { // Complete pending operation first const calculation = { id: `calc-${Date.now()}`, operation: this.calculatorState.pendingOperation, operand: this.calculatorState.currentValue, timestamp: Date.now() }; this.performCalculation(calculation); } else { this.calculatorState.previousValue = this.calculatorState.currentValue; } this.calculatorState.pendingOperation = data.operation; this.calculatorState.waitingForNewValue = true; this.setState(this.calculatorState); this.emitEvent('OperationSet', { calculatorId: this.id, operation: data.operation, display: this.calculatorState.display }); } // DSL binding: onEquals="equalsHandler" equalsHandler() { logInfo(`Calculator:${this.id}: Equals operation received`); if (this.calculatorState.pendingOperation && this.calculatorState.previousValue !== null) { const calculation = { id: `calc-${Date.now()}`, operation: this.calculatorState.pendingOperation, operand: this.calculatorState.currentValue, timestamp: Date.now() }; this.performCalculation(calculation); this.calculatorState.pendingOperation = null; this.calculatorState.previousValue = null; this.calculatorState.waitingForNewValue = true; this.setState(this.calculatorState); this.emitEvent('EqualsComplete', { calculatorId: this.id, result: this.calculatorState.display }); } } // DSL binding: onClear="clearHandler" clearHandler() { logInfo(`Calculator:${this.id}: Clear operation received`); this.calculatorState = { display: '0', currentValue: 0, previousValue: null, pendingOperation: null, waitingForNewValue: false, history: [...this.calculatorState.history] // Keep history but reset everything else }; const clearCalculation = { id: `clear-${Date.now()}`, operation: 'clear', timestamp: Date.now() }; this.calculatorState.history.push(clearCalculation); this.setState(this.calculatorState); this.emitEvent('CalculatorCleared', { calculatorId: this.id, display: this.calculatorState.display }); } performCalculation(calculation) { let result = this.calculatorState.currentValue; if (this.calculatorState.previousValue !== null && calculation.operand !== undefined) { switch (calculation.operation) { case 'add': result = this.calculatorState.previousValue + calculation.operand; break; case 'subtract': result = this.calculatorState.previousValue - calculation.operand; break; case 'multiply': result = this.calculatorState.previousValue * calculation.operand; break; case 'divide': if (calculation.operand === 0) { logInfo(`Calculator:${this.id}: Division by zero attempted`); this.calculatorState.display = 'Error'; this.emitEvent('CalculationError', { calculatorId: this.id, error: 'Division by zero', calculation }); return this.calculatorState.currentValue; } result = this.calculatorState.previousValue / calculation.operand; break; } } // Update state this.calculatorState.currentValue = result; this.calculatorState.display = result.toString(); this.calculatorState.history.push(calculation); logDebug(`Calculator:${this.id}: Calculation result`, { calculation, result }); return result; } // Method to get calculation history - useful for external queries getHistory() { return [...this.calculatorState.history]; } // Method to get current state - useful for external queries getCurrentState() { return { ...this.calculatorState }; } } CalculatorComponent.dslTag = 'calculator-definition';