diff --git a/.idea/.idea.calculator/.idea/git_toolbox_prj.xml b/.idea/.idea.calculator/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/.idea.calculator/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/Commands/CalculateCommand.cs b/Commands/CalculateCommand.cs deleted file mode 100644 index 782282f..0000000 --- a/Commands/CalculateCommand.cs +++ /dev/null @@ -1,38 +0,0 @@ -using calculator.Common; -using calculator.Model; -using calculator.Services; - -namespace calculator.Commands; - -public class CalculateCommand : ICommand -{ - private readonly ICaculator _caculator; - private readonly CaculatorData _data; - private readonly double? _b; - private readonly Operation _operation; - private double? _previousValue; - - public CalculateCommand(ICaculator caculator, CaculatorData data) - { - _caculator = caculator; - _data = data; - _operation = data.Operation.Value; - - if (double.TryParse(data.Input, out var b)) - _b = b; - } - - public void Execute() - { - if (_data.Value is null) - return; - _previousValue = _data.Value; - _data.Value = _caculator.Calculate(_operation, _data.Value.Value, _b); - _data.Input = null; - } - - public void Undo() - { - _data.Value = _previousValue; - } -} \ No newline at end of file diff --git a/Common/CalculatorExtensions.cs b/Common/CalculatorExtensions.cs new file mode 100644 index 0000000..60b2a36 --- /dev/null +++ b/Common/CalculatorExtensions.cs @@ -0,0 +1,56 @@ +namespace calculator.Common; + +public static class CalculatorExtensions +{ + public static int Precedence(this Operation op) + { + switch (op) + { + case Operation.Add: + case Operation.Sub: + return 1; + case Operation.Mul: + case Operation.Div: + case Operation.Factorial: + return 2; + case Operation.PowY: + case Operation.SqrtY: + return 3; + case Operation.Cube: + case Operation.Pow: + case Operation.Sqrt: + case Operation.CubeRoot: + case Operation.Square: + case Operation.Log: + case Operation.Ln: + case Operation.Exp: + case Operation.Inv: + case Operation.Pi: + case Operation.OneDiv: + case Operation.Mod: + case Operation.Neg: + case Operation.Percent: + case Operation.Sinh: + case Operation.Sin: + case Operation.Cosh: + case Operation.Cos: + case Operation.Tanh: + case Operation.Tan: + return 4; + default: + case Operation.OpenBracket: + case Operation.CloseBracket: + return 0; + } + } + + public static bool IsBigger(this Operation a, Operation b) + { + return Precedence(a) > Precedence(b); + } + + public static bool IsLowerOrEqual(this Operation a, Operation b) + { + return Precedence(a) <= Precedence(b); + } +} \ No newline at end of file diff --git a/Common/Operation.cs b/Common/Operation.cs index b969da4..b9b187e 100644 --- a/Common/Operation.cs +++ b/Common/Operation.cs @@ -28,5 +28,7 @@ public enum Operation Cosh, Cos, Tanh, - Tan + Tan, + OpenBracket, + CloseBracket } \ No newline at end of file diff --git a/Controller/CaculatorController.cs b/Controller/CaculatorController.cs index 612b414..7805afc 100644 --- a/Controller/CaculatorController.cs +++ b/Controller/CaculatorController.cs @@ -1,5 +1,4 @@ -using calculator.Commands; -using calculator.Common; +using calculator.Common; using calculator.Model; using calculator.Services; using calculator.View; @@ -12,7 +11,6 @@ public class CaculatorController private readonly IInputService _inputService; private readonly ICaculatorView _view; private readonly CaculatorData _data; - private ICommand? _currentCommand; public CaculatorController(ICaculator caculator, IInputService inputService, ICaculatorView view, CaculatorData data) @@ -32,9 +30,14 @@ public class CaculatorController private void OnSingleOperationPressed(Operation operation) { - OnOperatorPressed(operation); - _currentCommand = new CalculateCommand(_caculator, _data); - OnCalculatePressed(); + if (_data.Values.Count == 0) + return; + + if (double.TryParse(_data.Input, out var value) == false) + return; + + _data.Values.Push(_caculator.Calculate(operation, value)); + UpdateView(_data.Values.Peek()!.Value); } private void OnClearPressed(bool full) @@ -42,60 +45,104 @@ public class CaculatorController Clear(full: full); } + private void Calculate(bool fullAnswer = true) + { + if (_data.Operations.Count == 0) + return; + + if (_data.Values.Count == 0) + return; + + if (TryGetValueFromInput() == false) + return; + + PerformCalculation(fullAnswer); + + UpdateView(_data.Values.Peek()!.Value); + } + private void OnCalculatePressed() { - if (_data.Operation is null) - return; + Calculate(); + } - if (_data.Value is null) - return; - - if (_data is not { Caculated: true, Input: null } || _currentCommand == null) + private void PerformCalculation(bool fullAnswer = true) + { + while (true) { - _currentCommand = new CalculateCommand(_caculator, _data); + while (_data.Operations.Count > 0 && _data.Operations.Peek() != Operation.OpenBracket) + { + var b = _data.Values.Pop(); + var a = _data.Values.Pop(); + _data.Values.Push(_caculator.Calculate(_data.Operations.Pop(), a!.Value, b!.Value)); + } + + if (_data.Operations.Count > 0 && _data.Operations.Peek() == Operation.OpenBracket && fullAnswer) + { + _data.Operations.Pop(); + } + + if (_data.Operations.Count > 0 && fullAnswer) + { + continue; + } + + break; } - - _currentCommand?.Execute(); - _data.Caculated = true; - UpdateView(_data.Value.Value); } private void Clear(string value = "0", bool full = true) { if (full) { - _data.Value = null; - _data.Operation = null; + _data.Values.Clear(); + _data.Operations.Clear(); } - - _data.Caculated = false; + _data.Input = null; _view.UpdateView(value); } private void OnOperatorPressed(Operation operation) { - if (_data.Input == null && _data.Value == null) - return; - - if (_data is { Caculated: false, Input: not null, Value: not null }) + if (_data.Operations.Count > 0) { - OnCalculatePressed(); + if (operation == Operation.CloseBracket) + { + Calculate(false); + return; + } + + if (operation != Operation.OpenBracket && operation.IsLowerOrEqual(_data.Operations.Peek())) + { + Calculate(false); + } } - _data.Operation = operation; + _data.Operations.Push(operation); - if (_data.Input != null) + TryGetValueFromInput(); + } + + private bool TryGetValueFromInput() + { + if (_data.Input is not null) { - _data.Value = double.Parse(_data.Input); + if (double.TryParse(_data.Input, out var value) == false) + { + return false; + } + + _data.Values.Push(value); } _data.Input = null; + return true; } private void OnOperandPressed(char obj) { - if (_data.Caculated) + if (_data.Operations.Count == 0 && _data.Input == null) { Clear(full: true); } diff --git a/Form1.Designer.cs b/Form1.Designer.cs index 53bd2c3..4087726 100644 --- a/Form1.Designer.cs +++ b/Form1.Designer.cs @@ -403,6 +403,7 @@ button23.TabIndex = 35; button23.Text = ")"; button23.UseVisualStyleBackColor = true; + button23.Click += OnCloseBracketButtonClick; // // button30 // @@ -414,6 +415,7 @@ button30.TabIndex = 34; button30.Text = "("; button30.UseVisualStyleBackColor = true; + button30.Click += OnOpenBracketButtonClick; // // Ln_button // diff --git a/Form1.cs b/Form1.cs index 074e7e4..8944a74 100644 --- a/Form1.cs +++ b/Form1.cs @@ -221,5 +221,14 @@ namespace calculator SingleOperatorPressed?.Invoke(Operation.Pi); } + private void OnOpenBracketButtonClick(object? sender, EventArgs e) + { + OperatorPressed?.Invoke(Operation.OpenBracket); + } + + private void OnCloseBracketButtonClick(object? sender, EventArgs e) + { + OperatorPressed?.Invoke(Operation.CloseBracket); + } } } \ No newline at end of file diff --git a/Model/CaculatorData.cs b/Model/CaculatorData.cs index ddcd271..87e12c5 100644 --- a/Model/CaculatorData.cs +++ b/Model/CaculatorData.cs @@ -5,7 +5,6 @@ namespace calculator.Model; public class CaculatorData { public string? Input { get; set; } - public double? Value { get; set; } - public Operation? Operation { get; set; } - public bool Caculated { get; set; } + public Stack Values { get; set; } = new(); + public Stack Operations { get; set; } = new(); } \ No newline at end of file