排课版本新建、编辑、复制、发布、归档和删除。
周课表视图,支持12节课、单双周和起止周。 自动校验教师、行政班、教室、时间段冲突。 校验教室容量、教学任务状态和学期范围。 SQLite 开发环境自动升级,MySQL 提供正式 EF Core 迁移。 Vue 已编译为静态文件并随 ASP.NET Core 发布,无需 npm run dev。 桌面端和390px移动端页面均已验收。
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using Jiaowu.Api.Domain.Academic;
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Scheduling;
|
||||
|
||||
public static class ScheduleConflictDetector
|
||||
{
|
||||
public static string? FindConflict(IReadOnlyList<ScheduleEntry> entries)
|
||||
{
|
||||
for (var i = 0; i < entries.Count; i++)
|
||||
{
|
||||
for (var j = i + 1; j < entries.Count; j++)
|
||||
{
|
||||
var first = entries[i];
|
||||
var second = entries[j];
|
||||
if (!TimeOverlaps(first, second)) continue;
|
||||
var reason = ConflictReason(first, second);
|
||||
if (reason is not null)
|
||||
return $"“{first.TeachingTask!.Name}”与“{second.TeachingTask!.Name}”存在{reason}冲突。";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool TimeOverlaps(ScheduleEntry first, ScheduleEntry second) =>
|
||||
first.DayOfWeek == second.DayOfWeek &&
|
||||
first.StartPeriod < second.StartPeriod + second.PeriodCount &&
|
||||
second.StartPeriod < first.StartPeriod + first.PeriodCount &&
|
||||
WeeksOverlap(first, second);
|
||||
|
||||
public static string? ConflictReason(ScheduleEntry first, ScheduleEntry second)
|
||||
{
|
||||
if (first.ClassroomId == second.ClassroomId) return "教室";
|
||||
var firstTeachers = first.TeachingTask!.Teachers.Select(x => x.TeacherId).ToHashSet();
|
||||
if (second.TeachingTask!.Teachers.Any(x => firstTeachers.Contains(x.TeacherId)))
|
||||
return "教师";
|
||||
var firstClasses = first.TeachingTask.Classes
|
||||
.Select(x => x.AdministrativeClassId)
|
||||
.ToHashSet();
|
||||
return second.TeachingTask.Classes.Any(x =>
|
||||
firstClasses.Contains(x.AdministrativeClassId))
|
||||
? "行政班"
|
||||
: null;
|
||||
}
|
||||
|
||||
private static bool WeeksOverlap(ScheduleEntry first, ScheduleEntry second)
|
||||
{
|
||||
var start = Math.Max(first.StartWeek, second.StartWeek);
|
||||
var end = Math.Min(first.EndWeek, second.EndWeek);
|
||||
for (var week = start; week <= end; week++)
|
||||
{
|
||||
if (IncludesWeek(first.WeekPattern, week) &&
|
||||
IncludesWeek(second.WeekPattern, week))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IncludesWeek(WeekPattern pattern, int week) =>
|
||||
pattern == WeekPattern.All ||
|
||||
pattern == WeekPattern.Odd && week % 2 == 1 ||
|
||||
pattern == WeekPattern.Even && week % 2 == 0;
|
||||
}
|
||||
Reference in New Issue
Block a user