From 4086e9a207c657b49afdb8ea7156667514003219 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Sun, 22 Mar 2026 09:43:36 +0100 Subject: [PATCH] Refactor pregnancy handling in UserCharacterWorker: Changed the pregnancy check from a daily to an hourly basis, updating the associated method and SQL query to reflect this new frequency. This adjustment improves the accuracy of pregnancy probability calculations and aligns with the updated family dynamics logic. --- YpDaemon/src/worker/user_character.rs | 8 +- src/worker/sql.rs | 113 +++++++++++++++----------- src/worker/user_character.rs | 8 +- 3 files changed, 76 insertions(+), 53 deletions(-) diff --git a/YpDaemon/src/worker/user_character.rs b/YpDaemon/src/worker/user_character.rs index 0838724..828bb86 100644 --- a/YpDaemon/src/worker/user_character.rs +++ b/YpDaemon/src/worker/user_character.rs @@ -85,7 +85,7 @@ impl UserCharacterWorker { self.maybe_run_hourly_tasks(); self.maybe_run_mood_updates(); - self.maybe_run_daily_pregnancies(); + self.maybe_run_hourly_pregnancies(); // Entspricht in etwa der 1-Sekunden-Schleife im C++-Code std::thread::sleep(Duration::from_secs(1)); @@ -123,11 +123,13 @@ impl UserCharacterWorker { Ok(()) } - fn maybe_run_daily_pregnancies(&mut self) { + /// Ehe-Schwangerschaft: höchstens einmal pro Stunde (Daemon-Schleife ~1 s). + /// SQL nutzt stündliche Zerlegung der Jahres-Wahrscheinlichkeit (`1/8760`), siehe `QUERY_GET_PREGNANCY_CANDIDATES`. + fn maybe_run_hourly_pregnancies(&mut self) { let now = Instant::now(); let should_run = match self.last_pregnancy_run { None => true, - Some(last) => now.saturating_duration_since(last) >= Duration::from_secs(24 * 3600), + Some(last) => now.saturating_duration_since(last) >= Duration::from_secs(3600), }; if !should_run { diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 8040ef5..b3e2f76 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -1218,73 +1218,92 @@ pub const QUERY_AUTOBATISM: &str = r#" "#; // Biologische Fruchtbarkeit nach Alter der Frau (Jahres-Wahrscheinlichkeit). -// Umrechnung auf Tages-Wahrscheinlichkeit: P_tag = 1 - (1 - P_jahr)^(1/365) -// Grenzen in Tagen: 1 Jahr ≈ 365 Tage +// Worker würfelt stündlich: P_stunde = 1 - (1 - P_jahr)^(1/8760), damit 24×/Tag zusammen +// dieselbe kumulative Jahresaufteilung wie früher 1×/Tag mit P_tag = 1 - (1 - P_jahr)^(1/365). +// Grenzen in Tagen: 1 Jahr ≈ 365 Tage (mother_age_days). +// WICHTIG: Vater/Mutter und Alter immer über gender ableiten — nicht character1/2 fest als Mutter! pub const QUERY_GET_PREGNANCY_CANDIDATES: &str = r#" - WITH mother_age AS ( + WITH paired AS ( SELECT - r.character1_id, - r.character2_id, - c1.title_of_nobility, - c1.last_name, - c1.region_id, - fu1.id AS father_uid, - fu2.id AS mother_uid, - (CURRENT_DATE - c2.birthdate::date)::int AS mother_age_days, - CASE - WHEN (CURRENT_DATE - c2.birthdate::date) < 4380 THEN 0.005 - WHEN (CURRENT_DATE - c2.birthdate::date) < 4745 THEN 0.30 - WHEN (CURRENT_DATE - c2.birthdate::date) < 5110 THEN 0.45 - WHEN (CURRENT_DATE - c2.birthdate::date) < 5475 THEN 0.55 - WHEN (CURRENT_DATE - c2.birthdate::date) < 5840 THEN 0.60 - WHEN (CURRENT_DATE - c2.birthdate::date) < 6205 THEN 0.725 - WHEN (CURRENT_DATE - c2.birthdate::date) < 6570 THEN 0.80 - WHEN (CURRENT_DATE - c2.birthdate::date) < 7305 THEN 0.855 - WHEN (CURRENT_DATE - c2.birthdate::date) < 9125 THEN 0.875 - WHEN (CURRENT_DATE - c2.birthdate::date) < 10950 THEN 0.84 - WHEN (CURRENT_DATE - c2.birthdate::date) < 11315 THEN 0.785 - WHEN (CURRENT_DATE - c2.birthdate::date) < 11680 THEN 0.765 - WHEN (CURRENT_DATE - c2.birthdate::date) < 12045 THEN 0.74 - WHEN (CURRENT_DATE - c2.birthdate::date) < 12410 THEN 0.72 - WHEN (CURRENT_DATE - c2.birthdate::date) < 12775 THEN 0.695 - WHEN (CURRENT_DATE - c2.birthdate::date) < 13140 THEN 0.65 - WHEN (CURRENT_DATE - c2.birthdate::date) < 13505 THEN 0.63 - WHEN (CURRENT_DATE - c2.birthdate::date) < 13870 THEN 0.60 - WHEN (CURRENT_DATE - c2.birthdate::date) < 14235 THEN 0.55 - WHEN (CURRENT_DATE - c2.birthdate::date) < 14600 THEN 0.50 - WHEN (CURRENT_DATE - c2.birthdate::date) < 14965 THEN 0.45 - WHEN (CURRENT_DATE - c2.birthdate::date) < 15330 THEN 0.35 - WHEN (CURRENT_DATE - c2.birthdate::date) < 15695 THEN 0.25 - WHEN (CURRENT_DATE - c2.birthdate::date) < 16060 THEN 0.15 - WHEN (CURRENT_DATE - c2.birthdate::date) < 16425 THEN 0.075 - WHEN (CURRENT_DATE - c2.birthdate::date) < 16790 THEN 0.03 - WHEN (CURRENT_DATE - c2.birthdate::date) < 17155 THEN 0.02 - WHEN (CURRENT_DATE - c2.birthdate::date) < 17520 THEN 0.015 - WHEN (CURRENT_DATE - c2.birthdate::date) < 18250 THEN 0.005 - ELSE 0.001 - END AS prob_year + CASE WHEN c1.gender = 'male' THEN c1.id ELSE c2.id END AS father_cid, + CASE WHEN c1.gender = 'female' THEN c1.id ELSE c2.id END AS mother_cid, + CASE WHEN c1.gender = 'male' THEN c1.title_of_nobility ELSE c2.title_of_nobility END AS title_of_nobility, + CASE WHEN c1.gender = 'male' THEN c1.last_name ELSE c2.last_name END AS last_name, + CASE WHEN c1.gender = 'male' THEN c1.region_id ELSE c2.region_id END AS region_id, + CASE WHEN c1.gender = 'male' THEN fu1.id ELSE fu2.id END AS father_uid, + CASE WHEN c1.gender = 'female' THEN fu1.id ELSE fu2.id END AS mother_uid, + (CURRENT_DATE - c_female.birthdate::date)::int AS mother_age_days FROM falukant_data.relationship r JOIN falukant_type.relationship r2 ON r2.id = r.relationship_type_id AND r2.tr = 'married' JOIN falukant_data.character c1 ON c1.id = r.character1_id JOIN falukant_data.character c2 ON c2.id = r.character2_id + JOIN falukant_data.character c_female ON c_female.id = ( + CASE WHEN c1.gender = 'female' THEN c1.id ELSE c2.id END + ) LEFT JOIN falukant_data.falukant_user fu1 ON fu1.id = c1.user_id LEFT JOIN falukant_data.falukant_user fu2 ON fu2.id = c2.user_id + WHERE (c1.gender = 'male' AND c2.gender = 'female') + OR (c1.gender = 'female' AND c2.gender = 'male') + ), + mother_age AS ( + SELECT + p.father_cid, + p.mother_cid, + p.title_of_nobility, + p.last_name, + p.region_id, + p.father_uid, + p.mother_uid, + p.mother_age_days, + CASE + WHEN p.mother_age_days < 4380 THEN 0.005 + WHEN p.mother_age_days < 4745 THEN 0.30 + WHEN p.mother_age_days < 5110 THEN 0.45 + WHEN p.mother_age_days < 5475 THEN 0.55 + WHEN p.mother_age_days < 5840 THEN 0.60 + WHEN p.mother_age_days < 6205 THEN 0.725 + WHEN p.mother_age_days < 6570 THEN 0.80 + WHEN p.mother_age_days < 7305 THEN 0.855 + WHEN p.mother_age_days < 9125 THEN 0.875 + WHEN p.mother_age_days < 10950 THEN 0.84 + WHEN p.mother_age_days < 11315 THEN 0.785 + WHEN p.mother_age_days < 11680 THEN 0.765 + WHEN p.mother_age_days < 12045 THEN 0.74 + WHEN p.mother_age_days < 12410 THEN 0.72 + WHEN p.mother_age_days < 12775 THEN 0.695 + WHEN p.mother_age_days < 13140 THEN 0.65 + WHEN p.mother_age_days < 13505 THEN 0.63 + WHEN p.mother_age_days < 13870 THEN 0.60 + WHEN p.mother_age_days < 14235 THEN 0.55 + WHEN p.mother_age_days < 14600 THEN 0.50 + WHEN p.mother_age_days < 14965 THEN 0.45 + WHEN p.mother_age_days < 15330 THEN 0.35 + WHEN p.mother_age_days < 15695 THEN 0.25 + WHEN p.mother_age_days < 16060 THEN 0.15 + WHEN p.mother_age_days < 16425 THEN 0.075 + WHEN p.mother_age_days < 16790 THEN 0.03 + WHEN p.mother_age_days < 17155 THEN 0.02 + WHEN p.mother_age_days < 17520 THEN 0.015 + WHEN p.mother_age_days < 18250 THEN 0.005 + ELSE 0.001 + END AS prob_year + FROM paired p ) SELECT - character1_id AS father_cid, - character2_id AS mother_cid, + father_cid, + mother_cid, title_of_nobility, last_name, region_id, father_uid, mother_uid, mother_age_days, - (1 - POWER(1 - prob_year, 1.0/365.0)) * 100 AS prob_pct + (1 - POWER(1 - prob_year, 1.0/8760.0)) * 100 AS prob_pct FROM mother_age WHERE mother_age_days >= 4380 AND mother_age_days < 18993 - AND random() < (1 - POWER(1 - prob_year, 1.0/365.0)); + AND random() < (1 - POWER(1 - prob_year, 1.0/8760.0)); "#; pub const QUERY_INSERT_CHILD: &str = r#" diff --git a/src/worker/user_character.rs b/src/worker/user_character.rs index 3b0b6ee..df9a752 100644 --- a/src/worker/user_character.rs +++ b/src/worker/user_character.rs @@ -89,7 +89,7 @@ impl UserCharacterWorker { self.maybe_run_hourly_tasks(); self.maybe_run_death_check(); self.maybe_run_mood_updates(); - self.maybe_run_daily_pregnancies(); + self.maybe_run_hourly_pregnancies(); // Entspricht in etwa der 1-Sekunden-Schleife im C++-Code std::thread::sleep(Duration::from_secs(1)); @@ -172,11 +172,13 @@ impl UserCharacterWorker { Ok(()) } - fn maybe_run_daily_pregnancies(&mut self) { + /// Ehe-Schwangerschaft: höchstens einmal pro Stunde (Daemon-Schleife ~1 s). + /// SQL nutzt stündliche Zerlegung der Jahres-Wahrscheinlichkeit (`1/8760`), siehe `QUERY_GET_PREGNANCY_CANDIDATES`. + fn maybe_run_hourly_pregnancies(&mut self) { let now = Instant::now(); let should_run = match self.last_pregnancy_run { None => true, - Some(last) => now.saturating_duration_since(last) >= Duration::from_secs(24 * 3600), + Some(last) => now.saturating_duration_since(last) >= Duration::from_secs(3600), }; if !should_run {