add information about match players to match API object
This commit is contained in:
parent
523de3ba06
commit
63695c299c
3 changed files with 74 additions and 17 deletions
|
@ -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<MatchPlayer>,
|
||||
}
|
||||
|
||||
pub fn list_matches(conn: &PgConnection) -> QueryResult<Vec<MatchData>> {
|
||||
pub fn list_matches(conn: &PgConnection) -> QueryResult<Vec<FullMatchData>> {
|
||||
conn.transaction(|| {
|
||||
let matches = matches::table.get_results::<MatchBase>(conn)?;
|
||||
|
||||
let match_players = MatchPlayer::belonging_to(&matches)
|
||||
.load::<MatchPlayer>(conn)?
|
||||
.inner_join(code_bundles::table)
|
||||
.left_join(bots::table.on(code_bundles::bot_id.eq(bots::id.nullable())))
|
||||
.load::<FullMatchPlayerData>(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<Vec<MatchData>> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn find_match(id: i32, conn: &PgConnection) -> QueryResult<MatchData> {
|
||||
// TODO: maybe unify this with matchdata?
|
||||
pub struct FullMatchData {
|
||||
pub base: MatchBase,
|
||||
pub match_players: Vec<FullMatchPlayerData>,
|
||||
}
|
||||
|
||||
#[derive(Queryable)]
|
||||
// #[primary_key(base.match_id, base::player_id)]
|
||||
pub struct FullMatchPlayerData {
|
||||
pub base: MatchPlayer,
|
||||
pub code_bundle: CodeBundle,
|
||||
pub bot: Option<Bot>,
|
||||
}
|
||||
|
||||
impl BelongsTo<MatchBase> 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<FullMatchData> {
|
||||
conn.transaction(|| {
|
||||
let match_base = matches::table.find(id).get_result::<MatchBase>(conn)?;
|
||||
|
||||
let match_players = MatchPlayer::belonging_to(&match_base).load::<MatchPlayer>(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::<FullMatchPlayerData>(conn)?;
|
||||
|
||||
let res = MatchData {
|
||||
let res = FullMatchData {
|
||||
base: match_base,
|
||||
match_players,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
}))
|
||||
|
|
|
@ -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<i32>,
|
||||
bot_name: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn list_matches(conn: DatabaseConnection) -> Result<Json<Vec<ApiMatch>>, StatusCode> {
|
||||
|
@ -120,7 +120,7 @@ pub async fn list_matches(conn: DatabaseConnection) -> Result<Json<Vec<ApiMatch>
|
|||
.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(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue