Merge pull request #1 from Anymorexxx/PUK

Puk
This commit is contained in:
Xatiko 2024-04-15 00:02:12 +03:00 committed by GitHub
commit d4f8f07e9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 274 additions and 160 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,54 @@
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.Inv:
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

@ -18,7 +18,6 @@ public enum Operation
Ln,
Exp,
Inv,
Pi,
OneDiv,
Mod,
Neg,
@ -28,5 +27,16 @@ public enum Operation
Cosh,
Cos,
Tanh,
Tan
Tan,
OpenBracket,
CloseBracket,
Int,
Dms,
FE,
PowX
}
public enum Constants
{
Pi,
Exp
}

View file

@ -1,8 +1,8 @@
using calculator.Commands;
using calculator.Common;
using calculator.Common;
using calculator.Model;
using calculator.Services;
using calculator.View;
using System.Runtime.InteropServices;
namespace calculator.Controller;
@ -12,7 +12,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)
@ -27,14 +26,24 @@ public class CaculatorController
_view.ClearPressed += OnClearPressed;
_view.CalculatePressed += OnCalculatePressed;
_view.SingleOperatorPressed += OnSingleOperationPressed;
_view.Constants += OnConstantsPressed;
OnClearPressed(true);
}
private void OnSingleOperationPressed(Operation operation)
{
OnOperatorPressed(operation);
_currentCommand = new CalculateCommand(_caculator, _data);
OnCalculatePressed();
if (double.TryParse(_data.Input, out var value) == false)
{
if (_data.Values.Count > 0)
{
value = _data.Values.Pop()!.Value;
}
else { return; }
}
_data.Values.Push(_caculator.Calculate(operation, value));
UpdateView(_data.Values.Peek()!.Value);
_data.Input = null;
}
private void OnClearPressed(bool full)
@ -42,60 +51,104 @@ public class CaculatorController
Clear(full: full);
}
private void OnCalculatePressed()
private void Calculate(bool fullAnswer = true)
{
if (_data.Operation is null)
if (_data.Operations.Count == 0)
return;
if (_data.Value is null)
if (_data.Values.Count == 0)
return;
if (_data is not { Caculated: true, Input: null } || _currentCommand == null)
{
_currentCommand = new CalculateCommand(_caculator, _data);
if (TryGetValueFromInput() == false)
return;
PerformCalculation(fullAnswer);
UpdateView(_data.Values.Peek()!.Value);
}
_currentCommand?.Execute();
_data.Caculated = true;
UpdateView(_data.Value.Value);
private void OnCalculatePressed()
{
Calculate();
}
private void PerformCalculation(bool fullAnswer = true)
{
while (true)
{
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;
}
}
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;
}
_data.Operation = operation;
if (_data.Input != null)
if (operation != Operation.OpenBracket && operation.IsLowerOrEqual(_data.Operations.Peek()))
{
_data.Value = double.Parse(_data.Input);
Calculate(false);
}
}
_data.Operations.Push(operation);
TryGetValueFromInput();
}
private bool TryGetValueFromInput()
{
if (_data.Input is not null)
{
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);
}
@ -113,4 +166,26 @@ public class CaculatorController
{
_view.UpdateView(input);
}
private void OnConstantsPressed(Constants constants)
{
if (_data.Operations.Count == 0 && _data.Input == null)
{
Clear(full: true);
}
double output = 0;
switch (constants)
{
case Constants.Pi:
output = Math.PI;
break;
case Constants.Exp:
output = Math.E;
break;
}
_data.Input = output.ToString("0.#####");
UpdateView(output);
}
}

68
Form1.Designer.cs generated
View file

