using Core.Entities;
namespace Core.Calculation;
///
/// Represents a solution to the team scheduling problem.
/// Contains team assignments to time slots and information about student scheduling conflicts.
///
public class TeamSchedulerSolution(
Team[][] timeSlots,
Student[] students,
string status)
{
///
/// Gets the solver status (e.g., "Optimal", "Feasible", "Infeasible").
///
public string Status { get; } = status;
///
/// Gets the scheduled time slots with team assignments and conflict information.
///
public TeamScheduleTimeSlot[] TimeSlots { get; set; }
= timeSlots.Select( (teams,i) =>
new TeamScheduleTimeSlot{
Name = "Time Slot " + (i + 1),
Teams = teams,
StudentOverlaps = GetStudentTeamOverlaps(teams),
UnscheduledStudents = GetStudentsNotInTimSlot(teams, students)
}
).ToArray();
///
/// Calculates the total number of student conflicts across all time slots.
///
/// The scheduled time slots
/// Total count of students with overlapping team meetings
public static int GetStudentTeamOverlapCount(Team[][] timeSlots)
{
return timeSlots.Sum(GetStudentTeamOverlapCount);
}
///
/// Calculates the number of student conflicts in a single time slot.
///
/// The time slot to analyze
/// Count of students with multiple team meetings in this slot
private static int GetStudentTeamOverlapCount(Team[] timeSlot)
{
return GetStudentTeamOverlaps(timeSlot).Count();
}
///
/// Identifies students who have multiple team meetings in the same time slot.
///
/// The time slot to analyze
/// Students and their conflicting teams in this time slot
public static IEnumerable<(Student student, IEnumerable teams)> GetStudentTeamOverlaps(Team[] timeSlot)
{
return
from s in timeSlot.SelectMany(ts => ts.Students).Distinct()
group s by timeSlot.Where(t => t.Students.Contains(s))
into gs
where gs.Key.Count() > 1
select (gs.First(), gs.Key);
}
///
/// Identifies students who have no team meetings in the given time slot.
///
/// The time slot to analyze
/// All students
/// Students not scheduled in this time slot
public static Student[] GetStudentsNotInTimSlot(Team[] timeSlot, Student[] students)
{
var studentsInTimeSlot = timeSlot.SelectMany(ts => ts.Students).Distinct().ToHashSet();
return students.Where(s => !studentsInTimeSlot.Contains(s)).ToArray();
}
///
/// Gets the teams a student is on that weren't assigned to any time slot.
///
/// The student to check
/// Teams the student is on that have no scheduled meeting
public Team[] StudentUnassignedTeams(Student student)
{
var meetingTeams = TimeSlots.SelectMany(t => t.Teams);
var meetingTeamIds = meetingTeams.Select(t => t.Id).ToHashSet();
return student.Teams.Where(e => !meetingTeamIds.Contains(e.Id)).ToArray();
}
}