Update version and edition in Cargo.toml; enhance breakup risk management in FalukantFamilyWorker: Added logic to automatically deactivate low-affection relationships and notify users of high breakup risks. Updated SQL queries to support these changes.
Some checks failed
Deploy yourpart (blue-green) / deploy (push) Failing after 3s
Some checks failed
Deploy yourpart (blue-green) / deploy (push) Failing after 3s
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "YpDaemon"
|
name = "YpDaemon"
|
||||||
version = "0.1.0"
|
version = "0.5.0"
|
||||||
edition = "2024"
|
edition = "2026"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use rand::SeedableRng;
|
|||||||
|
|
||||||
use super::base::{BaseWorker, Worker, WorkerState};
|
use super::base::{BaseWorker, Worker, WorkerState};
|
||||||
use super::sql::{
|
use super::sql::{
|
||||||
|
QUERY_DEACTIVATE_LOVER_RELATIONSHIP,
|
||||||
QUERY_COUNT_LOVER_CHILDREN_FOR_USER, QUERY_FAMILY_SCHEMA_READY,
|
QUERY_COUNT_LOVER_CHILDREN_FOR_USER, QUERY_FAMILY_SCHEMA_READY,
|
||||||
QUERY_GET_ACTIVE_LOVER_ROWS_FOR_DAILY, QUERY_GET_ACTIVE_LOVER_ROWS_FOR_MONTHLY,
|
QUERY_GET_ACTIVE_LOVER_ROWS_FOR_DAILY, QUERY_GET_ACTIVE_LOVER_ROWS_FOR_MONTHLY,
|
||||||
QUERY_GET_ACTIVE_LOVER_ROWS_FOR_INSTALLMENT, QUERY_GET_LOVER_PREGNANCY_CANDIDATES,
|
QUERY_GET_ACTIVE_LOVER_ROWS_FOR_INSTALLMENT, QUERY_GET_LOVER_PREGNANCY_CANDIDATES,
|
||||||
@@ -32,6 +33,7 @@ use super::sql::{
|
|||||||
};
|
};
|
||||||
use crate::db::{ConnectionPool, DbError};
|
use crate::db::{ConnectionPool, DbError};
|
||||||
use crate::message_broker::MessageBroker;
|
use crate::message_broker::MessageBroker;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
const DAILY_INTERVAL: Duration = Duration::from_secs(24 * 3600);
|
const DAILY_INTERVAL: Duration = Duration::from_secs(24 * 3600);
|
||||||
/// Wie `DAILY_INTERVAL`: 1 Spieljahr = 1 Kalendertag — Monats-Stempel/„monthly“-Batch pro Spieltag, nicht alle 30 echten Tage.
|
/// Wie `DAILY_INTERVAL`: 1 Spieljahr = 1 Kalendertag — Monats-Stempel/„monthly“-Batch pro Spieltag, nicht alle 30 echten Tage.
|
||||||
@@ -258,6 +260,10 @@ impl FalukantFamilyWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn.prepare("upd_vd", QUERY_UPDATE_LOVER_VISIBILITY_DISCRETION)?;
|
conn.prepare("upd_vd", QUERY_UPDATE_LOVER_VISIBILITY_DISCRETION)?;
|
||||||
|
conn.prepare("deactivate_lover", QUERY_DEACTIVATE_LOVER_RELATIONSHIP)?;
|
||||||
|
let mut ended_rel_ids: HashSet<i32> = HashSet::new();
|
||||||
|
let mut breakup_socket_users: HashSet<i32> = HashSet::new();
|
||||||
|
let mut breakup_risk_notified: HashSet<(i32, i32)> = HashSet::new();
|
||||||
for l in &mut lovers {
|
for l in &mut lovers {
|
||||||
let ehe_conflict = marriages.iter().any(|m| {
|
let ehe_conflict = marriages.iter().any(|m| {
|
||||||
(m.m1 == l.c1 || m.m2 == l.c1 || m.m1 == l.c2 || m.m2 == l.c2) && m.satisfaction < 40
|
(m.m1 == l.c1 || m.m2 == l.c1 || m.m1 == l.c2 || m.m2 == l.c2) && m.satisfaction < 40
|
||||||
@@ -304,7 +310,42 @@ impl FalukantFamilyWorker {
|
|||||||
)?;
|
)?;
|
||||||
l.visibility = new_vis;
|
l.visibility = new_vis;
|
||||||
l.discretion = new_disc;
|
l.discretion = new_disc;
|
||||||
|
|
||||||
|
// Je niedriger die Zuneigung, desto höher das tägliche Trennungsrisiko.
|
||||||
|
let breakup_risk_pct = breakup_risk_percent(l);
|
||||||
|
if breakup_risk_pct > 50.0 {
|
||||||
|
for uid in [l.user1_id, l.user2_id].into_iter().flatten() {
|
||||||
|
if uid <= 0 || !breakup_risk_notified.insert((l.rel_id, uid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let payload = json!({
|
||||||
|
"tr": "random_event.lover_breakup_risk_high",
|
||||||
|
"event_id": "lover_breakup_risk_high",
|
||||||
|
"event_type": "family",
|
||||||
|
"relationship_id": l.rel_id,
|
||||||
|
"risk_percent": breakup_risk_pct,
|
||||||
|
"affection": l.affection,
|
||||||
|
"visibility": l.visibility,
|
||||||
|
"discretion": l.discretion,
|
||||||
|
"months_underfunded": l.months_underfunded
|
||||||
|
})
|
||||||
|
.to_string();
|
||||||
|
if let Err(e) = super::notify::insert_notification_conn(&mut conn, uid, &payload, None) {
|
||||||
|
eprintln!(
|
||||||
|
"[FalukantFamilyWorker] high breakup risk notification failed rel_id={} uid={}: {}",
|
||||||
|
l.rel_id, uid, e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if breakup_risk_pct > 0.0 && self.dist.sample(&mut self.rng) * 100.0 < breakup_risk_pct {
|
||||||
|
conn.execute("deactivate_lover", &[&l.rel_id])?;
|
||||||
|
ended_rel_ids.insert(l.rel_id);
|
||||||
|
push_user_id(&mut breakup_socket_users, l.user1_id);
|
||||||
|
push_user_id(&mut breakup_socket_users, l.user2_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
lovers.retain(|l| !ended_rel_ids.contains(&l.rel_id));
|
||||||
|
|
||||||
conn.prepare("mark_daily", QUERY_MARK_LOVER_DAILY_DONE)?;
|
conn.prepare("mark_daily", QUERY_MARK_LOVER_DAILY_DONE)?;
|
||||||
conn.prepare("mark_monthly", QUERY_MARK_LOVER_MONTHLY_DONE)?;
|
conn.prepare("mark_monthly", QUERY_MARK_LOVER_MONTHLY_DONE)?;
|
||||||
@@ -673,6 +714,7 @@ impl FalukantFamilyWorker {
|
|||||||
}
|
}
|
||||||
notify.extend(marriage_socket_users);
|
notify.extend(marriage_socket_users);
|
||||||
notify.extend(tension_socket_users);
|
notify.extend(tension_socket_users);
|
||||||
|
notify.extend(breakup_socket_users);
|
||||||
self.publish_falukant_update_family_batch(¬ify, "daily");
|
self.publish_falukant_update_family_batch(¬ify, "daily");
|
||||||
|
|
||||||
drop(conn);
|
drop(conn);
|
||||||
@@ -1279,6 +1321,19 @@ fn visibility_young_penalty(min_age_years: i32, visibility: i32) -> f64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn breakup_risk_percent(l: &LoverData) -> f64 {
|
||||||
|
if l.affection >= 45 {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let affection_risk = (45 - l.affection).max(0) as f64 * 0.5;
|
||||||
|
let underfund_risk = (l.months_underfunded.max(0) as f64 * 1.5).min(10.0);
|
||||||
|
let visibility_risk = if l.visibility >= 70 { 2.0 } else { 0.0 };
|
||||||
|
let discretion_risk = if l.discretion <= 30 { 3.0 } else { 0.0 };
|
||||||
|
|
||||||
|
(affection_risk + underfund_risk + visibility_risk + discretion_risk).clamp(0.0, 30.0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Spec Skandalrisiko: stufenweise Zusatz (exklusiv).
|
/// Spec Skandalrisiko: stufenweise Zusatz (exklusiv).
|
||||||
fn scandal_age_extra_pct(min_age_years: i32) -> f64 {
|
fn scandal_age_extra_pct(min_age_years: i32) -> f64 {
|
||||||
if min_age_years <= 13 {
|
if min_age_years <= 13 {
|
||||||
|
|||||||
@@ -444,6 +444,11 @@ SELECT tpw.region_id, tpw.product_id, tpw.worth_percent FROM falukant_data.town_
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
// Political offices and cumulative tax
|
// Political offices and cumulative tax
|
||||||
|
//
|
||||||
|
// `falukant_type.political_office_type.term_length`: überall als **Kalendertage** (Integer),
|
||||||
|
// nie als Jahre. Ablauf: `po.created_at + term_length * INTERVAL '1 day'`.
|
||||||
|
// Steht in den Stammdaten z. B. `4` für „4 Jahre“, wären das faktisch **4 Tage** — dann
|
||||||
|
// Werte auf Tage umrechnen (z. B. 4 Jahre → 1460) oder die Spalte/Seed-Daten korrigieren.
|
||||||
pub const QUERY_GET_USER_OFFICES: &str = r#"
|
pub const QUERY_GET_USER_OFFICES: &str = r#"
|
||||||
SELECT po.id AS office_id, pot.name AS office_name, po.region_id, rt.label_tr AS region_type
|
SELECT po.id AS office_id, pot.name AS office_name, po.region_id, rt.label_tr AS region_type
|
||||||
FROM falukant_data.political_office po
|
FROM falukant_data.political_office po
|
||||||
@@ -3574,6 +3579,15 @@ pub const QUERY_MARK_LOVER_MONTHLY_DONE: &str = r#"
|
|||||||
WHERE relationship_id = $1::int;
|
WHERE relationship_id = $1::int;
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
/// Daily: automatisches Beenden einer Liebschaft bei anhaltend niedriger Zuneigung.
|
||||||
|
pub const QUERY_DEACTIVATE_LOVER_RELATIONSHIP: &str = r#"
|
||||||
|
UPDATE falukant_data.relationship_state
|
||||||
|
SET active = false,
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE relationship_id = $1::int
|
||||||
|
AND active = true;
|
||||||
|
"#;
|
||||||
|
|
||||||
/// Liebschaft: fällige Teilzahlung (alle 2 h), Migration `006_falukant_lover_installments.sql`.
|
/// Liebschaft: fällige Teilzahlung (alle 2 h), Migration `006_falukant_lover_installments.sql`.
|
||||||
pub const QUERY_GET_ACTIVE_LOVER_ROWS_FOR_INSTALLMENT: &str = r#"
|
pub const QUERY_GET_ACTIVE_LOVER_ROWS_FOR_INSTALLMENT: &str = r#"
|
||||||
SELECT
|
SELECT
|
||||||
|
|||||||
Reference in New Issue
Block a user