Enhance Falukant family and production dynamics: Updated FalukantFamilyWorker to include public stability and household tension calculations, integrating new SQL queries for managing marriage states and household attributes. Added FalukantCertificateWorker for production certificate management, enhancing overall family interaction and production tracking.

This commit is contained in:
Torsten Schulz (local)
2026-03-23 09:02:51 +01:00
parent d921dc2f7e
commit fe0361971d
10 changed files with 997 additions and 12 deletions

View File

@@ -2,6 +2,8 @@
Technische Abstimmung mit dem Übergabedokument im Backend-Projekt (`FALUKANT_LOVERS_DAEMON_SPEC.md` / `FALUKANT_LOVERS_TECHNICAL_CONCEPT.md`).
**Ehe & Hausfrieden (Phase A):** [`FALUKANT_MARRIAGE_HOUSEPEACE_DAEMON_HANDOFF.md`](./FALUKANT_MARRIAGE_HOUSEPEACE_DAEMON_HANDOFF.md)
## Abweichungen / Zuordnung
| Handoff / Backend | YpDaemon |
@@ -55,6 +57,7 @@ Ehe-Malus „≤ 15“ gilt pro Ehe, wenn **irgendeine** berührende Liebschaft
2. Optional: `migrations/002_falukant_family_rename_legacy_columns.sql` bei Altbestand
3. `migrations/003_falukant_family_marriage_buffs.sql` — Ehe-Buffs (`marriage_gift_buff_days_remaining`, `marriage_pending_feast_bonus`, `marriage_house_supply`, `marriage_no_lover_bonus_counter`); Daily-Tick schreibt Zufriedenheit + Zähler via `QUERY_UPDATE_MARRIAGE_STATE_AND_BUFFS`.
4. `migrations/004_falukant_servants_daemon.sql` — Dienerschaft: Tick-Idempotenz + `servant_discretion_modifier` (Stammdaten-Dienerfelder kommen aus dem Backend). Siehe [`FALUKANT_SERVANTS_DAEMON.md`](./FALUKANT_SERVANTS_DAEMON.md).
5. `migrations/005_falukant_marriage_housepeace.sql``relationship.marriage_public_stability`, `user_house.household_tension_score`. Siehe [`FALUKANT_MARRIAGE_HOUSEPEACE_DAEMON_HANDOFF.md`](./FALUKANT_MARRIAGE_HOUSEPEACE_DAEMON_HANDOFF.md).
### Ehe-Buffs (Daemon)

View File

