From 4f9131a51eb4214a47a9349e09d252357cc2df15 Mon Sep 17 00:00:00 2001 From: ilyasBozdemir Date: Tue, 19 Mar 2024 20:28:20 +0300 Subject: [PATCH] updated --- quiz-console-app/Helpers/OptionHelper.cs | 20 +++ quiz-console-app/Helpers/QuestionLoader.cs | 33 +++- quiz-console-app/Helpers/QuizDisplay.cs | 56 +++++- .../Models/AnswerKeyCollection.cs | 31 ++++ quiz-console-app/Models/BookletQuestion.cs | 28 +++ quiz-console-app/Models/QuizResultSummary.cs | 25 +-- quiz-console-app/Models/ScoringRules.cs | 2 +- .../Models/UserAnswerKeyCollection.cs | 31 ++++ quiz-console-app/Program.cs | 5 +- .../Screens/DisplayBookletScreen.cs | 20 +-- quiz-console-app/Screens/QuizModeScreen.cs | 148 +++++++++++----- quiz-console-app/Services/QuizService.cs | 165 +++++++++++------- .../Validators/QuestionValidator.cs | 12 ++ .../ViewModels/AnswerKeyViewModel.cs | 1 + .../ViewModels/BookletViewModel.cs | 2 +- .../ViewModels/UserAnswerKeyViewModel.cs | 2 + 16 files changed, 430 insertions(+), 151 deletions(-) create mode 100644 quiz-console-app/Helpers/OptionHelper.cs create mode 100644 quiz-console-app/Models/AnswerKeyCollection.cs create mode 100644 quiz-console-app/Models/UserAnswerKeyCollection.cs create mode 100644 quiz-console-app/Validators/QuestionValidator.cs diff --git a/quiz-console-app/Helpers/OptionHelper.cs b/quiz-console-app/Helpers/OptionHelper.cs new file mode 100644 index 0000000..8645527 --- /dev/null +++ b/quiz-console-app/Helpers/OptionHelper.cs @@ -0,0 +1,20 @@ +namespace quiz_console_app.Helpers; + +public static class OptionHelper +{ + public static char ToOptionLetter(int optionId) + { + if (optionId < 0 || optionId > 25) + throw new ArgumentException("Option ID must be between 0 and 25"); + + return ((char)(65 + optionId)); + } + + public static int FromOptionLetter(char optionLetter) + { + if (!char.IsLetter(optionLetter)) + throw new ArgumentException("Input must be a letter."); + + return char.ToUpper(optionLetter) - 65; + } +} \ No newline at end of file diff --git a/quiz-console-app/Helpers/QuestionLoader.cs b/quiz-console-app/Helpers/QuestionLoader.cs index 209899c..931d2f9 100644 --- a/quiz-console-app/Helpers/QuestionLoader.cs +++ b/quiz-console-app/Helpers/QuestionLoader.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using quiz_console_app.Exceptions; using quiz_console_app.Models; namespace quiz_console_app.Helpers; @@ -17,19 +16,41 @@ public List LoadQuestionsFromJson(string jsonFilePath = null, s json = File.ReadAllText(fullPath); } if (jsonSource != null) - { json = jsonSource; - } - + if (json == null) + throw new ArgumentNullException("JSON dosyası yolu veya içeriği belirtilmemiş."); + + List questions = JsonConvert.DeserializeObject>(json); + + foreach (var question in questions) + { + if (!question.ValidateCorrectOptionCount()) + ConsoleHelper.WriteColoredLine($"{question.Id}. Soru için doğru şık sayısı geçerli değil. Sadece bir tane doğru şık olmalıdır.", ConsoleColors.Error); + + if (!question.ValidateIncorrectOptionCount()) + ConsoleHelper.WriteColoredLine($"{question.Id}. Soru için yanlış şık sayısı geçerli değil. Yanlış şık olmamalıdır.", ConsoleColors.Error); + } + + + return questions; } - catch (JsonLoadFailedException ex) + catch (JsonReaderException ex) + { + ConsoleHelper.WriteColored($"JSON formatında bir hata oluştu: {ex.Message}", ConsoleColors.Error); + return new List(); + } + catch (Exception ex) { - throw new JsonLoadFailedException("JSON dosyası yüklenirken bir hata oluştu.", ex); + ConsoleHelper.WriteColored($"JSON dosyası yüklenirken bir hata oluştu: {ex.Message}", ConsoleColors.Error); + return new List(); } + } + + public async Task> LoadQuestionsFromUrl(Uri url) { try diff --git a/quiz-console-app/Helpers/QuizDisplay.cs b/quiz-console-app/Helpers/QuizDisplay.cs index fe64373..4a6b76d 100644 --- a/quiz-console-app/Helpers/QuizDisplay.cs +++ b/quiz-console-app/Helpers/QuizDisplay.cs @@ -1,5 +1,6 @@ using quiz_console_app.Models; using quiz_console_app.ViewModels; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace quiz_console_app.Helpers; @@ -67,10 +68,61 @@ public static void DisplayAnswerKeys(List answerKeys) public static void EvaluateQuizResults(QuizResultSummary resultSummary) { Console.WriteLine(); + ConsoleHelper.WriteColoredLine($"Toplam Soru Sayısı: {resultSummary.TotalQuestions}", ConsoleColors.Info); ConsoleHelper.WriteColoredLine($"Doğru Sayısı: {resultSummary.CorrectCount}", ConsoleColors.Success); ConsoleHelper.WriteColoredLine($"Yanlış Sayısı: {resultSummary.IncorrectCount}", ConsoleColors.Error); + ConsoleHelper.WriteColoredLine($"Yanlış Cevap Cezası Durumu : {resultSummary.ScoringRules.PenaltyForIncorrectAnswer}", ConsoleColors.Info); ConsoleHelper.WriteColoredLine($"Boş Sayısı: {resultSummary.BlankCount}", ConsoleColors.Warning); - ConsoleHelper.WriteColoredLine($"Net: {resultSummary.NetCount}", ConsoleColors.Default); - ConsoleHelper.WriteColoredLine($"Başarı Yüzdesi: {resultSummary.SuccessPercentage:F2}%", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine($"Net: {resultSummary.NetCount:F2}/{resultSummary.TotalQuestions}", ConsoleColors.Default); + ConsoleHelper.WriteColoredLine($"Başarı Yüzdesi: {resultSummary.NetCount / resultSummary.TotalQuestions * 100:F2}%", ConsoleColors.Default); + Console.WriteLine(); + } + + public static void DisplaySeparator() + { + ConsoleHelper.WriteColoredLine(new string('-', 50), ConsoleColors.Default); + } + + public static void DisplayQuizAndUserData(Quiz quiz, User user) + { + ConsoleHelper.WriteColoredLine("Quiz Bilgileri: ", ConsoleColors.Title); + + ConsoleHelper.WriteColored("Oluşturan: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(quiz.Creator, ConsoleColors.Default); + + ConsoleHelper.WriteColored("Başlık: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(quiz.Title, ConsoleColors.Default); + + ConsoleHelper.WriteColored("Açıklama: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(quiz.Description, ConsoleColors.Default); + + Console.WriteLine(); + + ConsoleHelper.WriteColoredLine("Kullanıcı Bilgileri: ", ConsoleColors.Title); + + ConsoleHelper.WriteColored("Kullanıcı ID: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(user.Id, ConsoleColors.Default); + + ConsoleHelper.WriteColored("Ad Soyad : ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine($"{user.FirstName} {user.LastName}", ConsoleColors.Default); + + ConsoleHelper.WriteColored("Kullanıcı Adı : ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(user.Username, ConsoleColors.Default); + } + + public static void ClearConsole() + { + Console.Clear(); + } + + public static void DisplayUserInfo(User user) + { + ConsoleHelper.WriteColoredLine("Kullanıcı Bilgileri:", ConsoleColors.Title); + ConsoleHelper.WriteColored("ID: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine($"{user.Id}", ConsoleColors.Default); + ConsoleHelper.WriteColored("Ad: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine($"{user.FirstName} {user.LastName}", ConsoleColors.Default); + ConsoleHelper.WriteColored("Kullanıcı Adı: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine($"{user.Username}", ConsoleColors.Default); } } \ No newline at end of file diff --git a/quiz-console-app/Models/AnswerKeyCollection.cs b/quiz-console-app/Models/AnswerKeyCollection.cs new file mode 100644 index 0000000..80a097c --- /dev/null +++ b/quiz-console-app/Models/AnswerKeyCollection.cs @@ -0,0 +1,31 @@ +using quiz_console_app.ViewModels; + +namespace quiz_console_app.Models; + +public class AnswerKeyCollection +{ + private Dictionary> _answerKeysByBookletId; + + public AnswerKeyCollection() + { + _answerKeysByBookletId = new Dictionary>(); + } + + public void AddAnswerKey(int bookletId, List answerKeys) + { + _answerKeysByBookletId.Add(bookletId, answerKeys); + } + + public List GetAnswerKeys(int bookletId) + { + if (_answerKeysByBookletId.ContainsKey(bookletId)) + { + return _answerKeysByBookletId[bookletId]; + } + else + { + return new List(); + } + } +} + diff --git a/quiz-console-app/Models/BookletQuestion.cs b/quiz-console-app/Models/BookletQuestion.cs index bb879fe..cab049d 100644 --- a/quiz-console-app/Models/BookletQuestion.cs +++ b/quiz-console-app/Models/BookletQuestion.cs @@ -9,8 +9,36 @@ public class BookletQuestion public string Explanation { get; set; } public DifficultyLevel Difficulty { get; set; } public List QuestionOptions { get; set; } + public BookletQuestion() { QuestionOptions = new List(); } + + + public bool ValidateCorrectOptionCount() + { + int correctCount = QuestionOptions.Count(option => option.IsCorrect); + return correctCount == 1; + } + + public bool ValidateIncorrectOptionCount() + { + int correctCount = QuestionOptions.Count(option => option.IsCorrect); + int incorrectCount = QuestionOptions.Count(option => !option.IsCorrect); + + return ValidateIncorrectOptionCount(correctCount, incorrectCount); + } + + private bool ValidateIncorrectOptionCount(int correctCount, int incorrectCount) + { + return incorrectCount == QuestionOptions.Count - 1 && (correctCount + incorrectCount == QuestionOptions.Count); + } + + private bool ValidateCorrectOptionCount(int correctCount, int incorrectCount) + { + return correctCount == 1 && (correctCount + incorrectCount == QuestionOptions.Count); + } + + } diff --git a/quiz-console-app/Models/QuizResultSummary.cs b/quiz-console-app/Models/QuizResultSummary.cs index b66d10f..6d99dc2 100644 --- a/quiz-console-app/Models/QuizResultSummary.cs +++ b/quiz-console-app/Models/QuizResultSummary.cs @@ -1,31 +1,24 @@ namespace quiz_console_app.Models; - -// ScoringRules buna göre net hesaplaması yapılcaktır. public class QuizResultSummary { public int CorrectCount { get; set; } = 0; public int IncorrectCount { get; set; } = 0; public int BlankCount { get; set; } = 0; - public int NetCount => CorrectCount - (IncorrectCount + BlankCount); - public double SuccessPercentage => CalculateSuccessPercentage(); + public double NetCount => CalculateNetCount(); public int TotalQuestions { get; set; } = 0; - public int QuestionCurrentNumber { get; set; } = 1; - - public QuizResultSummary(int totalQuestions) + public ScoringRules ScoringRules { get; set; } + public QuizResultSummary(int totalQuestions, ScoringRules scoringRules) { - this.TotalQuestions = totalQuestions; + TotalQuestions = totalQuestions; + this.ScoringRules = scoringRules; } - private double CalculateSuccessPercentage() + private double CalculateNetCount() { - int totalQuestions = CorrectCount + IncorrectCount + BlankCount; - if (totalQuestions == 0) - { - return 0.0; - } - - return (double)CorrectCount / totalQuestions * 100; + return (ScoringRules.PenaltyForIncorrectAnswer) + ? CorrectCount - ScoringRules.IncorrectAnswerScore * IncorrectCount + : CorrectCount; } } diff --git a/quiz-console-app/Models/ScoringRules.cs b/quiz-console-app/Models/ScoringRules.cs index 201e98e..454d9fe 100644 --- a/quiz-console-app/Models/ScoringRules.cs +++ b/quiz-console-app/Models/ScoringRules.cs @@ -6,7 +6,7 @@ public class ScoringRules public double IncorrectAnswerScore => 1.0 / (NumberOfChoices - 1); // Yanlış cevap için puanlar public int BlankAnswerScore { get; set; } = 0; // Boş cevaplar için puan public int NumberOfChoices { get; set; } // Sorunun şık sayısı - public bool PenaltyForIncorrectAnswer { get; set; } // Yanlış cevaplar için varsayılan olarak ceza uygulanacak + public bool PenaltyForIncorrectAnswer { get; set; } = true; // Yanlış cevaplar için varsayılan olarak ceza uygulanacak public ScoringRules(int numberOfChoices) { NumberOfChoices = numberOfChoices; diff --git a/quiz-console-app/Models/UserAnswerKeyCollection.cs b/quiz-console-app/Models/UserAnswerKeyCollection.cs new file mode 100644 index 0000000..e749ffb --- /dev/null +++ b/quiz-console-app/Models/UserAnswerKeyCollection.cs @@ -0,0 +1,31 @@ +using quiz_console_app.ViewModels; + +namespace quiz_console_app.Models; + +public class UserAnswerKeyCollection +{ + private Dictionary> _userAnswerKeysByUserId; + + public UserAnswerKeyCollection() + { + _userAnswerKeysByUserId = new Dictionary>(); + } + + public void AddUserAnswerKey(Guid userId, List userAnswerKeys) + { + _userAnswerKeysByUserId.Add(userId, userAnswerKeys); + } + + public List GetUserAnswerKeys(Guid userId) + { + if (_userAnswerKeysByUserId.ContainsKey(userId)) + { + return _userAnswerKeysByUserId[userId]; + } + else + { + return new List(); + } + } +} + diff --git a/quiz-console-app/Program.cs b/quiz-console-app/Program.cs index 9fd3147..78bcfcd 100644 --- a/quiz-console-app/Program.cs +++ b/quiz-console-app/Program.cs @@ -1,4 +1,5 @@ -using quiz_console_app.Services; +using quiz_console_app.Helpers; +using quiz_console_app.Services; QuizModeHandlerService quizModeHandlerService = new QuizModeHandlerService(); -quizModeHandlerService.ShowMainMenu(); +quizModeHandlerService.ShowMainMenu(); \ No newline at end of file diff --git a/quiz-console-app/Screens/DisplayBookletScreen.cs b/quiz-console-app/Screens/DisplayBookletScreen.cs index fccb2a8..5ddd66b 100644 --- a/quiz-console-app/Screens/DisplayBookletScreen.cs +++ b/quiz-console-app/Screens/DisplayBookletScreen.cs @@ -1,25 +1,11 @@ -using quiz_console_app.Helpers; -using quiz_console_app.Models; -using quiz_console_app.Services; -using quiz_console_app.ViewModels; - -namespace quiz_console_app.Screens; +namespace quiz_console_app.Screens; public class DisplayBookletScreen { - private readonly QuizService _quizService; - private readonly QuestionLoader _questionLoader; - private readonly List _questions; - private readonly List _userAnswers; - private readonly List _answerKeys; + public DisplayBookletScreen() { - _questionLoader = new QuestionLoader(); - _questions = _questionLoader.LoadQuestionsFromJson(jsonFilePath: "software_questions.json"); - _quizService = new QuizService(); - _quizService.GenerateBooklets(_questions, 1); - _userAnswers = new List(); - _answerKeys = QuizService.AnswerKeys; + } public void Start() diff --git a/quiz-console-app/Screens/QuizModeScreen.cs b/quiz-console-app/Screens/QuizModeScreen.cs index 16ff61b..b8c96b8 100644 --- a/quiz-console-app/Screens/QuizModeScreen.cs +++ b/quiz-console-app/Screens/QuizModeScreen.cs @@ -8,69 +8,100 @@ namespace quiz_console_app.Screens; public class QuizModeScreen { private readonly QuizService _quizService; - private readonly QuestionLoader _questionLoader; - private readonly List _questions; - private readonly List _userAnswers; - private readonly List _answerKeys; + private readonly AnswerKeyCollection _answerKeys; private readonly List _users; + private List _userAnswers; private User _user; private UserQuiz _userQuiz; - private Quiz _quiz; private DateTime _quizEndTime; private DateTime _quizStartTime; private TimeSpan _quizDuration; private Timer _timer; + public QuizModeScreen() { - _questionLoader = new QuestionLoader(); - _questions = _questionLoader.LoadQuestionsFromJson(jsonFilePath: "software_questions.json"); _quizService = new QuizService(); - _quizService.GenerateBooklets(_questions, 1); + _quizService.GenerateBooklets(); _userAnswers = new List(); _answerKeys = QuizService.AnswerKeys; _quiz = new Quiz(options => { - options.DurationInMinutes = 20; - options.IsOpenToPublic = true; + options.DurationInMinutes = 20; + options.IsOpenToPublic = true; }); _quizStartTime = DateTime.Now; _quizDuration = TimeSpan.FromMinutes(_quiz.DurationInMinutes); _quizEndTime = _quizStartTime.Add(_quizDuration); _timer = new Timer(EndQuiz, null, _quizDuration, TimeSpan.Zero); - _users= new List(); + _users = new List(); } - public void StartQuiz() + private User GetUserFromConsoleInput() { - - _quiz.Title = "Yazılım Bilgisi Quiz'i"; - _quiz.Description = "Bu quiz, yazılım geliştirmeyle ilgili genel bilginizi test etmek için hazırlanmıştır. Programlama dillerinden, algoritmik düşünceye kadar birçok konuyu içerebilir."; - _quiz.Creator = "@QuizConsoleApp"; - - - ConsoleHelper.WriteColored(" Soru Id: ", ConsoleColors.Info); - Console.Write("Lütfen isminizi ve soyisminizi aralarında boşluk bırakarak girin:"); + ConsoleHelper.WriteColored( + "Lütfen isminizi ve soyisminizi aralarında boşluk bırakarak girin: ", + ConsoleColors.Info + ); string fullName = Console.ReadLine(); - string[] nameParts = fullName.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + string[] nameParts = fullName.Split( + new char[] { ' ' }, + StringSplitOptions.RemoveEmptyEntries + ); string firstName = nameParts.Length > 0 ? nameParts[0] : null; string lastName = nameParts.Length > 1 ? nameParts[1] : null; - // Kullanıcı adını al - Console.Write("Lütfen kullanıcı adınızı girin:"); + ConsoleHelper.WriteColored("Lütfen kullanıcı adınızı girin: ", ConsoleColors.Info); string username = Console.ReadLine(); Console.ResetColor(); - _user = _users.FirstOrDefault(u => u.Username == username); + User user = _users.FirstOrDefault(u => u.Username == username); + + if (user == null) + { + user = new User(firstName, lastName, username); + user.Id = Guid.NewGuid(); + _users.Add(user); + } + + return user; + } + private void CheckAndSetUser() + { if (_user == null) + _user = GetUserFromConsoleInput(); + else { - _user = new User(firstName, lastName, username); - _users.Add(_user); + QuizDisplay.DisplayUserInfo(_user); + QuizDisplay.DisplaySeparator(); + ConsoleHelper.WriteColored( + "Varolan bir kullanıcı bulundu. Yeniden giriş yapmak ister misiniz? (E/H): ", + ConsoleColors.Info + ); + string input = Console.ReadLine().ToUpper(); + if (input == "E") + _user = GetUserFromConsoleInput(); } + } + + public void StartQuiz() + { + var Booklet = QuizService.Booklets.FirstOrDefault(); + int questionNumber = 1; + int userBookletId = 1; + Booklet.Id = userBookletId; + + _quiz.Title = "Yazılım Bilgisi Quiz'i"; + _quiz.Description = "Bu quiz, yazılım geliştirmeyle ilgili genel bilginizi test etmek için hazırlanmıştır. "; + _quiz.Creator = "@QuizConsoleApp"; + + _quiz.ScoringRules = new ScoringRules(Booklet.Questions[0].QuestionOptions.Count); + + CheckAndSetUser(); _userQuiz = new UserQuiz { @@ -83,9 +114,6 @@ public void StartQuiz() _userQuiz.StartTime = _userQuiz.StartTime.Add(_quizDuration); - // - var Booklet = QuizService.Booklets.FirstOrDefault(); - int questionNumber = 1; foreach (var question in Booklet.Questions) { ConsoleHelper.WriteColoredLine($"{questionNumber}. Soru: ", ConsoleColors.Info); @@ -93,9 +121,10 @@ public void StartQuiz() for (int i = 0; i < question.QuestionOptions.Count; i++) { - char optionLetter = (char)(65 + i); + char optionLetter = OptionHelper.ToOptionLetter(i); ConsoleHelper.WriteColored($"{optionLetter})", ConsoleColors.Info); + ConsoleHelper.WriteColored( $"{question.QuestionOptions[i].Text} ", ConsoleColors.Default @@ -109,35 +138,44 @@ public void StartQuiz() ConsoleHelper.WriteColoredLine(question.AskText, ConsoleColors.Default); Console.ResetColor(); Console.WriteLine(); + if ( userAnswerFromReadLine.Length == 1 - && userAnswerFromReadLine[0] >= (char)65 - && userAnswerFromReadLine[0] <= (char)(65 + question.QuestionOptions.Count - 1) + && userAnswerFromReadLine[0] >= OptionHelper.ToOptionLetter(0) + && userAnswerFromReadLine[0] <= OptionHelper.ToOptionLetter(question.QuestionOptions.Count - 1) ) { + + var optionChar = userAnswerFromReadLine[0]; + var id = OptionHelper.FromOptionLetter(optionChar); + _userAnswers.Add( new UserAnswerKeyViewModel { BookletId = Booklet.Id, QuestionId = question.Id, - UserAnswerOption = userAnswerFromReadLine + Id = question.Id, + UserAnswerOption = userAnswerFromReadLine, + UserAnswerOptionText= question.QuestionOptions[id].Text, + UserAnswerOptionId = OptionHelper.FromOptionLetter(optionChar) } ); questionNumber++; - Console.Clear(); + QuizDisplay.ClearConsole(); } - else if (userAnswerFromReadLine.Length == 0) // cevap null ise + else if (userAnswerFromReadLine.Length == 0) { _userAnswers.Add( new UserAnswerKeyViewModel { BookletId = Booklet.Id, QuestionId = question.Id, - UserAnswerOption = null + UserAnswerOption = null, + Id = question.Id, } ); questionNumber++; - Console.Clear(); + QuizDisplay.ClearConsole(); } else { @@ -165,18 +203,42 @@ public void StartQuiz() _userQuiz.IsCompleted = true; _user.UserQuizzes.Add(_userQuiz); - _quizService.EvaluateQuizResults(_userAnswers); + QuizDisplay.ClearConsole(); + + QuizDisplay.DisplayQuizAndUserData(_quiz, _user); + + QuizDisplay.DisplaySeparator(); + _quizService.EvaluateQuizResults(_userAnswers, userBookletId, _quiz.ScoringRules); + + if (AskForQuizRetry()) + { + QuizDisplay.ClearConsole(); + RetryQuiz(); + } } + public bool AskForQuizRetry() + { + Console.WriteLine(); + Console.Write("Testi tekrar çözmek ister misiniz? (E/H): "); + string input = Console.ReadLine().Trim().ToUpper(); + + while (input != "E" && input != "H") + { + Console.Write("Geçersiz giriş. Lütfen sadece 'E' veya 'H' girin: "); + input = Console.ReadLine().Trim().ToUpper(); + } + + return input == "E"; + } public void EndQuiz(object state) { if (DateTime.Now >= _quizEndTime) - _timer.Dispose(); + _timer?.Dispose(); } - public void RetryQuiz() { _quiz.ConfigureQuiz(options => @@ -192,8 +254,8 @@ public void RetryQuiz() _timer = new Timer(EndQuiz, null, _quizDuration, TimeSpan.Zero); - + _userAnswers = new List(); + StartQuiz(); } - -} \ No newline at end of file +} diff --git a/quiz-console-app/Services/QuizService.cs b/quiz-console-app/Services/QuizService.cs index 4666574..8fb7544 100644 --- a/quiz-console-app/Services/QuizService.cs +++ b/quiz-console-app/Services/QuizService.cs @@ -7,114 +7,151 @@ namespace quiz_console_app.Services; public class QuizService { public static List Booklets { get; private set; } - public static List AnswerKeys { get; private set; } - public static List Questions { get; private set; } - private int maxShuffleCount = 10; + public static AnswerKeyCollection AnswerKeys { get; private set; } + + private readonly QuestionLoader _questionLoader; + private readonly List _sourceQuestions; + public QuizService() { + _questionLoader = new QuestionLoader(); + _sourceQuestions = _questionLoader.LoadQuestionsFromJson(jsonFilePath: "software_questions.json"); Booklets = new List(); - AnswerKeys = new List(); + AnswerKeys = new AnswerKeyCollection(); } - public void GenerateBooklets(List questions, int shuffleCount = 1) - { - - shuffleCount = Math.Min(shuffleCount, maxShuffleCount); - if (shuffleCount > maxShuffleCount) - ConsoleHelper.WriteColoredLine($"İzin verilen toplam kitapçık sayısı {maxShuffleCount}", ConsoleColors.Warning); - - Questions = questions; + public void GenerateBooklets(int shuffleCount = 1) + { List shuffledQuestions = new List(); - List booklets = new List(); - for (int i = 0; i < shuffleCount; i++) { char prefix = (char)(65 + i); - string bookletName = $"{prefix}_{1}"; + string bookletName = $"{prefix}_{1}"; - List bookletQuestions = QuestionShuffler.ShuffleQuestionOptions(questions); + List bookletQuestions = QuestionShuffler.ShuffleQuestionOptions(_sourceQuestions); BookletViewModel booklet = new BookletViewModel { Id = i + 1, BookletName = $"Booklet {i + 1}", Questions = bookletQuestions.Select(q => MapToQuestionViewModel(q)).ToList(), - Prefix = bookletName + Prefix = bookletName, + }; QuestionShuffler.ShuffleBookletQuestions(booklet); + GenerateAnswerKeys(booklet); booklets.Add(booklet); } Booklets = booklets; + } - public List GenerateAnswerKeys() + + public void GenerateAnswerKeys(BookletViewModel booklet) { - List answerKeys = new List(); + List questionAnswerKeys = new List(); - foreach (var question in Questions) + foreach (var question in booklet.Questions) { - var correctOption = question.QuestionOptions.FirstOrDefault(option => option.IsCorrect); - - if (correctOption != null) + foreach (var option in question.QuestionOptions) { - answerKeys.Add(new AnswerKeyViewModel + if (option.IsCorrect) { - BookletId = 1, - QuestionId = question.Id, - CorrectOptionText = correctOption.Text - }); + AnswerKeyViewModel answerKey = new AnswerKeyViewModel + { + BookletId = booklet.Id, + QuestionId = question.Id, + CorrectOptionText = option.Text + }; + questionAnswerKeys.Add(answerKey); + } } } - return answerKeys; + AnswerKeys.AddAnswerKey(booklet.Id, questionAnswerKeys); } - public void EvaluateQuizResults(List userAnswers) + + + + + public void EvaluateQuizResults(List userAnswers, int userBookletId, ScoringRules scoringRules) { - QuizResultSummary resultSummary = new QuizResultSummary(userAnswers.Count); + bool allAnswersInSameBooklet = true; + for (int i = 0; i < userAnswers.Count; i++) - ConsoleHelper.WriteColoredLine($"Cevaplar", ConsoleColors.Title); - foreach (var userAnswer in userAnswers) - { - string formattedQuestionNumber = FormattingHelper.FormatQuestionNumber(resultSummary.QuestionCurrentNumber, resultSummary.TotalQuestions); - ConsoleHelper.WriteColored($"{formattedQuestionNumber})", ConsoleColors.Default); - - if (string.IsNullOrEmpty(userAnswer.UserAnswerOption)) + if (userAnswers[i].BookletId != userBookletId) { - resultSummary.BlankCount++; - ConsoleHelper.WriteColored(" - Boş", ConsoleColors.Warning); + allAnswersInSameBooklet = false; + break; } - else - { - var correspondingQuestion = Booklets - .SelectMany(booklet => booklet.Questions) - .FirstOrDefault(question => question.Id == userAnswer.QuestionId); - if (correspondingQuestion != null) - { - var correctOption = correspondingQuestion.QuestionOptions - .FirstOrDefault(option => option.IsCorrect && option.Text == userAnswer.UserAnswerOption); + QuizResultSummary resultSummary = new QuizResultSummary(userAnswers.Count, scoringRules); - if (correctOption != null) - { - ConsoleHelper.WriteColored($"{userAnswer.UserAnswerOption} ", ConsoleColors.Info); - ConsoleHelper.WriteColored(" - Doğru", ConsoleColors.Success); - resultSummary.CorrectCount++; - } - else + List answerKeys = AnswerKeys.GetAnswerKeys(userBookletId); + + + if (allAnswersInSameBooklet) + { + ConsoleHelper.WriteColoredLine($"Cevaplar", ConsoleColors.Title); + + for (int i = 0; i < answerKeys.Count; i++) + { + for (int j = 0; j < userAnswers.Count; j++) + { + if (i == j) { - ConsoleHelper.WriteColored($"{userAnswer.UserAnswerOption} ", ConsoleColors.Info); - ConsoleHelper.WriteColored(" - Yanlış", ConsoleColors.Error); - resultSummary.IncorrectCount++; + string formattedQuestionNumber = + FormattingHelper + .FormatQuestionNumber(resultSummary.QuestionCurrentNumber, resultSummary.TotalQuestions); + + ConsoleHelper.WriteColored($"{formattedQuestionNumber})", ConsoleColors.Default); + + if (string.IsNullOrEmpty(userAnswers[i].UserAnswerOption)) + { + resultSummary.BlankCount++; + ConsoleHelper.WriteColored(" - Boş", ConsoleColors.Warning); + Console.WriteLine(); + } + else + { + var correspondingQuestion = Booklets + .SelectMany(booklet => booklet.Questions) + .FirstOrDefault(question => question.Id == userAnswers[j].QuestionId); + + if (correspondingQuestion != null) + { + var correctOption = correspondingQuestion + .QuestionOptions + .FirstOrDefault(option => option.IsCorrect); + + if (answerKeys[i].CorrectOptionText == userAnswers[j].UserAnswerOptionText) + { + ConsoleHelper.WriteColored($"{OptionHelper.ToOptionLetter(userAnswers[j].UserAnswerOptionId)} - Doğru", ConsoleColors.Success); + resultSummary.CorrectCount++; + Console.WriteLine(); + } + else + { + ConsoleHelper.WriteColored($"{OptionHelper.ToOptionLetter(userAnswers[j].UserAnswerOptionId)} - Yanlış", ConsoleColors.Error); + resultSummary.IncorrectCount++; + Console.WriteLine(); + } + + } + } + resultSummary.QuestionCurrentNumber++; } } } - Console.WriteLine(); - resultSummary.QuestionCurrentNumber++; } + else + ConsoleHelper.WriteColoredLine($"Hata: Beklenen kitapçık ID bulunamadı. Beklenen ID: {userBookletId}", ConsoleColors.Error); + QuizDisplay.EvaluateQuizResults(resultSummary); } + private static QuestionViewModel MapToQuestionViewModel(BookletQuestion question) { return new QuestionViewModel @@ -124,7 +161,8 @@ private static QuestionViewModel MapToQuestionViewModel(BookletQuestion question Explanation = question.Explanation, Difficulty = question.Difficulty, QuestionOptions = question.QuestionOptions - .Select(o => MapToQuestionOptionViewModel(o)).ToList() + .Select(o => MapToQuestionOptionViewModel(o)).ToList(), + }; } private static QuestionOptionViewModel MapToQuestionOptionViewModel(BookletQuestionOption option) @@ -132,7 +170,8 @@ private static QuestionOptionViewModel MapToQuestionOptionViewModel(BookletQuest return new QuestionOptionViewModel { Id = option.Id, - Text = option.Text + Text = option.Text, + IsCorrect = option.IsCorrect, }; } } diff --git a/quiz-console-app/Validators/QuestionValidator.cs b/quiz-console-app/Validators/QuestionValidator.cs new file mode 100644 index 0000000..e6c37e7 --- /dev/null +++ b/quiz-console-app/Validators/QuestionValidator.cs @@ -0,0 +1,12 @@ +using quiz_console_app.Models; + +namespace quiz_console_app.Validators; + +public static class QuestionValidator +{ + public static bool ValidateQuestionOptions(List options) + { + int correctCount = options.Count(option => option.IsCorrect); + return correctCount == 1 && correctCount + 1 == options.Count; + } +} diff --git a/quiz-console-app/ViewModels/AnswerKeyViewModel.cs b/quiz-console-app/ViewModels/AnswerKeyViewModel.cs index 7a5d8db..a1df74d 100644 --- a/quiz-console-app/ViewModels/AnswerKeyViewModel.cs +++ b/quiz-console-app/ViewModels/AnswerKeyViewModel.cs @@ -5,5 +5,6 @@ public class AnswerKeyViewModel public int Id { get; set; } public int BookletId { get; set; } public int QuestionId { get; set; } + public int CorrectOptionId { get; set; } public string CorrectOptionText { get; set; } } diff --git a/quiz-console-app/ViewModels/BookletViewModel.cs b/quiz-console-app/ViewModels/BookletViewModel.cs index 1fd88d3..31e5000 100644 --- a/quiz-console-app/ViewModels/BookletViewModel.cs +++ b/quiz-console-app/ViewModels/BookletViewModel.cs @@ -6,4 +6,4 @@ public class BookletViewModel public string BookletName { get; set; } public string Prefix { get; set; } public List Questions { get; set; } -} +} \ No newline at end of file diff --git a/quiz-console-app/ViewModels/UserAnswerKeyViewModel.cs b/quiz-console-app/ViewModels/UserAnswerKeyViewModel.cs index 7499c06..a465a3f 100644 --- a/quiz-console-app/ViewModels/UserAnswerKeyViewModel.cs +++ b/quiz-console-app/ViewModels/UserAnswerKeyViewModel.cs @@ -6,4 +6,6 @@ public class UserAnswerKeyViewModel public int BookletId { get; set; } public int QuestionId { get; set; } public string UserAnswerOption { get; set; } + public string UserAnswerOptionText { get; set; } + public int UserAnswerOptionId { get; set; } }