aboutsummaryrefslogtreecommitdiff
path: root/planetwars-cli/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'planetwars-cli/src/commands')
-rw-r--r--planetwars-cli/src/commands/build.rs27
-rw-r--r--planetwars-cli/src/commands/init.rs38
-rw-r--r--planetwars-cli/src/commands/mod.rs40
-rw-r--r--planetwars-cli/src/commands/run_match.rs51
-rw-r--r--planetwars-cli/src/commands/serve.rs17
5 files changed, 173 insertions, 0 deletions
diff --git a/planetwars-cli/src/commands/build.rs b/planetwars-cli/src/commands/build.rs
new file mode 100644
index 0000000..1df0bb6
--- /dev/null
+++ b/planetwars-cli/src/commands/build.rs
@@ -0,0 +1,27 @@
+use clap::Parser;
+use std::io;
+use tokio::process;
+
+use crate::workspace::Workspace;
+
+#[derive(Parser)]
+pub struct BuildCommand {
+ /// Name of the bot to build
+ bot: String,
+}
+
+impl BuildCommand {
+ pub async fn run(self) -> io::Result<()> {
+ let workspace = Workspace::open_current_dir()?;
+ let bot = workspace.get_bot(&self.bot)?;
+ if let Some(argv) = bot.config.get_build_argv() {
+ process::Command::new(&argv[0])
+ .args(&argv[1..])
+ .current_dir(&bot.path)
+ .spawn()?
+ .wait()
+ .await?;
+ }
+ Ok(())
+ }
+}
diff --git a/planetwars-cli/src/commands/init.rs b/planetwars-cli/src/commands/init.rs
new file mode 100644
index 0000000..c95626b
--- /dev/null
+++ b/planetwars-cli/src/commands/init.rs
@@ -0,0 +1,38 @@
+use std::path::PathBuf;
+
+use clap::Parser;
+use futures::io;
+
+#[derive(Parser)]
+pub struct InitCommand {
+ /// workspace root directory
+ path: String,
+}
+
+macro_rules! copy_asset {
+ ($path:expr, $file_name:literal) => {
+ ::std::fs::write(
+ $path.join($file_name),
+ include_bytes!(concat!("../../assets/", $file_name)),
+ )?;
+ };
+}
+
+impl InitCommand {
+ pub async fn run(self) -> io::Result<()> {
+ let path = PathBuf::from(&self.path);
+
+ // create directories
+ std::fs::create_dir_all(&path)?;
+ std::fs::create_dir(path.join("maps"))?;
+ std::fs::create_dir(path.join("matches"))?;
+ std::fs::create_dir_all(path.join("bots/simplebot"))?;
+
+ // create files
+ copy_asset!(path, "pw_workspace.toml");
+ copy_asset!(path.join("maps"), "hex.json");
+ copy_asset!(path.join("bots/"), "simplebot/botconfig.toml");
+ copy_asset!(path.join("bots/"), "simplebot/simplebot.py");
+ Ok(())
+ }
+}
diff --git a/planetwars-cli/src/commands/mod.rs b/planetwars-cli/src/commands/mod.rs
new file mode 100644
index 0000000..52fed5c
--- /dev/null
+++ b/planetwars-cli/src/commands/mod.rs
@@ -0,0 +1,40 @@
+mod build;
+mod init;
+mod run_match;
+mod serve;
+
+use clap::{Parser, Subcommand};
+use std::io;
+
+#[derive(Parser)]
+#[clap(name = "pwcli")]
+#[clap(author, version, about)]
+pub struct Cli {
+ #[clap(subcommand)]
+ command: Command,
+}
+
+impl Cli {
+ pub async fn run() -> io::Result<()> {
+ let cli = Self::parse();
+
+ match cli.command {
+ Command::Init(command) => command.run().await,
+ Command::RunMatch(command) => command.run().await,
+ Command::Serve(command) => command.run().await,
+ Command::Build(command) => command.run().await,
+ }
+ }
+}
+
+#[derive(Subcommand)]
+enum Command {
+ /// Initialize a new workspace
+ Init(init::InitCommand),
+ /// Run a match
+ RunMatch(run_match::RunMatchCommand),
+ /// Host local webserver
+ Serve(serve::ServeCommand),
+ /// Run build command for a bot
+ Build(build::BuildCommand),
+}
diff --git a/planetwars-cli/src/commands/run_match.rs b/planetwars-cli/src/commands/run_match.rs
new file mode 100644
index 0000000..868e87c
--- /dev/null
+++ b/planetwars-cli/src/commands/run_match.rs
@@ -0,0 +1,51 @@
+use std::io;
+
+use clap::Parser;
+
+use crate::match_runner::MatchConfig;
+use crate::match_runner::{self, MatchPlayer};
+use crate::workspace::Workspace;
+#[derive(Parser)]
+pub struct RunMatchCommand {
+ /// map name
+ map: String,
+ /// bot names
+ bots: Vec<String>,
+}
+
+impl RunMatchCommand {
+ pub async fn run(self) -> io::Result<()> {
+ let workspace = Workspace::open_current_dir()?;
+
+ let map_path = workspace.map_path(&self.map);
+ let timestamp = chrono::Local::now().format("%Y-%m-%d-%H-%M-%S");
+ let log_path = workspace.match_path(&format!("{}-{}", &self.map, &timestamp));
+
+ let mut players = Vec::new();
+ for bot_name in &self.bots {
+ let bot = workspace.get_bot(&bot_name)?;
+ players.push(MatchPlayer {
+ name: bot_name.clone(),
+ bot,
+ });
+ }
+
+ let match_config = MatchConfig {
+ map_name: self.map,
+ map_path,
+ log_path: log_path.clone(),
+ players,
+ };
+
+ match_runner::run_match(match_config).await;
+ println!("match completed successfully");
+ // TODO: maybe print the match result as well?
+
+ let relative_path = match log_path.strip_prefix(&workspace.root_path) {
+ Ok(path) => path.to_str().unwrap(),
+ Err(_) => log_path.to_str().unwrap(),
+ };
+ println!("wrote match log to {}", relative_path);
+ Ok(())
+ }
+}
diff --git a/planetwars-cli/src/commands/serve.rs b/planetwars-cli/src/commands/serve.rs
new file mode 100644
index 0000000..aa8d149
--- /dev/null
+++ b/planetwars-cli/src/commands/serve.rs
@@ -0,0 +1,17 @@
+use std::io;
+
+use clap::Parser;
+
+use crate::web;
+use crate::workspace::Workspace;
+
+#[derive(Parser)]
+pub struct ServeCommand;
+
+impl ServeCommand {
+ pub async fn run(self) -> io::Result<()> {
+ let workspace = Workspace::open_current_dir()?;
+ web::run(workspace).await;
+ Ok(())
+ }
+}