Enhance marriage pregnancy management in SQL and UserCharacterWorker: Added a new query to clear stale marriage pregnancy records after 30 days. Updated existing queries to include shared children count for more accurate pregnancy probability calculations. Refactored logic in maybe_run_hourly_pregnancies to incorporate the new query and improved documentation for clarity on marriage pregnancy mechanics.
This commit is contained in:
@@ -1666,6 +1666,8 @@ pub const QUERY_AUTOBATISM: &str = r#"
|
|||||||
// Worker würfelt stündlich: P_stunde = 1 - (1 - P_jahr)^(1/8760), damit 24×/Tag zusammen
|
// 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).
|
// 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).
|
// Grenzen in Tagen: 1 Jahr ≈ 365 Tage (mother_age_days).
|
||||||
|
// Erstes gemeinsames Kind (0 Zeilen in child_relation für dieses Paar): prob_year mindestens 1.0
|
||||||
|
// im Alter 18–~44 (6570–16000 Tage), damit kinderlose Ehen nicht über viele Jahre ohne Nachwuchs bleiben.
|
||||||
// WICHTIG: Vater/Mutter und Alter immer über gender ableiten — nicht character1/2 fest als Mutter!
|
// WICHTIG: Vater/Mutter und Alter immer über gender ableiten — nicht character1/2 fest als Mutter!
|
||||||
//
|
//
|
||||||
// Ablauf Ehe: (1) Konzeption setzt `marriage_pregnancy_due_at` (+5 Tage), (2) Geburt wenn fällig.
|
// Ablauf Ehe: (1) Konzeption setzt `marriage_pregnancy_due_at` (+5 Tage), (2) Geburt wenn fällig.
|
||||||
@@ -1705,6 +1707,14 @@ pub const QUERY_CLEAR_MARRIAGE_PREGNANCY_DUE: &str = r#"
|
|||||||
WHERE id = $1::int;
|
WHERE id = $1::int;
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
/// Hängengebliebene Ehe-Schwangerschaft (Geburt fehlgeschlagen / inkonsistent): Flag nach 30 Tagen löschen.
|
||||||
|
pub const QUERY_CLEAR_STALE_MARRIAGE_PREGNANCY_DUE: &str = r#"
|
||||||
|
UPDATE falukant_data.relationship
|
||||||
|
SET marriage_pregnancy_due_at = NULL
|
||||||
|
WHERE marriage_pregnancy_due_at IS NOT NULL
|
||||||
|
AND marriage_pregnancy_due_at < NOW() - INTERVAL '30 days';
|
||||||
|
"#;
|
||||||
|
|
||||||
/// Stündlicher Konzeptionswurf (Ehe): bei Treffer wird `marriage_pregnancy_due_at` auf +5 Tage gesetzt.
|
/// Stündlicher Konzeptionswurf (Ehe): bei Treffer wird `marriage_pregnancy_due_at` auf +5 Tage gesetzt.
|
||||||
pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#"
|
pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#"
|
||||||
WITH paired AS (
|
WITH paired AS (
|
||||||
@@ -1717,7 +1727,13 @@ pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#"
|
|||||||
CASE WHEN c1.gender = 'male' THEN c1.region_id ELSE c2.region_id END AS region_id,
|
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 = '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,
|
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
|
(CURRENT_DATE - c_female.birthdate::date)::int AS mother_age_days,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)::int
|
||||||
|
FROM falukant_data.child_relation cr
|
||||||
|
WHERE cr.father_character_id = (CASE WHEN c1.gender = 'male' THEN c1.id ELSE c2.id END)
|
||||||
|
AND cr.mother_character_id = (CASE WHEN c1.gender = 'female' THEN c1.id ELSE c2.id END)
|
||||||
|
) AS shared_children_count
|
||||||
FROM falukant_data.relationship r
|
FROM falukant_data.relationship r
|
||||||
JOIN falukant_type.relationship r2
|
JOIN falukant_type.relationship r2
|
||||||
ON r2.id = r.relationship_type_id AND r2.tr = 'married'
|
ON r2.id = r.relationship_type_id AND r2.tr = 'married'
|
||||||
@@ -1743,6 +1759,7 @@ pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#"
|
|||||||
p.father_uid,
|
p.father_uid,
|
||||||
p.mother_uid,
|
p.mother_uid,
|
||||||
p.mother_age_days,
|
p.mother_age_days,
|
||||||
|
p.shared_children_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN p.mother_age_days < 4380 THEN 0.005
|
WHEN p.mother_age_days < 4380 THEN 0.005
|
||||||
WHEN p.mother_age_days < 4745 THEN 0.30
|
WHEN p.mother_age_days < 4745 THEN 0.30
|
||||||
@@ -1774,12 +1791,24 @@ pub const QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE: &str = r#"
|
|||||||
WHEN p.mother_age_days < 17520 THEN 0.015
|
WHEN p.mother_age_days < 17520 THEN 0.015
|
||||||
WHEN p.mother_age_days < 18250 THEN 0.005
|
WHEN p.mother_age_days < 18250 THEN 0.005
|
||||||
ELSE 0.001
|
ELSE 0.001
|
||||||
END AS prob_year
|
END AS prob_year_raw
|
||||||
FROM paired p
|
FROM paired p
|
||||||
),
|
),
|
||||||
|
mother_age_final AS (
|
||||||
|
SELECT
|
||||||
|
ma.*,
|
||||||
|
CASE
|
||||||
|
WHEN ma.shared_children_count = 0
|
||||||
|
AND ma.mother_age_days >= 6570
|
||||||
|
AND ma.mother_age_days < 16000
|
||||||
|
THEN GREATEST(ma.prob_year_raw, 1.0)
|
||||||
|
ELSE ma.prob_year_raw
|
||||||
|
END AS prob_year
|
||||||
|
FROM mother_age ma
|
||||||
|
),
|
||||||
conceivable AS (
|
conceivable AS (
|
||||||
SELECT ma.relationship_id
|
SELECT ma.relationship_id
|
||||||
FROM mother_age ma
|
FROM mother_age_final ma
|
||||||
WHERE ma.mother_age_days >= 4380
|
WHERE ma.mother_age_days >= 4380
|
||||||
AND ma.mother_age_days < 18993
|
AND ma.mother_age_days < 18993
|
||||||
AND random() < (1 - POWER(1 - ma.prob_year, 1.0/8760.0))
|
AND random() < (1 - POWER(1 - ma.prob_year, 1.0/8760.0))
|
||||||
@@ -1811,7 +1840,13 @@ pub const QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES: &str = r#"
|
|||||||
CASE WHEN c1.gender = 'male' THEN c1.region_id ELSE c2.region_id END AS region_id,
|
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 = '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,
|
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
|
(CURRENT_DATE - c_female.birthdate::date)::int AS mother_age_days,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)::int
|
||||||
|
FROM falukant_data.child_relation cr
|
||||||
|
WHERE cr.father_character_id = (CASE WHEN c1.gender = 'male' THEN c1.id ELSE c2.id END)
|
||||||
|
AND cr.mother_character_id = (CASE WHEN c1.gender = 'female' THEN c1.id ELSE c2.id END)
|
||||||
|
) AS shared_children_count
|
||||||
FROM falukant_data.relationship r
|
FROM falukant_data.relationship r
|
||||||
JOIN falukant_type.relationship r2
|
JOIN falukant_type.relationship r2
|
||||||
ON r2.id = r.relationship_type_id AND r2.tr = 'married'
|
ON r2.id = r.relationship_type_id AND r2.tr = 'married'
|
||||||
@@ -1835,6 +1870,7 @@ pub const QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES: &str = r#"
|
|||||||
p.father_uid,
|
p.father_uid,
|
||||||
p.mother_uid,
|
p.mother_uid,
|
||||||
p.mother_age_days,
|
p.mother_age_days,
|
||||||
|
p.shared_children_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN p.mother_age_days < 4380 THEN 0.005
|
WHEN p.mother_age_days < 4380 THEN 0.005
|
||||||
WHEN p.mother_age_days < 4745 THEN 0.30
|
WHEN p.mother_age_days < 4745 THEN 0.30
|
||||||
@@ -1866,8 +1902,20 @@ pub const QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES: &str = r#"
|
|||||||
WHEN p.mother_age_days < 17520 THEN 0.015
|
WHEN p.mother_age_days < 17520 THEN 0.015
|
||||||
WHEN p.mother_age_days < 18250 THEN 0.005
|
WHEN p.mother_age_days < 18250 THEN 0.005
|
||||||
ELSE 0.001
|
ELSE 0.001
|
||||||
END AS prob_year
|
END AS prob_year_raw
|
||||||
FROM paired p
|
FROM paired p
|
||||||
|
),
|
||||||
|
mother_age_final AS (
|
||||||
|
SELECT
|
||||||
|
ma.*,
|
||||||
|
CASE
|
||||||
|
WHEN ma.shared_children_count = 0
|
||||||
|
AND ma.mother_age_days >= 6570
|
||||||
|
AND ma.mother_age_days < 16000
|
||||||
|
THEN GREATEST(ma.prob_year_raw, 1.0)
|
||||||
|
ELSE ma.prob_year_raw
|
||||||
|
END AS prob_year
|
||||||
|
FROM mother_age ma
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
father_cid,
|
father_cid,
|
||||||
@@ -1879,7 +1927,7 @@ pub const QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES: &str = r#"
|
|||||||
mother_uid,
|
mother_uid,
|
||||||
mother_age_days,
|
mother_age_days,
|
||||||
(1 - POWER(1 - prob_year, 1.0/8760.0)) * 100 AS prob_pct
|
(1 - POWER(1 - prob_year, 1.0/8760.0)) * 100 AS prob_pct
|
||||||
FROM mother_age
|
FROM mother_age_final
|
||||||
WHERE mother_age_days >= 4380
|
WHERE mother_age_days >= 4380
|
||||||
AND mother_age_days < 18993
|
AND mother_age_days < 18993
|
||||||
AND random() < (1 - POWER(1 - prob_year, 1.0/8760.0));
|
AND random() < (1 - POWER(1 - prob_year, 1.0/8760.0));
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ use crate::worker::sql::{
|
|||||||
QUERY_UPDATE_USER_MONEY,
|
QUERY_UPDATE_USER_MONEY,
|
||||||
QUERY_GET_FALUKANT_USER_ID,
|
QUERY_GET_FALUKANT_USER_ID,
|
||||||
QUERY_AUTOBATISM,
|
QUERY_AUTOBATISM,
|
||||||
QUERY_CLEAR_MARRIAGE_PREGNANCY_DUE, QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES,
|
QUERY_CLEAR_MARRIAGE_PREGNANCY_DUE, QUERY_CLEAR_STALE_MARRIAGE_PREGNANCY_DUE,
|
||||||
|
QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES,
|
||||||
QUERY_GET_MARRIAGE_BIRTH_DELIVERIES, QUERY_MARRIAGE_PREGNANCY_COLUMN_READY,
|
QUERY_GET_MARRIAGE_BIRTH_DELIVERIES, QUERY_MARRIAGE_PREGNANCY_COLUMN_READY,
|
||||||
QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE,
|
QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE,
|
||||||
QUERY_INSERT_CHILD,
|
QUERY_INSERT_CHILD,
|
||||||
@@ -181,6 +182,7 @@ impl UserCharacterWorker {
|
|||||||
/// Ehe-Schwangerschaft: höchstens einmal pro Stunde (Daemon-Schleife ~1 s).
|
/// Ehe-Schwangerschaft: höchstens einmal pro Stunde (Daemon-Schleife ~1 s).
|
||||||
/// Konzeption setzt `marriage_pregnancy_due_at` (+5 Tage); Geburt über `QUERY_GET_MARRIAGE_BIRTH_DELIVERIES`.
|
/// Konzeption setzt `marriage_pregnancy_due_at` (+5 Tage); Geburt über `QUERY_GET_MARRIAGE_BIRTH_DELIVERIES`.
|
||||||
/// Stündliche Zerlegung der Jahres-Wahrscheinlichkeit (`1/8760`), siehe `QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE`.
|
/// Stündliche Zerlegung der Jahres-Wahrscheinlichkeit (`1/8760`), siehe `QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE`.
|
||||||
|
/// Erstes gemeinsames Kind: Jahreswahrscheinlichkeit mindestens 1.0 (18–~44 J.), siehe `sql.rs`.
|
||||||
fn maybe_run_hourly_pregnancies(&mut self) {
|
fn maybe_run_hourly_pregnancies(&mut self) {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let should_run = match self.last_pregnancy_run {
|
let should_run = match self.last_pregnancy_run {
|
||||||
@@ -569,6 +571,9 @@ impl UserCharacterWorker {
|
|||||||
self.process_single_marriage_delivery(&mut conn, &row)?;
|
self.process_single_marriage_delivery(&mut conn, &row)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn.prepare("clear_stale_preg", QUERY_CLEAR_STALE_MARRIAGE_PREGNANCY_DUE)?;
|
||||||
|
conn.execute("clear_stale_preg", &[])?;
|
||||||
|
|
||||||
conn.prepare("try_conception", QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE)?;
|
conn.prepare("try_conception", QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE)?;
|
||||||
conn.execute("try_conception", &[])?;
|
conn.execute("try_conception", &[])?;
|
||||||
} else {
|
} else {
|
||||||
@@ -590,7 +595,7 @@ impl UserCharacterWorker {
|
|||||||
let relationship_id = parse_i32(row, "relationship_id", -1);
|
let relationship_id = parse_i32(row, "relationship_id", -1);
|
||||||
let father_cid = parse_i32(row, "father_cid", -1);
|
let father_cid = parse_i32(row, "father_cid", -1);
|
||||||
let mother_cid = parse_i32(row, "mother_cid", -1);
|
let mother_cid = parse_i32(row, "mother_cid", -1);
|
||||||
if relationship_id < 0 || father_cid < 0 || mother_cid < 0 {
|
if father_cid < 0 || mother_cid < 0 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user