diff --git a/src/lib.rs b/src/lib.rs index 2912312..3d2f5f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ extern crate toml; extern crate crossbeam; extern crate discord; extern crate rand; +extern crate pvn; use std::collections::BTreeMap; use toml::Table; diff --git a/src/modules/loader.rs b/src/modules/loader.rs index a6c6b8a..bb67119 100644 --- a/src/modules/loader.rs +++ b/src/modules/loader.rs @@ -10,6 +10,7 @@ use modules::lua::LuaModule; use modules::stdin::StdinModule; use modules::echo::EchoModule; use modules::random::RandomModule; +use modules::pvn::PvnModule; pub struct ModuleLoader { types: BTreeMap<&'static str, fn(&Table) -> Box> @@ -23,6 +24,7 @@ impl ModuleLoader { types.insert("stdin", StdinModule::new as fn(&Table) -> Box); types.insert("echo", EchoModule::new as fn(&Table) -> Box); types.insert("random", RandomModule::new as fn(&Table) -> Box); + types.insert("pvn", PvnModule::new as fn(&Table) -> Box); ModuleLoader { types: types } diff --git a/src/modules/mod.rs b/src/modules/mod.rs index f297d08..f68caf5 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -3,6 +3,7 @@ pub mod discord; pub mod stdin; pub mod echo; pub mod random; +pub mod pvn; pub mod loader; diff --git a/src/modules/pvn.rs b/src/modules/pvn.rs new file mode 100644 index 0000000..9f4c1ec --- /dev/null +++ b/src/modules/pvn.rs @@ -0,0 +1,163 @@ +use modules::Module; +use toml::Table; + +use std::sync::Arc; +use std::sync::mpsc::Receiver; +use event::Event; + +use {Channel, User}; + +use pvn::Fighter; +use pvn::pirates::{Pirate, Pirates}; +use pvn::ninjas::{Ninja, Ninjas}; + +pub struct PvnModule {} + +impl PvnModule { + pub fn new (configuration: &Table) -> Box { + Box::new(PvnModule {}) + } +} + +fn split_combatants (input: &str) -> Option<(&str, &str)> { + let fighters: Vec<&str> = input.split("|").map(|item| item.trim()).collect(); + if fighters.len() != 2 { + return None; + } + + Option::Some(( + *fighters.get(0).expect("should be exactly two fighters"), + *fighters.get(1).expect("should be exactly two fighters") + )) +} + +fn split_command (input: &str) -> Option<(&str, &str)> { + match input.split_whitespace().into_iter().next() { + Some(command) => { Some((command, input[command.len()..].trim())) }, + None => None + } +} + +fn reply (message: &str, channel: &Option, user: &User) { + match *channel { + Some(ref channel) => channel.send(message), + None => user.send(message) + } +} + +fn print_pirate (pirate: &Pirate, channel: &Option, user: &User) { + reply(&format!("**{}**", pirate.name), channel, user); + reply(&format!("Swashbuckling: {}", pirate.swashbuckling), channel, user); + reply(&format!("Drunkenness: {}", pirate.drunkenness), channel, user); + reply(&format!("Booty: {}", pirate.booty), channel, user); + reply(&format!("Weapons: {}", pirate.weapons.join(", ")), channel, user); + reply(&format!("**TOTAL POWER: {}**", pirate.power()), channel, user); +} + +fn print_ninja (ninja: &Ninja, channel: &Option, user: &User) { + reply(&format!("**{}**", ninja.name), channel, user); + reply(&format!("Sneakiness: {}", ninja.sneakiness), channel, user); + reply(&format!("Pajamas: {}", ninja.pajamas), channel, user); + reply(&format!("Pointy Things: {}", ninja.pointy_things), channel, user); + reply(&format!("Weapons: {}", ninja.weapons.join(", ")), channel, user); + reply(&format!("**TOTAL POWER: {}**", ninja.power()), channel, user); +} + +fn pirate_vs_ninja (pirate: &Pirate, ninja: &Ninja, channel: &Option, user: &User) { + print_pirate(pirate, channel, user); + print_ninja(ninja, channel, user); + + if pirate.power() == ninja.power() { + reply("**It's a tie!**", channel, user); + } else if pirate.power() > ninja.power() { + reply(&format!("**Winner: {}!**", pirate.name), channel, user); + } else { + reply(&format!("**Winner: {}!**", ninja.name), channel, user); + } +} + +struct PirateVsNinja { + pirates: Pirates, + ninjas: Ninjas +} + +impl PirateVsNinja { + fn pvn_command (&mut self, argument: &str, channel: &Option, user: &User) { + match split_combatants(argument) { + Some((pirate_name, ninja_name)) => { + match self.pirates.get(pirate_name) { + Ok(pirate) => { + match self.ninjas.get(ninja_name) { + Ok(ninja) => { + pirate_vs_ninja(pirate, ninja, channel, user); + }, + Err(error) => { + error!("Error getting ninja: {:?}", error); + } + } + }, + Err(error) => { + error!("Error getting pirate: {:?}", error); + } + } + }, + None => { + reply("Expected two arguments of the form: {pirate} | {ninja}", channel, user); + } + } + } + + fn pirate_command (&mut self, name: &str, channel: &Option, user: &User) { + match self.pirates.get(name) { + Ok(pirate) => { + print_pirate(pirate, channel, user); + }, + Err(error) => { + error!("Error getting pirate: {:?}", error); + } + } + } + + fn ninja_command (&mut self, name: &str, channel: &Option, user: &User) { + match self.ninjas.get(name) { + Ok(ninja) => { + print_ninja(ninja, channel, user); + }, + Err(error) => { + error!("Error getting ninja: {:?}", error); + } + } + } +} + +impl Module for PvnModule { + fn consume_events (&self, receiver: Receiver>) { + let mut pvn = PirateVsNinja { + pirates: Pirates::new(), + ninjas: Ninjas::new() + }; + + loop { + match receiver.recv() { + Ok(event) => { + match *event { + Event::Message { content: ref message, ref channel, ref sender } => { + let command = split_command(message); + debug!("Received message... {:?}", message); + match command { + Some(("?pvn", argument)) => { pvn.pvn_command(argument, channel, sender) }, + Some(("?pirate", name)) => { pvn.pirate_command(name, channel, sender) }, + Some(("?ninja", name)) => { pvn.ninja_command(name, channel, sender) }, + _ => {} + } + } + _ => () + } + } + Err(error) => { + error!("Error {:?}", error); + } + } + } + } +}