351 lines
12 KiB
C#
351 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Project_Periodensystem.Model;
|
|
using Project_Periodensystem.Persistence;
|
|
|
|
namespace Project_Periodensystem.Controller
|
|
{
|
|
/// <summary>
|
|
/// Controller für das Periodensystem - verwaltet die Geschäftslogik
|
|
/// und trennt View von Model gemäß MVC-Pattern
|
|
/// </summary>
|
|
public class PeriodensystemController
|
|
{
|
|
// Nullable Field um Warning zu vermeiden
|
|
private List<Element> _elements = new List<Element>();
|
|
|
|
/// <summary>
|
|
/// Konstruktor - initialisiert den Controller
|
|
/// </summary>
|
|
public PeriodensystemController()
|
|
{
|
|
LoadElements();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lädt alle Elemente über den Persistence-Layer (JETZT MIT DATAMANAGER!)
|
|
/// </summary>
|
|
private void LoadElements()
|
|
{
|
|
try
|
|
{
|
|
// NEUE METHODE: DataManager statt direkt PeriodicTableData
|
|
_elements = DataManager.LoadElements();
|
|
Logger.Log($"Controller: {_elements.Count} Elemente erfolgreich geladen (via DataManager)");
|
|
|
|
// NEUE FEATURES demonstrieren:
|
|
// Array-Operationen testen
|
|
var symbols = GetAllSymbols();
|
|
Logger.LogArray("Element-Symbole (erste 10)", symbols.Take(10).ToArray());
|
|
|
|
// Tuple-Operationen testen
|
|
var (totalElements, uniqueSeries, avgWeight) = GetStatistics();
|
|
Logger.LogTuple("Statistiken", $"Elemente: {totalElements}, Serien: {uniqueSeries}, Ø-Gewicht: {avgWeight:F2}");
|
|
|
|
// Extremwerte finden
|
|
var (lightest, heaviest) = GetWeightExtremes();
|
|
if (lightest != null && heaviest != null)
|
|
{
|
|
Logger.LogTuple("Gewichts-Extreme", $"Leichtestes: {lightest.Symbol} ({lightest.AtomicWeight}), Schwerstes: {heaviest.Symbol} ({heaviest.AtomicWeight})");
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Log($"EXCEPTION in LoadElements: {ex.Message}");
|
|
_elements = new List<Element>();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt alle verfügbaren Elemente zurück
|
|
/// </summary>
|
|
/// <returns>Liste aller Elemente</returns>
|
|
public List<Element> GetAllElements()
|
|
{
|
|
return _elements;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt Elemente als Array zurück (für Array-Operationen)
|
|
/// </summary>
|
|
/// <returns>Array aller Elemente</returns>
|
|
public Element[] GetAllElementsAsArray()
|
|
{
|
|
return _elements.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt nur die Symbole als String-Array zurück
|
|
/// </summary>
|
|
/// <returns>Array mit allen Element-Symbolen</returns>
|
|
public string[] GetAllSymbols()
|
|
{
|
|
string[] symbols = new string[_elements.Count];
|
|
for (int i = 0; i < _elements.Count; i++)
|
|
{
|
|
symbols[i] = _elements[i].Symbol;
|
|
}
|
|
return symbols;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt Atomgewichte als Array zurück
|
|
/// </summary>
|
|
/// <returns>Array mit allen Atomgewichten</returns>
|
|
public double[] GetAtomicWeights()
|
|
{
|
|
double[] weights = new double[_elements.Count];
|
|
for (int i = 0; i < _elements.Count; i++)
|
|
{
|
|
weights[i] = _elements[i].AtomicWeight;
|
|
}
|
|
return weights;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Berechnet Durchschnittsgewicht aus Array
|
|
/// </summary>
|
|
/// <returns>Durchschnittliches Atomgewicht</returns>
|
|
public double GetAverageAtomicWeight()
|
|
{
|
|
double[] weights = GetAtomicWeights();
|
|
if (weights.Length == 0) return 0;
|
|
|
|
double sum = 0;
|
|
for (int i = 0; i < weights.Length; i++)
|
|
{
|
|
sum += weights[i];
|
|
}
|
|
return sum / weights.Length;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Speichert Elemente persistent (NEUE FUNKTION)
|
|
/// </summary>
|
|
public void SaveElements()
|
|
{
|
|
try
|
|
{
|
|
DataManager.SaveElements(_elements);
|
|
Logger.Log("Elemente erfolgreich gespeichert");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogException(ex, "SaveElements");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sucht ein Element nach Atomnummer
|
|
/// </summary>
|
|
/// <param name="atomicNumber">Atomnummer des gesuchten Elements</param>
|
|
/// <returns>Element oder null wenn nicht gefunden</returns>
|
|
public Element? GetElementByAtomicNumber(int atomicNumber)
|
|
{
|
|
if (atomicNumber <= 0)
|
|
{
|
|
Logger.Log($"Ungültige Atomnummer: {atomicNumber}");
|
|
return null;
|
|
}
|
|
|
|
return _elements.FirstOrDefault(e => e.AtomicNumber == atomicNumber);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sucht ein Element nach Symbol
|
|
/// </summary>
|
|
/// <param name="symbol">Symbol des gesuchten Elements</param>
|
|
/// <returns>Element oder null wenn nicht gefunden</returns>
|
|
public Element? GetElementBySymbol(string symbol)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(symbol))
|
|
{
|
|
Logger.Log("Leeres Symbol übergeben");
|
|
return null;
|
|
}
|
|
|
|
return _elements.FirstOrDefault(e =>
|
|
string.Equals(e.Symbol, symbol, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Filtert Elemente nach Serie
|
|
/// </summary>
|
|
/// <param name="series">Gewünschte Elementserie</param>
|
|
/// <returns>Liste der Elemente der angegebenen Serie</returns>
|
|
public List<Element> GetElementsBySeries(string series)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(series))
|
|
{
|
|
return new List<Element>();
|
|
}
|
|
|
|
return _elements.Where(e =>
|
|
string.Equals(e.Series, series, StringComparison.OrdinalIgnoreCase))
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validiert Grid-Position eines Elements
|
|
/// </summary>
|
|
/// <param name="element">Zu validierendes Element</param>
|
|
/// <returns>True wenn Position gültig ist</returns>
|
|
public bool ValidateElementPosition(Element element)
|
|
{
|
|
if (element == null)
|
|
{
|
|
Logger.Log("Null-Element kann nicht validiert werden");
|
|
return false;
|
|
}
|
|
|
|
// Periodensystem hat 7 Perioden (0-6) und 18 Gruppen (0-17)
|
|
// Plus Lanthanoid/Actinoid-Reihen bei Zeile 8 und 9
|
|
bool validRow = element.Row >= 0 && element.Row <= 9;
|
|
bool validColumn = element.Column >= 0 && element.Column <= 17;
|
|
|
|
if (!validRow || !validColumn)
|
|
{
|
|
Logger.Log($"Ungültige Position für {element.Symbol}: ({element.Row},{element.Column})");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt alle verfügbaren Element-Serien zurück
|
|
/// </summary>
|
|
/// <returns>Liste aller Serien</returns>
|
|
public List<string> GetAllSeries()
|
|
{
|
|
return _elements.Select(e => e.Series)
|
|
.Distinct()
|
|
.Where(s => !string.IsNullOrWhiteSpace(s))
|
|
.OrderBy(s => s)
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Überprüft ob alle Elemente korrekt geladen wurden
|
|
/// </summary>
|
|
/// <returns>True wenn Daten vollständig sind</returns>
|
|
public bool ValidateData()
|
|
{
|
|
if (_elements.Count == 0)
|
|
{
|
|
Logger.Log("Keine Elemente geladen");
|
|
return false;
|
|
}
|
|
|
|
// Überprüfe auf Duplikate bei Atomnummern
|
|
var duplicateNumbers = _elements.GroupBy(e => e.AtomicNumber)
|
|
.Where(g => g.Count() > 1)
|
|
.Select(g => g.Key);
|
|
|
|
if (duplicateNumbers.Any())
|
|
{
|
|
Logger.Log($"Doppelte Atomnummern gefunden: {string.Join(", ", duplicateNumbers)}");
|
|
return false;
|
|
}
|
|
|
|
// Überprüfe auf leere Symbole
|
|
var emptySymbols = _elements.Where(e => string.IsNullOrWhiteSpace(e.Symbol));
|
|
if (emptySymbols.Any())
|
|
{
|
|
Logger.Log("Elemente mit leeren Symbolen gefunden");
|
|
return false;
|
|
}
|
|
|
|
Logger.Log($"Datenvalidierung erfolgreich - {_elements.Count} Elemente validiert");
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lädt Daten neu (für Refresh-Funktionalität)
|
|
/// </summary>
|
|
public void RefreshData()
|
|
{
|
|
Logger.Log("Daten werden neu geladen...");
|
|
LoadElements();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt die Anzahl der geladenen Elemente zurück
|
|
/// </summary>
|
|
/// <returns>Anzahl der Elemente</returns>
|
|
public int GetElementCount()
|
|
{
|
|
return _elements.Count;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt Element-Position als Tuple zurück
|
|
/// </summary>
|
|
/// <param name="atomicNumber">Atomnummer des Elements</param>
|
|
/// <returns>Tuple mit (Row, Column) oder (-1, -1) wenn nicht gefunden</returns>
|
|
public (int row, int column) GetElementPosition(int atomicNumber)
|
|
{
|
|
var element = GetElementByAtomicNumber(atomicNumber);
|
|
if (element != null)
|
|
{
|
|
return (element.Row, element.Column);
|
|
}
|
|
return (-1, -1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt Grundinfos eines Elements als Tuple zurück
|
|
/// </summary>
|
|
/// <param name="atomicNumber">Atomnummer</param>
|
|
/// <returns>Tuple mit (Symbol, Name, Gewicht)</returns>
|
|
public (string symbol, string name, double weight) GetElementInfo(int atomicNumber)
|
|
{
|
|
var element = GetElementByAtomicNumber(atomicNumber);
|
|
if (element != null)
|
|
{
|
|
return (element.Symbol, element.ElementName, element.AtomicWeight);
|
|
}
|
|
return ("", "Unbekannt", 0.0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt Statistiken als Tuple zurück
|
|
/// </summary>
|
|
/// <returns>Tuple mit (Anzahl Elemente, Anzahl Serien, Durchschnittsgewicht)</returns>
|
|
public (int totalElements, int uniqueSeries, double avgWeight) GetStatistics()
|
|
{
|
|
var seriesCount = GetAllSeries().Count;
|
|
var avgWeight = GetAverageAtomicWeight();
|
|
|
|
return (_elements.Count, seriesCount, avgWeight);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Findet leichtestes und schwerstes Element
|
|
/// </summary>
|
|
/// <returns>Tuple mit (leichtestes Element, schwerstes Element) oder null-Werte wenn keine Elemente</returns>
|
|
public (Element? lightest, Element? heaviest) GetWeightExtremes()
|
|
{
|
|
if (!_elements.Any())
|
|
{
|
|
return (null, null);
|
|
}
|
|
|
|
var lightest = _elements[0];
|
|
var heaviest = _elements[0];
|
|
|
|
foreach (var element in _elements)
|
|
{
|
|
if (element.AtomicWeight < lightest.AtomicWeight)
|
|
lightest = element;
|
|
if (element.AtomicWeight > heaviest.AtomicWeight)
|
|
heaviest = element;
|
|
}
|
|
|
|
return (lightest, heaviest);
|
|
}
|
|
}
|
|
}
|