diff --git a/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/.gitignore b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/.gitignore
new file mode 100644
index 00000000..32cd9cc7
--- /dev/null
+++ b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/.gitignore
@@ -0,0 +1,15 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/contentModel.xml
+/projectSettingsUpdater.xml
+/modules.xml
+/.idea.Rakenkode.MathGame.iml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/indexLayout.xml b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/indexLayout.xml
new file mode 100644
index 00000000..a76448c1
--- /dev/null
+++ b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/indexLayout.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ ../../CodeReviews.Console.MathGame
+
+
+
+
+
\ No newline at end of file
diff --git a/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/vcs.xml b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/vcs.xml
new file mode 100644
index 00000000..62bd7a01
--- /dev/null
+++ b/Rakenkode.MathGame/.idea/.idea.Rakenkode.MathGame/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Rakenkode.MathGame/Rakenkode.MathGame.sln b/Rakenkode.MathGame/Rakenkode.MathGame.sln
new file mode 100644
index 00000000..e87d799b
--- /dev/null
+++ b/Rakenkode.MathGame/Rakenkode.MathGame.sln
@@ -0,0 +1,16 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rakenkode.MathGame", "Rakenkode.MathGame\Rakenkode.MathGame.csproj", "{A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A6E9053C-DFA6-44F4-AECA-B67B162FA2FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Game.cs b/Rakenkode.MathGame/Rakenkode.MathGame/Game.cs
new file mode 100644
index 00000000..ae94607a
--- /dev/null
+++ b/Rakenkode.MathGame/Rakenkode.MathGame/Game.cs
@@ -0,0 +1,41 @@
+namespace Rakenkode.MathGame;
+
+public class Game
+{
+ private double _rating = 0;
+ public double Rating
+ {
+ get { return _rating; }
+ }
+ public int Duration { get; set; }
+ public GameType GameType { get;}
+ public Question[] Questions;
+
+ public Game(GameType gameType, int numberOfQuestions)
+ {
+ GameType = gameType;
+ Questions = new Question[numberOfQuestions];
+ Questions = Question.CreateProblems(gameType, numberOfQuestions);
+ }
+
+ public void Evaluate()
+ {
+ int score = 0;
+
+ for (int i = 0; i < Questions.Length; i++)
+ {
+ if (Questions[i].IsPlayerCorrect())
+ score++;
+ }
+ _rating = Math.Round((score / (double) Questions.Length) * 100, 1);
+ }
+}
+
+public enum GameType
+{
+ Addition = 0,
+ Subtraction = 1,
+ Multiplication = 2,
+ Division = 3,
+ Random = 4
+}
\ No newline at end of file
diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Program.cs b/Rakenkode.MathGame/Rakenkode.MathGame/Program.cs
new file mode 100644
index 00000000..b6bdd7f2
--- /dev/null
+++ b/Rakenkode.MathGame/Rakenkode.MathGame/Program.cs
@@ -0,0 +1,326 @@
+using System.Diagnostics;
+
+namespace Rakenkode.MathGame
+{
+ class Program
+ {
+ private static bool _isAppActive = true;
+ private static int _questionNumber = 0;
+ private static int _numberOfQuestions = 5;
+ private static int _selectedGameNumber = 1;
+ private static Game game = new Game(GameType.Addition, 5);
+ private static List games = new List();
+ private static Stopwatch _stopWatch = new Stopwatch();
+
+ static void Main(string[] args)
+ {
+ ActivePage activePage = ActivePage.MainPage;
+
+ while (_isAppActive)
+ {
+ switch (activePage)
+ {
+ case ActivePage.MainPage:
+ DisplayMain();
+ var userInput = Console.ReadLine()?.Trim().ToUpper();
+ if (userInput != null) activePage = NavigateFromMain(userInput);
+ break;
+ case ActivePage.GamePage:
+ if (_questionNumber < 5)
+ {
+ DisplayGame(_questionNumber);
+ var gameInput = Console.ReadLine()?.Trim().ToUpper();
+ if (gameInput != null) activePage = NavigateFromGame(gameInput);
+ }
+ else
+ {
+ DisplayResults();
+ var gameInput = Console.ReadLine()?.Trim().ToUpper();
+ if (gameInput != null) activePage = NavigateFromGameResults(gameInput);
+ }
+ break;
+ case ActivePage.HistoryPage:
+ if (games.Count == 0)
+ {
+ DisplayZeroGameHistory();
+ var historyInput = Console.ReadLine()?.Trim().ToUpper();
+ if (historyInput != null) activePage = NavigateFromZeroGameHistory(historyInput);
+ }
+ else
+ {
+ DisplayGameHistory();
+ var historyInput = Console.ReadLine()?.Trim().ToUpper();
+ if (historyInput != null) activePage = NavigateFromGameHistory(historyInput);
+ }
+ break;
+ case ActivePage.GameInfoPage:
+ DisplayGameInfo();
+ var gameDataInput = Console.ReadLine()?.Trim().ToUpper();
+ if (gameDataInput != null) activePage = NavigateFromGameInfo(gameDataInput);
+ break;
+ default:
+ ExitApplication();
+ break;
+ }
+ }
+
+ Console.WriteLine("Goodbye!");
+ }
+
+ private static void ExitApplication()
+ {
+ _isAppActive = false;
+
+ if(_stopWatch.IsRunning)
+ _stopWatch.Stop();
+
+ for (int i = 3; i >= 0; i--)
+ {
+ Console.Clear();
+ Console.WriteLine($"Closing in {i}...");
+ Thread.Sleep(400);
+ }
+ }
+
+ private static void DisplayMain()
+ {
+ Console.Clear();
+ Console.WriteLine("========== MATH GAME CONSOLE ==========");
+ Console.WriteLine(string.Empty);
+ Console.WriteLine(" Choose an option:");
+ Console.WriteLine(" [ 1 ] = Addition Game");
+ Console.WriteLine(" [ 2 ] = Subtraction Game");
+ Console.WriteLine(" [ 3 ] = Multiplication Game");
+ Console.WriteLine(" [ 4 ] = Division Game");
+ Console.WriteLine(" [ 5 ] = Random Game");
+ Console.WriteLine(" [ 6 ] = Game History");
+ Console.WriteLine(" [ x ] = Exit Application");
+ Console.WriteLine();
+ Console.Write(" Input: ");
+ }
+
+ private static ActivePage NavigateFromMain(string userInput)
+ {
+ switch (userInput)
+ {
+ case "X":
+ return ActivePage.ExitPage;
+ case "1":
+ game = new Game(GameType.Addition, _numberOfQuestions);
+ InitGameParams();
+ return ActivePage.GamePage;
+ case "2":
+ game = new Game(GameType.Subtraction, _numberOfQuestions);
+ InitGameParams();
+ return ActivePage.GamePage;
+ case "3":
+ game = new Game(GameType.Multiplication, _numberOfQuestions);
+ InitGameParams();
+ return ActivePage.GamePage;
+ case "4":
+ game = new Game(GameType.Division, _numberOfQuestions);
+ InitGameParams();
+ return ActivePage.GamePage;
+ case "5":
+ game = new Game(GameType.Random, _numberOfQuestions);
+ InitGameParams();
+ return ActivePage.GamePage;
+ case "6":
+ return ActivePage.HistoryPage;
+ default:
+ return ActivePage.MainPage;
+ }
+ }
+
+ private static void InitGameParams()
+ {
+ _questionNumber = 0;
+ _stopWatch.Restart();
+ }
+
+ private static void DisplayGame(int gameNumber)
+ {
+ Console.Clear();
+ Console.WriteLine($"=========== GAME {gameNumber + 1} of 5 ===========");
+ Console.WriteLine(string.Empty);
+ Console.WriteLine($" Problem: {game.Questions[gameNumber].ToString()}");
+ Console.WriteLine(string.Empty);
+ Console.Write(" Answer [ x to quit ]: ");
+ }
+
+ private static ActivePage NavigateFromGame(string userInput)
+ {
+ if (Int32.TryParse(userInput, out int number))
+ {
+ game.Questions[_questionNumber].PlayerAnswer = number;
+ _questionNumber++;
+ if (_questionNumber == 5)
+ {
+ _stopWatch.Stop();
+ game.Duration = (int) _stopWatch.ElapsedMilliseconds / 1000;
+ game.Evaluate();
+ games.Add(game);
+ }
+ }
+ else if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.ExitPage;
+ }
+
+ return ActivePage.GamePage;
+ }
+
+ private static void DisplayGameData(Game game)
+ {
+ Console.WriteLine($" problem answer result");
+ for (int i = 0; i < game.Questions.Length; i++)
+ {
+ Console.WriteLine($" {game.Questions[i].ToString(),-14} {game.Questions[i].PlayerAnswer.ToString(),-10} {(game.Questions[i].IsPlayerCorrect() ? "pass" : "fail")}");
+ }
+ Console.WriteLine(string.Empty);
+ Console.WriteLine($" Game time: {game.Duration} sec Rating: {game.Rating}%");
+ }
+
+ private static void DisplayResults()
+ {
+ Console.Clear();
+ Console.WriteLine("=========== GAME OVER ===========");
+ Console.WriteLine(string.Empty);
+ DisplayGameData(game);
+ Console.WriteLine(string.Empty);
+ Console.WriteLine(" Choose an option:");
+ Console.WriteLine(" [ m ] = Main Menu");
+ Console.WriteLine(" [ x ] = Exit Application");
+ Console.WriteLine();
+ Console.Write(" Input: ");
+ }
+
+ private static ActivePage NavigateFromGameResults(string userInput)
+ {
+ if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.ExitPage;
+ }
+ else if (userInput.Equals("M", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.MainPage;
+ }
+
+ return ActivePage.GamePage;
+ }
+
+ private static void DisplayZeroGameHistory()
+ {
+ Console.Clear();
+ Console.WriteLine("=========== GAME HISTORY ==========");
+ Console.WriteLine(string.Empty);
+ Console.WriteLine(" There are no previous games played.");
+ Console.WriteLine(string.Empty);
+ Console.WriteLine(" Choose an option:");
+ Console.WriteLine(" [ m ] = Main Menu");
+ Console.WriteLine(" [ x ] = Exit Application");
+ Console.WriteLine();
+ Console.Write(" Input: ");
+ }
+
+ private static ActivePage NavigateFromZeroGameHistory(string userInput)
+ {
+ if (userInput.Equals("M", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.MainPage;
+ }
+ else if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.ExitPage;
+ }
+
+ return ActivePage.HistoryPage;
+ }
+
+ private static void DisplayGameHistory()
+ {
+ Console.Clear();
+ Console.WriteLine("=========== GAME HISTORY ==========");
+ Console.WriteLine(string.Empty);
+
+ Console.WriteLine("Game# Type Rating Duration");
+ for (int i = 0; i < games.Count; i++)
+ {
+ Console.WriteLine($" {(i + 1).ToString(),-6} {games[i].GameType,-15} {games[i].Rating + "%",-11} {games[i].Duration} sec");
+ }
+
+ Console.WriteLine(string.Empty);
+ Console.WriteLine(" Choose an option:");
+ Console.WriteLine(" [ n ] = Where n is Game# to view");
+ Console.WriteLine(" [ m ] = Main Menu");
+ Console.WriteLine(" [ x ] = Exit Application");
+ Console.WriteLine();
+ Console.Write(" Input: ");
+ }
+
+ private static ActivePage NavigateFromGameHistory(string userInput)
+ {
+ if (int.TryParse(userInput, out int number))
+ {
+ if (number > 0 && number <= games.Count)
+ {
+ _selectedGameNumber = number;
+ return ActivePage.GameInfoPage;
+ }
+ }
+ else
+ {
+ if (userInput.Equals("M", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.MainPage;
+ }
+ else if (userInput.Equals("X", StringComparison.OrdinalIgnoreCase))
+ {
+ return ActivePage.ExitPage;
+ }
+ }
+ return ActivePage.HistoryPage;
+ }
+
+ private static void DisplayGameInfo()
+ {
+ Console.Clear();
+ Console.WriteLine("=========== GAME INFO ===========");
+ Console.WriteLine(string.Empty);
+ DisplayGameData(games[_selectedGameNumber - 1]);
+ Console.WriteLine(string.Empty);
+ Console.WriteLine(" Choose an option:");
+ Console.WriteLine(" [ h ] = Game History");
+ Console.WriteLine(" [ m ] = Main Menu");
+ Console.WriteLine(" [ x ] = Exit Application");
+ Console.WriteLine();
+ Console.Write(" Input: ");
+ }
+
+ private static ActivePage NavigateFromGameInfo(string userInput)
+ {
+ switch (userInput)
+ {
+ case "H":
+ return ActivePage.HistoryPage;
+ case "M":
+ return ActivePage.MainPage;
+ case "X":
+ return ActivePage.ExitPage;
+ default:
+ return ActivePage.GameInfoPage;
+ }
+ }
+
+ private enum ActivePage
+ {
+ MainPage = 0,
+ GamePage = 1,
+ HistoryPage = 2,
+ GameInfoPage = 3,
+ ExitPage = 4
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Question.cs b/Rakenkode.MathGame/Rakenkode.MathGame/Question.cs
new file mode 100644
index 00000000..e3189cca
--- /dev/null
+++ b/Rakenkode.MathGame/Rakenkode.MathGame/Question.cs
@@ -0,0 +1,188 @@
+namespace Rakenkode.MathGame
+{
+ public abstract class Question
+ {
+ private protected int _num1 = 0;
+ private protected int _num2 = 0;
+ private protected int _answer = 0;
+ public int PlayerAnswer { get; set; }
+ private protected Random _random = new Random();
+
+ public int GetAnswer()
+ {
+ return _answer;
+ }
+
+ public int GetNum1()
+ {
+ return _num1;
+ }
+
+ public int GetNum2()
+ {
+ return _num2;
+ }
+
+ public bool IsPlayerCorrect()
+ {
+ return _answer == PlayerAnswer;
+ }
+
+ public static Question[] CreateProblems(int mode)
+ {
+ int numQuestion = 5;
+ Question[] questions = new Question[numQuestion];
+ Random random = new Random();
+ int type = 0;
+
+ for (int i = 0; i < numQuestion; i++)
+ {
+ if (mode < 4)
+ {
+ type = mode;
+ }
+ else
+ {
+ Thread.Sleep(random.Next(0, 101));
+ type = random.Next(0, 4);
+ }
+
+ switch (type)
+ {
+ case 0:
+ questions[i] = new AdditionProblem();
+ break;
+ case 1:
+ questions[i] = new SubtractionProblem();
+ break;
+ case 2:
+ questions[i] = new MultiplicationProblem();
+ break;
+ case 3:
+ questions[i] = new DivisionProblem();
+ break;
+ }
+ }
+
+ return questions;
+ }
+
+ public static Question[] CreateProblems(GameType gameType, int numQuestion)
+ {
+ Question[] questions = new Question[numQuestion];
+ Random random = new Random();
+ int type = 0;
+
+ for (int i = 0; i < numQuestion; i++)
+ {
+ if (gameType == GameType.Random)
+ {
+ Thread.Sleep(random.Next(0, 101));
+ type = random.Next(0, 4);
+ }
+ else
+ {
+ type = (int) gameType;
+ }
+
+ switch (type)
+ {
+ case 0:
+ questions[i] = new AdditionProblem();
+ break;
+ case 1:
+ questions[i] = new SubtractionProblem();
+ break;
+ case 2:
+ questions[i] = new MultiplicationProblem();
+ break;
+ case 3:
+ questions[i] = new DivisionProblem();
+ break;
+ }
+ }
+
+ return questions;
+ }
+ }
+
+ internal class AdditionProblem : Question
+ {
+ public AdditionProblem()
+ {
+ _num1 = _random.Next(0, 101);
+ do
+ {
+ _num2 = _random.Next(0, 101);
+ } while(_num2 == _num1);
+
+ _answer = _num1 + _num2;
+ PlayerAnswer = -1;
+ }
+
+ public override string ToString()
+ {
+ return $"{_num1} + {_num2}";
+ }
+ }
+
+ internal class SubtractionProblem : Question
+ {
+ public SubtractionProblem()
+ {
+ int temp1 = _random.Next(0, 101);
+ int temp2 = 0;
+ do
+ {
+ temp2 = _random.Next(0, 101);
+ }while (temp1 == temp2);
+
+ _num1 = Math.Max(temp1, temp2);
+ _num2 = Math.Min(temp1, temp2);
+ _answer = _num1 - _num2;
+ PlayerAnswer = -1;
+ }
+
+ public override string ToString()
+ {
+ return $"{_num1} - {_num2}";
+ }
+ }
+
+ internal class MultiplicationProblem : Question
+ {
+ public MultiplicationProblem()
+ {
+ _num1 = _random.Next(0, 101);
+ _num2 = _random.Next(0, 101);
+ _answer = _num1 * _num2;
+ PlayerAnswer = -1;
+ }
+
+ public override string ToString()
+ {
+ return $"{_num1} x {_num2}";
+ }
+ }
+
+ internal class DivisionProblem : Question
+ {
+ public DivisionProblem()
+ {
+ while (true)
+ {
+ _num2 = _random.Next(1, 101);
+ _num1 = _num2 * _random.Next(2, 11);
+ if (_num1 < 101)
+ break;
+ }
+ _answer = _num1 / _num2;
+ PlayerAnswer = -1;
+ }
+
+ public override string ToString()
+ {
+ return $"{_num1} / {_num2}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Rakenkode.MathGame/Rakenkode.MathGame/Rakenkode.MathGame.csproj b/Rakenkode.MathGame/Rakenkode.MathGame/Rakenkode.MathGame.csproj
new file mode 100644
index 00000000..6c1dc922
--- /dev/null
+++ b/Rakenkode.MathGame/Rakenkode.MathGame/Rakenkode.MathGame.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+