Enhance character event notifications in EventsWorker: Update character health change and death handling to include first and last names in notifications. Modify SQL queries to retrieve character names, ensuring accurate user feedback. Refactor notification structure for better organization and clarity.
This commit is contained in:
@@ -595,7 +595,7 @@ impl EventsWorker {
|
|||||||
max_change,
|
max_change,
|
||||||
} => {
|
} => {
|
||||||
if effect_roll < *probability
|
if effect_roll < *probability
|
||||||
&& let Ok((character_id, health_change, died)) = Self::apply_character_health_change(
|
&& let Ok((character_id, health_change, died, first_name, last_name)) = Self::apply_character_health_change(
|
||||||
&mut conn,
|
&mut conn,
|
||||||
pool,
|
pool,
|
||||||
broker,
|
broker,
|
||||||
@@ -608,23 +608,30 @@ impl EventsWorker {
|
|||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "character_health_change",
|
"type": "character_health_change",
|
||||||
"character_id": character_id,
|
"character_id": character_id,
|
||||||
"change": health_change
|
"change": health_change,
|
||||||
|
"character_first_name": first_name,
|
||||||
|
"character_last_name": last_name
|
||||||
}));
|
}));
|
||||||
if died {
|
if died {
|
||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "character_death",
|
"type": "character_death",
|
||||||
"character_id": character_id
|
"character_id": character_id,
|
||||||
|
"character_first_name": first_name,
|
||||||
|
"character_last_name": last_name
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventEffect::CharacterDeath { probability } => {
|
EventEffect::CharacterDeath { probability } => {
|
||||||
if effect_roll < *probability
|
if effect_roll < *probability
|
||||||
&& let Ok(character_id) = Self::apply_character_death(&mut conn, user_id, pool, broker)
|
&& let Ok((character_id, first_name, last_name)) =
|
||||||
|
Self::apply_character_death(&mut conn, user_id, pool, broker)
|
||||||
{
|
{
|
||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "character_death",
|
"type": "character_death",
|
||||||
"character_id": character_id
|
"character_id": character_id,
|
||||||
|
"character_first_name": first_name,
|
||||||
|
"character_last_name": last_name
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -675,18 +682,56 @@ impl EventsWorker {
|
|||||||
eff.get("character_id").and_then(|v| v.as_i64()).map(|n| n as i32)
|
eff.get("character_id").and_then(|v| v.as_i64()).map(|n| n as i32)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Optional: Namen-Snapshot aus Effekten extrahieren (auch wenn der Charakter danach stirbt/gelöscht wird)
|
||||||
|
let (top_first_name, top_last_name) = if let Some(cid) = top_character_id {
|
||||||
|
let eff = effect_results.iter().find(|e| {
|
||||||
|
e.get("character_id")
|
||||||
|
.and_then(|v| v.as_i64())
|
||||||
|
.map(|n| n as i32)
|
||||||
|
== Some(cid)
|
||||||
|
});
|
||||||
|
let fn_ = eff
|
||||||
|
.and_then(|e| e.get("character_first_name"))
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
let ln_ = eff
|
||||||
|
.and_then(|e| e.get("character_last_name"))
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
(fn_, ln_)
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frontend: `tr` ist der i18n-Key, Details liegen in `value` (Interpolation/Detailansicht)
|
||||||
let mut notification_json = serde_json::json!({
|
let mut notification_json = serde_json::json!({
|
||||||
"tr": format!("random_event.{}", event.id),
|
"tr": format!("random_event.{}", event.id),
|
||||||
|
"value": {
|
||||||
"event_id": event.id,
|
"event_id": event.id,
|
||||||
"event_type": "personal",
|
"event_type": "personal",
|
||||||
|
"title": event.title,
|
||||||
|
"description": event.description,
|
||||||
"effects": effect_results
|
"effects": effect_results
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(cid) = top_character_id {
|
if let Some(cid) = top_character_id {
|
||||||
notification_json["character_id"] = serde_json::json!(cid);
|
notification_json["value"]["character_id"] = serde_json::json!(cid);
|
||||||
|
}
|
||||||
|
if let Some(fn_) = top_first_name {
|
||||||
|
notification_json["value"]["character_first_name"] = serde_json::json!(fn_);
|
||||||
|
}
|
||||||
|
if let Some(ln_) = top_last_name {
|
||||||
|
notification_json["value"]["character_last_name"] = serde_json::json!(ln_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::notify_user(pool, broker, user_id, ¬ification_json.to_string())?;
|
Self::notify_user(
|
||||||
|
pool,
|
||||||
|
broker,
|
||||||
|
user_id,
|
||||||
|
¬ification_json.to_string(),
|
||||||
|
top_character_id,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Sende Benachrichtigung über WebSocket
|
// Sende Benachrichtigung über WebSocket
|
||||||
let mut notification = json!({
|
let mut notification = json!({
|
||||||
@@ -753,6 +798,9 @@ impl EventsWorker {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let first_name = rows.first().and_then(|r| r.get("first_name")).cloned();
|
||||||
|
let last_name = rows.first().and_then(|r| r.get("last_name")).cloned();
|
||||||
|
|
||||||
// Wende Effekte an (in diesem Fall nur CharacterDeath)
|
// Wende Effekte an (in diesem Fall nur CharacterDeath)
|
||||||
let mut effect_results = Vec::new();
|
let mut effect_results = Vec::new();
|
||||||
for effect in &event.effects {
|
for effect in &event.effects {
|
||||||
@@ -764,7 +812,9 @@ impl EventsWorker {
|
|||||||
{
|
{
|
||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "character_death",
|
"type": "character_death",
|
||||||
"character_id": character_id
|
"character_id": character_id,
|
||||||
|
"character_first_name": first_name,
|
||||||
|
"character_last_name": last_name
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -780,12 +830,25 @@ impl EventsWorker {
|
|||||||
// Schreibe Benachrichtigung in die Datenbank mit Event-Details
|
// Schreibe Benachrichtigung in die Datenbank mit Event-Details
|
||||||
let notification_json = serde_json::json!({
|
let notification_json = serde_json::json!({
|
||||||
"tr": format!("random_event.{}", event.id),
|
"tr": format!("random_event.{}", event.id),
|
||||||
|
"value": {
|
||||||
"event_id": event.id,
|
"event_id": event.id,
|
||||||
"event_type": "personal",
|
"event_type": "personal",
|
||||||
|
"title": event.title,
|
||||||
|
"description": event.description,
|
||||||
"character_id": character_id,
|
"character_id": character_id,
|
||||||
|
"character_first_name": first_name,
|
||||||
|
"character_last_name": last_name,
|
||||||
"effects": effect_results
|
"effects": effect_results
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Self::notify_user(pool, broker, user_id, ¬ification_json.to_string())?;
|
// Falls das Kind inzwischen gelöscht wurde, halten wir Name + ID im Payload fest.
|
||||||
|
Self::notify_user(
|
||||||
|
pool,
|
||||||
|
broker,
|
||||||
|
user_id,
|
||||||
|
¬ification_json.to_string(),
|
||||||
|
Some(character_id),
|
||||||
|
)?;
|
||||||
|
|
||||||
// Sende Benachrichtigung über WebSocket
|
// Sende Benachrichtigung über WebSocket
|
||||||
let notification = json!({
|
let notification = json!({
|
||||||
@@ -1041,12 +1104,18 @@ impl EventsWorker {
|
|||||||
// Schreibe Benachrichtigung in die Datenbank mit Event-Details
|
// Schreibe Benachrichtigung in die Datenbank mit Event-Details
|
||||||
let notification_json = serde_json::json!({
|
let notification_json = serde_json::json!({
|
||||||
"tr": format!("random_event.{}", event.id),
|
"tr": format!("random_event.{}", event.id),
|
||||||
|
"value": {
|
||||||
"event_id": event.id,
|
"event_id": event.id,
|
||||||
"event_type": "regional",
|
"event_type": "regional",
|
||||||
|
"title": event.title,
|
||||||
|
"description": event.description,
|
||||||
"region_id": region_id,
|
"region_id": region_id,
|
||||||
"effects": effect_results
|
"effects": effect_results
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if let Err(err) = Self::notify_user(pool, broker, uid, ¬ification_json.to_string()) {
|
if let Err(err) =
|
||||||
|
Self::notify_user(pool, broker, uid, ¬ification_json.to_string(), None)
|
||||||
|
{
|
||||||
eprintln!("[EventsWorker] Fehler beim Schreiben der Benachrichtigung für User {}: {}", uid, err);
|
eprintln!("[EventsWorker] Fehler beim Schreiben der Benachrichtigung für User {}: {}", uid, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1350,7 +1419,7 @@ impl EventsWorker {
|
|||||||
min_change: i32,
|
min_change: i32,
|
||||||
max_change: i32,
|
max_change: i32,
|
||||||
rng: &mut impl Rng,
|
rng: &mut impl Rng,
|
||||||
) -> Result<(i32, i32, bool), DbError> {
|
) -> Result<(i32, i32, bool, Option<String>, Option<String>), DbError> {
|
||||||
// Hole einen zufälligen Charakter des Spielers
|
// Hole einen zufälligen Charakter des Spielers
|
||||||
conn.prepare("get_random_character", QUERY_GET_RANDOM_CHARACTER)?;
|
conn.prepare("get_random_character", QUERY_GET_RANDOM_CHARACTER)?;
|
||||||
let rows = conn.execute("get_random_character", &[&user_id])?;
|
let rows = conn.execute("get_random_character", &[&user_id])?;
|
||||||
@@ -1374,6 +1443,10 @@ impl EventsWorker {
|
|||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
.unwrap_or(100);
|
.unwrap_or(100);
|
||||||
|
|
||||||
|
// Namen-Snapshot (wichtig, falls der Charakter durch das Event stirbt und gelöscht wird)
|
||||||
|
let first_name = rows.first().and_then(|r| r.get("first_name")).cloned();
|
||||||
|
let last_name = rows.first().and_then(|r| r.get("last_name")).cloned();
|
||||||
|
|
||||||
let health_change = rng.gen_range(min_change..=max_change);
|
let health_change = rng.gen_range(min_change..=max_change);
|
||||||
let new_health = (current_health + health_change).clamp(0, 100);
|
let new_health = (current_health + health_change).clamp(0, 100);
|
||||||
|
|
||||||
@@ -1389,7 +1462,7 @@ impl EventsWorker {
|
|||||||
let _ = Self::handle_character_death(pool, broker, character_id);
|
let _ = Self::handle_character_death(pool, broker, character_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((character_id, health_change, died))
|
Ok((character_id, health_change, died, first_name, last_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_character_death(
|
fn apply_character_death(
|
||||||
@@ -1397,7 +1470,7 @@ impl EventsWorker {
|
|||||||
user_id: i32,
|
user_id: i32,
|
||||||
pool: &ConnectionPool,
|
pool: &ConnectionPool,
|
||||||
broker: &MessageBroker,
|
broker: &MessageBroker,
|
||||||
) -> Result<i32, DbError> {
|
) -> Result<(i32, Option<String>, Option<String>), DbError> {
|
||||||
// Hole einen zufälligen Charakter des Spielers
|
// Hole einen zufälligen Charakter des Spielers
|
||||||
conn.prepare("get_random_character_death", QUERY_GET_RANDOM_CHARACTER)?;
|
conn.prepare("get_random_character_death", QUERY_GET_RANDOM_CHARACTER)?;
|
||||||
let rows = conn.execute("get_random_character_death", &[&user_id])?;
|
let rows = conn.execute("get_random_character_death", &[&user_id])?;
|
||||||
@@ -1415,11 +1488,14 @@ impl EventsWorker {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let first_name = rows.first().and_then(|r| r.get("first_name")).cloned();
|
||||||
|
let last_name = rows.first().and_then(|r| r.get("last_name")).cloned();
|
||||||
|
|
||||||
// Verwende die existierende Logik zum Löschen von Charakteren
|
// Verwende die existierende Logik zum Löschen von Charakteren
|
||||||
// (ähnlich wie in CharacterCreationWorker)
|
// (ähnlich wie in CharacterCreationWorker)
|
||||||
Self::handle_character_death(pool, broker, character_id)?;
|
Self::handle_character_death(pool, broker, character_id)?;
|
||||||
|
|
||||||
Ok(character_id)
|
Ok((character_id, first_name, last_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_regional_character_health_change(
|
fn apply_regional_character_health_change(
|
||||||
@@ -1535,7 +1611,7 @@ impl EventsWorker {
|
|||||||
.get("employer_user_id")
|
.get("employer_user_id")
|
||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
{
|
{
|
||||||
Self::notify_user(pool, broker, user_id, "director_death")?;
|
Self::notify_user(pool, broker, user_id, "director_death", None)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1547,7 +1623,7 @@ impl EventsWorker {
|
|||||||
.get("related_user_id")
|
.get("related_user_id")
|
||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
{
|
{
|
||||||
Self::notify_user(pool, broker, related_user_id, "relationship_death")?;
|
Self::notify_user(pool, broker, related_user_id, "relationship_death", None)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1575,13 +1651,13 @@ impl EventsWorker {
|
|||||||
.get("father_user_id")
|
.get("father_user_id")
|
||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
{
|
{
|
||||||
Self::notify_user(pool, broker, father_user_id, "child_death")?;
|
Self::notify_user(pool, broker, father_user_id, "child_death", None)?;
|
||||||
}
|
}
|
||||||
if let Some(mother_user_id) = row
|
if let Some(mother_user_id) = row
|
||||||
.get("mother_user_id")
|
.get("mother_user_id")
|
||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
{
|
{
|
||||||
Self::notify_user(pool, broker, mother_user_id, "child_death")?;
|
Self::notify_user(pool, broker, mother_user_id, "child_death", None)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1744,9 +1820,10 @@ impl EventsWorker {
|
|||||||
broker: &MessageBroker,
|
broker: &MessageBroker,
|
||||||
user_id: i32,
|
user_id: i32,
|
||||||
event_type: &str,
|
event_type: &str,
|
||||||
|
character_id: Option<i32>,
|
||||||
) -> Result<(), DbError> {
|
) -> Result<(), DbError> {
|
||||||
// DB-Notification (zentralisiert). Historisch wird hier als `tr` der event_type-String gespeichert.
|
// DB-Notification (zentralisiert). Historisch wird hier als `tr` der event_type-String gespeichert.
|
||||||
insert_notification(pool, user_id, event_type, None)?;
|
insert_notification(pool, user_id, event_type, character_id)?;
|
||||||
|
|
||||||
// Frontend-Update (zentralisiert)
|
// Frontend-Update (zentralisiert)
|
||||||
publish_update_status(broker, user_id);
|
publish_update_status(broker, user_id);
|
||||||
|
|||||||
@@ -14,7 +14,12 @@ SELECT id FROM falukant_data.falukant_user ORDER BY RANDOM() LIMIT 1;
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
pub const QUERY_GET_RANDOM_INFANT: &str = r#"
|
pub const QUERY_GET_RANDOM_INFANT: &str = r#"
|
||||||
SELECT c.id AS character_id, c.user_id, CURRENT_DATE - c.birthdate::date AS age_days
|
SELECT
|
||||||
|
c.id AS character_id,
|
||||||
|
c.user_id,
|
||||||
|
c.first_name,
|
||||||
|
c.last_name,
|
||||||
|
CURRENT_DATE - c.birthdate::date AS age_days
|
||||||
FROM falukant_data."character" c
|
FROM falukant_data."character" c
|
||||||
WHERE c.user_id IS NOT NULL AND c.health > 0 AND CURRENT_DATE - c.birthdate::date <= 730
|
WHERE c.user_id IS NOT NULL AND c.health > 0 AND CURRENT_DATE - c.birthdate::date <= 730
|
||||||
ORDER BY RANDOM() LIMIT 1;
|
ORDER BY RANDOM() LIMIT 1;
|
||||||
@@ -693,7 +698,7 @@ WHERE region_id = $1;
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
pub const QUERY_GET_RANDOM_CHARACTER: &str = r#"
|
pub const QUERY_GET_RANDOM_CHARACTER: &str = r#"
|
||||||
SELECT id, health
|
SELECT id, health, first_name, last_name
|
||||||
FROM falukant_data."character"
|
FROM falukant_data."character"
|
||||||
WHERE user_id = $1 AND health > 0
|
WHERE user_id = $1 AND health > 0
|
||||||
ORDER BY RANDOM() LIMIT 1;
|
ORDER BY RANDOM() LIMIT 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user