66 lines
3.0 KiB
C#
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;
|
|
}
|
|
}
|