1use crate::consts::XP_STAKE_DIVISOR;
6use crate::state::{Dojo, Stake, Treasury};
7
8#[inline]
10pub fn xp_from_battle_points_moved(points_moved: u64) -> u64 {
11 if points_moved == 0 {
12 return 0;
13 }
14 let bps = crate::consts::XP_BATTLE_BP_TO_REWARD_BPS as u128;
15 ((points_moved as u128).saturating_mul(bps) / 10_000u128) as u64
16}
17
18#[inline]
20pub fn add_reward_points_xp(dojo: &mut Dojo, treasury: &mut Treasury, gain: u64) {
21 if gain == 0 {
22 return;
23 }
24 dojo.xp = dojo.xp.saturating_add(gain);
25 treasury.total_xp = treasury.total_xp.saturating_add(gain);
26}
27
28pub fn accrue_stake_xp(stake: &mut Stake, dojo: &mut Dojo, treasury: &mut Treasury, now: u64) {
30 if stake.last_xp_accrual_slot == 0 {
31 stake.last_xp_accrual_slot = now;
32 return;
33 }
34 let delta = now.saturating_sub(stake.last_xp_accrual_slot);
35 stake.last_xp_accrual_slot = now;
36 if delta == 0 || stake.balance == 0 {
37 return;
38 }
39 let num = (stake.balance as u128).saturating_mul(delta as u128);
40 let gain = (num / XP_STAKE_DIVISOR) as u64;
41 if gain > 0 {
42 dojo.xp = dojo.xp.saturating_add(gain);
43 treasury.total_xp = treasury.total_xp.saturating_add(gain);
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::xp_from_battle_points_moved;
50
51 #[test]
52 fn xp_from_battle_points_moved_scales() {
53 assert_eq!(xp_from_battle_points_moved(0), 0);
54 assert_eq!(xp_from_battle_points_moved(500), 50);
56 }
57}