aboutsummaryrefslogtreecommitdiff
path: root/planetwars-server
diff options
context:
space:
mode:
authorIlion Beyst <ilion.beyst@gmail.com>2022-01-01 16:32:55 +0100
committerIlion Beyst <ilion.beyst@gmail.com>2022-01-01 16:32:55 +0100
commitbdb77f97d6af5a59e80d2b2552cd6994754cbf29 (patch)
tree20bbc02edfe21f2dd75985976e273a97c809bb07 /planetwars-server
parent4a077c7c65eced447c45389acf05007dd571bf26 (diff)
downloadplanetwars.dev-bdb77f97d6af5a59e80d2b2552cd6994754cbf29.tar.xz
planetwars.dev-bdb77f97d6af5a59e80d2b2552cd6994754cbf29.zip
minimal port of start_match logic
Diffstat (limited to 'planetwars-server')
-rw-r--r--planetwars-server/Cargo.toml5
-rw-r--r--planetwars-server/src/db/bots.rs7
-rw-r--r--planetwars-server/src/lib.rs5
-rw-r--r--planetwars-server/src/routes/bots.rs10
-rw-r--r--planetwars-server/src/routes/matches.rs64
5 files changed, 82 insertions, 9 deletions
diff --git a/planetwars-server/Cargo.toml b/planetwars-server/Cargo.toml
index 3a28d5d..198d38f 100644
--- a/planetwars-server/Cargo.toml
+++ b/planetwars-server/Cargo.toml
@@ -21,6 +21,11 @@ chrono = { version = "0.4", features = ["serde"] }
serde_json = "1.0"
base64 = "0.13.0"
zip = "0.5"
+toml = "0.5"
+planetwars-matchrunner = { path = "../planetwars-matchrunner" }
+
+# TODO: remove me
+shlex = "1.1"
[dev-dependencies]
parking_lot = "0.11" \ No newline at end of file
diff --git a/planetwars-server/src/db/bots.rs b/planetwars-server/src/db/bots.rs
index bef69c0..970dcf9 100644
--- a/planetwars-server/src/db/bots.rs
+++ b/planetwars-server/src/db/bots.rs
@@ -68,3 +68,10 @@ pub fn find_bot_code_bundles(bot_id: i32, conn: &PgConnection) -> QueryResult<Ve
.filter(code_bundles::bot_id.eq(bot_id))
.get_results(conn)
}
+
+pub fn active_code_bundle(bot_id: i32, conn: &PgConnection) -> QueryResult<CodeBundle> {
+ code_bundles::table
+ .filter(code_bundles::bot_id.eq(bot_id))
+ .order(code_bundles::created_at.desc())
+ .first(conn)
+}
diff --git a/planetwars-server/src/lib.rs b/planetwars-server/src/lib.rs
index 01e9041..1d08580 100644
--- a/planetwars-server/src/lib.rs
+++ b/planetwars-server/src/lib.rs
@@ -22,6 +22,11 @@ use axum::{
AddExtensionLayer, Router,
};
+// TODO: make these configurable
+const BOTS_DIR: &str = "./data/bots";
+const MATCHES_DIR: &str = "./data/matches";
+const MAPS_DIR: &str = "./data/maps";
+
type ConnectionPool = bb8::Pool<DieselConnectionManager<PgConnection>>;
pub async fn api() -> Router {
diff --git a/planetwars-server/src/routes/bots.rs b/planetwars-server/src/routes/bots.rs
index 8327443..5f5d8f5 100644
--- a/planetwars-server/src/routes/bots.rs
+++ b/planetwars-server/src/routes/bots.rs
@@ -1,22 +1,18 @@
-use axum::extract::{Multipart, Path, RawBody};
+use axum::extract::{Multipart, Path};
use axum::http::StatusCode;
-use axum::response::IntoResponse;
use axum::Json;
use rand::distributions::Alphanumeric;
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde_json::{json, value::Value as JsonValue};
use std::io::Cursor;
-use std::path::{self, PathBuf};
+use std::path::PathBuf;
use crate::db::bots::{self, CodeBundle};
use crate::db::users::User;
-use crate::DatabaseConnection;
+use crate::{DatabaseConnection, BOTS_DIR};
use bots::Bot;
-// TODO: make this a parameter
-const BOTS_DIR: &str = "./data/bots";
-
#[derive(Serialize, Deserialize, Debug)]
pub struct BotParams {
name: String,
diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs
index 7eca6ab..4a556af 100644
--- a/planetwars-server/src/routes/matches.rs
+++ b/planetwars-server/src/routes/matches.rs
@@ -1,12 +1,72 @@
+use std::path::PathBuf;
+
use axum::Json;
+use hyper::StatusCode;
+use planetwars_matchrunner::{run_match, MatchConfig, MatchPlayer};
+use rand::{distributions::Alphanumeric, Rng};
use serde::{Deserialize, Serialize};
+use crate::{
+ db::{bots, users::User},
+ DatabaseConnection, BOTS_DIR, MAPS_DIR, MATCHES_DIR,
+};
+
#[derive(Serialize, Deserialize, Debug)]
pub struct MatchParams {
// Just bot ids for now
players: Vec<i32>,
}
-pub async fn play_match(params: Json<MatchParams>) {
- println!("start match: {:#?}", params);
+pub async fn play_match(
+ user: User,
+ conn: DatabaseConnection,
+ Json(params): Json<MatchParams>,
+) -> Result<(), StatusCode> {
+ let map_path = PathBuf::from(MAPS_DIR).join("hex.json");
+
+ let slug: String = rand::thread_rng()
+ .sample_iter(&Alphanumeric)
+ .take(16)
+ .map(char::from)
+ .collect();
+ let log_path = PathBuf::from(MATCHES_DIR).join(&format!("{}.log", slug));
+
+ let mut players = Vec::new();
+ for bot_name in params.players {
+ let bot = bots::find_bot(bot_name, &conn).map_err(|_| StatusCode::BAD_REQUEST)?;
+ let code_bundle =
+ bots::active_code_bundle(bot.id, &conn).map_err(|_| StatusCode::BAD_REQUEST)?;
+
+ let bundle_path = PathBuf::from(BOTS_DIR).join(&code_bundle.path);
+ let bot_config: BotConfig = std::fs::read_to_string(bundle_path.join("botconfig.toml"))
+ .and_then(|config_str| toml::from_str(&config_str).map_err(|e| e.into()))
+ .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
+
+ players.push(MatchPlayer {
+ name: bot.name.clone(),
+ path: PathBuf::from(BOTS_DIR).join(code_bundle.path),
+ argv: shlex::split(&bot_config.run_command)
+ // TODO: this is an user error, should ideally be handled before we get here
+ .ok_or_else(|| StatusCode::INTERNAL_SERVER_ERROR)?,
+ });
+ }
+
+ let match_config = MatchConfig {
+ map_name: "hex".to_string(),
+ map_path,
+ log_path: log_path.clone(),
+ players,
+ };
+
+ tokio::spawn(run_match(match_config));
+ Ok(())
+}
+
+// TODO: this is duplicated from planetwars-cli
+// clean this up and move to matchrunner crate
+#[derive(Serialize, Deserialize)]
+pub struct BotConfig {
+ pub name: String,
+ pub run_command: String,
+ pub build_command: Option<String>,
}