@@ -0,0 +1,156 @@
# Falukant: Daemon-Handoff für Ehe und Hausfrieden
Dieses Dokument beschreibt den Stand nach Phase A und die Rolle des externen Daemons (Übergabe Backend ↔ YpDaemon).
## 1. Was im Projekt jetzt vorhanden ist
Backend-/API-seitig vorhanden:
- `relationship_state.marriage_satisfaction`
- `relationship_state.marriage_public_stability`
- aktive Liebschaften mit:
- `visibility`
- `discretion`
- `maintenance_level`
- `status_fit`
- `months_underfunded`
- `acknowledged`
- `user_house` mit:
- `servant_count`
- `servant_quality`
- `servant_pay_level`
- `household_order`
- Family-API liefert jetzt zusätzlich:
- `householdTension`
- `householdTensionScore`
- `householdTensionReasons`
Direkte Spieleraktionen vorhanden:
- `POST /api/falukant/family/marriage/spend-time`
- `POST /api/falukant/family/marriage/gift`
- `POST /api/falukant/family/marriage/reconcile`
- `POST /api/falukant/houses/order`
## 2. Daily-Input für den externen Daemon
Pro betroffenem Falukant-User:
- `falukant_user.id`
- `user.id` / `user.hashed_id`
- aktive Ehe-`relationship` mit `relationship_state`
- aktive Liebschaften mit `relationship_state`
- Kinder mit:
- `birth_context`
- `legitimacy`
- `public_known`
- Haus mit:
- `servant_count`
- `servant_quality`
- `servant_pay_level`
- `household_order`
- Charakter mit:
- `reputation`
- `title_of_nobility`
## 3. Was der Daemon täglich berechnen soll
### Ehe
- Drift von `marriage_satisfaction`
- Drift von `marriage_public_stability`
- Einfluss aus:
- sichtbaren Liebschaften
- unterfinanzierten Liebschaften
- Standesunterschieden
- Dienerschaft / Haushaltsordnung
- zu jungen Liebschaften
### Hausfrieden
Der Daemon soll intern einen numerischen Spannungswert pflegen oder berechnen:
- `householdTensionScore` `0..100`
Einflussfaktoren:
- sichtbare Liebschaften
- anerkannte Liebschaften
- unterfinanzierte Liebschaften
- Kinder aus Liebschaften
- Haushaltsordnung
- Dienerschaft
- schwache Ehe
UI-Ableitung:
- `0..24` => `low`
- `25..59` => `medium`
- `60..100` => `high`
## 4. Was der Daemon zurückschreiben soll
Pflicht:
- `relationship_state.marriage_satisfaction`
- `relationship_state.marriage_public_stability`
- lover-state-Felder bei Änderungen:
- `visibility`
- `discretion`
- `months_underfunded`
- optional `notes_json` / `flags_json`
- falls eigener Persistenzwert eingeführt wird:
- `household_tension_score`
Wenn kein eigener Persistenzwert eingeführt wird:
- der Daemon darf den Spannungswert auch nur berechnen
- die API kann ihn weiterhin aus Ehe, Liebschaften, Kindern und Haus ableiten
## 5. Socket-/Refresh-Verhalten
Wenn Daily-/Monthly-Verarbeitung Ehe oder Hausfrieden betrifft:
- `falukantUpdateFamily` mit `reason: "daily"` oder `reason: "monthly"`
- danach `falukantUpdateStatus`
Wenn ein Sonderereignis entsteht:
- `reason: "scandal"` zusätzlich
## 6. Wichtige Phase-A-Regel
Die neuen Direktaktionen geben nur Sofortimpulse:
- `spend-time`
- `gift`
- `reconcile`
- `house/order`
Der Daemon ist weiterhin verantwortlich für:
- Rückdrift
- Gegenkräfte
- Langzeiteffekte
- Balancing
Kurz:
- UI/Backend setzen kleine direkte Impulse
- der Daemon bestimmt die dauerhafte Entwicklung
---
## Anhang: Abgleich YpDaemon (dieses Repo)
| Thema | Stand in YpDaemon |
|-------|---------------------|
| Ehe-Zufriedenheit, Buffs, Drift (`marriage_drift_*`) | `FalukantFamilyWorker` + Migrationen `001`/`003`, siehe [`FALUKANT_DAEMON_HANDOFF.md`](./FALUKANT_DAEMON_HANDOFF.md) |
| **`marriage_public_stability`** (Daily-Drift) | Migration **`005`**, `QUERY_GET_MARRIAGE_ROWS` / `QUERY_UPDATE_MARRIAGE_STATE_AND_BUFFS`, Logik in `falukant_family.rs` (Einfluss: sichtbare/unterfinanzierte/anerkannte Liebschaften, Stand, Alter, Haushalt/Diener, schwache Ehe) |
| **`household_tension_score`** (0..100) | Migration **`005`**, berechnet im Daily-Tick, persistiert in `user_house`; UI-Band **low/medium/high** weiterhin aus Score ableitbar (024 / 2559 / 60100) |
| Liebschaften (visibility, discretion, …, **`acknowledged`**, **`months_underfunded`**) | Daily-Query erweitert; Tension-Aggregation nutzt diese Felder |
| Dienerschaft / `household_order` | `falukant_servants.rs` + Migration `004`; zusätzlich in Ehe-Stabilität und Haus-Spannung |
| WebSocket | Bei Änderung von Ehe oder Spannung: `falukantUpdateFamily` mit `reason: "daily"` (wie bisher) |
| **HTTP-Routen** (`spend-time`, `gift`, …) | Liegen im **Backend** (nicht im Daemon-Repo) |
Verwandte Doku: [`FALUKANT_UI_WEBSOCKET.md`](./FALUKANT_UI_WEBSOCKET.md), [`FALUKANT_SERVANTS_DAEMON.md`](./FALUKANT_SERVANTS_DAEMON.md).

View File

