每个实验项目独立建成绩单,支持评分项、参与状态、补做次数、安全违规、报告地址和教师评语。 流程为:录入 → 学院审核 → 教务发布;学生只能查看已发布成绩。 自主预约实验支持同步有效预约名单,已评分记录不会被误删。 课程成绩可将已发布实验成绩汇总为快照导入指定分项;导入后锁定,不能手工篡改。 实验项目成绩不完整时,对应课程分项保持空白,不按 0 分处理。 一级“实验管理”菜单下增加“项目与场次”“实验成绩”;学生端增加“实验安排”“实验成绩”。 已生成 MySQL 正式迁移及 SQLite 开发迁移,尚未操作生产数据库。 界面采用“实验项目 → 独立评分 → 审核发布”工作台设计。
46 lines
1.5 KiB
C#
46 lines
1.5 KiB
C#
using Jiaowu.Api.Domain.Academic;
|
|
|
|
namespace Jiaowu.Api.Infrastructure.Grades;
|
|
|
|
public static class ExperimentGradeCalculator
|
|
{
|
|
public static bool AreWeightsValid(
|
|
decimal contributionWeight,
|
|
decimal passScore,
|
|
IEnumerable<ExperimentGradeItem> items)
|
|
{
|
|
var itemList = items.ToList();
|
|
return contributionWeight is > 0 and <= 100 &&
|
|
passScore is >= 0 and <= 100 &&
|
|
itemList.Count > 0 &&
|
|
itemList.All(item => item.Weight is > 0 and <= 100) &&
|
|
itemList.Sum(item => item.Weight) == 100;
|
|
}
|
|
|
|
public static decimal? CalculateTotal(
|
|
ExperimentGradeRecord record,
|
|
IReadOnlyCollection<ExperimentGradeItem> items)
|
|
{
|
|
if (record.SafetyViolation ||
|
|
record.ParticipationStatus == ExperimentParticipationStatus.Absent)
|
|
return 0;
|
|
if (record.ParticipationStatus is
|
|
ExperimentParticipationStatus.Pending or
|
|
ExperimentParticipationStatus.Excused or
|
|
ExperimentParticipationStatus.Exempt)
|
|
return null;
|
|
|
|
var scores = record.ItemScores.ToDictionary(
|
|
x => x.ExperimentGradeItemId);
|
|
decimal total = 0;
|
|
foreach (var item in items)
|
|
{
|
|
if (!scores.TryGetValue(item.Id, out var score) ||
|
|
!score.Score.HasValue)
|
|
return null;
|
|
total += score.Score.Value * item.Weight / 100;
|
|
}
|
|
return Math.Round(total, 1, MidpointRounding.AwayFromZero);
|
|
}
|
|
}
|