Compare commits

..

2 Commits

Author SHA1 Message Date
5654ed83ea no changes 2025-06-30 15:30:55 +02:00
60f83f9182 Finished 2025-06-30 15:30:41 +02:00
6 changed files with 171 additions and 347 deletions

0
KOMMENTIERUNGS-STATUS.md Normal file
View File

View File

@ -48,6 +48,18 @@ namespace Project_Periodensystem.Controller
_elements = elements ?? new List<Element>(); _elements = elements ?? new List<Element>();
} }
/// <summary>
/// Extrahiert alle Atomgewichte als Array - demonstriert klassische Array-Erstellung
///
/// C# KONZEPTE:
/// - Array-Initialisierung: new double[size]
/// - For-Schleife: Imperative Programmierung
/// - Property-Zugriff: element.AtomicWeight
///
/// ALTERNATIVE (LINQ): return _elements.Select(e => e.AtomicWeight).ToArray();
/// Zeigt Unterschied zwischen imperativem und funktionalem Stil
/// </summary>
/// <returns>Array aller Atomgewichte in g/mol</returns>
public double[] GetAtomicWeights() public double[] GetAtomicWeights()
{ {
double[] weights = new double[_elements.Count]; double[] weights = new double[_elements.Count];
@ -58,6 +70,17 @@ namespace Project_Periodensystem.Controller
return weights; return weights;
} }
/// <summary>
/// Berechnet das durchschnittliche Atomgewicht aller Elemente
///
/// C# KONZEPTE:
/// - Early Return Pattern: if (!_elements.Any()) return 0.0;
/// - Method Reuse: Nutzt GetAtomicWeights()
/// - Klassische Iteration: for-Schleife für Summe
///
/// MATHEMATIK: Arithmetisches Mittel = Summe / Anzahl
/// </summary>
/// <returns>Durchschnittliches Atomgewicht oder 0.0 bei leerer Liste</returns>
public double GetAverageAtomicWeight() public double GetAverageAtomicWeight()
{ {
if (!_elements.Any()) return 0.0; if (!_elements.Any()) return 0.0;
@ -71,15 +94,39 @@ namespace Project_Periodensystem.Controller
return sum / weights.Length; return sum / weights.Length;
} }
/// <summary>
/// Sammelt alle einzigartigen Element-Serien - demonstriert LINQ-Pipeline
///
/// C# KONZEPTE:
/// - LINQ Select(): Projektion (e => e.Series)
/// - LINQ Distinct(): Entfernt Duplikate
/// - LINQ Where(): Filtert leere/null Werte
/// - LINQ OrderBy(): Alphabetische Sortierung
/// - Method Chaining: Verkettung mehrerer Operationen
///
/// RÜCKGABE: Sortierte Liste aller chemischen Serien
/// </summary>
/// <returns>Liste aller Element-Serien (Alkalimetall, Edelgas, etc.)</returns>
public List<string> GetAllSeries() public List<string> GetAllSeries()
{ {
return _elements.Select(e => e.Series) return _elements.Select(e => e.Series) // Projektion
.Distinct() .Distinct() // Duplikate entfernen
.Where(s => !string.IsNullOrWhiteSpace(s)) .Where(s => !string.IsNullOrWhiteSpace(s)) // Null/Empty filtern
.OrderBy(s => s) .OrderBy(s => s) // Alphabetisch sortieren
.ToList(); .ToList(); // Zu Liste konvertieren
} }
/// <summary>
/// Sammelt wichtige Statistiken in einem Tuple - demonstriert strukturierte Rückgaben
///
/// C# KONZEPTE:
/// - Tuple Return Type: (int, int, double)
/// - Method Delegation: Ruft andere Methoden auf
/// - Tuple Creation: (value1, value2, value3)
///
/// VERWENDUNG: var (total, series, avg) = statistics.GetStatistics();
/// </summary>
/// <returns>Tuple mit (Anzahl Elemente, Anzahl Serien, Durchschnittsgewicht)</returns>
public (int totalElements, int uniqueSeries, double avgWeight) GetStatistics() public (int totalElements, int uniqueSeries, double avgWeight) GetStatistics()
{ {
var seriesCount = GetAllSeries().Count; var seriesCount = GetAllSeries().Count;
@ -88,6 +135,18 @@ namespace Project_Periodensystem.Controller
return (_elements.Count, seriesCount, avgWeight); return (_elements.Count, seriesCount, avgWeight);
} }
/// <summary>
/// Findet das leichteste und schwerste Element - demonstriert LINQ Ordering
///
/// C# KONZEPTE:
/// - LINQ OrderBy() / OrderByDescending(): Sortierung
/// - LINQ First(): Erstes Element nach Sortierung
/// - Tuple mit nullable Types: (Element?, Element?)
/// - Guard Clause: Early return bei leerer Liste
///
/// CHEMIE: Wasserstoff ist leichtestes (1.008), schwerste variieren
/// </summary>
/// <returns>Tuple mit (leichtestes Element, schwerstes Element) oder (null, null)</returns>
public (Element? lightest, Element? heaviest) GetWeightExtremes() public (Element? lightest, Element? heaviest) GetWeightExtremes()
{ {
if (!_elements.Any()) return (null, null); if (!_elements.Any()) return (null, null);
@ -98,6 +157,18 @@ namespace Project_Periodensystem.Controller
return (lightest, heaviest); return (lightest, heaviest);
} }
/// <summary>
/// Extrahiert Element-Informationen nach Ordnungszahl - demonstriert Tuple-basierte APIs
///
/// C# KONZEPTE:
/// - LINQ FirstOrDefault(): Sichere Suche (kann null zurückgeben)
/// - Conditional Operator: condition ? trueValue : falseValue
/// - Tuple mit Mixed Types: (string, string, double)
///
/// FALLBACK: Bei nicht gefundenem Element ("?", "Unknown", 0.0)
/// </summary>
/// <param name="atomicNumber">Ordnungszahl des gesuchten Elements (1-118)</param>
/// <returns>Tuple mit (Symbol, Name, Atomgewicht)</returns>
public (string symbol, string name, double weight) GetElementInfo(int atomicNumber) public (string symbol, string name, double weight) GetElementInfo(int atomicNumber)
{ {
var element = _elements.FirstOrDefault(e => e.AtomicNumber == atomicNumber); var element = _elements.FirstOrDefault(e => e.AtomicNumber == atomicNumber);
@ -106,6 +177,18 @@ namespace Project_Periodensystem.Controller
: ("?", "Unknown", 0.0); : ("?", "Unknown", 0.0);
} }
/// <summary>
/// Ermittelt die Position eines Elements im Periodensystem-Grid
///
/// C# KONZEPTE:
/// - Konsistente API: Gleiche Suchmuster wie GetElementInfo()
/// - Tuple für Koordinaten: (int row, int column)
/// - Fallback-Werte: (-1, -1) für "nicht gefunden"
///
/// VERWENDUNG: var (row, col) = statistics.GetElementPosition(1); // Wasserstoff
/// </summary>
/// <param name="atomicNumber">Ordnungszahl des gesuchten Elements</param>
/// <returns>Tuple mit (Zeile, Spalte) oder (-1, -1) wenn nicht gefunden</returns>
public (int row, int column) GetElementPosition(int atomicNumber) public (int row, int column) GetElementPosition(int atomicNumber)
{ {
var element = _elements.FirstOrDefault(e => e.AtomicNumber == atomicNumber); var element = _elements.FirstOrDefault(e => e.AtomicNumber == atomicNumber);

View File

@ -7,42 +7,21 @@ using Project_Periodensystem.Persistence;
namespace Project_Periodensystem.Controller namespace Project_Periodensystem.Controller
{ {
/// <summary> /// <summary>
/// Haupt-Controller für das Periodensystem - implementiert das MVC-Pattern /// Haupt-Controller für das Periodensystem - implementiert MVC-Pattern.
/// /// Koordiniert Geschäftslogik zwischen View und Model/Persistence.
/// ZWECK UND ARCHITEKTUR: /// Delegiert komplexe Aufgaben an spezialisierte Helper-Klassen.
/// - Zentrale Kontrollschicht zwischen View (UI) und Model/Persistence (Daten)
/// - Koordiniert alle Geschäftslogik-Operationen für das Periodensystem
/// - Delegiert komplexe Aufgaben an spezialisierte Helper-Klassen (Single Responsibility Principle)
/// - Bietet eine einheitliche API für alle UI-Komponenten
///
/// DESIGN PATTERN:
/// - MVC (Model-View-Controller): Trennt Präsentation von Geschäftslogik
/// - Delegation Pattern: Überträgt Verantwortlichkeiten an spezialisierte Klassen
/// - Dependency Injection: Nimmt INavigationService als abhängige Komponente entgegen
///
/// C# KONZEPTE:
/// - Nullable Reference Types (INavigationService?, ElementValidator?)
/// - LINQ für Datenoperationen (FirstOrDefault, Where, ToArray)
/// - Exception Handling mit try-catch-Blöcken
/// - Lambda Expressions für Delegation an Helper-Klassen
/// - Tuple-Rückgabewerte für strukturierte Daten
/// </summary> /// </summary>
public class PeriodensystemController public class PeriodensystemController
{ {
// ===== PRIVATE FELDER ===== // ===== PRIVATE FELDER =====
/// <summary> /// <summary>
/// Zentrale Liste aller chemischen Elemente /// Liste aller chemischen Elemente
/// List&lt;T&gt; ermöglicht dynamisches Hinzufügen/Entfernen von Elementen
/// Private Field mit Underscore-Notation (_elements) nach C#-Konvention
/// </summary> /// </summary>
private List<Element> _elements = new List<Element>(); private List<Element> _elements = new List<Element>();
/// <summary> /// <summary>
/// Navigation Service für Seitenwechsel in der Avalonia-Anwendung /// Navigation Service für Seitenwechsel (optional, da Interface-basiert)
/// Readonly: Kann nur im Konstruktor zugewiesen werden (Immutability)
/// Nullable (?): Kann null sein, da Navigation optional ist
/// Interface-basiert: Ermöglicht verschiedene Implementierungen (Dependency Inversion)
/// </summary> /// </summary>
private readonly INavigationService? _navigationService; private readonly INavigationService? _navigationService;
@ -63,22 +42,8 @@ namespace Project_Periodensystem.Controller
private ElementStatistics? _statistics; private ElementStatistics? _statistics;
// ===== KONSTRUKTOR ===== // ===== KONSTRUKTOR =====
/// <summary> /// <summary>
/// Konstruktor mit optionaler Dependency Injection /// Konstruktor mit optionaler Navigation
///
/// PARAMETER:
/// - navigationService: Optional (null by default), ermöglicht Navigation zwischen Seiten
///
/// C# FEATURES:
/// - Default Parameter (= null): Macht den Parameter optional
/// - Nullable Reference Types: navigationService kann null sein
/// - Constructor Chaining: Ruft LoadElements() zur Initialisierung auf
///
/// ABLAUF:
/// 1. Navigation Service speichern (kann null sein)
/// 2. Elemente aus Persistence-Layer laden
/// 3. Helper-Klassen mit geladenen Daten initialisieren
/// </summary> /// </summary>
public PeriodensystemController(INavigationService? navigationService = null) public PeriodensystemController(INavigationService? navigationService = null)
{ {
@ -86,52 +51,28 @@ namespace Project_Periodensystem.Controller
LoadElements(); // Daten sofort beim Erstellen laden LoadElements(); // Daten sofort beim Erstellen laden
} }
// ===== PRIVATE INITIALISIERUNGSMETHODEN =====
/// <summary> /// <summary>
/// Lädt alle chemischen Elemente aus dem Persistence-Layer /// Lädt alle chemischen Elemente und initialisiert Helper-Klassen
///
/// ZWECK:
/// - Zentrale Initialisierung aller Elementdaten
/// - Fehlerbehandlung beim Laden der Daten
/// - Initialisierung der Helper-Klassen nach erfolgreichem Laden
/// - Ausführliches Logging für Debugging und Monitoring
///
/// C# KONZEPTE:
/// - Exception Handling: try-catch für robuste Fehlerbehandlung
/// - LINQ: Take(10) für die ersten 10 Elemente
/// - Tuple Deconstruction: (totalElements, uniqueSeries, avgWeight) = GetStatistics()
/// - Null-Conditional Operator: lightest?.Symbol verhindert NullReferenceException
/// - String Interpolation: $"Text {variable}" für lesbare Ausgaben
///
/// FEHLERBEHANDLUNG:
/// - Bei Exceptions wird eine leere Liste initialisiert (Graceful Degradation)
/// - Alle Fehler werden geloggt für spätere Analyse
/// </summary> /// </summary>
private void LoadElements() private void LoadElements()
{ {
try try
{ {
// Elemente aus DataManager laden (Persistence Layer) // Elemente aus DataManager laden
_elements = DataManager.LoadElements(); _elements = DataManager.LoadElements();
Logger.Log($"Controller: {_elements.Count} Elemente erfolgreich geladen (via DataManager)"); Logger.Log($"Controller: {_elements.Count} Elemente erfolgreich geladen");
// Helper-Klassen mit den geladenen Daten initialisieren // Helper-Klassen initialisieren
// Delegation Pattern: Spezialisierte Klassen für verschiedene Aufgaben
_validator = new ElementValidator(_elements); _validator = new ElementValidator(_elements);
_statistics = new ElementStatistics(_elements); _statistics = new ElementStatistics(_elements);
// ===== DEMONSTRATIVE LOGGING VON C#-FEATURES ===== // Demonstrative Logging der geladenen Daten
// Arrays: Alle Element-Symbole als Array
var symbols = GetAllSymbols(); var symbols = GetAllSymbols();
Logger.LogArray("Element-Symbole (erste 10)", symbols.Take(10).ToArray()); Logger.LogArray("Element-Symbole (erste 10)", symbols.Take(10).ToArray());
// Tuples: Strukturierte Rückgabe mehrerer Werte
var (totalElements, uniqueSeries, avgWeight) = GetStatistics(); var (totalElements, uniqueSeries, avgWeight) = GetStatistics();
Logger.LogTuple("Statistiken", $"Elemente: {totalElements}, Serien: {uniqueSeries}, Ø-Gewicht: {avgWeight:F2}"); Logger.LogTuple("Statistiken", $"Elemente: {totalElements}, Serien: {uniqueSeries}, Ø-Gewicht: {avgWeight:F2}");
// Tuples mit Objekten: Extremwerte finden
var (lightest, heaviest) = GetWeightExtremes(); var (lightest, heaviest) = GetWeightExtremes();
if (lightest != null && heaviest != null) if (lightest != null && heaviest != null)
{ {

View File

@ -1,76 +1,25 @@
namespace Project_Periodensystem.Model namespace Project_Periodensystem.Model
{ {
/// <summary> /// <summary>
/// Repräsentiert ein chemisches Element im Periodensystem /// Repräsentiert ein chemisches Element im Periodensystem.
/// /// Zentrale Datenstruktur für alle Elementinformationen und -eigenschaften.
/// ZWECK UND DATENMODELL:
/// - Zentrale Datenstruktur für alle Elementinformationen
/// - Kapselt alle relevanten chemischen Eigenschaften
/// - Bildet die Grundlage für Periodensystem-Darstellung und -Berechnungen
///
/// DESIGN PRINCIPLES:
/// - Data Transfer Object (DTO): Reine Datenklasse ohne Geschäftslogik
/// - Immutable nach Konstruktion: Alle Properties haben nur Setter (könnten readonly sein)
/// - Rich Object: Enthält alle relevanten Eigenschaften in einer Klasse
///
/// C# KONZEPTE:
/// - Auto-Properties: { get; set; } automatische Getter/Setter
/// - Constructor mit mehreren Parametern: Vollständige Initialisierung
/// - Value Types (int, double): Primitive Datentypen für Zahlen
/// - Reference Types (string): Referenzdatentypen für Text
///
/// VERWENDUNG IM PERIODENSYSTEM:
/// - Gespeichert in List&lt;Element&gt; Collections
/// - Sortiert nach AtomicNumber für Periodensystem-Darstellung
/// - Gruppiert nach Series für chemische Klassifizierung
/// - Positioniert nach Row/Column im UI-Grid
/// </summary> /// </summary>
public class Element public class Element
{ {
// ===== IDENTIFIKATIONS-EIGENSCHAFTEN ===== // ===== IDENTIFIKATIONS-EIGENSCHAFTEN =====
/// <summary> /// <summary>
/// Ordnungszahl (Protonenzahl) des Elements /// Ordnungszahl (Protonenzahl) des Elements - eindeutige Identifikation (1-118)
///
/// CHEMISCHE BEDEUTUNG:
/// - Eindeutige Identifikation jedes Elements (1-118)
/// - Bestimmt Position im Periodensystem
/// - Entspricht der Anzahl Protonen im Atomkern
///
/// BEISPIELE:
/// - 1 = Wasserstoff (H)
/// - 6 = Kohlenstoff (C)
/// - 79 = Gold (Au)
/// </summary> /// </summary>
public int AtomicNumber { get; set; } public int AtomicNumber { get; set; }
/// <summary> /// <summary>
/// Chemisches Symbol (Kurzbezeichnung) des Elements /// Chemisches Symbol (z.B. H, C, Au) - kurze Bezeichnung (1-2 Buchstaben)
///
/// KONVENTIONEN:
/// - 1-2 Buchstaben, erster Buchstabe groß
/// - Oft lateinischen/griechischen Ursprungs
/// - International standardisiert (IUPAC)
///
/// BEISPIELE:
/// - "H" = Hydrogen (Wasserstoff)
/// - "Au" = Aurum (Gold)
/// - "Fe" = Ferrum (Eisen)
/// </summary> /// </summary>
public string Symbol { get; set; } public string Symbol { get; set; }
/// <summary> /// <summary>
/// Vollständiger wissenschaftlicher Name des Elements /// Vollständiger wissenschaftlicher Name des Elements
///
/// NAMENSGEBUNG:
/// - Offizielle IUPAC-Bezeichnung
/// - Meist englische Namen in der internationalen Wissenschaft
/// - Historische, mythologische oder wissenschaftliche Herkunft
///
/// BEISPIELE:
/// - "Hydrogen" (griechisch: Wasser-bildend)
/// - "Californium" (nach Kalifornien benannt)
/// - "Einstein­ium" (nach Albert Einstein)
/// </summary> /// </summary>
public string ElementName { get; set; } public string ElementName { get; set; }
@ -78,154 +27,62 @@ namespace Project_Periodensystem.Model
/// <summary> /// <summary>
/// Relative Atommasse in atomaren Masseneinheiten (u) /// Relative Atommasse in atomaren Masseneinheiten (u)
///
/// CHEMISCHE BEDEUTUNG:
/// - Durchschnittliche Masse aller Isotope eines Elements
/// - Gewichtet nach natürlicher Häufigkeit der Isotope
/// - Basis für stöchiometrische Berechnungen
///
/// EINHEIT: u (atomic mass unit)
/// - 1 u ≈ 1.66054 × 10⁻²⁷ kg
/// - Relative Skala (Kohlenstoff-12 = 12.000 u)
///
/// BEISPIELE:
/// - Wasserstoff: ~1.008 u
/// - Kohlenstoff: ~12.011 u
/// - Uran: ~238.029 u
/// </summary> /// </summary>
public double AtomicWeight { get; set; } public double AtomicWeight { get; set; }
/// <summary> /// <summary>
/// Elektronegativität nach Pauling-Skala /// Elektronegativität nach Pauling-Skala (0.7 bis 4.0)
///
/// CHEMISCHE BEDEUTUNG:
/// - Fähigkeit eines Atoms, Bindungselektronen anzuziehen
/// - Bestimmt Art der chemischen Bindung (ionisch vs. kovalent)
/// - Wichtig für Vorhersage chemischer Reaktionen
///
/// PAULING-SKALA:
/// - Dimensionslose Größe von 0.7 bis 4.0
/// - Fluor hat den höchsten Wert (4.0)
/// - Trends: Steigt in Perioden von links nach rechts
///
/// BEISPIELE:
/// - Fluor: 4.0 (höchste Elektronegativität)
/// - Sauerstoff: 3.5
/// - Wasserstoff: 2.1
/// - Cäsium: 0.7 (niedrigste)
/// </summary> /// </summary>
public double Electronegativity { get; set; } public double Electronegativity { get; set; }
/// <summary> /// <summary>
/// Dichte bei Standardbedingungen in g/cm³ /// Dichte bei Standardbedingungen in g/cm³
///
/// PHYSIKALISCHE BEDEUTUNG:
/// - Masse pro Volumeneinheit
/// - Abhängig von Atomgröße und Kristallstruktur
/// - Wichtig für technische Anwendungen
///
/// TRENDS IM PERIODENSYSTEM:
/// - Generell zunehmend mit steigender Ordnungszahl
/// - Maximum bei Osmium (~22.6 g/cm³)
/// - Gase haben sehr geringe Dichten
///
/// BEISPIELE:
/// - Wasserstoff (Gas): ~0.0000899 g/cm³
/// - Wasser (Referenz): 1.0 g/cm³
/// - Gold: ~19.3 g/cm³
/// - Osmium: ~22.6 g/cm³ (dichtestes Element)
/// </summary> /// </summary>
public double Density { get; set; } public double Density { get; set; }
// ===== KLASSIFIKATIONS-EIGENSCHAFTEN ===== // ===== KLASSIFIKATIONS-EIGENSCHAFTEN =====
/// <summary> /// <summary>
/// Chemische Serie/Gruppe des Elements /// Chemische Serie/Gruppe für Klassifikation und UI-Farbkodierung
///
/// KLASSIFIKATION:
/// - Gruppiert Elemente nach ähnlichen chemischen Eigenschaften
/// - Basis für Periodensystem-Farben und -Organisation
/// - Ermöglicht Vorhersage chemischen Verhaltens
///
/// WICHTIGE SERIEN:
/// - "Alkali metal": Li, Na, K, Rb, Cs, Fr (sehr reaktiv)
/// - "Noble gas": He, Ne, Ar, Kr, Xe, Rn (inert)
/// - "Halogen": F, Cl, Br, I, At (7 Valenzelektronen)
/// - "Transition metal": Fe, Cu, Au, etc. (d-Block)
/// - "Lanthanoid": Seltene Erden (f-Block)
///
/// UI-VERWENDUNG:
/// - Farbkodierung im Periodensystem
/// - Filterung und Gruppierung
/// - Tooltip-Informationen
/// </summary> /// </summary>
public string Series { get; set; } public string Series { get; set; }
// ===== POSITIONIERUNGS-EIGENSCHAFTEN =====
/// <summary> /// <summary>
/// Zeile (Periode) im Periodensystem /// Zeile (Periode) im Periodensystem (1-7)
///
/// CHEMISCHE BEDEUTUNG:
/// - Entspricht der Anzahl Elektronenschalen
/// - Bestimmt vertikale Position im Periodensystem
/// - 1-7 für natürliche Elemente
///
/// TRENDS:
/// - Atomradius nimmt innerhalb einer Periode ab
/// - Ionisierungsenergie steigt innerhalb einer Periode
/// </summary> /// </summary>
public int Row { get; set; } public int Row { get; set; }
/// <summary> /// <summary>
/// Spalte (Gruppe) im Periodensystem /// Spalte (Gruppe) im Periodensystem (1-18)
///
/// CHEMISCHE BEDEUTUNG:
/// - Entspricht der Anzahl Valenzelektronen (vereinfacht)
/// - Bestimmt horizontale Position im Periodensystem
/// - 1-18 nach IUPAC-Nummerierung
///
/// TRENDS:
/// - Elemente derselben Gruppe haben ähnliche Eigenschaften
/// - Chemische Reaktivität folgt Gruppenmustern
/// </summary> /// </summary>
public int Column { get; set; } public int Column { get; set; }
// ===== KONSTRUKTOR ===== // ===== KONSTRUKTOR =====
/// <summary> /// <summary>
/// Vollständiger Konstruktor für die Erstellung eines Element-Objekts /// Konstruktor - erstellt Element-Objekt mit allen erforderlichen Eigenschaften
///
/// ZWECK:
/// - Stellt sicher, dass alle Eigenschaften beim Erstellen gesetzt werden
/// - Verhindert unvollständig initialisierte Element-Objekte
/// - Ermöglicht direkte Erstellung aus Datenquellen (CSV, JSON, Database)
///
/// C# KONZEPTE:
/// - Constructor Overloading: Könnte mehrere Konstruktoren haben
/// - Parameter Validation: Könnte Validierung der Eingabewerte enthalten
/// - Immutable Object: Nach Konstruktion unveränderlich (wenn Properties readonly wären)
///
/// PARAMETER:
/// - Alle 9 Eigenschaften müssen beim Erstellen angegeben werden
/// - Reihenfolge entspricht logischer Gruppierung (ID, Name, Physik, Position)
///
/// VERWENDUNG:
/// var hydrogen = new Element(1, "H", "Hydrogen", 1.008, 2.1, 0.0000899, "Nonmetal", 1, 1);
/// </summary> /// </summary>
/// <param name="atomicNumber">Ordnungszahl (1-118)</param>
/// <param name="symbol">Chemisches Symbol (z.B. "H", "Au")</param>
/// <param name="elementname">Vollständiger Elementname</param>
/// <param name="atomicWeight">Atommasse in u</param>
/// <param name="electronegativity">Elektronegativität (Pauling-Skala)</param>
/// <param name="density">Dichte in g/cm³</param>
/// <param name="series">Chemische Serie/Gruppe</param>
/// <param name="row">Periodensystem-Zeile</param>
/// <param name="column">Periodensystem-Spalte</param>
public Element(int atomicNumber, string symbol, string elementname, double atomicWeight, public Element(int atomicNumber, string symbol, string elementname, double atomicWeight,
double electronegativity, double density, string series, int row, int column) double electronegativity, double density, string series, int row, int column)
{ {
// Eigenschafts-Zuweisungen mit Selbst-Dokumentation AtomicNumber = atomicNumber;
AtomicNumber = atomicNumber; // Eindeutige Identifikation Symbol = symbol;
Symbol = symbol; // Kurze chemische Bezeichnung ElementName = elementname;
ElementName = elementname; // Vollständiger Name AtomicWeight = atomicWeight;
AtomicWeight = atomicWeight; // Relative Atommasse Electronegativity = electronegativity;
Electronegativity = electronegativity; // Bindungsverhalten Density = density;
Density = density; // Physikalische Eigenschaft Series = series;
Series = series; // Chemische Klassifikation Row = row;
Row = row; // Periodensystem-Position vertikal Column = column;
Column = column; // Periodensystem-Position horizontal
} }
} }
} }

View File

@ -6,26 +6,43 @@ using Project_Periodensystem.Controller;
namespace Project_Periodensystem.View namespace Project_Periodensystem.View
{ {
/// <summary> /// <summary>
/// MainWindow mit sauberem MVC-Pattern und Interface-basierter Navigation /// Hauptfenster der Avalonia-Anwendung - implementiert MVC-Pattern.
/// Koordiniert NavigationService und PeriodensystemController.
/// Löst zirkuläre Abhängigkeiten durch zweistufige Initialisierung.
/// </summary> /// </summary>
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
/// <summary>
/// Hauptbereich für Seitenwechsel zwischen PeriodicTablePage, AboutPage, etc.
/// </summary>
private ContentControl? mainContent; private ContentControl? mainContent;
/// <summary>
/// Zentrale Geschäftslogik für Periodensystem-Daten und -Operationen
/// </summary>
private readonly PeriodensystemController _dataController; private readonly PeriodensystemController _dataController;
/// <summary>
/// Service für Navigation zwischen verschiedenen Anwendungsseiten
/// </summary>
private readonly NavigationService _navigationService; private readonly NavigationService _navigationService;
/// <summary>
/// Konstruktor - initialisiert Avalonia-Komponenten und MVC-Architektur
/// </summary>
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent(); // Avalonia UI initialisieren
mainContent = this.FindControl<ContentControl>("MainContent"); mainContent = this.FindControl<ContentControl>("MainContent");
// Erstelle Navigation Service mit this (MainWindow) // Zweistufige Initialisierung wegen zirkulärer Abhängigkeiten:
// 1. NavigationService mit MainWindow erstellen
_navigationService = new NavigationService(this); _navigationService = new NavigationService(this);
// Controller mit Navigation Service initialisieren (Dependency Injection) // 2. Controller mit NavigationService erstellen
_dataController = new PeriodensystemController(_navigationService); _dataController = new PeriodensystemController(_navigationService);
// Data Controller an Navigation Service setzen // 3. Controller an NavigationService zurückgeben (löst Zirkularität)
_navigationService.SetDataController(_dataController); _navigationService.SetDataController(_dataController);
// Landing Page anzeigen // Landing Page anzeigen

View File

@ -8,130 +8,48 @@ using Project_Periodensystem.Controller;
namespace Project_Periodensystem.View namespace Project_Periodensystem.View
{ {
/// <summary> /// <summary>
/// Concrete Implementation des Navigation Service für Avalonia UI /// Implementiert die Navigation zwischen verschiedenen Seiten der Avalonia-Anwendung.
/// /// Trennt die Navigation-Logik (WAS) vom UI-Framework (WIE) durch Interface-Implementation.
/// ZWECK UND ARCHITEKTUR: /// Löst zirkuläre Abhängigkeiten durch zweistufige Initialisierung.
/// - Implementiert INavigationService Interface aus dem Controller-Layer
/// - Trennt sauber "WAS navigiert wird" (Controller) von "WIE navigiert wird" (View)
/// - Kapselt alle Avalonia-spezifische Navigation-Logik
/// - Ermöglicht verschiedene UI-Frameworks ohne Controller-Änderungen
///
/// DESIGN PATTERNS:
/// - Interface Implementation: Konkrete Umsetzung der abstrakten Navigation
/// - Dependency Injection: MainWindow wird von außen injiziert
/// - Facade Pattern: Vereinfacht komplexe UI-Navigation für Controller
/// - Bridge Pattern: Verbindet Controller (Abstraktion) mit View (Implementation)
///
/// C# KONZEPTE:
/// - Interface Implementation: public class NavigationService : INavigationService
/// - Constructor Injection: MainWindow als Dependency
/// - Null-Conditional Checks: Robuste Parameter-Validierung
/// - Exception Handling: Try-Catch für alle UI-Operationen
/// - Method Delegation: Weiterleitung von Interface-Aufrufen an UI-Code
///
/// AVALONIA-INTEGRATION:
/// - MainWindow.Content: Zentrale Inhaltsbereich für Page-Wechsel
/// - UserControl-basierte Pages: PeriodicTablePage, AboutPage, LandingPage
/// - Theme-Management: Avalonia Application Resources
/// - Application.Current: Globaler Zugriff auf App-Instance
///
/// ZIRKULÄRE ABHÄNGIGKEITEN:
/// - Problem: Controller braucht NavigationService, NavigationService braucht Controller
/// - Lösung: Zweistufige Initialisierung mit SetDataController()
/// - Constructor nimmt MainWindow, SetDataController() löst Zirkularität auf
/// </summary> /// </summary>
public class NavigationService : INavigationService public class NavigationService : INavigationService
{ {
// ===== PRIVATE FELDER ===== // ===== PRIVATE FELDER =====
/// <summary> /// <summary>
/// Referenz zum Hauptfenster der Avalonia-Anwendung /// Referenz zum Hauptfenster für Navigation zwischen Seiten
///
/// ZWECK:
/// - Zentrale Kontrolle über den Hauptinhaltsbereich
/// - Zugriff auf MainWindow.Content für Page-Wechsel
/// - Window-Eigenschaften (Titel, Größe, etc.) ändern
///
/// C# KONZEPTE:
/// - Readonly Field: Kann nur im Konstruktor gesetzt werden
/// - Reference Type: Hält Verweis auf MainWindow-Objekt
/// - Encapsulation: Private field mit controlled access
/// </summary> /// </summary>
private readonly MainWindow _mainWindow; private readonly MainWindow _mainWindow;
/// <summary> /// <summary>
/// Referenz zum Data Controller (für Daten-Zugriff) /// Data Controller für Datenzugriff (wird nach Konstruktion gesetzt)
///
/// ZWECK:
/// - Navigation-Pages benötigen Zugriff auf Element-Daten
/// - Vermeidung direkter Model/Persistence-Zugriffe aus View
/// - Konsistente Daten-API für alle UI-Komponenten
///
/// ZIRKULÄRE ABHÄNGIGKEIT:
/// - Controller erstellt NavigationService
/// - NavigationService braucht Controller für Daten
/// - Lösung: Nullable field + SetDataController() nach Konstruktion
/// </summary> /// </summary>
private PeriodensystemController? _dataController; private PeriodensystemController? _dataController;
// ===== KONSTRUKTOR UND INITIALISIERUNG ===== // ===== KONSTRUKTOR UND INITIALISIERUNG =====
/// <summary> /// <summary>
/// Konstruktor mit Dependency Injection des MainWindow /// Initialisiert den NavigationService mit dem Hauptfenster
///
/// ZWECK:
/// - Initialisiert Navigation Service mit UI-Kontext
/// - Stellt sicher, dass MainWindow verfügbar ist
/// - Validiert kritische Dependencies
///
/// C# KONZEPTE:
/// - Constructor Dependency Injection: MainWindow als Parameter
/// - ArgumentNullException: Robuste Parameter-Validierung
/// - Null-Coalescing Throw: mainWindow ?? throw new ArgumentNullException()
/// - Self-Documenting Code: Logging der Initialisierung
///
/// PARAMETER-VALIDIERUNG:
/// - Null-Check mit Exception: Verhindert spätere NullReferenceExceptions
/// - Early Fail Principle: Probleme sofort erkennbar
/// - Descriptive Exception: nameof() für präzise Fehlermeldung
/// </summary> /// </summary>
/// <param name="mainWindow">Das Hauptfenster der Avalonia-Anwendung</param> /// <param name="mainWindow">Das Hauptfenster der Avalonia-Anwendung</param>
/// <exception cref="ArgumentNullException">Wenn mainWindow null ist</exception>
public NavigationService(MainWindow mainWindow) public NavigationService(MainWindow mainWindow)
{ {
_mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow));
Logger.Log("NavigationService initialisiert - implementiert Interface-basierte Navigation"); Logger.Log("NavigationService initialisiert");
} }
/// <summary> /// <summary>
/// Setzt den Data Controller nach der Konstruktion (löst zirkuläre Abhängigkeit) /// Setzt den Data Controller nach der Konstruktion (löst zirkuläre Abhängigkeit)
///
/// ZWECK:
/// - Zweistufige Initialisierung zur Auflösung zirkulärer Dependencies
/// - Ermöglicht Controller-Access für datenabhängige Navigation
/// - Trennt UI-Initialisierung von Daten-Initialisierung
///
/// ZIRKULÄRES ABHÄNGIGKEITS-PROBLEM:
/// 1. MainWindow erstellt PeriodensystemController
/// 2. Controller braucht NavigationService (this)
/// 3. NavigationService braucht Controller für Daten
/// 4. Lösung: Controller nach NavigationService-Konstruktion setzen
///
/// C# KONZEPTE:
/// - Two-Phase Construction: Konstruktor + Setter für komplexe Dependencies
/// - Null-Conditional Assignment: _dataController wird aus null zu gültigem Objekt
/// - Method Chaining möglich: SetDataController() könnte 'this' zurückgeben
/// </summary> /// </summary>
/// <param name="dataController">Der PeriodensystemController für Datenzugriff</param> /// <param name="dataController">Der PeriodensystemController für Datenzugriff</param>
/// <exception cref="ArgumentNullException">Wenn dataController null ist</exception>
public void SetDataController(PeriodensystemController dataController) public void SetDataController(PeriodensystemController dataController)
{ {
_dataController = dataController ?? throw new ArgumentNullException(nameof(dataController)); _dataController = dataController ?? throw new ArgumentNullException(nameof(dataController));
Logger.Log("DataController in NavigationService gesetzt - zirkuläre Abhängigkeit aufgelöst"); Logger.Log("DataController in NavigationService gesetzt");
} }
/// <summary> /// <summary>
/// Navigation zum Periodensystem (Interface Implementation) /// Navigation zum Periodensystem - zeigt PeriodicTablePage im MainContent an
/// </summary> /// </summary>
public void NavigateToPeriodicTable() public void NavigateToPeriodicTable()
{ {
@ -143,9 +61,11 @@ namespace Project_Periodensystem.View
return; return;
} }
// PeriodicTablePage erstellen und Controller setzen
var periodicTablePage = new PeriodicTablePage(); var periodicTablePage = new PeriodicTablePage();
periodicTablePage.SetController(_dataController); periodicTablePage.SetController(_dataController);
// MainContent Control finden und neue Seite anzeigen
var mainContent = _mainWindow.FindControl<ContentControl>("MainContent"); var mainContent = _mainWindow.FindControl<ContentControl>("MainContent");
if (mainContent != null) if (mainContent != null)
{ {
@ -164,7 +84,7 @@ namespace Project_Periodensystem.View
} }
/// <summary> /// <summary>
/// Navigation zur About-Seite (Interface Implementation) /// Navigation zur About-Seite - zeigt Projektinformationen und Credits
/// </summary> /// </summary>
public void NavigateToAbout() public void NavigateToAbout()
{ {
@ -176,9 +96,11 @@ namespace Project_Periodensystem.View
return; return;
} }
// AboutPage erstellen und Controller setzen
var aboutPage = new AboutPage(); var aboutPage = new AboutPage();
aboutPage.SetController(_dataController); aboutPage.SetController(_dataController);
// MainContent Control finden und neue Seite anzeigen
var mainContent = _mainWindow.FindControl<ContentControl>("MainContent"); var mainContent = _mainWindow.FindControl<ContentControl>("MainContent");
if (mainContent != null) if (mainContent != null)
{ {
@ -197,7 +119,7 @@ namespace Project_Periodensystem.View
} }
/// <summary> /// <summary>
/// Navigation zur Landing Page (Interface Implementation) /// Navigation zur Landing Page - Startseite der Anwendung
/// </summary> /// </summary>
public void NavigateToLanding() public void NavigateToLanding()
{ {
@ -209,9 +131,11 @@ namespace Project_Periodensystem.View
return; return;
} }
// LandingPage erstellen und Controller setzen
var landingPage = new LandingPage(); var landingPage = new LandingPage();
landingPage.SetController(_dataController); landingPage.SetController(_dataController);
// MainContent Control finden und neue Seite anzeigen
var mainContent = _mainWindow.FindControl<ContentControl>("MainContent"); var mainContent = _mainWindow.FindControl<ContentControl>("MainContent");
if (mainContent != null) if (mainContent != null)
{ {
@ -230,7 +154,7 @@ namespace Project_Periodensystem.View
} }
/// <summary> /// <summary>
/// Theme-Wechsel (Interface Implementation) /// Wechselt zwischen Dark- und Light-Theme der Avalonia-Anwendung
/// </summary> /// </summary>
public void ToggleTheme() public void ToggleTheme()
{ {
@ -239,14 +163,16 @@ namespace Project_Periodensystem.View
var app = Application.Current; var app = Application.Current;
if (app != null) if (app != null)
{ {
// Aktuelles Theme ermitteln und umschalten
var currentTheme = app.ActualThemeVariant; var currentTheme = app.ActualThemeVariant;
var newTheme = currentTheme == Avalonia.Styling.ThemeVariant.Dark var newTheme = currentTheme == Avalonia.Styling.ThemeVariant.Dark
? Avalonia.Styling.ThemeVariant.Light ? Avalonia.Styling.ThemeVariant.Light
: Avalonia.Styling.ThemeVariant.Dark; : Avalonia.Styling.ThemeVariant.Dark;
// Neues Theme anwenden
app.RequestedThemeVariant = newTheme; app.RequestedThemeVariant = newTheme;
// Settings speichern // Theme-Einstellung persistent speichern
var settings = new AppSettings var settings = new AppSettings
{ {
LastTheme = newTheme.ToString() ?? "Dark", LastTheme = newTheme.ToString() ?? "Dark",
@ -265,14 +191,14 @@ namespace Project_Periodensystem.View
} }
/// <summary> /// <summary>
/// Export-Bestätigung anzeigen (Interface Implementation) /// Zeigt eine Export-Bestätigung an (aktuell nur Logging)
/// </summary> /// </summary>
public void ShowExportConfirmation() public void ShowExportConfirmation()
{ {
try try
{ {
Logger.Log("NavigationService: Export-Bestätigung angezeigt"); Logger.Log("NavigationService: Export-Bestätigung angezeigt");
// Hier könnte ein Dialog oder Notification angezeigt werden // TODO: Hier könnte ein Dialog oder Notification angezeigt werden
} }
catch (Exception ex) catch (Exception ex)
{ {