From b8316787092341197ae6bd84bff119cc2ddea2e9 Mon Sep 17 00:00:00 2001 From: Rengan Date: Wed, 17 Dec 2025 20:51:41 +0300 Subject: [PATCH] =?UTF-8?q?Antagonist=20say=C4=B1s=C4=B1=20-=20storyteller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/database/events.rs | 50 +++++++++++++++++++++++++++++++++++++++++- src/database/round.rs | 10 +++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/database/events.rs b/src/database/events.rs index 6dd340e..37e4468 100644 --- a/src/database/events.rs +++ b/src/database/events.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use chrono::NaiveDateTime; use rocket::futures::StreamExt as _; @@ -572,6 +572,47 @@ pub async fn get_threat_overview( Ok(threats) } +pub async fn get_antagonist_overview( + limit: i32, + exclude_round: Option, + connection: &mut PoolConnection, +) -> Result, Error> { + let feedbacks = get_feedbacks( + "associative", + "antagonists", + limit, + exclude_round, + connection, + ) + .await?; + + let mut antagonists = HashMap::new(); + + for feedback in &feedbacks { + let round_id = match feedback.round_id { + Some(id) => id, + None => continue, + }; + + if let Some(data_map) = feedback.json.get("data").and_then(|d| d.as_object()) { + let mut total_count = 0; + let mut unique_types = HashSet::new(); + + for (_key, val) in data_map { + total_count += 1; + + if let Some(antag_type) = val.get("antagonist_type").and_then(|t| t.as_str()) { + unique_types.insert(antag_type.to_string()); + } + } + + antagonists.insert(round_id, (total_count, unique_types.len() as i32)); + } + } + + Ok(antagonists) +} + #[derive(Debug, Serialize)] pub struct Overview { pub round_id: u32, @@ -584,6 +625,8 @@ pub struct Overview { pub players: u32, pub dynamic_tier: i32, pub readied_players: i32, + pub antagonist_count: i32, + pub unique_antagonist_count: i32, } pub async fn get_overview( @@ -601,6 +644,7 @@ pub async fn get_overview( let crimes = get_crimes_overview(limit, exclude_round, &mut connection).await?; let players = get_players_overview(limit, exclude_round, &mut connection).await?; let threat_levels = get_threat_overview(limit, exclude_round, &mut connection).await?; + let antagonist = get_antagonist_overview(limit, exclude_round, &mut connection).await?; connection.close().await?; @@ -615,6 +659,8 @@ pub async fn get_overview( let crimes = *crimes.get(round_id).unwrap_or(&0); let players = *players.get(round_id).unwrap_or(&0); let (dynamic_tier, readied_players) = *threat_levels.get(round_id).unwrap_or(&(0, 0)); + let (antagonist_count, unique_antagonist_count) = + *antagonist.get(round_id).unwrap_or(&(0, 0)); let overview_ = Overview { round_id: *round_id, @@ -626,6 +672,8 @@ pub async fn get_overview( players, dynamic_tier, readied_players, + antagonist_count, + unique_antagonist_count, }; overview.push(overview_); diff --git a/src/database/round.rs b/src/database/round.rs index 054ac19..9270d9d 100644 --- a/src/database/round.rs +++ b/src/database/round.rs @@ -22,6 +22,7 @@ pub struct RoundData { pub nukedisk: Option, pub antagonists: Vec, pub dynamic_tier: Option, + pub storyteller: Option, #[serde(with = "crate::serde::datetime")] pub initialize_datetime: NaiveDateTime, #[serde(with = "crate::serde::opt_datetime")] @@ -58,6 +59,8 @@ pub async fn get_round( get_feedback("associative", "dynamic_tier", round_id, &mut connection).await?; let antagonists_feedback = get_feedback("associative", "antagonists", round_id, &mut connection).await?; + let storyteller_feedback = + get_feedback("associative", "storyteller", round_id, &mut connection).await?; let nukedisk: Option = nukedisk_feedback .and_then(|fb| fb.json.get("data").cloned()) @@ -67,6 +70,11 @@ pub async fn get_round( .and_then(|data| data.get("1").cloned()) .and_then(|data| data.get("tier").cloned()) .and_then(|v| v.as_str()?.parse::().ok()); + let storyteller: Option = storyteller_feedback + .and_then(|fb| fb.json.get("data").cloned()) + .and_then(|data| data.get("1").cloned()) + .and_then(|data| data.get("name").cloned()) + .and_then(|value| value.as_str().map(String::from)); let antagonists_objects: Option = antagonists_feedback.and_then(|fb| fb.json.get("data").cloned()); let antagonists: Vec = match antagonists_objects { @@ -106,6 +114,7 @@ pub async fn get_round( nukedisk, antagonists, dynamic_tier, + storyteller, }; connection.close().await?; @@ -236,6 +245,7 @@ pub async fn get_rounds( antagonists: Vec::new(), nukedisk: None, dynamic_tier: None, + storyteller: None, }; rounds.push(round);