mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 15:18:32 -06:00
158 lines
5.0 KiB
C#
158 lines
5.0 KiB
C#
using System.Text.RegularExpressions;
|
|
using YamlDotNet.Serialization;
|
|
|
|
namespace LocalModels;
|
|
|
|
public record LocalQuiz
|
|
{
|
|
public required string Name { get; init; }
|
|
public required string Description { get; init; }
|
|
public DateTime? LockAt { get; init; }
|
|
public DateTime DueAt { get; init; }
|
|
public bool ShuffleAnswers { get; init; } = true;
|
|
public bool OneQuestionAtATime { get; init; } = false;
|
|
public string? LocalAssignmentGroupName { get; init; }
|
|
public int AllowedAttempts { get; init; } = -1; // -1 is infinite
|
|
// public bool ShowCorrectAnswers { get; init; }
|
|
// public int? TimeLimit { get; init; } = null;
|
|
// public string? HideResults { get; init; } = null;
|
|
// If null, students can see their results after any attempt.
|
|
// If “always”, students can never see their results.
|
|
// If “until_after_last_attempt”, students can only see results after their last attempt. (Only valid if allowed_attempts > 1). Defaults to null.
|
|
public IEnumerable<LocalQuizQuestion> Questions { get; init; } =
|
|
Enumerable.Empty<LocalQuizQuestion>();
|
|
public ulong? GetCanvasAssignmentGroupId(IEnumerable<LocalAssignmentGroup> assignmentGroups) =>
|
|
assignmentGroups
|
|
.FirstOrDefault(g => g.Name == LocalAssignmentGroupName)?
|
|
.CanvasId;
|
|
|
|
public string GetDescriptionHtml() => Markdig.Markdown.ToHtml(Description);
|
|
|
|
public string ToYaml()
|
|
{
|
|
var serializer = new SerializerBuilder().DisableAliases().Build();
|
|
var yaml = serializer.Serialize(this);
|
|
return yaml;
|
|
}
|
|
|
|
public string ToMarkdown()
|
|
{
|
|
var questionMarkdownArray = Questions.Select(q => q.ToMarkdown()).ToArray();
|
|
var questionDelimiter = "\n\n---\n\n";
|
|
var questionMarkdown = string.Join(questionDelimiter, questionMarkdownArray);
|
|
|
|
return $@"Name: {Name}
|
|
LockAt: {LockAt}
|
|
DueAt: {DueAt}
|
|
ShuffleAnswers: {ShuffleAnswers.ToString().ToLower()}
|
|
OneQuestionAtATime: {OneQuestionAtATime.ToString().ToLower()}
|
|
AssignmentGroup: {LocalAssignmentGroupName}
|
|
AllowedAttempts: {AllowedAttempts}
|
|
Description: {Description}
|
|
---
|
|
{questionMarkdown}
|
|
";
|
|
}
|
|
|
|
public static LocalQuiz ParseMarkdown(string input)
|
|
{
|
|
|
|
var splitInput = input.Split("---\n");
|
|
var settings = splitInput[0];
|
|
var quizWithoutQuestions = getQuizWithOnlySettings(settings);
|
|
|
|
var questions = splitInput[1..]
|
|
.Where(str => !string.IsNullOrWhiteSpace(str))
|
|
.Select((q, i) => LocalQuizQuestion.ParseMarkdown(q, i))
|
|
.ToArray();
|
|
return quizWithoutQuestions with
|
|
{
|
|
Questions = questions
|
|
};
|
|
}
|
|
|
|
private static LocalQuiz getQuizWithOnlySettings(string settings)
|
|
{
|
|
|
|
var name = extractLabelValue(settings, "Name");
|
|
|
|
var rawShuffleAnswers = extractLabelValue(settings, "ShuffleAnswers");
|
|
var shuffleAnswers = bool.TryParse(rawShuffleAnswers, out bool parsedShuffleAnswers)
|
|
? parsedShuffleAnswers
|
|
: throw new QuizMarkdownParseException($"Error with ShuffleAnswers: {rawShuffleAnswers}");
|
|
|
|
|
|
var rawOneQuestionAtATime = extractLabelValue(settings, "OneQuestionAtATime");
|
|
var oneQuestionAtATime = bool.TryParse(rawOneQuestionAtATime, out bool parsedOneQuestion)
|
|
? parsedOneQuestion
|
|
: throw new QuizMarkdownParseException($"Error with oneQuestionAtATime: {rawOneQuestionAtATime}");
|
|
|
|
var rawAllowedAttempts = extractLabelValue(settings, "AllowedAttempts");
|
|
var allowedAttempts = int.TryParse(rawAllowedAttempts, out int parsedAllowedAttempts)
|
|
? parsedAllowedAttempts
|
|
: throw new QuizMarkdownParseException($"Error with AllowedAttempts: {rawAllowedAttempts}");
|
|
|
|
|
|
var rawDueAt = extractLabelValue(settings, "DueAt");
|
|
var dueAt = DateTime.TryParse(rawDueAt, out DateTime parsedDueAt)
|
|
? parsedDueAt
|
|
: throw new QuizMarkdownParseException($"Error with DueAt: {rawDueAt}");
|
|
|
|
|
|
var rawLockAt = extractLabelValue(settings, "LockAt");
|
|
DateTime? lockAt = DateTime.TryParse(rawLockAt, out DateTime parsedLockAt)
|
|
? parsedLockAt
|
|
: null;
|
|
|
|
|
|
var description = extractDescription(settings);
|
|
var assignmentGroup = extractLabelValue(settings, "AssignmentGroup");
|
|
|
|
return new LocalQuiz()
|
|
{
|
|
Name = name,
|
|
Description = description,
|
|
LockAt = lockAt,
|
|
DueAt = dueAt,
|
|
ShuffleAnswers = shuffleAnswers,
|
|
OneQuestionAtATime = oneQuestionAtATime,
|
|
LocalAssignmentGroupName = assignmentGroup,
|
|
AllowedAttempts = allowedAttempts,
|
|
Questions = new LocalQuizQuestion[] { }
|
|
};
|
|
}
|
|
|
|
static string extractLabelValue(string input, string label)
|
|
{
|
|
string pattern = $@"{label}: (.*?)\n";
|
|
Match match = Regex.Match(input, pattern);
|
|
|
|
if (match.Success)
|
|
{
|
|
return match.Groups[1].Value;
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
static string extractDescription(string input)
|
|
{
|
|
string pattern = "Description: (.*?)$";
|
|
Match match = Regex.Match(input, pattern, RegexOptions.Singleline);
|
|
|
|
if (match.Success)
|
|
{
|
|
return match.Groups[1].Value;
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public class QuizMarkdownParseException : Exception
|
|
{
|
|
public QuizMarkdownParseException(string message): base(message)
|
|
{
|
|
|
|
}
|
|
} |