calculator = new CalculatorService(); } /** * Test basic arithmetic operations */ public function testBasicArithmetic() { // Addition and multiplication precedence $result = $this->calculator->calculate('1+2*3'); $this->assertEquals(7.0, $result); // Parentheses $result = $this->calculator->calculate('(1+2)*3'); $this->assertEquals(9.0, $result); // Division $result = $this->calculator->calculate('10/2'); $this->assertEquals(5.0, $result); // Power $result = $this->calculator->calculate('2^3'); $this->assertEquals(8.0, $result); } /** * Test formula with simple variables */ public function testFormulaWithVariables() { $formula = '{result} * {factor}'; $variables = ['result' => 50, 'factor' => 2]; $result = $this->calculator->calculate($formula, $variables); $this->assertEquals(100.0, $result); } /** * Test formula with gender variable (numeric values) */ public function testFormulaWithGenderNumeric() { // Gender: 0=Unknown, 1=Female, 2=Male $formula = '50 + {gender} * 10'; // Male (2) $result = $this->calculator->calculate($formula, ['gender' => 2]); $this->assertEquals(70.0, $result); // Female (1) $result = $this->calculator->calculate($formula, ['gender' => 1]); $this->assertEquals(60.0, $result); // Unknown (0) $result = $this->calculator->calculate($formula, ['gender' => 0]); $this->assertEquals(50.0, $result); } /** * Test formula with gender variable (string values) */ public function testFormulaWithGenderString() { $formula = '50 + {gender} * 10'; // String values $result = $this->calculator->calculate($formula, ['gender' => 'male']); $this->assertEquals(70.0, $result); $result = $this->calculator->calculate($formula, ['gender' => 'female']); $this->assertEquals(60.0, $result); $result = $this->calculator->calculate($formula, ['gender' => 'unknown']); $this->assertEquals(50.0, $result); } /** * Test mathematical functions */ public function testMathFunctions() { // Square root $result = $this->calculator->calculate('sqrt(16)'); $this->assertEquals(4.0, $result); // Sine $result = $this->calculator->calculate('sin(pi/2)'); $this->assertEqualsWithDelta(1.0, $result, 0.0001); // Cosine $result = $this->calculator->calculate('cos(0)'); $this->assertEquals(1.0, $result); // Logarithm $result = $this->calculator->calculate('log(100)'); $this->assertEqualsWithDelta(4.60517, $result, 0.0001); // Natural log (ln) $result = $this->calculator->calculate('ln(2.71828)'); $this->assertEqualsWithDelta(1.0, $result, 0.0001); // Exponential $result = $this->calculator->calculate('exp(1)'); $this->assertEqualsWithDelta(2.71828, $result, 0.0001); } /** * Test formula validation */ public function testFormulaValidation() { // Valid formula $validation = $this->calculator->validate('{result} * 2 + 5'); $this->assertTrue($validation['valid']); $this->assertNull($validation['error']); // Invalid formula $validation = $this->calculator->validate('{result} * * 2'); $this->assertFalse($validation['valid']); $this->assertNotNull($validation['error']); } /** * Test variable extraction */ public function testExtractVariables() { $formula = '{result} * {factor} + {gender} - {age}'; $variables = $this->calculator->extractVariables($formula); $this->assertEquals(['result', 'factor', 'gender', 'age'], $variables); } /** * Test missing variable error */ public function testMissingVariableError() { $this->expectException(\Exception::class); $this->expectExceptionMessage("Missing variable value for: missing_var"); $this->calculator->calculate('{result} + {missing_var}', ['result' => 10]); } /** * Test invalid formula syntax error */ public function testInvalidFormulaError() { $this->expectException(\Exception::class); $this->expectExceptionMessage("Invalid formula"); $this->calculator->calculate('1 + * 2'); } /** * Test complex formula with multiple variables */ public function testComplexFormula() { // Complex formula: (result * factor / 100) + (gender * 5) - (age * 0.1) $formula = '({result} * {factor} / 100) + ({gender} * 5) - ({age} * 0.1)'; $variables = [ 'result' => 200, 'factor' => 10, 'gender' => 2, // Male 'age' => 30 ]; // Expected: (200 * 10 / 100) + (2 * 5) - (30 * 0.1) = 20 + 10 - 3 = 27 $result = $this->calculator->calculate($formula, $variables); $this->assertEquals(27.0, $result); } /** * Test calculation from TestDefCal definition */ public function testCalculateFromDefinition() { $calcDef = [ 'FormulaCode' => '{result} * {factor} + 10', 'Factor' => 2, ]; $testValues = [ 'result' => 50, ]; // Expected: 50 * 2 + 10 = 110 $result = $this->calculator->calculateFromDefinition($calcDef, $testValues); $this->assertEquals(110.0, $result); } /** * Test calculation with all optional variables */ public function testCalculateWithAllVariables() { $calcDef = [ 'FormulaCode' => '{result} + {factor} + {gender} + {age} + {ref_low} + {ref_high}', 'Factor' => 5, ]; $testValues = [ 'result' => 10, 'gender' => 1, 'age' => 25, 'ref_low' => 5, 'ref_high' => 15, ]; // Expected: 10 + 5 + 1 + 25 + 5 + 15 = 61 $result = $this->calculator->calculateFromDefinition($calcDef, $testValues); $this->assertEquals(61.0, $result); } /** * Test empty formula error */ public function testEmptyFormulaError() { $this->expectException(\Exception::class); $this->expectExceptionMessage("No formula defined"); $calcDef = [ 'FormulaCode' => '', 'Factor' => 1, ]; $this->calculator->calculateFromDefinition($calcDef, ['result' => 10]); } /** * Test implicit multiplication */ public function testImplicitMultiplication() { // math-parser supports implicit multiplication (2x means 2*x) $result = $this->calculator->calculate('2*3'); $this->assertEquals(6.0, $result); } /** * Test decimal calculations */ public function testDecimalCalculations() { $formula = '{result} / 3'; $result = $this->calculator->calculate($formula, ['result' => 10]); $this->assertEqualsWithDelta(3.33333, $result, 0.0001); } }