From 85dcf3ba2fd0cf907610625399db691b274118bb Mon Sep 17 00:00:00 2001 From: Ilion Beyst Date: Sun, 2 Jan 2022 16:14:03 +0100 Subject: store matches in database --- planetwars-server/src/routes/matches.rs | 63 +++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 7 deletions(-) (limited to 'planetwars-server/src/routes') diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs index 4a556af..f2c5186 100644 --- a/planetwars-server/src/routes/matches.rs +++ b/planetwars-server/src/routes/matches.rs @@ -1,14 +1,14 @@ use std::path::PathBuf; -use axum::Json; +use axum::{extract::Extension, Json}; use hyper::StatusCode; use planetwars_matchrunner::{run_match, MatchConfig, MatchPlayer}; use rand::{distributions::Alphanumeric, Rng}; use serde::{Deserialize, Serialize}; use crate::{ - db::{bots, users::User}, - DatabaseConnection, BOTS_DIR, MAPS_DIR, MATCHES_DIR, + db::{bots, matches, users::User}, + ConnectionPool, DatabaseConnection, BOTS_DIR, MAPS_DIR, MATCHES_DIR, }; #[derive(Serialize, Deserialize, Debug)] @@ -18,10 +18,11 @@ pub struct MatchParams { } pub async fn play_match( - user: User, - conn: DatabaseConnection, + _user: User, + Extension(pool): Extension, Json(params): Json, ) -> Result<(), StatusCode> { + let conn = pool.get().await.expect("could not get database connection"); let map_path = PathBuf::from(MAPS_DIR).join("hex.json"); let slug: String = rand::thread_rng() @@ -32,6 +33,7 @@ pub async fn play_match( let log_path = PathBuf::from(MATCHES_DIR).join(&format!("{}.log", slug)); let mut players = Vec::new(); + let mut bot_ids = Vec::new(); for bot_name in params.players { let bot = bots::find_bot(bot_name, &conn).map_err(|_| StatusCode::BAD_REQUEST)?; let code_bundle = @@ -49,19 +51,66 @@ pub async fn play_match( // TODO: this is an user error, should ideally be handled before we get here .ok_or_else(|| StatusCode::INTERNAL_SERVER_ERROR)?, }); + + bot_ids.push(matches::MatchPlayerData { bot_id: bot.id }); } let match_config = MatchConfig { map_name: "hex".to_string(), map_path, log_path: log_path.clone(), - players, + players: players, }; - tokio::spawn(run_match(match_config)); + tokio::spawn(run_match_task(match_config, bot_ids, pool.clone())); Ok(()) } +async fn run_match_task( + config: MatchConfig, + 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, + }; + + run_match(config).await; + let conn = pool.get().await.expect("could not get database connection"); + matches::create_match(&match_data, &match_players, &conn).expect("could not create match"); +} + +#[derive(Serialize, Deserialize)] +pub struct ApiMatch { + id: i32, + timestamp: chrono::NaiveDateTime, + players: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct ApiMatchPlayer { + bot_id: i32, +} + +pub async fn list_matches(conn: DatabaseConnection) -> Result>, StatusCode> { + matches::list_matches(&conn) + .map_err(|_| StatusCode::BAD_REQUEST) + .map(|matches| Json(matches.into_iter().map(match_data_to_api).collect())) +} + +fn match_data_to_api(data: matches::MatchData) -> ApiMatch { + ApiMatch { + id: data.base.id, + timestamp: data.base.created_at, + players: data + .match_players + .iter() + .map(|p| ApiMatchPlayer { bot_id: p.bot_id }) + .collect(), + } +} + // TODO: this is duplicated from planetwars-cli // clean this up and move to matchrunner crate #[derive(Serialize, Deserialize)] -- cgit v1.2.3