Switch Heatmaps to be for each side respectively
The analysis and storage now contain two different heatmaps for the CT and T sides respectively. However on the frontend I currently just have them all listed out with the side as a prefix, which is not very useful and we should more change the data structure to essentially send the two heatmaps for a player as a single data structure and then in the view display them side by side. However I am not 100% how to best achieve this
This commit is contained in:
@@ -52,7 +52,7 @@ impl HeatMap {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HeatMapOutput {
|
pub struct HeatMapOutput {
|
||||||
pub player_heatmaps: std::collections::HashMap<csdemo::UserId, HeatMap>,
|
pub player_heatmaps: std::collections::HashMap<(csdemo::UserId, String), HeatMap>,
|
||||||
pub player_info: std::collections::HashMap<csdemo::UserId, csdemo::parser::Player>,
|
pub player_info: std::collections::HashMap<csdemo::UserId, csdemo::parser::Player>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +96,7 @@ pub fn parse(config: &Config, buf: &[u8]) -> Result<HeatMapOutput, ()> {
|
|||||||
Some(csdemo::RawValue::I32(v)) => {
|
Some(csdemo::RawValue::I32(v)) => {
|
||||||
Some((PawnID::from(*v), pspawn.userid.unwrap()))
|
Some((PawnID::from(*v), pspawn.userid.unwrap()))
|
||||||
}
|
}
|
||||||
other => {
|
_ => {
|
||||||
// tracing::info!("Unknown Pawn-ID: {:?}", other);
|
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -116,6 +115,7 @@ pub fn parse(config: &Config, buf: &[u8]) -> Result<HeatMapOutput, ()> {
|
|||||||
tmp
|
tmp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut teams = std::collections::HashMap::new();
|
||||||
let mut player_lifestate = std::collections::HashMap::<csdemo::UserId, u32>::new();
|
let mut player_lifestate = std::collections::HashMap::<csdemo::UserId, u32>::new();
|
||||||
let mut player_position = std::collections::HashMap::<csdemo::UserId, (f32, f32, f32)>::new();
|
let mut player_position = std::collections::HashMap::<csdemo::UserId, (f32, f32, f32)>::new();
|
||||||
let mut player_cells = std::collections::HashMap::new();
|
let mut player_cells = std::collections::HashMap::new();
|
||||||
@@ -128,6 +128,7 @@ pub fn parse(config: &Config, buf: &[u8]) -> Result<HeatMapOutput, ()> {
|
|||||||
config,
|
config,
|
||||||
tick_state,
|
tick_state,
|
||||||
&pawn_ids,
|
&pawn_ids,
|
||||||
|
&mut teams,
|
||||||
&mut player_lifestate,
|
&mut player_lifestate,
|
||||||
&mut player_position,
|
&mut player_position,
|
||||||
&mut player_cells,
|
&mut player_cells,
|
||||||
@@ -149,22 +150,41 @@ fn process_tick(
|
|||||||
config: &Config,
|
config: &Config,
|
||||||
tick_state: &csdemo::parser::EntityTickStates,
|
tick_state: &csdemo::parser::EntityTickStates,
|
||||||
pawn_ids: &std::collections::HashMap<PawnID, csdemo::UserId>,
|
pawn_ids: &std::collections::HashMap<PawnID, csdemo::UserId>,
|
||||||
|
teams: &mut std::collections::HashMap<PawnID, String>,
|
||||||
player_lifestate: &mut std::collections::HashMap<csdemo::UserId, u32>,
|
player_lifestate: &mut std::collections::HashMap<csdemo::UserId, u32>,
|
||||||
player_position: &mut std::collections::HashMap<csdemo::UserId, (f32, f32, f32)>,
|
player_position: &mut std::collections::HashMap<csdemo::UserId, (f32, f32, f32)>,
|
||||||
player_cells: &mut std::collections::HashMap<csdemo::UserId, (u32, u32, u32)>,
|
player_cells: &mut std::collections::HashMap<csdemo::UserId, (u32, u32, u32)>,
|
||||||
heatmaps: &mut std::collections::HashMap<csdemo::UserId, HeatMap>,
|
heatmaps: &mut std::collections::HashMap<(csdemo::UserId, String), HeatMap>,
|
||||||
) {
|
) {
|
||||||
for entity_state in tick_state
|
for entity_state in tick_state
|
||||||
.states
|
.states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|s| s.class.as_ref() == "CCSPlayerPawn")
|
.filter(|s| matches!(s.class.as_ref(), "CCSPlayerPawn" | "CCSTeam"))
|
||||||
{
|
{
|
||||||
|
if entity_state.class.as_ref() == "CCSTeam" {
|
||||||
|
let raw_team_name = match entity_state.get_prop("CCSTeam.m_szTeamname").map(|p| match &p.value {
|
||||||
|
csdemo::parser::Variant::String(v) => Some(v),
|
||||||
|
_ => None,
|
||||||
|
}).flatten() {
|
||||||
|
Some(n) => n,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
for prop in entity_state.props.iter().filter(|p| p.prop_info.prop_name.as_ref() == "CCSTeam.m_aPawns").filter_map(|p| p.value.as_u32().map(|v| PawnID::from(v))) {
|
||||||
|
teams.insert(prop, raw_team_name.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let pawn_id = PawnID::from(entity_state.id);
|
let pawn_id = PawnID::from(entity_state.id);
|
||||||
let user_id = match pawn_ids.get(&pawn_id).cloned() {
|
let user_id = match pawn_ids.get(&pawn_id).cloned() {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => {
|
None => continue,
|
||||||
continue
|
};
|
||||||
}
|
let team = match teams.get(&pawn_id).cloned() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _inner_guard =
|
let _inner_guard =
|
||||||
@@ -245,7 +265,7 @@ fn process_tick(
|
|||||||
|
|
||||||
// tracing::trace!("Coord (X, Y, Z): {:?} -> {:?}", (x_coord, y_coord, z_coord), (x_cell, y_cell));
|
// tracing::trace!("Coord (X, Y, Z): {:?} -> {:?}", (x_coord, y_coord, z_coord), (x_cell, y_cell));
|
||||||
|
|
||||||
let heatmap = heatmaps.entry(user_id.clone()).or_insert(HeatMap::new(config.cell_size));
|
let heatmap = heatmaps.entry((user_id.clone(), team)).or_insert(HeatMap::new(config.cell_size));
|
||||||
heatmap.increment(x_cell, y_cell);
|
heatmap.increment(x_cell, y_cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ fn heatmap_nuke() {
|
|||||||
let config = heatmap::Config { cell_size: 5.0 };
|
let config = heatmap::Config { cell_size: 5.0 };
|
||||||
let result = heatmap::parse(&config, &input_bytes).unwrap();
|
let result = heatmap::parse(&config, &input_bytes).unwrap();
|
||||||
|
|
||||||
assert_eq!(result.player_heatmaps.len(), 10);
|
assert_eq!(result.player_heatmaps.len(), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -24,7 +24,7 @@ fn heatmap_inferno() {
|
|||||||
let config = heatmap::Config { cell_size: 5.0 };
|
let config = heatmap::Config { cell_size: 5.0 };
|
||||||
let result = heatmap::parse(&config, &input_bytes).unwrap();
|
let result = heatmap::parse(&config, &input_bytes).unwrap();
|
||||||
|
|
||||||
assert_eq!(result.player_heatmaps.len(), 10);
|
assert_eq!(result.player_heatmaps.len(), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -37,5 +37,5 @@ fn heatmap_dust2() {
|
|||||||
let config = heatmap::Config { cell_size: 5.0 };
|
let config = heatmap::Config { cell_size: 5.0 };
|
||||||
let result = heatmap::parse(&config, &input_bytes).unwrap();
|
let result = heatmap::parse(&config, &input_bytes).unwrap();
|
||||||
|
|
||||||
assert_eq!(result.player_heatmaps.len(), 10);
|
assert_eq!(result.player_heatmaps.len(), 20);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ impl Analysis for HeatmapAnalysis {
|
|||||||
let result = analysis::heatmap::parse(&config, &mmap).unwrap();
|
let result = analysis::heatmap::parse(&config, &mmap).unwrap();
|
||||||
|
|
||||||
tracing::info!("Got {} Entity-Heatmaps", result.player_heatmaps.len());
|
tracing::info!("Got {} Entity-Heatmaps", result.player_heatmaps.len());
|
||||||
let heatmap_result: Vec<_> = result.player_heatmaps.into_iter().filter_map(|(userid, heatmap)| {
|
let heatmap_result: Vec<_> = result.player_heatmaps.into_iter().filter_map(|((userid, team), heatmap)| {
|
||||||
let player = match result.player_info.get(&userid) {
|
let player = match result.player_info.get(&userid) {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
@@ -31,15 +31,16 @@ impl Analysis for HeatmapAnalysis {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((player.xuid.to_string(), heatmap))
|
Some(((player.xuid.to_string(), team), heatmap))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
let player_heatmaps: Vec<_> = heatmap_result.into_iter().map(|(player, heatmap)| {
|
let player_heatmaps: Vec<_> = heatmap_result.into_iter().map(|((player, team), heatmap)| {
|
||||||
tracing::trace!("HeatMap for Player: {:?}", player);
|
tracing::trace!("HeatMap for Player: {:?} in Team {:?}", player, team);
|
||||||
|
|
||||||
crate::models::DemoPlayerHeatmap {
|
crate::models::DemoPlayerHeatmap {
|
||||||
demo_id: input.demoid.clone(),
|
demo_id: input.demoid.clone(),
|
||||||
steam_id: player,
|
steam_id: player,
|
||||||
|
team,
|
||||||
data: serde_json::to_string(&heatmap).unwrap(),
|
data: serde_json::to_string(&heatmap).unwrap(),
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
@@ -47,7 +48,7 @@ impl Analysis for HeatmapAnalysis {
|
|||||||
Ok(Box::new(move |connection| {
|
Ok(Box::new(move |connection| {
|
||||||
let store_demo_player_heatmaps_query = diesel::dsl::insert_into(crate::schema::demo_heatmaps::dsl::demo_heatmaps)
|
let store_demo_player_heatmaps_query = diesel::dsl::insert_into(crate::schema::demo_heatmaps::dsl::demo_heatmaps)
|
||||||
.values(player_heatmaps)
|
.values(player_heatmaps)
|
||||||
.on_conflict((crate::schema::demo_heatmaps::dsl::demo_id, crate::schema::demo_heatmaps::dsl::steam_id))
|
.on_conflict((crate::schema::demo_heatmaps::dsl::demo_id, crate::schema::demo_heatmaps::dsl::steam_id, crate::schema::demo_heatmaps::dsl::team))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(crate::schema::demo_heatmaps::dsl::data.eq(diesel::upsert::excluded(crate::schema::demo_heatmaps::dsl::data)));
|
.set(crate::schema::demo_heatmaps::dsl::data.eq(diesel::upsert::excluded(crate::schema::demo_heatmaps::dsl::data)));
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ async fn heatmap(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let data: Vec<common::demo_analysis::PlayerHeatmap> = result.into_iter().map(|(player, heatmap)| {
|
let data: Vec<common::demo_analysis::PlayerHeatmap> = result.into_iter().map(|(player, heatmap)| {
|
||||||
|
let team = heatmap.team.clone();
|
||||||
let mut heatmap: analysis::heatmap::HeatMap = serde_json::from_str(&heatmap.data).unwrap();
|
let mut heatmap: analysis::heatmap::HeatMap = serde_json::from_str(&heatmap.data).unwrap();
|
||||||
heatmap.fit(minimap_coords.x_coord(0.0)..minimap_coords.x_coord(1024.0), minimap_coords.y_coord(1024.0)..minimap_coords.y_coord(0.0));
|
heatmap.fit(minimap_coords.x_coord(0.0)..minimap_coords.x_coord(1024.0), minimap_coords.y_coord(1024.0)..minimap_coords.y_coord(0.0));
|
||||||
let h_image = heatmap.as_image();
|
let h_image = heatmap.as_image();
|
||||||
@@ -314,6 +315,7 @@ async fn heatmap(
|
|||||||
|
|
||||||
common::demo_analysis::PlayerHeatmap {
|
common::demo_analysis::PlayerHeatmap {
|
||||||
name: player.name,
|
name: player.name,
|
||||||
|
team,
|
||||||
png_data: base64::prelude::BASE64_STANDARD.encode(buffer.into_inner()),
|
png_data: base64::prelude::BASE64_STANDARD.encode(buffer.into_inner()),
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ pub struct AnalysisTask {
|
|||||||
pub struct DemoPlayerHeatmap {
|
pub struct DemoPlayerHeatmap {
|
||||||
pub demo_id: String,
|
pub demo_id: String,
|
||||||
pub steam_id: String,
|
pub steam_id: String,
|
||||||
|
pub team: String,
|
||||||
pub data: String,
|
pub data: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
demo_heatmaps (demo_id, steam_id) {
|
demo_heatmaps (demo_id, steam_id, team) {
|
||||||
demo_id -> Text,
|
demo_id -> Text,
|
||||||
steam_id -> Text,
|
steam_id -> Text,
|
||||||
|
team -> Text,
|
||||||
data -> Text,
|
data -> Text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ pub mod demo_analysis {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct PlayerHeatmap {
|
pub struct PlayerHeatmap {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub team: String,
|
||||||
pub png_data: String,
|
pub png_data: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ fn heatmap_view(heatmaps: Vec<common::demo_analysis::PlayerHeatmap>) -> impl lep
|
|||||||
{ (move |heatmaps: Vec<common::demo_analysis::PlayerHeatmap>| {
|
{ (move |heatmaps: Vec<common::demo_analysis::PlayerHeatmap>| {
|
||||||
heatmaps.iter().enumerate().map(|(idx, heatmap)| {
|
heatmaps.iter().enumerate().map(|(idx, heatmap)| {
|
||||||
view! {
|
view! {
|
||||||
<option value={idx}>{heatmap.name.clone()}</option>
|
<option value={idx}>{ format!("[{}] {}", heatmap.team, heatmap.name) }</option>
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
})(h1.clone())}
|
})(h1.clone())}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
CREATE TABLE IF NOT EXISTS demo_heatmaps (
|
CREATE TABLE IF NOT EXISTS demo_heatmaps (
|
||||||
demo_id TEXT NOT NULL,
|
demo_id TEXT NOT NULL,
|
||||||
steam_id TEXT NOT NULL,
|
steam_id TEXT NOT NULL,
|
||||||
|
team TEXT NOT NULL,
|
||||||
data TEXT NOT NULL,
|
data TEXT NOT NULL,
|
||||||
PRIMARY KEY (demo_id, steam_id)
|
PRIMARY KEY (demo_id, steam_id, team)
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user