working on difference calculations

This commit is contained in:
2024-05-03 21:33:06 -06:00
parent 26bf2bbbd1
commit 5c931af141
6 changed files with 309 additions and 5 deletions

View 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");
}
}

View File

@@ -168,7 +168,7 @@
{
<QuizListItem Quiz="quiz" />
} *@
@foreach(var item in Module.SortedModuleItems)
@foreach(var item in Module.GetSortedModuleItems())
{
@(item switch
{

View File

@@ -1,7 +1,7 @@
namespace LocalModels;
public record LocalAssignment : IModuleItem
public sealed record LocalAssignment : IModuleItem
{
private string _name = "";
public string Name
@@ -37,4 +37,13 @@ public record LocalAssignment : IModuleItem
public string RubricToMarkdown() => this.AssignmentRubricToMarkdown();
public static LocalAssignment ParseMarkdown(string input) => LocalAssignmentMarkdownParser.ParseMarkdown(input);
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();
}

View File

@@ -3,7 +3,7 @@ namespace LocalModels;
public record LocalCourse
{
public IEnumerable<LocalModule> Modules { get; init; } = Enumerable.Empty<LocalModule>();
public required LocalCourseSettings Settings { get; set; }
public required LocalCourseSettings Settings { get; init; }
}
public record SimpleTimeOnly

View File

@@ -1,6 +1,6 @@
namespace LocalModels;
public record LocalModule
public sealed record LocalModule
{
public string Name { get; init; } = string.Empty;
public string Notes { get; set; } = string.Empty;
@@ -8,10 +8,57 @@ public record LocalModule
public IEnumerable<LocalQuiz> Quizzes { get; init; } = [];
public IEnumerable<LocalCoursePage> Pages { get; init; } = [];
public IEnumerable<IModuleItem> SortedModuleItems =>
public IEnumerable<IModuleItem> GetSortedModuleItems() =>
Enumerable.Empty<IModuleItem>()
.Concat(Assignments)
.Concat(Quizzes)
.Concat(Pages)
.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);
}
}
}

View 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; }
}