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>
64 lines
3.3 KiB
C#
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;
|
|
}
|
|
}
|