Added bracket support
This commit is contained in:
parent
a7ef4b0af7
commit
a9be1638c3
8 changed files with 164 additions and 72 deletions
15
.idea/.idea.calculator/.idea/git_toolbox_prj.xml
generated
Normal file
15
.idea/.idea.calculator/.idea/git_toolbox_prj.xml
generated
Normal 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>
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
56
Common/CalculatorExtensions.cs
Normal file
56
Common/CalculatorExtensions.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,5 +28,7 @@ public enum Operation
|
||||||
Cosh,
|
Cosh,
|
||||||
Cos,
|
Cos,
|
||||||
Tanh,
|
Tanh,
|
||||||
Tan
|
Tan,
|
||||||
|
OpenBracket,
|
||||||
|
CloseBracket
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using calculator.Commands;
|
using calculator.Common;
|
||||||
using calculator.Common;
|
|
||||||
using calculator.Model;
|
using calculator.Model;
|
||||||
using calculator.Services;
|
using calculator.Services;
|
||||||
using calculator.View;
|
using calculator.View;
|
||||||
|
|
@ -12,7 +11,6 @@ public class CaculatorController
|
||||||
private readonly IInputService _inputService;
|
private readonly IInputService _inputService;
|
||||||
private readonly ICaculatorView _view;
|
private readonly ICaculatorView _view;
|
||||||
private readonly CaculatorData _data;
|
private readonly CaculatorData _data;
|
||||||
private ICommand? _currentCommand;
|
|
||||||
|
|
||||||
public CaculatorController(ICaculator caculator, IInputService inputService, ICaculatorView view,
|
public CaculatorController(ICaculator caculator, IInputService inputService, ICaculatorView view,
|
||||||
CaculatorData data)
|
CaculatorData data)
|
||||||
|
|
@ -32,9 +30,14 @@ public class CaculatorController
|
||||||
|
|
||||||
private void OnSingleOperationPressed(Operation operation)
|
private void OnSingleOperationPressed(Operation operation)
|
||||||
{
|
{
|
||||||
OnOperatorPressed(operation);
|
if (_data.Values.Count == 0)
|
||||||
_currentCommand = new CalculateCommand(_caculator, _data);
|
return;
|
||||||
OnCalculatePressed();
|
|
||||||
|
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)
|
private void OnClearPressed(bool full)
|
||||||
|
|
@ -42,60 +45,104 @@ public class CaculatorController
|
||||||
Clear(full: full);
|
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()
|
private void OnCalculatePressed()
|
||||||
{
|
{
|
||||||
if (_data.Operation is null)
|
Calculate();
|
||||||
return;
|
}
|
||||||
|
|
||||||
if (_data.Value is null)
|
private void PerformCalculation(bool fullAnswer = true)
|
||||||
return;
|
{
|
||||||
|
while (true)
|
||||||
if (_data is not { Caculated: true, Input: null } || _currentCommand == null)
|
|
||||||
{
|
{
|
||||||
_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));
|
||||||
|
}
|
||||||
|
|
||||||
_currentCommand?.Execute();
|
if (_data.Operations.Count > 0 && _data.Operations.Peek() == Operation.OpenBracket && fullAnswer)
|
||||||
_data.Caculated = true;
|
{
|
||||||
UpdateView(_data.Value.Value);
|
_data.Operations.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data.Operations.Count > 0 && fullAnswer)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Clear(string value = "0", bool full = true)
|
private void Clear(string value = "0", bool full = true)
|
||||||
{
|
{
|
||||||
if (full)
|
if (full)
|
||||||
{
|
{
|
||||||
_data.Value = null;
|
_data.Values.Clear();
|
||||||
_data.Operation = null;
|
_data.Operations.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
_data.Caculated = false;
|
|
||||||
_data.Input = null;
|
_data.Input = null;
|
||||||
_view.UpdateView(value);
|
_view.UpdateView(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOperatorPressed(Operation operation)
|
private void OnOperatorPressed(Operation operation)
|
||||||
{
|
{
|
||||||
if (_data.Input == null && _data.Value == null)
|
if (_data.Operations.Count > 0)
|
||||||
return;
|
|
||||||
|
|
||||||
if (_data is { Caculated: false, Input: not null, Value: not null })
|
|
||||||
{
|
{
|
||||||
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;
|
_data.Input = null;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOperandPressed(char obj)
|
private void OnOperandPressed(char obj)
|
||||||
{
|
{
|
||||||
if (_data.Caculated)
|
if (_data.Operations.Count == 0 && _data.Input == null)
|
||||||
{
|
{
|
||||||
Clear(full: true);
|
Clear(full: true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
Form1.Designer.cs
generated
2
Form1.Designer.cs
generated
|
|
@ -403,6 +403,7 @@
|
||||||
button23.TabIndex = 35;
|
button23.TabIndex = 35;
|
||||||
button23.Text = ")";
|
button23.Text = ")";
|
||||||
button23.UseVisualStyleBackColor = true;
|
button23.UseVisualStyleBackColor = true;
|
||||||
|
button23.Click += OnCloseBracketButtonClick;
|
||||||
//
|
//
|
||||||
// button30
|
// button30
|
||||||
//
|
//
|
||||||
|
|
@ -414,6 +415,7 @@
|
||||||
button30.TabIndex = 34;
|
button30.TabIndex = 34;
|
||||||
button30.Text = "(";
|
button30.Text = "(";
|
||||||
button30.UseVisualStyleBackColor = true;
|
button30.UseVisualStyleBackColor = true;
|
||||||
|
button30.Click += OnOpenBracketButtonClick;
|
||||||
//
|
//
|
||||||
// Ln_button
|
// Ln_button
|
||||||
//
|
//
|
||||||
|
|
|
||||||
9
Form1.cs
9
Form1.cs
|
|
@ -221,5 +221,14 @@ namespace calculator
|
||||||
SingleOperatorPressed?.Invoke(Operation.Pi);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,6 @@ namespace calculator.Model;
|
||||||
public class CaculatorData
|
public class CaculatorData
|
||||||
{
|
{
|
||||||
public string? Input { get; set; }
|
public string? Input { get; set; }
|
||||||
public double? Value { get; set; }
|
public Stack<double?> Values { get; set; } = new();
|
||||||
public Operation? Operation { get; set; }
|
public Stack<Operation> Operations { get; set; } = new();
|
||||||
public bool Caculated { get; set; }
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue