diff --git a/Full-Doc.md b/Full-Doc.md new file mode 100644 index 0000000..149db6d --- /dev/null +++ b/Full-Doc.md @@ -0,0 +1,346 @@ +# LeanderShiftPlannerV2 – Technische Dokumentation + +**Version:** 2.0.1 +**Sprache:** C# / .NET 9.0 +**Framework:** Avalonia UI 11.2.1 +**Repository:** https://gitea.leanderserver.de/leander19961/LeanderShiftPlannerV2 + +--- + +## Inhaltsverzeichnis + +1. [Projektübersicht](#1-projektübersicht) +2. [Systemvoraussetzungen & Abhängigkeiten](#2-systemvoraussetzungen--abhängigkeiten) +3. [Projektstruktur](#3-projektstruktur) +4. [Datenmodell](#4-datenmodell) + - 4.1 [Person](#41-person) + - 4.2 [Shift (Schicht)](#42-shift-schicht) + - 4.3 [ShiftPlan](#43-shiftplan) + - 4.4 [Timesheet (Stundenzettel)](#44-timesheet-stundenzettel) + - 4.5 [Filter](#45-filter) +5. [Services (Geschäftslogik)](#5-services-geschäftslogik) + - 5.1 [AppService](#51-appservice) + - 5.2 [PersonService](#52-personservice) + - 5.3 [ShiftService](#53-shiftservice) + - 5.4 [ShiftPlanService](#54-shiftplanservice) + - 5.5 [FilterService](#55-filterservice) + - 5.6 [TimesheetService](#56-timesheetservice) + - 5.7 [ViewService](#57-viewservice) +6. [Berechnungsalgorithmus](#6-berechnungsalgorithmus) +7. [Datei-I/O (FileIO)](#7-datei-io-fileio) +8. [Benutzeroberfläche (View)](#8-benutzeroberfläche-view) +9. [Ausgabedateien](#9-ausgabedateien) +10. [Hinweise & Einschränkungen](#10-hinweise--einschränkungen) + +--- + +## 1. Projektübersicht + +LeanderShiftPlannerV2 ist eine Desktop-Anwendung zur **automatisierten Erstellung von Schichtplänen**. Das Tool erlaubt das Anlegen, Verwalten und Verknüpfen von Personen und Schichten, die anschließende Berechnung aller validen Schichtplankombinationen sowie die automatische Generierung von Stundenzetteln. + +**Kernfunktionen:** + +- Verwaltung von Personen (inkl. Wochenstunden und Stundenzettel-Quelle) +- Verwaltung von Schichten (Wochentag, Uhrzeit, Min./Max.-Personenanzahl) +- Bidirektionale Verknüpfung von Personen und Schichten +- Parallele Berechnung aller gültigen Schichtplankombinationen +- Filterung der berechneten Pläne +- Ausgabe als PNG und/oder Textdatei +- Automatische Generierung von Stundenzetteln (Excel-Format, optional Google Calendar-Integration) + +> **Wichtig:** Alle Stundenangaben müssen im **Wochenstunden-Format** erfolgen! + +--- + +## 2. Systemvoraussetzungen & Abhängigkeiten + +| Anforderung | Details | +|---|---| +| .NET-Version | .NET 9.0 | +| UI-Framework | Avalonia UI 11.2.1 (Cross-Platform: Windows, Linux, macOS) | +| Ausgabetyp | WinExe (Desktop-Anwendung) | + +**NuGet-Pakete:** + +| Paket | Version | Verwendung | +|---|---|---| +| Avalonia | 11.2.1 | UI-Framework | +| Avalonia.Desktop | 11.2.1 | Desktop-Unterstützung | +| Avalonia.Themes.Fluent | 11.2.1 | Fluent Design Theme | +| Avalonia.Fonts.Inter | 11.2.1 | Schriftarten | +| EPPlus | 7.5.3 | Excel-Generierung (Stundenzettel) | +| Google.Apis.Calendar.v3 | 1.69.0.3746 | Google Calendar Integration | +| SkiaSharp | 3.118.0-preview | PNG-Rendering der Schichtpläne | + +--- + +## 3. Projektstruktur + +``` +LeanderShiftPlannerV2/ +├── LeanderShiftPlannerV2.sln +└── LeanderShiftPlannerV2/ + ├── App.axaml / App.axaml.cs # Avalonia-Anwendungseinstieg + ├── Program.cs # Main-Einstiegspunkt + ├── app.manifest + ├── LeanderShiftPlannerV2.csproj + ├── Model/ # Datenmodelle (POCOs) + │ ├── Person.cs + │ ├── Shift.cs + │ ├── ShiftPlan.cs + │ ├── Timesheet.cs + │ └── Filter.cs + ├── Service/ # Geschäftslogik / Services + │ ├── AppService.cs # Zentraler Service-Container + │ ├── PersonService.cs + │ ├── ShiftService.cs + │ ├── ShiftPlanService.cs # Kernalgorithmus + │ ├── FilterService.cs + │ ├── TimesheetService.cs + │ └── ViewService.cs + ├── FileIO/ # Laden/Speichern von Daten + ├── View/ # Avalonia AXAML Views + ├── Util/ # Hilfsfunktionen + └── Resources/ + ├── icon/ # Anwendungssymbol + ├── font/ # Eingebettete Schriften (Emblem.ttf, Roboto.ttf) + └── templates/ + ├── timesheet.xlsx # Excel-Vorlage für Stundenzettel + └── googleapi.txt # Google API-Konfiguration +``` + +--- + +## 4. Datenmodell + +### 4.1 Person + +**Datei:** `Model/Person.cs` +**Implementiert:** `INotifyPropertyChanged`, `[Serializable]` + +Repräsentiert eine Person, die in Schichten eingeteilt werden kann. + +| Eigenschaft | Typ | Beschreibung | +|---|---|---| +| `FirstName` | `string` | Vorname der Person | +| `Surname` | `string` | Nachname der Person | +| `Hours` | `int` | Wöchentliche Arbeitsstunden (Pflichtangabe) | +| `TimeSheetSource` | `string` | Pfad/Quelle für die Stundenzettel-Daten | +| `Shifts` | `ObservableCollection` | Liste verknüpfter Schichten (nicht serialisiert) | +| `Timesheets` | `List` | Liste der Stundenzettel (nicht serialisiert) | +| `ShiftsString` | `string` (readonly) | Lesbare Darstellung aller Schichten für die UI | + +**Methoden:** + +- `AddShift(Shift)` / `RemoveShift(Shift)` / `ClearShifts()` – Verwaltung der Schichtverknüpfungen (lösen jeweils `PropertyChanged` aus) +- `GetTimeSheetByMonth(string month)` – Gibt den Stundenzettel für einen bestimmten Monat zurück + +--- + +### 4.2 Shift (Schicht) + +**Datei:** `Model/Shift.cs` +**Implementiert:** `INotifyPropertyChanged`, `[Serializable]` + +Repräsentiert eine einzelne Schicht an einem bestimmten Wochentag. + +| Eigenschaft | Typ | Beschreibung | +|---|---|---| +| `Day` | `string` | Wochentag (z.B. "Montag") | +| `StartTime` | `string` | Startzeit (Format: "HH:mm") | +| `EndTime` | `string` | Endzeit (Format: "HH:mm") | +| `Duration` | `int` | Dauer der Schicht in Stunden | +| `ShiftInDay` | `int` | Position der Schicht am Tag (1 = erste, 2 = zweite, 3 = dritte) | +| `MaxPersonCount` | `int` | Maximale Anzahl Personen pro Schicht | +| `MinPersonCount` | `int` | Minimale Anzahl Personen pro Schicht | +| `Persons` | `ObservableCollection` | Verknüpfte Personen (nicht serialisiert) | +| `PersonsString` | `string` (readonly) | Lesbare Darstellung aller Personen für die UI | +| `Time` | `string` (readonly) | Formatierte Zeitanzeige "HH:MM - HH:MM" | + +**Methoden:** + +- `AddPerson(Person)` / `RemovePerson(Person)` / `ClearPersons()` – Verwaltung der Personenverknüpfungen + +--- + +### 4.3 ShiftPlan + +**Datei:** `Model/ShiftPlan.cs` + +Repräsentiert einen vollständigen Schichtplan, der aus einer Kombination von Schichten über alle konfigurierten Wochentage besteht. Wird vom `ShiftPlanService` erzeugt. + +--- + +### 4.4 Timesheet (Stundenzettel) + +**Datei:** `Model/Timesheet.cs` + +Repräsentiert den Stundenzettel einer Person für einen bestimmten Monat. Beinhaltet die Arbeitszeiterfassung und wird wahlweise aus einer lokalen Quelle oder über Google Calendar bezogen. + +| Eigenschaft | Typ | Beschreibung | +|---|---|---| +| `Month` | `string` | Monat im Format "MM.YYYY" o.ä. | + +--- + +### 4.5 Filter + +**Datei:** `Model/Filter.cs` + +Hält die aktuell gesetzten Filterkriterien für die Anzeige der berechneten Schichtpläne. + +--- + +## 5. Services (Geschäftslogik) + +### 5.1 AppService + +**Datei:** `Service/AppService.cs` + +Zentraler Service-Container, der alle anderen Services hält und als einheitlicher Zugriffspunkt dient. Wird bei Anwendungsstart instanziiert und an alle abhängigen Komponenten weitergegeben. + +**Hält Referenzen auf:** `PersonService`, `ShiftService`, `ShiftPlanService`, `FilterService`, `TimesheetService`, `ViewService` + +--- + +### 5.2 PersonService + +**Datei:** `Service/PersonService.cs` + +Verwaltet die Liste aller Personen sowie deren Stundenzettel-Daten. + +**Kernfunktionen:** +- CRUD-Operationen für `Person`-Objekte +- Laden von Stundenzetteln aus einer externen Quelle (`TimeSheetSource`) +- `GenerateRandomTimeSheets()` – Generiert zufällige Stundenzettel auf Basis von Google Calendar-Einträgen und passt sie an die Wochenstunden der Person an + +--- + +### 5.3 ShiftService + +**Datei:** `Service/ShiftService.cs` + +Verwaltet die Liste aller Schichten. + +**Kernfunktionen:** +- CRUD-Operationen für `Shift`-Objekte +- `GetShiftList()` – Gibt alle konfigurierten Schichten zurück + +--- + +### 5.4 ShiftPlanService + +**Datei:** `Service/ShiftPlanService.cs` + +Der **Kernservice** der Anwendung. Enthält den gesamten Berechnungsalgorithmus für Schichtpläne. + +**Wichtige Methoden:** + +| Methode | Beschreibung | +|---|---| +| `StartCalculation(CancellationToken)` | Startet die vollständige Berechnung (Listen initialisieren → Schichten generieren → Pläne berechnen) | +| `GeneratePlannedShifts()` | Erzeugt alle möglichen Schichtkombinationen (Permutationen nach Personenanzahl: 1, 2 oder 3 Personen pro Schicht) | +| `CalculateShiftPlans(CancellationToken)` | Kombiniert die Tagesschichten zu vollständigen Wochenplänen, **parallel** mit `Parallel.ForEach` | +| `CheckShift(List<...>)` | Prüft, ob ein Schichtplan die Wochenstunden aller Personen exakt erfüllt (nicht über- oder unterschreitet) | +| `GetShiftPlans()` | Gibt die aktuell gefilterte `ObservableCollection` zurück | +| `GetAllShiftPlans()` | Gibt alle berechneten Pläne (ungefiltert) zurück | +| `ResetShiftPlanList()` | Setzt den gefilterten Stand auf alle berechneten Pläne zurück | + +--- + +### 5.5 FilterService + +**Datei:** `Service/FilterService.cs` + +Wendet einen `Filter` auf die Liste der Schichtpläne an und reduziert die angezeigte Liste entsprechend. + +--- + +### 5.6 TimesheetService + +**Datei:** `Service/TimesheetService.cs` + +Generiert Stundenzettel-Dateien im Excel-Format (`Data/Output/Timesheets`) auf Basis der `Timesheet`-Daten der Personen und der bereitgestellten `timesheet.xlsx`-Vorlage. + +--- + +### 5.7 ViewService + +**Datei:** `Service/ViewService.cs` + +Übernimmt die Darstellung eines `ShiftPlan` als PNG-Bild mittels **SkiaSharp**. Speichert alle Pläne im Verzeichnis `Data/Output/ShiftPlans`. + +--- + +## 6. Berechnungsalgorithmus + +Der Algorithmus in `ShiftPlanService` arbeitet in drei Phasen: + +### Phase 1 – Generierung der Einzelschicht-Varianten (`GeneratePlannedShifts`) + +Für jede konfigurierte Schicht werden alle Kombinationen von Personen gebildet, die dieser Schicht zugewiesen sind – von `MinPersonCount` bis `MaxPersonCount`. Das Ergebnis ist eine Liste aller möglichen "besetzten Einzelschichten": + +- **1 Person:** Jede Person einzeln +- **2 Personen:** Alle Zweier-Kombinationen (ohne Wiederholung) +- **3 Personen:** Alle Dreier-Kombinationen (ohne Wiederholung) + +### Phase 2 – Aufbau der Tagesschichten (`GenerateDayShifts`) + +Die Einzelschicht-Varianten werden nach Wochentag gruppiert. Innerhalb eines Tages werden die bis zu 3 möglichen Positionen (ShiftInDay = 1, 2, 3) zu Dreier-Tupeln `(Shift, Shift, Shift)` kombiniert. Fehlt eine Position, wird `null` eingesetzt. + +### Phase 3 – Kombination zum Wochenplan & Validierung (`CalculateShiftPlans`) + +Alle Tagesschichten werden durch **verschachtelte `Parallel.ForEach`-Schleifen** kombiniert (je ein Level pro Wochentag). Für jede entstehende Wochenplan-Kombination wird `CheckShift` aufgerufen: + +- Es werden die kumulierten Stunden aller Personen berechnet. +- Ein Plan gilt nur dann als **gültig**, wenn jede Person **exakt** ihre konfigurierten Wochenstunden arbeitet (weder mehr noch weniger). +- Gültige Pläne werden in die `ObservableCollection` eingetragen. + +> **Hinweis zur Performance:** Die Berechnung ist exponentiell in der Anzahl der Schichten und Personen. Die parallele Ausführung über `Parallel.ForEach` nutzt alle verfügbaren CPU-Kerne. Bei komplexen Konfigurationen kann die Berechnung dennoch mehrere Sekunden bis Minuten dauern. + +--- + +## 7. Datei-I/O (FileIO) + +Das `FileIO`-Verzeichnis enthält Klassen zum Laden und Speichern des Anwendungszustands (Personen, Schichten) als XML-Dateien mittels `XmlSerializer`. + +- Personen und Schichten werden als XML serialisiert/deserialisiert. +- Verknüpfungen (`Shifts` in Person, `Persons` in Shift) sind mit `[XmlIgnore]` dekoriert und werden nach dem Laden aus dem XML neu aufgebaut, um zirkuläre Referenzen zu vermeiden. + +--- + +## 8. Benutzeroberfläche (View) + +Die Oberfläche ist mit **Avalonia UI** und dem **Fluent Theme** umgesetzt. Sie besteht aus mehreren Tabs: + +| Tab | Funktion | +|---|---| +| **Persons** | Personen anlegen (`Add new person`), bearbeiten (`Edit person`), löschen (`Delete person`), Schichten zuweisen (`Select shifts for person`) | +| **Shifts** | Schichten anlegen (`Add new shift`), bearbeiten (`Edit shift`), löschen (`Delete shift`), Personen zuweisen (`Select persons for shift`) | +| **ShiftPlans** | Berechnung starten (`Start calculation`), Pläne filtern (`Filter shiftplans`), Filter zurücksetzen (`Reset all filters`), Plan öffnen (`Open selected ShiftPlan`), alle Pläne speichern (`Save all ShiftPlans`), Stundenzettel generieren (`Generate Timesheets`) | + +**Bidirektionale Verknüpfung:** Die Zuweisung von Personen und Schichten erfolgt stets automatisch in beide Richtungen. Eine über "Select shifts for person" hinzugefügte Schicht wird der Person **und** gleichzeitig der Person zur Schicht hinzugefügt – ohne manuellen Zweischritt. + +--- + +## 9. Ausgabedateien + +| Pfad | Inhalt | +|---|---| +| `Data/Output/ShiftPlans/` | Alle Schichtpläne als `.png`-Dateien (via `Save all ShiftPlans`) | +| `Data/Output/Timesheets/` | Stundenzettel als `.xlsx`-Dateien (via `Generate Timesheets`) | + +--- + +## 10. Hinweise & Einschränkungen + +- **Stundenformat:** Alle Stunden müssen als **Wochenstunden** angegeben werden. Tagesstunden oder Monatsstunden werden nicht unterstützt. +- **Personenanzahl pro Schicht:** Der Algorithmus unterstützt aktuell maximal **3 Personen** pro Schicht. Höhere Werte für `MaxPersonCount` werden im Code nicht berücksichtigt. +- **Anzahl Wochentage:** Der Algorithmus ist für genau **5 Wochentage** ausgelegt (die Schleifentiefe in `CalculateShiftPlans` ist auf 5 verschachtelt). +- **Stundenzettel-Quelle:** Die `TimeSheetSource` einer Person verweist auf eine externe Datenquelle (Google Calendar oder lokale Datei), die vor der Generierung verfügbar sein muss. +- **Google API:** Die Konfiguration der Google Calendar API erfolgt über die eingebettete Ressource `Resources/templates/googleapi.txt`. +- **Performance:** Bei sehr vielen Personen und Schichten kann die Anzahl der Permutationen exponentiell wachsen. Eine Abbruchmöglichkeit via `CancellationToken` ist implementiert. + +--- + +*Dokumentation erstellt am 22.04.2026*