Zwei Bugs behoben: - Gefilterte Listen blieben nach Klick auf eine Roster-Zeile leer: WebUntis liefert Schülernamen je nach Bericht in unterschiedlicher Reihenfolge (Schülerreport "Vorname Nachname", Fehlzeiten-/Klassenbuchberichte "Nachname Vorname"). Neuer reihenfolge-unabhängiger Namensvergleich (UntisNameMatching), betraf auch den Roster-Namensabgleich der Übersicht selbst (Ampel-Symbole/Badges waren ohne ExternKey vermutlich fast immer falsch). - Nach dem ersten Tab-Wechsel (Klick auf Roster-Zeile) blieb ein zweiter Klick wirkungslos, sobald man zwischendurch manuell zur Übersicht zurückgeklickt hatte: TabbedPage.SelectedIndex war ohne Mode=TwoWay gebunden. Explizit ergänzt. Zusätzlich: Fehlzeiten-Zeilen für einen kompletten Fehltag werden jetzt dezent hervorgehoben (Nutzer-Feedback, bisher nicht erkennbar). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
23 lines
1.3 KiB
C#
23 lines
1.3 KiB
C#
namespace LehrerApp.Desktop.ViewModels.ClassTeacher;
|
|
|
|
/// <summary>
|
|
/// WebUntis liefert Schülernamen je nach Bericht in unterschiedlicher Reihenfolge — der
|
|
/// Schülerreport baut "Vorname Nachname" (<see cref="Services.UntisStudentDto.DisplayName"/>),
|
|
/// die Fehlzeiten-/Klassenbuchberichte liefern typischerweise "Nachname Vorname". Ein exakter
|
|
/// String-Vergleich zwischen diesen Quellen schlägt deshalb praktisch immer fehl (Bug: gefilterte
|
|
/// Listen im Klassenlehrer-Bereich blieben leer, Roster-Symbole waren durchgängig falsch). Der
|
|
/// Vergleich hier ist deshalb reihenfolge-unabhängig: beide Namen werden in Wörter zerlegt und als
|
|
/// sortierte Menge verglichen (kein Abgleich über eine externe Schülerkennung möglich, da der
|
|
/// Klassenbuch-Bericht keine liefert, siehe UntisForeignClassRegisterEventDto).
|
|
/// </summary>
|
|
public static class UntisNameMatching
|
|
{
|
|
public static bool NamesMatch(string? a, string? b) =>
|
|
!string.IsNullOrWhiteSpace(a) && !string.IsNullOrWhiteSpace(b) && NameKey(a) == NameKey(b);
|
|
|
|
public static string NameKey(string value) => string.Join(' ',
|
|
value.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(w => w.Trim().ToLowerInvariant())
|
|
.OrderBy(w => w, StringComparer.Ordinal));
|
|
}
|