mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
can convert to and from markdown for assignment
This commit is contained in:
@@ -9,7 +9,104 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
Name="test assignment",
|
Name="test assignment",
|
||||||
Description ="here is the description",
|
Description ="here is the description",
|
||||||
// LockAtDueDate = false
|
DueAt = new DateTime(),
|
||||||
|
LockAt = new DateTime(),
|
||||||
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
|
LocalAssignmentGroupName = "Final Project",
|
||||||
|
Rubric = new List<RubricItem>() {
|
||||||
|
new RubricItem() {Points = 4, Label="do task 1"},
|
||||||
|
new RubricItem() {Points = 2, Label="do task 2"},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
||||||
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void AssignmentWithEmptyRubric_CanBeParsed()
|
||||||
|
{
|
||||||
|
var assignment = new LocalAssignment()
|
||||||
|
{
|
||||||
|
Name="test assignment",
|
||||||
|
Description ="here is the description",
|
||||||
|
DueAt = new DateTime(),
|
||||||
|
LockAt = new DateTime(),
|
||||||
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
|
LocalAssignmentGroupName = "Final Project",
|
||||||
|
Rubric = new List<RubricItem>() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
||||||
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void AssignmentWithEmptySubmissionTypes_CanBeParsed()
|
||||||
|
{
|
||||||
|
var assignment = new LocalAssignment()
|
||||||
|
{
|
||||||
|
Name="test assignment",
|
||||||
|
Description ="here is the description",
|
||||||
|
DueAt = new DateTime(),
|
||||||
|
LockAt = new DateTime(),
|
||||||
|
SubmissionTypes = [],
|
||||||
|
LocalAssignmentGroupName = "Final Project",
|
||||||
|
Rubric = new List<RubricItem>() {
|
||||||
|
new RubricItem() {Points = 4, Label="do task 1"},
|
||||||
|
new RubricItem() {Points = 2, Label="do task 2"},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
||||||
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void AssignmentWithoutLockAtDate_CanBeParsed()
|
||||||
|
{
|
||||||
|
var assignment = new LocalAssignment()
|
||||||
|
{
|
||||||
|
Name="test assignment",
|
||||||
|
Description ="here is the description",
|
||||||
|
DueAt = new DateTime(),
|
||||||
|
LockAt = null,
|
||||||
|
SubmissionTypes = [],
|
||||||
|
LocalAssignmentGroupName = "Final Project",
|
||||||
|
Rubric = new List<RubricItem>() {
|
||||||
|
new RubricItem() {Points = 4, Label="do task 1"},
|
||||||
|
new RubricItem() {Points = 2, Label="do task 2"},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
||||||
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void AssignmentWithoutDescription_CanBeParsed()
|
||||||
|
{
|
||||||
|
var assignment = new LocalAssignment()
|
||||||
|
{
|
||||||
|
Name="test assignment",
|
||||||
|
Description = "",
|
||||||
|
DueAt = new DateTime(),
|
||||||
|
LockAt = new DateTime(),
|
||||||
|
SubmissionTypes = [],
|
||||||
|
LocalAssignmentGroupName = "Final Project",
|
||||||
|
Rubric = new List<RubricItem>() {
|
||||||
|
new RubricItem() {Points = 4, Label="do task 1"},
|
||||||
|
new RubricItem() {Points = 2, Label="do task 2"},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
|
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
||||||
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
private bool discussionIsSelected
|
private bool discussionIsSelected
|
||||||
{
|
{
|
||||||
get => types.FirstOrDefault(
|
get => types.FirstOrDefault(
|
||||||
t => t == SubmissionType.DISCUSSION_TOPIC
|
t => t == AssignmentSubmissionType.DISCUSSION_TOPIC
|
||||||
) != null;
|
) != null;
|
||||||
}
|
}
|
||||||
private void saveTypes(IEnumerable<string> newTypes)
|
private void saveTypes(IEnumerable<string> newTypes)
|
||||||
@@ -51,9 +51,9 @@
|
|||||||
<h5>Submission Types</h5>
|
<h5>Submission Types</h5>
|
||||||
<div class="row" @key="types">
|
<div class="row" @key="types">
|
||||||
|
|
||||||
@foreach (var submissionType in SubmissionType.AllTypes)
|
@foreach (var submissionType in AssignmentSubmissionType.AllTypes)
|
||||||
{
|
{
|
||||||
var isDiscussion = submissionType == SubmissionType.DISCUSSION_TOPIC;
|
var isDiscussion = submissionType == AssignmentSubmissionType.DISCUSSION_TOPIC;
|
||||||
var allowedToBeChecked = !discussionIsSelected || isDiscussion;
|
var allowedToBeChecked = !discussionIsSelected || isDiscussion;
|
||||||
|
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
Rubric = new RubricItem[] { },
|
Rubric = new RubricItem[] { },
|
||||||
LockAt = DateTime.Now,
|
LockAt = DateTime.Now,
|
||||||
DueAt = DateTime.Now,
|
DueAt = DateTime.Now,
|
||||||
SubmissionTypes = new string[] { SubmissionType.ONLINE_TEXT_ENTRY },
|
SubmissionTypes = new string[] { AssignmentSubmissionType.ONLINE_TEXT_ENTRY },
|
||||||
LocalAssignmentGroupName = selectedAssignmentGroup?.Name,
|
LocalAssignmentGroupName = selectedAssignmentGroup?.Name,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ public static class CoursePlannerExtensions
|
|||||||
public static LocalAssignment validateSubmissionTypes(this LocalAssignment assignment)
|
public static LocalAssignment validateSubmissionTypes(this LocalAssignment assignment)
|
||||||
{
|
{
|
||||||
var containsDiscussion =
|
var containsDiscussion =
|
||||||
assignment.SubmissionTypes.FirstOrDefault(t => t == SubmissionType.DISCUSSION_TOPIC) != null;
|
assignment.SubmissionTypes.FirstOrDefault(t => t == AssignmentSubmissionType.DISCUSSION_TOPIC) != null;
|
||||||
|
|
||||||
if (containsDiscussion)
|
if (containsDiscussion)
|
||||||
return assignment with { SubmissionTypes = new string[] { SubmissionType.DISCUSSION_TOPIC } };
|
return assignment with { SubmissionTypes = new string[] { AssignmentSubmissionType.DISCUSSION_TOPIC } };
|
||||||
return assignment;
|
return assignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using YamlDotNet.Serialization;
|
using YamlDotNet.Serialization;
|
||||||
@@ -13,7 +14,7 @@ public record RubricItem
|
|||||||
public bool IsExtraCredit => Label.Contains(extraCredit.ToLower(), StringComparison.CurrentCultureIgnoreCase);
|
public bool IsExtraCredit => Label.Contains(extraCredit.ToLower(), StringComparison.CurrentCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SubmissionType
|
public static class AssignmentSubmissionType
|
||||||
{
|
{
|
||||||
public static readonly string ONLINE_TEXT_ENTRY = "online_text_entry";
|
public static readonly string ONLINE_TEXT_ENTRY = "online_text_entry";
|
||||||
public static readonly string ONLINE_UPLOAD = "online_upload";
|
public static readonly string ONLINE_UPLOAD = "online_upload";
|
||||||
@@ -46,12 +47,12 @@ public record LocalAssignment
|
|||||||
public string Name { get; init; } = "";
|
public string Name { get; init; } = "";
|
||||||
public string Description { get; init; } = "";
|
public string Description { get; init; } = "";
|
||||||
// public bool LockAtDueDate { get; init; }
|
// public bool LockAtDueDate { get; init; }
|
||||||
public IEnumerable<RubricItem> Rubric { get; init; } = Array.Empty<RubricItem>();
|
|
||||||
public DateTime? LockAt { get; init; }
|
public DateTime? LockAt { get; init; }
|
||||||
public DateTime DueAt { get; init; }
|
public DateTime DueAt { get; init; }
|
||||||
public string? LocalAssignmentGroupName { get; init; }
|
public string? LocalAssignmentGroupName { get; init; }
|
||||||
public int PointsPossible => Rubric.Sum(r => r.IsExtraCredit ? 0 : r.Points);
|
|
||||||
public IEnumerable<string> SubmissionTypes { get; init; } = Array.Empty<string>();
|
public IEnumerable<string> SubmissionTypes { get; init; } = Array.Empty<string>();
|
||||||
|
public IEnumerable<RubricItem> Rubric { get; init; } = Array.Empty<RubricItem>();
|
||||||
|
public int PointsPossible => Rubric.Sum(r => r.IsExtraCredit ? 0 : r.Points);
|
||||||
|
|
||||||
public string GetRubricHtml()
|
public string GetRubricHtml()
|
||||||
{
|
{
|
||||||
@@ -85,15 +86,97 @@ public record LocalAssignment
|
|||||||
return yaml;
|
return yaml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LocalAssignment FromMarkdown(string input)
|
||||||
|
{
|
||||||
|
var settingsString = input.Split("---")[0];
|
||||||
|
var (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt) = parseSettings(settingsString);
|
||||||
|
|
||||||
|
var description = input.Split("---" + Environment.NewLine)[1].Split("## Rubric")[0];
|
||||||
|
|
||||||
|
var rubricString = input.Split("## Rubric" + Environment.NewLine)[1];
|
||||||
|
var rubric = ParseRubricMarkdown(rubricString);
|
||||||
|
return new LocalAssignment()
|
||||||
|
{
|
||||||
|
Name=name.Trim(),
|
||||||
|
LocalAssignmentGroupName=localAssignmentGroupName.Trim(),
|
||||||
|
SubmissionTypes=submissionTypes,
|
||||||
|
DueAt=dueAt,
|
||||||
|
LockAt=lockAt,
|
||||||
|
Rubric=rubric,
|
||||||
|
Description=description.Trim()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (string name, string assignmentGroupName, List<string> submissionTypes, DateTime dueAt, DateTime? lockAt) parseSettings(string input)
|
||||||
|
{
|
||||||
|
var name = extractLabelValue(input, "Name");
|
||||||
|
var rawLockAt = extractLabelValue(input, "LockAt");
|
||||||
|
var rawDueAt = extractLabelValue(input, "DueAt");
|
||||||
|
var localAssignmentGroupName = extractLabelValue(input, "AssignmentGroupName");
|
||||||
|
var submissionTypes = parseSubmissionTypes(input);
|
||||||
|
|
||||||
|
DateTime? lockAt = DateTime.TryParse(rawLockAt, out DateTime parsedLockAt)
|
||||||
|
? parsedLockAt
|
||||||
|
: null;
|
||||||
|
var dueAt = DateTime.TryParse(rawDueAt, out DateTime parsedDueAt)
|
||||||
|
? parsedDueAt
|
||||||
|
: throw new QuizMarkdownParseException($"Error with DueAt: {rawDueAt}");
|
||||||
|
|
||||||
|
return (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> parseSubmissionTypes(string input)
|
||||||
|
{
|
||||||
|
List<string> submissionTypes = new List<string>();
|
||||||
|
|
||||||
|
// Define a regular expression pattern to match the bulleted list items
|
||||||
|
string startOfTypePattern = @"- (.+)";
|
||||||
|
Regex regex = new Regex(startOfTypePattern);
|
||||||
|
|
||||||
|
var inputAfterSubmissionTypes = input.Split("SubmissionTypes:" + Environment.NewLine)[1];
|
||||||
|
|
||||||
|
string[] lines = inputAfterSubmissionTypes.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
string trimmedLine = line.Trim();
|
||||||
|
Match match = regex.Match(trimmedLine);
|
||||||
|
|
||||||
|
if (!match.Success)
|
||||||
|
break;
|
||||||
|
|
||||||
|
string type = match.Groups[1].Value.Trim();
|
||||||
|
submissionTypes.Add(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return submissionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
public string ToMarkdown()
|
public string ToMarkdown()
|
||||||
{
|
{
|
||||||
var assignmentYaml = ToYaml();
|
var settingsMarkdown = settingsToMarkdown();
|
||||||
|
var rubricMarkdown = RubricToMarkdown();
|
||||||
var assignmentMarkdown =
|
var assignmentMarkdown =
|
||||||
"```yaml" + Environment.NewLine
|
settingsMarkdown + Environment.NewLine
|
||||||
+ assignmentYaml
|
+ "---" + Environment.NewLine
|
||||||
+ "```" + Environment.NewLine
|
+ Description + Environment.NewLine
|
||||||
+ "<!-- assignment markdown below -->" + Environment.NewLine
|
+ "## Rubric" + Environment.NewLine
|
||||||
+ Description;
|
+ rubricMarkdown;
|
||||||
|
|
||||||
return assignmentMarkdown;
|
return assignmentMarkdown;
|
||||||
}
|
}
|
||||||
@@ -109,8 +192,25 @@ public record LocalAssignment
|
|||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string settingsToMarkdown()
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
builder.Append($"Name: {Name}" + Environment.NewLine);
|
||||||
|
builder.Append($"LockAt: {LockAt}" + Environment.NewLine);
|
||||||
|
builder.Append($"DueAt: {DueAt}" + Environment.NewLine);
|
||||||
|
builder.Append($"AssignmentGroupName: {LocalAssignmentGroupName}" + Environment.NewLine);
|
||||||
|
builder.Append($"SubmissionTypes:" + Environment.NewLine);
|
||||||
|
foreach (var submissionType in SubmissionTypes)
|
||||||
|
{
|
||||||
|
builder.Append($"- {submissionType}" + Environment.NewLine);
|
||||||
|
}
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown)
|
public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown)
|
||||||
{
|
{
|
||||||
|
if(rawMarkdown.Trim() == string.Empty)
|
||||||
|
return [];
|
||||||
var lines = rawMarkdown.Trim().Split(Environment.NewLine);
|
var lines = rawMarkdown.Trim().Split(Environment.NewLine);
|
||||||
var items = lines.Select(parseIndividualRubricItemMarkdown).ToArray();
|
var items = lines.Select(parseIndividualRubricItemMarkdown).ToArray();
|
||||||
return items;
|
return items;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public class CanvasQuizService(
|
|||||||
.Where(
|
.Where(
|
||||||
assignment =>
|
assignment =>
|
||||||
!assignment.IsQuizAssignment
|
!assignment.IsQuizAssignment
|
||||||
&& assignment.SubmissionTypes.Contains(SubmissionType.ONLINE_QUIZ)
|
&& assignment.SubmissionTypes.Contains(AssignmentSubmissionType.ONLINE_QUIZ)
|
||||||
)
|
)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
var tasks = assignmentsToDelete.Select(
|
var tasks = assignmentsToDelete.Select(
|
||||||
|
|||||||
Reference in New Issue
Block a user