3.1.3: Aspekt-Typen Scale3/Binary/Points in Raster und Dialog unterstützt
Neue Klasse ParticipationRatingScale (Core) ist die einzige Quelle für Rohwerte je Aspekt-Typ. Scale3/Binary liegen bewusst direkt auf derselben -2..+2-Achse wie Scale5 (nur mit weniger Zwischenschritten), damit die bestehende Gewichtung/Mittelwertbildung zur Mitarbeitsnote unverändert kompatibel bleibt. Points ist grundverschieden (echter Zählwert 0..MaxPoints, neues Feld auf ParticipationAspect) und wird nur zur Aggregation linear auf dieselbe Achse normiert. Ohne diese Normierung hätte ein Punkte-Aspekt die Mitarbeitsnote verfälscht: drei Stellen summierten bisher den Rohwert direkt (ParticipationGradeDialog- ViewModel.Recompute, ParticipationWizardViewModels.WeightedRating und .ComputeSuggestion) - alle drei sind jetzt auf die Normierung umgestellt. Raster: Punkte-Aspekte zeigen ein NumericUpDown statt fester Stufen-Buttons. Schnelleingabe-Dialog: Zifferntasten/+/- sind jetzt typabhängig, Legende zeigt live die für den aktuellen Aspekt gültigen Tasten. Aspekt-Verwaltung um "Max. Punkte"-Feld ergänzt (nur bei Typ "Punkte" sichtbar). Bewusst nicht angefasst: die Trendlinien-Visualisierung im Mitarbeits-Assistenten bleibt fest auf die drei Standardaspekte zugeschnitten - eigener, größerer Umbau. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,9 @@ public class ParticipationAspect
|
||||
public string Key { get; set; } = "";
|
||||
public string Label { get; set; } = "";
|
||||
public AspectValueType ValueType { get; set; } = AspectValueType.Scale5;
|
||||
// Nur bei ValueType.Points relevant: die Rohbewertung ist dann ein echter Punktwert
|
||||
// 0..MaxPoints (nicht auf der -2..+2-Achse), siehe ParticipationRatingScale.
|
||||
public int MaxPoints { get; set; } = 5;
|
||||
public double Weight { get; set; } = 1.0;
|
||||
public bool IsActive { get; set; } = true;
|
||||
public int SortOrder { get; set; }
|
||||
@@ -113,3 +116,42 @@ public static class DefaultParticipationAspects
|
||||
new() { Key = "workphase", Label = "Arbeitsphase", ValueType = AspectValueType.Scale5, SortOrder = 2 },
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Definiert je <see cref="AspectValueType"/>, welche Rohwerte eine Bewertung annehmen kann und
|
||||
/// wie sie sich auf die gemeinsame Qualitätsachse (-2..+2, wie <see cref="AspectValueType.Scale5"/>)
|
||||
/// abbilden, auf der die Gewichtung/Mittelwertbildung zur Mitarbeitsnote (3.2) rechnet.
|
||||
/// Scale3/Binary liegen bewusst direkt AUF dieser Achse (nur mit weniger Zwischenschritten)
|
||||
/// statt einer eigenen Wertemenge zu bekommen — dadurch bleibt die bestehende Aggregation
|
||||
/// unverändert kompatibel, ohne pro Bewertung erst umrechnen zu müssen. Nur "Points" hat eine
|
||||
/// eigene, von der Lehrkraft festgelegte Obergrenze (<see cref="ParticipationAspect.MaxPoints"/>)
|
||||
/// und wird für die Aggregation linear auf dieselbe Achse normiert (0 → -2, MaxPoints → +2).
|
||||
/// </summary>
|
||||
public static class ParticipationRatingScale
|
||||
{
|
||||
/// Feste Rohwert/Label-Paare für Typen mit einer kleinen, festen Stufenzahl — Grundlage für
|
||||
/// Raster-Buttons und Schnelleingabe-Zifferntasten. Leer für Points (freie Zahleneingabe).
|
||||
public static IReadOnlyList<(int Value, string Label)> Steps(AspectValueType type) => type switch
|
||||
{
|
||||
AspectValueType.Scale5 => [(-2, "−−"), (-1, "−"), (0, "∼"), (1, "+"), (2, "++")],
|
||||
AspectValueType.Scale3 => [(-2, "−"), (0, "∼"), (2, "+")],
|
||||
AspectValueType.Binary => [(-2, "Nein"), (2, "Ja")],
|
||||
_ => [],
|
||||
};
|
||||
|
||||
public static string DisplayLabel(AspectValueType type, int? value)
|
||||
{
|
||||
if (value is null) return "·";
|
||||
if (type == AspectValueType.Points) return value.Value.ToString();
|
||||
var match = Steps(type).FirstOrDefault(s => s.Value == value.Value);
|
||||
return match.Label ?? "·";
|
||||
}
|
||||
|
||||
/// Bildet einen Rohwert auf die gemeinsame -2..+2-Achse ab, für die Mittelwertbildung in 3.2.
|
||||
public static double Normalize(AspectValueType type, int value, int maxPoints) => type switch
|
||||
{
|
||||
AspectValueType.Points when maxPoints > 0 => Math.Clamp(value, 0, maxPoints) / (double)maxPoints * 4.0 - 2.0,
|
||||
AspectValueType.Points => 0, // keine sinnvolle Obergrenze konfiguriert -> neutral werten
|
||||
_ => value,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user