45edcf5e5f
This commit removes the obsolete EventAssignment class from Core.Entities and introduces new models in Core.Models, including AssignmentParameters, AssignmentRequirement, PartialTeam, and StudentEventStatistics. The changes enhance the organization of assignment-related data and improve the overall structure of the codebase. Additionally, several files have been updated to include references to the new Core.Models namespace, ensuring consistency across the application.
176 lines
6.2 KiB
C#
176 lines
6.2 KiB
C#
using Core.Calculation;
|
|
using Core.Entities;
|
|
using Core.Models;
|
|
using Tests.Builders;
|
|
using Tests.Fixtures;
|
|
using EventAssignment = Core.Calculation.EventAssignment;
|
|
|
|
namespace Tests.Calculation;
|
|
|
|
[TestFixture]
|
|
public class EventAssignmentTests
|
|
{
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
BuilderExtensions.ResetAllBuilders();
|
|
}
|
|
|
|
[Test]
|
|
public async Task SolutionTest()
|
|
{
|
|
// Create custom test data with sufficient rankings for EventAssignment
|
|
// Need enough events and rankings to satisfy the default parameters:
|
|
// - 2-4 events per student
|
|
// - 6-8 effort points per student
|
|
// - At least 1 regional event
|
|
// - At least 1 on-site activity
|
|
|
|
var flight = EventDefinitionBuilder.Individual("Flight").AsRegionalEvent().Build();
|
|
var coding = EventDefinitionBuilder.Individual("Coding").AsRegionalEvent().Build();
|
|
var speech = EventDefinitionBuilder.Individual("Prepared Speech").AsOnSite().Build();
|
|
var photo = EventDefinitionBuilder.Individual("Digital Photography").Build();
|
|
var essays = EventDefinitionBuilder.Individual("Essays on Technology").Build();
|
|
|
|
var robotics = EventDefinitionBuilder.Team("Robotics", 2, 5).AsRegionalEvent().AsOnSite().Build();
|
|
var biotech = EventDefinitionBuilder.Team("Biotechnology", 2, 6).AsRegionalEvent().Build();
|
|
var webDesign = EventDefinitionBuilder.Team("Website Design", 3, 6).Build();
|
|
var videoGame = EventDefinitionBuilder.Team("Video Game Design", 2, 6).Build();
|
|
var engineering = EventDefinitionBuilder.Team("Engineering Design", 3, 6).AsOnSite().Build();
|
|
|
|
var events = new[] { flight, coding, speech, photo, essays, robotics, biotech, webDesign, videoGame, engineering };
|
|
|
|
// Create students with diverse rankings (each ranks 7-8 events)
|
|
var alice = StudentBuilder.Default()
|
|
.WithName("Alice", "A").WithGrade(9)
|
|
.WithRanking(flight, 1).WithRanking(robotics, 2).WithRanking(biotech, 3)
|
|
.WithRanking(speech, 4).WithRanking(webDesign, 5).WithRanking(coding, 6)
|
|
.WithRanking(videoGame, 7)
|
|
.Build();
|
|
|
|
var bob = StudentBuilder.Default()
|
|
.WithName("Bob", "B").WithGrade(10)
|
|
.WithRanking(coding, 1).WithRanking(engineering, 2).WithRanking(robotics, 3)
|
|
.WithRanking(speech, 4).WithRanking(biotech, 5).WithRanking(photo, 6)
|
|
.WithRanking(videoGame, 7)
|
|
.Build();
|
|
|
|
var carol = StudentBuilder.Default()
|
|
.WithName("Carol", "C").WithGrade(11)
|
|
.WithRanking(photo, 1).WithRanking(webDesign, 2).WithRanking(engineering, 3)
|
|
.WithRanking(speech, 4).WithRanking(biotech, 5).WithRanking(flight, 6)
|
|
.WithRanking(coding, 7)
|
|
.Build();
|
|
|
|
var david = StudentBuilder.Default()
|
|
.WithName("David", "D").WithGrade(9)
|
|
.WithRanking(essays, 1).WithRanking(robotics, 2).WithRanking(videoGame, 3)
|
|
.WithRanking(engineering, 4).WithRanking(speech, 5).WithRanking(coding, 6)
|
|
.WithRanking(biotech, 7)
|
|
.Build();
|
|
|
|
var eve = StudentBuilder.Default()
|
|
.WithName("Eve", "E").WithGrade(10)
|
|
.WithRanking(flight, 1).WithRanking(webDesign, 2).WithRanking(engineering, 3)
|
|
.WithRanking(robotics, 4).WithRanking(photo, 5).WithRanking(coding, 6)
|
|
.WithRanking(speech, 7)
|
|
.Build();
|
|
|
|
var frank = StudentBuilder.Default()
|
|
.WithName("Frank", "F").WithGrade(11)
|
|
.WithRanking(coding, 1).WithRanking(biotech, 2).WithRanking(videoGame, 3)
|
|
.WithRanking(speech, 4).WithRanking(webDesign, 5).WithRanking(flight, 6)
|
|
.WithRanking(robotics, 7)
|
|
.Build();
|
|
|
|
var students = new[] { alice, bob, carol, david, eve, frank };
|
|
|
|
// Use relaxed parameters for test
|
|
var parameters = new AssignmentParameters(
|
|
effortLowerBound: 4,
|
|
effortUpperBound: 7,
|
|
eventsLowerBound: 2,
|
|
eventsUpperBound: 4,
|
|
requireRegional: false, // Relax for test simplicity
|
|
requireOnSite: false // Relax for test simplicity
|
|
);
|
|
|
|
var eventAssignment = new EventAssignment(events, students, parameters);
|
|
var solution = await eventAssignment.Solve();
|
|
|
|
// Verify solution
|
|
Assert.That(solution.Teams, Is.Not.Null);
|
|
Assert.That(solution.Status, Is.EqualTo("Optimal").Or.EqualTo("Feasible"),
|
|
$"Solution should be Optimal or Feasible, but was {solution.Status}");
|
|
|
|
// Print solution summary for verification
|
|
Console.WriteLine($"Solution Status: {solution.Status}");
|
|
Console.WriteLine($"Teams Created: {solution.Teams.Length}");
|
|
Console.WriteLine($"Students Assigned: {solution.Teams.SelectMany(t => t.Students).Distinct().Count()}");
|
|
|
|
// Verify each team has valid structure
|
|
foreach (var team in solution.Teams)
|
|
{
|
|
Assert.That(team.Event, Is.Not.Null, $"Team should have an event");
|
|
Assert.That(team.Students, Is.Not.Empty, $"Team for {team.Event.Name} should have students");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task SolutionTest_WithMinimalData()
|
|
{
|
|
// Test with minimal custom data to verify basic functionality
|
|
var flight = EventDefinitionBuilder.Individual("Flight").Build();
|
|
var coding = EventDefinitionBuilder.Individual("Coding").Build();
|
|
var robotics = EventDefinitionBuilder.Team("Robotics", 2, 5).AsRegionalEvent().Build();
|
|
var biotech = EventDefinitionBuilder.Team("Biotechnology", 2, 6).AsRegionalEvent().Build();
|
|
|
|
var events = new[] { flight, coding, robotics, biotech };
|
|
|
|
var alice = StudentBuilder.Default()
|
|
.WithName("Alice", "A")
|
|
.WithGrade(9)
|
|
.WithRanking(flight, 1)
|
|
.WithRanking(robotics, 2)
|
|
.WithRanking(biotech, 3)
|
|
.Build();
|
|
|
|
var bob = StudentBuilder.Default()
|
|
.WithName("Bob", "B")
|
|
.WithGrade(10)
|
|
.WithRanking(coding, 1)
|
|
.WithRanking(robotics, 2)
|
|
.WithRanking(biotech, 3)
|
|
.Build();
|
|
|
|
var carol = StudentBuilder.Default()
|
|
.WithName("Carol", "C")
|
|
.WithGrade(11)
|
|
.WithRanking(flight, 2)
|
|
.WithRanking(biotech, 1)
|
|
.WithRanking(robotics, 3)
|
|
.Build();
|
|
|
|
var students = new[] { alice, bob, carol };
|
|
|
|
// Run the event assignment algorithm with minimal data
|
|
var parameters = new AssignmentParameters(
|
|
effortLowerBound: 2,
|
|
effortUpperBound: 4,
|
|
eventsLowerBound: 2,
|
|
eventsUpperBound: 3,
|
|
requireRegional: false,
|
|
requireOnSite: false
|
|
);
|
|
|
|
var eventAssignment = new EventAssignment(events, students, parameters);
|
|
var solution = await eventAssignment.Solve();
|
|
|
|
// Verify solution
|
|
Assert.That(solution.Status, Is.EqualTo("Optimal").Or.EqualTo("Feasible"));
|
|
Assert.That(solution.Teams, Is.Not.Empty, "Should create some teams");
|
|
|
|
Console.WriteLine($"Minimal Test - Status: {solution.Status}");
|
|
Console.WriteLine($"Teams: {solution.Teams.Length}");
|
|
}
|
|
} |