Added bracket support

This commit is contained in:
RomanNiki 2024-04-08 14:11:43 +03:00
parent a7ef4b0af7
commit a9be1638c3
8 changed files with 164 additions and 72 deletions

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -28,5 +28,7 @@ public enum Operation
Cosh,
Cos,
Tanh,
Tan
Tan,
OpenBracket,
CloseBracket
}

View file

@ -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);
}

2
Form1.Designer.cs generated
View file

@ -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
//

View file

@ -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);
}
}
}

View file

@ -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<double?> Values { get; set; } = new();
public Stack<Operation> Operations { get; set; } = new();
}