Change demoid to String and now use uuidV7 for it. Also add timestamps of demo uploads
This commit is contained in:
@@ -34,3 +34,5 @@ memmap2 = { version = "0.9" }
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
|
||||
phf = { version = "0.11", features = ["macros"] }
|
||||
|
||||
uuid = { version = "1.10", features = ["v7"] }
|
||||
|
||||
@@ -3,21 +3,38 @@ use std::path::PathBuf;
|
||||
use diesel::prelude::*;
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
pub mod perround;
|
||||
pub mod base;
|
||||
pub mod heatmap;
|
||||
pub mod perround;
|
||||
|
||||
pub trait 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>, ()>;
|
||||
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,
|
||||
>,
|
||||
(),
|
||||
>;
|
||||
}
|
||||
|
||||
pub static ANALYSIS_METHODS: std::sync::LazyLock<[std::sync::Arc<dyn Analysis + Send + Sync>; 3]> = std::sync::LazyLock::new(|| {
|
||||
[
|
||||
std::sync::Arc::new(base::BaseAnalysis::new()),
|
||||
std::sync::Arc::new(heatmap::HeatmapAnalysis::new()),
|
||||
std::sync::Arc::new(perround::PerRoundAnalysis::new()),
|
||||
]
|
||||
});
|
||||
pub static ANALYSIS_METHODS: std::sync::LazyLock<[std::sync::Arc<dyn Analysis + Send + Sync>; 3]> =
|
||||
std::sync::LazyLock::new(|| {
|
||||
[
|
||||
std::sync::Arc::new(base::BaseAnalysis::new()),
|
||||
std::sync::Arc::new(heatmap::HeatmapAnalysis::new()),
|
||||
std::sync::Arc::new(perround::PerRoundAnalysis::new()),
|
||||
]
|
||||
});
|
||||
|
||||
pub async fn poll_next_task(
|
||||
upload_folder: &std::path::Path,
|
||||
@@ -45,7 +62,7 @@ pub async fn poll_next_task(
|
||||
diesel::dsl::delete(crate::schema::analysis_queue::dsl::analysis_queue)
|
||||
.filter(
|
||||
crate::schema::analysis_queue::dsl::demo_id
|
||||
.eq(final_result.demo_id),
|
||||
.eq(final_result.demo_id.clone()),
|
||||
)
|
||||
.filter(
|
||||
crate::schema::analysis_queue::dsl::steam_id
|
||||
@@ -82,7 +99,7 @@ pub async fn poll_next_task(
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AnalysisInput {
|
||||
pub steamid: String,
|
||||
pub demoid: i64,
|
||||
pub demoid: String,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ impl Analysis for BaseAnalysis {
|
||||
.map(|(info, stats)| {
|
||||
(
|
||||
crate::models::DemoPlayer {
|
||||
demo_id: input.demoid,
|
||||
demo_id: input.demoid.clone(),
|
||||
name: info.name,
|
||||
steam_id: info.steam_id.clone(),
|
||||
team: info.team as i16,
|
||||
color: info.color as i16,
|
||||
},
|
||||
crate::models::DemoPlayerStats {
|
||||
demo_id: input.demoid,
|
||||
demo_id: input.demoid.clone(),
|
||||
steam_id: info.steam_id,
|
||||
deaths: stats.deaths as i16,
|
||||
kills: stats.kills as i16,
|
||||
@@ -60,7 +60,7 @@ impl Analysis for BaseAnalysis {
|
||||
.unzip();
|
||||
|
||||
let demo_info = crate::models::DemoInfo {
|
||||
demo_id: input.demoid,
|
||||
demo_id: input.demoid.clone(),
|
||||
map: base_result.map,
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ impl Analysis for HeatmapAnalysis {
|
||||
tracing::trace!("HeatMap for Player: {:?}", player);
|
||||
|
||||
crate::models::DemoPlayerHeatmap {
|
||||
demo_id: input.demoid,
|
||||
demo_id: input.demoid.clone(),
|
||||
steam_id: player,
|
||||
data: serde_json::to_string(&heatmap).unwrap(),
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ impl Analysis for PerRoundAnalysis {
|
||||
|
||||
let values: Vec<crate::models::DemoRound> = result.rounds.into_iter().enumerate().map(|(i, r)| {
|
||||
crate::models::DemoRound {
|
||||
demo_id: input.demoid,
|
||||
demo_id: input.demoid.clone(),
|
||||
round_number: i as i16,
|
||||
start_tick: r.start as i64,
|
||||
end_tick: r.end as i64,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::UserSession;
|
||||
use axum::extract::{Path, State};
|
||||
use diesel::prelude::*;
|
||||
use diesel::JoinOnDsl;
|
||||
use diesel_async::RunQueryDsl;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -40,7 +41,9 @@ async fn list(
|
||||
tracing::info!("SteamID: {:?}", steam_id);
|
||||
|
||||
let query = crate::schema::demos::dsl::demos
|
||||
.inner_join(crate::schema::demo_info::dsl::demo_info)
|
||||
.inner_join(crate::schema::demo_info::table.on(
|
||||
crate::schema::demos::dsl::demo_id.eq(crate::schema::demo_info::dsl::demo_id),
|
||||
))
|
||||
.select((
|
||||
crate::models::Demo::as_select(),
|
||||
crate::models::DemoInfo::as_select(),
|
||||
@@ -60,7 +63,7 @@ async fn list(
|
||||
))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(state, session))]
|
||||
#[tracing::instrument(skip(state, session, form))]
|
||||
async fn upload(
|
||||
State(state): State<Arc<DemoState>>,
|
||||
session: crate::UserSession,
|
||||
@@ -81,17 +84,17 @@ async fn upload(
|
||||
}
|
||||
};
|
||||
|
||||
let raw_demo_id = uuid::Uuid::now_v7();
|
||||
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();
|
||||
}
|
||||
|
||||
let timestamp_secs = std::time::SystemTime::now()
|
||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
let demo_id = timestamp_secs as i64;
|
||||
let demo_file_path = user_folder.join(format!("{}.dem", timestamp_secs));
|
||||
let demo_file_path = user_folder.join(format!("{}.dem", demo_id));
|
||||
|
||||
tokio::fs::write(&demo_file_path, file_content)
|
||||
.await
|
||||
@@ -102,15 +105,15 @@ async fn upload(
|
||||
// Turn all of this into a single transaction
|
||||
|
||||
let query =
|
||||
diesel::dsl::insert_into(crate::schema::demos::dsl::demos).values(crate::models::Demo {
|
||||
demo_id,
|
||||
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(&mut db_con).await.unwrap();
|
||||
|
||||
let queue_query = diesel::dsl::insert_into(crate::schema::analysis_queue::dsl::analysis_queue)
|
||||
.values(crate::models::AddAnalysisTask {
|
||||
demo_id,
|
||||
demo_id: demo_id.clone(),
|
||||
steam_id: steam_id.to_string(),
|
||||
});
|
||||
queue_query.execute(&mut db_con).await.unwrap();
|
||||
@@ -126,7 +129,7 @@ async fn upload(
|
||||
#[tracing::instrument(skip(session))]
|
||||
async fn analyise(
|
||||
session: crate::UserSession,
|
||||
Path(demo_id): Path<i64>,
|
||||
Path(demo_id): Path<String>,
|
||||
) -> Result<(), (axum::http::StatusCode, &'static str)> {
|
||||
let steam_id = session
|
||||
.data()
|
||||
@@ -139,7 +142,7 @@ async fn analyise(
|
||||
|
||||
let query = crate::schema::demos::dsl::demos
|
||||
.filter(crate::schema::demos::dsl::steam_id.eq(steam_id.to_string()))
|
||||
.filter(crate::schema::demos::dsl::demo_id.eq(demo_id));
|
||||
.filter(crate::schema::demos::dsl::demo_id.eq(demo_id.clone()));
|
||||
let result: Vec<_> = query
|
||||
.load::<crate::models::Demo>(&mut db_con)
|
||||
.await
|
||||
@@ -165,7 +168,7 @@ async fn analyise(
|
||||
#[tracing::instrument(skip(_session))]
|
||||
async fn info(
|
||||
_session: UserSession,
|
||||
Path(demo_id): Path<i64>,
|
||||
Path(demo_id): Path<String>,
|
||||
) -> Result<axum::response::Json<common::DemoInfo>, axum::http::StatusCode> {
|
||||
tracing::info!("Get info for Demo: {:?}", demo_id);
|
||||
|
||||
@@ -191,7 +194,7 @@ async fn info(
|
||||
#[tracing::instrument(skip(session))]
|
||||
async fn scoreboard(
|
||||
session: UserSession,
|
||||
Path(demo_id): Path<i64>,
|
||||
Path(demo_id): Path<String>,
|
||||
) -> Result<axum::response::Json<common::demo_analysis::ScoreBoard>, axum::http::StatusCode> {
|
||||
let query = crate::schema::demo_players::dsl::demo_players
|
||||
.inner_join(
|
||||
@@ -251,13 +254,13 @@ async fn scoreboard(
|
||||
#[tracing::instrument(skip(session))]
|
||||
async fn heatmap(
|
||||
session: UserSession,
|
||||
Path(demo_id): Path<i64>,
|
||||
Path(demo_id): Path<String>,
|
||||
) -> 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));
|
||||
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) => {
|
||||
@@ -309,9 +312,9 @@ async fn heatmap(
|
||||
#[tracing::instrument(skip(session))]
|
||||
async fn perround(
|
||||
session: UserSession,
|
||||
Path(demo_id): Path<i64>,
|
||||
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));
|
||||
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;
|
||||
|
||||
@@ -66,8 +66,8 @@ pub async fn run_api(
|
||||
"/api/",
|
||||
crate::api::router(crate::api::RouterConfig {
|
||||
steam_api_key: steam_api_key.into(),
|
||||
// steam_callback_base_url: "http://localhost:3000".into(),
|
||||
steam_callback_base_url: "http://192.168.0.156:3000".into(),
|
||||
steam_callback_base_url: "http://localhost:3000".into(),
|
||||
// steam_callback_base_url: "http://192.168.0.156:3000".into(),
|
||||
steam_callback_path: "/api/steam/callback".into(),
|
||||
upload_dir: upload_folder.clone(),
|
||||
}),
|
||||
@@ -99,7 +99,7 @@ pub async fn run_analysis(upload_folder: impl Into<std::path::PathBuf>) {
|
||||
}
|
||||
};
|
||||
|
||||
let demo_id = input.demoid;
|
||||
let demo_id = input.demoid.clone();
|
||||
|
||||
let mut store_result_fns = Vec::new();
|
||||
for analysis in analysis::ANALYSIS_METHODS.iter().map(|a| a.clone()) {
|
||||
|
||||
@@ -9,12 +9,21 @@ pub struct Session {
|
||||
pub expiry_date: String,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Insertable, Debug)]
|
||||
#[derive(Insertable, Debug)]
|
||||
#[diesel(table_name = crate::schema::demos)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct NewDemo {
|
||||
pub steam_id: String,
|
||||
pub demo_id: String,
|
||||
}
|
||||
|
||||
#[derive(Selectable, Queryable, Debug)]
|
||||
#[diesel(table_name = crate::schema::demos)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Demo {
|
||||
pub steam_id: String,
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub uploaded_at: diesel::data_types::PgTimestamp
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Insertable, Debug)]
|
||||
@@ -29,7 +38,7 @@ pub struct User {
|
||||
#[diesel(table_name = crate::schema::demo_info)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct DemoInfo {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub map: String,
|
||||
}
|
||||
|
||||
@@ -37,7 +46,7 @@ pub struct DemoInfo {
|
||||
#[diesel(table_name = crate::schema::demo_players)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct DemoPlayer {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub steam_id: String,
|
||||
pub name: String,
|
||||
pub team: i16,
|
||||
@@ -48,7 +57,7 @@ pub struct DemoPlayer {
|
||||
#[diesel(table_name = crate::schema::demo_player_stats)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct DemoPlayerStats {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub steam_id: String,
|
||||
pub kills: i16,
|
||||
pub deaths: i16,
|
||||
@@ -60,7 +69,7 @@ pub struct DemoPlayerStats {
|
||||
#[diesel(table_name = crate::schema::processing_status)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct ProcessingStatus {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub info: i16,
|
||||
}
|
||||
|
||||
@@ -68,7 +77,7 @@ pub struct ProcessingStatus {
|
||||
#[diesel(table_name = crate::schema::analysis_queue)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct AddAnalysisTask {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub steam_id: String,
|
||||
}
|
||||
|
||||
@@ -76,7 +85,7 @@ pub struct AddAnalysisTask {
|
||||
#[diesel(table_name = crate::schema::analysis_queue)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct AnalysisTask {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub steam_id: String,
|
||||
}
|
||||
|
||||
@@ -84,7 +93,7 @@ pub struct AnalysisTask {
|
||||
#[diesel(table_name = crate::schema::demo_heatmaps)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct DemoPlayerHeatmap {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub steam_id: String,
|
||||
pub data: String,
|
||||
}
|
||||
@@ -93,7 +102,7 @@ pub struct DemoPlayerHeatmap {
|
||||
#[diesel(table_name = crate::schema::demo_round)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct DemoRound {
|
||||
pub demo_id: i64,
|
||||
pub demo_id: String,
|
||||
pub round_number: i16,
|
||||
pub start_tick: i64,
|
||||
pub end_tick: i64,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
diesel::table! {
|
||||
analysis_queue (demo_id) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
steam_id -> Text,
|
||||
created_at -> Timestamp,
|
||||
}
|
||||
@@ -10,7 +10,7 @@ diesel::table! {
|
||||
|
||||
diesel::table! {
|
||||
demo_heatmaps (demo_id, steam_id) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
steam_id -> Text,
|
||||
data -> Text,
|
||||
}
|
||||
@@ -18,14 +18,14 @@ diesel::table! {
|
||||
|
||||
diesel::table! {
|
||||
demo_info (demo_id) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
map -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
demo_player_stats (demo_id, steam_id) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
steam_id -> Text,
|
||||
kills -> Int2,
|
||||
deaths -> Int2,
|
||||
@@ -36,7 +36,7 @@ diesel::table! {
|
||||
|
||||
diesel::table! {
|
||||
demo_players (demo_id, steam_id) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
steam_id -> Text,
|
||||
name -> Text,
|
||||
team -> Int2,
|
||||
@@ -46,7 +46,7 @@ diesel::table! {
|
||||
|
||||
diesel::table! {
|
||||
demo_round (demo_id, round_number) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
round_number -> Int2,
|
||||
start_tick -> Int8,
|
||||
end_tick -> Int8,
|
||||
@@ -56,15 +56,16 @@ diesel::table! {
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
demos (demo_id) {
|
||||
demos (steam_id, demo_id) {
|
||||
steam_id -> Text,
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
uploaded_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
processing_status (demo_id) {
|
||||
demo_id -> Int8,
|
||||
demo_id -> Text,
|
||||
info -> Int2,
|
||||
}
|
||||
}
|
||||
@@ -77,6 +78,13 @@ diesel::table! {
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
user_demos (steam_id, demo_id) {
|
||||
steam_id -> Text,
|
||||
demo_id -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
users (steamid) {
|
||||
steamid -> Text,
|
||||
@@ -84,14 +92,6 @@ diesel::table! {
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(analysis_queue -> demos (demo_id));
|
||||
diesel::joinable!(demo_heatmaps -> demo_info (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!(demo_round -> demo_info (demo_id));
|
||||
diesel::joinable!(processing_status -> demos (demo_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
analysis_queue,
|
||||
demo_heatmaps,
|
||||
@@ -102,5 +102,6 @@ diesel::allow_tables_to_appear_in_same_query!(
|
||||
demos,
|
||||
processing_status,
|
||||
sessions,
|
||||
user_demos,
|
||||
users,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user