Refactor Falukant daemon logic for time-based processing: Updated the handling of monthly servant costs and lover installments to align with the new game time model, introducing a unified "Monatstick" concept for cost calculations. Enhanced SQL queries and worker logic to ensure accurate processing every 2 hours, improving financial interactions and family dynamics.

This commit is contained in:
Torsten Schulz (local)
2026-03-23 10:11:49 +01:00
parent c82fbc0f7c
commit 708ffc3eda
7 changed files with 78 additions and 24 deletions

View File

@@ -0,0 +1,29 @@
# Änderungsnotiz (externer Daemon / Übergabe)
Kurznotiz zur **Abstimmung von Spielzeit, Monatsläufen und Wirtschaftswerten** — für Teams, die den Daemon einbinden oder die Spec pflegen.
## Zeitmaßstab
- **Falukant** nutzt einen stark komprimierten Zeitmaßstab: **1 Spieltag = 1 Spieljahr**.
- Der **Monatslauf** des Daemons entspricht in dieser Logik **ungefähr einem 2-Stunden-Schritt** (ein „Monatstick“ in der Spielzeit, nicht ein Kalendermonat in der Realität).
## Dienerschaft & Wirtschaft
- **Dienerkosten** dürfen **nicht** wie ein realistischer **Vollmonatslohn** skaliert oder interpretiert werden (kein 1:1-Vergleich mit realem Monatsgehalt).
- Der in Spec/Datenbank **definierte Monatswert** ist ein **abstrahierter Unterhalts- und Bindungsbetrag pro Monatstick** — er beschreibt die **ökonomische Last** im Spielmodell, nicht einen historischen Lohn.
## Datenbank
- Die Datenbank ist für diese Konzeption **bereits vorbereitet**; für diese inhaltliche Festlegung sind **keine zusätzlichen DB-Anpassungen** nötig.
## Umsetzung im Daemon (YpDaemon)
- **Gemeinsamer 2-h-Tick:** Dienerschaft (`falukant_servants::run_monthly`) und Liebschafts-Unterhalt (`process_lover_installments`) laufen im selben Intervall (`GAME_MONTH_SLICE_INTERVAL`).
- **Dienerschaft:** Abfrage über `servants_last_monthly_at` (alle 2 h fällig); Abbuchung = **1/12** des aus Stammdaten berechneten abstrakten Monatsbudgets.
- **Liebschaft:** Abbuchung = **1/12** des Monatsunterhalts; Idempotenz `lover_last_installment_at` (Migration `006`).
- **`process_monthly` (selten, ~30 Tage Wandzeit):** nur noch Liebschafts-Monatsmarkierung + Geburten — **keine** Dienerschaft mehr.
## Siehe auch
- Technisches Handoff: [`FALUKANT_DAEMON_HANDOFF.md`](./FALUKANT_DAEMON_HANDOFF.md)
- Dienerschaft im Daemon: [`FALUKANT_SERVANTS_DAEMON.md`](./FALUKANT_SERVANTS_DAEMON.md)

View File

