diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index 701fb21c..a4300edc 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -163,7 +163,15 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) { m_bRecord = true; m_input.Clear(); - CheckAndAddLastBinOpToHistory(); + + /* + * Account for scenarios where an equation includes any input after closing parenthesis - i.e. "(8)2=16". + * This prevents the calculator from ending an equation and adding to history prematurely. + */ + if (m_nLastCom != IDC_CLOSEP) + { + CheckAndAddLastBinOpToHistory(); + } } // Interpret digit keys. @@ -185,6 +193,38 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) return; } + // Check if the last command was a closing parenthesis + if (m_nLastCom == IDC_CLOSEP) + { + // Treat this as an implicit multiplication + m_nOpCode = IDC_MUL; + m_lastVal = m_currentVal; + + // We need to clear any previous state from last calculation + m_holdVal = Rational(0); + m_bNoPrevEqu = true; + + // Add the operand to history before adding the implicit multiplication + if (!m_HistoryCollector.FOpndAddedToHistory()) + { + m_HistoryCollector.AddOpenBraceToHistory(); + m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); + m_HistoryCollector.AddCloseBraceToHistory(); + } + + // Add the implicit multiplication to history + m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode); + + m_bChangeOp = true; + m_nPrevOpCode = 0; + + // Clear any pending operations in the precedence stack + while (m_precedenceOpCount > 0) + { + m_precedenceOpCount--; + m_nPrecOp[m_precedenceOpCount] = 0; + } + } DisplayNum(); return; @@ -504,11 +544,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) { wstring groupedString = GroupDigitsPerRadix(m_numberString, m_radix); m_HistoryCollector.CompleteEquation(groupedString); + + m_lastVal = m_currentVal; + m_nPrevOpCode = 0; + m_precedenceOpCount = 0; } m_bChangeOp = false; - m_nPrevOpCode = 0; - break; case IDC_OPENP: @@ -790,6 +832,40 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) break; case IDC_PNT: + + // Check if the last command was a closing parenthesis + if (m_nLastCom == IDC_CLOSEP) + { + // Treat this as an implicit multiplication + m_nOpCode = IDC_MUL; + m_lastVal = m_currentVal; + + // We need to clear any previous state from last calculation + m_holdVal = Rational(0); + m_bNoPrevEqu = true; + + // Add the operand to history before adding the implicit multiplication + if (!m_HistoryCollector.FOpndAddedToHistory()) + { + m_HistoryCollector.AddOpenBraceToHistory(); + m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); + m_HistoryCollector.AddCloseBraceToHistory(); + } + + // Add the implicit multiplication to history + m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode); + + m_bChangeOp = true; + m_nPrevOpCode = 0; + + // Clear any pending operations in the precedence stack + while (m_precedenceOpCount > 0) + { + m_precedenceOpCount--; + m_nPrecOp[m_precedenceOpCount] = 0; + } + } + if (m_bRecord && !m_fIntegerMode && m_input.TryAddDecimalPt()) { DisplayNum(); diff --git a/src/CalculatorUITests/ScientificModeFunctionalTests.cs b/src/CalculatorUITests/ScientificModeFunctionalTests.cs index 21e43f0b..9911bf8e 100644 --- a/src/CalculatorUITests/ScientificModeFunctionalTests.cs +++ b/src/CalculatorUITests/ScientificModeFunctionalTests.cs @@ -4,6 +4,7 @@ using CalculatorUITestFramework; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; namespace CalculatorUITests { @@ -133,6 +134,81 @@ namespace CalculatorUITests Assert.AreEqual("12", page.CalculatorResults.GetCalculatorResultText()); } + [TestMethod] + [Priority(0)] + public void SmokeTest_CloseParenthesis() + { + /* + * TEST #1 + */ + page.ScientificOperators.ParenthesisLeftButton.Click(); + page.StandardOperators.NumberPad.Input(8); + page.ScientificOperators.ParenthesisRightButton.Click(); + page.StandardOperators.NumberPad.Input(2); + page.StandardOperators.EqualButton.Click(); + + // Assert calculator & history results + Assert.AreEqual("16", page.CalculatorResults.GetCalculatorResultText()); + Assert.AreEqual("(8) \x00D7 2=", page.CalculatorResults.GetCalculatorExpressionText()); + + var historyItems0 = page.HistoryPanel.GetAllHistoryListViewItems(); + Assert.IsTrue(historyItems0[0].GetValue().Equals("16", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems0[0].GetExpression().Equals("(8) \x00D7 2=", StringComparison.InvariantCultureIgnoreCase)); + + /* + * TEST #2 + */ + page.ScientificOperators.ParenthesisLeftButton.Click(); + page.StandardOperators.NumberPad.Input(7); + page.StandardOperators.MultiplyButton.Click(); + page.StandardOperators.NumberPad.Input(2); + page.ScientificOperators.ParenthesisRightButton.Click(); + page.StandardOperators.NumberPad.Input(2); + page.StandardOperators.EqualButton.Click(); + + // Assert calculator & history results + Assert.AreEqual("28", page.CalculatorResults.GetCalculatorResultText()); + Assert.AreEqual("(7 \x00D7 2) \x00D7 2=", page.CalculatorResults.GetCalculatorExpressionText()); + + var historyItems1 = page.HistoryPanel.GetAllHistoryListViewItems(); + Assert.IsTrue(historyItems1[0].GetValue().Equals("28", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems1[0].GetExpression().Equals("(7 \x00D7 2) \x00D7 2=", StringComparison.InvariantCultureIgnoreCase)); + + /* + * TEST #3 + */ + page.ScientificOperators.ParenthesisLeftButton.Click(); + page.StandardOperators.NumberPad.Input(8); + page.ScientificOperators.ParenthesisRightButton.Click(); + page.StandardOperators.NumberPad.Input(0.5); + page.StandardOperators.EqualButton.Click(); + + // Assert calculator & history results + Assert.AreEqual("4", page.CalculatorResults.GetCalculatorResultText()); + Assert.AreEqual("(8) \x00D7 0.5=", page.CalculatorResults.GetCalculatorExpressionText()); + + var historyItems2 = page.HistoryPanel.GetAllHistoryListViewItems(); + Assert.IsTrue(historyItems2[0].GetValue().Equals("4", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems2[0].GetExpression().Equals("(8) \x00D7 0.5=", StringComparison.InvariantCultureIgnoreCase)); + + /* + * TEST #4 + */ + page.ScientificOperators.ParenthesisLeftButton.Click(); + page.StandardOperators.NumberPad.Input(8); + page.ScientificOperators.ParenthesisRightButton.Click(); + page.StandardOperators.NumberPad.Input(.5); + page.StandardOperators.EqualButton.Click(); + + // Assert calculator & history results + Assert.AreEqual("4", page.CalculatorResults.GetCalculatorResultText()); + Assert.AreEqual("(8) \x00D7 0.5=", page.CalculatorResults.GetCalculatorExpressionText()); + + var historyItems3 = page.HistoryPanel.GetAllHistoryListViewItems(); + Assert.IsTrue(historyItems3[0].GetValue().Equals("4", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems3[0].GetExpression().Equals("(8) \x00D7 0.5=", StringComparison.InvariantCultureIgnoreCase)); + } + [TestMethod] [Priority(0)] public void SmokeTest_RadianAngleOperator() diff --git a/src/CalculatorUnitTests/CalculatorManagerTest.cpp b/src/CalculatorUnitTests/CalculatorManagerTest.cpp index 73e83c0a..d5b574f7 100644 --- a/src/CalculatorUnitTests/CalculatorManagerTest.cpp +++ b/src/CalculatorUnitTests/CalculatorManagerTest.cpp @@ -643,6 +643,26 @@ namespace CalculatorManagerTest Command commands5[] = { Command::Command2, Command::CommandOPENP, Command::Command2, Command::CommandCLOSEP, Command::CommandADD, Command::CommandEQU, Command::CommandNULL }; TestDriver::Test(L"8", L"2 \x00D7 (2) + 4=", commands5, true, true); + + Command commands6[] = { Command::CommandOPENP, Command::Command8, Command::CommandCLOSEP, Command::Command2, Command::CommandEQU, Command::CommandNULL }; + TestDriver::Test(L"16", L"(8) \x00D7 2=", commands6, true, true); + + Command commands7[] = { Command::CommandOPENP, Command::Command7, Command::CommandMUL, Command::Command2, + Command::CommandCLOSEP, Command::Command2, Command::CommandEQU, Command::CommandNULL }; + TestDriver::Test(L"28", L"(7 \x00D7 2) \x00D7 2=", commands7, true, true); + + Command commands8[] = { Command::CommandOPENP, Command::Command7, Command::CommandMUL, Command::Command2, + Command::CommandCLOSEP, Command::Command2, Command::CommandEQU, + Command::CommandOPENP, Command::Command1, Command::Command4, Command::CommandCLOSEP, Command::Command2, Command::CommandEQU, Command::CommandNULL}; + TestDriver::Test(L"28", L"(14) \x00D7 2=", commands8, true, true); + + Command commands9[] = { Command::CommandOPENP, Command::Command8, Command::CommandCLOSEP, + Command::Command0, Command::CommandPNT, Command::Command5, Command::CommandEQU, Command::CommandNULL }; + TestDriver::Test(L"4", L"(8) \x00D7 0.5=", commands9, true, true); + + Command commands10[] = { Command::CommandOPENP, Command::Command8, Command::CommandCLOSEP, + Command::CommandPNT, Command::Command5, Command::CommandEQU, Command::CommandNULL }; + TestDriver::Test(L"4", L"(8) \x00D7 0.5=", commands10, true, true); } void CalculatorManagerTest::CalculatorManagerTestScientificError()