Files
LehrerApp/LehrerApp.Core/Services/ExamScoringService.cs
T

66 lines
3.0 KiB
C#

using LehrerApp.Core.Models;
namespace LehrerApp.Core.Services;
public static class ExamScoringService
{
public static bool AppliesTo(ExamTask task, ExamVariant variant) =>
task.Variant is null || task.Variant == variant;
public static double Maximum(IEnumerable<ExamTask> tasks, ExamVariant variant) =>
tasks.Where(t => AppliesTo(t, variant) && !t.IsBonus).Sum(t => t.MaxPoints);
public static double Achieved(IReadOnlyList<ExamTask> tasks, IReadOnlyList<double> points,
ExamVariant variant) => tasks.Select((task, index) =>
AppliesTo(task, variant) && index < points.Count ? points[index] : 0).Sum();
/// <summary>Wählt pro verknüpfter Wiederholung genau eine Note. Andere Arbeiten bleiben erhalten.</summary>
public static List<string> EffectiveGrades(IEnumerable<(Exam Exam, string Grade)> entries,
GradingSystem system)
{
var available = entries.ToList();
var byId = available.ToDictionary(x => x.Exam.Id);
var consumed = new HashSet<Guid>();
var result = new List<string>();
foreach (var entry in available)
{
if (!consumed.Add(entry.Exam.Id)) continue;
if (entry.Exam.RepeatOfExamId is { } originalId && byId.TryGetValue(originalId, out var original))
{
consumed.Add(originalId);
result.Add(Choose(original.Grade, entry.Grade, entry.Exam.RepeatGradeRule, system));
}
else if (available.FirstOrDefault(x => x.Exam.RepeatOfExamId == entry.Exam.Id) is var repeat
&& repeat.Exam is not null)
{
consumed.Add(repeat.Exam.Id);
result.Add(Choose(entry.Grade, repeat.Grade, repeat.Exam.RepeatGradeRule, system));
}
else result.Add(entry.Grade);
}
return result;
}
private static string Choose(string original, string repeat, RepeatGradeRule rule, GradingSystem system)
{
if (rule == RepeatGradeRule.Original) return original;
if (rule == RepeatGradeRule.Repeat) return repeat;
var first = GradeValue(original, system);
var second = GradeValue(repeat, system);
if (first is null || second is null) return original;
return system == GradingSystem.Grades1To6
? (second < first ? repeat : original)
: (second > first ? repeat : original);
}
private static double? GradeValue(string grade, GradingSystem system)
{
var core = grade.Trim();
var tendency = 0.0;
if (core.EndsWith('+')) { tendency = system == GradingSystem.Grades1To6 ? -1.0 / 3 : 1.0 / 3; core = core[..^1]; }
else if (core.EndsWith('-')) { tendency = system == GradingSystem.Grades1To6 ? 1.0 / 3 : -1.0 / 3; core = core[..^1]; }
return double.TryParse(core.Trim(), System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out var value) ? value + tendency : null;
}
}