mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 23:58:31 -06:00
working on difference calculations
This commit is contained in:
208
Management.Test/Markdown/CouresDifferencesTests.cs
Normal file
208
Management.Test/Markdown/CouresDifferencesTests.cs
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using LocalModels;
|
||||||
|
|
||||||
|
public class CoursesDifferencesTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void CanDetectNewSettings()
|
||||||
|
{
|
||||||
|
LocalCourse oldCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = []
|
||||||
|
};
|
||||||
|
LocalCourse newCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "new course name" },
|
||||||
|
Modules = []
|
||||||
|
};
|
||||||
|
var differences = CourseDifferences.GetNewChanges(newCourse, oldCourse);
|
||||||
|
|
||||||
|
differences.Modules.Should().BeEmpty();
|
||||||
|
differences.Settings.Should().NotBeNull();
|
||||||
|
differences.Settings?.Name.Should().Be("new course name");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanDetectNewModule()
|
||||||
|
{
|
||||||
|
|
||||||
|
LocalCourse oldCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = []
|
||||||
|
};
|
||||||
|
LocalCourse newCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var differences = CourseDifferences.GetNewChanges(newCourse, oldCourse);
|
||||||
|
|
||||||
|
differences.Modules.Should().NotBeNull();
|
||||||
|
differences.Modules?.Count().Should().Be(1);
|
||||||
|
differences.Modules?.First().Name.Should().Be("new module");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanDetectChangedAssignment()
|
||||||
|
{
|
||||||
|
LocalCourse oldCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
Assignments = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "",
|
||||||
|
DueAt = new DateTime(),
|
||||||
|
SubmissionTypes = [],
|
||||||
|
Rubric = []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
LocalCourse newCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
Assignments = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "new description",
|
||||||
|
DueAt = new DateTime(),
|
||||||
|
SubmissionTypes = [],
|
||||||
|
Rubric = []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var differences = CourseDifferences.GetNewChanges(newCourse, oldCourse);
|
||||||
|
|
||||||
|
differences.Modules.Should().NotBeNull();
|
||||||
|
differences.Modules?.Count().Should().Be(1);
|
||||||
|
differences.Modules?.First().Assignments.First().Description.Should().Be("new description");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanProperlyIgnoreUnchangedModules()
|
||||||
|
{
|
||||||
|
var commonDate = new DateTime();
|
||||||
|
LocalCourse oldCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = [new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
Assignments = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "",
|
||||||
|
DueAt = commonDate,
|
||||||
|
SubmissionTypes = [],
|
||||||
|
Rubric = []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
LocalCourse newCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = [new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
Assignments = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "",
|
||||||
|
DueAt = commonDate,
|
||||||
|
SubmissionTypes = [],
|
||||||
|
Rubric = []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
var differences = CourseDifferences.GetNewChanges(newCourse, oldCourse);
|
||||||
|
|
||||||
|
differences.Modules.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OnlyChangedAssignmentRepresented()
|
||||||
|
{
|
||||||
|
var commonDate = new DateTime();
|
||||||
|
LocalCourse oldCourse = new()
|
||||||
|
{
|
||||||
|
Settings = new() { Name = "Test Course" },
|
||||||
|
Modules = [new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
Assignments = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "",
|
||||||
|
DueAt = commonDate,
|
||||||
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
|
Rubric = [ new() {Points = 1, Label = "rubric"} ],
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment 2",
|
||||||
|
Description = "",
|
||||||
|
DueAt = commonDate,
|
||||||
|
SubmissionTypes = [],
|
||||||
|
Rubric = [],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
LocalCourse newCourse = oldCourse with {
|
||||||
|
Modules = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "new module",
|
||||||
|
Assignments = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "",
|
||||||
|
DueAt = commonDate,
|
||||||
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
|
Rubric = [ new() {Points = 1, Label = "rubric"} ],
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Name = "test assignment 2 with a new name",
|
||||||
|
Description = "",
|
||||||
|
DueAt = commonDate,
|
||||||
|
SubmissionTypes = [],
|
||||||
|
Rubric = []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var differences = CourseDifferences.GetNewChanges(newCourse, oldCourse);
|
||||||
|
|
||||||
|
differences.Modules.First().Assignments.Count().Should().Be(1);
|
||||||
|
differences.Modules.First().Assignments.First().Name.Should().Be("test assignment 2 with a new name");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
{
|
{
|
||||||
<QuizListItem Quiz="quiz" />
|
<QuizListItem Quiz="quiz" />
|
||||||
} *@
|
} *@
|
||||||
@foreach(var item in Module.SortedModuleItems)
|
@foreach(var item in Module.GetSortedModuleItems())
|
||||||
{
|
{
|
||||||
@(item switch
|
@(item switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
namespace LocalModels;
|
namespace LocalModels;
|
||||||
|
|
||||||
public record LocalAssignment : IModuleItem
|
public sealed record LocalAssignment : IModuleItem
|
||||||
{
|
{
|
||||||
private string _name = "";
|
private string _name = "";
|
||||||
public string Name
|
public string Name
|
||||||
@@ -37,4 +37,13 @@ public record LocalAssignment : IModuleItem
|
|||||||
public string RubricToMarkdown() => this.AssignmentRubricToMarkdown();
|
public string RubricToMarkdown() => this.AssignmentRubricToMarkdown();
|
||||||
public static LocalAssignment ParseMarkdown(string input) => LocalAssignmentMarkdownParser.ParseMarkdown(input);
|
public static LocalAssignment ParseMarkdown(string input) => LocalAssignmentMarkdownParser.ParseMarkdown(input);
|
||||||
public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown) => LocalAssignmentMarkdownParser.ParseRubricMarkdown(rawMarkdown);
|
public static IEnumerable<RubricItem> ParseRubricMarkdown(string rawMarkdown) => LocalAssignmentMarkdownParser.ParseRubricMarkdown(rawMarkdown);
|
||||||
|
|
||||||
|
|
||||||
|
public bool Equals(LocalAssignment? otherAssignment)
|
||||||
|
{
|
||||||
|
return ToMarkdown() == otherAssignment?.ToMarkdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => ToMarkdown().GetHashCode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ namespace LocalModels;
|
|||||||
public record LocalCourse
|
public record LocalCourse
|
||||||
{
|
{
|
||||||
public IEnumerable<LocalModule> Modules { get; init; } = Enumerable.Empty<LocalModule>();
|
public IEnumerable<LocalModule> Modules { get; init; } = Enumerable.Empty<LocalModule>();
|
||||||
public required LocalCourseSettings Settings { get; set; }
|
public required LocalCourseSettings Settings { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public record SimpleTimeOnly
|
public record SimpleTimeOnly
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace LocalModels;
|
namespace LocalModels;
|
||||||
|
|
||||||
public record LocalModule
|
public sealed record LocalModule
|
||||||
{
|
{
|
||||||
public string Name { get; init; } = string.Empty;
|
public string Name { get; init; } = string.Empty;
|
||||||
public string Notes { get; set; } = string.Empty;
|
public string Notes { get; set; } = string.Empty;
|
||||||
@@ -8,10 +8,57 @@ public record LocalModule
|
|||||||
public IEnumerable<LocalQuiz> Quizzes { get; init; } = [];
|
public IEnumerable<LocalQuiz> Quizzes { get; init; } = [];
|
||||||
public IEnumerable<LocalCoursePage> Pages { get; init; } = [];
|
public IEnumerable<LocalCoursePage> Pages { get; init; } = [];
|
||||||
|
|
||||||
public IEnumerable<IModuleItem> SortedModuleItems =>
|
public IEnumerable<IModuleItem> GetSortedModuleItems() =>
|
||||||
Enumerable.Empty<IModuleItem>()
|
Enumerable.Empty<IModuleItem>()
|
||||||
.Concat(Assignments)
|
.Concat(Assignments)
|
||||||
.Concat(Quizzes)
|
.Concat(Quizzes)
|
||||||
.Concat(Pages)
|
.Concat(Pages)
|
||||||
.OrderBy(i => i.DueAt);
|
.OrderBy(i => i.DueAt);
|
||||||
|
|
||||||
|
public bool Equals(LocalModule? otherModule)
|
||||||
|
{
|
||||||
|
var areEqual =
|
||||||
|
string.Equals(Name, otherModule?.Name, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& string.Equals(Notes, otherModule?.Notes, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& CompareCollections(Assignments.OrderBy(x => x.Name), otherModule?.Assignments.OrderBy(x => x.Name))
|
||||||
|
&& CompareCollections(Quizzes.OrderBy(x => x.Name), otherModule?.Quizzes.OrderBy(x => x.Name))
|
||||||
|
&& CompareCollections(Pages.OrderBy(x => x.Name), otherModule?.Pages.OrderBy(x => x.Name));
|
||||||
|
return areEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CompareCollections<T>(IEnumerable<T> first, IEnumerable<T>? second)
|
||||||
|
{
|
||||||
|
var firstList = first.ToList();
|
||||||
|
var secondList = second?.ToList();
|
||||||
|
|
||||||
|
if (firstList.Count != secondList?.Count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < firstList.Count; i++)
|
||||||
|
{
|
||||||
|
if (!Equals(firstList[i], secondList[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
HashCode hash = new HashCode();
|
||||||
|
hash.Add(Name, StringComparer.OrdinalIgnoreCase);
|
||||||
|
hash.Add(Notes, StringComparer.OrdinalIgnoreCase);
|
||||||
|
AddRangeToHash(hash, Assignments.OrderBy(x => x.Name));
|
||||||
|
AddRangeToHash(hash, Quizzes.OrderBy(x => x.Name));
|
||||||
|
AddRangeToHash(hash, Pages.OrderBy(x => x.Name));
|
||||||
|
return hash.ToHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddRangeToHash<T>(HashCode hash, IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
hash.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
40
Management/Services/Files/CourseDifferences.cs
Normal file
40
Management/Services/Files/CourseDifferences.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using LocalModels;
|
||||||
|
|
||||||
|
public static class CourseDifferences
|
||||||
|
{
|
||||||
|
public static NewCourseChanges GetNewChanges(LocalCourse newCourse, LocalCourse oldCourse)
|
||||||
|
{
|
||||||
|
if (newCourse == oldCourse)
|
||||||
|
return new NewCourseChanges();
|
||||||
|
|
||||||
|
var differentModules = newCourse.Modules
|
||||||
|
.Where(newModule =>
|
||||||
|
!oldCourse.Modules.Any(oldModule => oldModule.Equals(newModule))
|
||||||
|
)
|
||||||
|
.Select(newModule =>
|
||||||
|
{
|
||||||
|
var oldModule = oldCourse.Modules.FirstOrDefault(m => m.Name == newModule.Name);
|
||||||
|
if (oldModule == null)
|
||||||
|
return newModule;
|
||||||
|
|
||||||
|
var newAssignments = newModule.Assignments.Where(
|
||||||
|
newAssignment => !oldModule.Assignments.Any(oldAssignment => newAssignment == oldAssignment)
|
||||||
|
);
|
||||||
|
return newModule with { Assignments = newAssignments };
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return new NewCourseChanges
|
||||||
|
{
|
||||||
|
Settings = newCourse.Settings,
|
||||||
|
Modules = differentModules,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public record NewCourseChanges
|
||||||
|
{
|
||||||
|
public IEnumerable<LocalModule> Modules { get; init; } = [];
|
||||||
|
public LocalCourseSettings? Settings { get; init; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user