using LehrerApp.Core.Models; namespace LehrerApp.Core.Services; public enum SchoolYearPeriodKind { FullYear, H1, H2 } /// /// Gemeinsame Regeln für zeitlich begrenzte Gruppenzugehörigkeiten. /// Eintritt und Austritt gelten unabhängig vom gewählten Halbjahresmodus. /// public static class GroupMembershipService { public static bool IsActiveOn(GroupMembership membership, DateOnly date) { if (membership.JoinedAt is { } joinedAt && date < joinedAt) return false; if (membership.LeftAt is { } leftAt && date > leftAt) return false; return membership.Period switch { MembershipPeriod.H1Only => IsFirstSemester(date), MembershipPeriod.H2Only => !IsFirstSemester(date), _ => true, }; } public static bool Overlaps(GroupMembership membership, DateOnly from, DateOnly to) { if (to < from) return false; var effectiveFrom = membership.JoinedAt is { } joinedAt && joinedAt > from ? joinedAt : from; var effectiveTo = membership.LeftAt is { } leftAt && leftAt < to ? leftAt : to; if (effectiveTo < effectiveFrom) return false; if (membership.Period is MembershipPeriod.FullYear or MembershipPeriod.Custom) return true; for (var month = new DateOnly(effectiveFrom.Year, effectiveFrom.Month, 1); month <= effectiveTo; month = month.AddMonths(1)) { if (membership.Period == MembershipPeriod.H1Only && IsFirstSemester(month)) return true; if (membership.Period == MembershipPeriod.H2Only && !IsFirstSemester(month)) return true; } return false; } public static (DateOnly From, DateOnly To) SchoolYearPeriod( string schoolYear, SchoolYearPeriodKind period) { var slash = schoolYear.IndexOf('/'); var startText = slash >= 0 ? schoolYear[..slash] : schoolYear; if (!int.TryParse(startText, out var startYear)) throw new ArgumentException("Ungültiges Schuljahr.", nameof(schoolYear)); return period switch { SchoolYearPeriodKind.H1 => (new DateOnly(startYear, 8, 1), new DateOnly(startYear + 1, 1, 31)), SchoolYearPeriodKind.H2 => (new DateOnly(startYear + 1, 2, 1), new DateOnly(startYear + 1, 7, 31)), _ => (new DateOnly(startYear, 8, 1), new DateOnly(startYear + 1, 7, 31)), }; } private static bool IsFirstSemester(DateOnly date) => date.Month >= 8 || date.Month <= 1; }