选课
This commit is contained in:
@@ -26,4 +26,46 @@ public static class CourseSelectionRules
|
||||
candidateEntries.Any(candidate =>
|
||||
selectedEntries.Any(selected =>
|
||||
ScheduleConflictDetector.TimeOverlaps(candidate, selected)));
|
||||
|
||||
/// <summary>
|
||||
/// Returns the overlap percentage of candidate schedule entries with selected entries.
|
||||
/// 0 = no conflict, 100 = fully overlapping.
|
||||
/// Used for retake enrollment where ≤50% overlap is allowed.
|
||||
/// </summary>
|
||||
public static double CalculateScheduleOverlap(
|
||||
IReadOnlyCollection<ScheduleEntry> candidateEntries,
|
||||
IReadOnlyCollection<ScheduleEntry> selectedEntries)
|
||||
{
|
||||
if (candidateEntries.Count == 0 || selectedEntries.Count == 0)
|
||||
return 0;
|
||||
|
||||
int totalCandidatePeriods = 0;
|
||||
int overlappedPeriods = 0;
|
||||
|
||||
foreach (var candidate in candidateEntries)
|
||||
{
|
||||
totalCandidatePeriods += candidate.PeriodCount;
|
||||
foreach (var selected in selectedEntries)
|
||||
{
|
||||
if (!ScheduleConflictDetector.TimeOverlaps(candidate, selected))
|
||||
continue;
|
||||
// Calculate overlapping periods
|
||||
var overlapStart = Math.Max(
|
||||
candidate.StartPeriod, selected.StartPeriod);
|
||||
var overlapEnd = Math.Min(
|
||||
candidate.StartPeriod + candidate.PeriodCount,
|
||||
selected.StartPeriod + selected.PeriodCount);
|
||||
if (overlapEnd > overlapStart)
|
||||
overlappedPeriods += overlapEnd - overlapStart;
|
||||
}
|
||||
}
|
||||
|
||||
return totalCandidatePeriods == 0
|
||||
? 0
|
||||
: (double)overlappedPeriods / totalCandidatePeriods * 100;
|
||||
}
|
||||
|
||||
/// <summary>Retake expanded capacity: ceiling(original * 1.15).</summary>
|
||||
public static int RetakeCapacity(int originalCapacity) =>
|
||||
(int)Math.Ceiling(originalCapacity * 1.15);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
"20260725_19_flexible_grades";
|
||||
private const string ExamSchedulingOptimizationMigration =
|
||||
"20260725_20_exam_scheduling_optimization";
|
||||
private const string RetakeEnrollmentMigration =
|
||||
"20260725_21_retake_enrollment";
|
||||
|
||||
public async Task MigrateAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -225,6 +227,19 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
? []
|
||||
: ExamSchedulingOptimizationStatements,
|
||||
cancellationToken);
|
||||
|
||||
var retakeEnrollmentExists = await db.Database
|
||||
.SqlQueryRaw<int>(
|
||||
"""
|
||||
SELECT COUNT(*) AS "Value"
|
||||
FROM pragma_table_info('CourseEnrollments')
|
||||
WHERE name = 'EnrollmentType'
|
||||
""")
|
||||
.AnyAsync(value => value > 0, cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
RetakeEnrollmentMigration,
|
||||
retakeEnrollmentExists ? [] : RetakeEnrollmentStatements,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ApplyMigrationAsync(
|
||||
@@ -1461,4 +1476,12 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
ON "ExamSessions" ("RequiredBuildingId");
|
||||
"""
|
||||
];
|
||||
|
||||
private static readonly string[] RetakeEnrollmentStatements =
|
||||
[
|
||||
"""
|
||||
ALTER TABLE "CourseEnrollments"
|
||||
ADD COLUMN "EnrollmentType" INTEGER NOT NULL DEFAULT 1;
|
||||
"""
|
||||
];
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RetakeEnrollment : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "EnrollmentType",
|
||||
table: "CourseEnrollments",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "EnrollmentType",
|
||||
table: "CourseEnrollments");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user