Add marriage management features: Implement endpoints for spending time with, gifting to, and reconciling with spouses in the FalukantController. Update UserHouse model to include household tension attributes. Enhance frontend components to manage marriage actions and display household tension details, including localization updates in multiple languages.
This commit is contained in:
569
docs/FALUKANT_MARRIAGE_HOUSEHOLD_CONTROL_SPEC.md
Normal file
569
docs/FALUKANT_MARRIAGE_HOUSEHOLD_CONTROL_SPEC.md
Normal file
@@ -0,0 +1,569 @@
|
||||
# Falukant: Steuerung von Ehezustand und Hausfrieden
|
||||
|
||||
Dieses Dokument beschreibt:
|
||||
|
||||
- wie Spieler `Ehezustand` und `Hausfrieden` direkt beeinflussen können
|
||||
- welche Werte dafür im Backend sichtbar und änderbar sein müssen
|
||||
- was der externe Daemon täglich und monatlich berechnen soll
|
||||
|
||||
Die Datei ist bewusst als gemeinsame Arbeitsgrundlage für UI, Backend und externen Daemon formuliert.
|
||||
|
||||
## 1. Zielbild
|
||||
|
||||
Es soll zwei getrennte, aber gekoppelte Systeme geben:
|
||||
|
||||
- `marriageSatisfaction`
|
||||
- numerisch `0..100`
|
||||
- individueller Kernwert der Ehe
|
||||
- `householdTension`
|
||||
- aggregierter Haushaltszustand
|
||||
- nach außen in UI als `low | medium | high`
|
||||
- intern sinnvollerweise als numerischer Spannungswert `0..100`
|
||||
|
||||
Interpretation:
|
||||
|
||||
- `marriageSatisfaction` beschreibt die Qualität der Paarbeziehung
|
||||
- `householdTension` beschreibt Spannungen im gesamten Haus
|
||||
- Liebschaften
|
||||
- Unterversorgung
|
||||
- Ordnung
|
||||
- Kinderkonflikte
|
||||
- Dienerschaft
|
||||
|
||||
## 2. Werte und Ableitungen
|
||||
|
||||
## 2.1 Ehe
|
||||
|
||||
Bestehend:
|
||||
|
||||
- `relationship_state.marriage_satisfaction`
|
||||
|
||||
Neu sinnvoll:
|
||||
|
||||
- `relationship_state.marriage_public_stability`
|
||||
- besteht bereits
|
||||
- soll aktiv genutzt werden
|
||||
- optional später:
|
||||
- `last_affection_action_at`
|
||||
- `last_conflict_action_at`
|
||||
- `last_shared_time_at`
|
||||
|
||||
UI-Ableitung:
|
||||
|
||||
- `0..19` => `broken`
|
||||
- `20..39` => `fragile`
|
||||
- `40..59` => `strained`
|
||||
- `60..79` => `stable`
|
||||
- `80..100` => `harmonious`
|
||||
|
||||
## 2.2 Hausfrieden
|
||||
|
||||
Der bisherige reine UI-Helfer
|
||||
|
||||
- `low`
|
||||
- `medium`
|
||||
- `high`
|
||||
|
||||
reicht für eine echte Steuerung nicht aus.
|
||||
|
||||
Neu sinnvoll:
|
||||
|
||||
- interner Wert `householdTensionScore`
|
||||
- Bereich `0..100`
|
||||
- `0` = sehr ruhig
|
||||
- `100` = offener Hauskonflikt
|
||||
|
||||
UI-Ableitung:
|
||||
|
||||
- `0..24` => `low`
|
||||
- `25..59` => `medium`
|
||||
- `60..100` => `high`
|
||||
|
||||
Falls kein eigener Persistenzwert angelegt werden soll, darf der Daemon den Score auch nur berechnen und als API-Feld zurückgeben.
|
||||
|
||||
## 3. Direkte Spieleraktionen
|
||||
|
||||
Es braucht direkte Spielzüge, die der Spieler bewusst auslösen kann.
|
||||
|
||||
Wichtig:
|
||||
|
||||
- nicht jede Aktion muss sofort große Werte ändern
|
||||
- direkte Aktionen sollen kleine, klare Effekte haben
|
||||
- der Daemon übernimmt Drift, Gegenkräfte und Folgewirkungen
|
||||
|
||||
## 3.1 Ehe-Aktionen
|
||||
|
||||
Diese Aktionen gehören fachlich in `FamilyView`.
|
||||
|
||||
### A. Zeit mit Ehepartner verbringen
|
||||
|
||||
Zweck:
|
||||
|
||||
- Standardaktion zur Pflege der Beziehung
|
||||
|
||||
Regel:
|
||||
|
||||
- verfügbar nur bei aktiver Ehe
|
||||
- Cooldown: `1x pro Tag`
|
||||
- Kosten: `0` oder sehr klein
|
||||
|
||||
Soforteffekt:
|
||||
|
||||
- `marriageSatisfaction +2`
|
||||
- `householdTensionScore -1`
|
||||
|
||||
Modifikatoren:
|
||||
|
||||
- wenn aktive sichtbare Liebschaft `visibility >= 45`: nur `+1`
|
||||
- wenn `householdOrder <= 35`: kein Bonus auf Hausfrieden
|
||||
- wenn `marriageSatisfaction < 25`: stattdessen nur `+1`
|
||||
|
||||
### B. Geschenk an Ehepartner
|
||||
|
||||
Zweck:
|
||||
|
||||
- Geld gegen schnellere Stabilisierung
|
||||
|
||||
Regel:
|
||||
|
||||
- verfügbar nur bei aktiver Ehe
|
||||
- Stufen: `small`, `decent`, `lavish`
|
||||
- Cooldown: `1x pro 3 Tage`
|
||||
|
||||
Soforteffekt:
|
||||
|
||||
- `small`: `marriageSatisfaction +2`
|
||||
- `decent`: `marriageSatisfaction +4`
|
||||
- `lavish`: `marriageSatisfaction +7`
|
||||
|
||||
Nebeneffekt:
|
||||
|
||||
- `marriagePublicStability +1/+2/+3`
|
||||
|
||||
Malus:
|
||||
|
||||
- bei gleichzeitig unterfinanzierter Liebschaft halbierter Effekt
|
||||
|
||||
### C. Streit schlichten
|
||||
|
||||
Zweck:
|
||||
|
||||
- gezielte Krisenintervention
|
||||
|
||||
Regel:
|
||||
|
||||
- verfügbar nur wenn `householdTensionScore >= 35` oder `marriageSatisfaction <= 50`
|
||||
- Cooldown: `1x pro 2 Tage`
|
||||
|
||||
Soforteffekt:
|
||||
|
||||
- `householdTensionScore -4`
|
||||
- `marriageSatisfaction +1`
|
||||
|
||||
Malus:
|
||||
|
||||
- wenn `visibility` einer aktiven Liebschaft `>= 60`, dann nur `householdTensionScore -2`
|
||||
|
||||
### D. Fest nur für den Haushalt
|
||||
|
||||
Zweck:
|
||||
|
||||
- Hausfrieden über Geld und Repräsentation stützen
|
||||
|
||||
Regel:
|
||||
|
||||
- verfügbar bei vorhandenem Haus
|
||||
- kleiner interner Hausakt, nicht großes Reputationsfest
|
||||
- Cooldown: `1x pro Monat`
|
||||
|
||||
Soforteffekt:
|
||||
|
||||
- `householdTensionScore -6`
|
||||
- `marriageSatisfaction +2`
|
||||
- `householdOrder +2`
|
||||
|
||||
Malus:
|
||||
|
||||
- bei unterbesetzter Dienerschaft nur halbe Wirkung
|
||||
|
||||
## 3.2 Haus-Aktionen
|
||||
|
||||
Diese Aktionen gehören fachlich in `HouseView`.
|
||||
|
||||
### A. Haus ordnen
|
||||
|
||||
Zweck:
|
||||
|
||||
- kleine direkte Ordnungsmaßnahme
|
||||
|
||||
Regel:
|
||||
|
||||
- Cooldown: `1x pro Tag`
|
||||
- Kosten: niedrig
|
||||
|
||||
Soforteffekt:
|
||||
|
||||
- `householdOrder +3`
|
||||
- wenn `householdOrder > 70`: stattdessen nur `+1`
|
||||
|
||||
Indirekter Effekt:
|
||||
|
||||
- besserer Daily-Wert für `householdTensionScore`
|
||||
|
||||
### B. Diener einstellen
|
||||
|
||||
Bereits vorhanden.
|
||||
|
||||
Neue fachliche Wirkung:
|
||||
|
||||
- wenn vorher `servantCount < expectedMin`
|
||||
- sofort `householdTensionScore -2`
|
||||
|
||||
### C. Diener entlassen
|
||||
|
||||
Bereits vorhanden.
|
||||
|
||||
Neue fachliche Wirkung:
|
||||
|
||||
- wenn danach `servantCount < expectedMin`
|
||||
- sofort `householdTensionScore +3`
|
||||
|
||||
### D. Bezahlung erhöhen
|
||||
|
||||
Bereits vorhanden.
|
||||
|
||||
Neue fachliche Wirkung:
|
||||
|
||||
- wenn von `low -> normal` oder `normal -> high`
|
||||
- sofort `householdOrder +2`
|
||||
- `householdTensionScore -1`
|
||||
|
||||
## 3.3 Familien-/Kinder-Aktionen
|
||||
|
||||
### A. Uneheliches Kind anerkennen
|
||||
|
||||
Zweck:
|
||||
|
||||
- offenere, geordnetere Lösung statt versteckter Konfliktlage
|
||||
|
||||
Soforteffekt:
|
||||
|
||||
- `publicKnown = true`
|
||||
- `legitimacy = acknowledged_bastard`
|
||||
- `householdTensionScore -2`, wenn Beziehung bereits öffentlich geordnet
|
||||
- `householdTensionScore +3`, wenn Ehe schwach und Beziehung skandalös
|
||||
|
||||
Eheeffekt:
|
||||
|
||||
- `marriageSatisfaction -2` bis `-6` je nach Sichtbarkeit und Stand
|
||||
|
||||
### B. Erbenfrage regeln
|
||||
|
||||
Wenn uneheliche Kinder sichtbar werden, kann die UI später eine Handlung
|
||||
`Erbfolge klären` bekommen.
|
||||
|
||||
Erste Version:
|
||||
|
||||
- nur vorgemerkt
|
||||
- noch keine direkte Aktion nötig
|
||||
|
||||
## 3.4 Liebschafts-Aktionen mit Einfluss auf Ehe und Haus
|
||||
|
||||
Bestehend:
|
||||
|
||||
- Unterhalt ändern
|
||||
- Beziehung anerkennen
|
||||
- Beziehung beenden
|
||||
|
||||
Diese Aktionen sollen explizit folgende Sofortwirkung haben:
|
||||
|
||||
### Unterhalt erhöhen
|
||||
|
||||
- `monthsUnderfunded` baut sich später im Daemon ab
|
||||
- sofort kein großer Ehebonus
|
||||
- aber `householdTensionScore -1`, wenn vorher Unterversorgung bestand
|
||||
|
||||
### Beziehung anerkennen
|
||||
|
||||
- `visibility` steigt nicht automatisch hart, aber öffentlicher Charakter nimmt zu
|
||||
- bei hohen Ständen geordnet eher neutral bis leicht positiv für Ehe-Stabilität
|
||||
- bei niedrigen Ständen eher negativ
|
||||
|
||||
Sofortregel:
|
||||
|
||||
- Standesgruppe `0-1`: `marriageSatisfaction -3`, `householdTensionScore +2`
|
||||
- Standesgruppe `2`: `marriageSatisfaction -1`, `householdTensionScore +1`
|
||||
- Standesgruppe `3`: `marriagePublicStability +1`, `householdTensionScore -1`, wenn Diskretion und Versorgung gut sind
|
||||
|
||||
### Beziehung beenden
|
||||
|
||||
- sofort `householdTensionScore -3`, wenn Liebschaft riskant war
|
||||
- sofort `marriageSatisfaction +1`, wenn aktive Ehe existiert
|
||||
- aber bei hoher `affection >= 70` auch möglicher Malus auf Stimmungssystem später
|
||||
|
||||
## 4. Daemon-Berechnung
|
||||
|
||||
## 4.1 Daily-Input
|
||||
|
||||
Der externe Daemon braucht pro Spielerfigur:
|
||||
|
||||
- aktive Ehebeziehung mit `marriageSatisfaction`, `marriagePublicStability`
|
||||
- aktive Liebschaften mit:
|
||||
- `loverRole`
|
||||
- `visibility`
|
||||
- `discretion`
|
||||
- `maintenanceLevel`
|
||||
- `statusFit`
|
||||
- `monthsUnderfunded`
|
||||
- `acknowledged`
|
||||
- Kinderdaten:
|
||||
- `legitimacy`
|
||||
- `birthContext`
|
||||
- `publicKnown`
|
||||
- Hausdaten:
|
||||
- `servantCount`
|
||||
- `servantQuality`
|
||||
- `servantPayLevel`
|
||||
- `householdOrder`
|
||||
- Charakterdaten:
|
||||
- `titleOfNobility`
|
||||
- `reputation`
|
||||
|
||||
## 4.2 Daily-Berechnung für Ehe
|
||||
|
||||
Grunddrift:
|
||||
|
||||
```text
|
||||
marriageDelta = 0
|
||||
|
||||
if marriageSatisfaction > 55: marriageDelta -= 1 every 3 days
|
||||
if marriageSatisfaction < 55: marriageDelta += 1 every 5 days
|
||||
```
|
||||
|
||||
Liebschaften:
|
||||
|
||||
```text
|
||||
for each active lover:
|
||||
if visibility >= 60: marriageDelta -= 2
|
||||
else if visibility >= 35: marriageDelta -= 1
|
||||
|
||||
if monthsUnderfunded >= 2: marriageDelta -= 1
|
||||
if acknowledged = true and statusGroup <= 1: marriageDelta -= 1
|
||||
if acknowledged = true and statusGroup = 3 and visibility <= 35 and maintenanceLevel >= 60:
|
||||
marriageDelta += 0 or +1 every few days
|
||||
```
|
||||
|
||||
Zu jung:
|
||||
|
||||
```text
|
||||
if minAge <= 15: marriageDelta -= 1
|
||||
if minAge <= 13: marriageDelta -= 2
|
||||
```
|
||||
|
||||
Haus:
|
||||
|
||||
```text
|
||||
if householdOrder >= 75: marriageDelta += 1
|
||||
if householdOrder <= 35: marriageDelta -= 1
|
||||
if householdTensionScore >= 60: marriageDelta -= 1
|
||||
```
|
||||
|
||||
Dienerschaft:
|
||||
|
||||
```text
|
||||
if servantCount < expectedMin: marriageDelta -= 1
|
||||
if servantPayLevel = high and servantQuality >= 70 and householdOrder >= 70:
|
||||
marriageDelta += 1 every 3 days
|
||||
```
|
||||
|
||||
Danach:
|
||||
|
||||
- clamp `0..100`
|
||||
|
||||
## 4.3 Daily-Berechnung für Hausfrieden
|
||||
|
||||
Interner Wert:
|
||||
|
||||
```text
|
||||
householdTensionScore = base
|
||||
```
|
||||
|
||||
Empfohlene Berechnung:
|
||||
|
||||
```text
|
||||
base = 10
|
||||
|
||||
for each active lover:
|
||||
if visibility >= 60: base += 18
|
||||
else if visibility >= 35: base += 10
|
||||
else: base += 4
|
||||
|
||||
if monthsUnderfunded >= 1: base += 6
|
||||
if monthsUnderfunded >= 2: base += 6
|
||||
if acknowledged = true: base += 4
|
||||
if statusFit = -1: base += 3
|
||||
if statusFit = -2: base += 6
|
||||
```
|
||||
|
||||
Kinder:
|
||||
|
||||
```text
|
||||
for each child where birthContext = 'lover':
|
||||
if publicKnown = true: base += 6
|
||||
else: base += 2
|
||||
|
||||
if legitimacy = 'acknowledged_bastard': base += 2
|
||||
if legitimacy = 'hidden_bastard': base += 4
|
||||
```
|
||||
|
||||
Haus:
|
||||
|
||||
```text
|
||||
if householdOrder >= 80: base -= 6
|
||||
else if householdOrder >= 65: base -= 3
|
||||
|
||||
if householdOrder <= 35: base += 8
|
||||
else if householdOrder <= 50: base += 4
|
||||
```
|
||||
|
||||
Dienerschaft:
|
||||
|
||||
```text
|
||||
if servantCount < expectedMin: base += 5
|
||||
if servantPayLevel = low: base += 2
|
||||
if servantQuality >= 70 and servantPayLevel = high: base -= 3
|
||||
```
|
||||
|
||||
Ehe:
|
||||
|
||||
```text
|
||||
if marriageSatisfaction <= 35: base += 6
|
||||
if marriageSatisfaction >= 75: base -= 2
|
||||
```
|
||||
|
||||
Danach:
|
||||
|
||||
- clamp `0..100`
|
||||
- UI-Ableitung auf `low/medium/high`
|
||||
|
||||
## 4.4 Monthly-Berechnung
|
||||
|
||||
Monatlich soll der Daemon zusätzlich:
|
||||
|
||||
- Dienerkosten abbuchen
|
||||
- Liebschaftskosten abbuchen
|
||||
- bei Unterversorgung `householdTensionScore` stärker erhöhen
|
||||
- langfristige Ordnungs- oder Eheboni addieren
|
||||
|
||||
Empfohlene Zusatzregeln:
|
||||
|
||||
```text
|
||||
if a lover was underfunded this month:
|
||||
householdTensionScore += 4
|
||||
|
||||
if servantCount far below expectedMin for full month:
|
||||
householdTensionScore += 3
|
||||
|
||||
if householdOrder >= 80 for full month:
|
||||
marriageSatisfaction += 1
|
||||
|
||||
if householdOrder <= 30 for full month:
|
||||
marriageSatisfaction -= 2
|
||||
```
|
||||
|
||||
## 5. UI-Anforderungen
|
||||
|
||||
## 5.1 FamilyView
|
||||
|
||||
Neu sinnvolle Aktionen:
|
||||
|
||||
- `Zeit miteinander verbringen`
|
||||
- `Geschenk machen`
|
||||
- `Streit schlichten`
|
||||
- `Liebschaft beenden`
|
||||
- `Uneheliches Kind anerkennen`
|
||||
|
||||
Zusätzlich hilfreiche Anzeige:
|
||||
|
||||
- kurze Ursachenliste für `Hausfrieden`
|
||||
- z. B. `sichtbare Liebschaft`
|
||||
- `Unruhe im Haus`
|
||||
- `zu wenig Diener`
|
||||
- `anerkanntes uneheliches Kind`
|
||||
|
||||
## 5.2 HouseView
|
||||
|
||||
Neu sinnvolle Aktionen:
|
||||
|
||||
- `Haus ordnen`
|
||||
- vorhandene Dieneraktionen mit klarer Auswirkungstextzeile
|
||||
|
||||
Anzeige:
|
||||
|
||||
- `Haushaltsordnung`
|
||||
- `erwartete Dienerzahl`
|
||||
- `Auswirkung auf Hausfrieden`
|
||||
|
||||
## 6. Backend-Anforderungen
|
||||
|
||||
## 6.1 Direktaktionen
|
||||
|
||||
Dieses Projekt sollte Endpunkte für direkte Einflussaktionen bereitstellen:
|
||||
|
||||
- `POST /api/falukant/family/marriage/spend-time`
|
||||
- `POST /api/falukant/family/marriage/gift`
|
||||
- `POST /api/falukant/family/marriage/reconcile`
|
||||
- `POST /api/falukant/houses/order`
|
||||
- später optional:
|
||||
- `POST /api/falukant/family/children/acknowledge`
|
||||
|
||||
## 6.2 API-Rückgabe
|
||||
|
||||
Family-API sollte zusätzlich liefern:
|
||||
|
||||
- `marriageSatisfaction`
|
||||
- `marriageState`
|
||||
- `marriagePublicStability`
|
||||
- `householdTension`
|
||||
- `householdTensionScore`
|
||||
- optional:
|
||||
- `householdTensionReasons[]`
|
||||
|
||||
House-API sollte zusätzlich liefern:
|
||||
|
||||
- `householdOrder`
|
||||
- `expectedServantsMin`
|
||||
- `expectedServantsMax`
|
||||
- `marriageComfortModifier`
|
||||
|
||||
## 7. Priorisierte Umsetzung
|
||||
|
||||
## Phase A
|
||||
|
||||
- `statusFit`-Fehler korrigieren
|
||||
- direkte Ehe-Aktionen `Zeit`, `Geschenk`, `Streit schlichten`
|
||||
- direkte Haus-Aktion `Haus ordnen`
|
||||
- Family-API um `householdTensionScore` erweitern
|
||||
|
||||
## Phase B
|
||||
|
||||
- externer Daemon berechnet Daily-Drift für Ehe und Hausfrieden
|
||||
- Dienerschaft fließt in Hausfrieden ein
|
||||
- Liebschaften und Unterversorgung wirken vollständig auf Hausfrieden
|
||||
|
||||
## Phase C
|
||||
|
||||
- uneheliche Kinder als aktiver Konfliktfaktor
|
||||
- Anerkennungsaktion
|
||||
- genauere Ursachenlisten in der UI
|
||||
|
||||
## 8. Offene Balancing-Punkte
|
||||
|
||||
Diese Werte sind absichtlich noch nicht final:
|
||||
|
||||
- exakte Geldkosten für Ehe-Aktionen
|
||||
- Stärke der Boni für hohe Stände
|
||||
- Stärke des Malus bei sichtbaren Liebschaften
|
||||
- Stärke der Dienerwirkung auf Ehe und Haus
|
||||
|
||||
Die Struktur sollte jetzt aber stabil genug sein, damit UI und Daemon unabhängig voneinander anfangen können.
|
||||
137
docs/FALUKANT_MARRIAGE_HOUSEHOLD_DAEMON_HANDOFF.md
Normal file
137
docs/FALUKANT_MARRIAGE_HOUSEHOLD_DAEMON_HANDOFF.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Falukant: Daemon-Handoff für Ehe und Hausfrieden
|
||||
|
||||
Dieses Dokument beschreibt den Stand nach Phase A.
|
||||
|
||||
## 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`
|
||||
- `household_tension_score`
|
||||
- `household_tension_reasons_json`
|
||||
- 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`
|
||||
- `user_house.household_tension_score`
|
||||
- `user_house.household_tension_reasons_json`
|
||||
- lover-state-Felder bei Änderungen:
|
||||
- `visibility`
|
||||
- `discretion`
|
||||
- `months_underfunded`
|
||||
- optional `notes_json` / `flags_json`
|
||||
|
||||
## 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
|
||||
472
docs/FALUKANT_PRODUCTION_CERTIFICATE_SPEC.md
Normal file
472
docs/FALUKANT_PRODUCTION_CERTIFICATE_SPEC.md
Normal file
@@ -0,0 +1,472 @@
|
||||
# Falukant: Produktionszertifikate – Fach- und Integrationsspezifikation
|
||||
|
||||
## 1. Ziel
|
||||
|
||||
Das Produktionssystem soll stärker an den tatsächlichen gesellschaftlichen und fachlichen Fortschritt eines Spielers gebunden werden. Ein Spieler darf nur Produkte herstellen, deren Zertifikatsstufe seiner aktuellen Produktionsfreigabe entspricht.
|
||||
|
||||
Die Zertifikatsstufe steigt nicht sofort bei jeder Einzelaktion, sondern wird ausschließlich im externen Daemon einmal täglich neu berechnet.
|
||||
|
||||
Dieses Dokument beschreibt:
|
||||
|
||||
- das fachliche Modell der Produktionszertifikate
|
||||
- die Faktoren für Aufstieg und Begrenzung
|
||||
- die Daily-Berechnung im Daemon
|
||||
- die Kommunikation zwischen Daemon und UI
|
||||
- die Einbindung in die bestehende Backend-/UI-Struktur
|
||||
|
||||
Wichtig:
|
||||
|
||||
- Die nötigen DB-Grundlagen sind bereits vorhanden.
|
||||
- Der Daemon muss keine neuen Schemaänderungen erwarten.
|
||||
- Bestehende Felder wie `falukant_data.falukant_user.certificate` und `falukant_type.product.category` bleiben die führende Basis.
|
||||
|
||||
## 2. Bestehende technische Basis
|
||||
|
||||
Bereits vorhanden:
|
||||
|
||||
- `falukant_data.falukant_user.certificate`
|
||||
- aktuelle Produktionsfreigabe des Spielers
|
||||
- `falukant_type.product.category`
|
||||
- erforderliche Zertifikatsstufe des Produkts
|
||||
- `falukant_data.knowledge`
|
||||
- Produktwissen je Charakter und Produkt
|
||||
- `falukant_data.production`
|
||||
- Produktionsvorgänge
|
||||
- `falukant_data.character.reputation`
|
||||
- Ansehen des Spielercharakters
|
||||
- `falukant_data.character.title_of_nobility`
|
||||
- Adelstitel
|
||||
- `falukant_data.user_house.house_type_id`
|
||||
- aktuelles Haus
|
||||
- politische und kirchliche Ämter
|
||||
- `falukant_data.political_office`
|
||||
- `falukant_data.church_office`
|
||||
- `falukant_log.political_office_history`
|
||||
- `falukant_type.church_office_type.hierarchy_level`
|
||||
|
||||
Bestehende Produktfreigabe im Backend:
|
||||
|
||||
- Produkte werden bereits in `falukantService.getProducts()` über `product.category <= user.certificate` gefiltert.
|
||||
|
||||
Das heißt:
|
||||
|
||||
- Zertifikatslogik muss nicht neu in die Produktionsfreigabe eingebaut werden.
|
||||
- Es muss nur die Berechnung und Fortschreibung von `falukant_user.certificate` sauber geregelt werden.
|
||||
|
||||
## 3. Fachmodell
|
||||
|
||||
### 3.1 Zertifikatsstufen
|
||||
|
||||
Die Zertifikatsstufe bleibt eine einfache ganze Zahl im Feld `falukant_user.certificate`.
|
||||
|
||||
Empfohlene Bedeutung:
|
||||
|
||||
| Stufe | Bedeutung |
|
||||
|------|-----------|
|
||||
| `1` | Grundproduktion, einfache Güter |
|
||||
| `2` | Gehobene Alltagsproduktion |
|
||||
| `3` | Fortgeschrittene Manufaktur |
|
||||
| `4` | Anspruchsvolle Qualitätsproduktion |
|
||||
| `5` | Hochwertige oder prestigegebundene Produktion |
|
||||
|
||||
Wenn im Typensystem bereits höhere `product.category`-Werte existieren, gilt dieselbe Logik entsprechend weiter.
|
||||
|
||||
### 3.2 Führungsprinzip
|
||||
|
||||
Die Zertifikatsstufe ist kein reines Wissenslevel.
|
||||
|
||||
Sie soll ausdrücken, ob ein Haushalt/Betrieb gesellschaftlich und fachlich als ausreichend etabliert gilt, um komplexere Produktion zu verantworten.
|
||||
|
||||
Darum fließen mehrere Faktoren ein:
|
||||
|
||||
- Durchschnittliches Produktwissen
|
||||
- Anzahl abgeschlossener Produktionen
|
||||
- höchstes politisches oder kirchliches Amt
|
||||
- Adelstitel
|
||||
- Ansehen
|
||||
- derzeitiges Haus
|
||||
|
||||
## 4. Berechnungslogik
|
||||
|
||||
## 4.1 Grundidee
|
||||
|
||||
Der Daemon berechnet einmal täglich einen `certificateScore`.
|
||||
|
||||
Aus diesem `certificateScore` wird eine Zielstufe `targetCertificate` abgeleitet.
|
||||
|
||||
Die gespeicherte Stufe `falukant_user.certificate` wird dann höchstens um `+1` pro Tag angehoben. Senkungen sind optional und in der ersten Version nicht vorgesehen.
|
||||
|
||||
Dadurch gilt:
|
||||
|
||||
- Aufstieg ist spürbar, aber nicht sprunghaft
|
||||
- kurzfristige Schwankungen führen nicht zu hektischen Freischaltungen
|
||||
- Balancing bleibt später leichter
|
||||
|
||||
## 4.2 Eingangsgrößen
|
||||
|
||||
Für jeden Spielercharakter mit `falukant_user`:
|
||||
|
||||
- `avgKnowledge`
|
||||
- Durchschnitt aus `falukant_data.knowledge.knowledge` des Spielercharakters
|
||||
- `completedProductions`
|
||||
- Anzahl abgeschlossener Produktionen des Spielers
|
||||
- `highestPoliticalOfficeRank`
|
||||
- höchster politischer Amtsrang
|
||||
- `highestChurchOfficeRank`
|
||||
- höchster kirchlicher Amtsrang
|
||||
- `highestOfficeRank`
|
||||
- Maximum aus politischem und kirchlichem Rang
|
||||
- `nobilityLevel`
|
||||
- aus `title_of_nobility`
|
||||
- `reputation`
|
||||
- aus `character.reputation`
|
||||
- `housePosition`
|
||||
- aus `house.position`
|
||||
|
||||
## 4.3 Normalisierung der Faktoren
|
||||
|
||||
### Produktwissen
|
||||
|
||||
`knowledgePoints`:
|
||||
|
||||
- `0`, wenn `avgKnowledge < 20`
|
||||
- `1`, wenn `avgKnowledge >= 20`
|
||||
- `2`, wenn `avgKnowledge >= 35`
|
||||
- `3`, wenn `avgKnowledge >= 50`
|
||||
- `4`, wenn `avgKnowledge >= 65`
|
||||
- `5`, wenn `avgKnowledge >= 80`
|
||||
|
||||
### Produktionsmenge
|
||||
|
||||
`productionPoints`:
|
||||
|
||||
- `0`, wenn `completedProductions < 5`
|
||||
- `1`, wenn `completedProductions >= 5`
|
||||
- `2`, wenn `completedProductions >= 20`
|
||||
- `3`, wenn `completedProductions >= 50`
|
||||
- `4`, wenn `completedProductions >= 100`
|
||||
- `5`, wenn `completedProductions >= 200`
|
||||
|
||||
### Politische / kirchliche Stellung
|
||||
|
||||
`officePoints`:
|
||||
|
||||
- politische Ämter:
|
||||
- über definierte Mapping-Tabelle im Daemon von `office_type.name -> rank`
|
||||
- kirchliche Ämter:
|
||||
- bevorzugt `church_office_type.hierarchy_level`
|
||||
- dann:
|
||||
- `highestOfficeRank = max(highestPoliticalOfficeRank, highestChurchOfficeRank)`
|
||||
- `officePoints = min(5, highestOfficeRank)`
|
||||
|
||||
Empfehlung für politische Mapping-Tabelle:
|
||||
|
||||
- einfache Kommunalämter: `1`
|
||||
- regionale Ämter: `2`
|
||||
- hohe Regionalämter: `3`
|
||||
- reichs- oder königsnahe Spitzenämter: `4` bis `5`
|
||||
|
||||
Das Mapping lebt im Daemon und kann balanciert werden, ohne DB-Änderungen.
|
||||
|
||||
### Adel
|
||||
|
||||
`nobilityPoints`:
|
||||
|
||||
- aus `title_of_nobility.level`
|
||||
- `nobilityPoints = clamp(level - 1, 0, 5)`
|
||||
|
||||
### Ansehen
|
||||
|
||||
`reputationPoints`:
|
||||
|
||||
- `0`, wenn `reputation < 20`
|
||||
- `1`, wenn `reputation >= 20`
|
||||
- `2`, wenn `reputation >= 40`
|
||||
- `3`, wenn `reputation >= 60`
|
||||
- `4`, wenn `reputation >= 75`
|
||||
- `5`, wenn `reputation >= 90`
|
||||
|
||||
### Haus
|
||||
|
||||
`housePoints`:
|
||||
|
||||
- aus `house.position`
|
||||
- Vorschlag:
|
||||
- `0`, wenn `position <= 1`
|
||||
- `1`, wenn `position >= 2`
|
||||
- `2`, wenn `position >= 4`
|
||||
- `3`, wenn `position >= 6`
|
||||
- `4`, wenn `position >= 8`
|
||||
- `5`, wenn `position >= 10`
|
||||
|
||||
Die genauen Schwellen können im Balancing später angepasst werden.
|
||||
|
||||
## 4.4 Gesamtwert
|
||||
|
||||
Der Daemon berechnet:
|
||||
|
||||
```text
|
||||
certificateScore =
|
||||
knowledgePoints * 0.35 +
|
||||
productionPoints * 0.20 +
|
||||
officePoints * 0.15 +
|
||||
nobilityPoints * 0.10 +
|
||||
reputationPoints * 0.10 +
|
||||
housePoints * 0.10
|
||||
```
|
||||
|
||||
Zusätzlich gelten Mindestanforderungen je Stufe.
|
||||
|
||||
## 4.5 Mindestanforderungen je Zertifikatsstufe
|
||||
|
||||
Eine höhere Zielstufe darf nur erreicht werden, wenn neben dem `certificateScore` auch harte Mindestgrenzen erfüllt sind.
|
||||
|
||||
### Für Zertifikat 2
|
||||
|
||||
- `avgKnowledge >= 25`
|
||||
- `completedProductions >= 5`
|
||||
|
||||
### Für Zertifikat 3
|
||||
|
||||
- `avgKnowledge >= 40`
|
||||
- `completedProductions >= 20`
|
||||
- mindestens einer der Statusfaktoren erfüllt:
|
||||
- `officePoints >= 1`
|
||||
- oder `nobilityPoints >= 1`
|
||||
- oder `reputationPoints >= 2`
|
||||
- oder `housePoints >= 1`
|
||||
|
||||
### Für Zertifikat 4
|
||||
|
||||
- `avgKnowledge >= 55`
|
||||
- `completedProductions >= 60`
|
||||
- mindestens zwei Statusfaktoren erfüllt
|
||||
|
||||
### Für Zertifikat 5
|
||||
|
||||
- `avgKnowledge >= 70`
|
||||
- `completedProductions >= 150`
|
||||
- `reputationPoints >= 3`
|
||||
- mindestens zwei der folgenden:
|
||||
- `officePoints >= 2`
|
||||
- `nobilityPoints >= 2`
|
||||
- `housePoints >= 2`
|
||||
|
||||
## 4.6 Ableitung der Zielstufe
|
||||
|
||||
Vorschlag:
|
||||
|
||||
- `targetCertificate = 1`, wenn `certificateScore < 1.2`
|
||||
- `targetCertificate = 2`, wenn `certificateScore >= 1.2`
|
||||
- `targetCertificate = 3`, wenn `certificateScore >= 2.1`
|
||||
- `targetCertificate = 4`, wenn `certificateScore >= 3.0`
|
||||
- `targetCertificate = 5`, wenn `certificateScore >= 4.0`
|
||||
|
||||
Danach werden die Mindestanforderungen geprüft.
|
||||
|
||||
Wenn eine Schwelle rechnerisch erreicht ist, die Mindestanforderungen aber fehlen, bleibt der Spieler auf der niedrigeren Zielstufe.
|
||||
|
||||
## 4.7 Fortschreibung
|
||||
|
||||
Daily-Regel:
|
||||
|
||||
- wenn `targetCertificate > currentCertificate`
|
||||
- dann `newCertificate = currentCertificate + 1`
|
||||
- sonst
|
||||
- `newCertificate = currentCertificate`
|
||||
|
||||
Für die erste Version keine automatische Herabstufung.
|
||||
|
||||
Ausnahmen, die bereits im Daemon berücksichtigt werden dürfen:
|
||||
|
||||
- `Bankrott`
|
||||
- Wenn der Spieler wirtschaftlich zusammenbricht, darf das Zertifikat gesenkt werden.
|
||||
- Die genaue Definition von Bankrott lebt im Daemon bzw. im Wirtschaftssystem.
|
||||
- `Tod ohne Kinder`
|
||||
- Stirbt der Spielercharakter und es gibt keinen erbberechtigten Nachfolger, darf das Zertifikat auf den Grundzustand des Nachfolgesystems bzw. auf eine definierte niedrige Stufe zurückgesetzt werden.
|
||||
- Dieser Fall darf bereits jetzt im Daemon umgesetzt werden.
|
||||
|
||||
Nicht vorgesehen für die erste Version:
|
||||
|
||||
- Downgrade wegen normaler Alltagsschwankungen
|
||||
- Downgrade wegen vorübergehend schlechter Werte bei Wissen, Ruf, Haus oder Amt
|
||||
|
||||
## 5. Daemon-Verhalten
|
||||
|
||||
## 5.1 Ausführungszeitpunkt
|
||||
|
||||
Die Zertifikatsprüfung läuft ausschließlich im Daily-Tick.
|
||||
|
||||
Nicht bei:
|
||||
|
||||
- Produktionsstart
|
||||
- Produktionsende
|
||||
- Wissensänderung
|
||||
- Hauswechsel
|
||||
- Amtswechsel
|
||||
|
||||
Diese Aktionen verändern nur die Eingangsgrößen. Die eigentliche Zertifikatsanpassung erfolgt erst im nächsten Daily-Lauf.
|
||||
|
||||
## 5.2 Daemon-Hinweis
|
||||
|
||||
Für den Daemon gilt ausdrücklich:
|
||||
|
||||
- die relevanten DB-Felder sind bereits vorhanden
|
||||
- es müssen für diese Funktion keine zusätzlichen Schemaänderungen mehr eingeplant werden
|
||||
- der Daemon soll direkt mit den vorhandenen Tabellen arbeiten
|
||||
|
||||
## 5.3 Empfohlener Daily-Ablauf
|
||||
|
||||
Für jeden Spieler mit `falukant_user`:
|
||||
|
||||
1. Spielercharakter laden
|
||||
2. `avgKnowledge` berechnen
|
||||
3. Anzahl abgeschlossener Produktionen laden
|
||||
4. höchstes aktives oder historisches politisches Amt ermitteln
|
||||
5. höchstes aktives kirchliches Amt ermitteln
|
||||
6. Adelstitel, Ruf und Haus laden
|
||||
7. `certificateScore` und `targetCertificate` berechnen
|
||||
8. falls Aufstieg möglich:
|
||||
- `falukant_user.certificate` um genau `+1` erhöhen
|
||||
9. Event an UI senden
|
||||
|
||||
## 6. Event-Kommunikation zwischen Daemon und UI
|
||||
|
||||
## 6.1 Neues Event
|
||||
|
||||
Zusätzlich zum allgemeinen `falukantUpdateStatus` wird ein gezieltes Zertifikats-Event empfohlen:
|
||||
|
||||
### `falukantUpdateProductionCertificate`
|
||||
|
||||
Payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "falukantUpdateProductionCertificate",
|
||||
"user_id": 123,
|
||||
"reason": "daily_recalculation",
|
||||
"old_certificate": 2,
|
||||
"new_certificate": 3
|
||||
}
|
||||
```
|
||||
|
||||
`reason` ist in der ersten Version fest:
|
||||
|
||||
- `daily_recalculation`
|
||||
|
||||
## 6.2 Wann senden
|
||||
|
||||
Wenn sich die Zertifikatsstufe geändert hat:
|
||||
|
||||
1. `falukantUpdateProductionCertificate`
|
||||
2. danach `falukantUpdateStatus`
|
||||
|
||||
Wenn sich die Stufe nicht geändert hat:
|
||||
|
||||
- kein spezielles Zertifikats-Event nötig
|
||||
- normales `falukantUpdateStatus` bleibt anderen Systemen vorbehalten
|
||||
|
||||
## 6.3 UI-Reaktion
|
||||
|
||||
### BranchView
|
||||
|
||||
Bei `falukantUpdateProductionCertificate`:
|
||||
|
||||
- Produkte neu laden
|
||||
- Produktionsbereich neu laden
|
||||
- optional kurzer Hinweis:
|
||||
- „Neues Handelszertifikat erreicht“
|
||||
|
||||
### OverviewView
|
||||
|
||||
Bei `falukantUpdateProductionCertificate`:
|
||||
|
||||
- Falukant-Status neu laden
|
||||
- Produktionsüberblick neu laden
|
||||
- Zertifikatsaufstieg visuell hervorheben
|
||||
|
||||
### StatusBar / DashboardWidget
|
||||
|
||||
- auf denselben Nutzer filtern
|
||||
- Zertifikat/Produktionsstatus neu laden
|
||||
|
||||
## 6.4 Deduplizierung
|
||||
|
||||
Da direkt nach dem Zertifikats-Event oft `falukantUpdateStatus` folgt, soll die UI wie bei anderen Falukant-Events entprellen:
|
||||
|
||||
- beide Events dürfen denselben kurzen Refresh-Puffer nutzen
|
||||
- ein Zertifikatsaufstieg darf keinen doppelten Reload-Sturm auslösen
|
||||
|
||||
## 7. API- und UI-Empfehlungen
|
||||
|
||||
## 7.1 Sichtbare Anzeige
|
||||
|
||||
Die UI sollte mittelfristig anzeigen:
|
||||
|
||||
- aktuelle Zertifikatsstufe
|
||||
- nächste Stufe
|
||||
- Fortschrittsfaktoren
|
||||
- Wissen
|
||||
- Produktionen
|
||||
- Amt
|
||||
- Adel
|
||||
- Ruf
|
||||
- Haus
|
||||
|
||||
## 7.2 Empfohlene Backend-Ausgabe
|
||||
|
||||
Zusätzlich zur bestehenden User-/Overview-API ist später sinnvoll:
|
||||
|
||||
- `certificate`
|
||||
- `nextCertificate`
|
||||
- `certificateFactors`
|
||||
- `avgKnowledge`
|
||||
- `completedProductions`
|
||||
- `highestOfficeRank`
|
||||
- `nobilityLevel`
|
||||
- `reputation`
|
||||
- `housePosition`
|
||||
|
||||
Das ist für die erste Daemon-Integration aber optional.
|
||||
|
||||
## 8. Balancing-Hinweis
|
||||
|
||||
Die genannten Schwellen und Gewichte sind bewusst als Spielregelrahmen zu verstehen, nicht als endgültiges Balancing.
|
||||
|
||||
Für die erste produktive Version gilt:
|
||||
|
||||
- keine zusätzlichen Stufen oder Nebensysteme
|
||||
- keine normale Herabstufung im Alltagsbetrieb
|
||||
- Herabstufung nur in Sonderfällen wie `Bankrott` oder `Tod ohne Kinder`
|
||||
- Daily-Aufstieg maximal `+1`
|
||||
|
||||
Balancing erst nach Live-Erfahrung.
|
||||
|
||||
## 9. Umsetzungsreihenfolge
|
||||
|
||||
### P1
|
||||
|
||||
- Daemon: Daily-Berechnung von `certificate`
|
||||
- Event `falukantUpdateProductionCertificate`
|
||||
- UI: gezielter Refresh in Branch/Overview
|
||||
|
||||
### P2
|
||||
|
||||
- UI: Sichtbarer Zertifikatsstatus und Aufstiegshinweis
|
||||
- Backend/API: optionale Faktor-Ausgabe
|
||||
|
||||
### P3
|
||||
|
||||
- Balancing
|
||||
- feinere Sonderfallregeln für `Bankrott`
|
||||
- feinere politische Mapping-Tabelle
|
||||
|
||||
## 10. Done-Kriterien
|
||||
|
||||
Fertig ist die erste Version, wenn:
|
||||
|
||||
- nur Produkte mit `product.category <= falukant_user.certificate` produzierbar sind
|
||||
- der Daemon die Zertifikatsprüfung genau einmal täglich ausführt
|
||||
- der Daemon bei Aufstieg das Zertifikat fortschreibt
|
||||
- die UI auf das Zertifikats-Event gezielt reagiert
|
||||
- keine neuen DB-Änderungen für diese Funktion nötig sind
|
||||
Reference in New Issue
Block a user