diff --git a/README.md b/README.md new file mode 100644 index 0000000..fde4ffa --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Quiz Uygulaması + +Bu uygulama, kullanıcıların çeşitli sınav kitapçıklarından soruları çözebilecekleri ve cevap anahtarlarını görüntüleyebilecekleri bir konsol uygulamasıdır. + +## Uygulamanın Akışı +1. Kullanıcılar, JSON formatında örnek veri girerek soru verilerini uygulamaya aktarır. + +2. Uygulama, girilen verileri kullanarak farklı zorluk seviyelerinde kitapçıklar oluşturur. +3. Oluşturulan kitapçıklar, içerdikleri soruları ve seçenekleri karışık bir şekilde düzenler. +4.Kullanıcılar, oluşturulan kitapçıkları dışa aktarabilir veya quiz moduna geçerek soruları çözebilirler. + +## Nasıl Kullanılır + +1. Uygulamayı çalıştırın (`quiz-console-app.exe` veya Visual Studio'da F5 tuşuna basarak). +2. Uygulama başlatıldığında, mevcut kitapçıklar listelenecek ve kullanıcı bir kitapçık seçmek için talimatlar alacak. +3. Kitapçık seçildikten sonra, kullanıcı soruları çözebilir. +4. Soruları çözdükten sonra, kullanıcı cevap anahtarlarını görüntüleyebilir. + +## Özellikler + +- Kullanıcı dostu arayüz +- Farklı zorluk seviyelerine sahip sorular +- Soruların ve cevap anahtarlarının XML ve JSON olarak dışa aktarılması +- XML verilerinin XSLT ile biçimlendirilerek tarayıcıda görüntülenmesi +- Hata işleme ve güvenilirlik + +## Kullanılan Teknolojiler + +- C# +- .NET Framework +- JSON.NET kütüphanesi + +## Kurulum + +1. Bu depoyu klonlayın: `https://github.com/ilyasBozdemir/quiz-console-app` +2. Visual Studio'da çözümü açın: `quiz-console-app.sln` +3. Uygulamayı derleyin ve çalıştırın. + +## Katkıda Bulunma + +1. Bu depoyu çatallayın (fork). +2. Yeni bir dal (branch) oluşturun: `git checkout -b new-feature` +3. Değişikliklerinizi yapın ve bunları işleyin (commit): `git commit -am 'Yeni özellik ekle'` +4. Dalınızı ana depoya gönderin (push): `git push origin yeni-ozellik` +5. Bir birleştirme isteği (pull request) gönderin. + +## Lisans + +Bu proje MIT lisansı altında lisanslanmıştır. Daha fazla bilgi için `LICENSE` dosyasına bakın. diff --git a/quiz-console-app/Exceptions/JsonLoadFailedException.cs b/quiz-console-app/Exceptions/JsonLoadFailedException.cs new file mode 100644 index 0000000..4904243 --- /dev/null +++ b/quiz-console-app/Exceptions/JsonLoadFailedException.cs @@ -0,0 +1,10 @@ +namespace quiz_console_app.Exceptions; + +public class JsonLoadFailedException : Exception +{ + public JsonLoadFailedException() : base("JSON dosyası yüklenirken bir hata oluştu.") { } + + public JsonLoadFailedException(string message) : base(message) { } + + public JsonLoadFailedException(string message, Exception innerException) : base(message, innerException) { } +} \ No newline at end of file diff --git a/quiz-console-app/Helpers/ConsoleColors.cs b/quiz-console-app/Helpers/ConsoleColors.cs new file mode 100644 index 0000000..93e196d --- /dev/null +++ b/quiz-console-app/Helpers/ConsoleColors.cs @@ -0,0 +1,12 @@ +namespace quiz_console_app.Helpers; +public static class ConsoleColors +{ + public static readonly ConsoleColor Default = ConsoleColor.Gray; + public static readonly ConsoleColor Error = ConsoleColor.Red; + public static readonly ConsoleColor Success = ConsoleColor.Green; + public static readonly ConsoleColor Title = ConsoleColor.DarkGreen; + public static readonly ConsoleColor Info = ConsoleColor.DarkBlue; + public static readonly ConsoleColor Warning = ConsoleColor.Yellow; + public static readonly ConsoleColor Debug = ConsoleColor.Magenta; + public static readonly ConsoleColor Prompt = ConsoleColor.Cyan; +} diff --git a/quiz-console-app/Helpers/ConsoleHelper.cs b/quiz-console-app/Helpers/ConsoleHelper.cs new file mode 100644 index 0000000..8c1c28f --- /dev/null +++ b/quiz-console-app/Helpers/ConsoleHelper.cs @@ -0,0 +1,18 @@ +namespace quiz_console_app.Helpers; + +public static class ConsoleHelper +{ + public static void WriteColoredLine(object text, ConsoleColor color) + { + Console.ForegroundColor = color; + Console.WriteLine(text); + Console.ResetColor(); + } + + public static void WriteColored(object text, ConsoleColor color) + { + Console.ForegroundColor = color; + Console.Write(text); + Console.ResetColor(); + } +} diff --git a/quiz-console-app/Helpers/QuestionLoader.cs b/quiz-console-app/Helpers/QuestionLoader.cs index 143bf71..3dcd64e 100644 --- a/quiz-console-app/Helpers/QuestionLoader.cs +++ b/quiz-console-app/Helpers/QuestionLoader.cs @@ -1,15 +1,50 @@ using Newtonsoft.Json; +using quiz_console_app.Exceptions; using quiz_console_app.Models; namespace quiz_console_app.Helpers; - public class QuestionLoader { public List LoadQuestionsFromJson(string jsonFilePath) { - string fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, jsonFilePath); - string json = File.ReadAllText(fullPath); - List questions = JsonConvert.DeserializeObject>(json); - return questions; + try + { + string fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, jsonFilePath); + string json = File.ReadAllText(fullPath); + List questions = JsonConvert.DeserializeObject>(json); + return questions; + } + catch (JsonLoadFailedException ex) + { + throw new JsonLoadFailedException("JSON dosyası yüklenirken bir hata oluştu.", ex); + } + } + public async Task> LoadQuestionsFromUrl(Uri url) + { + try + { + using (HttpClient client = new HttpClient()) + { + HttpResponseMessage response = await client.GetAsync(url); + response.EnsureSuccessStatusCode(); + + string contentType = response.Content.Headers.ContentType.MediaType; + + if (contentType != "application/json") + throw new InvalidOperationException($"Beklenen JSON içeriği değil., alınan medya türü: {contentType}"); + + + if (response.IsSuccessStatusCode) + return LoadQuestionsFromJson(await response.Content.ReadAsStringAsync()); + else + throw new Exception("API'den veri alınamadı. Hata kodu: " + response.StatusCode); + + } + } + catch (Exception ex) + { + throw new Exception("Hata oluştu: " + ex.Message); + } } + } \ No newline at end of file diff --git a/quiz-console-app/Helpers/QuestionShuffler.cs b/quiz-console-app/Helpers/QuestionShuffler.cs index ec715cd..12cfff9 100644 --- a/quiz-console-app/Helpers/QuestionShuffler.cs +++ b/quiz-console-app/Helpers/QuestionShuffler.cs @@ -20,8 +20,7 @@ public static void ShuffleBookletQuestions(BookletViewModel booklet) public static List ShuffleQuestionOptions(List questions) { - Random random = new Random(); - + foreach (var question in questions) { List shuffledOptions = ShuffleOptions(question.QuestionOptions, random); @@ -31,6 +30,7 @@ public static List ShuffleQuestionOptions(List questions) return questions; } + private static List ShuffleOptions(List options, Random random) { for (int i = options.Count - 1; i > 0; i--) diff --git a/quiz-console-app/Helpers/QuizDisplay.cs b/quiz-console-app/Helpers/QuizDisplay.cs new file mode 100644 index 0000000..d1ffe89 --- /dev/null +++ b/quiz-console-app/Helpers/QuizDisplay.cs @@ -0,0 +1,59 @@ +using quiz_console_app.ViewModels; + +namespace quiz_console_app.Helpers; + +public class QuizDisplay +{ + public static void DisplayBooklets(List booklets) + { + foreach (var booklet in booklets) + { + Console.WriteLine(); + ConsoleHelper.WriteColored("Kitapçık Id: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(booklet.Id, ConsoleColors.Default); + + ConsoleHelper.WriteColored("Kitapçık Adı: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(booklet.BookletName, ConsoleColors.Default); + + foreach (var question in booklet.Questions) + DisplayQuestion(question); + + Console.WriteLine(); + } + } + + private static void DisplayQuestion(QuestionViewModel question) + { + Console.WriteLine(); + ConsoleHelper.WriteColored("Soru : ", ConsoleColors.Prompt); + ConsoleHelper.WriteColoredLine(question.AskText, ConsoleColors.Default); + + foreach (var questionOption in question.QuestionOptions) + { + Console.Write(questionOption.Text + " "); + } + Console.WriteLine(); + } + + public static void DisplayAnswerKeys(List answerKeys) + { + if (answerKeys == null || answerKeys.Count == 0) + { + ConsoleHelper.WriteColoredLine("Cevap anahtarları bulunamadı.", ConsoleColors.Error); + return; + } + + ConsoleHelper.WriteColored("Cevap Anahtarları:", ConsoleColors.Info); + foreach (var answerKey in answerKeys) + { + ConsoleHelper.WriteColored("Kitapçık Id: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(answerKey.BookletId, ConsoleColors.Default); + + ConsoleHelper.WriteColored(" Soru Id: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(answerKey.QuestionId, ConsoleColors.Default); + + ConsoleHelper.WriteColored(" Doğru Seçenek Id: ", ConsoleColors.Info); + ConsoleHelper.WriteColoredLine(answerKey.CorrectOptionId, ConsoleColors.Default); + } + } +} \ No newline at end of file diff --git a/quiz-console-app/Program.cs b/quiz-console-app/Program.cs index e81a6a1..c326c76 100644 --- a/quiz-console-app/Program.cs +++ b/quiz-console-app/Program.cs @@ -1,15 +1,15 @@ using quiz_console_app.Helpers; using quiz_console_app.Models; using quiz_console_app.Services; -using quiz_console_app.ViewModels; - -class Program -{ - static void Main(string[] args) - { - List questions = new QuestionLoader().LoadQuestionsFromJson("software_questions.json"); - List shuffledBooklets = QuizService.GenerateBooklets(questions, 2); - QuizDisplay.DisplayBooklets(shuffledBooklets); - Console.ReadLine(); - } -} + +QuizService quizService = new QuizService(); + + +List questions = new QuestionLoader().LoadQuestionsFromJson("software_questions.json"); // default path : {root-project}/bin/Debug/net8.0/software_questions.json + +quizService.GenerateBooklets(questions, 1); + +QuizDisplay.DisplayBooklets(quizService.Booklets); +QuizDisplay.DisplayAnswerKeys(quizService.AnswerKeys); + +Console.ReadLine(); \ No newline at end of file diff --git a/quiz-console-app/Services/ExportService.cs b/quiz-console-app/Services/ExportService.cs new file mode 100644 index 0000000..a2bf58b --- /dev/null +++ b/quiz-console-app/Services/ExportService.cs @@ -0,0 +1,140 @@ +using quiz_console_app.ViewModels; +using System.Xml; + +namespace quiz_console_app.Services; + +public class ExportService +{ + public void ExportToXml(List booklets, string xmlFilePath) + { + XmlDocument xmlDoc = CreateXmlDocument(booklets); + + xmlDoc.Save(xmlFilePath); + } + + public void ExportAnswerKeyToXsl(string xslFilePath) + { + string xslContent = @" + + + + + Answer Key Report + + +

