minimal port of start_match logic
This commit is contained in:
parent
4a077c7c65
commit
bdb77f97d6
5 changed files with 82 additions and 9 deletions
|
@ -21,6 +21,11 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
zip = "0.5"
|
zip = "0.5"
|
||||||
|
toml = "0.5"
|
||||||
|
planetwars-matchrunner = { path = "../planetwars-matchrunner" }
|
||||||
|
|
||||||
|
# TODO: remove me
|
||||||
|
shlex = "1.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
parking_lot = "0.11"
|
parking_lot = "0.11"
|
|
@ -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))
|
.filter(code_bundles::bot_id.eq(bot_id))
|
||||||
.get_results(conn)
|
.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)
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,11 @@ use axum::{
|
||||||
AddExtensionLayer, Router,
|
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>>;
|
type ConnectionPool = bb8::Pool<DieselConnectionManager<PgConnection>>;
|
||||||
|
|
||||||
pub async fn api() -> Router {
|
pub async fn api() -> Router {
|
||||||
|
|
|
@ -1,22 +1,18 @@
|
||||||
use axum::extract::{Multipart, Path, RawBody};
|
use axum::extract::{Multipart, Path};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::IntoResponse;
|
|
||||||
use axum::Json;
|
use axum::Json;
|
||||||
use rand::distributions::Alphanumeric;
|
use rand::distributions::Alphanumeric;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, value::Value as JsonValue};
|
use serde_json::{json, value::Value as JsonValue};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::path::{self, PathBuf};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::db::bots::{self, CodeBundle};
|
use crate::db::bots::{self, CodeBundle};
|
||||||
use crate::db::users::User;
|
use crate::db::users::User;
|
||||||
use crate::DatabaseConnection;
|
use crate::{DatabaseConnection, BOTS_DIR};
|
||||||
use bots::Bot;
|
use bots::Bot;
|
||||||
|
|
||||||
// TODO: make this a parameter
|
|
||||||
const BOTS_DIR: &str = "./data/bots";
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct BotParams {
|
pub struct BotParams {
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
@ -1,12 +1,72 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use axum::Json;
|
use axum::Json;
|
||||||
|
use hyper::StatusCode;
|
||||||
|
use planetwars_matchrunner::{run_match, MatchConfig, MatchPlayer};
|
||||||
|
use rand::{distributions::Alphanumeric, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
db::{bots, users::User},
|
||||||
|
DatabaseConnection, BOTS_DIR, MAPS_DIR, MATCHES_DIR,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct MatchParams {
|
pub struct MatchParams {
|
||||||
// Just bot ids for now
|
// Just bot ids for now
|
||||||
players: Vec<i32>,
|
players: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn play_match(params: Json<MatchParams>) {
|
pub async fn play_match(
|
||||||
println!("start match: {:#?}", params);
|
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>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue