Files
Academic-Affairs-System/src/Jiaowu.Api/Infrastructure/Grades/GradeCalculator.cs
T
2026-07-25 19:16:11 +08:00

69 lines
2.2 KiB
C#

using Jiaowu.Api.Domain.Academic;
namespace Jiaowu.Api.Infrastructure.Grades;
public static class GradeCalculator
{
public static bool AreWeightsValid(
decimal regularWeight,
decimal finalWeight,
IEnumerable<GradeItem> items) =>
regularWeight is >= 0 and <= 100 &&
finalWeight is >= 0 and <= 100 &&
items.All(item => item.Weight is >= 0 and <= 100) &&
regularWeight + finalWeight + items.Sum(item => item.Weight) == 100;
public static decimal? CalculateTotal(
decimal? regularScore,
decimal? finalScore,
IReadOnlyCollection<GradeItemScore> itemScores,
decimal regularWeight,
decimal finalWeight,
IReadOnlyCollection<GradeItem> items,
GradeExamStatus examStatus)
{
if (examStatus != GradeExamStatus.Normal && examStatus != GradeExamStatus.Makeup)
return null;
if (regularWeight > 0 && !regularScore.HasValue)
return null;
if (finalWeight > 0 && !finalScore.HasValue)
return null;
var itemWeightById = items.ToDictionary(item => item.Id, item => item.Weight);
foreach (var itemScore in itemScores)
{
if (itemWeightById.TryGetValue(itemScore.GradeItemId, out var weight) &&
weight > 0 && !itemScore.Score.HasValue)
return null;
}
var total = (regularScore ?? 0) * regularWeight / 100;
foreach (var itemScore in itemScores)
{
if (itemWeightById.TryGetValue(itemScore.GradeItemId, out var weight))
total += (itemScore.Score ?? 0) * weight / 100;
}
total += (finalScore ?? 0) * finalWeight / 100;
return Math.Round(total, 1, MidpointRounding.AwayFromZero);
}
public static decimal? CalculateGradePoint(decimal? totalScore)
{
if (!totalScore.HasValue) return null;
return totalScore.Value switch
{
>= 90 => 4.0m,
>= 85 => 3.7m,
>= 82 => 3.3m,
>= 78 => 3.0m,
>= 75 => 2.7m,
>= 72 => 2.3m,
>= 68 => 2.0m,
>= 64 => 1.5m,
>= 60 => 1.0m,
_ => 0m
};
}
}