diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 0ba0e97..7e8fd3d 100755 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -2175,10 +2175,8 @@ pub const QUERY_GET_MARRIAGE_BIRTH_DELIVERIES: &str = r#" LEFT JOIN falukant_data.falukant_user fu2 ON fu2.id = c2.user_id WHERE r.marriage_pregnancy_due_at IS NOT NULL AND r.marriage_pregnancy_due_at <= NOW() - -- Eine fällige automatische Ehe-Geburt bleibt vorgemerkt, bis beide - -- Eltern mindestens 16 Spieljahre (Kalendertage) alt sind. - AND c1.birthdate <= CURRENT_DATE - INTERVAL '16 days' - AND c2.birthdate <= CURRENT_DATE - INTERVAL '16 days' + -- Das Fruchtbarkeitsalter wird bei der Konzeption geprüft. + -- Bestehende Schwangerschaften werden durch Backfills nicht blockiert. AND ((c1.gender = 'male' AND c2.gender = 'female') OR (c1.gender = 'female' AND c2.gender = 'male')) AND c_female.pregnancy_due_at IS NULL @@ -2233,8 +2231,8 @@ pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#" 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 r.marriage_pregnancy_due_at IS NULL - AND c1.birthdate <= CURRENT_DATE - INTERVAL '16 days' - AND c2.birthdate <= CURRENT_DATE - INTERVAL '16 days' + AND (CURRENT_DATE - c1.birthdate::date) >= c1.fertile_from_age + AND (CURRENT_DATE - c2.birthdate::date) >= c2.fertile_from_age AND ((c1.gender = 'male' AND c2.gender = 'female') OR (c1.gender = 'female' AND c2.gender = 'male')) AND c_female.pregnancy_due_at IS NULL @@ -2256,8 +2254,7 @@ pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#" conceivable AS ( SELECT ma.relationship_id FROM mother_age ma - WHERE ma.mother_age_days >= 16 - AND random() < ma.prob_year + WHERE random() < ma.prob_year ) UPDATE falukant_data.relationship r SET marriage_pregnancy_due_at = NOW() + INTERVAL '18 hours' @@ -2304,8 +2301,8 @@ pub const QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES: &str = r#" 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')) - AND c1.birthdate <= CURRENT_DATE - INTERVAL '16 days' - AND c2.birthdate <= CURRENT_DATE - INTERVAL '16 days' + AND (CURRENT_DATE - c1.birthdate::date) >= c1.fertile_from_age + AND (CURRENT_DATE - c2.birthdate::date) >= c2.fertile_from_age AND c_female.pregnancy_due_at IS NULL AND NOT EXISTS ( SELECT 1 @@ -2338,8 +2335,7 @@ pub const QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES: &str = r#" mother_age_days, prob_year * 100.0 AS prob_pct FROM mother_age - WHERE mother_age_days >= 16 - AND random() < prob_year; + WHERE random() < prob_year; "#; /// Spalten `pregnancy_due_at` / `pregnancy_father_character_id` auf `character` (Migration `011_…`). @@ -3945,8 +3941,8 @@ pub const QUERY_GET_LOVER_PREGNANCY_CANDIDATES: &str = r#" -- `last_monthly_processed_at` wird im Familien-Tageslauf mitgeführt (1 Spieljahr = 1 Kalendertag). AND rs.last_monthly_processed_at IS NOT NULL AND rs.last_monthly_processed_at >= NOW() - INTERVAL '50 days' - AND c1.birthdate <= CURRENT_DATE - INTERVAL '16 days' - AND c2.birthdate <= CURRENT_DATE - INTERVAL '16 days' + AND (CURRENT_DATE - c1.birthdate::date) >= c1.fertile_from_age + AND (CURRENT_DATE - c2.birthdate::date) >= c2.fertile_from_age AND c_female.pregnancy_due_at IS NULL AND NOT EXISTS ( SELECT 1 @@ -3966,7 +3962,6 @@ pub const QUERY_GET_LOVER_PREGNANCY_CANDIDATES: &str = r#" AND cr.created_at::date = CURRENT_DATE ) -- Ein Kalendertag entspricht einem Spieljahr (vgl. Ehe-Konzeption). - AND (CURRENT_DATE - c_female.birthdate::date) >= 16 AND random() * 100.0 < ( LEAST(12.0, GREATEST(0.0, CASE rs.lover_role @@ -3991,12 +3986,12 @@ pub const QUERY_SET_CHARACTER_PREGNANCY_FROM_LOVER: &str = r#" WHERE c_m.id = $1::int AND c_m.health > 0 AND c_m.pregnancy_due_at IS NULL - AND c_m.birthdate <= CURRENT_DATE - INTERVAL '16 days' + AND (CURRENT_DATE - c_m.birthdate::date) >= c_m.fertile_from_age AND EXISTS ( SELECT 1 FROM falukant_data.character c_f WHERE c_f.id = $2::int - AND c_f.birthdate <= CURRENT_DATE - INTERVAL '16 days' + AND (CURRENT_DATE - c_f.birthdate::date) >= c_f.fertile_from_age ) AND NOT EXISTS ( SELECT 1 @@ -4176,7 +4171,6 @@ mod tests { use super::*; const AGE_14_GUARD: &str = "birthdate <= CURRENT_DATE - INTERVAL '14 days'"; - const AGE_16_GUARD: &str = "birthdate <= CURRENT_DATE - INTERVAL '16 days'"; #[test] fn weddings_require_both_fiances_to_be_fourteen() { @@ -4185,30 +4179,40 @@ mod tests { } #[test] - fn automatic_pregnancy_paths_require_both_parents_to_be_sixteen() { + fn automatic_conception_uses_each_parents_individual_fertility_age() { for query in [ - QUERY_GET_MARRIAGE_BIRTH_DELIVERIES, QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE, QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES, QUERY_GET_LOVER_PREGNANCY_CANDIDATES, ] { - assert_eq!(query.matches(AGE_16_GUARD).count(), 2, "{query}"); + for parent in ["c1", "c2"] { + assert!( + query.contains(&format!( + "(CURRENT_DATE - {parent}.birthdate::date) >= {parent}.fertile_from_age" + )), + "{query}" + ); + } + assert!(!query.contains("16 days"), "{query}"); + assert!(!query.contains(">= 16"), "{query}"); + assert!(!query.contains("5110"), "{query}"); + } + for parent in ["c_m", "c_f"] { + assert!(QUERY_SET_CHARACTER_PREGNANCY_FROM_LOVER.contains(&format!( + "(CURRENT_DATE - {parent}.birthdate::date) >= {parent}.fertile_from_age" + ))); } - - assert!(QUERY_SET_CHARACTER_PREGNANCY_FROM_LOVER.contains(AGE_16_GUARD)); - assert!(QUERY_GET_PLANNED_CHARACTER_BIRTH_DELIVERIES.contains("pregnancy_due_at <= NOW()")); - assert!(!QUERY_GET_PLANNED_CHARACTER_BIRTH_DELIVERIES.contains(AGE_16_GUARD)); } #[test] - fn automatic_conception_uses_game_years_not_real_world_days() { + fn due_births_are_not_blocked_by_backfilled_fertility_ages() { for query in [ - QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE, - QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES, - QUERY_GET_LOVER_PREGNANCY_CANDIDATES, + QUERY_GET_MARRIAGE_BIRTH_DELIVERIES, + QUERY_GET_PLANNED_CHARACTER_BIRTH_DELIVERIES, ] { - assert!(!query.contains("5110"), "{query}"); - assert!(query.contains(">= 16"), "{query}"); + assert!(!query.contains("fertile_from_age")); + assert!(!query.contains("16 days")); + assert!(query.contains("<= NOW()")); } }