aboutsummaryrefslogtreecommitdiff
path: root/planetwars-server/src/routes/matches.rs
diff options
context:
space:
mode:
Diffstat (limited to 'planetwars-server/src/routes/matches.rs')
-rw-r--r--planetwars-server/src/routes/matches.rs75
1 files changed, 69 insertions, 6 deletions
diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs
index 58ca478..10b4507 100644
--- a/planetwars-server/src/routes/matches.rs
+++ b/planetwars-server/src/routes/matches.rs
@@ -1,19 +1,30 @@
-use axum::{extract::Path, Extension, Json};
+use axum::{
+ extract::{Path, Query},
+ Extension, Json,
+};
+use chrono::NaiveDateTime;
use hyper::StatusCode;
use serde::{Deserialize, Serialize};
use std::{path::PathBuf, sync::Arc};
use crate::{
- db::matches::{self, MatchState},
+ db::{
+ self,
+ matches::{self, MatchState},
+ },
DatabaseConnection, GlobalConfig,
};
+use super::maps::ApiMap;
+
#[derive(Serialize, Deserialize)]
pub struct ApiMatch {
id: i32,
timestamp: chrono::NaiveDateTime,
state: MatchState,
players: Vec<ApiMatchPlayer>,
+ winner: Option<i32>,
+ map: Option<ApiMap>,
}
#[derive(Serialize, Deserialize)]
@@ -23,10 +34,60 @@ pub struct ApiMatchPlayer {
bot_name: Option<String>,
}
-pub async fn list_matches(conn: DatabaseConnection) -> Result<Json<Vec<ApiMatch>>, StatusCode> {
- matches::list_matches(100, &conn)
- .map_err(|_| StatusCode::BAD_REQUEST)
- .map(|matches| Json(matches.into_iter().map(match_data_to_api).collect()))
+#[derive(Serialize, Deserialize)]
+pub struct ListRecentMatchesParams {
+ count: Option<usize>,
+ // TODO: should timezone be specified here?
+ before: Option<NaiveDateTime>,
+ after: Option<NaiveDateTime>,
+
+ bot: Option<String>,
+}
+
+const MAX_NUM_RETURNED_MATCHES: usize = 100;
+const DEFAULT_NUM_RETURNED_MATCHES: usize = 50;
+
+#[derive(Serialize, Deserialize)]
+pub struct ListMatchesResponse {
+ matches: Vec<ApiMatch>,
+ has_next: bool,
+}
+
+pub async fn list_recent_matches(
+ Query(params): Query<ListRecentMatchesParams>,
+ conn: DatabaseConnection,
+) -> Result<Json<ListMatchesResponse>, StatusCode> {
+ let requested_count = std::cmp::min(
+ params.count.unwrap_or(DEFAULT_NUM_RETURNED_MATCHES),
+ MAX_NUM_RETURNED_MATCHES,
+ );
+
+ // fetch one additional record to check whether a next page exists
+ let count = (requested_count + 1) as i64;
+
+ let matches_result = match params.bot {
+ Some(bot_name) => {
+ let bot = db::bots::find_bot_by_name(&bot_name, &conn)
+ .map_err(|_| StatusCode::BAD_REQUEST)?;
+ matches::list_bot_matches(bot.id, count, params.before, params.after, &conn)
+ }
+ None => matches::list_public_matches(count, params.before, params.after, &conn),
+ };
+
+ let mut matches = matches_result.map_err(|_| StatusCode::BAD_REQUEST)?;
+
+ let mut has_next = false;
+ if matches.len() > requested_count {
+ has_next = true;
+ matches.truncate(requested_count);
+ }
+
+ let api_matches = matches.into_iter().map(match_data_to_api).collect();
+
+ Ok(Json(ListMatchesResponse {
+ matches: api_matches,
+ has_next,
+ }))
}
pub fn match_data_to_api(data: matches::FullMatchData) -> ApiMatch {
@@ -43,6 +104,8 @@ pub fn match_data_to_api(data: matches::FullMatchData) -> ApiMatch {
bot_name: _p.bot.as_ref().map(|b| b.name.clone()),
})
.collect(),
+ winner: data.base.winner,
+ map: data.map.map(|m| ApiMap { name: m.name }),
}
}