实验成绩计算

This commit is contained in:
2026-08-09 22:40:21 +08:00 Unverified
parent d4abdd3db4
commit c25f16ec20
12 changed files with 7653 additions and 290 deletions
@@ -2,6 +2,7 @@ using Jiaowu.Api.Controllers;
using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Domain.Identity;
using Jiaowu.Api.Infrastructure.Auth;
using Jiaowu.Api.Infrastructure.Grades;
using Jiaowu.Api.Infrastructure.Persistence;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
@@ -262,7 +263,17 @@ public sealed class ExperimentGradesControllerTests
var studentResult = await fixture
.ExperimentGrades(fixture.StudentScope)
.GetMine(CancellationToken.None);
Assert.IsType<OkObjectResult>(studentResult);
var studentResultOk = Assert.IsType<OkObjectResult>(studentResult);
var studentCourse = Assert.Single(
Assert.IsAssignableFrom<System.Collections.IEnumerable>(
studentResultOk.Value).Cast<object>());
Assert.Equal(85m, Property<decimal>(
studentCourse,
"ExperimentCourseScore"));
var persistedExperimentCourseGrade = await fixture.Db
.ExperimentCourseGrades.SingleAsync();
Assert.Equal(85m, persistedExperimentCourseGrade.WeightedAverageScore);
Assert.Equal(1, persistedExperimentCourseGrade.PublishedProjectCount);
var courseSheet = new GradeSheet
{
@@ -330,6 +341,83 @@ public sealed class ExperimentGradesControllerTests
Assert.IsType<ConflictObjectResult>(manualOverride);
}
[Fact]
public async Task ExperimentCourseGrade_IsPersistedAsWeightedAverage()
{
await using var fixture = await ExperimentGradeFixture.CreateAsync();
var firstProject = new ExperimentProject
{
TeachingTaskId = fixture.Task.Id,
Code = "LAB-W1",
Name = "低权重实验",
ArrangementMode = ExperimentArrangementMode.Centralized,
StartDate = fixture.Term.StartDate,
EndDate = fixture.Term.EndDate,
Status = ExperimentProjectStatus.Published,
GradeSheet = new ExperimentGradeSheet
{
ContributionWeight = 1,
Status = ExperimentGradeSheetStatus.Published,
Records =
[
new ExperimentGradeRecord
{
StudentId = fixture.Student.Id,
ParticipationStatus = ExperimentParticipationStatus.Completed,
TotalScore = 80,
IsPassed = true
}
]
}
};
var secondProject = new ExperimentProject
{
TeachingTaskId = fixture.Task.Id,
Code = "LAB-W2",
Name = "高权重实验",
ArrangementMode = ExperimentArrangementMode.Centralized,
StartDate = fixture.Term.StartDate,
EndDate = fixture.Term.EndDate,
Status = ExperimentProjectStatus.Published,
GradeSheet = new ExperimentGradeSheet
{
ContributionWeight = 3,
Status = ExperimentGradeSheetStatus.Published,
Records =
[
new ExperimentGradeRecord
{
StudentId = fixture.Student.Id,
ParticipationStatus = ExperimentParticipationStatus.Completed,
TotalScore = 90,
IsPassed = true
}
]
}
};
fixture.Db.AddRange(firstProject, secondProject);
await fixture.Db.SaveChangesAsync();
await ExperimentGradeAggregationService.RefreshTeachingTaskAsync(
fixture.Db,
fixture.Task.Id,
CancellationToken.None);
var persisted = await fixture.Db.ExperimentCourseGrades.SingleAsync();
Assert.Equal(87.5m, persisted.WeightedAverageScore);
Assert.Equal(4m, persisted.TotalWeight);
Assert.Equal(2, persisted.PublishedProjectCount);
firstProject.GradeSheet!.Records.Single().TotalScore = 0;
await fixture.Db.SaveChangesAsync();
var referenced = await ExperimentGradeAggregationService.CalculateAsync(
fixture.Db,
fixture.Task.Id,
[fixture.Student.Id],
CancellationToken.None);
Assert.Equal(87.5m, referenced.Scores[fixture.Student.Id]);
}
[Fact]
public async Task SelfScheduledSheet_SyncsOnlyActiveBookings()
{