diff --git a/README.md b/README.md index 4aad1ef..60da198 100644 --- a/README.md +++ b/README.md @@ -2,34 +2,13 @@ Automatische Zuteilung von Elterndiensten im Kinderladen unter Berücksichtigung von Fairness und Präferenzen. -## Wie funktioniert die Dienstplanung? +## Überblick -Der Elterndienstplaner verteilt die anfallenden Dienstzuteilungen für einen Monat automatisch auf die Eltern. Dabei werden folgende Ziele berücksichtigt: +Der Elterndienstplaner verteilt monatliche Dienstzuteilungen optimal auf die Eltern durch Lösung eines linearen Optimierungsproblems. Das System berücksichtigt: -### 1. Regeln (Harte Constraints) - -Diese Regeln **müssen** immer eingehalten werden: - -- **C1: Maximal einmal pro Woche pro Diensttyp** - Niemand muss z.B. zweimal in einer Woche Frühstücksdienst machen -- **C2: Maximal eine Zuteilung pro Tag** - Niemand bekommt mehrere Dienstzuteilungen am selben Tag -- **C3: Nur bei Verfügbarkeit** - Zuteilungen erfolgen nur bei Verfügbarkeit (keine Abwesenheiten) -- **C4: Alle Dienste werden besetzt** - Jeder benötigte Diensttyp wird an jedem Tag besetzt - -### 2. Fairness und Präferenzen (Weiche Constraints) - -Diese Ziele werden optimiert, können aber nicht immer perfekt erfüllt werden: - -**Fairness:** -- **F1: Faire Jahresverteilung** - Über das ganze Kitajahr hinweg werden Zuteilungen fair verteilt (pro Diensttyp) -- **F2: Faire Monatsverteilung** - Innerhalb eines Monats werden Zuteilungen fair verteilt (pro Diensttyp). **Besonderheit:** Abwesenheitstage werden aus der Dienstpflicht herausgerechnet, um eine gleichmäßigere Verteilung zu erreichen. Die "verpassten" Dienste werden über F1 im Jahresverlauf ausgeglichen. -- **F3: Ausgewogene Diensttypen (Jahr)** - Verhindert über das ganze Jahr, dass einzelne Familien über alle Diensttypen hinweg zu viele Zuteilungen bekommen -- **F4: Ausgewogene Diensttypen (Monat)** - Verhindert im aktuellen Monat, dass einzelne Familien über alle Diensttypen hinweg zu viele Zuteilungen bekommen - -**Präferenzen:** -- **P1: Bevorzugte Tage für Diensttypen** - An bestimmten Tagen bevorzugte Diensttypen werden nach Möglichkeit zugeteilt -- **P2: Vermeiden an bestimmten Tagen** - An bestimmten Tagen abgelehnte Diensttypen werden nach Möglichkeit vermieden - -Die Fairness bestimmt **wie viele** Zuteilungen jede Familie erhält, die Präferenzen beeinflussen **an welchen Tagen welcher Diensttyp** zugeteilt wird. Selbst bei Ablehnung kann ein Diensttyp an einem bestimmten Tag zugeteilt werden, wenn das für die faire Verteilung nötig ist. +- **Harte Constraints (C1-C4):** Müssen immer eingehalten werden +- **Fairness-Constraints (F1-F4):** Werden optimiert +- **Präferenzen (P1-P2):** Werden berücksichtigt, wenn möglich ## Diensttypen @@ -39,97 +18,52 @@ Die Fairness bestimmt **wie viele** Zuteilungen jede Familie erhält, die Präfe - **K** - Kochen (ca. alle 2 Wochen, 1 Person) - **A** - Elternabend (ca. einmal im Monat, 2 Personen) -Die Planung erfolgt für einen Kalendermonat. +## Eingabedateien -## Abwesenheiten und Präferenzen angeben (eingabe.csv) +### eingabe.csv -Diese Datei enthält für jeden Tag des Planungsmonats, welche Dienste anfallen und welche Eltern verfügbar sind bzw. Präferenzen haben. +Tägliche Dienste und Eltern-Verfügbarkeiten/Präferenzen für den Planungsmonat. **Format:** -``` -Datum, Wochentag, Dienste, Sarah & Tim, Leon, Maya, ... -2026-01-06, Montag, FPE, F+, x, , ... -2026-01-07, Dienstag, FPE, P-, F+P+, , ... +```csv +Datum,Wochentag,Dienste,Kind1,Kind2,... +2026-01-06,Montag,FPE,x,F+,... ``` **Spalten:** -1. **Datum** (ISO-Format: YYYY-MM-DD) -2. **Wochentag** (zur Information) -3. **Diensttypen** - Welche Diensttypen an diesem Tag benötigt werden (z.B. "FPE" für Frühstück, Putzen, Essen) -4-n. **Eine Spalte pro Familie** - Abwesenheiten und Präferenzen: - - `x` = nicht verfügbar (Urlaub, Krankheit, etc.) - - `Kürzel+` = diesen Dienst bevorzugt (z.B. `F+` für Frühstücksdienst bevorzugt) - - `Kürzel-` = diesen Dienst abgelehnt (z.B. `P-` für Putznotdienst abgelehnt) - - Mehrere kombinierbar: `F+P-E+` (Frühstück bevorzugt, Putzen abgelehnt, Essen bevorzugt) - - Leer = verfügbar, keine Präferenz - -**Beispiel:** -``` -Datum ,Wochentag ,Dienste,Sarah & Tim,Leon ,Maya -2026-01-06 ,Montag ,FPE ,x , ,F+ -2026-01-07 ,Dienstag ,FPE , ,F+P- , -2026-01-10 ,Freitag ,FPEK ,F+K+ , ,P- -``` - -- Sarah & Tim sind am 6.1. nicht verfügbar -- Leon bevorzugt am 7.1. Frühstück, lehnt Putzen ab -- Maya bevorzugt am 6.1. Frühstück -- Am 10.1. bevorzugen Sarah & Tim Frühstück oder Kochen - -## Weitere Eingabedateien +- Datum (YYYY-MM-DD) +- Wochentag +- Dienste (Kombination aus F/P/E/K/A) +- Pro Familie: `x` (abwesend), `Kürzel+` (bevorzugt), `Kürzel-` (abgelehnt), leer (verfügbar) ### eltern.csv -Dienstfaktoren (= Anzahl betreuter Kinder) pro Elternteil und Zeitraum. +Dienstfaktoren (Anzahl Kinder) pro Familie und Zeitraum. **Format:** +```csv +Name_Kind(er),Zeitraum_Beginn,Zeitraum_Ende,Dienstfaktor,... +Sarah & Tim,2024-09-01,2025-07-31,2 +Leon,2024-09-01,2024-12-31,1,2025-01-01,2025-07-31,0 ``` -Eltern, Beginn, Ende, Faktor, Beginn, Ende, Faktor, ... -Sarah & Tim, 2024-09-01, 2025-07-31, 2 -Leon, 2024-09-01, 2024-12-31, 1, 2025-01-01, 2025-07-31, 0 -Maya, 2024-09-01, 2025-07-31, 1 -``` - -**Spalten:** -1. **Kind-Name(n)** - Bei mehreren Kindern durch & verbunden (z.B. "Sarah & Tim") -2-4. **Zeitraum 1:** Beginn (Datum), Ende (Datum), Dienstfaktor -5-7. **Zeitraum 2:** Beginn, Ende, Dienstfaktor (optional, für Änderungen während des Jahres) -... **Hinweise:** -- Der Dienstfaktor entspricht der Anzahl der Kinder in der Familie (z.B. 2 für "Sarah & Tim", 1 für "Leon") -- Familien mit mehreren Kindern werden als ein Eintrag mit entsprechendem Dienstfaktor geführt -- Bei überlappenden Zeiträumen gilt der letzte Eintrag -- Außerhalb definierter Zeiträume: Faktor = 0 (keine Dienstpflicht) -- Faktor = 0 bedeutet: Befreiung von Diensten (z.B. durch Vorstandsamt) - -**Beispiel:** Sarah & Tim (Dienstfaktor 2), Leon (Dienstfaktor 1, aber ab Januar 2025 keine Dienstpflicht), Maya (Dienstfaktor 1). +- Dienstfaktor = Anzahl Kinder +- Faktor 0 = keine Dienstpflicht (z.B. Vorstand) +- Mehrere Zeiträume möglich für Änderungen im Jahr ### vorherige-ausgaben.csv (optional) -Frühere Ausgaben des Programms zur Berechnung der Jahres-Fairness. - -**Format:** Wie `ausgabe.csv` (siehe unten). - -**Verwendung:** -- Zu Beginn des Kita-Jahres (September): Keine Datei nötig -- Ab Oktober: Vorherige Ausgaben anhängen für kumulative Fairness über das Jahr -- Im Jahresverlauf sammeln sich die Ausgaben an +Historische Dienstzuteilungen für Jahres-Fairness. Format wie `ausgabe.csv`. ## Ausgabedatei ### ausgabe.csv -Dienstzuteilungen pro Tag. Diese Datei wird vom Programm erstellt. - -**Format:** +```csv +Datum,Wochentag,Frühstücksdienst,Putznotdienst,Essensausgabenotdienst,Kochen,Elternabend +2026-01-06,Montag,Sarah & Tim,Leon,Erika,, ``` -Datum, Wochentag, Frühstücksdienst, Putznotdienst, Essensausgabenotdienst, Kochen, Elternabend -2026-01-06, Montag, Sarah & Tim, Leon, Maya, , -2026-01-07, Dienstag, Maya, Sarah & Tim, Leon, , -``` - -Jede Zeile entspricht einem Tag, die Spalten enthalten die Kindernamen, denen die jeweiligen Diensttypen zugeteilt wurden. ## Verwendung @@ -137,89 +71,67 @@ Jede Zeile entspricht einem Tag, die Spalten enthalten die Kindernamen, denen di ./elterndienstplaner.py [] ``` -**Parameter:** -- `eingabe.csv`: Benötigte Diensttypen und Eltern-Präferenzen für den Planungsmonat -- `eltern.csv`: Dienstfaktoren der Eltern (Anzahl betreuter Kinder) -- `ausgabe.csv`: Hier werden die Zuteilungen geschrieben -- `vorherige-ausgaben.csv` (optional): Historische Zuteilungen für Fairness über das Jahr +## Constraints -## Wie werden die Constraints umgesetzt? +### Harte Constraints (müssen erfüllt sein) -Dieser Abschnitt erklärt die technische Umsetzung für technisch interessierte Eltern. +- **C1:** Maximal 1× pro Woche pro Diensttyp +- **C2:** Maximal 1 Dienst pro Tag +- **C3:** Nur bei Verfügbarkeit (keine `x` in eingabe.csv) +- **C4:** Alle benötigten Dienste werden besetzt -### Mathematisches Optimierungsproblem +### Fairness (werden optimiert) -Der Elterndienstplaner formuliert die Dienstverteilung als **lineares Optimierungsproblem**. Das bedeutet: Es gibt viele mögliche Dienstverteilungen, die alle die harten Constraints (C1-C4) erfüllen. Das Programm sucht diejenige, die die Fairness-Ziele am besten erfüllt und Präferenzen berücksichtigt. +- **F1 (Global):** Faire Jahresverteilung pro Diensttyp +- **F2 (Lokal):** Faire Monatsverteilung pro Diensttyp + - **Besonderheit:** Abwesenheitstage = Dienstfaktor 0, werden nicht nachgeholt im selben Monat +- **F3 (Global):** Ausgewogene Gesamtdienste über Jahr +- **F4 (Lokal):** Ausgewogene Gesamtdienste im Monat -**Entscheidungsvariablen:** Für jeden Tag, jeden Eintrag und jeden Diensttyp gibt es eine Variable: "Wird Sarah & Tim am 6. Januar der Frühstücksdienst zugeteilt?" (Ja/Nein) +### Präferenzen (niedrige Gewichtung) -**Constraints (Nebenbedingungen):** Diese schränken die möglichen Lösungen ein: +- **P1:** Bevorzugte Dienste (`+`) werden bevorzugt zugeteilt +- **P2:** Abgelehnte Dienste (`-`) werden vermieden -- **C1 (Wöchentliches Limit):** Für jeden Eintrag und jeden Diensttyp: Die Summe der Zuweisungen pro Woche ≤ 1 -- **C2 (Tageslimit):** Für jeden Eintrag und jeden Tag: Die Summe aller Zuweisungen ≤ 1 -- **C3 (Verfügbarkeit):** Wenn im Feld "x" steht, wird die entsprechende Variable auf 0 gesetzt -- **C4 (Bedarfsdeckung):** Für jeden Tag und Diensttyp: Summe der Zuweisungen = benötigte Personenzahl +## Technische Details -### Zielfunktion: Fairness und Präferenzen +### Optimierungsproblem -Die **Zielfunktion** bewertet, wie gut eine Dienstverteilung ist. Das Programm minimiert Abweichungen von fairer Verteilung und berücksichtigt Präferenzen. +**Entscheidungsvariablen:** +- Binär: `x[eltern, tag, dienst]` = 1 wenn zugeteilt, 0 sonst -**F1 (Globale Fairness):** -- Berechnung: Für jeden Eintrag und jeden Diensttyp wird gezählt, wie viele Zuteilungen bisher über das Jahr verteilt wurden (aus `vorherige-ausgaben.csv`) -- Ziel: Die Gesamtanzahl soll proportional zum Dienstfaktor sein -- Beispiel: Sarah & Tim (Dienstfaktor 2) hatten bisher 10 Zuteilungen, Leon (Dienstfaktor 1) hatte 8 Zuteilungen. Das ist unfair (sollte 2:1 sein, also z.B. 12:6). Im aktuellen Monat sollte Leon bevorzugt werden, um das auszugleichen. -**F2 (Lokale Fairness):** -- Berechnung: Nur für den aktuellen Planungsmonat -- Ziel: Die Anzahl der Zuteilungen im aktuellen Monat soll proportional zum Dienstfaktor sein -- **Besonderheit Abwesenheiten:** Abwesenheitstage werden aus der Dienstpflicht herausgerechnet (Dienstfaktor = 0). Das bedeutet: Bei einer 2-wöchigen Abwesenheit werden in den verbleibenden 2 Wochen keine zusätzlichen Dienste zugeteilt, um die Abwesenheit auszugleichen. -- **Warum?** Dies führt zu einer gleichmäßigeren Verteilung im aktuellen Monat und verhindert, dass Familien in den wenigen verfügbaren Tagen überproportional viele Dienste bekommen müssen. -- **Ausgleich:** Die durch Abwesenheit "verpassten" Dienste werden über F1 (globale Fairness) im Jahresverlauf ausgeglichen. -- Beispiel: Im Januar sollten Sarah & Tim ca. 2× so viele Zuteilungen erhalten wie Leon (sofern beide den ganzen Monat verfügbar sind) +**Zielfunktion:** -**F3 (Dienstübergreifende Fairness - Global):** -- Berechnung: Gesamtanzahl aller Zuteilungen (über alle Diensttypen) pro Eintrag über das ganze Jahr -- Ziel: Verhindert, dass einzelne Familien über verschiedene Diensttypen hinweg zu viele Zuteilungen bekommen -- Beispiel: Sarah & Tim hatten bisher 10 Zuteilungen über alle Diensttypen, Leon nur 3. Das Verhältnis sollte 2:1 sein (12:6). F3 würde Leon im aktuellen Monat bevorzugen. +Minimiert gewichtete Summe der Abweichungen von fairer Verteilung unter Berücksichtigung von Präferenzen. Lokale Fairness (aktueller Monat) hat höchste Priorität, gefolgt von globaler Fairness (ganzes Jahr). -**F4 (Dienstübergreifende Fairness - Lokal):** -- Berechnung: Gesamtanzahl aller Zuteilungen (über alle Diensttypen) pro Eintrag im aktuellen Monat -- Ziel: Verhindert, dass einzelne Familien im aktuellen Monat über verschiedene Diensttypen hinweg zu viele Zuteilungen bekommen -- Beispiel: Im Januar werden Sarah & Tim 3× Frühstück, 2× Putzen, 2× Essen = 7 Zuteilungen zugeteilt. Leon bekommt nur 1× Frühstück, 1× Putzen = 2 Zuteilungen. F4 würde Leon weitere Zuteilungen zuweisen, um die Gesamtzahl im Monat anzugleichen. +### Lokale vs. Globale Fairness -**P1 und P2 (Präferenzen):** -- An bestimmten Tagen bevorzugte Diensttypen (`+`) bekommen einen Bonus in der Zielfunktion -- An bestimmten Tagen abgelehnte Diensttypen (`-`) bekommen eine Strafe in der Zielfunktion -- Diese Effekte sind **schwächer** als die Fairness-Terme, d.h. Fairness hat Vorrang -- **Wichtig:** Präferenzen beeinflussen nur, an welchen Tagen welcher Diensttyp zugeteilt wird, nicht die Gesamtanzahl der Zuteilungen +**Lokal (F2/F4):** +- Nur aktueller Planungsmonat +- Abwesenheitstage: Dienstfaktor = 0 +- Ziel: Gleichmäßige Verteilung im Monat -### Gewichtung +**Global (F1/F3):** +- Historische Daten + aktueller Monat +- Abwesenheitstage: Dienstfaktor wie in eltern.csv +- Ziel: Ausgleich über das Kitajahr +- Bereits geleistete Dienste werden abgezogen -Die verschiedenen Fairness-Ziele werden gewichtet: -- **F1 (global): 40%** - Wichtig für Ausgleich über das Jahr (pro Diensttyp) -- **F2 (lokal): 60%** - Wichtiger für den aktuellen Monat (pro Diensttyp) -- **F3 (global): 10%** - Verhindert extreme Ungleichverteilung über Diensttypen im Jahr -- **F4 (lokal): 15%** - Verhindert extreme Ungleichverteilung über Diensttypen im Monat -- **P1/P2: niedrig** - Präferenzen werden berücksichtigt, wenn Fairness gewahrt ist +## Programmausgabe -## Programmausgabe und Statistiken +1. **Zuteilungen pro Familie:** Anzahl je Diensttyp +2. **Dienstfaktoren-Summe:** Im Planungszeitraum +3. **Verteilungsvergleich:** Soll (lokal/global) vs. Ist +4. **Präferenz-Verletzungen:** Anzahl abgelehnte/nicht-erfüllte Präferenzen -Das Programm zeigt nach der Optimierung: - -1. **Zuteilungen pro Eintrag**: Übersicht der zugeteilten Diensttypen für jeden Eintrag -2. **Dienstfaktoren**: Summe der Dienstfaktoren im Planungszeitraum -3. **Verteilungsvergleich**: - - Soll-Werte (lokal und global) basierend auf Fairness - - Ist-Werte (tatsächlich zugeteilte Diensttypen) - - Abweichungen zwischen Soll und Ist -4. **Präferenz-Verletzungen**: Wie oft wurden abgelehnte Diensttypen (`-`) trotzdem zugeteilt ## Troubleshooting **"Keine optimale Lösung gefunden":** -- Zu viele Eltern nicht verfügbar -- Nicht genug Eltern für alle benötigten Diensttypen +- Zu viele Abwesenheiten +- Nicht genug verfügbare Eltern für benötigte Dienste **"Unfaire Verteilung":** - Dienstfaktoren in `eltern.csv` prüfen -- Sicherstellen, dass `vorherige.ausgaben.csv` korrekt ist +- `vorherige-ausgaben.csv` auf Korrektheit prüfen diff --git a/anleitung-eltern.md b/anleitung-eltern.md new file mode 100644 index 0000000..bbf862a --- /dev/null +++ b/anleitung-eltern.md @@ -0,0 +1,80 @@ +# Anleitung: Abwesenheiten und Präferenzen angeben + +Diese Anleitung erklärt, wie ihr eure Abwesenheiten und Präferenzen für die Elterndienst-Planung angebt. + +## Was sind Präferenzen? + +An welchen Tagen ihr welche Dienste gern (oder lieber nicht) machen möchtet. + +**Berücksichtigung der Präferenzen** +- Präferenzen beeinflussen **an welchen Tagen** ihr Dienste bekommt. +- Sie beeinflussen wenig, wie viele Dienste ihr bekommt. +- Fairness hat Vorrang: Wenn es für eine faire Verteilung nötig ist, werden eure Präferenzen ggf. nicht berücksichtigt. + +## Bearbeiten der Monatsvorlage + +Ihr erhaltet eine Datei `eingabe-monat-vorlage.csv`. + +**Änderungen:** +1. Spaltenüberschrift `Eingabe` durch euren Kindernamen ersetzen +2. In dieser Spalte eure Abwesenheiten/Präferenzen eintragen + +**Programm zum Öffnen:** +- Computer: LibreOffice Calc, Excel oder Texteditor +- Android: App "CSV Editor" +- iOS: Dateien-App + +## Eintragen + +### Dienstkürzel + +**F** = Frühstücksdienst, **P** = Putznotdienst, **E** = Essensausgabenotdienst, **K** = Kochen, **A** = Elternabend + +### Was eintragen? + +| Eingabe | Bedeutung | +|---------|-----------| +| `x` | Abwesend | +| `F+` | Frühstücksdienst gern | +| `P-` | Putznotdienst lieber nicht | + +**Kombinierbar:** `F+P-K+` = "Frühstück/Kochen gern, Putzen nicht" +**Leer:** Verfügbar, keine Präferenz + +## Beispiel + +Angenommen, euer Kind heißt Erika und ihr seid vom 6. bis 10. April im Urlaub, wollt gern dienstags oder freitags Frühstücksdienst machen, und am 15., 22. und 29. lieber keinen Frühstücks-, Putz- oder Essensdienst. + +Die Tabelle sieht dann so aus: + +```csv +Datum , Wochentag , Dienste, Erika +2026-04-01, Mittwoch , FPE , +2026-04-02, Donnerstag, FPE , +2026-04-03, Freitag , , F+ +2026-04-06, Montag , , x +2026-04-07, Dienstag , FPE , x +2026-04-08, Mittwoch , FPE , x +2026-04-09, Donnerstag, FPE , x +2026-04-10, Freitag , FPEK , x +2026-04-13, Montag , FPE , +2026-04-14, Dienstag , FPE , F+ +2026-04-15, Mittwoch , FPE , F-P-E- +2026-04-16, Donnerstag, FPEA , +2026-04-17, Freitag , FPE , F+ +2026-04-20, Montag , FPE , +2026-04-21, Dienstag , FPE , F+ +2026-04-22, Mittwoch , FPE , F-P-E- +2026-04-23, Donnerstag, FPE , +2026-04-24, Freitag , FPEK , F+K+ +2026-04-27, Montag , FPE , +2026-04-28, Dienstag , FPE , F+ +2026-04-29, Mittwoch , FPE , F-P-E- +2026-04-30, Donnerstag, FPE , +``` + +**Anmerkungen zum Beispiel:** +- Am 3. April ist `F+` eingetragen, obwohl keine Dienste anfallen (Spalte "Dienste" ist leer). Das hat keine Auswirkung. +- Am 24. April sind sowohl Frühstücksdienst als auch Kochen gewünscht (`F+K+`). Ihr bekommt aber maximal einen davon, da pro Tag nur ein Dienst erlaubt ist. +- Die Präferenzen am 15., 22. und 29. (`F-P-E-`) werden nach Möglichkeit berücksichtigt, aber wenn es für eine faire Verteilung nötig ist, könntet ihr trotzdem einen dieser Dienste bekommen. +