From 46be4f4d8fafad074398a218c37b198b317a2741 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Tue, 21 Oct 2025 11:06:15 +0300 Subject: [PATCH 1/7] init proj and create basic logic of the calculator --- HW3/CalculatorCore/CalculatorCore.csproj | 23 +++ HW3/CalculatorCore/CalculatorLogic.cs | 209 +++++++++++++++++++++++ HW3/CalculatorCore/stylecop.json | 9 + HW3/HW3.sln | 16 ++ 4 files changed, 257 insertions(+) create mode 100644 HW3/CalculatorCore/CalculatorCore.csproj create mode 100644 HW3/CalculatorCore/CalculatorLogic.cs create mode 100644 HW3/CalculatorCore/stylecop.json create mode 100644 HW3/HW3.sln diff --git a/HW3/CalculatorCore/CalculatorCore.csproj b/HW3/CalculatorCore/CalculatorCore.csproj new file mode 100644 index 0000000..8a67f40 --- /dev/null +++ b/HW3/CalculatorCore/CalculatorCore.csproj @@ -0,0 +1,23 @@ + + + + Exe + net8.0 + enable + enable + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/HW3/CalculatorCore/CalculatorLogic.cs b/HW3/CalculatorCore/CalculatorLogic.cs new file mode 100644 index 0000000..8bfede8 --- /dev/null +++ b/HW3/CalculatorCore/CalculatorLogic.cs @@ -0,0 +1,209 @@ +// +// Copyright (c) khusainovilas. All rights reserved. +// + +namespace CalculatorCore; + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// Calculator logic that processes the input of numbers, operators, and calculations. +/// +public class CalculatorLogic : INotifyPropertyChanged +{ + private double? currentValue; + private string? pendingOperator; + private string? display = "0"; + private bool isNewInput = true; + private string? inputBuffer = string.Empty; + + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + /// Gets the value displayed on the calculator screen. + /// Updates the UI via data binding when changing. + /// + public string? Display + { + get => this.display; + private set + { + if (this.display == value) + { + return; + } + + this.display = value; + this.OnPropertyChanged(); + } + } + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + /// + /// Adds a digit or dot to the current input number. + /// + /// Digit (0-9) or dot (.). + public void AppendDigit(string? digit) + { + if (digit != "." && !char.IsDigit(digit ?? string.Empty, 0)) + { + return; + } + + if (this.isNewInput) + { + this.inputBuffer = string.Empty; + this.isNewInput = false; + } + + if (digit == "." && this.inputBuffer != null && this.inputBuffer.Contains('.')) + { + return; + } + + this.inputBuffer += digit; + this.Display = this.inputBuffer.Length > 0 ? this.inputBuffer : "0"; + } + + /// + /// Sets the operator (+, -, *, /) and performs the calculation if there are two operands. + /// + /// The operator. + public void SetOperator(string @operator) + { + if (@operator != "+" && @operator != "-" && @operator != "*" && @operator != "/") + { + return; + } + + if (!string.IsNullOrEmpty(this.inputBuffer)) + { + if (!double.TryParse(this.inputBuffer, out var number)) + { + this.Display = "Error"; + this.Clear(); + return; + } + + if (this.currentValue == null) + { + this.currentValue = number; + } + else if (this.pendingOperator != null) + { + try + { + this.currentValue = CalculateResult(this.currentValue!.Value, number, this.pendingOperator); + this.Display = this.currentValue.ToString(); + } + catch (Exception) + { + this.Display = "Error"; + this.Clear(); + return; + } + } + + this.inputBuffer = string.Empty; + this.isNewInput = true; + } + + this.pendingOperator = @operator; + this.Display = this.currentValue?.ToString() ?? "0"; + } + + /// + /// Performs the final calculation. + /// + public void Calculate() + { + if (string.IsNullOrEmpty(this.inputBuffer) || this.pendingOperator == null) + { + return; + } + + if (!double.TryParse(this.inputBuffer, out var secondNumber)) + { + this.Display = "Error"; + this.Clear(); + return; + } + + try + { + this.currentValue = CalculateResult(this.currentValue!.Value, secondNumber, this.pendingOperator); + this.Display = this.currentValue.ToString(); + } + catch (Exception) + { + this.Display = "Error"; + this.Clear(); + return; + } + + this.inputBuffer = string.Empty; + this.isNewInput = true; + this.pendingOperator = null; + } + + /// + /// Performs the calculation of two numbers with the specified operator. + /// + /// The first operand. + /// The second operand. + /// The operator. + /// The result of the calculation. + private static double CalculateResult(double first, double second, string @operator) + { + return @operator switch + { + "+" => first + second, + "-" => first - second, + "*" => first * second, + "/" => second != 0 ? first / second : throw new DivideByZeroException(), + _ => throw new InvalidOperationException("Unknown operator"), + }; + } + + /// + /// Completely resets the calculator state. + /// + public void Clear() + { + this.currentValue = null; + this.pendingOperator = null; + this.inputBuffer = string.Empty; + this.isNewInput = true; + this.Display = "0"; + } + + /// + /// Resets the current input, saving the result and the operator. + /// + public void ClearEnter() + { + this.inputBuffer = string.Empty; + this.isNewInput = true; + this.Display = this.currentValue?.ToString() ?? "0"; + } + + /// + /// Removes the last digit from the current input. + /// + public void Backspace() + { + if (this.isNewInput || this.inputBuffer is { Length: <= 0 }) + { + return; + } + + this.inputBuffer = this.inputBuffer?[..^1]; + this.Display = this.inputBuffer is { Length: > 0 } ? this.inputBuffer : "0"; + } +} \ No newline at end of file diff --git a/HW3/CalculatorCore/stylecop.json b/HW3/CalculatorCore/stylecop.json new file mode 100644 index 0000000..76c8e76 --- /dev/null +++ b/HW3/CalculatorCore/stylecop.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "khusainovilas", + "copyrightText": "Copyright (c) {companyName}. All rights reserved." + } + } +} \ No newline at end of file diff --git a/HW3/HW3.sln b/HW3/HW3.sln new file mode 100644 index 0000000..8565082 --- /dev/null +++ b/HW3/HW3.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorCore", "CalculatorCore\CalculatorCore.csproj", "{5D070A5B-FA66-416C-B482-A5396D4A04C1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5D070A5B-FA66-416C-B482-A5396D4A04C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D070A5B-FA66-416C-B482-A5396D4A04C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D070A5B-FA66-416C-B482-A5396D4A04C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D070A5B-FA66-416C-B482-A5396D4A04C1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal From 661eaa90d0e0c9c018024fc8e247012fffb2730f Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Sun, 26 Oct 2025 23:36:20 +0300 Subject: [PATCH 2/7] add: implemented the calculator UI --- HW3/CalculatorCore/App.xaml | 7 +++ HW3/CalculatorCore/CalculatorCore.csproj | 8 +-- HW3/CalculatorCore/CalculatorLogic.cs | 48 +++++++-------- HW3/CalculatorCore/MainWindow.xaml | 55 +++++++++++++++++ HW3/CalculatorCore/MainWindow.xaml.cs | 75 ++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 28 deletions(-) create mode 100644 HW3/CalculatorCore/App.xaml create mode 100644 HW3/CalculatorCore/MainWindow.xaml create mode 100644 HW3/CalculatorCore/MainWindow.xaml.cs diff --git a/HW3/CalculatorCore/App.xaml b/HW3/CalculatorCore/App.xaml new file mode 100644 index 0000000..d1ac71f --- /dev/null +++ b/HW3/CalculatorCore/App.xaml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/HW3/CalculatorCore/CalculatorCore.csproj b/HW3/CalculatorCore/CalculatorCore.csproj index 8a67f40..0a1dc66 100644 --- a/HW3/CalculatorCore/CalculatorCore.csproj +++ b/HW3/CalculatorCore/CalculatorCore.csproj @@ -1,8 +1,9 @@  - Exe - net8.0 + WinExe + net8.0-windows + true enable enable true @@ -18,6 +19,5 @@ - - + diff --git a/HW3/CalculatorCore/CalculatorLogic.cs b/HW3/CalculatorCore/CalculatorLogic.cs index 8bfede8..4f87663 100644 --- a/HW3/CalculatorCore/CalculatorLogic.cs +++ b/HW3/CalculatorCore/CalculatorLogic.cs @@ -40,11 +40,6 @@ private set } } - private void OnPropertyChanged([CallerMemberName] string? propertyName = null) - { - this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - /// /// Adds a digit or dot to the current input number. /// @@ -152,25 +147,6 @@ public void Calculate() this.pendingOperator = null; } - /// - /// Performs the calculation of two numbers with the specified operator. - /// - /// The first operand. - /// The second operand. - /// The operator. - /// The result of the calculation. - private static double CalculateResult(double first, double second, string @operator) - { - return @operator switch - { - "+" => first + second, - "-" => first - second, - "*" => first * second, - "/" => second != 0 ? first / second : throw new DivideByZeroException(), - _ => throw new InvalidOperationException("Unknown operator"), - }; - } - /// /// Completely resets the calculator state. /// @@ -206,4 +182,28 @@ public void Backspace() this.inputBuffer = this.inputBuffer?[..^1]; this.Display = this.inputBuffer is { Length: > 0 } ? this.inputBuffer : "0"; } + + /// + /// Performs the calculation of two numbers with the specified operator. + /// + /// The first operand. + /// The second operand. + /// The operator. + /// The result of the calculation. + private static double CalculateResult(double first, double second, string @operator) + { + return @operator switch + { + "+" => first + second, + "-" => first - second, + "*" => first * second, + "/" => second != 0 ? first / second : throw new DivideByZeroException(), + _ => throw new InvalidOperationException("Unknown operator"), + }; + } + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } \ No newline at end of file diff --git a/HW3/CalculatorCore/MainWindow.xaml b/HW3/CalculatorCore/MainWindow.xaml new file mode 100644 index 0000000..9e72494 --- /dev/null +++ b/HW3/CalculatorCore/MainWindow.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + +