diff --git a/planetwars-server/src/db/matches.rs b/planetwars-server/src/db/matches.rs index 85f0631..9bf00db 100644 --- a/planetwars-server/src/db/matches.rs +++ b/planetwars-server/src/db/matches.rs @@ -1,5 +1,5 @@ use chrono::NaiveDateTime; -use diesel::{BelongingToDsl, RunQueryDsl}; +use diesel::{BelongingToDsl, QueryDsl, RunQueryDsl}; use diesel::{Connection, GroupedBy, PgConnection, QueryResult}; use crate::schema::{match_players, matches}; @@ -95,3 +95,22 @@ pub fn list_matches(conn: &PgConnection) -> QueryResult> { Ok(res) }) } + +pub fn find_match(id: i32, conn: &PgConnection) -> QueryResult { + conn.transaction(|| { + let match_base = matches::table.find(id).get_result::(conn)?; + + let match_players = MatchPlayer::belonging_to(&match_base).load::(conn)?; + + let res = MatchData { + base: match_base, + match_players, + }; + + Ok(res) + }) +} + +pub fn find_mach_base(id: i32, conn: &PgConnection) -> QueryResult { + matches::table.find(id).get_result::(conn) +} diff --git a/planetwars-server/src/lib.rs b/planetwars-server/src/lib.rs index 7eaa5a0..754d062 100644 --- a/planetwars-server/src/lib.rs +++ b/planetwars-server/src/lib.rs @@ -52,6 +52,7 @@ pub async fn api() -> Router { "/matches", get(routes::matches::list_matches).post(routes::matches::play_match), ) + .route("/matches/:match_id", get(routes::matches::get_match_log)) .layer(AddExtensionLayer::new(pool)); api } diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs index f2c5186..4dfd44e 100644 --- a/planetwars-server/src/routes/matches.rs +++ b/planetwars-server/src/routes/matches.rs @@ -1,6 +1,9 @@ -use std::path::PathBuf; +use std::{io::Read, path::PathBuf}; -use axum::{extract::Extension, Json}; +use axum::{ + extract::{Extension, Path}, + Json, +}; use hyper::StatusCode; use planetwars_matchrunner::{run_match, MatchConfig, MatchPlayer}; use rand::{distributions::Alphanumeric, Rng}; @@ -30,7 +33,7 @@ pub async fn play_match( .take(16) .map(char::from) .collect(); - let log_path = PathBuf::from(MATCHES_DIR).join(&format!("{}.log", slug)); + let log_file_name = format!("{}.log", slug); let mut players = Vec::new(); let mut bot_ids = Vec::new(); @@ -58,22 +61,27 @@ pub async fn play_match( let match_config = MatchConfig { map_name: "hex".to_string(), map_path, - log_path: log_path.clone(), + log_path: PathBuf::from(MATCHES_DIR).join(&log_file_name), players: players, }; - tokio::spawn(run_match_task(match_config, bot_ids, pool.clone())); + tokio::spawn(run_match_task( + match_config, + log_file_name, + bot_ids, + pool.clone(), + )); Ok(()) } async fn run_match_task( config: MatchConfig, + log_file_name: String, match_players: Vec, pool: ConnectionPool, ) { - let log_path = config.log_path.as_os_str().to_str().unwrap().to_string(); let match_data = matches::NewMatch { - log_path: &log_path, + log_path: &log_file_name, }; run_match(config).await; @@ -119,3 +127,13 @@ pub struct BotConfig { pub run_command: String, pub build_command: Option, } + +pub async fn get_match_log( + Path(match_id): Path, + conn: DatabaseConnection, +) -> Result, StatusCode> { + let match_base = matches::find_mach_base(match_id, &conn).map_err(|_| StatusCode::NOT_FOUND)?; + let log_path = PathBuf::from(MATCHES_DIR).join(&match_base.log_path); + let log_contents = std::fs::read(log_path).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + Ok(log_contents) +}