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); } }