@@ -4,6 +4,8 @@ Technische Abstimmung mit dem Übergabedokument im Backend-Projekt (`FALUKANT_LO
**Ehe & Hausfrieden (Phase A):** [`FALUKANT_MARRIAGE_HOUSEPEACE_DAEMON_HANDOFF.md`](./FALUKANT_MARRIAGE_HOUSEPEACE_DAEMON_HANDOFF.md)
**Zeitmaßstab & Monatstick (Übergabe extern):** [`FALUKANT_DAEMON_AENDERUNGSNOTIZ_ZEITMASSSTAB.md`](./FALUKANT_DAEMON_AENDERUNGSNOTIZ_ZEITMASSSTAB.md)
## Abweichungen / Zuordnung
| Handoff / Backend | YpDaemon |
@@ -12,12 +14,13 @@ Technische Abstimmung mit dem Übergabedokument im Backend-Projekt (`FALUKANT_LO
| `months_underfunded` | Spalte `months_underfunded` (Migration 001; Legacy: `002` benennt `consecutive_underpayment_months` um) |
| Idempotenz `last_daily_processed_at` / `last_monthly_processed_at` | Gesetzt von `FalukantFamilyWorker` pro Liebschaft |
| Idempotenz `lover_last_installment_at` (Migration `006`) | Gesetzt alle **2 h** pro Liebschaft nach Unterhalts-Tick (1/12 des Monatsbetrags) |
| Idempotenz `servants_last_monthly_at` (Migration `004`) | Gesetzt alle **2 h** pro Haushalt nach Dienerschafts-Tick (1/12 des abstrakten Monatsbudgets), semantisch „Monatstick“ |
## Ticks
- **Daily:** nur Zeilen mit `(last_daily_processed_at IS NULL OR last_daily_processed_at::date < CURRENT_DATE)`; danach `last_daily_processed_at = NOW()`.
- **Monthly:** nur Zeilen mit `(last_monthly_processed_at IS NULL OR date_trunc('month', last_monthly_processed_at) < date_trunc('month', CURRENT_TIMESTAMP))`; danach `last_monthly_processed_at = NOW()` (**ohne** Liebschafts-Geld — nur Monatsstand/Schwangerschafts-Logik; ggf. **Dienerschaft** `run_monthly` mit eigenen Kosten).
- **Liebschafts-Unterhalt (Spielzeit):** alle **2 h** (`lover_last_installment_at`), Betrag = **1/12** des bisherigen Monatsunterhalts (12 „Spielmonate“ pro **Spieltag** = 1 Spieljahr). Action in `money_history`: weiterhin `lover maintenance`.
- **Monthly (Kalender / Liebschaft):** nur Zeilen mit `(last_monthly_processed_at IS NULL OR date_trunc('month', last_monthly_processed_at) < date_trunc('month', CURRENT_TIMESTAMP))`; danach `last_monthly_processed_at = NOW()` **ohne** Liebschafts-Geld; Monatsstand/Schwangerschafts-Logik + `process_lover_births`.
- **Monatstick (~2 h, Spielzeit):** gemeinsamer Worker-Tick für **Dienerschaft** (`servants_last_monthly_at`, Abfrage alle 2 h) und **Liebschaft** (`lover_last_installment_at`). Beträge = **1/12** des abstrakten Monats“-Budgets pro Rolle (12 Monatsticke pro **Spieltag** = 1 Spieljahr). `money_history`: `servants_monthly` bzw. `lover maintenance`. Siehe [`FALUKANT_DAEMON_AENDERUNGSNOTIZ_ZEITMASSSTAB.md`](./FALUKANT_DAEMON_AENDERUNGSNOTIZ_ZEITMASSSTAB.md).
**Hinweis:** Der Worker nutzt weiterhin **Wandzeit** (24 h / 30 Tage / **2 h** Unterhalt) als Intervall; die Idempotenz über die Zeitstempel verhindert Doppelverarbeitung bei Neustarts am selben Tag/Monat bzw. im selben 2-h-Fenster.

View File

@@ -2,6 +2,10 @@
Umsetzung gemäß Projektspezifikation (Daily/Monthly, Handoff).
**Wichtig (Spielzeit / Kosten):** Falukant arbeitet mit **1 Spieltag = 1 Spieljahr**; Monatsläufe entsprechen **ungefähr einem 2-h-Schritt**. Dienerkosten sind **kein** realistischer Vollmonatslohn, sondern ein **abstrakter Monatstick** — siehe [`FALUKANT_DAEMON_AENDERUNGSNOTIZ_ZEITMASSSTAB.md`](./FALUKANT_DAEMON_AENDERUNGSNOTIZ_ZEITMASSSTAB.md).
**Umsetzung:** `run_monthly` wird alle **2 h** ausgeführt (gemeinsam mit Liebschafts-Raten im `FalukantFamilyWorker`). SQL: `servants_last_monthly_at` älter als 2 h oder `NULL`. Abgebucht wird **1/12** des berechneten Monatsbudgets pro Tick (`servants_monthly` in `money_history`). Spaltenname `servants_last_monthly_at` bleibt historisch; semantisch = letzter Monatstick.
## Voraussetzungen
1. **Backend:** Stammdaten in `falukant_data.user_house` (`servant_count`, `servant_quality`, `servant_pay_level`, `household_order`) — z. B. Migration aus YourPart3.
@@ -11,7 +15,7 @@ Umsetzung gemäß Projektspezifikation (Daily/Monthly, Handoff).
- Logik: `src/worker/falukant_servants.rs`
- SQL: `src/worker/sql.rs` (Abschnitt Dienerschaft)
- Ausführung: **`FalukantFamilyWorker`** ruft bei gesetztem Servant-Schema **vor** Liebschafts-Daily/Monthly `run_daily` / `run_monthly` auf (keine Race mit Liebschafts-Ticks).
- Ausführung: **`run_daily`** beim täglichen Familien-Tick; **`run_monthly`** im **2-h-Monatstick** zusammen mit Liebschafts-Installments (nicht mehr im seltenen Kalender-`process_monthly`).
## WebSocket

View File

@@ -35,7 +35,7 @@ Dieses Dokument beschreibt die **Nachrichten**, die der **YpDaemon** (`FalukantF
| `reason` | Bedeutung (Daemon) | Empfehlung UI |
|----------|---------------------|---------------|
| `daily` | Daily-Tick: Liebschafts-/Ehe-/Ansehens-Logik; u. a. `marriage_public_stability`, `household_tension_score` | Family-API + ggf. Charakter/Ansehen/Haus neu laden |
| `monthly` | Monthly-Tick: Monatsmarkierung Liebschaft (`last_monthly_processed_at`), ggf. Dienerschaft-Monatskosten; **kein** vollständiger Liebschafts-Monatsbetrag mehr | **Geld** (falls Dienerschaft zahlt) + Family-State neu laden |
| `monthly` | Kalender-`monthly` (Liebschafts-Monatsmarkierung / selten) **oder** Dienerschaft zahlt Monatstick: **Geld** (`servants_monthly`) | **Geld** + Family-State neu laden |
| `lover_installment` | Alle **2 h**: **1/12** Liebschafts-Unterhalt bzw. Unterversorgung (`money_history`: `lover maintenance`) | **Geld** + Family-State neu laden |
| `scandal` | Skandal-Ereignis (zusätzlich zu `daily` möglich) | Kurzer Hinweis / Eintrag „Skandal“; Family + Ruf |
| `lover_birth` | Uneheliches Kind angelegt | Wie `children_update`, plus Eltern-Story |