using System; using System.Collections.Generic; using System.Linq; using Project_Periodensystem.Model; namespace Project_Periodensystem.Controller { /// /// ElementValidator - Spezialisierte Klasse für Datenvalidierung /// /// Diese Klasse wurde aus dem PeriodensystemController ausgelagert, um das /// Single Responsibility Principle (SRP) zu befolgen. Sie ist ausschließlich /// für die Validierung von Element-Daten zuständig. /// /// Vorteile der Auslagerung: /// - Bessere Testbarkeit (kann isoliert getestet werden) /// - Klarere Verantwortlichkeiten /// - Wiederverwendbarkeit in anderen Controllern /// - Einfachere Wartung und Erweiterung /// public class ElementValidator { // Private readonly Liste der zu validierenden Elemente // readonly = kann nach Initialisierung nicht mehr geändert werden private readonly List _elements; /// /// Konstruktor - Initialisiert den Validator mit einer Element-Liste /// /// Liste der zu validierenden Elemente public ElementValidator(List elements) { // Null-Check mit Fallback zu leerer Liste - verhindert NullReferenceExceptions _elements = elements ?? new List(); } /// /// Führt eine umfassende Validierung der Element-Daten durch. /// /// Diese Methode prüft verschiedene Datenintegritäts-Aspekte: /// 1. Existenz von Elementen (leere Liste = Problem) /// 2. Eindeutigkeit der Atomnummern (jede darf nur einmal vorkommen) /// 3. Vollständigkeit der Element-Symbole (keine leeren/null Werte) /// /// Verwendet moderne C# LINQ-Syntax für effiziente Datenabfragen: /// - GroupBy() für Gruppierung nach Atomnummer /// - Where() für Filterung /// - Any() für Existenzprüfung /// - Count() für Anzahl-Ermittlung /// /// true = alle Validierungen bestanden, false = Fehler gefunden public bool ValidateData() { // Erste Prüfung: Sind überhaupt Elemente vorhanden? // Any() ist effizienter als Count() > 0, da es beim ersten Element stoppt if (!_elements.Any()) { Logger.Log("Keine Elemente zum Validieren"); return false; } // Zweite Prüfung: Doppelte Atomnummern aufspüren // LINQ-Chain: GroupBy sammelt Elemente mit gleicher Atomnummer // Where filtert Gruppen mit mehr als einem Element (= Duplikate) // Select extrahiert nur die Atomnummer (Key) für Logging var duplicateNumbers = _elements.GroupBy(e => e.AtomicNumber) .Where(g => g.Count() > 1) .Select(g => g.Key); if (duplicateNumbers.Any()) { // string.Join() erstellt eine kommaseparierte Liste der doppelten Nummern Logger.Log($"Doppelte Atomnummern gefunden: {string.Join(", ", duplicateNumbers)}"); return false; } // Dritte Prüfung: Leere oder ungültige Element-Symbole finden // string.IsNullOrWhiteSpace() prüft auf null, leer oder nur Leerzeichen var emptySymbols = _elements.Where(e => string.IsNullOrWhiteSpace(e.Symbol)); if (emptySymbols.Any()) { Logger.Log($"Elemente mit leeren Symbolen gefunden: {emptySymbols.Count()}"); return false; } // Alle Validierungen bestanden Logger.Log("Datenvalidierung erfolgreich"); return true; } /// /// Validiert die Position eines Elements im Periodensystem. /// /// Das Periodensystem hat feste Dimensionen: /// - Zeilen (Perioden): 0-9 (insgesamt 10 Perioden) /// - Spalten (Gruppen): 0-17 (insgesamt 18 Gruppen) /// /// Diese Methode stellt sicher, dass Elemente nur an gültigen Positionen /// platziert werden. Ungültige Positionen würden zu Layout-Fehlern oder /// Abstürzen in der Benutzeroberfläche führen. /// /// Verwendet nullable Reference Types (Element?) - moderne C# 8.0+ Syntax /// /// Das zu prüfende Element (kann null sein) /// true = Position ist gültig, false = Position ungültig oder Element ist null public bool ValidateElementPosition(Element? element) { // Null-Check: Defensive Programmierung verhindert NullReferenceExceptions if (element == null) { Logger.Log("Element ist null"); return false; } // Positionsgrenzen prüfen: Standard-Periodensystem Layout // Row: 0-9 (Periode 1-10, aber 0-basiert indiziert) // Column: 0-17 (Gruppe 1-18, aber 0-basiert indiziert) if (element.Row < 0 || element.Row > 9 || element.Column < 0 || element.Column > 17) { Logger.Log($"Ungültige Position für {element.Symbol}: Row={element.Row}, Column={element.Column}"); return false; } return true; } /// /// Führt eine vollständige Validierungsprüfung aller Elemente durch und protokolliert Fehler. /// /// Diese Utility-Methode iteriert durch alle Elemente und prüft jedes einzeln. /// Hauptzweck ist das Debugging und die Qualitätssicherung: /// - Identifiziert problematische Elemente /// - Protokolliert detaillierte Fehlermeldungen /// - Hilfreich bei der Datenbereinigung /// /// Besonderheiten: /// - Verwendet null-conditional operator (?.) für sichere Navigation /// - Null-coalescing operator (??) für Fallback-Werte /// - Moderne C# Syntax für robuste Fehlerbehandlung /// public void LogValidationInfo() { // Iteriere durch alle Elemente und validiere jedes einzeln foreach (var element in _elements) { // Prüfe Position für jedes Element if (!ValidateElementPosition(element)) { // element?.Symbol verwendet null-conditional operator // Falls element null ist, wird Symbol nicht abgerufen -> kein Crash // ?? "NULL" ist ein Fallback falls Symbol null/leer ist Logger.Log($"VALIDIERUNGSFEHLER: {element?.Symbol ?? "NULL"}"); } } } } }