diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..2efc0762 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dotnet.defaultSolution": "MathGame.sln" +} \ No newline at end of file diff --git a/MathGame.rcraig14/Controllers/GameController.cs b/MathGame.rcraig14/Controllers/GameController.cs new file mode 100644 index 00000000..1ef0ab5b --- /dev/null +++ b/MathGame.rcraig14/Controllers/GameController.cs @@ -0,0 +1,53 @@ +using MathGame.rcraig14.Models; + +namespace MathGame.rcraig14.Controllers; + +public class GameController : IGameController +{ + + private Problem? CurrentProblem { get; set; } + private List AnswerHistory { get; set; } + + public GameController() + { + AnswerHistory = new List(); + } + + public Problem GenerateProblem(Operation operation) + { + CurrentProblem = operation switch + { + Operation.Addition => Addition.GenerateRandom(), + Operation.Subtraction => Subtraction.GenerateRandom(), + Operation.Multiplication => Multiplication.GenerateRandom(), + Operation.Division => Division.GenerateRandom(), + _ => throw new ArgumentOutOfRangeException(nameof(operation), $"Unexpected operation value: {operation}") + }; + + return CurrentProblem; + } + + + public SubmittedAnswer SubmitAnswer(int answer, TimeSpan timeToComplete) + { + if (CurrentProblem is null) + { + throw new ArgumentNullException("Problem must be generated before submitting answer"); + } + + var submittedAnswer = new SubmittedAnswer(CurrentProblem, answer, timeToComplete); + AnswerHistory.Add(submittedAnswer); + + return submittedAnswer; + } + + public void DisplayProblem() + { + Console.WriteLine(CurrentProblem?.ToString() ?? "Problem needs to be generated"); + } + + public List GetAnswerHistory() + { + return AnswerHistory; + } +} diff --git a/MathGame.rcraig14/Controllers/IGameController.cs b/MathGame.rcraig14/Controllers/IGameController.cs new file mode 100644 index 00000000..e92ff0c0 --- /dev/null +++ b/MathGame.rcraig14/Controllers/IGameController.cs @@ -0,0 +1,12 @@ +using MathGame.rcraig14.Models; + +namespace MathGame.rcraig14.Controllers; + +public interface IGameController +{ + public Problem GenerateProblem(Operation operation); + public void DisplayProblem(); + public SubmittedAnswer SubmitAnswer(int answer, TimeSpan timeToComplete); + public List GetAnswerHistory(); + +} diff --git a/MathGame.rcraig14/Controllers/IUserInteractionsController.cs b/MathGame.rcraig14/Controllers/IUserInteractionsController.cs new file mode 100644 index 00000000..39769cc3 --- /dev/null +++ b/MathGame.rcraig14/Controllers/IUserInteractionsController.cs @@ -0,0 +1,14 @@ +using MathGame.rcraig14.Models; + +namespace MathGame.rcraig14.Controllers; + +public interface IUserInteractionsController +{ + public void DisplayWelcome(); + public NextStep GetNextStep(); + public Operation GetNextOperationType(); + public int GetAnswer(Problem problem); + public void DisplayResults(SubmittedAnswer submittedAnswer); + public void DisplayAnswerHistory(List submittedAnswers); + +} diff --git a/MathGame.rcraig14/Controllers/UserInteractionsController.cs b/MathGame.rcraig14/Controllers/UserInteractionsController.cs new file mode 100644 index 00000000..1fab73d9 --- /dev/null +++ b/MathGame.rcraig14/Controllers/UserInteractionsController.cs @@ -0,0 +1,85 @@ +using MathGame.rcraig14.Models; + +namespace MathGame.rcraig14.Controllers; + +public class UserInteractionsController : IUserInteractionsController +{ + public void DisplayResults(SubmittedAnswer submittedAnswer) + { + Console.WriteLine(submittedAnswer.ToString()); + Console.WriteLine($"It took {submittedAnswer.TimeToComplete} to complete"); + } + + public void DisplayWelcome() + { + Console.WriteLine("Welcome to the new math game"); + } + + public int GetAnswer(Problem problem) + { + Console.WriteLine(problem.ToString()); + Console.Write("Answer: "); + string? strAnswer = Console.ReadLine(); + + if (int.TryParse(strAnswer, out int intOut)) + { + return intOut; + } + else + { + Console.WriteLine("Only integers can be submitted for answers"); + return GetAnswer(problem); + } + } + + public NextStep GetNextStep() + { + while (true) + { + Console.WriteLine("Get next problem (n), history of problems (h), or quit (q)"); + string? input = Console.ReadLine(); + + switch (input?.ToLower() ?? "") + { + case "q": + return NextStep.Quit; + case "n": + return NextStep.NewProblem; + case "h": + return NextStep.History; + default: + continue; + } + } + + } + + public Operation GetNextOperationType() + { + Console.WriteLine(@" +Select a type of problem + - Additon (a) + - Subtraction (s) + - Multipication (m) + - Division (d)"); + + string? problemType = Console.ReadLine(); + + if (problemType is null) + return GetNextOperationType(); + + return OperationConverter.StringToOperation(problemType); + } + + public void DisplayAnswerHistory(List submittedAnswers) + { + int correct = 0; + submittedAnswers.ForEach(answer => + { + Console.WriteLine($"{answer.Problem} {answer.UserAnswer} Correct: {answer.IsCorrect()}"); + correct += answer.IsCorrect() ? 1 : 0; + }); + + Console.WriteLine($"Total Correct {correct} / {submittedAnswers.Count()}"); + } +} diff --git a/MathGame.rcraig14/MathGame.rcraig14.csproj b/MathGame.rcraig14/MathGame.rcraig14.csproj new file mode 100644 index 00000000..ed9781c2 --- /dev/null +++ b/MathGame.rcraig14/MathGame.rcraig14.csproj @@ -0,0 +1,10 @@ + + + + Exe + net10.0 + enable + enable + + + diff --git a/MathGame.rcraig14/MathGameRunner.cs b/MathGame.rcraig14/MathGameRunner.cs new file mode 100644 index 00000000..dd02bfb6 --- /dev/null +++ b/MathGame.rcraig14/MathGameRunner.cs @@ -0,0 +1,63 @@ +using MathGame.rcraig14.Controllers; +using MathGame.rcraig14.Models; + +namespace MathGame.rcraig14; + +public class MathGameRunner +{ + private UserInteractionsController UserInteractionController { get; } + private GameController GameController { get; } + private bool NewProblem { get; set; } + + public MathGameRunner( + UserInteractionsController userInteractionsController, + GameController gameController) + { + UserInteractionController = userInteractionsController; + GameController = gameController; + NewProblem = true; + } + + private void NextProblem() + { + Operation op = UserInteractionController.GetNextOperationType(); + Problem problem = GameController.GenerateProblem(op); + + DateTime startTime = DateTime.UtcNow; + int userAnswer = UserInteractionController.GetAnswer(problem); + DateTime endTime = DateTime.UtcNow; + + SubmittedAnswer submittedAnswer = GameController.SubmitAnswer(userAnswer, endTime - startTime); + UserInteractionController.DisplayResults(submittedAnswer); + } + + private void History() + { + var history = GameController.GetAnswerHistory(); + UserInteractionController.DisplayAnswerHistory(history); + } + + public void Start() + { + UserInteractionController.DisplayWelcome(); + + while (NewProblem) + { + NextStep next = UserInteractionController.GetNextStep(); + + switch (next) + { + case NextStep.Quit: + NewProblem = false; + break; + case NextStep.History: + this.History(); + break; + default: + this.NextProblem(); + break; + } + + } + } +} diff --git a/MathGame.rcraig14/Models/Addition.cs b/MathGame.rcraig14/Models/Addition.cs new file mode 100644 index 00000000..883f8439 --- /dev/null +++ b/MathGame.rcraig14/Models/Addition.cs @@ -0,0 +1,16 @@ +namespace MathGame.rcraig14.Models; + +public class Addition(int pLeft, int pRight) : Problem(pLeft, pRight, Operation.Addition, "+") +{ + + public static Addition GenerateRandom() + { + var random = new Random(); + return new Addition(random.Next(0, 100), random.Next(0, 100)); + } + + public override int Answer() + { + return Left + Right; + } +} diff --git a/MathGame.rcraig14/Models/Division.cs b/MathGame.rcraig14/Models/Division.cs new file mode 100644 index 00000000..7155b335 --- /dev/null +++ b/MathGame.rcraig14/Models/Division.cs @@ -0,0 +1,23 @@ +namespace MathGame.rcraig14.Models; + +public class Division(int pLeft, int pRight) : Problem(pLeft, pRight, Operation.Division, "/") +{ + + public static Division GenerateRandom() + { + var random = new Random(); + int left = 1, right = 1; + + while (left <= right || (left % right) != 0) + { + left = random.Next(1, 100); + right = random.Next(1, 99); + } + + return new Division(left, right); + } + public override int Answer() + { + return Left / Right; + } +} diff --git a/MathGame.rcraig14/Models/Multiplication.cs b/MathGame.rcraig14/Models/Multiplication.cs new file mode 100644 index 00000000..670d3df1 --- /dev/null +++ b/MathGame.rcraig14/Models/Multiplication.cs @@ -0,0 +1,15 @@ +namespace MathGame.rcraig14.Models; + +public class Multiplication(int pLeft, int pRight) : Problem(pLeft, pRight, Operation.Multiplication, "*") +{ + public override int Answer() + { + return Left * Right; + } + + public static Multiplication GenerateRandom() + { + var random = new Random(); + return new Multiplication(random.Next(0, 100), random.Next(0, 100)); + } +} diff --git a/MathGame.rcraig14/Models/Problem.cs b/MathGame.rcraig14/Models/Problem.cs new file mode 100644 index 00000000..69ee3ac4 --- /dev/null +++ b/MathGame.rcraig14/Models/Problem.cs @@ -0,0 +1,24 @@ +namespace MathGame.rcraig14.Models; + +public abstract class Problem +{ + protected int Left { get; } + protected int Right { get; } + public Operation Operation { get; } + string OperationString { get; } + + public Problem(int pLeft, int pRight, Operation pOperation, string pOperationString) + { + Left = pLeft; + Right = pRight; + Operation = pOperation; + OperationString = pOperationString; + } + + public abstract int Answer(); + + public override string ToString() + { + return $"{Left} {OperationString} {Right} ="; + } +} diff --git a/MathGame.rcraig14/Models/SubmittedAnswer.cs b/MathGame.rcraig14/Models/SubmittedAnswer.cs new file mode 100644 index 00000000..c2cb744c --- /dev/null +++ b/MathGame.rcraig14/Models/SubmittedAnswer.cs @@ -0,0 +1,23 @@ +namespace MathGame.rcraig14.Models; + +public class SubmittedAnswer +{ + public Problem Problem { get; } + public int UserAnswer { get; } + public TimeSpan TimeToComplete { get; } + + + public SubmittedAnswer(Problem problem, int answer, TimeSpan timeToComplete) + { + Problem = problem; + UserAnswer = answer; + TimeToComplete = timeToComplete; + } + + public bool IsCorrect() => Problem.Answer() == UserAnswer; + + public override string ToString() + { + return IsCorrect() ? $"Correct the answer is {Problem.Answer()}" : $"Incorrect the answer is {Problem.Answer()}"; + } +} diff --git a/MathGame.rcraig14/Models/Subtraction.cs b/MathGame.rcraig14/Models/Subtraction.cs new file mode 100644 index 00000000..e55d6098 --- /dev/null +++ b/MathGame.rcraig14/Models/Subtraction.cs @@ -0,0 +1,23 @@ +namespace MathGame.rcraig14.Models; + +public class Subtraction(int pLeft, int pRight) : Problem(pLeft, pRight, Operation.Subtraction, "-") +{ + public override int Answer() + { + return Left - Right; + } + + public static Subtraction GenerateRandom() + { + var random = new Random(); + int left = 0, right = 0; + + while (left <= right) + { + left = random.Next(1, 100); + right = random.Next(0, 100); + } + + return new Subtraction(left, right); + } +} diff --git a/MathGame.rcraig14/NextStep.cs b/MathGame.rcraig14/NextStep.cs new file mode 100644 index 00000000..5addbc83 --- /dev/null +++ b/MathGame.rcraig14/NextStep.cs @@ -0,0 +1,8 @@ +namespace MathGame.rcraig14; + +public enum NextStep +{ + Quit, + NewProblem, + History +} diff --git a/MathGame.rcraig14/Operation.cs b/MathGame.rcraig14/Operation.cs new file mode 100644 index 00000000..2e10c705 --- /dev/null +++ b/MathGame.rcraig14/Operation.cs @@ -0,0 +1,45 @@ +namespace MathGame.rcraig14; + +public enum Operation +{ + Addition, + Subtraction, + Multiplication, + Division +} + + +public static class OperationConverter +{ + + public static Operation StringToOperation(string input) + { + switch (input.ToLower()) + { + case "a": + return Operation.Addition; + case "s": + return Operation.Subtraction; + case "m": + return Operation.Multiplication; + case "d": + return Operation.Division; + default: + throw new InvalidOperationException(); + } + } +} + +public class InvalidOperationString : Exception +{ + public InvalidOperationString() + { + + } + + public InvalidOperationString(string message) : base(message) + { + + } + +} \ No newline at end of file diff --git a/MathGame.rcraig14/Program.cs b/MathGame.rcraig14/Program.cs new file mode 100644 index 00000000..4a3426e5 --- /dev/null +++ b/MathGame.rcraig14/Program.cs @@ -0,0 +1,6 @@ +using MathGame.rcraig14; +using MathGame.rcraig14.Controllers; + +var game = new MathGameRunner(new UserInteractionsController(), new GameController()); + +game.Start(); diff --git a/MathGame.sln b/MathGame.sln new file mode 100644 index 00000000..375a7642 --- /dev/null +++ b/MathGame.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MathGame.rcraig14", "MathGame.rcraig14\MathGame.rcraig14.csproj", "{1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Debug|x64.ActiveCfg = Debug|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Debug|x64.Build.0 = Debug|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Debug|x86.ActiveCfg = Debug|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Debug|x86.Build.0 = Debug|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Release|Any CPU.Build.0 = Release|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Release|x64.ActiveCfg = Release|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Release|x64.Build.0 = Release|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Release|x86.ActiveCfg = Release|Any CPU + {1178E02F-3FDD-4B87-8996-A1EC3AD6BFD7}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal