From 08db1eb6816a2b64e221c7ce64afc403dab96a9b Mon Sep 17 00:00:00 2001 From: Elias Fierke Date: Sun, 7 Jun 2026 20:31:30 +0200 Subject: [PATCH] [fix:] first semester priority --- crafter.cs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/crafter.cs b/crafter.cs index 7d6c76d..7fcae05 100644 --- a/crafter.cs +++ b/crafter.cs @@ -744,6 +744,87 @@ public class CourseCrafter return true; } + bool EnsureFirstSemesterCoverage() + { + bool changed = false; + + foreach (var student in Settings.Instance.Students) + { + if (student.SelectedCourseNames.Count == 0) + continue; + + var assignments = GetAssignmentsBySemester(student.ID); + if (assignments[0] != null) + continue; + + if (TryAssignStudentToFirstSemester(student)) + changed = true; + } + + return changed; + } + + bool TryAssignStudentToFirstSemester(Student student) + { + var desiredSports = student.SelectedCourseNames + .Select(ResolveSportFromSelection) + .Where(sp => sp != null && sp.Semester[0] != 0) + .DistinctBy(sp => sp!.Name) + .Select(sp => sp!) + .ToList(); + + foreach (var sport in desiredSports) + { + // Direkt in bestehendes Kursangebot eintragen + var existingCourse = GeneratedCourses + .FirstOrDefault(c => c.Semester == 1 && c.Instance.Sport.Name == sport.Name && + c.Instance.Students.Count < c.Instance.Sport.MaxStudents); + + if (existingCourse.Instance != null) + { + existingCourse.Instance.Students.Add(student.ID); + students_in_semester[0].Add(student.ID); + return true; + } + + // Versuche einen Teilnehmer aus einem bestehenden Sem.1-Kurs umzudisponieren + var firstSemesterCourses = GeneratedCourses + .Where(c => c.Semester == 1 && c.Instance.Sport.Name == sport.Name) + .ToList(); + + foreach (var course in firstSemesterCourses) + { + if (course.Instance.Students.Count <= getEffectiveMinStudents(sport, 1)) + continue; + + foreach (var otherStudent in course.Instance.Students.ToList()) + { + if (otherStudent == student.ID) + continue; + + var targetCourse = GeneratedCourses + .FirstOrDefault(c => c.Semester != 1 && c.Instance.Sport.Name == sport.Name && + c.Instance.Students.Count < c.Instance.Sport.MaxStudents && + !students_in_semester[c.Semester - 1].Contains(otherStudent)); + + if (targetCourse.Instance == null) + continue; + + course.Instance.Students.Remove(otherStudent); + students_in_semester[0].Remove(otherStudent); + targetCourse.Instance.Students.Add(otherStudent); + students_in_semester[targetCourse.Semester - 1].Add(otherStudent); + + course.Instance.Students.Add(student.ID); + students_in_semester[0].Add(student.ID); + return true; + } + } + } + + return false; + } + (int Semester, CourseInstance Instance)?[] GetAssignmentsBySemester(string studentId) { var assignments = new (int Semester, CourseInstance Instance)?[4]; @@ -800,7 +881,8 @@ public class CourseCrafter if (freeInterestedStudents > maxFreeInterestedStudents || (freeInterestedStudents == maxFreeInterestedStudents && - totalCoursesPerSemester[i] < minCourses)) + (totalCoursesPerSemester[i] < minCourses || + (totalCoursesPerSemester[i] == minCourses && semesterNumber < bestSem)))) { maxFreeInterestedStudents = freeInterestedStudents; minCourses = totalCoursesPerSemester[i]; @@ -811,6 +893,7 @@ public class CourseCrafter return bestSem; } + EnsureFirstSemesterCoverage(); ReloadResult(); }