use std::fmt;
use std::ops::{Add, AddAssign};
use separator::Separatable;
#[derive(Clone, Copy)]
pub struct Experience {
current: u64,
total: u64,
}
impl Experience {
#[inline]
pub fn new(current: u64, total: u64) -> Self {
assert!(total > 0, "Total experience cannot be zero");
assert!(current <= total, "Current experience must not be greater than total");
Experience { current, total }
}
#[inline]
pub fn zero_out_of(total: u64) -> Self {
assert!(total > 0, "Total experience cannot be zero");
Experience { current: 0, total }
}
#[inline]
pub fn full(total: u64) -> Self {
assert!(total > 0, "Total experience cannot be zero");
Experience { current: total, total }
}
}
impl Experience {
#[inline]
pub fn current(&self) -> u64 {
self.current
}
#[inline]
pub fn total(&self) -> u64 {
self.total
}
#[inline]
pub fn is_empty(&self) -> bool {
self.current == 0
}
#[inline]
pub fn is_full(&self) -> bool {
self.current == self.total
}
pub fn fraction(&self) -> f64 {
self.current as f64 / self.total as f64
}
pub fn percentage(&self) -> f64 {
self.fraction() * 100.0
}
}
impl Add<u64> for Experience {
type Output = Experience;
fn add(mut self, rhs: u64) -> Self {
self += rhs; self
}
}
impl AddAssign<u64> for Experience {
fn add_assign(&mut self, rhs: u64) {
let new = self.total.min(self.current + rhs);
self.current = new;
}
}
impl fmt::Display for Experience {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}/{}", self.current.separated_string(), self.total.separated_string())
}
}
impl fmt::Debug for Experience {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_tuple("Experience")
.field(&self.current)
.field(&self.total)
.finish()
}
}