Add basic analysis results, like scoreboard

This commit is contained in:
Lol3rrr
2024-09-17 17:35:02 +02:00
parent 8290fcf390
commit b216022768
7 changed files with 157 additions and 47 deletions

10
Cargo.lock generated
View File

@@ -307,9 +307,9 @@ checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
[[package]]
name = "cc"
version = "1.1.19"
version = "1.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800"
checksum = "45bcde016d64c21da4be18b655631e5ab6d3107607e71a73a9f53eb48aae23fb"
dependencies = [
"shlex",
]
@@ -504,7 +504,7 @@ dependencies = [
[[package]]
name = "csdemo"
version = "0.1.0"
source = "git+https://github.com/Lol3rrr/csdemo.git#4417b263a0c04ceb32e199e67dd790adf4645277"
source = "git+https://github.com/Lol3rrr/csdemo.git#c5237af33bc892437cf7b8658de34d7dad8947a0"
dependencies = [
"bitter",
"phf",
@@ -3059,9 +3059,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.20"
version = "0.22.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf"
dependencies = [
"indexmap",
"serde",

View File

@@ -49,7 +49,22 @@ pub struct AnalysisInput {
#[derive(Debug)]
pub struct BaseInfo {
pub map: String,
pub players: Vec<()>,
pub players: Vec<(BasePlayerInfo, BasePlayerStats)>,
}
#[derive(Debug)]
pub struct BasePlayerInfo {
pub name: String,
pub steam_id: String,
pub team: i32,
pub color: i32,
pub ingame_id: i32,
}
#[derive(Debug)]
pub struct BasePlayerStats {
pub kills: usize,
pub deaths: usize,
}
#[tracing::instrument(skip(input))]
@@ -66,7 +81,7 @@ pub fn analyse_base(input: AnalysisInput) -> BaseInfo {
tracing::info!("Header: {:?}", header);
dbg!(&output.player_info);
let mut player_stats = std::collections::HashMap::with_capacity(output.player_info.len());
for event in output.events.iter() {
match event {
@@ -76,52 +91,58 @@ pub fn analyse_base(input: AnalysisInput) -> BaseInfo {
csdemo::DemoEvent::RankReveal(reveal) => {}
csdemo::DemoEvent::GameEvent(gevent) => {
match gevent {
csdemo::game_event::GameEvent::BeginNewMatch(_) => {
player_stats.clear();
}
csdemo::game_event::GameEvent::PlayerTeam(pteam) => {
tracing::info!("{:?}", pteam);
// tracing::info!("{:?}", pteam);
}
csdemo::game_event::GameEvent::RoundOfficiallyEnded(r_end) => {
tracing::info!("{:?}", r_end);
// tracing::info!("{:?}", r_end);
}
csdemo::game_event::GameEvent::PlayerDeath(pdeath) => {
tracing::info!("{:?}", pdeath);
// tracing::info!("{:?}", pdeath);
let player_died_id = pdeath.userid.unwrap();
let player_died = player_stats.entry(player_died_id).or_insert(BasePlayerStats {
kills: 0,
deaths: 0,
});
player_died.deaths += 1;
if let Some(attacker_id) = pdeath.attacker {
let attacker = player_stats.entry(attacker_id).or_insert(BasePlayerStats {
kills: 0,
deaths: 0,
});
attacker.kills += 1;
// tracing::trace!("{:?} killed {:?}", attacker_id, player_died_id);
}
}
other => {}
};
}
};
}
/*
match event.name.as_str() {
"team_info" => {
tracing::info!("Team Info: {:?}", event);
}
"player_spawn" => {
// tracing::info!("Player Spawn: {:?}", event);
}
"team_score" => {
tracing::info!("Team Score: {:?}", event);
}
"game_end" => {
tracing::info!("Game End: {:?}", event);
}
"match_end_conditions" => {
tracing::info!("Match End Conditions: {:?}", event);
}
"switch_team" => {
tracing::info!("Switch Team: {:?}", event);
}
"player_given_c4" => {
tracing::info!("Player Given C4: {:?}", event);
}
_ => {}
};
*/
}
let players: Vec<_> = player_stats.into_iter().filter_map(|(id, stats)| {
let player = output.player_info.get(&id)?;
Some((BasePlayerInfo {
name: player.name.clone(),
steam_id: player.xuid.to_string(),
team: player.team,
color: player.color,
ingame_id: id.0,
}, stats))
}).collect();
let map = header.map_name().to_owned();
BaseInfo {
map,
players: Vec::new(),
players,
}
}

View File

@@ -114,23 +114,49 @@ pub async fn run_analysis(
let mut db_con = crate::db_connection().await;
let store_info_query = diesel::dsl::insert_into(crate::schema::demo_info::dsl::demo_info)
.values(crate::models::DemoInfo {
let (player_info, player_stats): (Vec<_>, Vec<_>) = result.players.into_iter().map(|(info, stats)| {
(crate::models::DemoPlayer {
demo_id,
name: info.name,
steam_id: info.steam_id.clone(),
team: info.team as i16,
color: info.color as i16,
}, crate::models::DemoPlayerStats {
demo_id,
steam_id: info.steam_id,
deaths: stats.deaths as i16,
kills: stats.kills as i16,
})
}).unzip();
let demo_info = crate::models::DemoInfo {
demo_id,
map: result.map,
});
};
let store_demo_info_query = diesel::dsl::insert_into(crate::schema::demo_info::dsl::demo_info)
.values(&demo_info).on_conflict(crate::schema::demo_info::dsl::demo_id).do_update().set(crate::schema::demo_info::dsl::map.eq(diesel::upsert::excluded(crate::schema::demo_info::dsl::map)));
let store_demo_players_query = diesel::dsl::insert_into(crate::schema::demo_players::dsl::demo_players).values(player_info)
.on_conflict_do_nothing();
let store_demo_player_stats_query = diesel::dsl::insert_into(crate::schema::demo_player_stats::dsl::demo_player_stats)
.values(player_stats)
.on_conflict((crate::schema::demo_player_stats::dsl::demo_id, crate::schema::demo_player_stats::dsl::steam_id))
.do_update()
.set((
crate::schema::demo_player_stats::dsl::deaths.eq(diesel::upsert::excluded(crate::schema::demo_player_stats::dsl::deaths)),
crate::schema::demo_player_stats::dsl::kills.eq(diesel::upsert::excluded(crate::schema::demo_player_stats::dsl::kills)),
));
let update_process_info =
diesel::dsl::update(crate::schema::processing_status::dsl::processing_status)
.set(crate::schema::processing_status::dsl::info.eq(1))
.filter(crate::schema::processing_status::dsl::demo_id.eq(demo_id));
tracing::trace!(?store_info_query, "Store demo info query");
tracing::trace!(?update_process_info, "Update processing info query");
db_con
.transaction::<'_, '_, '_, _, diesel::result::Error, _>(|conn| {
Box::pin(async move {
store_info_query.execute(conn).await?;
store_demo_info_query.execute(conn).await?;
store_demo_players_query.execute(conn).await?;
store_demo_player_stats_query.execute(conn).await?;
update_process_info.execute(conn).await?;
Ok(())
})

View File

@@ -33,6 +33,27 @@ pub struct DemoInfo {
pub map: String,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::demo_players)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoPlayer {
pub demo_id: i64,
pub steam_id: String,
pub name: String,
pub team: i16,
pub color: i16,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::demo_player_stats)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoPlayerStats {
pub demo_id: i64,
pub steam_id: String,
pub kills: i16,
pub deaths: i16,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::processing_status)]
#[diesel(check_for_backend(diesel::pg::Pg))]

View File

@@ -15,6 +15,25 @@ diesel::table! {
}
}
diesel::table! {
demo_player_stats (demo_id, steam_id) {
demo_id -> Int8,
steam_id -> Text,
kills -> Int2,
deaths -> Int2,
}
}
diesel::table! {
demo_players (demo_id, steam_id) {
demo_id -> Int8,
steam_id -> Text,
name -> Text,
team -> Int2,
color -> Int2,
}
}
diesel::table! {
demos (demo_id) {
steam_id -> Text,
@@ -46,11 +65,15 @@ diesel::table! {
diesel::joinable!(analysis_queue -> demos (demo_id));
diesel::joinable!(demo_info -> demos (demo_id));
diesel::joinable!(demo_player_stats -> demo_info (demo_id));
diesel::joinable!(demo_players -> demo_info (demo_id));
diesel::joinable!(processing_status -> demos (demo_id));
diesel::allow_tables_to_appear_in_same_query!(
analysis_queue,
demo_info,
demo_player_stats,
demo_players,
demos,
processing_status,
sessions,

View File

@@ -1,3 +1,5 @@
-- This file should undo anything in `up.sql`
DROP TABLE processing_status;
DROP TABLE demo_info
DROP TABLE demo_player_stats;
DROP TABLE demo_players;
DROP TABLE demo_info;

View File

@@ -7,4 +7,21 @@ CREATE TABLE IF NOT EXISTS processing_status (
CREATE TABLE IF NOT EXISTS demo_info (
demo_id bigint PRIMARY KEY REFERENCES demos(demo_id),
map TEXT NOT NULL
)
);
CREATE TABLE IF NOT EXISTS demo_players (
demo_id bigint REFERENCES demo_info(demo_id),
steam_id TEXT NOT NULL,
name TEXT NOT NULL,
team int2 NOT NULL,
color int2 NOT NULL,
PRIMARY KEY (demo_id, steam_id)
);
CREATE TABLE IF NOT EXISTS demo_player_stats (
demo_id bigint REFERENCES demo_info(demo_id),
steam_id TEXT NOT NULL,
kills int2 NOT NULL,
deaths int2 NOT NULL,
PRIMARY KEY (demo_id, steam_id)
);