Answer Key Report

+ + + +
+ + + +
+

+

Soru Id:

+

Doğru Seçenek Id:

+
+
+
+
"; + + File.WriteAllText(xslFilePath, xslContent); + } + + public void ExportAnswerKeyToXsd(string xsdFilePath) + { + string xsdContent = @" + + + + + + + + + + + + + + + + + "; + + File.WriteAllText(xsdFilePath, xsdContent); + } + + + public void ExportToXsl(string xslFilePath) + { + string xslContent = @" + + + + + Booklets Report + + +

Booklets Report

+ + + +
+ + + +
+

+ +
+
+
+
"; + + File.WriteAllText(xslFilePath, xslContent); + } + + public void ExportToXsd(string xsdFilePath) + { + string xsdContent = @" + + + + + + + + + + + + + + + + "; + + File.WriteAllText(xsdFilePath, xsdContent); + } + + + private XmlDocument CreateXmlDocument(List booklets) + { + XmlDocument xmlDoc = new XmlDocument(); + + XmlElement rootElement = xmlDoc.CreateElement("Booklets"); + xmlDoc.AppendChild(rootElement); + + // Her bir kitapçık için XML elementi oluştur ve kök elemente ekle + foreach (var booklet in booklets) + { + XmlElement bookletElement = xmlDoc.CreateElement("Booklet"); + // Kitapçık verilerini XML elementine ekleme işlemi burada yapılabilir + rootElement.AppendChild(bookletElement); + } + + return xmlDoc; + } +} diff --git a/quiz-console-app/Services/QuizDisplay.cs b/quiz-console-app/Services/QuizDisplay.cs deleted file mode 100644 index 788e2d5..0000000 --- a/quiz-console-app/Services/QuizDisplay.cs +++ /dev/null @@ -1,36 +0,0 @@ -using quiz_console_app.ViewModels; - -namespace quiz_console_app.Services; - -public class QuizDisplay -{ - public static void DisplayBooklets(List booklets) - { - foreach (var booklet in booklets) - { - Console.WriteLine(); - Console.WriteLine("Kitapçık Id: " + booklet.Id); - Console.WriteLine("Kitapçık Adı: " + booklet.BookletName); - - foreach (var question in booklet.Questions) - { - DisplayQuestion(question); - } - - Console.WriteLine(); - } - } - - private static void DisplayQuestion(QuestionViewModel question) - { - Console.WriteLine(); - Console.WriteLine("Soru :" + question.AskText); - - foreach (var questionOption in question.QuestionOptions) - { - Console.Write(questionOption.Text + " "); - } - Console.WriteLine(); - } -} - diff --git a/quiz-console-app/Services/QuizService.cs b/quiz-console-app/Services/QuizService.cs index d6eb6ce..c56c3c1 100644 --- a/quiz-console-app/Services/QuizService.cs +++ b/quiz-console-app/Services/QuizService.cs @@ -4,9 +4,19 @@ namespace quiz_console_app.Services; -public static class QuizService +public class QuizService { - public static List GenerateBooklets(List questions, int shuffleCount = 1) + public List Booklets { get; private set; } + public List AnswerKeys { get; private set; } + + + public QuizService() + { + Booklets = new List(); + AnswerKeys = new List(); + } + + public void GenerateBooklets(List questions, int shuffleCount = 1) { List shuffledQuestions = new List(); @@ -17,8 +27,6 @@ public static List GenerateBooklets(List questions, { List bookletQuestions = QuestionShuffler.ShuffleQuestionOptions(questions); - - BookletViewModel booklet = new BookletViewModel { Id = i + 1, @@ -29,11 +37,23 @@ public static List GenerateBooklets(List questions, QuestionShuffler.ShuffleBookletQuestions(booklet); booklets.Add(booklet); + } - return booklets; + Booklets = booklets; } + public void GenerateAnswerKey(List booklets) + { + List answerKeys = new List(); + + + AnswerKeys = answerKeys; + } + + + + private static QuestionViewModel MapToQuestionViewModel(Question question) { return new QuestionViewModel