Files
yourpart3/docs/FALUKANT_PREGNANCY_SCHEDULED_BIRTH_DAEMON_SPEC.md
Torsten Schulz (local) 6b3aee458a
All checks were successful
Deploy to production / deploy (push) Successful in 2m57s
feat(bisaya-course): expand exercises for shopping, neighborhood visits, conflict resolution, and free speaking
- Added new exercises in multiple-choice, gap-fill, and situational response formats for categories including 'Einkaufen vertiefen', 'Nachbarschaft & Besuche', 'Rollenspiel - Konflikt und Hilfe', and 'Freies Sprechen - Alltag ohne Stütze'.
- Each exercise includes detailed instructions, question data, answer data, and explanations to enhance the learning experience for Bisaya language learners.
- Focused on practical scenarios to improve conversational skills and vocabulary retention.
2026-03-31 09:04:24 +02:00

9.0 KiB
Raw Blame History

Falukant: Geplante Schwangerschaft & Geburt Daemon- und Datenbankkonzept

Dieses Dokument beschreibt das vereinheitlichte Konzept für Schwangerschaft, die der externe Daemon (UserCharacterWorker, C++) verarbeiten soll, sowie die Datenbank und die Abgrenzung zur bestehenden Zufallslogik. Ziel ist, dass gesetzte Termine (pregnancy_due_at) und der gewählte Vater (pregnancy_father_character_id) u.a. aus dem Admin-Tool tatsächlich zu Geburten führen, ohne dass nur die Node-API „Geburt erzwingen“ funktioniert.


1. Ist-Zustand (Problem)

1.1 Datenbank (bereits vorhanden)

Auf falukant_data."character" existieren (siehe backend/sql/add_character_pregnancy.sql):

Spalte Typ Bedeutung
pregnancy_due_at TIMESTAMPTZ NULL Erwarteter Geburtstermin
pregnancy_father_character_id INTEGER NULL, FK auf character(id) Vater-Charakter

Die Node-Backend-Logik (Admin, falukantService) liest und schreibt diese Felder.

1.2 Daemon aktuelles Verhalten

In src/usercharacterworker.cpp / src/usercharacterworker.h:

  • processPregnancies() führt QUERY_GET_PREGNANCY_CANDIDATES aus.
  • Diese Query:
    • bezieht sich nur auf Ehen (falukant_type.relationship.tr = 'married'),
    • nutzt keine pregnancy_*-Spalten,
    • modelliert Geburten per Zufallsprozess (altersabhängige Wahrscheinlichkeit),
    • setzt implizit character1_id = Vater und character2_id = Mutter (fest verdrahtet, ohne Geschlechts- oder Rollenprüfung).

Folge: Wer im Spiel oder per Admin als „schwanger“ mit Termin und Vater gespeichert wird, wird vom Daemon nicht erkannt. Geburten aus diesem Konzept passieren nur, wenn sie manuell per Node (z.B. Admin „Geburt erzwingen“) ausgelöst werden.

Zusätzlich: QUERY_AUTOBATISM setzt nur child_relation.name_set nach einigen Tagen hat nichts mit Schwangerschafts-Spalten zu tun.


2. Soll-Konzept (Zwei parallele Wege, eine klare Priorität)

2.1 Weg A Geplante Schwangerschaft (DB-gesteuert, neu für den Daemon)

Auslöser: pregnancy_due_at ist gesetzt und der Zeitpunkt ist fällig.

Regeln (Vorschlag):

  1. Eine Mutter ist immer der Datensatz in character, auf dem pregnancy_due_at und die Schwangerschaft „liegen“.
  2. Vater: pregnancy_father_character_id
    • Wenn gesetzt: muss ein existierender Charakter sein, nicht mother.id.
    • Wenn NULL: Policy festlegen (siehe Abschnitt 8).
  3. Fälligkeit: z.B. date_trunc('day', pregnancy_due_at AT TIME ZONE 'Europe/Berlin') <= current_date (oder einheitlich UTC wichtig ist eine Definition im Team).
  4. Nach erfolgreicher Geburt: pregnancy_due_at und pregnancy_father_character_id auf NULL setzen (Schwangerschaft beendet).

Dieser Weg entspricht dem, was Admin und Spieler erwarten, wenn ein Termin existiert.

2.2 Weg B Legacy: Zufallsgeburten bei Ehe (bestehende Query)

Die Query QUERY_GET_PREGNANCY_CANDIDATES modelliert „natürliche“ Zufallsgeburten ohne pregnancy_*-Felder.

Entscheidung für die Umsetzung:

  • Option B1: Weg B abschalten oder stark reduzieren, wenn Weg A das offizielle Modell ist.
  • Option B2: Weg B beibehalten für Atmosphäre, aber nur, wenn keine aktive geplante Schwangerschaft auf den betroffenen Charakteren existiert (doppelte Geburten vermeiden).
  • Option B3: Weg B nur noch Simulation, bis Spiel-Logik „Konzeption“ explizit setzt (größerer Umbau).

Empfehlung: Mindestens B2 oder B1, damit keine zwei Geburten pro Tag für dieselbe Ehe aus unterschiedlichen Regeln entstehen.


3. Datenbank Erweiterungen (Vorschlag)

Die Minimalvariante kommt ohne neue Spalten aus (nur Daemon-Logik). Für Robustheit und spätere Features sind optionale Erweiterungen sinnvoll:

3.1 Pflicht (kein Schema-Zwang, aber empfohlen)

  • Index für den Daemon-Tick, z.B.:
