Enhance money change functionality in EventsWorker: Updated the MoneyChange event effect to include an optional minimum absolute positive value, ensuring that money changes do not result in zero for positive adjustments. Introduced a new SQL query for inserting money history, improving reliability in tracking monetary changes for users.

This commit is contained in:
Torsten Schulz (local)
2026-02-06 07:40:25 +01:00
parent 4baf88b0cf
commit 69dad6854a
2 changed files with 35 additions and 16 deletions

View File

@@ -16,6 +16,7 @@ use crate::worker::sql::{
QUERY_INSERT_NOTIFICATION,
QUERY_GET_MONEY,
QUERY_UPDATE_MONEY,
QUERY_INSERT_MONEY_HISTORY,
QUERY_GET_REGION_STOCKS,
QUERY_GET_USER_STOCKS,
QUERY_UPDATE_STOCK_CAPACITY,
@@ -67,8 +68,14 @@ pub enum EventType {
/// Mögliche Effekte, die ein Ereignis haben kann
#[derive(Debug, Clone)]
pub enum EventEffect {
/// Änderung des Geldes eines Spielers (in Prozent)
MoneyChange { probability: f64, min_percent: f64, max_percent: f64 },
/// Änderung des Geldes eines Spielers (in Prozent).
/// Bei positiver Änderung kann min_absolute_positive einen Mindestbetrag erzwingen (z. B. damit ein „Fund“ nie 0 ist).
MoneyChange {
probability: f64,
min_percent: f64,
max_percent: f64,
min_absolute_positive: Option<f64>,
},
/// Änderung der Produktionsqualität in einer Region (in Prozentpunkten)
ProductionQualityChange { probability: f64, min_change: i32, max_change: i32 },
/// Änderung der Verkaufspreise in einer Region (in Prozent)
@@ -169,6 +176,7 @@ impl EventsWorker {
probability: 1.0,
min_percent: 5.0,
max_percent: 15.0,
min_absolute_positive: Some(1.0), // Fund ist nie 0
},
],
},
@@ -183,6 +191,7 @@ impl EventsWorker {
probability: 1.0,
min_percent: -10.0,
max_percent: -5.0,
min_absolute_positive: None,
},
],
},
@@ -511,13 +520,23 @@ impl EventsWorker {
probability,
min_percent,
max_percent,
min_absolute_positive,
} => {
if effect_roll < *probability {
let percent_change = rng.gen_range(*min_percent..=*max_percent);
let current_money = Self::get_current_money(&mut conn, user_id).unwrap_or(0.0);
let computed_change = current_money * (percent_change / 100.0);
let absolute_change = Self::apply_money_change(&mut conn, user_id, percent_change)
.unwrap_or(computed_change);
let effective_change = match min_absolute_positive {
Some(min_abs) if percent_change > 0.0 && computed_change < *min_abs => *min_abs,
_ => computed_change,
};
let absolute_change = Self::apply_money_change(
&mut conn,
user_id,
percent_change,
Some(effective_change),
)
.unwrap_or(effective_change);
effect_results.push(json!({
"type": "money_change",
"percent": percent_change,
@@ -1030,19 +1049,18 @@ impl EventsWorker {
conn: &mut DbConnection,
user_id: i32,
percent_change: f64,
absolute_override: Option<f64>,
) -> Result<f64, DbError> {
let current_money = Self::get_current_money(conn, user_id)?;
let change = current_money * (percent_change / 100.0);
let change = absolute_override
.unwrap_or_else(|| current_money * (percent_change / 100.0));
let action = format!("Zufallsereignis: Geldänderung {:.2}%", percent_change);
// Verwende parametrisierte Queries für Sicherheit gegen SQL-Injection
conn.prepare("update_money_event", QUERY_UPDATE_MONEY)?;
let _ = conn.execute("update_money_event", &[&user_id, &change, &action])?;
// Best-effort money_history insert for UI/history visibility.
let money_str = format!("{:.2}", change);
fn escape_sql_literal(s: &str) -> String { s.replace('\'', "''") }
let escaped_action = escape_sql_literal(&action);
// money_history für UI/Verlauf: Betrag und Aktion zuverlässig speichern (parametrisiert).
let create_sql = r#"
CREATE TABLE IF NOT EXISTS falukant_log.money_history (
id BIGSERIAL PRIMARY KEY,
@@ -1054,13 +1072,9 @@ impl EventsWorker {
"#;
let _ = conn.query(create_sql);
let history_sql = format!(
"INSERT INTO falukant_log.money_history (user_id, change, action, created_at) VALUES ({uid}, {money}::numeric, '{act}', NOW());",
uid = user_id,
money = money_str,
act = escaped_action
);
if let Err(err) = conn.query(&history_sql) {
let money_str = format!("{:.2}", change);
let _ = conn.prepare("insert_money_history", QUERY_INSERT_MONEY_HISTORY);
if let Err(err) = conn.execute("insert_money_history", &[&user_id, &money_str, &action]) {
eprintln!(
"[EventsWorker] Warning: inserting money_history failed for user {}: {}",
user_id, err