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"
|
||||
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"
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue