use modules::Module; use toml::Table; use std::sync::Arc; use std::sync::mpsc::Receiver; use event::Event; use {Channel, User}; use pvn::Error; 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) } } trait PvnFighter: Fighter { fn name (&self) -> &str; fn print (&self, channel: &Option, user: &User); fn fight (&self, other: &PvnFighter, channel: &Option, user: &User) { self.print(channel, user); other.print(channel, user); if self.power() == other.power() { reply("**It's a tie!**", channel, user); } else if self.power() > other.power() { reply(&format!("**Winner: {}!**", self.name()), channel, user); } else { reply(&format!("**Winner: {}!**", other.name()), channel, user); } } } impl PvnFighter for Pirate { fn print (&self, channel: &Option, user: &User) { reply(&format!("**{}**", self.name), channel, user); reply(&format!("Swashbuckling: {}", self.swashbuckling), channel, user); reply(&format!("Drunkenness: {}", self.drunkenness), channel, user); reply(&format!("Booty: {}", self.booty), channel, user); reply(&format!("Weapons: {}", self.weapons.join(", ")), channel, user); reply(&format!("**TOTAL POWER: {}**", self.power()), channel, user); } fn name (&self) -> &str { &self.name[..] } } impl PvnFighter for Ninja { fn print (&self, channel: &Option, user: &User) { reply(&format!("**{}**", self.name), channel, user); reply(&format!("Sneakiness: {}", self.sneakiness), channel, user); reply(&format!("Pajamas: {}", self.pajamas), channel, user); reply(&format!("Pointy Things: {}", self.pointy_things), channel, user); reply(&format!("Weapons: {}", self.weapons.join(", ")), channel, user); reply(&format!("**TOTAL POWER: {}**", self.power()), channel, user); } fn name (&self) -> &str { &self.name[..] } } 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.fight(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) => { pirate.print(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) => { ninja.print(channel, user); }, Err(error) => { error!("Error getting ninja: {:?}", error); } } } fn get_pirate (&mut self, name: &str) -> Result<&Pirate, Error> { self.pirates.get(name) } fn get_ninja (&mut self, name: &str) -> Result<&Ninja, Error> { self.ninjas.get(name) } } 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); } } } } }