Skip to content

Commit

Permalink
Merge pull request #4 from brandonphelps/feature/dungeon
Browse files Browse the repository at this point in the history
feature/dungeon
  • Loading branch information
Brandon Phelps authored Jan 11, 2021
2 parents f33312d + c0d6dda commit 73ab8db
Show file tree
Hide file tree
Showing 6 changed files with 849 additions and 7 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
reqwest = { version = "0.11", features = ["json", "blocking"] }
serde_derive = "^1.0"
serde = "^1.0"
derive_more = "0.99.11"
17 changes: 10 additions & 7 deletions src/coins.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
extern crate derive_more;
use derive_more::Add;

/// Represents a monetary amount.
///
/// The inner value is the total number of copper coins.
Expand All @@ -6,7 +9,7 @@
/// one silver coin and every 100 silver coins is one gold coin.
///
/// The Display trait uses this in game format.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Add)]
pub struct Coins(i32);

impl Coins {
Expand All @@ -16,8 +19,8 @@ impl Coins {
}

/// Creates an amount of currency from a number of gold coins.
pub fn from_gold(gold: impl Into<i32>) -> Self {
Coins(gold.into() * 1_00_00)
pub const fn from_gold(gold: i32) -> Self {
Coins(gold * 1_00_00)
}

/// The number of silver coins.
Expand All @@ -26,8 +29,8 @@ impl Coins {
}

/// Creates an amount of currency from a number of silver coins.
pub fn from_silver(silver: impl Into<i32>) -> Self {
Coins(silver.into() * 1_00)
pub const fn from_silver(silver: i32) -> Self {
Coins(silver * 1_00)
}

/// The number of copper coins.
Expand All @@ -36,8 +39,8 @@ impl Coins {
}

/// Creates an amount of currency from a number of copper coins.
pub fn from_copper(copper: impl Into<i32>) -> Self {
Coins(copper.into())
pub const fn from_copper(copper: i32) -> Self {
Coins(copper)
}
}

Expand Down
205 changes: 205 additions & 0 deletions src/dungeon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
mod info;
use info::{DungeonInfo, PathInfo, Rewards, DUNGEONS};

mod user;
pub use user::UserProgress;

use crate::Coins;

/// Information about a dungeon.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dungeon {
info: &'static DungeonInfo,
}

/// Information about a path within a dungeon.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Path {
info: &'static PathInfo,
dungeon: &'static DungeonInfo,
}

impl Dungeon {
/// Gets every dungeon.
pub fn all() -> Vec<Self> {
DUNGEONS.iter().map(|x| Self { info: x }).collect()
}

/// Gets the name of the dungeon.
pub fn name(&self) -> &str {
self.info.long_name
}

/// Gets a short name for this dungeon.
pub fn short_name(&self) -> &str {
self.info.short_name
}

/// Gets the achievement id of the skin collection achievement for this dungeon.
pub fn collection_id(&self) -> u32 {
self.info.collection_id
}

/// Gets the wallet currency id of the dungeon token for this dungeon.
pub fn currency_id(&self) -> u32 {
self.info.currency_id
}

/// Gets all paths in this dungeon.
pub fn paths(&self) -> Vec<Path> {
self.info
.paths
.iter()
.map(|path| Path {
info: path,
dungeon: self.info,
})
.collect()
}
}

impl Path {
/// Gets every dungeon path.
pub fn all() -> Vec<Path> {
Dungeon::all().iter().flat_map(Dungeon::paths).collect()
}

/// Looks up a path by its id.
pub fn from_id(path_id: &str) -> Option<Path> {
for path in Self::all() {
if path_id == path.id() {
return Some(path);
}
}
None
}

/// Looks up a path by its index into the dungeon frequenter bits list.
pub fn from_dungeon_frequenter_index(index: u8) -> Option<Path> {
for path in Self::all() {
if Some(index) == path.dungeon_frequenter_index() {
return Some(path);
}
}
None
}

/// Gets the dungeon that contains this path.
pub fn dungeon(&self) -> Dungeon {
Dungeon { info: self.dungeon }
}

/// Gets the unique dungeon path id used by the GW2 API for this path.
pub fn id(&self) -> &str {
self.info.id
}

/// Gets the name of this path.
pub fn name(&self) -> &str {
self.info.long_name
}

/// Gets a short name for this path. This is typically used in LFG.
pub fn short_name(&self) -> &str {
self.info.short_name
}

/// Gets the index into the dungeon frequenter achievement bits array
/// in the GW2 achievement API for this dungeon path.
pub fn dungeon_frequenter_index(&self) -> Option<u8> {
self.info.dungeon_frequenter_index
}

/// The number of coins gotten by doing this dungeon path the first
/// time in a day.
pub fn coins(&self) -> Coins {
match self.info.rewards {
Rewards::Story { coins } => coins,
Rewards::Explorable { bonus_coins } => Coins::from_silver(26) + bonus_coins,
}
}

/// The number of coins gotten by doing this dungeon repeatedly in a day.
pub fn repeat_coins(&self) -> Coins {
match self.info.rewards {
Rewards::Story { coins } => coins,
Rewards::Explorable { .. } => Coins::from_silver(26),
}
}

/// The number of tokens gotten by doing this dungeon path the first
/// time in a day.
pub fn tokens(&self) -> u32 {
match self.info.rewards {
Rewards::Story { .. } => 0,
Rewards::Explorable { .. } => 100,
}
}

/// The number of tokens gotten by doing this dungeon repeatedly in a day.
pub fn repeat_tokens(&self) -> u32 {
match self.info.rewards {
Rewards::Story { .. } => 0,
Rewards::Explorable { .. } => 20,
}
}
}

#[cfg(test)]
/// NOTE: Many tests have hard coded constants that must be changed if dungeon rewards
/// are reworked or more dungeons are added.
mod test {
use super::*;

#[test]
fn all_dungeons() {
assert_eq!(Dungeon::all().len(), 8);
}

#[test]
fn all_paths() {
assert_eq!(Path::all().len(), 33);
}

#[test]
fn from_id() {
assert_eq!(Path::from_id("coe_story").unwrap().id(), "coe_story");
assert!(Path::from_id("bad_id").is_none());
}

#[test]
fn from_dungeon_frequenter_index() {
assert_eq!(
Path::from_dungeon_frequenter_index(5)
.unwrap()
.dungeon_frequenter_index(),
Some(5)
);
assert!(Path::from_dungeon_frequenter_index(100).is_none());
}

#[test]
fn ac_story_rewards() {
let path = Path::from_id("ac_story").unwrap();

assert_eq!(Coins::from_silver(13), path.coins());
assert_eq!(Coins::from_silver(13), path.repeat_coins());

assert_eq!(0, path.tokens());
assert_eq!(0, path.repeat_tokens());
}

#[test]
fn ac_p1_rewards() {
let path = Path::from_id("hodgins").unwrap();

assert_eq!(
Coins::from_silver(50) + Coins::from_silver(26),
path.coins()
);
assert_eq!(Coins::from_silver(26), path.repeat_coins());

assert_eq!(100, path.tokens());
assert_eq!(20, path.repeat_tokens());
}
}
Loading

0 comments on commit 73ab8db

Please sign in to comment.