1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::time::{SystemTime, UNIX_EPOCH};
4
5#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
6pub struct Card {
7 pub card_id: u128,
8 pub n: u32,
9 pub ef: f32,
10 pub i: u32,
11 pub due: DateTime<Utc>,
12 pub needs_extra_review: bool,
13}
14
15impl Default for Card {
16 fn default() -> Self {
17 Self {
18 card_id: now_millis(),
19 n: 0,
20 ef: 2.5,
21 i: 0,
22 due: Utc::now(),
23 needs_extra_review: false,
24 }
25 }
26}
27
28impl Card {
29 pub fn to_json(&self) -> Result<String, serde_json::Error> {
30 serde_json::to_string(self)
31 }
32
33 pub fn from_json(json: &str) -> Result<Card, serde_json::Error> {
34 serde_json::from_str(json)
35 }
36}
37
38fn now_millis() -> u128 {
39 SystemTime::now()
40 .duration_since(UNIX_EPOCH)
41 .expect("SystemTime::now() is before UNIX_EPOCH")
42 .as_millis()
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use chrono::Duration;
49
50 #[test]
51 fn create_card_with_default_values() {
52 let card = Card::default();
53
54 assert!(card.card_id > 0);
55
56 assert_eq!(card.n, 0);
57 assert_eq!(card.ef, 2.5);
58 assert_eq!(card.i, 0);
59
60 let now = Utc::now();
61 assert!(now >= card.due);
62 assert!(now - card.due <= Duration::milliseconds(10));
63
64 assert!(!card.needs_extra_review);
65 }
66}