158 lines
6.8 KiB
C#
158 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Project_Periodensystem.Model;
|
|
|
|
namespace Project_Periodensystem.Controller
|
|
{
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
public class ElementValidator
|
|
{
|
|
// Private readonly Liste der zu validierenden Elemente
|
|
// readonly = kann nach Initialisierung nicht mehr geändert werden
|
|
private readonly List<Element> _elements;
|
|
|
|
/// <summary>
|
|
/// Konstruktor - Initialisiert den Validator mit einer Element-Liste
|
|
/// </summary>
|
|
/// <param name="elements">Liste der zu validierenden Elemente</param>
|
|
public ElementValidator(List<Element> elements)
|
|
{
|
|
// Null-Check mit Fallback zu leerer Liste - verhindert NullReferenceExceptions
|
|
_elements = elements ?? new List<Element>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
/// <returns>true = alle Validierungen bestanden, false = Fehler gefunden</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
/// <param name="element">Das zu prüfende Element (kann null sein)</param>
|
|
/// <returns>true = Position ist gültig, false = Position ungültig oder Element ist null</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
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"}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|