record-daemon: refactor client.rs, dropping metadata
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m17s
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m17s
This commit is contained in:
@@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
|
||||
// =============================================================================
|
||||
|
||||
/// Response from `/lol-summoner/v1/current-summoner`
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SummonerResponse {
|
||||
/// Summoner ID.
|
||||
@@ -51,7 +51,7 @@ pub struct SummonerResponse {
|
||||
// =============================================================================
|
||||
|
||||
/// Response from `/lol-gameflow/v1/session`
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameflowSessionResponse {
|
||||
/// Current gameflow phase.
|
||||
@@ -552,6 +552,80 @@ impl ChampionSelectResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Aggregated Data Containers
|
||||
// =============================================================================
|
||||
|
||||
/// Container for pre-game data collected from multiple API calls.
|
||||
/// Stores raw API responses directly for maximum flexibility.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct PreGameData {
|
||||
/// Session data (map, game mode, queue info).
|
||||
pub session: Option<GameflowSessionResponse>,
|
||||
/// Summoner data (puuid, name).
|
||||
pub summoner: Option<SummonerResponse>,
|
||||
/// Champion select data (champion, skin, team).
|
||||
pub champion_select: Option<ChampionSelectResponse>,
|
||||
/// Rune page data.
|
||||
pub rune_page: Option<RunePageResponse>,
|
||||
}
|
||||
|
||||
impl PreGameData {
|
||||
/// Get the summoner name from any available source.
|
||||
pub fn summoner_name(&self) -> Option<&str> {
|
||||
self.summoner
|
||||
.as_ref()
|
||||
.and_then(|s| s.display_name.as_deref())
|
||||
.or_else(|| self.summoner.as_ref().and_then(|s| s.name.as_deref()))
|
||||
}
|
||||
|
||||
/// Get the PUUID.
|
||||
pub fn puuid(&self) -> Option<&str> {
|
||||
self.summoner.as_ref()?.puuid.as_deref()
|
||||
}
|
||||
|
||||
/// Get the champion ID from champion select.
|
||||
pub fn champion_id(&self) -> Option<u64> {
|
||||
let cs = self.champion_select.as_ref()?;
|
||||
let player = cs.get_local_player_selection()?;
|
||||
player.champion_id
|
||||
}
|
||||
|
||||
/// Get the team ID from champion select.
|
||||
pub fn team(&self) -> Option<i64> {
|
||||
let cs = self.champion_select.as_ref()?;
|
||||
let player = cs.get_local_player_selection()?;
|
||||
player.team
|
||||
}
|
||||
|
||||
/// Get the skin ID from champion select.
|
||||
pub fn skin_id(&self) -> Option<u64> {
|
||||
let cs = self.champion_select.as_ref()?;
|
||||
let player = cs.get_local_player_selection()?;
|
||||
player.skin_id
|
||||
}
|
||||
|
||||
/// Get the map name from session.
|
||||
pub fn map_name(&self) -> Option<&str> {
|
||||
self.session.as_ref()?.map.as_deref()
|
||||
}
|
||||
|
||||
/// Get the game mode from session.
|
||||
pub fn game_mode(&self) -> Option<&str> {
|
||||
self.session.as_ref()?.game_mode.as_deref()
|
||||
}
|
||||
|
||||
/// Get the queue ID from session.
|
||||
pub fn queue_id(&self) -> Option<u64> {
|
||||
self.session.as_ref()?.queue_id
|
||||
}
|
||||
|
||||
/// Get the rune page name.
|
||||
pub fn rune_page_name(&self) -> Option<&str> {
|
||||
self.rune_page.as_ref()?.name.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -12,14 +12,13 @@ use tracing::{debug, error, info, trace, warn};
|
||||
|
||||
use super::api_types::{
|
||||
ActivePlayerResponse, ChampionSelectResponse, EndOfGameStatsResponse, GameflowSessionResponse,
|
||||
PlayerListResponse, RunePageResponse, SummonerResponse,
|
||||
PlayerListResponse, PreGameData, RunePageResponse, SummonerResponse,
|
||||
};
|
||||
use super::auth::LockfileCredentials;
|
||||
use super::endpoints;
|
||||
use super::events::{GameEvent, ItemBuild};
|
||||
use super::items::{parse_items_from_game_stats, parse_items_from_live_client};
|
||||
use super::mappings::{champion_id_to_name, spell_id_to_name};
|
||||
use super::metadata::{GameEndMetadata, PreGameMetadata};
|
||||
use super::state::{ClientState, GameflowPhase};
|
||||
use super::tls::create_insecure_tls_config;
|
||||
use super::websocket::parse_websocket_message;
|
||||
@@ -478,69 +477,47 @@ impl LqpClient {
|
||||
// Metadata Fetching Methods
|
||||
// =========================================================================
|
||||
|
||||
/// Fetch pre-game metadata (champion, skin, runes, queue info).
|
||||
pub async fn fetch_pregame_metadata(&self) -> Result<PreGameMetadata> {
|
||||
let mut metadata = PreGameMetadata::default();
|
||||
/// Fetch pre-game data (stores raw API responses directly).
|
||||
pub async fn fetch_pregame_data(&self) -> Result<PreGameData> {
|
||||
let mut data = PreGameData::default();
|
||||
|
||||
// Get session info for queue type and game mode
|
||||
if let Ok(session) = self.get_session_typed().await {
|
||||
metadata.map_name = session.map;
|
||||
metadata.game_mode = session.game_mode;
|
||||
metadata.queue_id = session.queue_id.map(|id| id as u32);
|
||||
// Fetch all API responses in parallel where possible
|
||||
let (session, summoner, champ_select, rune_page) = tokio::join!(
|
||||
self.get_session_typed(),
|
||||
self.get_summoner_typed(),
|
||||
self.get_champion_select_typed(),
|
||||
self.get_rune_page_typed()
|
||||
);
|
||||
|
||||
// Store session data
|
||||
if let Ok(session) = session {
|
||||
data.session = Some(session);
|
||||
}
|
||||
|
||||
// Get summoner info (including puuid)
|
||||
if let Ok(summoner) = self.get_summoner_typed().await {
|
||||
metadata.summoner_name = summoner.display_name;
|
||||
if let Some(puuid) = &summoner.puuid {
|
||||
// Store summoner data and update state
|
||||
if let Ok(summoner) = summoner {
|
||||
if let Some(ref puuid) = summoner.puuid {
|
||||
self.state.write().await.local_puuid = Some(puuid.clone());
|
||||
}
|
||||
metadata.local_puuid = summoner.puuid;
|
||||
data.summoner = Some(summoner);
|
||||
}
|
||||
|
||||
// Get champion select info
|
||||
if let Ok(champ_select) = self.get_champion_select_typed().await {
|
||||
if let Some(player) = champ_select.get_local_player_selection() {
|
||||
metadata.champion_id = player.champion_id.map(|id| id as u32);
|
||||
metadata.team = player.team.map(|id| id as u32);
|
||||
metadata.skin_id = player.skin_id.map(|id| id as u32);
|
||||
}
|
||||
// Store champion select data
|
||||
if let Ok(champ_select) = champ_select {
|
||||
data.champion_select = Some(champ_select);
|
||||
}
|
||||
|
||||
// Get rune page
|
||||
if let Ok(rune_page) = self.get_rune_page_typed().await {
|
||||
metadata.rune_page_name = rune_page.name;
|
||||
// Store rune page data
|
||||
if let Ok(rune_page) = rune_page {
|
||||
data.rune_page = Some(rune_page);
|
||||
}
|
||||
|
||||
Ok(metadata)
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
/// Fetch end-of-game stats.
|
||||
pub async fn fetch_game_end_stats(&self) -> Result<GameEndMetadata> {
|
||||
let mut metadata = GameEndMetadata::default();
|
||||
|
||||
if let Ok(stats) = self.get_game_stats_typed().await {
|
||||
metadata.victory = Some(stats.is_victory());
|
||||
metadata.game_duration = stats.game_length.unwrap_or(0.0);
|
||||
metadata.match_id = stats.match_id.map(|id| id.to_string());
|
||||
|
||||
// Extract player stats
|
||||
if let Some(player) = stats.get_local_player() {
|
||||
if let Some(player_stats) = &player.stats {
|
||||
metadata.kills = player_stats.champions_killed.unwrap_or(0) as u32;
|
||||
metadata.deaths = player_stats.num_deaths.unwrap_or(0) as u32;
|
||||
metadata.assists = player_stats.assists.unwrap_or(0) as u32;
|
||||
metadata.creep_score = player_stats.minions_killed.unwrap_or(0) as u32;
|
||||
metadata.gold_earned = player_stats.gold_earned.unwrap_or(0) as u32;
|
||||
metadata.damage_dealt =
|
||||
player_stats.total_damage_dealt_to_champions.unwrap_or(0);
|
||||
metadata.damage_taken = player_stats.total_damage_taken.unwrap_or(0);
|
||||
metadata.vision_score = player_stats.vision_score.unwrap_or(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(metadata)
|
||||
/// Fetch end-of-game stats (returns raw API response).
|
||||
pub async fn fetch_game_end_stats(&self) -> Result<EndOfGameStatsResponse> {
|
||||
self.get_game_stats_typed().await
|
||||
}
|
||||
|
||||
/// Fetch complete player game metadata including runes, summoner spells, and items.
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
//! Metadata structures for pre-game and end-of-game data.
|
||||
//!
|
||||
//! Contains structures for capturing game information before and after matches.
|
||||
|
||||
/// Pre-game metadata fetched before the game starts.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct PreGameMetadata {
|
||||
/// Champion ID selected.
|
||||
pub champion_id: Option<u32>,
|
||||
/// Skin ID selected.
|
||||
pub skin_id: Option<u32>,
|
||||
/// Name of the rune page.
|
||||
pub rune_page_name: Option<String>,
|
||||
/// Summoner name.
|
||||
pub summoner_name: Option<String>,
|
||||
/// Queue type (e.g., "RANKED_SOLO_5x5").
|
||||
pub queue_type: Option<String>,
|
||||
/// Queue ID.
|
||||
pub queue_id: Option<u32>,
|
||||
/// Game mode (e.g., "CLASSIC", "ARAM").
|
||||
pub game_mode: Option<String>,
|
||||
/// Map name.
|
||||
pub map_name: Option<String>,
|
||||
/// Team ID (100 or 200).
|
||||
pub team: Option<u32>,
|
||||
/// Local player's PUUID.
|
||||
pub local_puuid: Option<String>,
|
||||
}
|
||||
|
||||
/// End-of-game metadata fetched after the game ends.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct GameEndMetadata {
|
||||
/// Whether the player won.
|
||||
pub victory: Option<bool>,
|
||||
/// Match ID.
|
||||
pub match_id: Option<String>,
|
||||
/// Number of kills.
|
||||
pub kills: u32,
|
||||
/// Number of deaths.
|
||||
pub deaths: u32,
|
||||
/// Number of assists.
|
||||
pub assists: u32,
|
||||
/// Creep score (minions killed).
|
||||
pub creep_score: u32,
|
||||
/// Gold earned.
|
||||
pub gold_earned: u32,
|
||||
/// Damage dealt to champions.
|
||||
pub damage_dealt: u64,
|
||||
/// Damage taken.
|
||||
pub damage_taken: u64,
|
||||
/// Vision score.
|
||||
pub vision_score: f64,
|
||||
/// Game duration in seconds.
|
||||
pub game_duration: f64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_pre_game_metadata_default() {
|
||||
let metadata = PreGameMetadata::default();
|
||||
assert!(metadata.champion_id.is_none());
|
||||
assert!(metadata.skin_id.is_none());
|
||||
assert!(metadata.summoner_name.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_game_end_metadata_default() {
|
||||
let metadata = GameEndMetadata::default();
|
||||
assert!(metadata.victory.is_none());
|
||||
assert_eq!(metadata.kills, 0);
|
||||
assert_eq!(metadata.deaths, 0);
|
||||
assert_eq!(metadata.assists, 0);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ mod endpoints;
|
||||
mod events;
|
||||
mod items;
|
||||
mod mappings;
|
||||
mod metadata;
|
||||
mod state;
|
||||
mod tls;
|
||||
mod websocket;
|
||||
@@ -18,7 +17,7 @@ mod websocket;
|
||||
pub use api_types::{
|
||||
ActivePlayerResponse, ChampionSelectPlayer, ChampionSelectResponse, EndOfGamePlayer,
|
||||
EndOfGameStatsResponse, EndOfGameTeam, GameData, GameflowSessionResponse, LiveClientItem,
|
||||
LiveClientPlayer, PlayerListResponse, PlayerStats, QueueData, RunePageResponse,
|
||||
LiveClientPlayer, PlayerListResponse, PlayerStats, PreGameData, QueueData, RunePageResponse,
|
||||
SummonerResponse, SummonerSpellsData, TeamPlayer, Timers,
|
||||
};
|
||||
pub use auth::{LockfileCredentials, LockfileWatcher};
|
||||
@@ -37,6 +36,5 @@ pub use events::{
|
||||
};
|
||||
pub use items::{parse_items_from_game_stats, parse_items_from_live_client};
|
||||
pub use mappings::{champion_id_to_name, map_id_to_name, spell_id_to_name};
|
||||
pub use metadata::{GameEndMetadata, PreGameMetadata};
|
||||
pub use state::{ClientState, GameflowPhase};
|
||||
pub use websocket::{parse_event_from_uri, parse_websocket_message};
|
||||
|
||||
Reference in New Issue
Block a user