14 KiB
Falukant: Dienerschaft – Daemon-, Technik- und Umsetzungs-Spezifikation
Dieses Dokument bündelt die umsetzungsreife Spezifikation für das Dienerschaftssystem in einer Datei.
Es ersetzt für die technische Umsetzung die sonst übliche Aufteilung in:
- Daemon-Spec
- Daemon-Handoff
- technisches Konzept
- Implementierungs-Backlog
Die fachliche Grundidee bleibt in FALUKANT_SERVANTS_CONCEPT.md beschrieben. Dieses Dokument hier ist die Arbeitsgrundlage für Implementierung und Daemon-Anbindung.
1. Zielbild
Die Dienerschaft ist ein Haussystem mit vier Kernwerten:
servantCountservantQualityservantPayLevelhouseholdOrder
Diese Werte wirken auf:
- monatliche Kosten
- Repräsentation und Ansehen
- Komfort und Ordnung des Haushalts
- Ehezufriedenheit und Haushaltsfrieden
- Diskretion bei Liebschaften
- spätere Untergrund-Aufdeckungen
2. Systemgrenzen
In Scope der ersten Version:
- Dienerschaft hängt an
user_house - House-UI zeigt und verändert Dienerwerte
- externer Daemon verarbeitet Daily- und Monthly-Effekte
- Familie, Liebschaften und Untergrund nutzen die resultierenden Werte mit
Nicht in Scope der ersten Version:
- einzelne benannte Diener
- eigene Dienerrollen wie Küchenpersonal, Wachen, Zofen
- eigene Eventketten nur für Diener
- finales Balancing
3. Datenmodell
3.1 Bereits vorhandene Hausfelder
In falukant_data.user_house:
servant_count integer not null default 0servant_quality integer not null default 50servant_pay_level varchar(20) not null default 'normal'household_order integer not null default 55
3.2 Wertebereiche
servant_count:0..999servant_quality:0..100servant_pay_level:low | normal | highhousehold_order:0..100
3.3 Abgeleitete Werte
Diese Werte müssen nicht persistent gespeichert werden, sondern können im Backend oder Daemon berechnet werden:
expectedServantsMinexpectedServantsMaxstaffingStateorderStatemonthlyServantCostdiscretionModifierservantReputationModifiermarriageComfortModifier
4. Erwartungswert der Dienerschaft
Die Sollgröße hängt von Haus und Stand ab.
4.1 Basis nach Hausposition
house.house_type.position ist die grobe Hausklasse.
Empfohlene erste Regel:
| Hausposition | Basis Min | Basis Max |
|---|---|---|
<= 2 |
0 | 1 |
3 |
1 | 2 |
4 |
2 | 4 |
5 |
3 | 6 |
>= 6 |
4 | 8 |
4.2 Standesbonus
Aus character.noble_title.level:
titleBonus = floor(level / 3), mindestens 0
expectedMin = baseMin + titleBonus
expectedMax = baseMax + titleBonus
4.3 Zustandsklassen
if servantCount < expectedMin => understaffed
if servantCount > expectedMax => overstaffed
sonst => fitting
5. Daily-Regeln für den externen Daemon
5.1 Daily-Input
Pro Falukant-User mit Haus braucht der Daemon:
falukant_user.iduser.idbzw.user.hashed_idfür Benachrichtigungcharacter.idcharacter.reputationcharacter.noble_title_idund idealerweisecharacter.nobleTitle.leveluser_house.house_type_idhouse_type.positionhouse_type.costservant_countservant_qualityservant_pay_levelhousehold_order- optional für Verknüpfungen:
marriage_satisfactionoderrelationship_state.marriage_satisfaction- aktive Liebschaften mit
visibility,discretion,risk
5.2 Daily-Hilfswerte
payShift(low) = -6
payShift(normal) = 0
payShift(high) = +6
missing = max(0, expectedMin - servantCount)
excessive = max(0, servantCount - expectedMax)
qualityPart = round((servantQuality - 50) * 0.35)
payPart = payShift(servantPayLevel)
fitPenalty = missing * 10 + excessive * 4
5.3 Daily-Zielwert für Haushaltsordnung
targetHouseholdOrder = clamp(
55 + qualityPart + payPart - fitPenalty,
0,
100
)
5.4 Daily-Drift der Haushaltsordnung
Die Ordnung springt nicht hart, sondern driftet langsam:
newHouseholdOrder = oldHouseholdOrder
if oldHouseholdOrder < targetHouseholdOrder:
newHouseholdOrder += min(2, targetHouseholdOrder - oldHouseholdOrder)
if oldHouseholdOrder > targetHouseholdOrder:
newHouseholdOrder -= min(2, oldHouseholdOrder - targetHouseholdOrder)
Zusatzregel:
- bei
servantPayLevel = lowundservantCount < expectedMinzusätzlich-1 - bei
servantPayLevel = highundservantQuality >= 65zusätzlich+1
Danach clamp auf 0..100.
5.5 Daily-Drift der Dienerqualität
Die Qualität ändert sich langsam:
qualityDelta = 0
if servantPayLevel = low: qualityDelta -= 1
if servantPayLevel = high: qualityDelta += 1
if servantCount < expectedMin: qualityDelta -= 1
if servantCount > expectedMax + 2: qualityDelta -= 1
if householdOrder >= 80: qualityDelta += 1
if householdOrder <= 30: qualityDelta -= 1
Danach:
- auf
-2..+2pro Tag begrenzen servantQuality = clamp(servantQuality + qualityDelta, 0, 100)
5.6 Daily-Effekt auf Ansehen
Der Daily-Rufeffekt ist klein, damit Monats- und Ereigniseffekte wichtiger bleiben.
reputationDelta = 0
if titleLevel >= 4 and servantCount < expectedMin:
reputationDelta -= 0.15 * missing
if titleLevel <= 1 and servantCount > expectedMax:
reputationDelta -= 0.10 * excessive
if householdOrder >= 85 and servantCount between expectedMin and expectedMax:
reputationDelta += 0.05
if householdOrder <= 25:
reputationDelta -= 0.20
Rundung:
- intern als Dezimalwert möglich
- falls nur Ganzzahlen gespeichert werden, über Tagespuffer oder Rundungsregel aggregieren
5.7 Daily-Effekt auf Ehe / Haushalt
Wenn ein Ehe-Zufriedenheitssystem vorhanden ist:
marriageDelta = 0
if householdOrder >= 75: marriageDelta += 0.10
if householdOrder <= 35: marriageDelta -= 0.15
if servantCount < expectedMin: marriageDelta -= 0.10
Wenn noch kein eigener Wert gespeichert wird:
- diese Regel für später vormerken
- aktuell nur
householdTensionoder UI-Ableitungen beeinflussen
5.8 Daily-Effekt auf Liebschaften / Diskretion
Der Daemon berechnet einen Diskretionsmodifikator:
discretionModifier = 0
if servantQuality >= 70 and servantPayLevel = high and servantCount <= expectedMax:
discretionModifier -= 8
if servantPayLevel = low:
discretionModifier += 6
if servantCount > expectedMax + 1:
discretionModifier += 4
if householdOrder <= 35:
discretionModifier += 5
Bedeutung:
- negativer Wert verbessert Geheimhaltung
- positiver Wert erhöht Entdeckungsrisiko
Anwendung:
- bei aktiven Liebschaften auf Sichtbarkeit/Skandalchance
- bei Untergrundaktivitäten als Erfolgsmodifikator
5.9 Daily-Notifications
Daily sendet nicht für jede Teildrift ein eigenes Event.
Wenn sich einer dieser Punkte relevant verändert:
household_orderservant_qualityreputation- Ehe-/Liebschaftsfolgen über Diener
dann:
falukantUpdateFamilymitreason: "daily"- danach
falukantUpdateStatus
Es gibt keinen separaten reason für Dienerschaft.
6. Monthly-Regeln für den externen Daemon
6.1 Monthly-Input
Wie Daily, zusätzlich:
- aktuelles Geld
falukant_user.money
6.2 Monatskosten
basePerServant = max(20, round((houseType.cost / 1000) + 40))
qualityFactor = 1 + ((servantQuality - 50) / 200)
payFactor(low) = 0.8
payFactor(normal) = 1.0
payFactor(high) = 1.3
monthlyServantCost = servantCount * basePerServant * qualityFactor * payFactor
Auf 2 Nachkommastellen runden.
6.3 Abbuchung
Wenn genügend Geld vorhanden:
- Geld abziehen
- Aktivität z. B.
servants_monthly
Wenn nicht genügend Geld vorhanden:
- so viel wie möglich abziehen oder auf 0 fallen lassen, je nach vorhandener Gesamtlogik
- Unterversorgung markieren
Empfehlung für die erste Version:
- vollständige Abbuchung nur wenn genug Geld da
- sonst
underfunded = true
6.4 Folgen von Unterversorgung
Bei Unterversorgung im Monat:
servantQuality -= 4
householdOrder -= 6
Zusätzlich:
- wenn
titleLevel >= 4:reputation -= 1 - wenn aktive Liebschaften vorhanden: Diskretionsmalus für den Folgemonat
6.5 Monatsbonus bei gutem Haushalt
Wenn gleichzeitig:
servantCountinnerhalb SollbereichservantQuality >= 70householdOrder >= 80servantPayLevel != low
dann:
reputation += 1für hohe Stände abtitleLevel >= 3- kleiner Ehe-/Komfortbonus, falls System vorhanden
6.6 Monthly-Notifications
Nach Monatsverarbeitung:
falukantUpdateFamilymitreason: "monthly"- danach
falukantUpdateStatus
7. Handoff an den externen Daemon
7.1 Der externe Daemon muss lesen
Aus Backend/DB:
falukant_data.user_housefalukant_type.housefalukant_data.falukant_userfalukant_data.character- Titel/Stand
- optional aktive Ehe-/Liebschaftsdaten
7.2 Der externe Daemon muss schreiben
Mindestens:
user_house.servant_qualityuser_house.household_ordercharacter.reputationoder entsprechender Rufwert
Optional, falls vorhanden:
relationship_state.marriage_satisfaction- Hilfs-/Logtabellen für Monatskosten und Unterversorgung
7.3 Der externe Daemon muss senden
Bei relevanten Änderungen:
falukantUpdateFamilyfalukantUpdateStatus
reason nur:
dailymonthly
Keine zusätzlichen Diener-Reason-Werte.
7.4 Idempotenz
Der Daemon muss verhindern, dass Daily/Monthly doppelt auf denselben Tick laufen.
Empfohlen:
- eigene Tick-Marker außerhalb dieses Projekts
- oder Zeitstempel in Worker-Logs
8. Backend-Aufgaben in diesem Projekt
8.1 Bereits erledigt
- Hausfelder in
user_house - Migration
- Produktions-SQL
- House-API mit Dienerwerten
- UI in
HouseView - direkte Spieleraktionen:
- einstellen
- entlassen
- Bezahlungsstufe ändern
8.2 Noch sinnvolle Backend-Nacharbeiten
- eigenes Money-Label für Monatskosten, z. B.
servants_monthly - optional eigener Read-Endpunkt nur für Dienerschaft
- optionale Validierungsgrenzen serverseitig weiter schärfen
- später: Ableitung von
householdTensionstärker an Diener koppeln
9. UI-Anforderungen
Die House-UI soll anzeigen:
- aktuelle Dienerzahl
- Sollbereich
- Monatskosten
- Qualität
- Haushaltsordnung
- Bezahlungsstufe
- Besetzungsstatus
- Ordnungsstatus
Die UI soll direkt erlauben:
+1Diener-1Diener- Pay-Level wechseln
Die UI braucht keine Daemon-Sonderlogik außer normalen House-/Status-Refresh.
10. API-Schnittstellen
Bereits vorgesehen:
GET /api/falukant/housesPOST /api/falukant/houses/servants/hirePOST /api/falukant/houses/servants/dismissPOST /api/falukant/houses/servants/pay-level
Beispiel-Response für GET /houses
{
"roofCondition": 100,
"wallCondition": 100,
"floorCondition": 100,
"windowCondition": 100,
"servantCount": 3,
"servantQuality": 58,
"servantPayLevel": "normal",
"householdOrder": 63,
"houseType": {
"id": 5,
"position": 5,
"cost": 273000,
"labelTr": "family_house"
},
"servantSummary": {
"expectedMin": 3,
"expectedMax": 6,
"monthlyCost": 925.4,
"staffingState": "fitting",
"orderState": "stable"
}
}
11. Technische Architektur
11.1 Quelle der Wahrheit
Quelle der Wahrheit für:
- Stammdaten und persistente Hauswerte: dieses Backend / Datenbank
- Tick-Ausführung: externer Daemon
11.2 Verantwortungstrennung
Dieses Projekt:
- speichert Werte
- bietet UI und API
- berechnet einfache Hilfswerte für Anzeige
Externer Daemon:
- tägliche und monatliche Veränderung
- Kostenabbuchung
- Reputationseffekte
- Verknüpfung mit Familie, Liebschaften und Untergrund
11.3 Warum so
Damit:
- Spiellogik nicht doppelt tickt
- UI trotzdem schon benutzbar ist
- der Daemon später nur auf stabile Felder aufsetzen muss
12. Implementierungs-Backlog
B1 Datenbasis
Status: erledigt
Aufgaben:
- Hausfelder in
user_house - Migration
- Produktions-SQL
Done:
- Felder vorhanden
- Model aktualisiert
B2 Haus-Service
Status: erledigt
Aufgaben:
- Sollbereich berechnen
- Monatskosten berechnen
- Zustandslabels ableiten
Done:
servantSummarywird im House-Read geliefert
B3 Spieleraktionen
Status: erledigt
Aufgaben:
- einstellen
- entlassen
- Bezahlung ändern
Done:
- Endpunkte vorhanden
- UI verdrahtet
B4 House-UI
Status: erledigt
Aufgaben:
- Anzeige in
HouseView - Aktionen
- Locale-Texte
Done:
- HouseView zeigt den Dienerblock
B5 Daemon Daily
Status: offen
Aufgaben:
expectedMin/Maxim Worker berechnenhouseholdOrderdriftenservantQualitydriften- kleinen Reputationseffekt anwenden
- Diskretionsmodifikator für Liebschaften ableiten
daily-Refresh senden
Done-Kriterien:
- täglicher Tick verändert Hauswerte nachvollziehbar
- keine zusätzlichen UI-Reason-Werte nötig
B6 Daemon Monthly
Status: offen
Aufgaben:
- Monatskosten berechnen
- Geld abbuchen
- Unterversorgung behandeln
- Monatsrufeffekte anwenden
monthly-Refresh senden
Done-Kriterien:
- Monatskosten und Unterversorgung sind im Spiel spürbar
B7 Integration mit Familie / Liebschaften
Status: offen
Aufgaben:
householdOrderauf Ehekomfort mappen- Diskretionsmodifikator in Skandal-/Liebschaftslogik einbeziehen
- schlechte Bezahlung oder Überbesetzung als Gerüchtefaktor nutzen
Done-Kriterien:
- Dienerschaft beeinflusst Familien- und Liebschaftssystem real
B8 Integration mit Untergrund
Status: offen
Aufgaben:
investigate_affairnutzt Dienerwerte- schlechter Haushalt erhöht Aufdeckungschance
- guter, diskreter Haushalt senkt Erfolgswahrscheinlichkeit
Done-Kriterien:
- Untergrund spürt Dienerschaft in Erfolgsmodifikatoren
B9 Balancing
Status: offen, bewusst spätere Phase
Aufgaben:
- Kosten, Rufwerte, Driftgeschwindigkeiten und Schwellwerte feinjustieren
13. Produktionshinweise
Wenn keine Migrationen laufen:
- add_servants_to_user_house.sql ausführen
Der externe Daemon muss erst danach aktiviert werden, damit die Felder sicher vorhanden sind.
14. Empfehlung für die nächste Reihenfolge
Empfohlene Reihenfolge ab jetzt:
- Produktions-SQL einspielen
- B5 Daily im externen Daemon
- B6 Monthly im externen Daemon
- B7 Familie/Liebschaften anbinden
- B8 Untergrund anbinden
- B9 Balancing
15. Kurzfazit
Die Haus- und UI-Basis ist bereits eingebaut. Für eine vollständige Spielwirkung fehlen jetzt vor allem die beiden externen Worker-Blöcke:
- tägliche Drift
- monatliche Kosten und Folgen
Mit dieser Datei sollte der externe Daemon direkt implementierbar sein, ohne weitere Konzeptdokumente zu benötigen.