diff --git a/CalculatorApp/CalculatorApp.csproj b/CalculatorApp/CalculatorApp.csproj new file mode 100644 index 00000000..8acb7da5 --- /dev/null +++ b/CalculatorApp/CalculatorApp.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/CalculatorApp/CalculatorApp.slnx b/CalculatorApp/CalculatorApp.slnx new file mode 100644 index 00000000..e4946298 --- /dev/null +++ b/CalculatorApp/CalculatorApp.slnx @@ -0,0 +1,4 @@ + + + + diff --git a/CalculatorApp/Program.cs b/CalculatorApp/Program.cs new file mode 100644 index 00000000..a8d2044f --- /dev/null +++ b/CalculatorApp/Program.cs @@ -0,0 +1,223 @@ +using System.Text.RegularExpressions; +using System.Xml.Serialization; +using CalculatorLibrary; + +class Program +{ + static void Main(string[] args) + { + bool endApp = false; + int count = 0; + // Display title as the C# console calculator app. + Console.WriteLine("Console Calculator in C#\r"); + Console.WriteLine("------------------------\n"); + + Calculator calculator = new Calculator(); + + while (!endApp) + { + // Declare variables and set to empty. + // Use Nullable types (with ?) to match type of System.Console.ReadLine + string? numInput1 = ""; + string? numInput2 = ""; + double result = 0; + + endApp = ShowMenu(); + if (endApp == true) + { break; } + + // Ask the user to type the first number. + Console.WriteLine("Collecting your first number..."); + numInput1 = GetNumInput(); + + double cleanNum1 = 0; + while (!double.TryParse(numInput1, out cleanNum1)) + { + Console.Write("This is not valid input. Please enter a numeric value: "); + numInput1 = Console.ReadLine(); + } + + // Ask the user to type the second number. + Console.WriteLine("Collecting your second number..."); + numInput2 = GetNumInput(); + + double cleanNum2 = 0; + while (!double.TryParse(numInput2, out cleanNum2)) + { + Console.Write("This is not valid input. Please enter a numeric value: "); + numInput2 = Console.ReadLine(); + } + + string? op = GetOperand(); + // Validate input is not null, and matches the pattern + while (op == null || op == "exit") + { + if (op == "exit") + { + Console.WriteLine("You've chosen to close the app, press any key to close."); + Console.ReadKey(); + return; + } + Console.WriteLine("Error: Unrecognized input. Try Again or type 'exit' to exit."); + op = GetOperand(); + + + } + try + { + result = calculator.DoOperation(cleanNum1, cleanNum2, op); + if (double.IsNaN(result)) + { + Console.WriteLine("This operation will result in a mathematical error.\n"); + } + else + { + + Console.WriteLine("Your result: {0:0.##}\n", result); + count++; + Console.WriteLine($"You have used the calculator {count} times."); + } + } + catch (Exception e) + { + Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message); + } + Console.WriteLine("------------------------\n"); + + // Wait for the user to respond before closing. + Console.Write("Press 'n' and Enter to close the app, or press any other key and Enter to continue: "); + if (Console.ReadLine() == "n") endApp = true; + + Console.WriteLine("\n"); // Friendly linespacing. + } + calculator.Finish(); + return; + + string GetOperand() + { + + // Ask the user to choose an operator. + Console.WriteLine("Choose an operator from the following list:"); + Console.WriteLine("\ta - Add"); + Console.WriteLine("\ts - Subtract"); + Console.WriteLine("\tm - Multiply"); + Console.WriteLine("\td - Divide"); + Console.Write("Your option? "); + + string? input = Console.ReadLine()?.Trim()?.ToLower() switch + { + "a" or "add" => "a", + "s" or "subtract" => "s", + "m" or "multiply" => "m", + "d" or "divide" => "d", + "exit" => "exit", + _ => null + }; + return input; + } + + + string GetNumInput() + { + if (calculator.History.Count > 0) + { + Console.WriteLine("Do you want to use a previous result as your number? Y/N"); + bool? decision; + do + { + decision = Console.ReadLine()?.ToLower()?.Trim() switch + { + "y" => true, + "n" => false, + _ => null + }; + } while (decision == null); + + if (decision == true) + { + calculator.RecallMemory(); + int choice; + while (true) + { + Console.Write($"Pick an entry (from 1 to {calculator.History.Count}) or 'c' to cancel: "); + string? input = Console.ReadLine()?.Trim().ToLower(); + + if (input == "c") + { + Console.WriteLine("Cancelled."); + Console.Write("Type a number, and then press Enter: "); + return Console.ReadLine(); + } + + if (int.TryParse(input, out choice) && choice >= 1 && choice <= calculator.History.Count) + { + return calculator.RecallResult(choice - 1).ToString(); + } + + Console.WriteLine("Invalid input, try again."); + } + + } + else + { + Console.Write("Type a number, and then press Enter: "); + return Console.ReadLine(); + } + } + else + { + Console.Write("Type a number, and then press Enter: "); + return Console.ReadLine(); + } + } + + bool ShowMenu() + { + while (true) + { + Console.Clear(); + Console.WriteLine("What would you like to do?"); + Console.WriteLine("1. Perform Calculation"); + Console.WriteLine("2. Display Number of calculations performed"); + Console.WriteLine("3. Display History"); + Console.WriteLine("4. Clear History"); + Console.WriteLine("5. Exit"); + Console.Write("Enter the # for your choice: "); + + switch (Console.ReadLine()?.Trim()) + { + case "1": + return false; + case "2": + Console.WriteLine($"Calculations performed: {count}"); + break; + case "3": + if (calculator.History.Count > 0) + calculator.RecallMemory(); + else + Console.WriteLine("No history to display."); + break; + case "4": + if (calculator.History.Count > 0) + { + calculator.History.Clear(); + Console.WriteLine("History has been cleared."); + } + else + { + Console.WriteLine("No history to clear."); + } + break; + case "5": + return true; + default: + Console.WriteLine("Invalid choice, please try again."); + break; + } + + Console.WriteLine("Press any key to continue..."); + Console.ReadKey(); + } + } + } +} \ No newline at end of file diff --git a/CalculatorLibrary/CalculatorLibrary.cs b/CalculatorLibrary/CalculatorLibrary.cs new file mode 100644 index 00000000..c9033ddd --- /dev/null +++ b/CalculatorLibrary/CalculatorLibrary.cs @@ -0,0 +1,105 @@ +using System.Diagnostics; +using Newtonsoft.Json; +namespace CalculatorLibrary +{ + public class Calculator + { + JsonWriter writer; + StreamWriter logFile; + + public record Calculation(double Num1, double Num2, string Op, double Result) + { + public string Symbol => Op switch + { + "a" => "+", + "s" => "-", + "m" => "*", + "d" => "/", + _ => Op + }; + } + public List History { get; private set; } = new(); + public Calculator() + { + StartLog(); + } + public double DoOperation(double num1, double num2, string op) + { + double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error. + writer.WriteStartObject(); + writer.WritePropertyName("Operand1"); + writer.WriteValue(num1); + writer.WritePropertyName("Operand2"); + writer.WriteValue(num2); + writer.WritePropertyName("Operation"); + // Use a switch statement to do the math. + switch (op) + { + case "a": + result = num1 + num2; + writer.WriteValue("Add"); + break; + case "s": + result = num1 - num2; + writer.WriteValue("Subtract"); + break; + case "m": + result = num1 * num2; + writer.WriteValue("Multiply"); + break; + case "d": + // Ask the user to enter a non-zero divisor. + if (num2 != 0) + { + result = num1 / num2; + writer.WriteValue("Divide"); + } + break; + // Return text for an incorrect option entry. + default: + break; + } + writer.WritePropertyName("Result"); + writer.WriteValue(result); + writer.WriteEndObject(); + History.Add(new Calculation(num1, num2, op, result)); + + return result; + } + public void Finish() + { + writer.WriteEndArray(); + writer.WriteEndObject(); + writer.Close(); + } + + public void ClearMemory() + { + History.Clear(); + } + + public void RecallMemory() + { + for (int i = 0; i < History.Count; i++) + { + Calculation calc = History[i]; + Console.WriteLine($"{i + 1}. {calc.Num1} {calc.Symbol} {calc.Num2} = {calc.Result}"); + } + } + + public double RecallResult(int resultNum) + { + return History[resultNum].Result; + } + private void StartLog() + { + logFile = File.CreateText("calculatorlog.json"); + logFile.AutoFlush = true; + writer = new JsonTextWriter(logFile); + writer.Formatting = Formatting.Indented; + writer.WriteStartObject(); + writer.WritePropertyName("Operations"); + writer.WriteStartArray(); + } + } +} diff --git a/CalculatorLibrary/CalculatorLibrary.csproj b/CalculatorLibrary/CalculatorLibrary.csproj new file mode 100644 index 00000000..22badd14 --- /dev/null +++ b/CalculatorLibrary/CalculatorLibrary.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + enable + enable + + + + + + +