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;
|
pub use crate::db_types::MatchState;
|
||||||
use chrono::NaiveDateTime;
|
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 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)]
|
#[derive(Insertable)]
|
||||||
#[table_name = "matches"]
|
#[table_name = "matches"]
|
||||||
|
@ -32,7 +37,7 @@ pub struct MatchBase {
|
||||||
pub created_at: NaiveDateTime,
|
pub created_at: NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Queryable, Identifiable, Associations)]
|
#[derive(Queryable, Identifiable, Associations, Clone)]
|
||||||
#[primary_key(match_id, player_id)]
|
#[primary_key(match_id, player_id)]
|
||||||
#[belongs_to(MatchBase, foreign_key = "match_id")]
|
#[belongs_to(MatchBase, foreign_key = "match_id")]
|
||||||
pub struct MatchPlayer {
|
pub struct MatchPlayer {
|
||||||
|
@ -81,18 +86,20 @@ pub struct MatchData {
|
||||||
pub match_players: Vec<MatchPlayer>,
|
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(|| {
|
conn.transaction(|| {
|
||||||
let matches = matches::table.get_results::<MatchBase>(conn)?;
|
let matches = matches::table.get_results::<MatchBase>(conn)?;
|
||||||
|
|
||||||
let match_players = MatchPlayer::belonging_to(&matches)
|
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);
|
.grouped_by(&matches);
|
||||||
|
|
||||||
let res = matches
|
let res = matches
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(match_players.into_iter())
|
.zip(match_players.into_iter())
|
||||||
.map(|(base, players)| MatchData {
|
.map(|(base, players)| FullMatchData {
|
||||||
base,
|
base,
|
||||||
match_players: players.into_iter().collect(),
|
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(|| {
|
conn.transaction(|| {
|
||||||
let match_base = matches::table.find(id).get_result::<MatchBase>(conn)?;
|
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,
|
base: match_base,
|
||||||
match_players,
|
match_players,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::db;
|
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::modules::bots::save_code_bundle;
|
||||||
use crate::util::gen_alphanumeric;
|
use crate::util::gen_alphanumeric;
|
||||||
use crate::{ConnectionPool, BOTS_DIR, MAPS_DIR, MATCHES_DIR};
|
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,
|
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)
|
let match_data = db::matches::create_match(&new_match_data, &new_match_players, &conn)
|
||||||
.expect("failed to create match");
|
.expect("failed to create match");
|
||||||
|
|
||||||
|
@ -102,7 +101,24 @@ pub async fn submit_bot(
|
||||||
pool.clone(),
|
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 {
|
Ok(Json(SubmitBotResponse {
|
||||||
match_data: api_match,
|
match_data: api_match,
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -109,9 +109,9 @@ pub struct ApiMatch {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ApiMatchPlayer {
|
pub struct ApiMatchPlayer {
|
||||||
// TODO!
|
code_bundle_id: i32,
|
||||||
// bot_id: i32,
|
bot_id: Option<i32>,
|
||||||
// code_bundle_id: i32
|
bot_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_matches(conn: DatabaseConnection) -> Result<Json<Vec<ApiMatch>>, StatusCode> {
|
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()))
|
.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 {
|
ApiMatch {
|
||||||
id: data.base.id,
|
id: data.base.id,
|
||||||
timestamp: data.base.created_at,
|
timestamp: data.base.created_at,
|
||||||
|
@ -128,7 +128,11 @@ pub fn match_data_to_api(data: matches::MatchData) -> ApiMatch {
|
||||||
players: data
|
players: data
|
||||||
.match_players
|
.match_players
|
||||||
.iter()
|
.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(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue