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]
|
||||
name = "YpDaemon"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
version = "0.5.0"
|
||||
edition = "2026"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8"
|
||||
|
||||
@@ -18,6 +18,7 @@ use rand::SeedableRng;
|
||||
|
||||
use super::base::{BaseWorker, Worker, WorkerState};
|
||||
use super::sql::{
|
||||
QUERY_DEACTIVATE_LOVER_RELATIONSHIP,
|
||||
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_INSTALLMENT, QUERY_GET_LOVER_PREGNANCY_CANDIDATES,
|
||||
@@ -32,6 +33,7 @@ use super::sql::{
|
||||
};
|
||||
use crate::db::{ConnectionPool, DbError};
|
||||
use crate::message_broker::MessageBroker;
|
||||
use serde_json::json;
|
||||
|
||||
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.
|
||||
@@ -258,6 +260,10 @@ impl FalukantFamilyWorker {
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
@@ -304,7 +310,42 @@ impl FalukantFamilyWorker {
|
||||
)?;
|
||||
l.visibility = new_vis;
|
||||
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_monthly", QUERY_MARK_LOVER_MONTHLY_DONE)?;
|
||||
@@ -673,6 +714,7 @@ impl FalukantFamilyWorker {
|
||||
}
|
||||
notify.extend(marriage_socket_users);
|
||||
notify.extend(tension_socket_users);
|
||||
notify.extend(breakup_socket_users);
|
||||
self.publish_falukant_update_family_batch(¬ify, "daily");
|
||||
|
||||
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).
|
||||
fn scandal_age_extra_pct(min_age_years: i32) -> f64 {
|
||||
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
|
||||
//
|
||||
// `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#"
|
||||
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
|
||||
@@ -3574,6 +3579,15 @@ pub const QUERY_MARK_LOVER_MONTHLY_DONE: &str = r#"
|
||||
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`.
|
||||
pub const QUERY_GET_ACTIVE_LOVER_ROWS_FOR_INSTALLMENT: &str = r#"
|
||||
SELECT
|
||||
|
||||
Reference in New Issue
Block a user