@ -29,7 +29,7 @@
private void InitializeComponent()
{
panel1 = new Panel();
button49 = new Button();
PowX = new Button();
Log_button = new Button();
Mod_button = new Button();
Exp_button = new Button();
@ -97,7 +97,7 @@
// panel1
//
panel1.BackColor = Color.MediumSlateBlue;
panel1.Controls.Add(button49);
panel1.Controls.Add(PowX);
panel1.Controls.Add(Log_button);
panel1.Controls.Add(Mod_button);
panel1.Controls.Add(Exp_button);
@ -157,16 +157,17 @@
panel1.Size = new Size(573, 338);
panel1.TabIndex = 0;
//
// button49
// PowX
//
button49.FlatStyle = FlatStyle.Flat;
button49.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button49.Location = new Point(232, 296);
button49.Name = "button49";
button49.Size = new Size(51, 37);
button49.TabIndex = 55;
button49.Text = "10ᵜ";
button49.UseVisualStyleBackColor = true;
PowX.FlatStyle = FlatStyle.Flat;
PowX.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
PowX.Location = new Point(232, 296);
PowX.Name = "PowX";
PowX.Size = new Size(51, 37);
PowX.TabIndex = 55;
PowX.Text = "10ᵜ";
PowX.UseVisualStyleBackColor = true;
PowX.Click += OnPowXButtonClick;
//
// Log_button
//
@ -206,8 +207,11 @@
//
// button53
//
button53.Cursor = Cursors.No;
button53.Enabled = false;
button53.FlatStyle = FlatStyle.Flat;
button53.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button53.ForeColor = Color.Tomato;
button53.Location = new Point(4, 296);
button53.Name = "button53";
button53.Size = new Size(51, 37);
@ -325,8 +329,12 @@
//
// dms_button
//
dms_button.BackgroundImageLayout = ImageLayout.None;
dms_button.Cursor = Cursors.No;
dms_button.Enabled = false;
dms_button.FlatStyle = FlatStyle.Flat;
dms_button.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
dms_button.ForeColor = Color.Tomato;
dms_button.Location = new Point(4, 210);
dms_button.Name = "dms_button";
dms_button.Size = new Size(51, 37);
@ -392,6 +400,7 @@
Int_button.TabIndex = 36;
Int_button.Text = "Int";
Int_button.UseVisualStyleBackColor = true;
Int_button.Click += OnIntButtonClick;
//
// button23
//
@ -403,6 +412,7 @@
button23.TabIndex = 35;
button23.Text = ")";
button23.UseVisualStyleBackColor = true;
button23.Click += OnCloseBracketButtonClick;
//
// button30
//
@ -414,6 +424,7 @@
button30.TabIndex = 34;
button30.Text = "(";
button30.UseVisualStyleBackColor = true;
button30.Click += OnOpenBracketButtonClick;
//
// Ln_button
//
@ -729,8 +740,11 @@
//
// button5
//
button5.Cursor = Cursors.No;
button5.Enabled = false;
button5.FlatStyle = FlatStyle.Flat;
button5.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button5.ForeColor = Color.Tomato;
button5.Location = new Point(517, 81);
button5.Name = "button5";
button5.Size = new Size(51, 37);
@ -740,8 +754,11 @@
//
// button4
//
button4.Cursor = Cursors.No;
button4.Enabled = false;
button4.FlatStyle = FlatStyle.Flat;
button4.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button4.ForeColor = Color.Tomato;
button4.Location = new Point(460, 81);
button4.Name = "button4";
button4.Size = new Size(51, 37);
@ -751,8 +768,11 @@
//
// button3
//
button3.Cursor = Cursors.No;
button3.Enabled = false;
button3.FlatStyle = FlatStyle.Flat;
button3.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button3.ForeColor = Color.Tomato;
button3.Location = new Point(403, 81);
button3.Name = "button3";
button3.Size = new Size(51, 37);
@ -762,8 +782,11 @@
//
// button2
//
button2.Cursor = Cursors.No;
button2.Enabled = false;
button2.FlatStyle = FlatStyle.Flat;
button2.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button2.ForeColor = Color.Tomato;
button2.Location = new Point(346, 81);
button2.Name = "button2";
button2.Size = new Size(51, 37);
@ -773,8 +796,11 @@
//
// button1
//
button1.Cursor = Cursors.No;
button1.Enabled = false;
button1.FlatStyle = FlatStyle.Flat;
button1.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
button1.ForeColor = Color.Tomato;
button1.Location = new Point(289, 81);
button1.Name = "button1";
button1.Size = new Size(51, 37);
@ -796,8 +822,11 @@
// radioButton3
//
radioButton3.AutoSize = true;
radioButton3.BackgroundImageLayout = ImageLayout.None;
radioButton3.Cursor = Cursors.No;
radioButton3.Enabled = false;
radioButton3.Font = new Font("Microsoft Sans Serif", 11.25F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
radioButton3.ForeColor = Color.FromArgb(255, 192, 255);
radioButton3.ForeColor = Color.Tomato;
radioButton3.Location = new Point(197, 13);
radioButton3.Name = "radioButton3";
radioButton3.Size = new Size(76, 22);
@ -809,8 +838,11 @@
// radioButton2
//
radioButton2.AutoSize = true;
radioButton2.BackgroundImageLayout = ImageLayout.None;
radioButton2.Cursor = Cursors.No;
radioButton2.Enabled = false;
radioButton2.Font = new Font("Microsoft Sans Serif", 11.25F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
radioButton2.ForeColor = Color.FromArgb(255, 192, 255);
radioButton2.ForeColor = Color.Tomato;
radioButton2.Location = new Point(98, 13);
radioButton2.Name = "radioButton2";
radioButton2.Size = new Size(95, 22);
@ -822,8 +854,11 @@
// radioButton1
//
radioButton1.AutoSize = true;
radioButton1.BackgroundImageLayout = ImageLayout.None;
radioButton1.Cursor = Cursors.No;
radioButton1.Enabled = false;
radioButton1.Font = new Font("Microsoft Sans Serif", 11.25F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
radioButton1.ForeColor = Color.FromArgb(255, 192, 255);
radioButton1.ForeColor = Color.Tomato;
radioButton1.Location = new Point(6, 13);
radioButton1.Name = "radioButton1";
radioButton1.Size = new Size(93, 22);
@ -848,6 +883,7 @@
// linkLabel1
//
linkLabel1.AutoSize = true;
linkLabel1.Enabled = false;
linkLabel1.LinkColor = Color.FromArgb(255, 192, 255);
linkLabel1.Location = new Point(16, 6);
linkLabel1.Name = "linkLabel1";
@ -859,6 +895,7 @@
// linkLabel2
//
linkLabel2.AutoSize = true;
linkLabel2.Enabled = false;
linkLabel2.LinkColor = Color.FromArgb(255, 192, 255);
linkLabel2.Location = new Point(49, 6);
linkLabel2.Name = "linkLabel2";
@ -870,6 +907,7 @@
// linkLabel3
//
linkLabel3.AutoSize = true;
linkLabel3.Enabled = false;
linkLabel3.LinkColor = Color.FromArgb(255, 192, 255);
linkLabel3.Location = new Point(102, 6);
linkLabel3.Name = "linkLabel3";
@ -914,7 +952,7 @@
private LinkLabel linkLabel1;
private LinkLabel linkLabel2;
private LinkLabel linkLabel3;
private Button button49;
private Button PowX;
private Button Log_button;
private Button Mod_button;
private Button Exp_button;

View file

@ -15,6 +15,7 @@ namespace calculator
public event Action<Operation>? SingleOperatorPressed;
public event Action<bool>? ClearPressed;
public event Action? CalculatePressed;
public event Action<Constants>? Constants;
public void UpdateView(string input)
{
@ -83,7 +84,7 @@ namespace calculator
private void OnDotButtonClick(object sender, EventArgs e)
{
OperandPressed?.Invoke('.');
OperandPressed?.Invoke(',');
}
private void OnNegativeButtonClick(object sender, EventArgs e)
@ -198,7 +199,7 @@ namespace calculator
private void OnLogButtonClick(object sender, EventArgs e)
{
SingleOperatorPressed?.Invoke(Operation.Log);
OperatorPressed?.Invoke(Operation.Log);
}
private void OnInvButtonClick(object sender, EventArgs e)
@ -213,13 +214,32 @@ namespace calculator
private void OnExpButtonClick(object sender, EventArgs e)
{
SingleOperatorPressed?.Invoke(Operation.Exp);
Constants?.Invoke(Common.Constants.Exp);
}
private void OnPiButtonClick(object sender, EventArgs e)
{
SingleOperatorPressed?.Invoke(Operation.Pi);
Constants?.Invoke(Common.Constants.Pi);
}
private void OnOpenBracketButtonClick(object? sender, EventArgs e)
{
OperatorPressed?.Invoke(Operation.OpenBracket);
}
private void OnCloseBracketButtonClick(object? sender, EventArgs e)
{
OperatorPressed?.Invoke(Operation.CloseBracket);
}
private void OnIntButtonClick(object sender, EventArgs e)
{
SingleOperatorPressed?.Invoke(Operation.Int);
}
private void OnPowXButtonClick(object sender, EventArgs e)
{
SingleOperatorPressed?.Invoke(Operation.PowX);
}
}
}

View file

@ -120,78 +120,18 @@
<metadata name="panel1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button49.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button50.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button51.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button52.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="PowX.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button53.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button44.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button45.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button46.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button47.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button48.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button39.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button40.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button41.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button42.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button43.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button34.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button35.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button36.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button37.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button38.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button23.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button30.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button31.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button32.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button33.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

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

View file

@ -31,6 +31,8 @@ namespace calculator.Services
return Math.Pow(a, b);
case Operation.Mod:
return a % b;
case Operation.Log:
return Math.Log(a, b);
default:
throw new ArgumentException($"Invalid operator: {token}");
}
@ -75,16 +77,14 @@ namespace calculator.Services
return Math.Pow(a, 3);
case Operation.CubeRoot:
return Math.Pow(a, 1 / 3);
case Operation.Log:
return Math.Log10(a);
case Operation.Ln:
return Math.Log(a);
case Operation.Exp:
return Math.Exp(a);
case Operation.Inv:
return 1 / a;
case Operation.Pi:
return Math.PI;
case Operation.Int:
return Math.Round(a);
case Operation.PowX:
return Math.Pow(10, a);
default:
throw new ArgumentException($"Invalid operator: {token}");
}

View file

@ -9,5 +9,6 @@ public interface ICaculatorView
public event Action<bool> ClearPressed;
public event Action CalculatePressed;
public event Action<Operation> SingleOperatorPressed;
public event Action<Constants> Constants;
public void UpdateView(string input);
}