Fix formatting and implement the end of game score display
This commit is contained in:
@@ -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)]
|
||||
|
||||
@@ -10,7 +10,24 @@ 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 {
|
||||
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 {
|
||||
},
|
||||
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,6 +94,15 @@ 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)
|
||||
@@ -94,18 +133,29 @@ impl Analysis for BaseAnalysis {
|
||||
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.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(())
|
||||
})
|
||||
|
||||
@@ -10,19 +10,36 @@ 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 config = analysis::heatmap::Config {
|
||||
cell_size: 5.0,
|
||||
};
|
||||
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 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 => {
|
||||
@@ -32,9 +49,12 @@ impl Analysis for HeatmapAnalysis {
|
||||
};
|
||||
|
||||
Some(((player.xuid.to_string(), team), heatmap))
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
|
||||
let player_heatmaps: Vec<_> = heatmap_result.into_iter().map(|((player, team), heatmap)| {
|
||||
let player_heatmaps: Vec<_> = heatmap_result
|
||||
.into_iter()
|
||||
.map(|((player, team), heatmap)| {
|
||||
tracing::trace!("HeatMap for Player: {:?} in Team {:?}", player, team);
|
||||
|
||||
crate::models::DemoPlayerHeatmap {
|
||||
@@ -43,14 +63,24 @@ impl Analysis for HeatmapAnalysis {
|
||||
team,
|
||||
data: serde_json::to_string(&heatmap).unwrap(),
|
||||
}
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
|
||||
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)
|
||||
.on_conflict((crate::schema::demo_heatmaps::dsl::demo_id, crate::schema::demo_heatmaps::dsl::steam_id, crate::schema::demo_heatmaps::dsl::team))
|
||||
.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)));
|
||||
.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?;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Ok(axum::response::Json(
|
||||
results
|
||||
.into_iter()
|
||||
.map(|(demo, info)| {
|
||||
common::BaseDemoInfo {
|
||||
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,
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
}
|
||||
|
||||
// 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",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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| {
|
||||
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 {
|
||||
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)
|
||||
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)
|
||||
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>(())
|
||||
})
|
||||
}).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,12 +311,20 @@ 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 {
|
||||
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);
|
||||
@@ -304,21 +341,30 @@ 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();
|
||||
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 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();
|
||||
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();
|
||||
})
|
||||
.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))
|
||||
|
||||
@@ -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,7 +110,8 @@ 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 {
|
||||
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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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))]
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
pub struct BaseDemoInfo {
|
||||
pub id: String,
|
||||
pub map: String,
|
||||
pub team2_score: i16,
|
||||
pub team3_score: i16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
|
||||
@@ -18,7 +18,7 @@ pub fn demo_list_entry(demo: common::BaseDemoInfo) -> impl leptos::IntoView {
|
||||
view! {
|
||||
<li>
|
||||
<A href=format!("demo/{}/scoreboard", demo.id)>
|
||||
<span>{demo.map} - {demo.id}</span>
|
||||
<span>{demo.map} - {demo.id} - {demo.team2_score}:{demo.team3_score}</span>
|
||||
</A>
|
||||
</li>
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
DROP TABLE processing_status;
|
||||
DROP TABLE demo_player_stats;
|
||||
DROP TABLE demo_players;
|
||||
DROP TABLE demo_teams;
|
||||
DROP TABLE demo_info;
|
||||
|
||||
@@ -27,3 +27,11 @@ CREATE TABLE IF NOT EXISTS demo_player_stats (
|
||||
assists int2 NOT NULL,
|
||||
PRIMARY KEY (demo_id, steam_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS demo_teams (
|
||||
demo_id TEXT NOT NULL,
|
||||
team int2 NOT NULL,
|
||||
end_score int2 NOT NULL,
|
||||
start_name TEXT NOT NULL,
|
||||
PRIMARY KEY (demo_id, team)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user