diff --git a/src/jobs/classification.rs b/src/jobs/classification.rs new file mode 100644 index 0000000..d5681de --- /dev/null +++ b/src/jobs/classification.rs @@ -0,0 +1,60 @@ +//! Job classification types + +use errors::UnknownVariant; + +use std::fmt::{Display, Formatter, Result as FmtResult}; +use std::str::FromStr; + +/// The classification of jobs available in the game. +/// +/// `{War, Magic}` refer to [`Job`], while `{Land, Hand}` refer to [`NonCombatJob`]. +/// +/// [`Job`]: ::jobs::Job +/// [`NonCombatJob`]: ::jobs::NonCombatJob +#[derive(Debug, Clone, Copy)] +pub enum Classification { + War, + Magic, + Land, + Hand, +} + +impl Classification { + pub const ALL: [Classification; 4] = [ + Classification::War, + Classification::Magic, + Classification::Land, + Classification::Hand, + ]; + + pub fn as_str(&self) -> &'static str { + match *self { + Classification::War => "Disciple of War", + Classification::Magic => "Disciple of Magic", + Classification::Land => "Disciple of the Land", + Classification::Hand => "Disciple of the Hand", + } + } +} + +impl FromStr for Classification { + type Err = UnknownVariant; + + fn from_str(s: &str) -> Result { + let class = match s.to_lowercase().as_str() { + "disciple of war" | "war" => Classification::War, + "disciple of magic" | "magic" => Classification::Magic, + "disciple of the land" | "land" => Classification::Land, + "disciple of the hand" | "hand" => Classification::Hand, + _ => return Err(UnknownVariant("Classification", s.into())) + }; + + Ok(class) + } +} + +impl Display for Classification { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + write!(f, "{}", self.as_str()) + } +} diff --git a/src/jobs.rs b/src/jobs/mod.rs similarity index 69% rename from src/jobs.rs rename to src/jobs/mod.rs index 5f6b9cc..037824c 100644 --- a/src/jobs.rs +++ b/src/jobs/mod.rs @@ -1,9 +1,18 @@ +//! Job types + +pub mod classification; +pub mod non_combat; + +pub use self::classification::Classification; +pub use self::non_combat::NonCombatJob; + use errors::UnknownVariant; use roles::Role; use std::fmt::{Display, Formatter, Result as FmtResult}; use std::str::FromStr; +/// The Disciple of War and Disciple of Magic jobs available in the game. #[derive(Debug, Clone, Copy)] pub enum Job { // DPS @@ -52,6 +61,9 @@ impl Job { Job::Warrior, ]; + /// Returns the string representation of this job. + /// + /// Jobs are title-cased and have spaces between words (e.g. "Bard" and "Black Mage"). pub fn as_str(&self) -> &'static str { match *self { Job::Bard => "Bard", @@ -74,6 +86,7 @@ impl Job { } } + /// Returns the [`Role`] for this job. pub fn role(&self) -> Role { match *self { Job::Bard | @@ -95,11 +108,39 @@ impl Job { Job::Warrior => Role::Tank, } } + + /// Returns the [`Classification`] for this job. + pub fn classification(&self) -> Classification { + match *self { + Job::Bard | + Job::DarkKnight | + Job::Dragoon | + Job::Machinist | + Job::Monk | + Job::Ninja | + Job::Paladin | + Job::Samurai | + Job::Warrior => Classification::War, + + Job::Astrologian | + Job::BlackMage | + Job::RedMage | + Job::Scholar | + Job::Summoner | + Job::WhiteMage => Classification::Magic, + } + } } impl FromStr for Job { type Err = UnknownVariant; + /// Parses a string `s` to return a value of this type. + /// + /// This accepts the name of the variant as a string, the name of the variant as a string with + /// spaces between words, and the shortened job code for each variant (e.g. "BLM" for Black Mage). + /// + /// This is case-insensitive. fn from_str(s: &str) -> Result { let job = match s.to_lowercase().as_str() { "bard" | "brd" => Job::Bard, diff --git a/src/jobs/non_combat.rs b/src/jobs/non_combat.rs new file mode 100644 index 0000000..cacc6aa --- /dev/null +++ b/src/jobs/non_combat.rs @@ -0,0 +1,107 @@ +//! Non-combat job types + +use jobs::classification::Classification; +use errors::UnknownVariant; + +use std::fmt::{Display, Formatter, Result as FmtResult}; +use std::str::FromStr; + +/// The Disciple of the Land and Disciple of the Hand jobs available in the game. +#[derive(Debug, Clone, Copy)] +pub enum NonCombatJob { + // Gatherers + Botanist, + Fisher, + Miner, + + // Crafters + Alchemist, + Armorer, + Blacksmith, + Carpenter, + Culinarian, + Goldsmith, + Leatherworker, + Weaver, +} + +impl NonCombatJob { + pub const ALL: [NonCombatJob; 11] = [ + NonCombatJob::Botanist, + NonCombatJob::Fisher, + NonCombatJob::Miner, + + NonCombatJob::Alchemist, + NonCombatJob::Armorer, + NonCombatJob::Blacksmith, + NonCombatJob::Carpenter, + NonCombatJob::Culinarian, + NonCombatJob::Goldsmith, + NonCombatJob::Leatherworker, + NonCombatJob::Weaver, + ]; + + pub fn as_str(&self) -> &'static str { + match *self { + NonCombatJob::Botanist => "Botanist", + NonCombatJob::Fisher => "Fisher", + NonCombatJob::Miner => "Miner", + + NonCombatJob::Alchemist => "Alchemist", + NonCombatJob::Armorer => "Armorer", + NonCombatJob::Blacksmith => "Blacksmith", + NonCombatJob::Carpenter => "Carpenter", + NonCombatJob::Culinarian => "Culinarian", + NonCombatJob::Goldsmith => "Goldsmith", + NonCombatJob::Leatherworker => "Leatherworker", + NonCombatJob::Weaver => "Weaver", + } + } + + pub fn classification(&self) -> Classification { + match *self { + NonCombatJob::Botanist | + NonCombatJob::Fisher | + NonCombatJob::Miner => Classification::Land, + + NonCombatJob::Alchemist | + NonCombatJob::Armorer | + NonCombatJob::Blacksmith | + NonCombatJob::Carpenter | + NonCombatJob::Culinarian | + NonCombatJob::Goldsmith | + NonCombatJob::Leatherworker | + NonCombatJob::Weaver => Classification::Hand, + } + } +} + +impl FromStr for NonCombatJob { + type Err = UnknownVariant; + + fn from_str(s: &str) -> Result { + let job = match s.to_lowercase().as_str() { + "botanist" => NonCombatJob::Botanist, + "fisher" => NonCombatJob::Fisher, + "miner" => NonCombatJob::Miner, + + "alchemist" => NonCombatJob::Alchemist, + "armorer" => NonCombatJob::Armorer, + "blacksmith" => NonCombatJob::Blacksmith, + "carpenter" => NonCombatJob::Carpenter, + "culinarian" => NonCombatJob::Culinarian, + "goldsmith" => NonCombatJob::Goldsmith, + "leatherworker" => NonCombatJob::Leatherworker, + "weaver" => NonCombatJob::Weaver, + _ => return Err(UnknownVariant("NonCombatJob", s.into())) + }; + + Ok(job) + } +} + +impl Display for NonCombatJob { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + write!(f, "{}", self.as_str()) + } +} diff --git a/src/lib.rs b/src/lib.rs index ec3393c..ec316df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,6 @@ pub mod roles; pub mod worlds; pub use self::data_centers::DataCenter; -pub use self::jobs::Job; +pub use self::jobs::{Job, NonCombatJob, Classification}; pub use self::roles::Role; pub use self::worlds::World;