use modules::Module; use toml::Table; use std::sync::Arc; use std::sync::mpsc::Receiver; use transformable_channels::mpsc::ExtSender; use event::{Event, Envelope}; use Message; use helpers::command::split_command; use pvn::Fighter; use pvn::pirates::{Pirate, Pirates}; use pvn::ninjas::{Ninja, Ninjas}; pub struct PvnModule {} impl PvnModule { pub fn new (_: &Table, _: &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") )) } trait PvnFighter: Fighter { fn name (&self) -> &str; fn print (&self, message: &Message); fn fight (&self, other: &PvnFighter, message: &Message) { self.print(message); other.print(message); if self.power() == other.power() { message.reply("**It's a tie!**"); } else if self.power() > other.power() { message.reply(&format!("**Winner: {}!**", self.name())); } else { message.reply(&format!("**Winner: {}!**", other.name())); } } } impl PvnFighter for Pirate { fn print (&self, message: &Message) { message.reply(&format!("**{}**", self.name)); message.reply(&format!("Swashbuckling: {}", self.swashbuckling)); message.reply(&format!("Drunkenness: {}", self.drunkenness)); message.reply(&format!("Booty: {}", self.booty)); message.reply(&format!("Weapons: {}", self.weapons.join(", "))); message.reply(&format!("**TOTAL POWER: {}**", self.power())); } fn name (&self) -> &str { &self.name[..] } } impl PvnFighter for Ninja { fn print (&self, message: &Message) { message.reply(&format!("**{}**", self.name)); message.reply(&format!("Sneakiness: {}", self.sneakiness)); message.reply(&format!("Pajamas: {}", self.pajamas)); message.reply(&format!("Pointy Things: {}", self.pointy_things)); message.reply(&format!("Weapons: {}", self.weapons.join(", "))); message.reply(&format!("**TOTAL POWER: {}**", self.power())); } fn name (&self) -> &str { &self.name[..] } } struct PirateVsNinja { pirates: Pirates, ninjas: Ninjas } impl PirateVsNinja { fn pvn_command (&mut self, argument: &str, message: &Message) { 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, message); }, Err(error) => { error!("Error getting ninja: {:?}", error); } } }, Err(error) => { error!("Error getting pirate: {:?}", error); } } }, None => { message.reply("Expected two arguments of the form: {pirate} | {ninja}"); } } } fn pirate_command (&mut self, name: &str, message: &Message) { match self.pirates.get(name) { Ok(pirate) => { pirate.print(message); }, Err(error) => { error!("Error getting pirate: {:?}", error); } } } fn ninja_command (&mut self, name: &str, message: &Message) { match self.ninjas.get(name) { Ok(ninja) => { ninja.print(message); }, Err(error) => { error!("Error getting ninja: {:?}", error); } } } } impl Module for PvnModule { fn run(&self, _: Box>, receiver: Receiver>) { let mut pvn = PirateVsNinja { pirates: Pirates::new(), ninjas: Ninjas::new() }; loop { match receiver.recv() { Ok(envelope) => { match envelope.event { Event::Message { ref message } => { let command = split_command(&message.content); debug!("Received message from module {:?}... {:?}", envelope.from, message.content); match command { Some(("?pvn", argument)) => { pvn.pvn_command(argument, message) }, Some(("?pirate", name)) => { pvn.pirate_command(name, message) }, Some(("?ninja", name)) => { pvn.ninja_command(name, message) }, _ => {} } } _ => () } } Err(error) => { error!("Error {:?}", error); } } } } }