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