97 lines
3.1 KiB
Rust
97 lines
3.1 KiB
Rust
use crate::data::entities::CardState;
|
|
use crate::data::repositories::{DataRepository, DataRepositoryInner, Query};
|
|
use crate::data::Id;
|
|
use crate::data_provider::{SqliteDbLayer, TableAccessQuerySet};
|
|
use chrono::NaiveDate;
|
|
use fsrs::MemoryState;
|
|
use rusqlite::{Error, Params, Row};
|
|
use std::sync::Arc;
|
|
|
|
pub type CardStateRepository = DataRepository<CardState, CardStateDbLayer>;
|
|
pub type CardStateRepositoryInner = DataRepositoryInner<CardState, CardStateDbLayer>;
|
|
pub type CardStateDbLayer = SqliteDbLayer<CardState, CardStatesQuerySet>;
|
|
#[derive(Clone)]
|
|
pub struct CardStatesQuerySet;
|
|
impl TableAccessQuerySet<CardState> for CardStatesQuerySet {
|
|
fn load() -> &'static str {
|
|
"SELECT id, word_id, deck_id, score, last_opened, fsrs_opened, fsrs_memory, fsrs_open_day FROM states"
|
|
}
|
|
|
|
fn save() -> &'static str {
|
|
"UPDATE states SET score = ?1, last_opened = ?2, fsrs_opened = ?3, fsrs_memory = ?4, fsrs_open_day = ?5 WHERE id = ?6"
|
|
}
|
|
|
|
fn add() -> &'static str {
|
|
"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)"
|
|
}
|
|
|
|
fn name() -> &'static str {
|
|
"states"
|
|
}
|
|
|
|
fn from_sql(row: &Row) -> Result<CardState, Error> {
|
|
Ok(CardState {
|
|
id: row.get(0)?,
|
|
word_id: row.get(1)?,
|
|
deck_id: row.get(2)?,
|
|
score: row.get(3)?,
|
|
fsrs_opened: NaiveDate::from_epoch_days(row.get::<usize, i32>(5)?)
|
|
.expect("Incorrect date encoding"),
|
|
fsrs_memory: get_memory(row.get(6)?),
|
|
last_open: row.get(4)?,
|
|
fsrs_open_day: NaiveDate::from_epoch_days(row.get::<usize, i32>(7)?)
|
|
.expect("Incorrect date encoding"),
|
|
})
|
|
}
|
|
|
|
fn insert_params(entity: &CardState) -> impl Params {
|
|
(
|
|
entity.word_id,
|
|
entity.deck_id,
|
|
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 {
|
|
(
|
|
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(),
|
|
entity.id,
|
|
)
|
|
}
|
|
}
|
|
|
|
fn get_memory(value: i64) -> Option<MemoryState> {
|
|
if value == 0 {
|
|
return None;
|
|
}
|
|
Some(MemoryState {
|
|
stability: f32::from_bits(value as u32),
|
|
difficulty: f32::from_bits((value >> 32) as u32),
|
|
})
|
|
}
|
|
|
|
fn memory_to_i64(value: &Option<MemoryState>) -> i64 {
|
|
let Some(value) = &value else {
|
|
return 0;
|
|
};
|
|
|
|
value.stability.to_bits() as i64 | ((value.difficulty.to_bits() as i64) << 32)
|
|
}
|
|
|
|
impl CardStateRepositoryInner {
|
|
pub fn deck_states(
|
|
&self,
|
|
deck_id: Id,
|
|
) -> Query<CardState, CardStateRepositoryInner, CardStateDbLayer> {
|
|
self.query(Arc::new(move |state| state.deck_id == deck_id))
|
|
}
|
|
}
|