# 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`** (gegen `effective_target` und 5 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 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: 1. `falukantUpdateProductionCertificate` mit `reason`, `old_certificate`, `new_certificate` 2. `falukantUpdateStatus` **`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)