新增按学期配置的“自动排课优化”页签,可调教师/行政班同日集中、行政班空档与连堂、首末节、教室容量冗余等权重。
自动排课在所有硬约束满足后,对候选排法应用这些软约束评分;不会改动既有课程或已发布课表。
This commit is contained in:
1 parent
8074d59e82
commit
0513e251df
10 files changed
+7588
-2
No files matched your search
@@ -14,6 +14,46 @@ namespace Jiaowu.Api.Controllers;
|
||||
[Route("api/schedules")]
|
||||
public sealed class ScheduleSettingsController(AppDbContext db, IAppCache cache) : ControllerBase
|
||||
{
|
||||
[HttpGet("optimization-settings")]
|
||||
public async Task<ActionResult> GetOptimizationSettings(
|
||||
Guid academicTermId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var settings = await db.ScheduleOptimizationSettings.AsNoTracking()
|
||||
.FirstOrDefaultAsync(x => x.AcademicTermId == academicTermId, cancellationToken)
|
||||
?? ScheduleOptimizationSettings.CreateDefault(academicTermId);
|
||||
return Ok(ToOptimizationSettingsResponse(settings));
|
||||
}
|
||||
|
||||
[HttpPut("optimization-settings/{academicTermId:guid}")]
|
||||
public async Task<ActionResult> SaveOptimizationSettings(
|
||||
Guid academicTermId,
|
||||
ScheduleOptimizationSettingsRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await db.AcademicTerms.AnyAsync(
|
||||
x => x.Id == academicTermId && x.IsEnabled,
|
||||
cancellationToken))
|
||||
return ValidationProblem("学期不存在或已停用。");
|
||||
|
||||
var settings = await db.ScheduleOptimizationSettings
|
||||
.FirstOrDefaultAsync(x => x.AcademicTermId == academicTermId, cancellationToken);
|
||||
if (settings is null)
|
||||
{
|
||||
settings = ScheduleOptimizationSettings.CreateDefault(academicTermId);
|
||||
db.ScheduleOptimizationSettings.Add(settings);
|
||||
}
|
||||
settings.TeacherSameDayWeight = request.TeacherSameDayWeight;
|
||||
settings.ClassSameDayWeight = request.ClassSameDayWeight;
|
||||
settings.ClassGapWeight = request.ClassGapWeight;
|
||||
settings.ConsecutiveClassWeight = request.ConsecutiveClassWeight;
|
||||
settings.EarlyPeriodPenalty = request.EarlyPeriodPenalty;
|
||||
settings.LatePeriodPenalty = request.LatePeriodPenalty;
|
||||
settings.RoomCapacityWasteWeight = request.RoomCapacityWasteWeight;
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
return Ok(ToOptimizationSettingsResponse(settings));
|
||||
}
|
||||
|
||||
[HttpGet("time-slots")]
|
||||
public async Task<ActionResult> GetTimeSlots(
|
||||
Guid academicTermId,
|
||||
@@ -32,6 +72,17 @@ public sealed class ScheduleSettingsController(AppDbContext db, IAppCache cache)
|
||||
})
|
||||
.ToListAsync(cancellationToken));
|
||||
|
||||
private static object ToOptimizationSettingsResponse(ScheduleOptimizationSettings settings) => new
|
||||
{
|
||||
settings.TeacherSameDayWeight,
|
||||
settings.ClassSameDayWeight,
|
||||
settings.ClassGapWeight,
|
||||
settings.ConsecutiveClassWeight,
|
||||
settings.EarlyPeriodPenalty,
|
||||
settings.LatePeriodPenalty,
|
||||
settings.RoomCapacityWasteWeight
|
||||
};
|
||||
|
||||
[HttpPut("time-slots/{academicTermId:guid}")]
|
||||
public async Task<ActionResult> ReplaceTimeSlots(
|
||||
Guid academicTermId,
|
||||
@@ -544,6 +595,15 @@ public sealed record ScheduleTimeSlotRequest(
|
||||
TimeOnly EndsAt,
|
||||
bool IsEnabled);
|
||||
|
||||
public sealed record ScheduleOptimizationSettingsRequest(
|
||||
[Range(0, 10_000)] int TeacherSameDayWeight,
|
||||
[Range(0, 10_000)] int ClassSameDayWeight,
|
||||
[Range(0, 10_000)] int ClassGapWeight,
|
||||
[Range(0, 10_000)] int ConsecutiveClassWeight,
|
||||
[Range(0, 10_000)] int EarlyPeriodPenalty,
|
||||
[Range(0, 10_000)] int LatePeriodPenalty,
|
||||
[Range(0, 10_000)] int RoomCapacityWasteWeight);
|
||||
|
||||
public sealed record TeachingTaskScheduleConstraintRequest(
|
||||
TeachingTaskSchedulingMode SchedulingMode,
|
||||
bool RequiresClassroom,
|
||||
|
||||
Reference in new issue
Block a user