split player module

This commit is contained in:
2019-10-19 21:44:10 +02:00
parent 24807615f7
commit 2248e25aec
4 changed files with 121 additions and 110 deletions

View File

@@ -0,0 +1,119 @@
use crate::schema::players;
/// Unpack a floating value of gold pieces to integer
/// values of copper, silver, gold and platinum pieces
///
/// # Note
///
/// The conversion is slightly different than standard rules :
/// ``` 1pp = 100gp = 1000sp = 10000 cp ```
///
fn unpack_gold_value(gold: f64) -> (i32, i32, i32, i32) {
let rest = (gold.fract() * 100.0).round() as i32;
let gold = gold.trunc() as i32;
let pp = gold / 100;
let gp = gold % 100;
let sp = rest / 10;
let cp = rest % 10;
(cp, sp, gp, pp)
}
/// State of a player's wealth
///
/// Values are held as individual pieces counts.
/// Allows conversion from and to a floating amount of gold pieces.
#[derive(Queryable, AsChangeset, Serialize, Deserialize, Debug)]
#[table_name = "players"]
pub struct Wealth {
pub cp: i32,
pub sp: i32,
pub gp: i32,
pub pp: i32,
}
impl Wealth {
/// Unpack individual pieces counts from gold value
///
/// # Examples
/// ```
/// # use lootalot_db::models::Wealth;
/// let wealth = Wealth::from_gp(403.21);
/// assert_eq!(wealth.as_tuple(), (1, 2, 3, 4));
/// ```
pub fn from_gp(gp: f64) -> Self {
let (cp, sp, gp, pp) = unpack_gold_value(gp);
Self { cp, sp, gp, pp }
}
/// Convert total value to a floating value in gold pieces
///
/// # Examples
/// ```
/// # use lootalot_db::models::Wealth;
/// let wealth = Wealth{ pp: 4, gp: 5, sp: 8, cp: 4};
/// assert_eq!(wealth.to_gp(), 405.84);
/// ```
pub fn to_gp(&self) -> f64 {
let i = self.pp * 100 + self.gp;
let f = (self.sp * 10 + self.cp) as f64 / 100.0;
i as f64 + f
}
/// Pack the counts inside a tuple, from lower to higher coin value.
pub fn as_tuple(&self) -> (i32, i32, i32, i32) {
(self.cp, self.sp, self.gp, self.pp)
}
}
impl std::ops::Sub for Wealth {
type Output = Self;
/// What needs to be added to 'other' so that
/// the result equals 'self'
fn sub(self, other: Self) -> Self {
Wealth {
cp: self.cp - other.cp,
sp: self.sp - other.sp,
gp: self.gp - other.gp,
pp: self.pp - other.pp,
}
}
}
impl std::ops::Add for Wealth {
type Output = Self;
fn add(self, other: Self) -> Self {
Wealth {
cp: self.cp + other.cp,
sp: self.sp + other.sp,
gp: self.gp + other.gp,
pp: self.pp + other.pp
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_unpack_gold_values() {
use super::unpack_gold_value;
let test_values = [
(0.01, (1, 0, 0, 0)),
(0.1, (0, 1, 0, 0)),
(1.0, (0, 0, 1, 0)),
(1.23, (3, 2, 1, 0)),
(1.03, (3, 0, 1, 0)),
(100.23, (3, 2, 0, 1)),
(-100.23, (-3, -2, -0, -1)),
(10189.23, (3, 2, 89, 101)),
(141805.9, (0, 9, 5, 1418)),
(123141805.9, (0, 9, 5, 1231418)),
(-8090.20, (0, -2, -90, -80)),
];
for (tested, expected) in test_values.into_iter() {
assert_eq!(unpack_gold_value(*tested), *expected);
}
}
}