Change demoid to String and now use uuidV7 for it. Also add timestamps of demo uploads

This commit is contained in:
Lol3rrr
2024-10-10 12:46:41 +02:00
parent 539adecf5d
commit 351b4e016d
17 changed files with 112 additions and 77 deletions

1
Cargo.lock generated
View File

@@ -301,6 +301,7 @@ dependencies = [
"tower-sessions", "tower-sessions",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"uuid",
] ]
[[package]] [[package]]

View File

@@ -34,3 +34,5 @@ memmap2 = { version = "0.9" }
clap = { version = "4.5", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
phf = { version = "0.11", features = ["macros"] } phf = { version = "0.11", features = ["macros"] }
uuid = { version = "1.10", features = ["v7"] }

View File

@@ -3,21 +3,38 @@ use std::path::PathBuf;
use diesel::prelude::*; use diesel::prelude::*;
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
pub mod perround;
pub mod base; pub mod base;
pub mod heatmap; pub mod heatmap;
pub mod perround;
pub trait Analysis { 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(|| { 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(base::BaseAnalysis::new()),
std::sync::Arc::new(perround::PerRoundAnalysis::new()), std::sync::Arc::new(heatmap::HeatmapAnalysis::new()),
] std::sync::Arc::new(perround::PerRoundAnalysis::new()),
}); ]
});
pub async fn poll_next_task( pub async fn poll_next_task(
upload_folder: &std::path::Path, 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) diesel::dsl::delete(crate::schema::analysis_queue::dsl::analysis_queue)
.filter( .filter(
crate::schema::analysis_queue::dsl::demo_id crate::schema::analysis_queue::dsl::demo_id
.eq(final_result.demo_id), .eq(final_result.demo_id.clone()),
) )
.filter( .filter(
crate::schema::analysis_queue::dsl::steam_id crate::schema::analysis_queue::dsl::steam_id
@@ -82,7 +99,7 @@ pub async fn poll_next_task(
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AnalysisInput { pub struct AnalysisInput {
pub steamid: String, pub steamid: String,
pub demoid: i64, pub demoid: String,
pub path: PathBuf, pub path: PathBuf,
} }

View File

@@ -41,14 +41,14 @@ impl Analysis for BaseAnalysis {
.map(|(info, stats)| { .map(|(info, stats)| {
( (
crate::models::DemoPlayer { crate::models::DemoPlayer {
demo_id: input.demoid, demo_id: input.demoid.clone(),
name: info.name, name: info.name,
steam_id: info.steam_id.clone(), steam_id: info.steam_id.clone(),
team: info.team as i16, team: info.team as i16,
color: info.color as i16, color: info.color as i16,
}, },
crate::models::DemoPlayerStats { crate::models::DemoPlayerStats {
demo_id: input.demoid, demo_id: input.demoid.clone(),
steam_id: info.steam_id, steam_id: info.steam_id,
deaths: stats.deaths as i16, deaths: stats.deaths as i16,
kills: stats.kills as i16, kills: stats.kills as i16,
@@ -60,7 +60,7 @@ impl Analysis for BaseAnalysis {
.unzip(); .unzip();
let demo_info = crate::models::DemoInfo { let demo_info = crate::models::DemoInfo {
demo_id: input.demoid, demo_id: input.demoid.clone(),
map: base_result.map, map: base_result.map,
}; };

View File

@@ -38,7 +38,7 @@ impl Analysis for HeatmapAnalysis {
tracing::trace!("HeatMap for Player: {:?}", player); tracing::trace!("HeatMap for Player: {:?}", player);
crate::models::DemoPlayerHeatmap { crate::models::DemoPlayerHeatmap {
demo_id: input.demoid, demo_id: input.demoid.clone(),
steam_id: player, steam_id: player,
data: serde_json::to_string(&heatmap).unwrap(), data: serde_json::to_string(&heatmap).unwrap(),
} }

View File

@@ -18,7 +18,7 @@ impl Analysis for PerRoundAnalysis {
let values: Vec<crate::models::DemoRound> = result.rounds.into_iter().enumerate().map(|(i, r)| { let values: Vec<crate::models::DemoRound> = result.rounds.into_iter().enumerate().map(|(i, r)| {
crate::models::DemoRound { crate::models::DemoRound {
demo_id: input.demoid, demo_id: input.demoid.clone(),
round_number: i as i16, round_number: i as i16,
start_tick: r.start as i64, start_tick: r.start as i64,
end_tick: r.end as i64, end_tick: r.end as i64,

View File

@@ -1,6 +1,7 @@
use crate::UserSession; use crate::UserSession;
use axum::extract::{Path, State}; use axum::extract::{Path, State};
use diesel::prelude::*; use diesel::prelude::*;
use diesel::JoinOnDsl;
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use std::sync::Arc; use std::sync::Arc;
@@ -40,7 +41,9 @@ async fn list(
tracing::info!("SteamID: {:?}", steam_id); tracing::info!("SteamID: {:?}", steam_id);
let query = crate::schema::demos::dsl::demos 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(( .select((
crate::models::Demo::as_select(), crate::models::Demo::as_select(),
crate::models::DemoInfo::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( async fn upload(
State(state): State<Arc<DemoState>>, State(state): State<Arc<DemoState>>,
session: crate::UserSession, 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)); 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) { if !tokio::fs::try_exists(&user_folder).await.unwrap_or(false) {
tokio::fs::create_dir_all(&user_folder).await.unwrap(); tokio::fs::create_dir_all(&user_folder).await.unwrap();
} }
let timestamp_secs = std::time::SystemTime::now() let demo_file_path = user_folder.join(format!("{}.dem", demo_id));
.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));
tokio::fs::write(&demo_file_path, file_content) tokio::fs::write(&demo_file_path, file_content)
.await .await
@@ -102,15 +105,15 @@ async fn upload(
// Turn all of this into a single transaction // Turn all of this into a single transaction
let query = let query =
diesel::dsl::insert_into(crate::schema::demos::dsl::demos).values(crate::models::Demo { diesel::dsl::insert_into(crate::schema::demos::dsl::demos).values(crate::models::NewDemo {
demo_id, demo_id: demo_id.clone(),
steam_id: steam_id.to_string(), steam_id: steam_id.to_string(),
}); });
query.execute(&mut db_con).await.unwrap(); query.execute(&mut db_con).await.unwrap();
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 { .values(crate::models::AddAnalysisTask {
demo_id, demo_id: demo_id.clone(),
steam_id: steam_id.to_string(), steam_id: steam_id.to_string(),
}); });
queue_query.execute(&mut db_con).await.unwrap(); queue_query.execute(&mut db_con).await.unwrap();
@@ -126,7 +129,7 @@ async fn upload(
#[tracing::instrument(skip(session))] #[tracing::instrument(skip(session))]
async fn analyise( async fn analyise(
session: crate::UserSession, session: crate::UserSession,
Path(demo_id): Path<i64>, Path(demo_id): Path<String>,
) -> Result<(), (axum::http::StatusCode, &'static str)> { ) -> Result<(), (axum::http::StatusCode, &'static str)> {
let steam_id = session let steam_id = session
.data() .data()
@@ -139,7 +142,7 @@ async fn analyise(
let query = crate::schema::demos::dsl::demos let query = crate::schema::demos::dsl::demos
.filter(crate::schema::demos::dsl::steam_id.eq(steam_id.to_string())) .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 let result: Vec<_> = query
.load::<crate::models::Demo>(&mut db_con) .load::<crate::models::Demo>(&mut db_con)
.await .await
@@ -165,7 +168,7 @@ async fn analyise(
#[tracing::instrument(skip(_session))] #[tracing::instrument(skip(_session))]
async fn info( async fn info(
_session: UserSession, _session: UserSession,
Path(demo_id): Path<i64>, Path(demo_id): Path<String>,
) -> Result<axum::response::Json<common::DemoInfo>, axum::http::StatusCode> { ) -> Result<axum::response::Json<common::DemoInfo>, axum::http::StatusCode> {
tracing::info!("Get info for Demo: {:?}", demo_id); tracing::info!("Get info for Demo: {:?}", demo_id);
@@ -191,7 +194,7 @@ async fn info(
#[tracing::instrument(skip(session))] #[tracing::instrument(skip(session))]
async fn scoreboard( async fn scoreboard(
session: UserSession, session: UserSession,
Path(demo_id): Path<i64>, Path(demo_id): Path<String>,
) -> Result<axum::response::Json<common::demo_analysis::ScoreBoard>, axum::http::StatusCode> { ) -> Result<axum::response::Json<common::demo_analysis::ScoreBoard>, axum::http::StatusCode> {
let query = crate::schema::demo_players::dsl::demo_players let query = crate::schema::demo_players::dsl::demo_players
.inner_join( .inner_join(
@@ -251,13 +254,13 @@ async fn scoreboard(
#[tracing::instrument(skip(session))] #[tracing::instrument(skip(session))]
async fn heatmap( async fn heatmap(
session: UserSession, session: UserSession,
Path(demo_id): Path<i64>, 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; use base64::prelude::Engine;
let mut db_con = crate::db_connection().await; 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 { let demo_info: crate::models::DemoInfo = match demo_info_query.first(&mut db_con).await {
Ok(i) => i, Ok(i) => i,
Err(e) => { Err(e) => {
@@ -309,9 +312,9 @@ async fn heatmap(
#[tracing::instrument(skip(session))] #[tracing::instrument(skip(session))]
async fn perround( async fn perround(
session: UserSession, session: UserSession,
Path(demo_id): Path<i64>, Path(demo_id): Path<String>,
) -> Result<axum::response::Json<Vec<common::demo_analysis::DemoRound>>, axum::http::StatusCode> { ) -> 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 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 mut db_con = crate::db_connection().await;

View File

@@ -66,8 +66,8 @@ pub async fn run_api(
"/api/", "/api/",
crate::api::router(crate::api::RouterConfig { crate::api::router(crate::api::RouterConfig {
steam_api_key: steam_api_key.into(), steam_api_key: steam_api_key.into(),
// steam_callback_base_url: "http://localhost:3000".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://192.168.0.156:3000".into(),
steam_callback_path: "/api/steam/callback".into(), steam_callback_path: "/api/steam/callback".into(),
upload_dir: upload_folder.clone(), 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(); let mut store_result_fns = Vec::new();
for analysis in analysis::ANALYSIS_METHODS.iter().map(|a| a.clone()) { for analysis in analysis::ANALYSIS_METHODS.iter().map(|a| a.clone()) {

View File

@@ -9,12 +9,21 @@ pub struct Session {
pub expiry_date: String, 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(table_name = crate::schema::demos)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Demo { pub struct Demo {
pub steam_id: String, pub steam_id: String,
pub demo_id: i64, pub demo_id: String,
pub uploaded_at: diesel::data_types::PgTimestamp
} }
#[derive(Queryable, Selectable, Insertable, Debug)] #[derive(Queryable, Selectable, Insertable, Debug)]
@@ -29,7 +38,7 @@ pub struct User {
#[diesel(table_name = crate::schema::demo_info)] #[diesel(table_name = crate::schema::demo_info)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoInfo { pub struct DemoInfo {
pub demo_id: i64, pub demo_id: String,
pub map: String, pub map: String,
} }
@@ -37,7 +46,7 @@ pub struct DemoInfo {
#[diesel(table_name = crate::schema::demo_players)] #[diesel(table_name = crate::schema::demo_players)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoPlayer { pub struct DemoPlayer {
pub demo_id: i64, pub demo_id: String,
pub steam_id: String, pub steam_id: String,
pub name: String, pub name: String,
pub team: i16, pub team: i16,
@@ -48,7 +57,7 @@ pub struct DemoPlayer {
#[diesel(table_name = crate::schema::demo_player_stats)] #[diesel(table_name = crate::schema::demo_player_stats)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoPlayerStats { pub struct DemoPlayerStats {
pub demo_id: i64, pub demo_id: String,
pub steam_id: String, pub steam_id: String,
pub kills: i16, pub kills: i16,
pub deaths: i16, pub deaths: i16,
@@ -60,7 +69,7 @@ pub struct DemoPlayerStats {
#[diesel(table_name = crate::schema::processing_status)] #[diesel(table_name = crate::schema::processing_status)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct ProcessingStatus { pub struct ProcessingStatus {
pub demo_id: i64, pub demo_id: String,
pub info: i16, pub info: i16,
} }
@@ -68,7 +77,7 @@ pub struct ProcessingStatus {
#[diesel(table_name = crate::schema::analysis_queue)] #[diesel(table_name = crate::schema::analysis_queue)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct AddAnalysisTask { pub struct AddAnalysisTask {
pub demo_id: i64, pub demo_id: String,
pub steam_id: String, pub steam_id: String,
} }
@@ -76,7 +85,7 @@ pub struct AddAnalysisTask {
#[diesel(table_name = crate::schema::analysis_queue)] #[diesel(table_name = crate::schema::analysis_queue)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct AnalysisTask { pub struct AnalysisTask {
pub demo_id: i64, pub demo_id: String,
pub steam_id: String, pub steam_id: String,
} }
@@ -84,7 +93,7 @@ pub struct AnalysisTask {
#[diesel(table_name = crate::schema::demo_heatmaps)] #[diesel(table_name = crate::schema::demo_heatmaps)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoPlayerHeatmap { pub struct DemoPlayerHeatmap {
pub demo_id: i64, pub demo_id: String,
pub steam_id: String, pub steam_id: String,
pub data: String, pub data: String,
} }
@@ -93,7 +102,7 @@ pub struct DemoPlayerHeatmap {
#[diesel(table_name = crate::schema::demo_round)] #[diesel(table_name = crate::schema::demo_round)]
#[diesel(check_for_backend(diesel::pg::Pg))] #[diesel(check_for_backend(diesel::pg::Pg))]
pub struct DemoRound { pub struct DemoRound {
pub demo_id: i64, pub demo_id: String,
pub round_number: i16, pub round_number: i16,
pub start_tick: i64, pub start_tick: i64,
pub end_tick: i64, pub end_tick: i64,

View File

@@ -2,7 +2,7 @@
diesel::table! { diesel::table! {
analysis_queue (demo_id) { analysis_queue (demo_id) {
demo_id -> Int8, demo_id -> Text,
steam_id -> Text, steam_id -> Text,
created_at -> Timestamp, created_at -> Timestamp,
} }
@@ -10,7 +10,7 @@ diesel::table! {
diesel::table! { diesel::table! {
demo_heatmaps (demo_id, steam_id) { demo_heatmaps (demo_id, steam_id) {
demo_id -> Int8, demo_id -> Text,
steam_id -> Text, steam_id -> Text,
data -> Text, data -> Text,
} }
@@ -18,14 +18,14 @@ diesel::table! {
diesel::table! { diesel::table! {
demo_info (demo_id) { demo_info (demo_id) {
demo_id -> Int8, demo_id -> Text,
map -> Text, map -> Text,
} }
} }
diesel::table! { diesel::table! {
demo_player_stats (demo_id, steam_id) { demo_player_stats (demo_id, steam_id) {
demo_id -> Int8, demo_id -> Text,
steam_id -> Text, steam_id -> Text,
kills -> Int2, kills -> Int2,
deaths -> Int2, deaths -> Int2,
@@ -36,7 +36,7 @@ diesel::table! {
diesel::table! { diesel::table! {
demo_players (demo_id, steam_id) { demo_players (demo_id, steam_id) {
demo_id -> Int8, demo_id -> Text,
steam_id -> Text, steam_id -> Text,
name -> Text, name -> Text,
team -> Int2, team -> Int2,
@@ -46,7 +46,7 @@ diesel::table! {
diesel::table! { diesel::table! {
demo_round (demo_id, round_number) { demo_round (demo_id, round_number) {
demo_id -> Int8, demo_id -> Text,
round_number -> Int2, round_number -> Int2,
start_tick -> Int8, start_tick -> Int8,
end_tick -> Int8, end_tick -> Int8,
@@ -56,15 +56,16 @@ diesel::table! {
} }
diesel::table! { diesel::table! {
demos (demo_id) { demos (steam_id, demo_id) {
steam_id -> Text, steam_id -> Text,
demo_id -> Int8, demo_id -> Text,
uploaded_at -> Timestamptz,
} }
} }
diesel::table! { diesel::table! {
processing_status (demo_id) { processing_status (demo_id) {
demo_id -> Int8, demo_id -> Text,
info -> Int2, info -> Int2,
} }
} }
@@ -77,6 +78,13 @@ diesel::table! {
} }
} }
diesel::table! {
user_demos (steam_id, demo_id) {
steam_id -> Text,
demo_id -> Text,
}
}
diesel::table! { diesel::table! {
users (steamid) { users (steamid) {
steamid -> Text, 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!( diesel::allow_tables_to_appear_in_same_query!(
analysis_queue, analysis_queue,
demo_heatmaps, demo_heatmaps,
@@ -102,5 +102,6 @@ diesel::allow_tables_to_appear_in_same_query!(
demos, demos,
processing_status, processing_status,
sessions, sessions,
user_demos,
users, users,
); );

View File

@@ -1,6 +1,6 @@
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct BaseDemoInfo { pub struct BaseDemoInfo {
pub id: i64, pub id: String,
pub map: String, pub map: String,
} }
@@ -12,7 +12,7 @@ pub struct UserStatus {
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct DemoInfo { pub struct DemoInfo {
pub id: i64, pub id: String,
pub map: String, pub map: String,
} }

View File

@@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql` -- This file should undo anything in `up.sql`
DROP TABLE demos DROP TABLE demos;

View File

@@ -1,5 +1,7 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS demos ( CREATE TABLE IF NOT EXISTS demos (
steam_id TEXT NOT NULL, steam_id TEXT NOT NULL,
demo_id bigint NOT NULL PRIMARY KEY demo_id TEXT NOT NULL,
) uploaded_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (steam_id, demo_id)
);

View File

@@ -1,16 +1,16 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS processing_status ( CREATE TABLE IF NOT EXISTS processing_status (
demo_id bigint PRIMARY KEY REFERENCES demos(demo_id), demo_id TEXT PRIMARY KEY,
info int2 NOT NULL -- the processing_status of the basic demo info info int2 NOT NULL -- the processing_status of the basic demo info
); );
CREATE TABLE IF NOT EXISTS demo_info ( CREATE TABLE IF NOT EXISTS demo_info (
demo_id bigint PRIMARY KEY REFERENCES demos(demo_id), demo_id TEXT PRIMARY KEY,
map TEXT NOT NULL map TEXT NOT NULL
); );
CREATE TABLE IF NOT EXISTS demo_players ( CREATE TABLE IF NOT EXISTS demo_players (
demo_id bigint REFERENCES demo_info(demo_id), demo_id TEXT NOT NULL,
steam_id TEXT NOT NULL, steam_id TEXT NOT NULL,
name TEXT NOT NULL, name TEXT NOT NULL,
team int2 NOT NULL, team int2 NOT NULL,
@@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS demo_players (
); );
CREATE TABLE IF NOT EXISTS demo_player_stats ( CREATE TABLE IF NOT EXISTS demo_player_stats (
demo_id bigint REFERENCES demo_info(demo_id), demo_id TEXT NOT NULL,
steam_id TEXT NOT NULL, steam_id TEXT NOT NULL,
kills int2 NOT NULL, kills int2 NOT NULL,
deaths int2 NOT NULL, deaths int2 NOT NULL,

View File

@@ -1,6 +1,6 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS ANALYSIS_QUEUE ( CREATE TABLE IF NOT EXISTS ANALYSIS_QUEUE (
demo_id bigint PRIMARY KEY REFERENCES demos(demo_id), demo_id TEXT PRIMARY KEY,
steam_id Text NOT NULL, steam_id Text NOT NULL,
created_at timestamp NOT NULL default current_timestamp created_at timestamp NOT NULL default current_timestamp
); );

View File

@@ -1,6 +1,6 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS demo_heatmaps ( CREATE TABLE IF NOT EXISTS demo_heatmaps (
demo_id bigint REFERENCES demo_info(demo_id), demo_id TEXT NOT NULL,
steam_id TEXT NOT NULL, steam_id TEXT NOT NULL,
data TEXT NOT NULL, data TEXT NOT NULL,
PRIMARY KEY (demo_id, steam_id) PRIMARY KEY (demo_id, steam_id)

View File

@@ -1,6 +1,6 @@
-- Your SQL goes here -- Your SQL goes here
CREATE TABLE IF NOT EXISTS demo_round ( CREATE TABLE IF NOT EXISTS demo_round (
demo_id bigint REFERENCES demo_info(demo_id), demo_id TEXT NOT NULL,
round_number int2 NOT NULL, round_number int2 NOT NULL,
start_tick bigint NOT NULL, start_tick bigint NOT NULL,
end_tick bigint NOT NULL, end_tick bigint NOT NULL,