Tagesflagge im Sitzplan, Leistungsüberblick mit Zielnoten-Rechner
CI / build-and-test (push) Canceled after 0s
CI / build-and-test (push) Canceled after 0s
- Mitarbeit: Tagesflagge (👑 Spitzentag / 😴 Schlaftag / ⚡ Schlechter Tag) je Schüler und Sitzung. Primär im Sitzplatz-Dialog (⇧1/2/3, ⇧X) mit Badge auf der Sitzplatz-Kachel; Fallback in der Schnelleingabe für Lerngruppen ohne Sitzplan. - Noten: neuer Dialog "Überblick" in der Notenübersicht zeigt Klausuren, Mitarbeit- und sonstige Noten eines Schülers samt berechneter Zeugnisnote. Zielnoten-Rechner (ReportGradeTargetCalculator) beantwortet "was brauche ich noch für Note X", ein Was-wäre-wenn-Rechner simuliert eine zusätzliche Klausurnote. Bewerter-/Schülermodus per Umschalter im selben Fenster — Bewertermodus zeigt zusätzlich Kursdurchschnitt je Klausur und erlaubt das Bearbeiten von Mitarbeit-/Sonstige-Noten. Klausurverlauf als Balken-Sparkline wie die bestehende Notenentwicklung. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,9 +32,18 @@ public class ParticipationEntry
|
||||
// ParticipationCountSuggestion.
|
||||
public int RaisedHandCount { get; set; }
|
||||
public int CalledOnCount { get; set; }
|
||||
/// <summary>
|
||||
/// Tagesflagge (Nutzer-Feedback): markiert eine session-bezogene Bewertung als besonders
|
||||
/// herausragend oder besonders schwach, unabhängig von der Richtung ("egal in welche
|
||||
/// Richtung, herausragend festhalten"). Rein deskriptiv — fließt nirgends in eine Berechnung
|
||||
/// (Mitarbeitsnote 3.2, Aufrufgerechtigkeit) ein, nur zur Erinnerung/Dokumentation.
|
||||
/// </summary>
|
||||
public DayHighlightKind? DayHighlight { get; set; }
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public enum DayHighlightKind { Standout, Sleepy, Rough }
|
||||
|
||||
/// <summary>
|
||||
/// Hausaufgabenstatus einer Sitzung; null bedeutet, dass für diesen Termin keine
|
||||
/// Hausaufgabe erfasst wurde. MissingOpen kann später in MissingOverdue oder SubmittedLate
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using LehrerApp.Core.Models;
|
||||
|
||||
namespace LehrerApp.Core.Services;
|
||||
|
||||
/// Welcher der drei Leistungsbereiche (siehe GradingScheme) bei der Zielnoten-Frage der
|
||||
/// gesuchte/unbekannte ist.
|
||||
public enum GradeBucketKind { Exams, Participation, Other }
|
||||
|
||||
public readonly record struct TargetGradeResult(double RequiredAverage, bool IsAchievable);
|
||||
|
||||
/// <summary>
|
||||
/// Beantwortet die Zielnoten-Frage "Was brauche ich noch, um Zeugnisnote X zu erreichen?"
|
||||
/// (Nutzer-Feedback) — kehrt <see cref="GradingService.CalculateReportGrade"/> um: löst nach
|
||||
/// dem Durchschnitt eines gewählten Bereichs auf, der zusammen mit den bekannten Durchschnitten
|
||||
/// der übrigen Bereiche (gewichtet nach <see cref="GradingScheme"/>) genau die Zielnote ergibt.
|
||||
/// Bereiche ohne bekannten Durchschnitt (z.B. noch keine Mitarbeitsnote im Halbjahr) fließen
|
||||
/// nicht in die bekannte Seite der Gleichung ein — exakt dieselbe Normierung wie
|
||||
/// <see cref="GradingService.CalculateReportGrade"/> bei fehlenden Bereichen.
|
||||
/// </summary>
|
||||
public static class ReportGradeTargetCalculator
|
||||
{
|
||||
public static TargetGradeResult? SolveRequiredAverage(double target, GradeBucketKind solveFor,
|
||||
double? examsAverage, double? participationAverage, double? otherAverage,
|
||||
GradingScheme scheme, GradingSystem system)
|
||||
{
|
||||
var solvePercent = solveFor switch
|
||||
{
|
||||
GradeBucketKind.Exams => scheme.ExamsPercent,
|
||||
GradeBucketKind.Participation => scheme.ParticipationPercent,
|
||||
_ => scheme.OtherPercent,
|
||||
};
|
||||
// Dieser Bereich fließt laut Gewichtungsschema gar nicht in die Zeugnisnote ein —
|
||||
// keine Zielnoten-Frage für ihn beantwortbar.
|
||||
if (solvePercent <= 0) return null;
|
||||
|
||||
var known = new List<(double Avg, double Percent)>();
|
||||
if (solveFor != GradeBucketKind.Exams && examsAverage is { } e) known.Add((e, scheme.ExamsPercent));
|
||||
if (solveFor != GradeBucketKind.Participation && participationAverage is { } p) known.Add((p, scheme.ParticipationPercent));
|
||||
if (solveFor != GradeBucketKind.Other && otherAverage is { } o) known.Add((o, scheme.OtherPercent));
|
||||
|
||||
var totalPercent = known.Sum(k => k.Percent) + solvePercent;
|
||||
var knownContribution = known.Sum(k => k.Avg * k.Percent);
|
||||
var required = (target * totalPercent - knownContribution) / solvePercent;
|
||||
|
||||
var (min, max) = system == GradingSystem.Grades1To6 ? (1.0, 6.0) : (0.0, 15.0);
|
||||
return new TargetGradeResult(required, required >= min && required <= max);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user