diff --git a/Calculator.FeedMyData/.gitattributes b/Calculator.FeedMyData/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/Calculator.FeedMyData/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/Calculator.FeedMyData/.vscode/launch.json b/Calculator.FeedMyData/.vscode/launch.json new file mode 100644 index 00000000..8969795d --- /dev/null +++ b/Calculator.FeedMyData/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Calculator/bin/Debug/net10.0/Calculator.dll", + "args": [], + "cwd": "${workspaceFolder}", + "stopAtEntry": false, + "console": "integratedTerminal" + } + + ] +} \ No newline at end of file diff --git a/Calculator.FeedMyData/.vscode/tasks.json b/Calculator.FeedMyData/.vscode/tasks.json new file mode 100644 index 00000000..28f9a199 --- /dev/null +++ b/Calculator.FeedMyData/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "dotnet", + "task": "build", + "group": "build", + "problemMatcher": [], + "label": "build" + } + ] +} \ No newline at end of file diff --git a/Calculator.FeedMyData/Calculator/Calculator.csproj b/Calculator.FeedMyData/Calculator/Calculator.csproj new file mode 100644 index 00000000..8acb7da5 --- /dev/null +++ b/Calculator.FeedMyData/Calculator/Calculator.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/Calculator.FeedMyData/Calculator/Program.cs b/Calculator.FeedMyData/Calculator/Program.cs new file mode 100644 index 00000000..4901ffa4 --- /dev/null +++ b/Calculator.FeedMyData/Calculator/Program.cs @@ -0,0 +1,128 @@ +// Challenge instructions +// DONE - Create a functionality that will count the amount of times the calculator was used. +// DONE - Store a list with the latest calculations. And give the users the ability to delete that list. +// DONE - Allow the users to use the results in the list above to perform new calculations. +// DONE - Add extra calculations: Square Root, Taking the Power, 10x, Trigonometry functions. + +using System.Text.RegularExpressions; +using CalculatorLibrary; + +class Program +{ + static Calculator calculator = new(); + + static void Main(string[] args) + { + bool endApp = false; + Console.WriteLine("Console Calculator in C#\r"); + Console.WriteLine("------------------------\n"); + + while (!endApp) + { + Console.WriteLine("Choose an operation to perform from the following list:"); + Console.WriteLine("\ta - Add"); + Console.WriteLine("\ts - Subtract"); + Console.WriteLine("\tm - Multiply"); + Console.WriteLine("\td - Divide"); + Console.WriteLine("\tp - Power"); + Console.WriteLine("\tex - Exponent"); + Console.WriteLine("\tsr - Square Root"); + Console.WriteLine("\tsin - Sin"); + + if (calculator.history.Count >= 1) + { + Console.WriteLine("\t-------"); + Console.WriteLine("\th - Display calculations history"); + Console.WriteLine("\thdel - Delete calculations history"); + } + + string op = ""; + while (op == "" || !Regex.IsMatch(op, "^(a|s|m|d|p|ex|sr|sin|h|hdel)$")) + { + Console.WriteLine("Your choice?"); + op = Console.ReadLine().Trim().ToLower(); + } + + if (Regex.IsMatch(op, "^(h)$")) + HistoryMenu(); + + else if (Regex.IsMatch(op, "^(hdel)$")) + { + calculator.history.Clear(); + Console.WriteLine("All previous calculations were successfully deleted."); + } + + else + GetNumbers(op); + + Console.WriteLine("------------------------\n"); + Console.Write("Enter 'exit' to close the app, or press any other key and Enter to continue: "); + if (Console.ReadLine() == "exit") + endApp = true; + + Console.WriteLine("\n"); + } + + calculator.Finish(); + return; + } + + static void HistoryMenu() + { + Console.WriteLine("------------------------"); + Console.WriteLine("-------- History -------"); + Console.WriteLine("------------------------"); + Console.WriteLine("Type an '[ID]' with brackets instead of a number to use a result in a new calculation."); + foreach (OperationLog operation in calculator.history) + { + Console.WriteLine(operation.Display()); + } + } + + static void GetNumbers(string op) + { + double cleanNum1 = 0; + double cleanNum2 = 0; + double result = 0; + + Console.Write("Type a number or [ID], and then press Enter: "); + cleanNum1 = ParseInput(Console.ReadLine()); + + if (!Regex.IsMatch(op, "^(sr|sin)$")) + { + Console.Write("Type another number or [ID], and then press Enter: "); + cleanNum2 = ParseInput(Console.ReadLine()); + } + 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); + } + catch (Exception e) + { + Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message); + } + } + + static double ParseInput(string input) + { + double cleanNumber; + + while (!double.TryParse(input, out cleanNumber)) + { + if (input.StartsWith('[') && input.Trim().EndsWith(']') && input.Trim().Length == 5) + foreach (OperationLog operation in calculator.history) + if (input.Trim() == operation.ID) + return operation.Result; + + Console.Write("This is not valid input. Please enter a numeric value: "); + input = Console.ReadLine(); + } + return cleanNumber; + } +} + diff --git a/Calculator.FeedMyData/Calculator/calculatorlog.json b/Calculator.FeedMyData/Calculator/calculatorlog.json new file mode 100644 index 00000000..31a8a922 --- /dev/null +++ b/Calculator.FeedMyData/Calculator/calculatorlog.json @@ -0,0 +1,6 @@ +{ + "CalculatorUsage": 1, + "Operations": [ + "Operation [001]\r\n 5 Add 5 = 10" + ] +} \ No newline at end of file diff --git a/Calculator.FeedMyData/CalculatorLibrary/CalculatorLibrary.cs b/Calculator.FeedMyData/CalculatorLibrary/CalculatorLibrary.cs new file mode 100644 index 00000000..f4767766 --- /dev/null +++ b/Calculator.FeedMyData/CalculatorLibrary/CalculatorLibrary.cs @@ -0,0 +1,144 @@ +using Newtonsoft.Json; +using System.Text.RegularExpressions; + +namespace CalculatorLibrary; + +public class Calculator +{ + public int useCount = 0; + JsonWriter writer; + public List history = new(); + + public Calculator() + { + StreamWriter logFile = File.CreateText("calculatorlog.json"); + logFile.AutoFlush = true; + writer = new JsonTextWriter(logFile); + writer.Formatting = Formatting.Indented; + } + + public double DoOperation(double num1, double num2, string op) + { + double result = double.NaN; + string operation = ""; + + switch (op) + { + case "a": + operation = "Add"; + result = num1 + num2; + break; + case "s": + operation = "Substract"; + result = num1 - num2; + break; + case "m": + operation = "Multiply"; + result = num1 * num2; + break; + case "d": + if (num2 != 0) + { + operation = "Divide"; + result = num1 / num2; + } + break; + case "p": + operation = "Power"; + result = Math.Pow(num1, num2); + break; + case "sr": + operation = "Square Root"; + result = Math.Sqrt(num1); + break; + case "sin": + operation = "Sin"; + result = Math.Sin(num1); + break; + case "ex": + operation = "Exponent"; + result = num1 * Math.Pow(10, num2); + break; + default: + break; + } + + if (!Regex.IsMatch(op, "^(sr|sin)$")) + { + OperationLog newLog = new(operation, result, num1, num2); + history.Add(newLog); + } + + else + { + OperationLog newLog = new(operation, result, num1); + history.Add(newLog); + } + + useCount++; + return result; + } + + public void Finish() + { + writer.WriteStartObject(); + writer.WritePropertyName("CalculatorUsage"); + writer.WriteValue(useCount); + writer.WritePropertyName("Operations"); + writer.WriteStartArray(); + + foreach (OperationLog operation in history) + { + writer.WriteValue(operation.Display()); + Console.WriteLine(operation.Display()); + } + + writer.WriteEndArray(); + writer.WriteEndObject(); + writer.Close(); + } +} + +public class OperationLog +{ + private static int itemCount = 1; + private int operationNumber; + public string ID { get; } + public double Operand1 { get; } + public double Operand2 { get; } + public string Operation { get; } + public double Result { get; } + bool singleNumberOperation; + + public OperationLog(string operation, double result, double operand1, double operand2) + { + singleNumberOperation = false; + operationNumber = itemCount++; + ID = operationNumber.ToString("D3"); + ID = $"[{ID}]"; + Operand1 = operand1; + Operand2 = operand2; + Operation = operation; + Result = result; + } + + public OperationLog(string operation, double result, double operand1) + { + singleNumberOperation = true; + operationNumber = itemCount++; + ID = operationNumber.ToString("D3"); + ID = $"[{ID}]"; + Operand1 = operand1; + Operation = operation; + Result = result; + } + + public string Display() + { + if (!singleNumberOperation) + return $"{ID} {Operand1} {Operation} {Operand2} = {Result}"; + + else + return $"{ID} {Operand1} {Operation} = {Result}"; + } +} \ No newline at end of file diff --git a/Calculator.FeedMyData/CalculatorLibrary/CalculatorLibrary.csproj b/Calculator.FeedMyData/CalculatorLibrary/CalculatorLibrary.csproj new file mode 100644 index 00000000..6c82ca78 --- /dev/null +++ b/Calculator.FeedMyData/CalculatorLibrary/CalculatorLibrary.csproj @@ -0,0 +1,14 @@ + + + + net10.0 + enable + enable + + + + + + + + \ No newline at end of file diff --git a/Calculator.FeedMyData/calculatorlog.json b/Calculator.FeedMyData/calculatorlog.json new file mode 100644 index 00000000..e69de29b