aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--planetwars-cli/src/commands/init.rs38
-rw-r--r--planetwars-cli/src/commands/mod.rs36
-rw-r--r--planetwars-cli/src/commands/run_match.rs61
-rw-r--r--planetwars-cli/src/commands/serve.rs18
-rw-r--r--planetwars-cli/src/lib.rs125
5 files changed, 156 insertions, 122 deletions
diff --git a/planetwars-cli/src/commands/init.rs b/planetwars-cli/src/commands/init.rs
new file mode 100644
index 0000000..42491bc
--- /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 {
+ /// project 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_project.toml");
+ copy_asset!(path.join("maps"), "hex.json");
+ 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..6606c77
--- /dev/null
+++ b/planetwars-cli/src/commands/mod.rs
@@ -0,0 +1,36 @@
+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,
+ }
+ }
+}
+
+#[derive(Subcommand)]
+enum Command {
+ /// Initialize a new project
+ Init(init::InitCommand),
+ /// Run a match
+ RunMatch(run_match::RunMatchCommand),
+ /// Host local webserver
+ Serve(serve::ServeCommand),
+}
diff --git a/planetwars-cli/src/commands/run_match.rs b/planetwars-cli/src/commands/run_match.rs
new file mode 100644
index 0000000..a5512f4
--- /dev/null
+++ b/planetwars-cli/src/commands/run_match.rs
@@ -0,0 +1,61 @@
+use std::env;
+use std::io;
+
+use clap::Parser;
+
+use crate::match_runner;
+use crate::match_runner::MatchBot;
+use crate::match_runner::MatchConfig;
+use crate::resolve_bot_config;
+use crate::ProjectConfig;
+
+#[derive(Parser)]
+pub struct RunMatchCommand {
+ /// map name
+ map: String,
+ /// bot names
+ bots: Vec<String>,
+}
+
+impl RunMatchCommand {
+ pub async fn run(self) -> io::Result<()> {
+ let project_dir = env::current_dir().unwrap();
+
+ let config_path = project_dir.join("pw_project.toml");
+
+ let map_path = project_dir.join(format!("maps/{}.json", self.map));
+
+ let timestamp = chrono::Local::now().format("%Y-%m-%d-%H-%M-%S");
+ let log_path = project_dir.join(format!("matches/{}.log", timestamp));
+
+ let config_str = std::fs::read_to_string(config_path).unwrap();
+ let project_config: ProjectConfig = toml::from_str(&config_str).unwrap();
+
+ let players = self
+ .bots
+ .into_iter()
+ .map(|bot_name| {
+ let bot_config = project_config.bots.get(&bot_name).unwrap().clone();
+ let resolved_config = resolve_bot_config(&project_dir, bot_config);
+ MatchBot {
+ name: bot_name,
+ bot_config: resolved_config,
+ }
+ })
+ .collect();
+
+ let match_config = MatchConfig {
+ map_name: self.map,
+ map_path,
+ log_path,
+ players,
+ };
+
+ match_runner::run_match(match_config).await;
+ println!("match completed successfully");
+ // TODO: don't hardcode match path.
+ // maybe print the match result as well?
+ println!("wrote match log to matches/{}.log", timestamp);
+ Ok(())
+ }
+}
diff --git a/planetwars-cli/src/commands/serve.rs b/planetwars-cli/src/commands/serve.rs
new file mode 100644
index 0000000..2a2e59b
--- /dev/null
+++ b/planetwars-cli/src/commands/serve.rs
@@ -0,0 +1,18 @@
+use std::env;
+use std::io;
+
+use clap::Parser;
+
+use crate::web;
+
+#[derive(Parser)]
+pub struct ServeCommand;
+
+impl ServeCommand {
+ pub async fn run(self) -> io::Result<()> {
+ let project_dir = env::current_dir().unwrap();
+
+ web::run(project_dir).await;
+ Ok(())
+ }
+}
diff --git a/planetwars-cli/src/lib.rs b/planetwars-cli/src/lib.rs
index 7eea75a..de9905d 100644
--- a/planetwars-cli/src/lib.rs
+++ b/planetwars-cli/src/lib.rs
@@ -1,51 +1,12 @@
-use match_runner::{MatchBot, MatchConfig};
use serde::Deserialize;
+mod commands;
mod match_runner;
+mod web;
use serde::Serialize;
use std::collections::HashMap;
-use std::env;
-use std::io;
use std::path::{Path, PathBuf};
-use toml;
-
-use clap::{Parser, Subcommand};
-
-#[derive(Parser)]
-#[clap(name = "pwcli")]
-#[clap(author, version, about)]
-struct Cli {
- #[clap(subcommand)]
- command: Commands,
-}
-
-#[derive(Subcommand)]
-enum Commands {
- /// Initialize a new project
- InitProject(InitProjectCommand),
- /// Run a match
- RunMatch(RunMatchCommand),
- /// Host local webserver
- Serve(ServeCommand),
-}
-
-#[derive(Parser)]
-struct RunMatchCommand {
- /// map name
- map: String,
- /// bot names
- bots: Vec<String>,
-}
-
-#[derive(Parser)]
-struct InitProjectCommand {
- /// project root directory
- path: String,
-}
-
-#[derive(Parser)]
-struct ServeCommand;
#[derive(Serialize, Deserialize, Debug)]
struct ProjectConfig {
@@ -59,59 +20,13 @@ pub struct BotConfig {
}
pub async fn run() {
- let matches = Cli::parse();
- let res = match matches.command {
- Commands::RunMatch(command) => run_match(command).await,
- Commands::InitProject(command) => init_project(command),
- Commands::Serve(_) => run_webserver().await,
- };
+ let res = commands::Cli::run().await;
if let Err(err) = res {
eprintln!("{}", err);
std::process::exit(1);
}
}
-async fn run_match(command: RunMatchCommand) -> io::Result<()> {
- let project_dir = env::current_dir().unwrap();
-
- let config_path = project_dir.join("pw_project.toml");
-
- let map_path = project_dir.join(format!("maps/{}.json", command.map));
-
- let timestamp = chrono::Local::now().format("%Y-%m-%d-%H-%M-%S");
- let log_path = project_dir.join(format!("matches/{}.log", timestamp));
-
- let config_str = std::fs::read_to_string(config_path).unwrap();
- let project_config: ProjectConfig = toml::from_str(&config_str).unwrap();
-
- let players = command
- .bots
- .into_iter()
- .map(|bot_name| {
- let bot_config = project_config.bots.get(&bot_name).unwrap().clone();
- let resolved_config = resolve_bot_config(&project_dir, bot_config);
- MatchBot {
- name: bot_name,
- bot_config: resolved_config,
- }
- })
- .collect();
-
- let match_config = MatchConfig {
- map_name: command.map,
- map_path,
- log_path,
- players,
- };
-
- match_runner::run_match(match_config).await;
- println!("match completed successfully");
- // TODO: don't hardcode match path.
- // maybe print the match result as well?
- println!("wrote match log to matches/{}.log", timestamp);
- Ok(())
-}
-
fn resolve_bot_config(project_dir: &Path, config: BotConfig) -> BotConfig {
let mut path = PathBuf::from(project_dir);
path.push(&config.path);
@@ -120,37 +35,3 @@ fn resolve_bot_config(project_dir: &Path, config: BotConfig) -> BotConfig {
argv: config.argv,
}
}
-
-macro_rules! copy_asset {
- ($path:expr, $file_name:literal) => {
- ::std::fs::write(
- $path.join($file_name),
- include_bytes!(concat!("../assets/", $file_name)),
- )?;
- };
-}
-
-fn init_project(command: InitProjectCommand) -> io::Result<()> {
- let path = PathBuf::from(&command.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_project.toml");
- copy_asset!(path.join("maps"), "hex.json");
- copy_asset!(path.join("bots/simplebot"), "simplebot.py");
-
- Ok(())
-}
-
-mod web;
-async fn run_webserver() -> io::Result<()> {
- let project_dir = env::current_dir().unwrap();
-
- web::run(project_dir).await;
- Ok(())
-}