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>
82 lines
3.4 KiB
C#
82 lines
3.4 KiB
C#
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Tests;
|
|
|
|
/// Tests für die Zielnoten-Frage (Nutzer-Feedback): "Was brauche ich noch, um Note X zu
|
|
/// erreichen?" — Umkehrung von GradingService.CalculateReportGrade.
|
|
public sealed class ReportGradeTargetCalculatorTests
|
|
{
|
|
private static readonly GradingScheme Scheme = new()
|
|
{
|
|
ExamsPercent = 50, ParticipationPercent = 30, OtherPercent = 20,
|
|
};
|
|
|
|
[Fact]
|
|
public void SolveRequiredAverage_LoestNachDemGesuchtenBereichAuf()
|
|
{
|
|
// Ziel 2,0; Mitarbeit 3,0 (30%), Sonstige 2,0 (20%) bekannt -> Klausuren (50%) gesucht.
|
|
// 2,0 * 100 = x*50 + 3,0*30 + 2,0*20 => 200 = 50x + 90 + 40 => x = 1,4
|
|
var result = ReportGradeTargetCalculator.SolveRequiredAverage(
|
|
2.0, GradeBucketKind.Exams, examsAverage: null, participationAverage: 3.0, otherAverage: 2.0,
|
|
Scheme, GradingSystem.Grades1To6);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(1.4, result!.Value.RequiredAverage, precision: 4);
|
|
Assert.True(result.Value.IsAchievable);
|
|
}
|
|
|
|
[Fact]
|
|
public void SolveRequiredAverage_IgnoriertBereicheOhneBekanntenDurchschnitt()
|
|
{
|
|
// Nur Klausuren (50%) bekannt, Mitarbeit gesucht (30%), Sonstige ohne Daten (fällt raus).
|
|
// Ziel 2,0 nur aus Klausuren(50%, Ø 2,0) + Mitarbeit(30%, gesucht) => Gesamtprozent 80.
|
|
// 2,0*80 = 2,0*50 + x*30 => 160 = 100 + 30x => x = 2,0
|
|
var result = ReportGradeTargetCalculator.SolveRequiredAverage(
|
|
2.0, GradeBucketKind.Participation, examsAverage: 2.0, participationAverage: null, otherAverage: null,
|
|
Scheme, GradingSystem.Grades1To6);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2.0, result!.Value.RequiredAverage, precision: 4);
|
|
}
|
|
|
|
[Fact]
|
|
public void SolveRequiredAverage_AusserhalbDesGueltigenBereichs_IstNichtErreichbar()
|
|
{
|
|
// Mitarbeit bereits sehr schlecht (5,5) -> selbst eine Traumnote in Klausuren reicht nicht für 1,5.
|
|
var result = ReportGradeTargetCalculator.SolveRequiredAverage(
|
|
1.5, GradeBucketKind.Exams, examsAverage: null, participationAverage: 5.5, otherAverage: null,
|
|
Scheme, GradingSystem.Grades1To6);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.False(result!.Value.IsAchievable);
|
|
}
|
|
|
|
[Fact]
|
|
public void SolveRequiredAverage_BereichOhneGewichtungsanteil_GibtNullZurueck()
|
|
{
|
|
var scheme = new GradingScheme { ExamsPercent = 100, ParticipationPercent = 0, OtherPercent = 0 };
|
|
|
|
var result = ReportGradeTargetCalculator.SolveRequiredAverage(
|
|
2.0, GradeBucketKind.Participation, examsAverage: 2.0, participationAverage: null, otherAverage: null,
|
|
scheme, GradingSystem.Grades1To6);
|
|
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void SolveRequiredAverage_FunktioniertAufDerPunkteskala()
|
|
{
|
|
// Punktesystem: höher ist besser. Ziel 12 Punkte, Mitarbeit 10 (30%), Sonstige 8 (20%)
|
|
// bekannt -> Klausuren (50%) gesucht. 12*100 = x*50+10*30+8*20 => 1200=50x+300+160 => x=14,8
|
|
var result = ReportGradeTargetCalculator.SolveRequiredAverage(
|
|
12.0, GradeBucketKind.Exams, examsAverage: null, participationAverage: 10.0, otherAverage: 8.0,
|
|
Scheme, GradingSystem.Points0To15);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(14.8, result!.Value.RequiredAverage, precision: 4);
|
|
Assert.True(result.Value.IsAchievable);
|
|
}
|
|
}
|