Fix formatting and implement the end of game score display

This commit is contained in:
Lol3rrr
2024-10-14 21:20:26 +02:00
parent 6f255faeb3
commit a2be4c2167
13 changed files with 401 additions and 200 deletions

View File

@@ -107,6 +107,13 @@ pub struct AnalysisInput {
pub struct BaseInfo {
pub map: String,
pub players: Vec<(BasePlayerInfo, BasePlayerStats)>,
pub teams: Vec<(u32, BaseTeamInfo)>
}
#[derive(Debug)]
pub struct BaseTeamInfo {
pub score: usize,
pub name: String,
}
#[derive(Debug)]

View File

@@ -10,8 +10,25 @@ impl BaseAnalysis {
impl Analysis for BaseAnalysis {
#[tracing::instrument(name = "Base", skip(self, input))]
fn analyse(&self, input: AnalysisInput) -> Result<Box<dyn FnOnce(&mut diesel_async::pg::AsyncPgConnection) -> core::pin::Pin<Box<(dyn core::future::Future<Output = Result<(), diesel::result::Error>> + Send + '_)>> + Send>, ()> { tracing::info!("Performing Base analysis");
fn analyse(
&self,
input: AnalysisInput,
) -> Result<
Box<
dyn FnOnce(
&mut diesel_async::pg::AsyncPgConnection,
) -> core::pin::Pin<
Box<
(dyn core::future::Future<Output = Result<(), diesel::result::Error>>
+ Send
+ '_),
>,
> + Send,
>,
(),
> {
tracing::info!("Performing Base analysis");
let file = std::fs::File::open(&input.path).unwrap();
let mmap = unsafe { memmap2::MmapOptions::new().map(&file).unwrap() };
@@ -19,20 +36,33 @@ impl Analysis for BaseAnalysis {
let base_result = BaseInfo {
map: result.map,
players: result.players.into_iter().map(|(info, stats)| {
(BasePlayerInfo {
name: info.name,
steam_id: info.steam_id,
team: info.team,
ingame_id: info.ingame_id,
color: info.color,
}, BasePlayerStats {
kills: stats.kills,
assists: stats.assists,
damage: stats.damage,
deaths: stats.deaths,
players: result
.players
.into_iter()
.map(|(info, stats)| {
(
BasePlayerInfo {
name: info.name,
steam_id: info.steam_id,
team: info.team,
ingame_id: info.ingame_id,
color: info.color,
},
BasePlayerStats {
kills: stats.kills,
assists: stats.assists,
damage: stats.damage,
deaths: stats.deaths,
},
)
})
}).collect()
.collect(),
teams: result.teams.into_iter().map(|(numb, val)| {
(numb, BaseTeamInfo {
name: val.name,
score: val.score,
})
}).collect(),
};
let (player_info, player_stats): (Vec<_>, Vec<_>) = base_result
@@ -64,48 +94,68 @@ impl Analysis for BaseAnalysis {
map: base_result.map,
};
let demo_teams: Vec<crate::models::DemoTeam> = base_result.teams.into_iter().map(|(numb, info)| {
crate::models::DemoTeam {
demo_id: input.demoid.clone(),
team: numb as i16,
end_score: info.score as i16,
start_name: info.name,
}
}).collect();
Ok(Box::new(move |connection| {
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();
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,
)),
crate::schema::demo_player_stats::dsl::assists.eq(diesel::upsert::excluded(
crate::schema::demo_player_stats::dsl::assists,
)),
crate::schema::demo_player_stats::dsl::damage.eq(diesel::upsert::excluded(
crate::schema::demo_player_stats::dsl::damage,
)),
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,
)),
crate::schema::demo_player_stats::dsl::assists.eq(
diesel::upsert::excluded(
crate::schema::demo_player_stats::dsl::assists,
),
),
crate::schema::demo_player_stats::dsl::damage.eq(diesel::upsert::excluded(
crate::schema::demo_player_stats::dsl::damage,
)),
));
let store_demo_teams = diesel::dsl::insert_into(crate::schema::demo_teams::dsl::demo_teams)
.values(demo_teams).on_conflict((crate::schema::demo_teams::dsl::demo_id, crate::schema::demo_teams::dsl::team))
.do_update()
.set((
crate::schema::demo_teams::dsl::start_name.eq(diesel::upsert::excluded(crate::schema::demo_teams::dsl::start_name)),
crate::schema::demo_teams::dsl::end_score.eq(diesel::upsert::excluded(crate::schema::demo_teams::dsl::end_score)),
));
Box::pin(async move {
store_demo_info_query.execute(connection).await?;
store_demo_players_query.execute(connection).await?;
store_demo_player_stats_query.execute(connection).await?;
store_demo_teams.execute(connection).await?;
Ok(())
})

View File

@@ -10,47 +10,77 @@ impl HeatmapAnalysis {
impl Analysis for HeatmapAnalysis {
#[tracing::instrument(name = "Heatmap", skip(self, input))]
fn analyse(&self, input: AnalysisInput) -> Result<Box<dyn FnOnce(&mut diesel_async::pg::AsyncPgConnection) -> core::pin::Pin<Box<(dyn core::future::Future<Output = Result<(), diesel::result::Error>> + Send + '_)>> + Send>, ()> {
fn analyse(
&self,
input: AnalysisInput,
) -> Result<
Box<
dyn FnOnce(
&mut diesel_async::pg::AsyncPgConnection,
) -> core::pin::Pin<
Box<
(dyn core::future::Future<Output = Result<(), diesel::result::Error>>
+ Send
+ '_),
>,
> + Send,
>,
(),
> {
tracing::info!("Generating HEATMAPs");
let file = std::fs::File::open(&input.path).unwrap();
let mmap = unsafe { memmap2::MmapOptions::new().map(&file).unwrap() };
let file = std::fs::File::open(&input.path).unwrap();
let mmap = unsafe { memmap2::MmapOptions::new().map(&file).unwrap() };
let config = analysis::heatmap::Config {
cell_size: 5.0,
};
let result = analysis::heatmap::parse(&config, &mmap).unwrap();
let config = analysis::heatmap::Config { cell_size: 5.0 };
let result = analysis::heatmap::parse(&config, &mmap).unwrap();
tracing::info!("Got {} Entity-Heatmaps", result.player_heatmaps.len());
let heatmap_result: Vec<_> = result.player_heatmaps.into_iter().filter_map(|((userid, team), heatmap)| {
let player = match result.player_info.get(&userid) {
Some(p) => p,
None => {
tracing::warn!("Could not find player: {:?}", userid);
return None;
}
};
Some(((player.xuid.to_string(), team), heatmap))
}).collect();
tracing::info!("Got {} Entity-Heatmaps", result.player_heatmaps.len());
let heatmap_result: Vec<_> = result
.player_heatmaps
.into_iter()
.filter_map(|((userid, team), heatmap)| {
let player = match result.player_info.get(&userid) {
Some(p) => p,
None => {
tracing::warn!("Could not find player: {:?}", userid);
return None;
}
};
let player_heatmaps: Vec<_> = heatmap_result.into_iter().map(|((player, team), heatmap)| {
tracing::trace!("HeatMap for Player: {:?} in Team {:?}", player, team);
Some(((player.xuid.to_string(), team), heatmap))
})
.collect();
crate::models::DemoPlayerHeatmap {
demo_id: input.demoid.clone(),
steam_id: player,
team,
data: serde_json::to_string(&heatmap).unwrap(),
}
}).collect();
let player_heatmaps: Vec<_> = heatmap_result
.into_iter()
.map(|((player, team), heatmap)| {
tracing::trace!("HeatMap for Player: {:?} in Team {:?}", player, team);
crate::models::DemoPlayerHeatmap {
demo_id: input.demoid.clone(),
steam_id: player,
team,
data: serde_json::to_string(&heatmap).unwrap(),
}
})
.collect();
Ok(Box::new(move |connection| {
let store_demo_player_heatmaps_query = diesel::dsl::insert_into(crate::schema::demo_heatmaps::dsl::demo_heatmaps)
.values(player_heatmaps)
.on_conflict((crate::schema::demo_heatmaps::dsl::demo_id, crate::schema::demo_heatmaps::dsl::steam_id, crate::schema::demo_heatmaps::dsl::team))
.do_update()
.set(crate::schema::demo_heatmaps::dsl::data.eq(diesel::upsert::excluded(crate::schema::demo_heatmaps::dsl::data)));
let store_demo_player_heatmaps_query =
diesel::dsl::insert_into(crate::schema::demo_heatmaps::dsl::demo_heatmaps)
.values(player_heatmaps)
.on_conflict((
crate::schema::demo_heatmaps::dsl::demo_id,
crate::schema::demo_heatmaps::dsl::steam_id,
crate::schema::demo_heatmaps::dsl::team,
))
.do_update()
.set(
crate::schema::demo_heatmaps::dsl::data.eq(diesel::upsert::excluded(
crate::schema::demo_heatmaps::dsl::data,
)),
);
Box::pin(async move {
store_demo_player_heatmaps_query.execute(connection).await?;

View File

@@ -10,22 +10,41 @@ impl PerRoundAnalysis {
impl Analysis for PerRoundAnalysis {
#[tracing::instrument(name = "PerRoundAnalysis", skip(self, input))]
fn analyse(&self, input: AnalysisInput) -> Result<Box<dyn FnOnce(&mut diesel_async::pg::AsyncPgConnection) -> core::pin::Pin<Box<(dyn core::future::Future<Output = Result<(), diesel::result::Error>> + Send + '_)>> + Send>, ()> {
fn analyse(
&self,
input: AnalysisInput,
) -> Result<
Box<
dyn FnOnce(
&mut diesel_async::pg::AsyncPgConnection,
) -> core::pin::Pin<
Box<
(dyn core::future::Future<Output = Result<(), diesel::result::Error>>
+ Send
+ '_),
>,
> + Send,
>,
(),
> {
let file = std::fs::File::open(&input.path).unwrap();
let mmap = unsafe { memmap2::MmapOptions::new().map(&file).unwrap() };
let result = analysis::perround::parse(&mmap).unwrap();
let values: Vec<crate::models::DemoRound> = result.rounds.into_iter().enumerate().map(|(i, r)| {
crate::models::DemoRound {
let values: Vec<crate::models::DemoRound> = result
.rounds
.into_iter()
.enumerate()
.map(|(i, r)| crate::models::DemoRound {
demo_id: input.demoid.clone(),
round_number: i as i16,
start_tick: r.start as i64,
end_tick: r.end as i64,
win_reason: serde_json::to_string(&r.winreason).unwrap(),
events: serde_json::to_value(&r.events).unwrap(),
}
}).collect();
})
.collect();
Ok(Box::new(move |connection| {
Box::pin(async move {

View File

@@ -41,28 +41,46 @@ async fn list(
tracing::info!("SteamID: {:?}", steam_id);
let query = crate::schema::demos::dsl::demos
.inner_join(crate::schema::demo_info::table.on(
crate::schema::demos::dsl::demo_id.eq(crate::schema::demo_info::dsl::demo_id),
))
.inner_join(
crate::schema::demo_info::table
.on(crate::schema::demos::dsl::demo_id.eq(crate::schema::demo_info::dsl::demo_id)),
)
.inner_join(
crate::schema::demo_teams::table
.on(crate::schema::demos::dsl::demo_id.eq(crate::schema::demo_teams::dsl::demo_id)),
)
.select((
crate::models::Demo::as_select(),
crate::models::DemoInfo::as_select(),
crate::models::DemoTeam::as_select(),
))
.filter(crate::schema::demos::dsl::steam_id.eq(steam_id.to_string()));
let results: Vec<(crate::models::Demo, crate::models::DemoInfo)> =
let results: Vec<(crate::models::Demo, crate::models::DemoInfo, crate::models::DemoTeam)> =
query.load(&mut crate::db_connection().await).await.unwrap();
let mut demos = std::collections::HashMap::new();
for (demo, info, team) in results.into_iter() {
let entry = demos.entry(demo.demo_id.clone()).or_insert(common::BaseDemoInfo {
id: demo.demo_id,
map: info.map,
team2_score: 0,
team3_score: 0,
});
Ok(axum::response::Json(
results
.into_iter()
.map(|(demo, info)| {
common::BaseDemoInfo {
id: demo.demo_id,
map: info.map,
}
})
.collect::<Vec<_>>(),
))
if team.team == 2 {
entry.team2_score = team.end_score;
} else if team.team == 3 {
entry.team3_score = team.end_score;
} else {
tracing::warn!("Unknown Team: {:?}", team);
}
}
// TODO
// Sort this
let mut output = demos.into_values().collect::<Vec<_>>();
Ok(axum::response::Json(output))
}
#[tracing::instrument(skip(state, session, form))]
@@ -82,7 +100,10 @@ async fn upload(
Some(c) => c,
None => {
tracing::error!("Getting File content from request");
return Err((axum::http::StatusCode::BAD_REQUEST, "Failed to get file-content from upload"));
return Err((
axum::http::StatusCode::BAD_REQUEST,
"Failed to get file-content from upload",
));
}
};
@@ -90,7 +111,7 @@ async fn upload(
let demo_id = raw_demo_id.to_string();
tracing::debug!(?demo_id, "Upload Size: {:?}", file_content.len());
let user_folder = std::path::Path::new(&state.upload_folder).join(format!("{}/", steam_id));
if !tokio::fs::try_exists(&user_folder).await.unwrap_or(false) {
tokio::fs::create_dir_all(&user_folder).await.unwrap();
@@ -106,30 +127,36 @@ async fn upload(
// Turn all of this into a single transaction
let db_trans_result = db_con.build_transaction().run(|c| {
Box::pin(async move {
let query =
diesel::dsl::insert_into(crate::schema::demos::dsl::demos).values(crate::models::NewDemo {
demo_id: demo_id.clone(),
steam_id: steam_id.to_string(),
});
query.execute(c).await?;
let db_trans_result = db_con
.build_transaction()
.run(|c| {
Box::pin(async move {
let query = diesel::dsl::insert_into(crate::schema::demos::dsl::demos).values(
crate::models::NewDemo {
demo_id: demo_id.clone(),
steam_id: steam_id.to_string(),
},
);
query.execute(c).await?;
let queue_query = diesel::dsl::insert_into(crate::schema::analysis_queue::dsl::analysis_queue)
.values(crate::models::AddAnalysisTask {
demo_id: demo_id.clone(),
steam_id: steam_id.to_string(),
});
queue_query.execute(c).await?;
let queue_query =
diesel::dsl::insert_into(crate::schema::analysis_queue::dsl::analysis_queue)
.values(crate::models::AddAnalysisTask {
demo_id: demo_id.clone(),
steam_id: steam_id.to_string(),
});
queue_query.execute(c).await?;
let processing_query =
diesel::dsl::insert_into(crate::schema::processing_status::dsl::processing_status)
.values(crate::models::ProcessingStatus { demo_id, info: 0 });
processing_query.execute(c).await?;
let processing_query = diesel::dsl::insert_into(
crate::schema::processing_status::dsl::processing_status,
)
.values(crate::models::ProcessingStatus { demo_id, info: 0 });
processing_query.execute(c).await?;
Ok::<(), diesel::result::Error>(())
Ok::<(), diesel::result::Error>(())
})
})
}).await;
.await;
if let Err(e) = db_trans_result {
tracing::error!("Inserting data into db: {:?}", e);
@@ -267,12 +294,14 @@ async fn scoreboard(
async fn heatmap(
session: UserSession,
Path(demo_id): Path<String>,
) -> Result<axum::response::Json<Vec<common::demo_analysis::PlayerHeatmap>>, axum::http::StatusCode> {
) -> Result<axum::response::Json<Vec<common::demo_analysis::PlayerHeatmap>>, axum::http::StatusCode>
{
use base64::prelude::Engine;
let mut db_con = crate::db_connection().await;
let demo_info_query = crate::schema::demo_info::dsl::demo_info.filter(crate::schema::demo_info::dsl::demo_id.eq(demo_id.clone()));
let demo_info_query = crate::schema::demo_info::dsl::demo_info
.filter(crate::schema::demo_info::dsl::demo_id.eq(demo_id.clone()));
let demo_info: crate::models::DemoInfo = match demo_info_query.first(&mut db_con).await {
Ok(i) => i,
Err(e) => {
@@ -282,18 +311,26 @@ async fn heatmap(
};
let query = crate::schema::demo_players::dsl::demo_players
.inner_join(crate::schema::demo_heatmaps::dsl::demo_heatmaps.on(
crate::schema::demo_players::dsl::steam_id.eq(crate::schema::demo_heatmaps::dsl::steam_id)
.and(crate::schema::demo_players::dsl::demo_id.eq(crate::schema::demo_heatmaps::dsl::demo_id))
)).filter(crate::schema::demo_players::dsl::demo_id.eq(demo_id));
.inner_join(
crate::schema::demo_heatmaps::dsl::demo_heatmaps.on(
crate::schema::demo_players::dsl::steam_id
.eq(crate::schema::demo_heatmaps::dsl::steam_id)
.and(
crate::schema::demo_players::dsl::demo_id
.eq(crate::schema::demo_heatmaps::dsl::demo_id),
),
),
)
.filter(crate::schema::demo_players::dsl::demo_id.eq(demo_id));
let result: Vec<(crate::models::DemoPlayer, crate::models::DemoPlayerHeatmap)> = match query.load(&mut db_con).await {
Ok(d) => d,
Err(e) => {
tracing::error!("Querying DB: {:?}", e);
return Err(axum::http::StatusCode::INTERNAL_SERVER_ERROR);
}
};
let result: Vec<(crate::models::DemoPlayer, crate::models::DemoPlayerHeatmap)> =
match query.load(&mut db_con).await {
Ok(d) => d,
Err(e) => {
tracing::error!("Querying DB: {:?}", e);
return Err(axum::http::StatusCode::INTERNAL_SERVER_ERROR);
}
};
let demo_map = &demo_info.map;
let minimap_coords = match MINIMAP_COORDINATES.get(demo_map) {
@@ -304,21 +341,30 @@ async fn 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();
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 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();
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 mut buffer = std::io::Cursor::new(Vec::new());
h_image.write_to(&mut buffer, image::ImageFormat::Png).unwrap();
let mut buffer = std::io::Cursor::new(Vec::new());
h_image
.write_to(&mut buffer, image::ImageFormat::Png)
.unwrap();
common::demo_analysis::PlayerHeatmap {
name: player.name,
team,
png_data: base64::prelude::BASE64_STANDARD.encode(buffer.into_inner()),
}
}).collect();
common::demo_analysis::PlayerHeatmap {
name: player.name,
team,
png_data: base64::prelude::BASE64_STANDARD.encode(buffer.into_inner()),
}
})
.collect();
Ok(axum::Json(data))
}
@@ -328,23 +374,38 @@ async fn perround(
session: UserSession,
Path(demo_id): Path<String>,
) -> Result<axum::response::Json<Vec<common::demo_analysis::DemoRound>>, axum::http::StatusCode> {
let rounds_query = crate::schema::demo_round::dsl::demo_round.filter(crate::schema::demo_round::dsl::demo_id.eq(demo_id.clone()));
let round_players_query = crate::schema::demo_players::dsl::demo_players.filter(crate::schema::demo_players::dsl::demo_id.eq(demo_id));
let rounds_query = crate::schema::demo_round::dsl::demo_round
.filter(crate::schema::demo_round::dsl::demo_id.eq(demo_id.clone()));
let round_players_query = crate::schema::demo_players::dsl::demo_players
.filter(crate::schema::demo_players::dsl::demo_id.eq(demo_id));
let mut db_con = crate::db_connection().await;
let raw_rounds: Vec<crate::models::DemoRound> = rounds_query.load(&mut db_con).await.unwrap();
let players: Vec<crate::models::DemoPlayer> = round_players_query.load(&mut db_con).await.unwrap();
let players: Vec<crate::models::DemoPlayer> =
round_players_query.load(&mut db_con).await.unwrap();
let mut result = Vec::with_capacity(raw_rounds.len());
for raw_round in raw_rounds.into_iter() {
let reason = match serde_json::from_str(&raw_round.win_reason) {
Ok(analysis::perround::WinReason::StillInProgress) => common::demo_analysis::RoundWinReason::StillInProgress,
Ok(analysis::perround::WinReason::TKilled) => common::demo_analysis::RoundWinReason::TKilled,
Ok(analysis::perround::WinReason::CTKilled) => common::demo_analysis::RoundWinReason::CTKilled,
Ok(analysis::perround::WinReason::BombDefused) => common::demo_analysis::RoundWinReason::BombDefused,
Ok(analysis::perround::WinReason::BombExploded) => common::demo_analysis::RoundWinReason::BombExploded,
Ok(analysis::perround::WinReason::TimeRanOut) => common::demo_analysis::RoundWinReason::TimeRanOut,
Ok(analysis::perround::WinReason::StillInProgress) => {
common::demo_analysis::RoundWinReason::StillInProgress
}
Ok(analysis::perround::WinReason::TKilled) => {
common::demo_analysis::RoundWinReason::TKilled
}
Ok(analysis::perround::WinReason::CTKilled) => {
common::demo_analysis::RoundWinReason::CTKilled
}
Ok(analysis::perround::WinReason::BombDefused) => {
common::demo_analysis::RoundWinReason::BombDefused
}
Ok(analysis::perround::WinReason::BombExploded) => {
common::demo_analysis::RoundWinReason::BombExploded
}
Ok(analysis::perround::WinReason::TimeRanOut) => {
common::demo_analysis::RoundWinReason::TimeRanOut
}
Ok(other) => {
tracing::error!("Unknown Mapping {:?}", other);
return Err(axum::http::StatusCode::INTERNAL_SERVER_ERROR);
@@ -355,27 +416,38 @@ async fn perround(
}
};
let parsed_events: Vec<analysis::perround::RoundEvent> = serde_json::from_value(raw_round.events).unwrap();
let events: Vec<_> = parsed_events.into_iter().map(|event| {
match event {
analysis::perround::RoundEvent::BombPlanted => common::demo_analysis::RoundEvent::BombPlanted,
analysis::perround::RoundEvent::BombDefused => common::demo_analysis::RoundEvent::BombDefused,
let parsed_events: Vec<analysis::perround::RoundEvent> =
serde_json::from_value(raw_round.events).unwrap();
let events: Vec<_> = parsed_events
.into_iter()
.map(|event| match event {
analysis::perround::RoundEvent::BombPlanted => {
common::demo_analysis::RoundEvent::BombPlanted
}
analysis::perround::RoundEvent::BombDefused => {
common::demo_analysis::RoundEvent::BombDefused
}
analysis::perround::RoundEvent::Kill { attacker, died } => {
let attacker_name = players.iter().find(|p| p.steam_id == attacker.to_string()).map(|p| p.name.clone()).unwrap();
let died_name = players.iter().find(|p| p.steam_id == died.to_string()).map(|p| p.name.clone()).unwrap();
let attacker_name = players
.iter()
.find(|p| p.steam_id == attacker.to_string())
.map(|p| p.name.clone())
.unwrap();
let died_name = players
.iter()
.find(|p| p.steam_id == died.to_string())
.map(|p| p.name.clone())
.unwrap();
common::demo_analysis::RoundEvent::Killed {
attacker: attacker_name,
died: died_name,
}
}
}
}).collect();
})
.collect();
result.push(common::demo_analysis::DemoRound {
reason,
events,
});
result.push(common::demo_analysis::DemoRound { reason, events });
}
Ok(axum::Json(result))

View File

@@ -76,12 +76,12 @@ pub async fn run_api(
}),
)
.layer(session_layer)
.nest_service(
"/",
tower_http::services::ServeDir::new(serve_dir),
);
.nest_service("/", tower_http::services::ServeDir::new(serve_dir));
let listen_addr = std::net::SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(0, 0, 0, 0)), 3000);
let listen_addr = std::net::SocketAddr::new(
std::net::IpAddr::V4(std::net::Ipv4Addr::new(0, 0, 0, 0)),
3000,
);
tracing::info!("Listening on Addr: {:?}", listen_addr);
let listener = tokio::net::TcpListener::bind(listen_addr).await.unwrap();
@@ -110,17 +110,18 @@ pub async fn run_analysis(upload_folder: impl Into<std::path::PathBuf>) {
let mut store_result_fns = Vec::new();
for analysis in analysis::ANALYSIS_METHODS.iter().map(|a| a.clone()) {
let input = input.clone();
let store_result = match tokio::task::spawn_blocking(move || analysis.analyse(input)).await {
Ok(Ok(r)) => r,
Ok(Err(e)) => {
tracing::error!("Analysis failed: {:?}", e);
continue;
}
Err(e) => {
tracing::error!("Joining Task: {:?}", e);
continue;
}
};
let store_result =
match tokio::task::spawn_blocking(move || analysis.analyse(input)).await {
Ok(Ok(r)) => r,
Ok(Err(e)) => {
tracing::error!("Analysis failed: {:?}", e);
continue;
}
Err(e) => {
tracing::error!("Joining Task: {:?}", e);
continue;
}
};
store_result_fns.push(store_result);
}

View File

@@ -26,8 +26,7 @@ async fn main() {
let registry = tracing_subscriber::Registry::default()
.with(tracing_subscriber::fmt::layer())
.with(tracing_subscriber::filter::filter_fn(|meta| {
meta.target().contains("backend")
|| meta.target().contains("analysis")
meta.target().contains("backend") || meta.target().contains("analysis")
}));
tracing::subscriber::set_global_default(registry).unwrap();

View File

@@ -23,7 +23,7 @@ pub struct NewDemo {
pub struct Demo {
pub steam_id: String,
pub demo_id: String,
pub uploaded_at: diesel::data_types::PgTimestamp
pub uploaded_at: diesel::data_types::PgTimestamp,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
@@ -65,6 +65,16 @@ pub struct DemoPlayerStats {
pub assists: i16,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::demo_teams)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoTeam {
pub demo_id: String,
pub team: i16,
pub end_score: i16,
pub start_name: String,
}
#[derive(Queryable, Selectable, Insertable, Debug)]
#[diesel(table_name = crate::schema::processing_status)]
#[diesel(check_for_backend(diesel::pg::Pg))]

View File

@@ -56,6 +56,15 @@ diesel::table! {
}
}
diesel::table! {
demo_teams (demo_id, team) {
demo_id -> Text,
team -> Int2,
end_score -> Int2,
start_name -> Text,
}
}
diesel::table! {
demos (steam_id, demo_id) {
steam_id -> Text,
@@ -79,13 +88,6 @@ diesel::table! {
}
}
diesel::table! {
user_demos (steam_id, demo_id) {
steam_id -> Text,
demo_id -> Text,
}
}
diesel::table! {
users (steamid) {
steamid -> Text,
@@ -100,9 +102,9 @@ diesel::allow_tables_to_appear_in_same_query!(
demo_player_stats,
demo_players,
demo_round,
demo_teams,
demos,
processing_status,
sessions,
user_demos,
users,
);