CREATE INDEX IF NOT EXISTS idx_character_pregnancy_due
  ON falukant_data."character" (pregnancy_due_at)
  WHERE pregnancy_due_at IS NOT NULL;

3.2 Optional Metadaten

Spalte Typ Zweck
pregnancy_source TEXT oder ENUM z.B. admin, gameplay, npc für Logging und Regeln
pregnancy_conception_at TIMESTAMPTZ optional, für Anzeige/Quests
pregnancy_birth_context TEXT marriage

Wenn pregnancy_birth_context nicht eingeführt wird, leitet der Daemon den Kontext aus der Beziehung zwischen Mutter und Vater ab (verheiratet → marriage, Liebhaber → lover, sonst Default marriage oder Policy).

3.3 child_relation Parität mit Node

Das Sequelize-Modell erwartet u.a. father_name, mother_name, legitimacy, birth_context, public_known. Die Daemon-INSERT-Query (QUERY_INSERT_CHILD_RELATION) muss mit der realen DB übereinstimmen (Pflichtfelder, Defaults). Falls nötig:

  • INSERT um Namen (aus Vordefiniert-Tabellen) und legitimacy / birth_context / public_known erweitern,
  • oder DB-Defaults / Trigger ergänzen,
  • gleiche Semantik wie adminForceFalukantBirth in adminService.js anstreben.

4. Daemon Umsetzung (technisch)

4.1 Neue SQL-Query: „fällige geplante Geburten“

Skizze (logisch):

  • SELECT Mutter-character c mit:
    • c.pregnancy_due_at IS NOT NULL
    • c.pregnancy_due_at fällig (siehe Zeitzone)
    • JOIN Vater c_father auf c.pregnancy_father_character_id = c_father.id wenn Vater Pflicht ist
  • Pro Zeile: father_cid, mother_cid, region_id, title_of_nobility (vom passenden Elternteil), last_name, father_uid, mother_uid analog zur bestehenden Schleife.

Wichtig: Vater/Mutter nicht aus relationship.character1/2 ableiten, sondern aus expliziten IDs (pregnancy_father_character_id + Zeilen-ID der Mutter).

4.2 Ablauf in processPregnancies()

  1. QUERY_AUTOBATISM wie bisher (optional, Reihenfolge beachten).
  2. Neu: Transaktion oder feste Reihenfolge:
    • Kandidaten für geplante Geburt laden
    • pro Kandidat: Kind einfügen (QUERY_INSERT_CHILD oder gemeinsame Funktion), child_relation einfügen, Schwangerschaft auf der Mutter leeren
    • Benachrichtigungen (children_update, falukantUpdateStatus) wie bei bestehender Schleife
  3. Legacy-Query nur ausführen, wenn nach Absprache (Option B1B3).

Idempotenz: Pro Tick darf dieselbe schwangere Zeile nicht zweimal gebären. Am sichersten: UPDATE … RETURNING oder DELETE der Schwangerschaftsdaten in derselben Transaktion wie das Kind.

4.3 Geschlecht der Eltern

Optional: Plausibilitätsprüfung (gender Mutter/Vater) kann im ersten Schritt weggelassen werden, sollte aber langfristig mit dem Spielregelwerk übereinstimmen.


5. Backend (Node) Abstimmung

  • Zeitzonen: pregnancy_due_at wird in JS als Date gesetzt; Daemon muss dieselbe Fälligkeitsdefinition nutzen wie die UI („heute“ = 0 Tage).
  • WebSocket: Nach Daemon-Geburt dieselben Events wie bei Admin-Geburt, damit Clients die Familie aktualisieren.

6. Frontend

  • Hinweis in der Familien-Ansicht: „Geburt erfolgt automatisch am Termin“ (wenn Daemon aktiv), sonst „nur nach Admin-Aktion“ je nach Rollout.

7. Test-Checkliste

  • Admin: Schwangerschaft mit Termin heute und Vater nach Daemon-Lauf: Kind existiert, Schwangerschaft weg.
  • Kein Vater (NULL) definiertes Verhalten (Fehler loggen / überspringen / NPC-Vater Policy).
  • Doppel-Tick: keine doppelte Geburt.
  • Legacy-Zufallsgeburt: keine Kollision mit aktivem pregnancy_due_at auf derselben Mutter.
  • child_relation und character-Kind konsistent mit Node-Admin-Geburt.

8. Offene Policy-Fragen (bitte vor Implementierung festlegen)

  1. Vater NULL: Geburt abbrechen, stillen Vater aus Beziehung erraten, oder festen Platzhalter?
  2. Legacy-Query: komplett entfernen oder nur noch unter Bedingungen?
  3. Zeitzone für „Termin ist heute“: Server-UTC, Europe/Berlin, oder Nutzer-TZ?
  4. Liebschaftsgeburten: nur über pregnancy_* + birth_context/pregnancy_birth_context, nie über reine Ehe-Query?

9. Referenzdateien im Repo

Bereich Datei
Daemon src/usercharacterworker.cpp (processPregnancies)
SQL-Strings src/usercharacterworker.h (QUERY_GET_PREGNANCY_CANDIDATES, QUERY_INSERT_CHILD, QUERY_INSERT_CHILD_RELATION)
DB-Spalten Schwangerschaft backend/sql/add_character_pregnancy.sql
Modell Character backend/models/falukant/data/character.js
Admin / Geburt Node backend/services/adminService.js (adminForceFalukantPregnancy, adminForceFalukantBirth)
Familie API backend/services/falukantService.js (_getCharacterPregnancyOptional, getFamily)

Stand: technische Analyse des Repos; zur Abstimmung mit Game-Design und Deployment des Daemons.