LearningGroup.PreviousGroupId wird von GroupRolloverService jetzt automatisch gesetzt; neue Karte "Vorjahresvergleich" im Kurs-Tab Übersicht zeigt den gepoolten Klausurdurchschnitt neben dem der Vorgängergruppe, sobald dort Ergebnisse vorliegen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,12 +33,15 @@ public partial class GroupOverviewViewModel : ObservableObject
|
||||
|
||||
private readonly ILessonRepository _lessons;
|
||||
private readonly IExamRepository _exams;
|
||||
private readonly IExamResultRepository _examResults;
|
||||
private readonly IParticipationSessionRepository _sessions;
|
||||
private readonly IParticipationRepository _entries;
|
||||
private readonly IStudentRepository _students;
|
||||
private readonly IDocumentationRepository _documentation;
|
||||
private readonly IWorkTaskRepository _tasks;
|
||||
private readonly IGroupRepository _groups;
|
||||
private readonly AttendanceBalanceService _attendanceBalance;
|
||||
private readonly GradingService _grading;
|
||||
private readonly SchoolYearService _schoolYear;
|
||||
|
||||
private Guid _groupId;
|
||||
@@ -48,6 +51,8 @@ public partial class GroupOverviewViewModel : ObservableObject
|
||||
[ObservableProperty] private string _nextLessonLabel = "";
|
||||
[ObservableProperty] private bool _hasNextExam;
|
||||
[ObservableProperty] private string _nextExamLabel = "";
|
||||
[ObservableProperty] private bool _hasYearComparison;
|
||||
[ObservableProperty] private string _yearComparisonLabel = "";
|
||||
[ObservableProperty] private string _participationHintLabel = "";
|
||||
[ObservableProperty] private bool _participationHintIsStale;
|
||||
[ObservableProperty] private bool _hasOpenHomeworkCheck;
|
||||
@@ -105,13 +110,14 @@ public partial class GroupOverviewViewModel : ObservableObject
|
||||
}
|
||||
|
||||
public GroupOverviewViewModel(ILessonRepository lessons, IExamRepository exams,
|
||||
IParticipationSessionRepository sessions, IParticipationRepository entries,
|
||||
IStudentRepository students, IDocumentationRepository documentation, IWorkTaskRepository tasks,
|
||||
AttendanceBalanceService attendanceBalance, SchoolYearService schoolYear)
|
||||
IExamResultRepository examResults, IParticipationSessionRepository sessions,
|
||||
IParticipationRepository entries, IStudentRepository students,
|
||||
IDocumentationRepository documentation, IWorkTaskRepository tasks, IGroupRepository groups,
|
||||
AttendanceBalanceService attendanceBalance, GradingService grading, SchoolYearService schoolYear)
|
||||
{
|
||||
_lessons = lessons; _exams = exams; _sessions = sessions;
|
||||
_lessons = lessons; _exams = exams; _examResults = examResults; _sessions = sessions;
|
||||
_entries = entries; _students = students; _documentation = documentation; _tasks = tasks;
|
||||
_attendanceBalance = attendanceBalance; _schoolYear = schoolYear;
|
||||
_groups = groups; _attendanceBalance = attendanceBalance; _grading = grading; _schoolYear = schoolYear;
|
||||
}
|
||||
|
||||
public void Initialize(Guid groupId, string groupName)
|
||||
@@ -126,6 +132,7 @@ public partial class GroupOverviewViewModel : ObservableObject
|
||||
var today = DateOnly.FromDateTime(DateTime.Today);
|
||||
LoadNextLesson(today);
|
||||
LoadNextExam(today);
|
||||
LoadYearComparison();
|
||||
LoadParticipationHint(today);
|
||||
LoadOpenHomeworkCheck(today);
|
||||
LoadOpenExcuses(today);
|
||||
@@ -156,6 +163,38 @@ public partial class GroupOverviewViewModel : ObservableObject
|
||||
NextExamLabel = next is null ? "" : $"{next.Date:dd.MM.yyyy} — {next.Title}";
|
||||
}
|
||||
|
||||
// ── Klausurschnitt-Vorjahresvergleich (Nutzer-Feedback) ──────────────────
|
||||
//
|
||||
// Setzt voraus, dass diese Gruppe über GroupRolloverService aus einer Vorgängergruppe
|
||||
// hochgestuft wurde (LearningGroup.PreviousGroupId) — vor Einführung dieses Felds
|
||||
// hochgestufte Gruppen bleiben unverknüpft und zeigen keinen Vergleich. Nur sichtbar, wenn
|
||||
// im Vorjahr tatsächlich Klausurergebnisse vorliegen; ohne die ist kein Vergleich möglich,
|
||||
// auch wenn eine Verknüpfung besteht.
|
||||
|
||||
private void LoadYearComparison()
|
||||
{
|
||||
var group = _groups.GetById(_groupId);
|
||||
var previous = group?.PreviousGroupId is Guid previousId ? ComputeExamAverage(previousId) : null;
|
||||
if (previous is null) { HasYearComparison = false; return; }
|
||||
|
||||
var current = ComputeExamAverage(_groupId);
|
||||
YearComparisonLabel = current is null
|
||||
? $"Vorjahr: Ø {previous.Value.Average:0.0} ({previous.Value.Count} Klausuren) — dieses Jahr noch keine Klausur."
|
||||
: $"Dieses Jahr: Ø {current.Value.Average:0.0} ({current.Value.Count} Klausuren) · " +
|
||||
$"Vorjahr: Ø {previous.Value.Average:0.0} ({previous.Value.Count} Klausuren)";
|
||||
HasYearComparison = true;
|
||||
}
|
||||
|
||||
private (double Average, int Count)? ComputeExamAverage(Guid groupId)
|
||||
{
|
||||
var grades = _exams.GetByGroup(groupId)
|
||||
.SelectMany(e => _examResults.GetByExam(e.Id))
|
||||
.Where(r => !r.Absent && !string.IsNullOrWhiteSpace(r.Grade))
|
||||
.Select(r => (Grade: r.Grade!, Weight: 1.0))
|
||||
.ToList();
|
||||
return grades.Count == 0 ? null : (_grading.WeightedAverage(grades), grades.Count);
|
||||
}
|
||||
|
||||
/// Erinnert nicht an eine Note, sondern schlicht daran, überhaupt wieder eine Sitzung
|
||||
/// anzulegen — genau das vergisst man in Kursen, die man seltener unterrichtet, zuerst.
|
||||
private void LoadParticipationHint(DateOnly today)
|
||||
|
||||
@@ -66,6 +66,14 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Klausurschnitt-Vorjahresvergleich (Nutzer-Feedback) -->
|
||||
<Border Classes="card" IsVisible="{Binding HasYearComparison}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="VORJAHRESVERGLEICH" Classes="cardTitle"/>
|
||||
<TextBlock Text="{Binding YearComparisonLabel}" TextWrapping="Wrap" Classes="cardBody"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Mitarbeit -->
|
||||
<Border Classes="card">
|
||||
<StackPanel>
|
||||
|
||||
Reference in New Issue
Block a user