254 lines
10 KiB
C#
254 lines
10 KiB
C#
using LehrerApp.Core.Models;
|
|
using LehrerApp.Desktop.ViewModels.Groups;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Desktop.Tests;
|
|
|
|
public sealed class StudentGroupGeneratorViewModelTests
|
|
{
|
|
private static (StudentGroupGeneratorViewModel Vm, List<Student> Students, LearningGroup Group,
|
|
FakeSessions Sessions, FakeEntries Entries) Build(int studentCount = 10,
|
|
FakeStudentGroupPlans? savedPlans = null)
|
|
{
|
|
var group = new LearningGroup { Name = "8a", GradingSystem = GradingSystem.Grades1To6 };
|
|
var students = Enumerable.Range(1, studentCount).Select(i => new Student
|
|
{
|
|
FirstName = $"Kind{i:00}", LastName = "Test",
|
|
}).ToList();
|
|
var memberships = students.Select(s => new GroupMembership
|
|
{
|
|
GroupId = group.Id, StudentId = s.Id,
|
|
}).ToList();
|
|
var sessions = new FakeSessions([]);
|
|
var entries = new FakeEntries();
|
|
var vm = new StudentGroupGeneratorViewModel(
|
|
new FakeStudents(students), new FakeGroups([group]), new FakeMemberships(memberships),
|
|
sessions, entries, new FakeGrades(), group.Id, new Random(7), savedPlans);
|
|
return (vm, students, group, sessions, entries);
|
|
}
|
|
|
|
[Fact]
|
|
public void ManuelleUmverteilung_WirdGespeichertUndSpaeterWiederGeladen()
|
|
{
|
|
var plans = new FakeStudentGroupPlans();
|
|
var (vm, students, group, _, _) = Build(6, plans);
|
|
vm.TargetGroupCount = 2;
|
|
vm.CountPriority = 100;
|
|
vm.GenerateCommand.Execute(null);
|
|
var source = vm.GeneratedGroups[0];
|
|
var target = vm.GeneratedGroups[1];
|
|
var member = source.Members[0];
|
|
|
|
Assert.True(vm.MoveStudent(member, target));
|
|
Assert.False(vm.MoveStudent(member, target));
|
|
Assert.DoesNotContain(member, source.Members);
|
|
vm.PlanName = "Projektwoche";
|
|
vm.SavePlanCommand.Execute(null);
|
|
|
|
var saved = Assert.Single(plans.GetByGroup(group.Id));
|
|
Assert.Equal("Projektwoche", saved.Name);
|
|
Assert.Contains(member.Id, saved.Groups[1].StudentIds);
|
|
Assert.False(vm.HasUnsavedChanges);
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
vm.SelectedSavedPlan = Assert.Single(vm.SavedPlans);
|
|
vm.LoadSavedPlanCommand.Execute(null);
|
|
Assert.Contains(vm.GeneratedGroups[1].Members, m => m.Id == member.Id);
|
|
Assert.DoesNotContain(vm.GeneratedGroups[0].Members, m => m.Id == member.Id);
|
|
Assert.False(vm.HasUnsavedChanges);
|
|
Assert.Equal("Projektwoche", vm.PlanName);
|
|
|
|
var reopened = new StudentGroupGeneratorViewModel(
|
|
new FakeStudents(students), new FakeGroups([group]),
|
|
new FakeMemberships(students.Select(s => new GroupMembership
|
|
{
|
|
GroupId = group.Id, StudentId = s.Id,
|
|
}).ToList()),
|
|
new FakeSessions([]), new FakeEntries(), new FakeGrades(), group.Id,
|
|
savedPlans: plans);
|
|
reopened.SelectedSavedPlan = Assert.Single(reopened.SavedPlans);
|
|
reopened.LoadSavedPlanCommand.Execute(null);
|
|
Assert.Contains(reopened.GeneratedGroups[1].Members, m => m.Id == member.Id);
|
|
|
|
reopened.PlanName = "Projektwoche aktualisiert";
|
|
reopened.SavePlanCommand.Execute(null);
|
|
Assert.Equal("Projektwoche aktualisiert", Assert.Single(plans.GetByGroup(group.Id)).Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void SpeichernUeberschreibtAusgewaehltenPlanErstNachDemLaden()
|
|
{
|
|
var plans = new FakeStudentGroupPlans();
|
|
var (vm, _, group, _, _) = Build(6, plans);
|
|
vm.GenerateCommand.Execute(null);
|
|
vm.PlanName = "Alter Plan";
|
|
vm.SavePlanCommand.Execute(null);
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
vm.SelectedSavedPlan = Assert.Single(vm.SavedPlans);
|
|
vm.PlanName = "Neuer Plan";
|
|
vm.SavePlanCommand.Execute(null);
|
|
|
|
Assert.Equal(2, plans.GetByGroup(group.Id).Count);
|
|
Assert.Contains(plans.GetByGroup(group.Id), p => p.Name == "Alter Plan");
|
|
Assert.Contains(plans.GetByGroup(group.Id), p => p.Name == "Neuer Plan");
|
|
}
|
|
|
|
[Fact]
|
|
public void FesteZielgroesse_ErzeugtPassendeAnzahlMitKleinerAusnahme()
|
|
{
|
|
var (vm, _, _, _, _) = Build(10);
|
|
vm.TargetGroupSize = 4;
|
|
vm.TargetGroupCount = 2;
|
|
vm.SizePriority = 100;
|
|
vm.CountPriority = 20;
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
|
|
Assert.Equal(3, vm.GeneratedGroups.Count);
|
|
Assert.Equal(new[] { 3, 3, 4 }, vm.GeneratedGroups.Select(g => g.Members.Count).OrderBy(x => x));
|
|
Assert.Contains("nicht gleichzeitig", vm.WarningText);
|
|
}
|
|
|
|
[Fact]
|
|
public void FesteGruppenanzahl_HatVorrangVorZielgroesse()
|
|
{
|
|
var (vm, _, _, _, _) = Build(10);
|
|
vm.TargetGroupSize = 3;
|
|
vm.TargetGroupCount = 2;
|
|
vm.SizePriority = 20;
|
|
vm.CountPriority = 100;
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
|
|
Assert.Equal(2, vm.GeneratedGroups.Count);
|
|
Assert.All(vm.GeneratedGroups, group => Assert.Equal(5, group.Members.Count));
|
|
}
|
|
|
|
[Fact]
|
|
public void AdHoc_SchliesstHeuteAbwesendeAus()
|
|
{
|
|
var (vm, students, group, sessions, entries) = Build(6);
|
|
var session = new ParticipationSession { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today) };
|
|
sessions.Save(session);
|
|
entries.Add(new ParticipationEntry
|
|
{
|
|
SessionId = session.Id, StudentId = students[0].Id, Attendance = AttendanceStatus.Excused,
|
|
});
|
|
vm.ParticipantModeName = StudentGroupGeneratorViewModel.AdHocModeLabel;
|
|
vm.TargetGroupCount = 2;
|
|
vm.CountPriority = 100;
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
|
|
var names = vm.GeneratedGroups.SelectMany(g => g.Members).Select(m => m.Name).ToList();
|
|
Assert.Equal(5, names.Count);
|
|
Assert.DoesNotContain(students[0].FullName, names);
|
|
Assert.Contains("fehlt heute", vm.WarningText);
|
|
}
|
|
|
|
[Fact]
|
|
public void AdHoc_OhneHeutigeErfassung_WarntUndNutztAlleAktiven()
|
|
{
|
|
var (vm, students, _, _, _) = Build(6);
|
|
vm.ParticipantModeName = StudentGroupGeneratorViewModel.AdHocModeLabel;
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
|
|
Assert.Equal(students.Count, vm.GeneratedGroups.SelectMany(g => g.Members).Count());
|
|
Assert.Contains("keine Anwesenheit", vm.WarningText);
|
|
}
|
|
|
|
[Fact]
|
|
public void Leistungsverteilung_UnterscheidetHomogeneUndHeterogeneGruppen()
|
|
{
|
|
var group = new LearningGroup { Name = "Kurs", GradingSystem = GradingSystem.Grades1To6 };
|
|
var students = new[] { "A", "B", "C", "D" }.Select(name => new Student
|
|
{
|
|
FirstName = name, LastName = "Test",
|
|
}).ToList();
|
|
var memberships = students.Select(s => new GroupMembership { GroupId = group.Id, StudentId = s.Id }).ToList();
|
|
var grades = new FakeGrades();
|
|
var values = new[] { "1", "2", "5", "6" };
|
|
for (var i = 0; i < students.Count; i++)
|
|
grades.Add(new Grade { GroupId = group.Id, StudentId = students[i].Id, Value = values[i] });
|
|
var vm = new StudentGroupGeneratorViewModel(
|
|
new FakeStudents(students), new FakeGroups([group]), new FakeMemberships(memberships),
|
|
new FakeSessions([]), new FakeEntries(), grades, group.Id, new Random(3))
|
|
{
|
|
TargetGroupCount = 2,
|
|
CountPriority = 100,
|
|
PerformanceDistribution = -100,
|
|
};
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
var homogeneousFirst = vm.GeneratedGroups[0].Members.Select(m => m.Name).ToHashSet();
|
|
Assert.Contains(students[0].FullName, homogeneousFirst);
|
|
Assert.Contains(students[1].FullName, homogeneousFirst);
|
|
|
|
vm.PerformanceDistribution = 100;
|
|
vm.GenerateCommand.Execute(null);
|
|
Assert.All(vm.GeneratedGroups, generated =>
|
|
{
|
|
var names = generated.Members.Select(m => m.Name).ToHashSet();
|
|
Assert.True(names.Overlaps([students[0].FullName, students[1].FullName]));
|
|
Assert.True(names.Overlaps([students[2].FullName, students[3].FullName]));
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Paarregeln_ErzwingenZusammenUndTrennenMitHoherPrioritaet()
|
|
{
|
|
var (vm, students, _, _, _) = Build(6);
|
|
vm.TargetGroupCount = 2;
|
|
vm.CountPriority = 100;
|
|
vm.PerformanceDistribution = 0;
|
|
vm.ForcedPairPriority = 100;
|
|
vm.SelectedPairStudentA = vm.PairCandidates.Single(s => s.Id == students[0].Id);
|
|
vm.SelectedPairStudentB = vm.PairCandidates.Single(s => s.Id == students[1].Id);
|
|
vm.AddForcedPairCommand.Execute(null);
|
|
vm.SelectedPairStudentA = vm.PairCandidates.Single(s => s.Id == students[2].Id);
|
|
vm.SelectedPairStudentB = vm.PairCandidates.Single(s => s.Id == students[3].Id);
|
|
vm.AddExcludedPairCommand.Execute(null);
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
|
|
var groupByName = vm.GeneratedGroups.SelectMany((group, index) =>
|
|
group.Members.Select(member => (member.Name, index)))
|
|
.ToDictionary(x => x.Name, x => x.index);
|
|
Assert.Equal(groupByName[students[0].FullName], groupByName[students[1].FullName]);
|
|
Assert.NotEqual(groupByName[students[2].FullName], groupByName[students[3].FullName]);
|
|
}
|
|
|
|
[Fact]
|
|
public void FoerderschuelerWerdenMoeglichstGleichmaessigVerteilt()
|
|
{
|
|
var group = new LearningGroup { Name = "Kurs" };
|
|
var students = Enumerable.Range(1, 8).Select(i => new Student
|
|
{
|
|
FirstName = $"Kind{i}", LastName = "Test",
|
|
}).ToList();
|
|
var memberships = students.Select((student, index) => new GroupMembership
|
|
{
|
|
GroupId = group.Id,
|
|
StudentId = student.Id,
|
|
Niveau = index < 4 ? Niveau.Foerder : null,
|
|
}).ToList();
|
|
var vm = new StudentGroupGeneratorViewModel(
|
|
new FakeStudents(students), new FakeGroups([group]), new FakeMemberships(memberships),
|
|
new FakeSessions([]), new FakeEntries(), new FakeGrades(), group.Id, new Random(4))
|
|
{
|
|
TargetGroupCount = 2,
|
|
CountPriority = 100,
|
|
PerformanceDistribution = -100,
|
|
DistributeSupportStudents = true,
|
|
};
|
|
|
|
vm.GenerateCommand.Execute(null);
|
|
|
|
var supportNames = students.Take(4).Select(s => s.FullName).ToHashSet();
|
|
Assert.All(vm.GeneratedGroups, generated =>
|
|
Assert.Equal(2, generated.Members.Count(member => supportNames.Contains(member.Name))));
|
|
}
|
|
}
|