record-daemon: don't propagate puuid, record it and compute at end
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m10s
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m10s
This commit is contained in:
@@ -191,10 +191,7 @@ impl LqpClient {
|
|||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Get local_puuid from state for champion extraction
|
if let Some(event) = parse_websocket_message(&text) {
|
||||||
let local_puuid = state.read().await.local_puuid.clone();
|
|
||||||
if let Some(event) = parse_websocket_message(&text, local_puuid.as_deref())
|
|
||||||
{
|
|
||||||
// Update state based on event
|
// Update state based on event
|
||||||
Self::update_state_from_event(&state, &event).await;
|
Self::update_state_from_event(&state, &event).await;
|
||||||
|
|
||||||
@@ -227,11 +224,7 @@ impl LqpClient {
|
|||||||
// Try to parse as UTF-8
|
// Try to parse as UTF-8
|
||||||
if let Ok(text) = String::from_utf8(data) {
|
if let Ok(text) = String::from_utf8(data) {
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
// Get local_puuid from state for champion extraction
|
if let Some(event) = parse_websocket_message(&text) {
|
||||||
let local_puuid = state.read().await.local_puuid.clone();
|
|
||||||
if let Some(event) =
|
|
||||||
parse_websocket_message(&text, local_puuid.as_deref())
|
|
||||||
{
|
|
||||||
// Update state based on event
|
// Update state based on event
|
||||||
Self::update_state_from_event(&state, &event).await;
|
Self::update_state_from_event(&state, &event).await;
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use super::events::{GameEvent, GameflowSession};
|
use super::events::{GameEvent, GameflowSession};
|
||||||
use super::mappings::{champion_id_to_name, map_id_to_name};
|
use super::mappings::map_id_to_name;
|
||||||
|
|
||||||
/// Parse a WebSocket message into a game event.
|
/// Parse a WebSocket message into a game event.
|
||||||
pub fn parse_websocket_message(text: &str, local_puuid: Option<&str>) -> Option<GameEvent> {
|
pub fn parse_websocket_message(text: &str) -> Option<GameEvent> {
|
||||||
// Parse the message array format: [type, callback, data]
|
// Parse the message array format: [type, callback, data]
|
||||||
let value: serde_json::Value = match serde_json::from_str(text) {
|
let value: serde_json::Value = match serde_json::from_str(text) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
@@ -42,7 +42,6 @@ pub fn parse_websocket_message(text: &str, local_puuid: Option<&str>) -> Option<
|
|||||||
&raw_event.uri,
|
&raw_event.uri,
|
||||||
event_type,
|
event_type,
|
||||||
&serde_json::to_value(raw_event.data).unwrap_or_default(),
|
&serde_json::to_value(raw_event.data).unwrap_or_default(),
|
||||||
local_puuid,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +53,7 @@ pub fn parse_websocket_message(text: &str, local_puuid: Option<&str>) -> Option<
|
|||||||
.and_then(|t| t.as_str())
|
.and_then(|t| t.as_str())
|
||||||
.unwrap_or("Update");
|
.unwrap_or("Update");
|
||||||
|
|
||||||
return parse_event_from_uri(uri, event_type, data, local_puuid);
|
return parse_event_from_uri(uri, event_type, data);
|
||||||
} else {
|
} else {
|
||||||
debug!("Unknown callback: {}", callback);
|
debug!("Unknown callback: {}", callback);
|
||||||
}
|
}
|
||||||
@@ -80,7 +79,6 @@ pub fn parse_event_from_uri(
|
|||||||
uri: &str,
|
uri: &str,
|
||||||
event_type: &str,
|
event_type: &str,
|
||||||
data: &serde_json::Value,
|
data: &serde_json::Value,
|
||||||
local_puuid: Option<&str>,
|
|
||||||
) -> Option<GameEvent> {
|
) -> Option<GameEvent> {
|
||||||
info!("Parsing event from URI: {} (type: {})", uri, event_type);
|
info!("Parsing event from URI: {} (type: {})", uri, event_type);
|
||||||
|
|
||||||
@@ -91,7 +89,7 @@ pub fn parse_event_from_uri(
|
|||||||
|
|
||||||
// Handle gameflow session updates
|
// Handle gameflow session updates
|
||||||
if uri == "/lol-gameflow/v1/session" {
|
if uri == "/lol-gameflow/v1/session" {
|
||||||
return parse_gameflow_session_event(data, local_puuid);
|
return parse_gameflow_session_event(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle game events (kills, deaths, objectives)
|
// Handle game events (kills, deaths, objectives)
|
||||||
@@ -158,16 +156,13 @@ fn parse_gameflow_phase_event(data: &serde_json::Value) -> Option<GameEvent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse gameflow session event.
|
/// Parse gameflow session event.
|
||||||
fn parse_gameflow_session_event(
|
fn parse_gameflow_session_event(data: &serde_json::Value) -> Option<GameEvent> {
|
||||||
data: &serde_json::Value,
|
|
||||||
local_puuid: Option<&str>,
|
|
||||||
) -> Option<GameEvent> {
|
|
||||||
if let Some(phase) = data.get("phase").and_then(|p| p.as_str()) {
|
if let Some(phase) = data.get("phase").and_then(|p| p.as_str()) {
|
||||||
info!("Gameflow session phase: {}", phase);
|
info!("Gameflow session phase: {}", phase);
|
||||||
|
|
||||||
// Check for game start
|
// Check for game start
|
||||||
if phase == "InProgress" {
|
if phase == "InProgress" {
|
||||||
return parse_game_start_event(data, local_puuid);
|
return parse_game_start_event(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(
|
return Some(
|
||||||
@@ -182,10 +177,10 @@ fn parse_gameflow_session_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse game start event from session data.
|
/// Parse game start event from session data.
|
||||||
fn parse_game_start_event(
|
///
|
||||||
data: &serde_json::Value,
|
/// The session data contains all player information. The reading software should
|
||||||
local_puuid: Option<&str>,
|
/// use the puuid from RecordingMetadata to find the local player's data in the session.
|
||||||
) -> Option<GameEvent> {
|
fn parse_game_start_event(data: &serde_json::Value) -> Option<GameEvent> {
|
||||||
info!("Game is now in progress!");
|
info!("Game is now in progress!");
|
||||||
|
|
||||||
// Try to parse the gameData into a GameflowSession struct
|
// Try to parse the gameData into a GameflowSession struct
|
||||||
@@ -256,28 +251,10 @@ fn parse_game_start_event(
|
|||||||
game_id, queue_type, queue_id, game_mode, map_name
|
game_id, queue_type, queue_id, game_mode, map_name
|
||||||
);
|
);
|
||||||
|
|
||||||
// Extract player-specific data using puuid
|
// Note: Player-specific data (champion, team, summoner_name) is NOT extracted here.
|
||||||
let (champion, team, summoner_name) = if let Some(puuid) = local_puuid {
|
// The full session is stored in the event, and the reading software should use
|
||||||
let champ_id = session.as_ref().and_then(|s| s.get_champion_id(puuid));
|
// the puuid from RecordingMetadata to find the local player's data in the session.
|
||||||
let team_id = session.as_ref().and_then(|s| s.get_team(puuid));
|
// This allows the same recording to be analyzed for any player by their puuid.
|
||||||
let summoner = session
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|s| s.get_summoner_name(puuid))
|
|
||||||
.map(|s| s.to_string());
|
|
||||||
|
|
||||||
// Convert champion_id to champion name
|
|
||||||
let champ_name = champ_id.and_then(champion_id_to_name);
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"Extracted player data via puuid: champion={:?}, team={:?}, summoner={:?}",
|
|
||||||
champ_name, team_id, summoner
|
|
||||||
);
|
|
||||||
|
|
||||||
(champ_name, team_id, summoner)
|
|
||||||
} else {
|
|
||||||
info!("No local_puuid available, cannot extract player-specific data");
|
|
||||||
(None, None, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
GameEvent::from_json(&serde_json::json!({
|
GameEvent::from_json(&serde_json::json!({
|
||||||
@@ -287,9 +264,6 @@ fn parse_game_start_event(
|
|||||||
"queueId": queue_id,
|
"queueId": queue_id,
|
||||||
"gameMode": game_mode,
|
"gameMode": game_mode,
|
||||||
"map": map_name,
|
"map": map_name,
|
||||||
"champion": champion,
|
|
||||||
"team": team,
|
|
||||||
"summonerName": summoner_name,
|
|
||||||
"session": session
|
"session": session
|
||||||
}))
|
}))
|
||||||
.unwrap_or(GameEvent::Unknown),
|
.unwrap_or(GameEvent::Unknown),
|
||||||
@@ -470,13 +444,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_websocket_message_invalid_json() {
|
fn test_parse_websocket_message_invalid_json() {
|
||||||
let result = parse_websocket_message("not json", None);
|
let result = parse_websocket_message("not json");
|
||||||
assert!(result.is_none());
|
assert!(result.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_websocket_message_empty_array() {
|
fn test_parse_websocket_message_empty_array() {
|
||||||
let result = parse_websocket_message("[]", None);
|
let result = parse_websocket_message("[]");
|
||||||
assert!(result.is_none());
|
assert!(result.is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,27 +233,6 @@ impl DaemonStateMachine {
|
|||||||
|
|
||||||
match event {
|
match event {
|
||||||
GameEvent::GameStart(info) => {
|
GameEvent::GameStart(info) => {
|
||||||
// Extract summoner spells from session data if available
|
|
||||||
let summoner_spells = info.session.as_ref().and_then(|session| {
|
|
||||||
session
|
|
||||||
.player_champion_selections
|
|
||||||
.first()
|
|
||||||
.map(|selection| SummonerSpells {
|
|
||||||
spell1_id: selection.spell1_id,
|
|
||||||
spell2_id: selection.spell2_id,
|
|
||||||
spell1_name: crate::lqp::spell_id_to_name(selection.spell1_id),
|
|
||||||
spell2_name: crate::lqp::spell_id_to_name(selection.spell2_id),
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
// Extract puuid from session data if available
|
|
||||||
let puuid = info.session.as_ref().and_then(|session| {
|
|
||||||
session
|
|
||||||
.player_champion_selections
|
|
||||||
.first()
|
|
||||||
.map(|selection| selection.puuid.clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
Some(StateTransition::GameStarted {
|
Some(StateTransition::GameStarted {
|
||||||
game_id: info.game_id,
|
game_id: info.game_id,
|
||||||
champion: info.champion.clone(),
|
champion: info.champion.clone(),
|
||||||
@@ -263,9 +242,9 @@ impl DaemonStateMachine {
|
|||||||
map_name: info.map_name.clone(),
|
map_name: info.map_name.clone(),
|
||||||
team: info.team,
|
team: info.team,
|
||||||
summoner_name: info.summoner_name.clone(),
|
summoner_name: info.summoner_name.clone(),
|
||||||
puuid,
|
puuid: None, // Will be populated from client.fetch_player_game_metadata()
|
||||||
runes: None, // Will be populated from client.fetch_player_game_metadata()
|
runes: None, // Will be populated from client.fetch_player_game_metadata()
|
||||||
summoner_spells,
|
summoner_spells: None, // Will be populated from client.fetch_player_game_metadata()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
GameEvent::GameEnd(info) => Some(StateTransition::GameEnded {
|
GameEvent::GameEnd(info) => Some(StateTransition::GameEnded {
|
||||||
|
|||||||
Reference in New Issue
Block a user