aboutsummaryrefslogtreecommitdiff
path: root/planetwars-server/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'planetwars-server/src/routes')
-rw-r--r--planetwars-server/src/routes/demo.rs14
-rw-r--r--planetwars-server/src/routes/maps.rs19
-rw-r--r--planetwars-server/src/routes/matches.rs75
-rw-r--r--planetwars-server/src/routes/mod.rs1
4 files changed, 101 insertions, 8 deletions
diff --git a/planetwars-server/src/routes/demo.rs b/planetwars-server/src/routes/demo.rs
index dad9453..1ec8825 100644
--- a/planetwars-server/src/routes/demo.rs
+++ b/planetwars-server/src/routes/demo.rs
@@ -14,12 +14,13 @@ use serde::{Deserialize, Serialize};
use super::matches::ApiMatch;
const DEFAULT_OPPONENT_NAME: &str = "simplebot";
+const DEFAULT_MAP_NAME: &str = "hex";
#[derive(Serialize, Deserialize, Debug)]
pub struct SubmitBotParams {
pub code: String,
- // TODO: would it be better to pass an ID here?
pub opponent_name: Option<String>,
+ pub map_name: Option<String>,
}
#[derive(Serialize, Deserialize)]
@@ -40,16 +41,24 @@ pub async fn submit_bot(
.opponent_name
.unwrap_or_else(|| DEFAULT_OPPONENT_NAME.to_string());
+ let map_name = params
+ .map_name
+ .unwrap_or_else(|| DEFAULT_MAP_NAME.to_string());
+
let (opponent_bot, opponent_bot_version) =
db::bots::find_bot_with_version_by_name(&opponent_name, &conn)
.map_err(|_| StatusCode::BAD_REQUEST)?;
+ let map = db::maps::find_map_by_name(&map_name, &conn).map_err(|_| StatusCode::BAD_REQUEST)?;
+
let player_bot_version = save_code_string(&params.code, None, &conn, &config)
// TODO: can we recover from this?
.expect("could not save bot code");
- let run_match = RunMatch::from_players(
+ let run_match = RunMatch::new(
config,
+ false,
+ map.clone(),
vec![
MatchPlayer::BotVersion {
bot: None,
@@ -81,6 +90,7 @@ pub async fn submit_bot(
bot: Some(opponent_bot),
},
],
+ map: Some(map),
};
let api_match = super::matches::match_data_to_api(full_match_data);
diff --git a/planetwars-server/src/routes/maps.rs b/planetwars-server/src/routes/maps.rs
new file mode 100644
index 0000000..689b11e
--- /dev/null
+++ b/planetwars-server/src/routes/maps.rs
@@ -0,0 +1,19 @@
+use crate::{db, DatabaseConnection};
+use axum::Json;
+use hyper::StatusCode;
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize)]
+pub struct ApiMap {
+ pub name: String,
+}
+
+pub async fn list_maps(conn: DatabaseConnection) -> Result<Json<Vec<ApiMap>>, StatusCode> {
+ let maps = db::maps::list_maps(&conn).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
+
+ let api_maps = maps
+ .into_iter()
+ .map(|map| ApiMap { name: map.name })
+ .collect();
+ Ok(Json(api_maps))
+}
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 }),
}
}
diff --git a/planetwars-server/src/routes/mod.rs b/planetwars-server/src/routes/mod.rs
index b3decb8..9510fd4 100644
--- a/planetwars-server/src/routes/mod.rs
+++ b/planetwars-server/src/routes/mod.rs
@@ -1,4 +1,5 @@
pub mod bots;
pub mod demo;
+pub mod maps;
pub mod matches;
pub mod users;