4.2 KiB
Falukant: Produktionszertifikate (Daemon)
Die Zertifikatslogik läuft im 24h-Daily-Tick von FalukantFamilyWorker (run_iteration), nicht in einem eigenen Worker-Thread. Sie ist von der Familien-Migration entkoppelt: Schuldturm + Zertifikat laufen immer im Daily-Intervall; Liebhaber/Ehe/Monatslogik nur, wenn QUERY_FAMILY_SCHEMA_READY (Spalte relationship_state.last_daily_processed_at) erfüllt ist. Sie schreibt falukant_user.certificate fort (max. +1 pro Tag, keine normale Herabstufung außer Bankrott / Erbfolge).
Implementierung: src/worker/falukant_certificate.rs (run_daily).
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, Spec §4)
- certificateScore (Gewichte): Wissen 0,45 · Produktion 0,30 · Amt 0,08 · Adel 0,05 · Ruf 0,07 · Haus 0,05
- raw_target aus Score-Schwellen: <0,9 → 1, ≥0,9 → 2, ≥1,8 → 3, ≥2,8 → 4, ≥3,8 → 5
- effective_target mit Mindestanforderungen je Stufe (Spec §4.5)
- Aufstieg nur wenn
effective_target > current→current + 1(gegeneffective_targetund 5 begrenzt) - Bankrott (
money <= -5000): Zertifikat auf 1, mit Event
Wichtig: UI vs. Daemon („48 h kein Aufstieg“)
Die Mindestanforderungen (z. B. Wissen ≥ 28, Produktionen ≥ 15 für Stufe 3) sind nur ein Teil. Zusätzlich gilt eine Obergrenze aus der gewichteten Wertung (certificateScore → raw_target): Es wird die höchste Stufe ≤ raw_target, die alle Mindestanforderungen erfüllt (effective_certificate_target in falukant_certificate.rs).
Typische Folge: Die UI zeigt nur zwei grüne Häkchen (Wissen/Produktionen), der Spieler bleibt aber auf Stufe 2, weil:
raw_target= 2 (Wertung unter 1,8) — dann ist Stufe 3 fachlich ausgeschlossen, auch wenn die Mindestzahlen für Stufe 3 erfüllt sind. Oft liegt die Wertung knapp unter 1,8, wenn z. B. Produktionspunkte im Daemon niedrig sind (Bucket < 20 abgeschlossene Produktionen infalukant_log.productiontrotz höherer Anzeige in der UI).- Abweichende Eingangsdaten gegenüber der UI: anderer gewählter Charakter (
DISTINCT ON … c.id DESC), andere Zählungfalukant_log.production(producer_id), Geld/Bankrott, etc.
Diagnose: Daemon mit YPDAEMON_CERT_VERBOSE=1 starten. Wenn jemand die Mindestanforderungen für die nächste Stufe erfüllt, aber nicht aufsteigt, erscheint eine Zeile [falukant_certificate] fu_id=… bleibt auf Stufe … mit certificate_score, raw_target, effective_target und Rohwerten.
SQL: QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS in src/worker/sql.rs — für einen Betroffenen falukant_user.id filtern und mit der UI abgleichen.
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 0–5).
Abgeschlossene Produktionen
COUNT(*) aus falukant_log.production mit producer_id = falukant_user.id oder character.id (Backend kann je nach Kontext die eine oder andere ID schreiben).
Gewählter Charakter pro User
Bei mehreren lebenden Charakteren: DISTINCT ON (fu.id) … ORDER BY fu.id, c.id DESC — der Charakter mit der höchsten character.id (typisch zuletzt genutzter Slot), damit Wissen/Ruf/Ämter näher an der UI liegen.
Events (WebSocket)
Bei Änderung der Stufe:
falukantUpdateProductionCertificatemitreason,old_certificate,new_certificatefalukantUpdateStatus
reason: daily_recalculation (normaler Aufstieg), bankruptcy (Geld ≤ −5000), succession_no_heir (Tod ohne Erben → Stufe 1).
user_id in den Events: app_user_id aus der Query (COALESCE(fu.user_id, fu.id)), sonst Fallback falukant_user_id.
Nicht umgesetzt (optional / später)
- Feinere Bankrott-Definition
political_office_history(nicht im Repo)