Files
jap_learn/src/data_provider/card_states.rs
T

96 lines
3.1 KiB
Rust
Raw Normal View History

2026-09-09 15:00:52 +03:00
use crate::data::entities::CardState;
2026-09-09 10:08:52 +03:00
use crate::data::repositories::{DataRepository, DataRepositoryInner, Query};
2026-09-09 15:00:52 +03:00
use crate::data::Id;
2026-08-31 11:52:54 +03:00
use crate::data_provider::{SqliteDbLayer, TableAccessQuerySet};
2026-08-28 18:52:38 +03:00
use chrono::NaiveDate;
use fsrs::MemoryState;
2026-09-09 15:00:52 +03:00
use rusqlite::{Error, Params, Row};
use std::sync::Arc;
2026-04-13 22:25:58 +03:00
2026-09-09 15:00:52 +03:00
pub type CardStateRepository = DataRepository<CardState, CardStateDbLayer>;
pub type CardStateRepositoryInner = DataRepositoryInner<CardState, CardStateDbLayer>;
2026-09-09 10:08:52 +03:00
pub type CardStateDbLayer = SqliteDbLayer<CardState, CardStatesQuerySet>;
2026-08-31 14:35:11 +03:00
#[derive(Clone)]
2026-08-30 20:43:31 +03:00
pub struct CardStatesQuerySet;
impl TableAccessQuerySet<CardState> for CardStatesQuerySet {
fn load() -> &'static str {
2026-09-06 23:55:50 +03:00
"SELECT id, word_id, deck_id, score, last_opened, fsrs_opened, fsrs_memory, fsrs_open_day FROM states"
2026-08-30 20:43:31 +03:00
}
fn save() -> &'static str {
2026-09-08 00:09:13 +03:00
"UPDATE states SET score = ?1, last_opened = ?2, fsrs_opened = ?3, fsrs_memory = ?4, fsrs_open_day = ?5 WHERE id = ?6"
2026-08-30 20:43:31 +03:00
}
fn add() -> &'static str {
2026-09-08 00:09:13 +03:00
"INSERT INTO states (word_id, deck_id, score, last_opened, fsrs_opened, fsrs_memory, fsrs_open_day) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"
2026-08-30 20:43:31 +03:00
}
fn name() -> &'static str {
"states"
}
fn from_sql(row: &Row) -> Result<CardState, Error> {
Ok(CardState {
id: row.get(0)?,
word_id: row.get(1)?,
2026-09-06 23:55:50 +03:00
deck_id: row.get(2)?,
2026-08-30 20:46:52 +03:00
score: row.get(3)?,
fsrs_opened: NaiveDate::from_epoch_days(row.get::<usize, i32>(5)?)
2026-08-30 20:43:31 +03:00
.expect("Incorrect date encoding"),
2026-08-30 20:46:52 +03:00
fsrs_memory: get_memory(row.get(6)?),
last_open: row.get(4)?,
fsrs_open_day: NaiveDate::from_epoch_days(row.get::<usize, i32>(7)?)
2026-08-30 20:43:31 +03:00
.expect("Incorrect date encoding"),
})
}
fn insert_params(entity: &CardState) -> impl Params {
(
entity.word_id,
2026-09-06 23:55:50 +03:00
entity.deck_id,
2026-08-30 20:43:31 +03:00
entity.score,
entity.last_open.timestamp(),
entity.fsrs_opened.to_epoch_days(),
memory_to_i64(&entity.fsrs_memory),
entity.fsrs_open_day.to_epoch_days(),
)
}
fn update_params(entity: &CardState) -> impl Params {
2026-09-08 00:09:13 +03:00
(
entity.score,
entity.last_open.timestamp(),
2026-09-09 10:08:52 +03:00
entity.fsrs_opened.to_epoch_days(),
2026-09-08 00:09:13 +03:00
memory_to_i64(&entity.fsrs_memory),
2026-09-09 10:08:52 +03:00
entity.fsrs_open_day.to_epoch_days(),
entity.id,
2026-09-08 00:09:13 +03:00
)
2026-08-30 20:43:31 +03:00
}
}
2026-04-13 22:25:58 +03:00
2026-08-30 20:32:16 +03:00
fn get_memory(value: i64) -> Option<MemoryState> {
if value == 0 {
return None;
}
Some(MemoryState {
2026-08-28 18:52:38 +03:00
stability: f32::from_bits(value as u32),
difficulty: f32::from_bits((value >> 32) as u32),
2026-08-30 20:32:16 +03:00
})
2026-08-28 18:52:38 +03:00
}
2026-08-30 20:32:16 +03:00
fn memory_to_i64(value: &Option<MemoryState>) -> i64 {
let Some(value) = &value else {
return 0;
};
2026-08-28 18:52:38 +03:00
value.stability.to_bits() as i64 | ((value.difficulty.to_bits() as i64) << 32)
}
2026-09-09 10:08:52 +03:00
impl CardStateRepositoryInner {
2026-09-09 15:00:52 +03:00
pub fn deck_states(
&self,
deck_id: Id,
) -> Query<CardState, CardStateRepositoryInner, CardStateDbLayer> {
self.query(Arc::new(move |state| state.deck_id == deck_id))
2026-08-20 16:22:38 +03:00
}
2026-09-09 15:00:52 +03:00
}