Nutze individuelles Fruchtbarkeitsalter für Schwangerschaften
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 4m42s

This commit is contained in:
Torsten Schulz (local)
2026-11-04 14:16:13 +01:00
parent ebb23787c3
commit 4fbb4d371c

View File

@@ -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()"));
}
}