From 63695c299c023bd61d2a45cc22e509ac3717ec8d Mon Sep 17 00:00:00 2001 From: Ilion Beyst Date: Fri, 11 Mar 2022 00:41:18 +0100 Subject: add information about match players to match API object --- planetwars-server/src/db/matches.rs | 55 +++++++++++++++++++++++++++------ planetwars-server/src/routes/demo.rs | 22 +++++++++++-- planetwars-server/src/routes/matches.rs | 14 ++++++--- 3 files changed, 74 insertions(+), 17 deletions(-) (limited to 'planetwars-server/src') diff --git a/planetwars-server/src/db/matches.rs b/planetwars-server/src/db/matches.rs index d649189..24f3c27 100644 --- a/planetwars-server/src/db/matches.rs +++ b/planetwars-server/src/db/matches.rs @@ -1,9 +1,14 @@ pub use crate::db_types::MatchState; use chrono::NaiveDateTime; -use diesel::{BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl}; +use diesel::associations::BelongsTo; +use diesel::{ + BelongingToDsl, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl, RunQueryDsl, +}; use diesel::{Connection, GroupedBy, PgConnection, QueryResult}; -use crate::schema::{match_players, matches}; +use crate::schema::{bots, code_bundles, match_players, matches}; + +use super::bots::{Bot, CodeBundle}; #[derive(Insertable)] #[table_name = "matches"] @@ -32,7 +37,7 @@ pub struct MatchBase { pub created_at: NaiveDateTime, } -#[derive(Queryable, Identifiable, Associations)] +#[derive(Queryable, Identifiable, Associations, Clone)] #[primary_key(match_id, player_id)] #[belongs_to(MatchBase, foreign_key = "match_id")] pub struct MatchPlayer { @@ -81,18 +86,20 @@ pub struct MatchData { pub match_players: Vec, } -pub fn list_matches(conn: &PgConnection) -> QueryResult> { +pub fn list_matches(conn: &PgConnection) -> QueryResult> { conn.transaction(|| { let matches = matches::table.get_results::(conn)?; let match_players = MatchPlayer::belonging_to(&matches) - .load::(conn)? + .inner_join(code_bundles::table) + .left_join(bots::table.on(code_bundles::bot_id.eq(bots::id.nullable()))) + .load::(conn)? .grouped_by(&matches); let res = matches .into_iter() .zip(match_players.into_iter()) - .map(|(base, players)| MatchData { + .map(|(base, players)| FullMatchData { base, match_players: players.into_iter().collect(), }) @@ -102,13 +109,43 @@ pub fn list_matches(conn: &PgConnection) -> QueryResult> { }) } -pub fn find_match(id: i32, conn: &PgConnection) -> QueryResult { +// TODO: maybe unify this with matchdata? +pub struct FullMatchData { + pub base: MatchBase, + pub match_players: Vec, +} + +#[derive(Queryable)] +// #[primary_key(base.match_id, base::player_id)] +pub struct FullMatchPlayerData { + pub base: MatchPlayer, + pub code_bundle: CodeBundle, + pub bot: Option, +} + +impl BelongsTo for FullMatchPlayerData { + type ForeignKey = i32; + type ForeignKeyColumn = match_players::match_id; + + fn foreign_key(&self) -> Option<&Self::ForeignKey> { + Some(&self.base.match_id) + } + + fn foreign_key_column() -> Self::ForeignKeyColumn { + match_players::match_id + } +} + +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 match_players = MatchPlayer::belonging_to(&match_base) + .inner_join(code_bundles::table) + .left_join(bots::table.on(code_bundles::bot_id.eq(bots::id.nullable()))) + .load::(conn)?; - let res = MatchData { + let res = FullMatchData { base: match_base, match_players, }; diff --git a/planetwars-server/src/routes/demo.rs b/planetwars-server/src/routes/demo.rs index 5dbbe92..749c0ca 100644 --- a/planetwars-server/src/routes/demo.rs +++ b/planetwars-server/src/routes/demo.rs @@ -1,5 +1,5 @@ use crate::db; -use crate::db::matches::{MatchPlayerData, MatchState}; +use crate::db::matches::{FullMatchData, FullMatchPlayerData, MatchPlayerData, MatchState}; use crate::modules::bots::save_code_bundle; use crate::util::gen_alphanumeric; use crate::{ConnectionPool, BOTS_DIR, MAPS_DIR, MATCHES_DIR}; @@ -92,7 +92,6 @@ pub async fn submit_bot( code_bundle_id: opponent_code_bundle.id, }, ]; - // TODO: set match players let match_data = db::matches::create_match(&new_match_data, &new_match_players, &conn) .expect("failed to create match"); @@ -102,7 +101,24 @@ pub async fn submit_bot( pool.clone(), )); - let api_match = super::matches::match_data_to_api(match_data); + // TODO: avoid clones + let full_match_data = FullMatchData { + base: match_data.base, + match_players: vec![ + FullMatchPlayerData { + base: match_data.match_players[0].clone(), + code_bundle: player_code_bundle, + bot: None, + }, + FullMatchPlayerData { + base: match_data.match_players[1].clone(), + code_bundle: opponent_code_bundle, + bot: Some(opponent), + }, + ], + }; + + let api_match = super::matches::match_data_to_api(full_match_data); Ok(Json(SubmitBotResponse { match_data: api_match, })) diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs index a6d8ff2..fc09551 100644 --- a/planetwars-server/src/routes/matches.rs +++ b/planetwars-server/src/routes/matches.rs @@ -109,9 +109,9 @@ pub struct ApiMatch { #[derive(Serialize, Deserialize)] pub struct ApiMatchPlayer { - // TODO! -// bot_id: i32, -// code_bundle_id: i32 + code_bundle_id: i32, + bot_id: Option, + bot_name: Option, } pub async fn list_matches(conn: DatabaseConnection) -> Result>, StatusCode> { @@ -120,7 +120,7 @@ pub async fn list_matches(conn: DatabaseConnection) -> Result .map(|matches| Json(matches.into_iter().map(match_data_to_api).collect())) } -pub fn match_data_to_api(data: matches::MatchData) -> ApiMatch { +pub fn match_data_to_api(data: matches::FullMatchData) -> ApiMatch { ApiMatch { id: data.base.id, timestamp: data.base.created_at, @@ -128,7 +128,11 @@ pub fn match_data_to_api(data: matches::MatchData) -> ApiMatch { players: data .match_players .iter() - .map(|_p| ApiMatchPlayer {}) + .map(|_p| ApiMatchPlayer { + code_bundle_id: _p.code_bundle.id, + bot_id: _p.bot.as_ref().map(|b| b.id), + bot_name: _p.bot.as_ref().map(|b| b.name.clone()), + }) .collect(), } } -- cgit v1.2.3