diff --git a/.gitignore b/.gitignore index 0d44d8c7..99e01f14 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ # Env files. .env +FlashCards.Review/FlashCard.App/app.config + # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -480,3 +482,8 @@ $RECYCLE.BIN/ *.lnk .idea + + +#temp files +FlashCards.Review/FlashCard.App/obj/ +FlashCards.Review/FlashCard.App/DataBaseScripts/ \ No newline at end of file diff --git a/FlashCards.Review/FlashCard.App/Controller/FlashCardController.cs b/FlashCards.Review/FlashCard.App/Controller/FlashCardController.cs new file mode 100644 index 00000000..bc07dea7 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Controller/FlashCardController.cs @@ -0,0 +1,49 @@ +using FlashCardLearning.DataAccess; +using FlashCardLearning.Model.entities; + +namespace FlashCardLearning.Controller +{ + class FlashCardController + { + FlashCardDataAccess flashCardDataAccess = new(); + + internal void CreateFlashCard(string? question, string answer, int stackId) + { + FlashCards flashCardEntity = new(); + flashCardEntity.Question = question; + flashCardEntity.Answer = answer; + flashCardEntity.StackId = stackId; + + flashCardDataAccess.AddFlashCard(flashCardEntity); + } + + internal bool CheckFlashCardAvailable(int flashCardId) + { + bool flashCardAvailable = flashCardDataAccess.CheckFlashCardAvailable(flashCardId); + return flashCardAvailable; + } + + internal void EditFlashCard(int flashCardId, string question, string answer) + { + FlashCards flashCardEntity = new(); + flashCardEntity.Id = flashCardId; + flashCardEntity.Question = question; + flashCardEntity.Answer = answer; + + flashCardDataAccess.UpdateFlashCard(flashCardEntity); + } + + internal void RemoveFlashCard(int flashCardId) + { + flashCardDataAccess.DeleteFlashCard(flashCardId); + } + + internal List ViewFlashCards(int StackId) + { + List flashCards = flashCardDataAccess.SelectFlashCard(StackId); + return flashCards; + } + + + } +} diff --git a/FlashCards.Review/FlashCard.App/Controller/StackController.cs b/FlashCards.Review/FlashCard.App/Controller/StackController.cs new file mode 100644 index 00000000..cfc9a894 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Controller/StackController.cs @@ -0,0 +1,52 @@ +using FlashCardLearning.DataAccess; +using FlashCardLearning.Model.entities; + + +namespace FlashCardLearning.Controller +{ + internal class StackController + { + StackDataAccess stackDataAccess = new(); + + internal void CreateStack(string stackName) + { + Stacks stackEntity = new(); + stackEntity.StackName = stackName; + + stackDataAccess.Addstack(stackEntity); + } + + internal List ViewStack() + { + List stacks = stackDataAccess.Selectstack(); + return stacks; + } + + internal bool CheckStackAvailable(int stackId) + { + bool StackAvailable = stackDataAccess.CheckStackAvailable(stackId); + return StackAvailable; + } + + internal void EditStack(int stackId, string stackName) + { + Stacks stackEntity = new(); + + stackEntity.Id = stackId; + stackEntity.StackName = stackName; + + stackDataAccess.UpdateStack(stackEntity); + } + + internal void RemoveStack(int stackId) + { + stackDataAccess.DeleteStack(stackId); + + stackDataAccess.DeleteFlashCards(stackId); + + stackDataAccess.DeleteSudySession(stackId); + } + + + } +} diff --git a/FlashCards.Review/FlashCard.App/Controller/StudyController.cs b/FlashCards.Review/FlashCard.App/Controller/StudyController.cs new file mode 100644 index 00000000..c59c9658 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Controller/StudyController.cs @@ -0,0 +1,41 @@ +using FlashCardLearning.DataAccess; +using FlashCardLearning.Model.entities; + +namespace FlashCardLearning.Controller +{ + internal class StudyController + { + StudyDataAccess studyDataAccess = new(); + internal void TrackSession(string flashCardslist, int stackId, int durationPerSession, int totalPoints) + { + StudySession studySession = new(); + studySession.FlashCardsLearned = flashCardslist; + studySession.StackId = stackId; + studySession.SessionDuration = durationPerSession; + studySession.Points = totalPoints; + + studyDataAccess.AddSession(studySession); + } + + + internal List ViewReports(int year) + { + List report = studyDataAccess.SelectReport(year); + return report; + } + + internal List ViewSessionLog(string? startDate, string? endDate) + { + StudySessionHistoryInput studySessionHistoryInput = new(); + + DateOnly startDateOnly = DateOnly.Parse(startDate); + DateOnly endDateOnly = DateOnly.Parse(endDate); + + studySessionHistoryInput.SessionStartDate = startDateOnly; + studySessionHistoryInput.SessionEndDate = endDateOnly; + + List studySessionHistories = studyDataAccess.SelectSessionLog(studySessionHistoryInput); + return studySessionHistories; + } + } +} diff --git a/FlashCards.Review/FlashCard.App/DataAccess/FlashCardDataAccess.cs b/FlashCards.Review/FlashCard.App/DataAccess/FlashCardDataAccess.cs new file mode 100644 index 00000000..3f9fc850 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/DataAccess/FlashCardDataAccess.cs @@ -0,0 +1,184 @@ +using FlashCardLearning.Model.entities; +using Microsoft.Data.SqlClient; +using System.Configuration; +using System.Data; + +namespace FlashCardLearning.DataAccess +{ + internal class FlashCardDataAccess + { + + string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"]?.ConnectionString; + + internal void AddFlashCard(FlashCards flashCardEntity) + { + string query = "INSERT INTO FlashCards (question, answer, stack_id) VALUES (@question, @answer, @stackId)"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@question", SqlDbType.VarChar).Value = flashCardEntity.Question; + command.Parameters.Add("@answer", SqlDbType.VarChar).Value = flashCardEntity.Answer; + command.Parameters.Add("@stackId", SqlDbType.VarChar).Value = flashCardEntity.StackId; + command.ExecuteNonQuery(); + + Console.WriteLine(); + Console.WriteLine($"Flash Card has been created succesfully"); + Console.WriteLine(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + + internal List SelectFlashCard(int StackId) + { + + string query = "SELECT id, question, answer FROM FlashCards WHERE stack_id = @StackId"; + + List flashCards = new List(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@StackId", SqlDbType.VarChar).Value = StackId; + + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + flashCards.Add(new FlashCards + { + Id = reader.GetInt32(reader.GetOrdinal("Id")), + Question = reader.GetString(reader.GetOrdinal("question")), + Answer = reader.GetString(reader.GetOrdinal("answer")) + }); + } + + } + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + return flashCards; + } + internal bool CheckFlashCardAvailable(int flashCardId) + { + string query = "SELECT id FROM FlashCards WHERE id=@flashCardId"; + + bool flashCardAvailable = true; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@flashCardId", SqlDbType.Int).Value = flashCardId; + object? result = command.ExecuteScalar(); + if (result == null) + { + flashCardAvailable = false; + } + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + return flashCardAvailable; + } + + internal void UpdateFlashCard(FlashCards flashCardEntity) + { + string question = ""; + string answer = ""; + + if (flashCardEntity.Question != "" && flashCardEntity.Answer != "") + { + question = "question = @question,"; + answer = " answer = @answer"; + + } + else if (flashCardEntity.Answer != "") + { + answer = " answer = @answer"; + } + else if (flashCardEntity.Question != "") + { + question = "question = @question"; + } + + + string query = $"UPDATE FlashCards SET {question} {answer} WHERE id = @flashCardId"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@flashCardId", SqlDbType.Int).Value = flashCardEntity.Id; + command.Parameters.Add("@question", SqlDbType.VarChar).Value = flashCardEntity.Question; + command.Parameters.Add("@answer", SqlDbType.VarChar).Value = flashCardEntity.Answer; + command.ExecuteNonQuery(); + + Console.WriteLine(); + Console.WriteLine($"Flash Card updated successfully"); + Console.WriteLine(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + + internal void DeleteFlashCard(int flashCardId) + { + string query = "DELETE FROM FlashCards WHERE id = @flashCardId"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@flashCardId", SqlDbType.Int).Value = flashCardId; + command.ExecuteNonQuery(); + + Console.WriteLine(); + Console.WriteLine($"Flash Card deleted successfully"); + Console.WriteLine(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + } + +} + diff --git a/FlashCards.Review/FlashCard.App/DataAccess/StackDataAccess.cs b/FlashCards.Review/FlashCard.App/DataAccess/StackDataAccess.cs new file mode 100644 index 00000000..1fab8355 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/DataAccess/StackDataAccess.cs @@ -0,0 +1,212 @@ +using Microsoft.Data.SqlClient; +using System.Data; +using System.Configuration; +using FlashCardLearning.Model.entities; + + +namespace FlashCardLearning.DataAccess +{ + internal class StackDataAccess + { + string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"]?.ConnectionString; + + internal void Addstack(Stacks stackEntity) + { + string query = "INSERT INTO Stacks (stack_name) VALUES (@stackname)"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@stackname", SqlDbType.VarChar).Value = stackEntity.StackName; + command.ExecuteNonQuery(); + + Console.WriteLine(); + Console.WriteLine($"Stack with name {stackEntity.StackName} has been created succesfully"); + Console.WriteLine(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + + } + } + + internal List Selectstack() + { + string query = "SELECT id, stack_name from stacks"; + + List stacks = new List(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + stacks.Add(new Stacks + { + Id = reader.GetInt32(reader.GetOrdinal("Id")), + StackName = reader.GetString(reader.GetOrdinal("stack_name")) + }); + } + + } + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + return stacks; + } + + internal bool CheckStackAvailable(int stackId) + { + string query = "SELECT id FROM stacks WHERE id=@stackId"; + + bool stackAvailable = true; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@stackId", SqlDbType.Int).Value = stackId; + + object? result = command.ExecuteScalar(); + + if (result == null) + { + stackAvailable = false; + } + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + return stackAvailable; + } + + internal void UpdateStack(Stacks stacks) + { + string query = "UPDATE stacks SET stack_name = @stackname WHERE id = @stackId"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@stackId", SqlDbType.Int).Value = stacks.Id; + command.Parameters.Add("@stackname", SqlDbType.VarChar).Value = stacks.StackName; + + command.ExecuteNonQuery(); + + Console.WriteLine(); + Console.WriteLine($"Stack updated to {stacks.StackName} succesfully"); + Console.WriteLine(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + + internal void DeleteStack(int stackId) + { + string query = "DELETE FROM stacks WHERE id = @stackId"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@stackId", SqlDbType.Int).Value = stackId; + command.ExecuteNonQuery(); + + Console.WriteLine(); + Console.WriteLine($"Stack deleted succesfully"); + Console.WriteLine(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + + internal void DeleteFlashCards(int stackId) + { + + string query = "DELETE FROM FlashCards WHERE stack_id = @stackId"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@stackId", SqlDbType.Int).Value = stackId; + command.ExecuteNonQuery(); + + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + internal void DeleteSudySession(int stackId) + { + + string query = "DELETE FROM LearningLog WHERE stack_id = @stackId"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@stackId", SqlDbType.Int).Value = stackId; + command.ExecuteNonQuery(); + + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + } + } +} diff --git a/FlashCards.Review/FlashCard.App/DataAccess/StudyDataAccess.cs b/FlashCards.Review/FlashCard.App/DataAccess/StudyDataAccess.cs new file mode 100644 index 00000000..8094c54f --- /dev/null +++ b/FlashCards.Review/FlashCard.App/DataAccess/StudyDataAccess.cs @@ -0,0 +1,149 @@ +using System.Configuration; +using FlashCardLearning.Model.entities; +using Microsoft.Data.SqlClient; +using System.Data; + +namespace FlashCardLearning.DataAccess +{ + internal class StudyDataAccess + { + + string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"]?.ConnectionString; + + internal void AddSession(StudySession studySession) + { + string query = "INSERT INTO LearningLog (flash_cards_reviewed, stack_id, duration_minutes, points) " + + "VALUES (@flashCardslist, @stackId, @durationPerSession, @totalPoints)"; + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@flashCardslist", SqlDbType.VarChar).Value = studySession.FlashCardsLearned; + command.Parameters.Add("@stackId", SqlDbType.VarChar).Value = studySession.StackId; + command.Parameters.Add("@durationPerSession", SqlDbType.VarChar).Value = studySession.SessionDuration; + command.Parameters.Add("@totalPoints", SqlDbType.VarChar).Value = studySession.Points; + command.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + + } + } + + internal List SelectReport(int year) + { + string query = @" + SELECT + s.stack_name, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 1 THEN l.stack_id END) AS January, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 2 THEN l.stack_id END) AS February, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 3 THEN l.stack_id END) AS March, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 4 THEN l.stack_id END) AS April, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 5 THEN l.stack_id END) AS May, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 6 THEN l.stack_id END) AS June, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 7 THEN l.stack_id END) AS July, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 8 THEN l.stack_id END) AS August, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 9 THEN l.stack_id END) AS September, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 10 THEN l.stack_id END) AS October, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 11 THEN l.stack_id END) AS November, + COUNT(CASE WHEN DATEPART(month, l.session_date) = 12 THEN l.stack_id END) AS December + FROM LearningLog l + INNER JOIN Stacks s ON s.id = l.stack_id + WHERE YEAR(l.session_date) = @Year + GROUP BY s.stack_name + ORDER BY s.stack_name;"; + + List reports = new List(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@Year", SqlDbType.Int).Value = year; // use Int not VarChar + + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + reports.Add(new StackReport + { + StackName = reader.GetString(reader.GetOrdinal("stack_name")), + January = reader.GetInt32(reader.GetOrdinal("January")), + February = reader.GetInt32(reader.GetOrdinal("February")), + March = reader.GetInt32(reader.GetOrdinal("March")), + April = reader.GetInt32(reader.GetOrdinal("April")), + May = reader.GetInt32(reader.GetOrdinal("May")), + June = reader.GetInt32(reader.GetOrdinal("June")), + July = reader.GetInt32(reader.GetOrdinal("July")), + August = reader.GetInt32(reader.GetOrdinal("August")), + September = reader.GetInt32(reader.GetOrdinal("September")), + October = reader.GetInt32(reader.GetOrdinal("October")), + November = reader.GetInt32(reader.GetOrdinal("November")), + December = reader.GetInt32(reader.GetOrdinal("December")) + }); + } + } + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + return reports; + } + + internal List SelectSessionLog(StudySessionHistoryInput studySessionHistoryInput) + { + string query = @" + select + stack_name,points,session_date from LearningLog l + INNER JOIN Stacks s ON s.id = l.stack_id + where session_date >= @startDate and session_date < @endDate + ORDER BY session_date ASC"; + + List history = new List(); + + using (SqlConnection connection = new SqlConnection(connectionString)) + { + connection.Open(); + try + { + using (SqlCommand command = new SqlCommand(query, connection)) + { + command.Parameters.Add("@startDate", SqlDbType.Date).Value = studySessionHistoryInput.SessionStartDate; // use Int not VarChar + command.Parameters.Add("@endDate", SqlDbType.Date).Value = studySessionHistoryInput.SessionEndDate; + + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + history.Add(new StudySessionHistory + { + StackName = reader.GetString(reader.GetOrdinal("stack_name")), + Points = reader.GetInt32(reader.GetOrdinal("points")), + SessionDate = reader.GetDateTime(reader.GetOrdinal("session_date")), + }); + } + } + } + } + catch (Exception ex) + { + Console.WriteLine($"SQL Error: {ex.Message}"); + } + } + return history; + } + } +} diff --git a/FlashCards.Review/FlashCard.App/FlashCardLearning.csproj b/FlashCards.Review/FlashCard.App/FlashCardLearning.csproj new file mode 100644 index 00000000..5d78ac7a --- /dev/null +++ b/FlashCards.Review/FlashCard.App/FlashCardLearning.csproj @@ -0,0 +1,19 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + diff --git a/FlashCards.Review/FlashCard.App/Helper/utilities.cs b/FlashCards.Review/FlashCard.App/Helper/utilities.cs new file mode 100644 index 00000000..226cc944 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Helper/utilities.cs @@ -0,0 +1,41 @@ +using FlashCardLearning.View; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FlashCardLearning.Helper +{ + internal class Utilities + { + FlashCardMenu flashCardMenu = new(); + + public int ValidateFlashCardId() + { + Console.WriteLine("Please enter the FlashCard Id, Press 0 to Return to Main Menu"); + string userInput = Console.ReadLine(); + + int flashCardId = 0; + + bool isInteger = int.TryParse(userInput, out flashCardId); + + + while (flashCardId < 0 || !isInteger) + { + Console.WriteLine("Please Enter a valid FlashCard Id, To Return to Stack Menu Enter 0"); + userInput = Console.ReadLine(); + + isInteger = int.TryParse(userInput, out flashCardId); + } + + if (flashCardId == 0) + { + flashCardMenu.ManageFlashCard(); + return 0; + } + + return flashCardId; + } + } +} diff --git a/FlashCards.Review/FlashCard.App/Model/entities/FlashCards.cs b/FlashCards.Review/FlashCard.App/Model/entities/FlashCards.cs new file mode 100644 index 00000000..cfbd7f07 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Model/entities/FlashCards.cs @@ -0,0 +1,10 @@ +namespace FlashCardLearning.Model.entities +{ + internal class FlashCards + { + public int Id {get; set;} + public string? Question { get; set; } + public string? Answer { get; set; } + public int StackId { get; set; } + } +} diff --git a/FlashCards.Review/FlashCard.App/Model/entities/Stacks.cs b/FlashCards.Review/FlashCard.App/Model/entities/Stacks.cs new file mode 100644 index 00000000..fcd35f7c --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Model/entities/Stacks.cs @@ -0,0 +1,8 @@ +namespace FlashCardLearning.Model.entities +{ + public class Stacks + { + public int Id {get; set;} + public string? StackName {get; set;} + } +} diff --git a/FlashCards.Review/FlashCard.App/Model/entities/StudySession.cs b/FlashCards.Review/FlashCard.App/Model/entities/StudySession.cs new file mode 100644 index 00000000..3067eff4 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Model/entities/StudySession.cs @@ -0,0 +1,39 @@ +namespace FlashCardLearning.Model.entities +{ + internal class StudySession + { + public string FlashCardsLearned { get; set; } + public int StackId { get; set; } + public int SessionDuration { get; set; } + public int Points { get; set; } + } + + internal class StudySessionHistoryInput + { + public DateOnly SessionStartDate { get; set; } + public DateOnly SessionEndDate { get; set; } + } + internal class StudySessionHistory + { + public string StackName { get; set; } + public DateTime SessionDate { get; set; } + public int Points { get; set; } + } + + internal class StackReport + { + public string StackName { get; set; } + public int January { get; set; } + public int February { get; set; } + public int March { get; set; } + public int April { get; set; } + public int May { get; set; } + public int June { get; set; } + public int July { get; set; } + public int August { get; set; } + public int September { get; set; } + public int October { get; set; } + public int November { get; set; } + public int December { get; set; } + } +} diff --git a/FlashCards.Review/FlashCard.App/Program.cs b/FlashCards.Review/FlashCard.App/Program.cs new file mode 100644 index 00000000..934577ea --- /dev/null +++ b/FlashCards.Review/FlashCard.App/Program.cs @@ -0,0 +1,5 @@ +using FlashCardLearning.View; + +MainMenu mainMenu = new(); + +mainMenu.UserMainMenue(); \ No newline at end of file diff --git a/FlashCards.Review/FlashCard.App/View/FlashCardMenu.cs b/FlashCards.Review/FlashCard.App/View/FlashCardMenu.cs new file mode 100644 index 00000000..fd130b57 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/View/FlashCardMenu.cs @@ -0,0 +1,190 @@ +using ConsoleTables; +using FlashCardLearning.Controller; +using FlashCardLearning.Model.entities; +using FlashCardLearning.Helper; + +namespace FlashCardLearning.View +{ + internal class FlashCardMenu + { + FlashCardController flashCardController = new(); + StackController stackController = new(); + StackMenu stackMenu = new(); + Utilities utilities = new(); + + int StackId; + public void ManageFlashCard() + { + Console.Clear(); + + ViewFlashCard(); + Console.WriteLine(); + Console.WriteLine("-----------Manage Flash Card Menu-----------"); + Console.WriteLine(); + Console.WriteLine("Enter 1 to create a FlashCard"); + Console.WriteLine("Enter 2 to Edit a FlashCard"); + Console.WriteLine("Enter 3 to Delete a FlashCard"); + Console.WriteLine("Enter 4 to Return to Stack Menu"); + Console.WriteLine(); + var userInput = Console.ReadLine(); + + string[] allowedUserInput = { "1", "2", "3", "4" }; + + while (!allowedUserInput.Contains(userInput)) + { + Console.WriteLine("Please Enter a valid menu number"); + userInput = Console.ReadLine(); + } + + while (true) + { + switch (userInput) + { + case "1": + CreateFlashCard(); + break; + case "2": + EditFlashCard(); + break; + case "3": + RemoveFlashCard(); + break; + case "4": + SelectStack(); + break; + } + } + } + + internal void SelectStack() + { + StackMenu stackMenu = new(); + + Console.Clear(); + + stackMenu.ViewStack(false); + + Console.WriteLine("Please Enter the Stack Id to View the Flash Cards and Manage It , enter 0 to return to stack menu"); + StackId = stackMenu.ValidateStackId(); + + Console.Clear(); + + if (StackId != 0) ManageFlashCard(); + else stackMenu.ManageStacks(); + + } + + private void ViewFlashCard() + { + Console.WriteLine("Below are the Available Flash Cards"); + Console.WriteLine(); + + List flashCards = flashCardController.ViewFlashCards(StackId); + + var flashCardTable = new ConsoleTable("Id", "Question", "Answer"); + + foreach (FlashCards flashCard in flashCards) + { + flashCardTable.AddRow(flashCard.Id, flashCard.Question, flashCard.Answer); + } + flashCardTable.Write(); + + } + + private void CreateFlashCard() + { + Console.Clear(); + Console.WriteLine("Please Enter the Question, Press 0 to Return to Main Menu "); + + string Question = Console.ReadLine(); + + while (string.IsNullOrEmpty(Question) || Question.Length < 2) + { + if (Question == "0") + { + ManageFlashCard(); + return; + } + + Console.WriteLine("Please Enter a Proper Question"); + Question = Console.ReadLine(); + } + + Console.WriteLine("Please Enter the Answer, Press 0 to Return to Main Menu "); + + string Answer = Console.ReadLine(); + + while (string.IsNullOrEmpty(Answer) || Answer.Length < 2) + { + if (Answer == "0") + { + ManageFlashCard(); + return; + } + + Console.WriteLine("Please Enter a Proper Answer"); + Answer = Console.ReadLine(); + } + flashCardController.CreateFlashCard(Question, Answer, StackId); + } + + private void EditFlashCard() + { + int flashCardId = GetFlashcardId(); + + Console.WriteLine("Please enter the Question to update, Press 0 to Return to Main Menu"); + string question = Console.ReadLine(); + + Console.WriteLine(); + + Console.WriteLine("Please enter the Answer to update, Press 0 to Return to Main Menu"); + string answer = Console.ReadLine(); + + while ((string.IsNullOrEmpty(question) || question.Length < 2) && (string.IsNullOrEmpty(answer) || answer.Length < 2)) + { + if (question == "0") + { + ManageFlashCard(); + return; + } + Console.WriteLine("Please enter either Answer or Question to update"); + question = Console.ReadLine(); + } + + flashCardController.EditFlashCard(flashCardId, question, answer); + } + + private void RemoveFlashCard() + { + int flashCardId = GetFlashcardId(); + + while (!flashCardController.CheckFlashCardAvailable(flashCardId)) + { + flashCardId = utilities.ValidateFlashCardId(); + } + + flashCardController.RemoveFlashCard(flashCardId); + } + + private int GetFlashcardId() + { + Console.Clear(); + + ViewFlashCard(); + Console.WriteLine(); + + int flashCardId = utilities.ValidateFlashCardId(); + Console.WriteLine(); + + while (!flashCardController.CheckFlashCardAvailable(flashCardId)) + { + flashCardId = utilities.ValidateFlashCardId(); + } + + return flashCardId; + } + + + + } +} diff --git a/FlashCards.Review/FlashCard.App/View/MainMenu.cs b/FlashCards.Review/FlashCard.App/View/MainMenu.cs new file mode 100644 index 00000000..30230251 --- /dev/null +++ b/FlashCards.Review/FlashCard.App/View/MainMenu.cs @@ -0,0 +1,49 @@ +namespace FlashCardLearning.View +{ + internal class MainMenu + { + internal void UserMainMenue() + { + StackMenu stackMenu = new(); + StudyMenu studyMenu = new(); + + Console.Clear(); + Console.WriteLine("-----------Welcome to Flash Card Learning App-----------"); + Console.WriteLine("Enter 1 to Manage Stacks and Flash Cards"); + Console.WriteLine("Enter 2 to Start a Learning Session"); + Console.WriteLine("Enter 3 View Study Session Reports"); + Console.WriteLine("Enter 0 to Quit"); + Console.WriteLine(); + var userInput = Console.ReadLine(); + bool runApp = true; + + string[] allowedUserInput = { "1", "2", "3", "0" }; + + while (!allowedUserInput.Contains(userInput)) + { + Console.WriteLine("Please Enter a valid menu number"); + userInput = Console.ReadLine(); + } + + while (runApp) + { + switch (userInput) + { + case "1": + stackMenu.ManageStacks(); + break; + case "2": + studyMenu.StudySession(); + break; + case "3": + studyMenu.ViewReports(); + break; + case "0": + Environment.Exit(0); + break; + } + } + + } + } +} diff --git a/FlashCards.Review/FlashCard.App/View/StackMenu.cs b/FlashCards.Review/FlashCard.App/View/StackMenu.cs new file mode 100644 index 00000000..79561cfe --- /dev/null +++ b/FlashCards.Review/FlashCard.App/View/StackMenu.cs @@ -0,0 +1,204 @@ +using System.Text.RegularExpressions; +using ConsoleTables; +using FlashCardLearning.Controller; +using FlashCardLearning.Model.entities; + +namespace FlashCardLearning.View +{ + internal class StackMenu + { + StackController stackController = new(); + FlashCardMenu flashCardMenu = new(); + MainMenu mainMenu = new(); + + internal void ManageStacks() + { + Console.Clear(); + Console.WriteLine("-----------Manage Stack Menu-----------"); + Console.WriteLine(); + Console.WriteLine("Enter 1 to Create a Stack"); + Console.WriteLine("Enter 2 to Edit a Stack"); + Console.WriteLine("Enter 3 to Delete a Stack"); + Console.WriteLine("Enter 4 to View Available Stacks"); + Console.WriteLine("Enter 5 to View Flash Cards Inside the Stack"); + Console.WriteLine("Enter 6 to Return to Main Menu"); + + var userInput = Console.ReadLine(); + + string[] allowedUserInput = { "1", "2", "3", "4", "5", "6" }; + + while (!allowedUserInput.Contains(userInput)) + { + Console.WriteLine("Please Enter a valid menu number"); + userInput = Console.ReadLine(); + } + bool fromMenu = true; + + while (true) + { + switch (userInput) + { + case "1": + CreateStack(); + break; + case "2": + EditStack(); + break; + case "3": + RemoveStack(); + break; + case "4": + ViewStack(fromMenu); + break; + case "5": + flashCardMenu.SelectStack(); + break; + case "6": + mainMenu.UserMainMenue(); + break; + } + } + } + + private void CreateStack() + { + Console.Clear(); + Console.WriteLine("Please Enter the Stack Name, To Return to Stack Menu Enter 0"); + + string stackName = Console.ReadLine(); + + while (string.IsNullOrEmpty(stackName) || stackName.Length < 2 || !Regex.IsMatch(stackName, @"^[a-zA-Z #\-/]+$")) + { + if (stackName == "0") + { + ManageStacks(); + return; + } + + Console.WriteLine("Please Enter a Proper Stack Name"); + stackName = Console.ReadLine(); + } + stackController.CreateStack(stackName); + } + + private void EditStack() + { + Console.Clear(); + + //display available stacks + ViewStack(false); + Console.WriteLine("Please Enter a valid Stack Id, To Return to Stack Menu Enter 0"); + int StackId = ValidateStackId(); + + while (!stackController.CheckStackAvailable(StackId)) + { + Console.WriteLine(); + Console.WriteLine("Stack Id was not available "); + Console.WriteLine(); + StackId = ValidateStackId(); + } + + //obtain stack name + Console.WriteLine(); + Console.WriteLine("Please Enter a Stack Name to Update, To Return to Stack Menu Enter 0"); + string stackName = Console.ReadLine(); + + while (string.IsNullOrEmpty(stackName) || stackName.Length < 2 || !Regex.IsMatch(stackName, @"^(?!\d+$)[a-zA-Z0-9 #\-/]+$")) + { + if (stackName == "0") + { + ManageStacks(); + return; + } + + Console.WriteLine("Please Enter a Proper Stack Name to Update"); + stackName = Console.ReadLine(); + + } + + stackController.EditStack(StackId, stackName); + } + + public int ValidateStackId() + { + + string userInput = Console.ReadLine(); + + int StackId = 0; + + bool isInteger = int.TryParse(userInput, out StackId); + + + while (StackId < 0 || !isInteger) + { + Console.WriteLine("Please Enter a valid Stack Id, To Return to Stack Menu Enter 0"); + userInput = Console.ReadLine(); + + isInteger = int.TryParse(userInput, out StackId); + } + + if (StackId == 0) + { + ManageStacks(); + return 0; + } + + return StackId; + } + + public void ViewStack(bool fromMenu) + { + + Console.WriteLine("Below are the available stacks"); + + List stackList = stackController.ViewStack(); + + var stackTable = new ConsoleTable("Id", "Stack Name"); + + foreach (Stacks stack in stackList) + { + stackTable.AddRow(stack.Id, stack.StackName); + } + + stackTable.Write(); + + Console.WriteLine(); + + //obtain ID + if (fromMenu) + { + Console.WriteLine("To Return to Stack Menu Enter 0"); + string unserInput = Console.ReadLine(); + + if (unserInput == "0") + { + ManageStacks(); + return; + } + } + } + + private void RemoveStack() + { + Console.Clear(); + //display available stacks + ViewStack(false); + + //obtain ID + Console.WriteLine("Please note that by deleting a stack the related flash cards will also get deleted!!!"); + Console.WriteLine(); + Console.WriteLine("Please Enter a valid Stack Id, To Return to Stack Menu Enter 0"); + int StackId = ValidateStackId(); + + + while (!stackController.CheckStackAvailable(StackId)) + { + StackId = ValidateStackId(); + } + + stackController.RemoveStack(StackId); + + } + + } +} diff --git a/FlashCards.Review/FlashCard.App/View/StudyMenu.cs b/FlashCards.Review/FlashCard.App/View/StudyMenu.cs new file mode 100644 index 00000000..7fc2edba --- /dev/null +++ b/FlashCards.Review/FlashCard.App/View/StudyMenu.cs @@ -0,0 +1,331 @@ +using ConsoleTables; +using FlashCardLearning.Controller; +using FlashCardLearning.Model.entities; +using FlashCardLearning.Helper; + +namespace FlashCardLearning.View +{ + internal class StudyMenu + { + MainMenu mainMenu = new(); + StackMenu stackMenu = new(); + FlashCardMenu flashCardMenu = new(); + + FlashCardController flashCardController = new(); + StackController stackController = new(); + StudyController studyController = new(); + + Utilities utilities = new(); + + int StackId; + int totalPoints; + int totalReviewdPoints; + DateTime sessionStartTime; + DateTime sessionEndTime; + int durationPerSession; + string FlashCardslist = ""; + + internal void StudySession() + { + Console.Clear(); + Console.WriteLine("-----------Learning Menu-----------"); + Console.WriteLine(); + Console.WriteLine("Enter 1 to Open Avaliable Stacks"); + Console.WriteLine("Enter 2 to Open Learning Session History"); + Console.WriteLine("Enter 0 to Return To Main Menue"); + + string userInput = Console.ReadLine(); + + string[] allowedUserInput = { "1", "2", "0" }; + + while (!allowedUserInput.Contains(userInput)) + { + Console.WriteLine("Please Enter a valid menu number"); + userInput = Console.ReadLine(); + } + + while (true) + { + switch (userInput) + { + case "1": + SelectStack(); + break; + case "2": + ViewSessionLog(); + break; + case "0": + mainMenu.UserMainMenue(); + break; + } + } + } + + private void ViewSessionLog() + { + Console.WriteLine("------------Session Log-----------"); + Console.WriteLine(); + + Console.WriteLine("Please enter the Start Date(yyyy-mm-dd), Enter 0 to Return to Main Menu "); + string startDate = Console.ReadLine(); + Console.WriteLine(); + + if (startDate == "0") + { + StudySession(); + return; + } + + string pattern = @"^\d{4}-\d{2}-\d{2}$"; + while (!System.Text.RegularExpressions.Regex.IsMatch(startDate, pattern) || + !DateTime.TryParseExact(startDate, "yyyy-mm-dd", + System.Globalization.CultureInfo.InvariantCulture, + System.Globalization.DateTimeStyles.None, + out DateTime validDate)) + { + if (startDate == "0") + { + StudySession(); + return; + } + Console.WriteLine("Please enter the Start Date(yyyy-mm-dd) in proper format"); + startDate = Console.ReadLine(); + } + + Console.WriteLine("Please enter the End Date(yyyy-mm-dd), Enter 0 to Return to Main Menu "); + string endDate = Console.ReadLine(); + Console.WriteLine(); + + if (endDate == "0") + { + StudySession(); + return; + } + + while (!System.Text.RegularExpressions.Regex.IsMatch(endDate, pattern) || + !DateTime.TryParseExact(startDate, "yyyy-mm-dd", + System.Globalization.CultureInfo.InvariantCulture, + System.Globalization.DateTimeStyles.None, + out DateTime validDate)) + { + if (endDate == "0") + { + StudySession(); + return; + } + Console.WriteLine("Please enter the End Date(yyyy-mm-dd) in proper format"); + endDate = Console.ReadLine(); + } + + + List historyList = studyController.ViewSessionLog(startDate, endDate); + + var stackTable = new ConsoleTable("Id", "Stack Name", "Points", "Session Date"); + + int rowCount = 1; + + foreach (StudySessionHistory history in historyList) + { + stackTable.AddRow(rowCount, history.StackName, history.Points, history.SessionDate); + rowCount += 1; + } + stackTable.Write(); + + Console.WriteLine(); + + Console.WriteLine("Enter 0 to return to Previous menu"); + string userInput = Console.ReadLine(); + + if (userInput == "0") + { + StudySession(); + return; + } + } + + internal void ViewReports() + { + + Console.WriteLine("Please Enter a year in YYYY format to generate report, enter 0 to return to Previous menu"); + Console.WriteLine(); + + string year = Console.ReadLine(); + + int YearInput = 0; + + while (string.IsNullOrEmpty(year) || year.Length != 4 || !int.TryParse(year, out YearInput)) + { + if (year == "0") + { + StudySession(); + return; + } + + Console.WriteLine("Please Enter year in YYYY format"); + year = Console.ReadLine(); + } + + if (YearInput == 0) mainMenu.UserMainMenue(); + + List studySessions = studyController.ViewReports(YearInput); + + var ReportTable = new ConsoleTable( + "Stack Name", + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ); + + // Add rows for each stack + foreach (StackReport studySession in studySessions) + { + ReportTable.AddRow( + studySession.StackName, + studySession.January, + studySession.February, + studySession.March, + studySession.April, + studySession.May, + studySession.June, + studySession.July, + studySession.August, + studySession.September, + studySession.October, + studySession.November, + studySession.December + ); + } + + ReportTable.Write(); + + Console.WriteLine(); + Console.WriteLine("Enter 0 to return to Previous menu"); + Console.WriteLine(); + + string exit = Console.ReadLine(); + + if (exit == "0") mainMenu.UserMainMenue(); + } + + private void SelectStack() + { + Console.Clear(); + + stackMenu.ViewStack(false); + + Console.WriteLine("Please Enter the Stack Id to View the Flash Cards and Manage It , enter 0 to return to Previous menu"); + Console.WriteLine(); + + StackId = stackMenu.ValidateStackId(); + + if (StackId != 0) ViewFlashCards(StackId); + else mainMenu.UserMainMenue(); + } + private void ViewFlashCards(int StackId) + { + Console.WriteLine("Below are the Available Flash Cards"); + Console.WriteLine(); + + List flashCards = flashCardController.ViewFlashCards(StackId); + + var flashCardTable = new ConsoleTable("Id", "Question"); + + foreach (FlashCards flashCard in flashCards) + { + flashCardTable.AddRow(flashCard.Id, flashCard.Question); + } + + flashCardTable.Write(); + + AnswerFlashCard(flashCards); + } + + private void AnswerFlashCard(List FlashCards) + { + sessionStartTime = DateTime.Now; + + Console.WriteLine("Please enter the id of the flash card you choose to answer. enter 0 to return to Previous menu"); + + int flashCardId = utilities.ValidateFlashCardId(); + + if (flashCardId == 0) + { + Console.Clear(); + + Console.WriteLine(); + + sessionEndTime = DateTime.Now; + + GetDurationPerSession(); + + studyController.TrackSession(FlashCardslist, StackId, durationPerSession, totalPoints); + + SelectStack(); + + totalPoints = 0; + + } + + Console.WriteLine("Please enter the answer"); + + string answer = Console.ReadLine(); + string correctAnswer = ""; + + foreach (FlashCards flashCard in FlashCards) + { + + if (flashCard.Id == flashCardId) + { + totalReviewdPoints += 20; + correctAnswer = flashCard.Answer; + } + } + + if (answer == correctAnswer) + { + Console.Clear(); + + Console.WriteLine("The answer you entered was correct. 20 points added !!"); + Console.WriteLine(); + + totalPoints += 20; + + FlashCardslist += $"{flashCardId},"; + + Console.WriteLine($"You Scored {totalPoints} out of {totalReviewdPoints} points"); + Console.WriteLine(); + + ViewFlashCards(StackId); + + } + else + { + Console.Clear(); + + Console.WriteLine("The answer you entered was Incorrect!!. Below is the correct answer"); + Console.WriteLine(); + + Console.WriteLine($"Answer : {correctAnswer}"); + Console.WriteLine(); + + ViewFlashCards(StackId); + } + } + + private void GetDurationPerSession() + { + TimeSpan duration = sessionEndTime.Subtract(sessionStartTime); + + durationPerSession = duration.Minutes; + } + } +} diff --git a/FlashCards.Review/FlashCardLearning.sln b/FlashCards.Review/FlashCardLearning.sln new file mode 100644 index 00000000..8f54580d --- /dev/null +++ b/FlashCards.Review/FlashCardLearning.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35818.85 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlashCardLearning", "FlashCardLearning.csproj", "{5F4A8261-6C28-B41A-79DC-4896337F85ED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5F4A8261-6C28-B41A-79DC-4896337F85ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F4A8261-6C28-B41A-79DC-4896337F85ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F4A8261-6C28-B41A-79DC-4896337F85ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F4A8261-6C28-B41A-79DC-4896337F85ED}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E4095846-3E33-4066-88AF-996F9FA43AF7} + EndGlobalSection +EndGlobal