diff --git a/Management.Test/Markdown/QuizMarkdownTests.cs b/Management.Test/Markdown/QuizMarkdownTests.cs index 9c745c3..d0336f8 100644 --- a/Management.Test/Markdown/QuizMarkdownTests.cs +++ b/Management.Test/Markdown/QuizMarkdownTests.cs @@ -209,6 +209,7 @@ b) false var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz); var firstQuestion = quiz.Questions.First(); + firstQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_CHOICE); firstQuestion.Points.Should().Be(2); firstQuestion.Text.Should().Contain("```"); firstQuestion.Text.Should().Contain("`some type` of question"); @@ -217,4 +218,75 @@ b) false firstQuestion.Answers.ElementAt(1).Correct.Should().BeFalse(); firstQuestion.Answers.ElementAt(1).Text.Should().Contain("endline"); } + + [Test] + public void CanParseQuestionWithMultipleAnswers() + { + var rawMarkdownQuiz = @" +Name: Test Quiz +LockAtDueDate: true +ShuffleAnswers: true +OneQuestionAtATime: false +DueAt: 2023-08-21T23:59:00 +LockAt: 2023-08-21T23:59:00 +AssignmentGroup: Assignments +AllowedAttempts: -1 +Description: this is the +multi line +description +--- +Which events are triggered when the user clicks on an input field? +[*] click +[*] focus +[*] mousedown +[] submit +[] change +[] mouseout +[] keydown +--- +"; + + var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz); + var firstQuestion = quiz.Questions.First(); + firstQuestion.Points.Should().Be(1); + firstQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_ANSWERS); + firstQuestion.Text.Should().Contain("Which events are triggered when the user clicks on an input field?"); + firstQuestion.Answers.First().Text.Should().Be("click"); + firstQuestion.Answers.First().Correct.Should().BeTrue(); + firstQuestion.Answers.ElementAt(3).Correct.Should().BeFalse(); + firstQuestion.Answers.ElementAt(3).Text.Should().Be("submit"); + } + [Test] + public void CanParseMultipleQuestions() + { + var rawMarkdownQuiz = @" +Name: Test Quiz +LockAtDueDate: true +ShuffleAnswers: true +OneQuestionAtATime: false +DueAt: 2023-08-21T23:59:00 +LockAt: 2023-08-21T23:59:00 +AssignmentGroup: Assignments +AllowedAttempts: -1 +Description: this is the +multi line +description +--- +Which events are triggered when the user clicks on an input field? +[*] click +--- +points: 2 +`some type` of question +*a) true +b) false +"; + + var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz); + var firstQuestion = quiz.Questions.First(); + firstQuestion.Points.Should().Be(1); + firstQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_ANSWERS); + var secondQuestion = quiz.Questions.ElementAt(1); + secondQuestion.Points.Should().Be(2); + secondQuestion.QuestionType.Should().Be(QuestionType.MULTIPLE_CHOICE); + } } \ No newline at end of file diff --git a/Management/Models/Local/LocalQuizQuestion.cs b/Management/Models/Local/LocalQuizQuestion.cs index f597351..ef7eb7c 100644 --- a/Management/Models/Local/LocalQuizQuestion.cs +++ b/Management/Models/Local/LocalQuizQuestion.cs @@ -33,9 +33,7 @@ public record LocalQuizQuestion return $@"Points: {Points} {Text} -{answersText} ---- -"; +{answersText}"; } private static readonly string[] validFirstAnswerDelimiters = new string[] { "*a)", "a)", "[ ]", "[*]" }; @@ -52,18 +50,19 @@ public record LocalQuizQuestion .ToArray(); var description = string.Join(Environment.NewLine, linesWithoutAnswers); - - LocalQuizQuestionAnswer[] answers = getAnswers(linesWithoutPoints); + + var (answers, questionType) = getAnswers(linesWithoutPoints); return new LocalQuizQuestion() { Text = description, Points = points, - Answers = answers + Answers = answers, + QuestionType = questionType }; } - private static LocalQuizQuestionAnswer[] getAnswers(string[] linesWithoutPoints) + private static (LocalQuizQuestionAnswer[], string questionType) getAnswers(string[] linesWithoutPoints) { var indexOfAnswerStart = linesWithoutPoints .ToList() @@ -96,7 +95,22 @@ public record LocalQuizQuestion }); var answers = answerLines.Select(LocalQuizQuestionAnswer.ParseMarkdown).ToArray(); - return answers; + + var isMultipleChoice = + answerLines.First().StartsWith("a)") + || answerLines.First().StartsWith("*a)"); + + var isMultipleAnswer = + answerLines.First().StartsWith("[ ]") + || answerLines.First().StartsWith("[*]"); + + var questionType = isMultipleChoice + ? "multiple_choice" + : isMultipleAnswer + ? "multiple_answers" + : ""; + + return (answers, questionType); } } diff --git a/Management/Services/YamlManager.cs b/Management/Services/YamlManager.cs index a4a30b7..cf97663 100644 --- a/Management/Services/YamlManager.cs +++ b/Management/Services/YamlManager.cs @@ -29,36 +29,36 @@ public class YamlManager if (!Directory.Exists(courseDirectory)) Directory.CreateDirectory(courseDirectory); - await SaveModules(course); + await saveModules(course); await File.WriteAllTextAsync($"../storage/{course.Settings.Name}.yml", courseString); } - public async Task SaveModules(LocalCourse course) + private static async Task saveModules(LocalCourse course) { var courseDirectory = $"../storage/{course.Settings.Name}"; - await SaveSettings(course, courseDirectory); + await saveSettings(course, courseDirectory); foreach (var module in course.Modules) { var moduleDirectory = courseDirectory + "/" + module.Name; if (!Directory.Exists(moduleDirectory)) Directory.CreateDirectory(moduleDirectory); - await SaveQuizzes(course, module); - await SaveAssignments(course, module); + await saveQuizzes(course, module); + await saveAssignments(course, module); } } - public async Task SaveSettings(LocalCourse course, string courseDirectory) + private static async Task saveSettings(LocalCourse course, string courseDirectory) { var settingsFilePath = courseDirectory + "/settings.yml"; ; var settingsYaml = course.Settings.ToYaml(); await File.WriteAllTextAsync(settingsFilePath, settingsYaml); } - public async Task SaveQuizzes(LocalCourse course, LocalModule module) + private static async Task saveQuizzes(LocalCourse course, LocalModule module) { var quizzesDirectory = $"../storage/{course.Settings.Name}/{module.Name}/quizzes"; if (!Directory.Exists(quizzesDirectory)) @@ -69,10 +69,14 @@ public class YamlManager var filePath = quizzesDirectory + "/" + quiz.Name + ".yml"; ; var quizYaml = quiz.ToYaml(); await File.WriteAllTextAsync(filePath, quizYaml); + + var markdownPath = quizzesDirectory + "/" + quiz.Name + ".md"; ; + var quizMarkdown = quiz.ToMarkdown(); + await File.WriteAllTextAsync(markdownPath, quizMarkdown); } } - public async Task SaveAssignments(LocalCourse course, LocalModule module) + private static async Task saveAssignments(LocalCourse course, LocalModule module) { var assignmentsDirectory = $"../storage/{course.Settings.Name}/{module.Name}/assignments"; if (!Directory.Exists(assignmentsDirectory))