use super::{BonusTrack, PushContext, Reward, Tier};
pub struct FirstPush;
static TIERS: &[Tier] = &[
Tier {
cost: 50,
reward: Reward::FlatPoints(5),
},
Tier {
cost: 500,
reward: Reward::FlatPoints(10),
},
Tier {
cost: 3000,
reward: Reward::FlatPoints(20),
},
Tier {
cost: 20000,
reward: Reward::FlatPoints(50),
},
Tier {
cost: 120000,
reward: Reward::FlatPoints(100),
},
];
impl BonusTrack for FirstPush {
fn id(&self) -> &'static str {
"first_push"
}
fn name(&self) -> &'static str {
"First Push of the Day"
}
fn description(&self) -> &'static str {
"Some bonus points for your first push each day."
}
fn tiers(&self) -> &'static [Tier] {
TIERS
}
fn applies(&self, ctx: &PushContext) -> u32 {
let pushed_today = ctx
.history
.count_since(ctx.clock.today_start())
.unwrap_or_default()
!= 0;
if pushed_today { 0 } else { 1 }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
bonus_track::Clock,
git::{Commit, Push},
storage::{DbConnection, PushEntry, PushHistory},
};
const TODAY_9AM: u64 = 1769594400; const TODAY_3PM: u64 = 1769616000; const YESTERDAY_9AM: u64 = 1769508000;
const JAN28_9AM_LOCAL: u64 = 1769522400; const JAN28_11PM_LOCAL: u64 = 1769572800; const UTC_MINUS_5: i32 = -5 * 3600;
#[test]
fn respects_local_timezone() {
let conn = DbConnection::create_in_memory().unwrap();
let bonus = FirstPush;
let push = Push::new(vec![Commit::default()]);
let history = PushHistory::new(&conn).with_entries([PushEntry::at(JAN28_9AM_LOCAL)]);
let clock = Clock::with_offset(JAN28_11PM_LOCAL, UTC_MINUS_5);
let ctx = PushContext {
push: &push,
history: &history,
clock: &clock,
};
assert_eq!(bonus.applies(&ctx), 0);
}
#[test]
fn applies_when_no_pushes_today() {
let conn = DbConnection::create_in_memory().unwrap();
let bonus = FirstPush;
let push = Push::new(vec![Commit::default()]);
let history = PushHistory::new(&conn).with_entries([PushEntry::at(YESTERDAY_9AM)]);
let clock = Clock::at(TODAY_9AM);
let ctx = PushContext {
push: &push,
history: &history,
clock: &clock,
};
assert_eq!(bonus.applies(&ctx), 1);
}
#[test]
fn does_not_apply_when_already_pushed_today() {
let conn = DbConnection::create_in_memory().unwrap();
let bonus = FirstPush;
let push = Push::new(vec![Commit::default()]);
let history = PushHistory::new(&conn).with_entries([PushEntry::at(TODAY_9AM)]);
let clock = Clock::at(TODAY_3PM);
let ctx = PushContext {
push: &push,
history: &history,
clock: &clock,
};
assert_eq!(bonus.applies(&ctx), 0);
}
#[test]
fn applies_on_first_push_ever() {
let conn = DbConnection::create_in_memory().unwrap();
let bonus = FirstPush;
let push = Push::new(vec![Commit::default()]);
let history = PushHistory::new(&conn);
let clock = Clock::at(TODAY_9AM);
let ctx = PushContext {
push: &push,
history: &history,
clock: &clock,
};
assert_eq!(bonus.applies(&ctx), 1);
}
}