Implement inheritance logic for player characters in EventsWorker: Added functionality to handle character inheritance before deleting child relations. This includes querying for the user ID, determining the heir, and updating the heir's assets accordingly. Enhanced logging for inheritance events to improve traceability.

This commit is contained in:
Torsten Schulz (local)
2025-12-08 13:22:20 +01:00
parent d078b6b19a
commit 9b6883ea84

View File

@@ -1482,7 +1482,29 @@ impl EventsWorker {
} }
} }
// 3) Child-Relations löschen und Eltern benachrichtigen // 3) Erben-Logik für Spieler-Charaktere (VOR dem Löschen der Child-Relations!)
// Prüfe, ob der Charakter ein Spieler-Charakter ist
const QUERY_GET_USER_ID: &str = r#"
SELECT user_id
FROM falukant_data.character
WHERE id = $1;
"#;
conn.prepare("get_user_id", QUERY_GET_USER_ID)?;
let user_rows = conn.execute("get_user_id", &[&character_id])?;
let user_id: Option<i32> = user_rows
.get(0)
.and_then(|r| r.get("user_id"))
.and_then(|v| v.parse::<i32>().ok());
if let Some(falukant_user_id) = user_id {
// Spieler-Charakter: Erben-Logik ausführen
// WICHTIG: Dies muss VOR dem Löschen der Child-Relations passieren!
Self::handle_inheritance(pool, broker, &mut conn, character_id, falukant_user_id)?;
}
// 4) Child-Relations löschen und Eltern benachrichtigen
const QUERY_DELETE_CHILD_RELATION: &str = r#" const QUERY_DELETE_CHILD_RELATION: &str = r#"
WITH deleted AS ( WITH deleted AS (
DELETE FROM falukant_data.child_relation DELETE FROM falukant_data.child_relation
@@ -1518,7 +1540,7 @@ impl EventsWorker {
} }
} }
// 4) Charakter löschen // 5) Charakter löschen
const QUERY_DELETE_CHARACTER: &str = r#" const QUERY_DELETE_CHARACTER: &str = r#"
DELETE FROM falukant_data.character DELETE FROM falukant_data.character
WHERE id = $1; WHERE id = $1;
@@ -1530,6 +1552,184 @@ impl EventsWorker {
Ok(()) Ok(())
} }
fn handle_inheritance(
pool: &ConnectionPool,
broker: &MessageBroker,
conn: &mut DbConnection,
deceased_character_id: i32,
falukant_user_id: i32,
) -> Result<(), DbError> {
// 1) Finde den Erben (bevorzugt is_heir = TRUE)
const QUERY_GET_HEIR: &str = r#"
SELECT child_character_id
FROM falukant_data.child_relation
WHERE father_character_id = $1
OR mother_character_id = $1
ORDER BY (is_heir IS TRUE) DESC,
updated_at DESC
LIMIT 1;
"#;
conn.prepare("get_heir", QUERY_GET_HEIR)?;
let heir_rows = conn.execute("get_heir", &[&deceased_character_id])?;
let heir_id: Option<i32> = heir_rows
.get(0)
.and_then(|r| r.get("child_character_id"))
.and_then(|v| v.parse::<i32>().ok());
let heir_id = match heir_id {
Some(id) if id > 0 => id,
_ => {
// Kein Erbe gefunden - Vermögen geht verloren
eprintln!(
"[EventsWorker] Kein Erbe für Charakter {} gefunden, Vermögen geht verloren",
deceased_character_id
);
return Ok(());
}
};
// 2) Setze den Erben als neuen Spieler-Charakter
const QUERY_SET_CHARACTER_USER: &str = r#"
UPDATE falukant_data.character
SET user_id = $1,
updated_at = NOW()
WHERE id = $2;
"#;
conn.prepare("set_character_user", QUERY_SET_CHARACTER_USER)?;
conn.execute("set_character_user", &[&falukant_user_id, &heir_id])?;
// 3) Berechne das neue Vermögen basierend auf dem gesamten Vermögen
// Hole alle Vermögenswerte (analog zu UserCharacterWorker::calculate_new_money)
const QUERY_GET_CURRENT_MONEY: &str = r#"
SELECT money
FROM falukant_data.falukant_user
WHERE id = $1;
"#;
const QUERY_GET_HOUSE_VALUE: &str = r#"
SELECT COALESCE(SUM(h.cost), 0) AS sum
FROM falukant_data.user_house AS uh
JOIN falukant_type.house AS h ON uh.house_type_id = h.id
WHERE uh.user_id = $1;
"#;
const QUERY_GET_SETTLEMENT_VALUE: &str = r#"
SELECT COALESCE(SUM(b.base_cost), 0) AS sum
FROM falukant_data.branch AS br
JOIN falukant_type.branch AS b ON br.branch_type_id = b.id
WHERE br.falukant_user_id = $1;
"#;
const QUERY_GET_INVENTORY_VALUE: &str = r#"
SELECT COALESCE(SUM(i.quantity * p.sell_cost), 0) AS sum
FROM falukant_data.inventory AS i
JOIN falukant_type.product AS p ON i.product_id = p.id
JOIN falukant_data.stock AS s ON i.stock_id = s.id
JOIN falukant_data.branch AS br ON s.branch_id = br.id
WHERE br.falukant_user_id = $1;
"#;
const QUERY_GET_CREDIT_DEBT: &str = r#"
SELECT COALESCE(SUM(remaining_amount), 0) AS sum
FROM falukant_data.credit
WHERE falukant_user_id = $1;
"#;
const QUERY_COUNT_CHILDREN: &str = r#"
SELECT COUNT(*) AS cnt
FROM falukant_data.child_relation
WHERE (father_character_id = $1 OR mother_character_id = $1)
AND child_character_id != $2;
"#;
conn.prepare("get_current_money", QUERY_GET_CURRENT_MONEY)?;
conn.prepare("get_house_value", QUERY_GET_HOUSE_VALUE)?;
conn.prepare("get_settlement_value", QUERY_GET_SETTLEMENT_VALUE)?;
conn.prepare("get_inventory_value", QUERY_GET_INVENTORY_VALUE)?;
conn.prepare("get_credit_debt", QUERY_GET_CREDIT_DEBT)?;
conn.prepare("count_children", QUERY_COUNT_CHILDREN)?;
let cash: f64 = conn
.execute("get_current_money", &[&falukant_user_id])?
.get(0)
.and_then(|r| r.get("money"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0);
let houses: f64 = conn
.execute("get_house_value", &[&falukant_user_id])?
.get(0)
.and_then(|r| r.get("sum"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0);
let settlements: f64 = conn
.execute("get_settlement_value", &[&falukant_user_id])?
.get(0)
.and_then(|r| r.get("sum"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0);
let inventory: f64 = conn
.execute("get_inventory_value", &[&falukant_user_id])?
.get(0)
.and_then(|r| r.get("sum"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0);
let debt: f64 = conn
.execute("get_credit_debt", &[&falukant_user_id])?
.get(0)
.and_then(|r| r.get("sum"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0);
let child_count: i32 = conn
.execute("count_children", &[&deceased_character_id, &heir_id])?
.get(0)
.and_then(|r| r.get("cnt"))
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(0);
// Berechne das neue Vermögen (analog zu UserCharacterWorker::calculate_new_money)
let total_assets = cash + houses + settlements + inventory - debt;
let single = child_count <= 0; // Nur der Erbe bleibt
let heir_share = if single {
total_assets
} else {
total_assets * 0.8
};
let new_money = heir_share - (houses + settlements + inventory + debt);
let final_money = if new_money <= 1000.0 {
1000.0
} else {
new_money
};
// 4) Aktualisiere das Vermögen über die update_money Funktion
// Verwende die BaseWorker-Funktion für konsistente Geld-Updates
use crate::worker::base::BaseWorker;
let base = BaseWorker::new("EventsWorker", pool.clone(), broker.clone());
let money_change = final_money - cash;
base.change_falukant_user_money(
falukant_user_id,
money_change,
&format!("Erbe für Charakter {}", deceased_character_id),
)?;
eprintln!(
"[EventsWorker] Erbe {} übernimmt Vermögen von Charakter {} (User {}): {:.2} (von {:.2} Gesamtvermögen, {} weitere Kinder)",
heir_id, deceased_character_id, falukant_user_id, final_money, total_assets, child_count
);
Ok(())
}
fn notify_user( fn notify_user(
pool: &ConnectionPool, pool: &ConnectionPool,
broker: &MessageBroker, broker: &MessageBroker,