Files
LehrerApp/LehrerApp.Core/Services/ExamCoverSheetService.cs
T
adminandClaude Sonnet 5.5 41649b0a05 Förderschüler je Gruppe markieren und Förderarbeit darauf beschränken
GroupMembership.IsSupportStudent markiert Förderschüler unabhängig von der
Niveaudifferenzierung (Checkbox-Spalte in der Schülerliste; in differenzierten
Gruppen zählt das Förderniveau). Punkteeingabe und Deckblätter einer
Förderarbeit zeigen nur Förderschüler und Schüler mit vorhandenem Ergebnis.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:00:56 +02:00

64 lines
3.3 KiB
C#

using LehrerApp.Core.Models;
namespace LehrerApp.Core.Services;
/// <summary>Eine Spalte der Punktetabelle auf dem Klausur-Deckblatt. Bonusaufgaben tragen keine
/// Nummer; <see cref="AchievedPoints"/> ist null, solange nichts eingetragen werden soll.</summary>
public sealed record ExamCoverTaskColumn(string Number, double MaxPoints, bool IsBonus, double? AchievedPoints);
public static class ExamCoverSheetService
{
/// <summary>
/// Spalten für genau die Fassung, die der Schüler geschrieben hat. Nummeriert wird innerhalb
/// dieser Fassung (wie auf dem gedruckten Aufgabenblatt), Bonusaufgaben zählen nicht mit.
/// <paramref name="points"/> folgt wie <see cref="ExamResult.Points"/> der Reihenfolge aller
/// Aufgaben, nicht nur der dieser Fassung.
/// </summary>
public static List<ExamCoverTaskColumn> Columns(IReadOnlyList<ExamTask> orderedTasks, ExamVariant variant,
IReadOnlyList<double>? points)
{
var columns = new List<ExamCoverTaskColumn>();
var number = 0;
for (var index = 0; index < orderedTasks.Count; index++)
{
var task = orderedTasks[index];
if (!ExamScoringService.AppliesTo(task, variant)) continue;
double? achieved = points is null ? null : index < points.Count ? points[index] : 0;
columns.Add(new(task.IsBonus ? "" : (++number).ToString(), task.MaxPoints, task.IsBonus, achieved));
}
return columns;
}
/// <summary>Ein Ergebnis gilt als korrigiert, sobald Punkte oder eine Note eingetragen sind.</summary>
public static bool IsCorrected(ExamResult? result) =>
result is { Absent: false } && (result.Points.Count > 0 || !string.IsNullOrWhiteSpace(result.Grade));
}
/// <summary>Wer eine Arbeit mitschreibt — eine Regel für Punkteeingabe und Deckblätter.</summary>
public static class ExamParticipantService
{
/// <summary>Bei einer Nachschreib- oder Förderarbeit: Schüler, die die erste Arbeit bereits mit
/// Note geschrieben haben. Sonst leer.</summary>
public static HashSet<Guid> WroteOriginal(Exam exam, Func<Guid, List<ExamResult>> resultsByExam)
{
var wroteOriginal = new HashSet<Guid>();
if (exam.ReplacesMissingGrade() && exam.RepeatOfExamId is { } originalId)
foreach (var r in resultsByExam(originalId).Where(r => !r.Absent && r.Grade is not null))
wroteOriginal.Add(r.StudentId);
return wroteOriginal;
}
public static bool Includes(Exam exam, GroupMembership? membership, bool hasResult, bool wroteOriginal)
{
if (membership is not null && !GroupMembershipService.IsActiveOn(membership, exam.Date)) return false;
// Niveau-Klausur: nur Schüler mit passendem Niveau. Klausuren ohne Niveau-Zuordnung gelten
// weiterhin für die ganze Gruppe.
if (exam.Niveau.HasValue && membership?.Niveau != exam.Niveau) return false;
// Förderarbeit: nur Förderschüler (außer es gibt hier bereits ein Ergebnis).
if (exam.IsSupportWork && !hasResult && !GroupMembershipService.IsSupportStudent(membership)) return false;
// Nachschreib-/Förderarbeit: wer die erste Arbeit schon mit Note geschrieben hat, taucht nicht auf —
// außer es gibt hier bereits ein Ergebnis (nichts verstecken, was schon eingetragen wurde).
return hasResult || !wroteOriginal;
}
}