@@ -0,0 +1,41 @@
# Falukant: Produktionszertifikate (Daemon)
Der **`FalukantCertificateWorker`** berechnet einmal täglich die Zielstufe und schreibt `falukant_user.certificate` fort (max. **+1** pro Tag, keine normale Herabstufung).
## SQL
- `QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS` Eingangsdaten je Falukant-User (Spielercharakter, Wissen, Produktionen, Ämter, Haus …)
- `QUERY_UPDATE_FALUKANT_USER_CERTIFICATE` Update der Stufe
## Logik (Kurz)
- `certificateScore` aus gewichteten Punktwerten (Wissen, Produktion, Amt, Adel, Ruf, Haus)
- `raw_target` aus Score-Schwellen (1.2 / 2.1 / 3.0 / 4.0)
- `effective_target` mit Mindestanforderungen je Stufe (Spec §4.5)
- Aufstieg nur wenn `effective_target > current`**`current + 1`** (gegen `effective_target` begrenzt)
- **Bankrott** (`money <= -5000`): Zertifikat auf **1**, mit Event
## Politische Ämter
Rang aus **`political_office_type.name`** (Substring-Heuristik im Daemon, ohne DB-Änderung). Anpassung über `political_name_to_rank` in `falukant_certificate.rs`.
## Kirchliche Ämter
`officePoints` aus **`max(hierarchy_level)`** der aktiven `church_office`-Zeilen (gekappt 05).
## Abgeschlossene Produktionen
**`COUNT(*)`** aus `falukant_log.production` mit `producer_id = falukant_user.id` (Zeilen = aggregierte Log-Einträge).
## Events (WebSocket)
Bei Änderung der Stufe:
1. `falukantUpdateProductionCertificate` mit `reason: "daily_recalculation"`, `old_certificate`, `new_certificate`
2. `falukantUpdateStatus`
## Nicht umgesetzt (optional / später)
- **Tod ohne Erben** / Zertifikats-Reset
- Feinere **Bankrott**-Definition
- **`political_office_history`** (nicht im Repo)

View File

@@ -12,6 +12,7 @@ Dieses Dokument beschreibt die **Nachrichten**, die der **YpDaemon** (`FalukantF
|---------|----------------|----------------------|
| `falukantUpdateFamily` | `user_id`, `reason` | Gezielter Refresh Familie/Liebe/Geld je nach `reason` |
| `falukantUpdateStatus` | `user_id` | Allgemeiner Status-/Spielstand-Refresh (wie bisher) |
| `falukantUpdateProductionCertificate` | `user_id`, `reason`, `old_certificate`, `new_certificate` | Produkte / Produktions-UI / Zertifikat neu laden (nach Daily-Recalc oder Bankrott) |
| `children_update` | `user_id` | Kinderliste / FamilyView aktualisieren |
| `falukant_family_scandal_hint` | `relationship_id` | Optional: Toast, Log **kein** `user_id` (siehe unten) |
@@ -33,7 +34,7 @@ Dieses Dokument beschreibt die **Nachrichten**, die der **YpDaemon** (`FalukantF
| `reason` | Bedeutung (Daemon) | Empfehlung UI |
|----------|---------------------|---------------|
| `daily` | Daily-Tick: Liebschafts-/Ehe-/Ansehens-Logik für den Tag | Family-API + ggf. Charakter/Ansehen neu laden |
| `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: Kosten, Unterversorgung, Monatsstand | **Geld** (`falukant_user.money`) + 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 |
@@ -49,7 +50,22 @@ Dieses Dokument beschreibt die **Nachrichten**, die der **YpDaemon** (`FalukantF
Kommt **typischerweise direkt nach** `falukantUpdateFamily` mit derselben `user_id` (gemeinsamer Refresh).
### 2.3 `children_update`
### 2.3 `falukantUpdateProductionCertificate`
```json
{
"event": "falukantUpdateProductionCertificate",
"user_id": 123,
"reason": "daily_recalculation",
"old_certificate": 2,
"new_certificate": 3
}
```
- **`reason`:** in der ersten Version fest `daily_recalculation` (inkl. Bankrott-Herabstufung, falls so umgesetzt).
- Danach sendet der Daemon **`falukantUpdateStatus`** mit derselben `user_id` (wie bei anderen Falukant-Events).
### 2.4 `children_update`
```json
{
@@ -60,7 +76,7 @@ Kommt **typischerweise direkt nach** `falukantUpdateFamily` mit derselben `user_
Tritt bei **Geburt aus Liebschaft** auf; oft zusammen mit `falukantUpdateFamily` (`reason: lover_birth`) und `falukantUpdateStatus`.
### 2.4 `falukant_family_scandal_hint`
### 2.5 `falukant_family_scandal_hint`
```json
{
@@ -84,6 +100,10 @@ onMessage(json):
refreshPlayerStatus() // bestehend
return
case "falukantUpdateProductionCertificate":
refreshProductsAndProductionUi() // Zertifikat / erlaubte Produkte
return
case "children_update":
refreshChildrenAndFamilyView()
return