From 55bdc5a7ad12bdcaa2f0c1f478e4548c6b3eaff0 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Mon, 31 Aug 2026 14:35:11 +0300 Subject: [PATCH] New repository methods --- src/app.rs | 3 ++ src/core/deck.rs | 2 +- src/data/entities.rs | 63 ++++++++++++++------------------ src/data/repositories.rs | 35 +++++++++++++++--- src/data_provider/card_states.rs | 1 + 5 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/app.rs b/src/app.rs index dc7e187..3534593 100644 --- a/src/app.rs +++ b/src/app.rs @@ -17,6 +17,7 @@ use log::info; use parking_lot::RwLock; use rusqlite::Connection; use crate::data::repositories::Repository; +use crate::data_provider::card_states::CardStateRepository; use crate::data_provider::word_groups::WordGroupRepository; pub const USER_FONT: Font = Font::with_name("Noto Sans JP"); @@ -65,6 +66,7 @@ pub struct AppState { pub dictionary: WordRepository, pub decks: DeckRepository, pub word_groups: WordGroupRepository, + pub card_states: CardStateRepository, pub connection: Arc>, pub sync_data: Arc>, pub activity: HashMap>, @@ -83,6 +85,7 @@ impl AppState { dictionary: WordRepository::new(connection.clone()), decks: DeckRepository::new(connection.clone()), word_groups: WordGroupRepository::new(connection.clone()), + card_states: CardStateRepository::new(connection.clone()), sync_data: Arc::new(RwLock::new(AppSettings { key: None, auto_web_fetch: false, diff --git a/src/core/deck.rs b/src/core/deck.rs index d5aca96..c08f4fa 100644 --- a/src/core/deck.rs +++ b/src/core/deck.rs @@ -27,7 +27,7 @@ impl DeckData { ) -> Result { let state_for = state.clone(); - let stats = load_stats_of_deck(settings, &state.connection.read())?; + let stats = state (settings, &state.connection.read())?; let words = stats .iter() .map(|stat| { diff --git a/src/data/entities.rs b/src/data/entities.rs index 9f42fc1..de19116 100644 --- a/src/data/entities.rs +++ b/src/data/entities.rs @@ -1,5 +1,6 @@ use crate::app::AppState; use crate::core::srs::{FADE_PER_DAY, MAX_SCORE, OrderMode, WordOpenMode}; +use crate::data::repositories::Repository; use crate::data::{INVALID_ID, Id}; use chrono::{DateTime, NaiveDate, Utc}; use fsrs::MemoryState; @@ -116,42 +117,34 @@ impl DeckSettings { let ast = engine.compile(&self.filter); if let Ok(ast) = ast { - let groups = &state.word_groups; + let groups = state.word_groups.read(); + let query = state + .dictionary.read().query_par(| word: &WordData|{ + let mut more = rhai::Map::new(); + for iced in &word.additional { + more.insert(iced.0.clone().into(), iced.1.clone().into()); + } + let mut scope = Scope::new(); + let group_name = groups.get_ref(&mut groups.handle_by_id(word.group_id)).unwrap().name; - list = state - .dictionary - .par_iter() - .enumerate() - .filter(|(_, word)| { - let mut more = rhai::Map::new(); - for iced in &word.additional { - more.insert(iced.0.clone().into(), iced.1.clone().into()); - } - let mut scope = Scope::new(); - scope - .push_constant("id", word.id.0 as i64) - .push_constant("key", word.key.clone()) - .push_constant("value", word.value.clone()) - .push_constant("tags", word.tags.clone()) - .push_constant("more", more) - .push_constant( - "group", - groups - .iter() - .find(|g| g.id == word.group_id) - .cloned() - .expect("No group id") - .name, - ); + scope + .push_constant("id", word.id.0 as i64) + .push_constant("key", word.key.clone()) + .push_constant("value", word.value.clone()) + .push_constant("tags", word.tags.clone()) + .push_constant("more", more) + .push_constant( + "group", + group_name, + ); + + let result = engine.eval_ast_with_scope::(&mut scope, &ast); + if let Ok(result) = result { + return result; + } + false + }); - let result = engine.eval_ast_with_scope::(&mut scope, &ast); - if let Ok(result) = result { - return result; - } - false - }) - .map(|(index, _)| index) - .collect(); info!("Collecting available words is {:?}", time.elapsed()); @@ -214,7 +207,7 @@ impl CardState { } } -pub struct CustomField{ +pub struct CustomField { pub id: Id, pub name: String, } diff --git a/src/data/repositories.rs b/src/data/repositories.rs index 2c23a7d..e19dc6b 100644 --- a/src/data/repositories.rs +++ b/src/data/repositories.rs @@ -1,5 +1,5 @@ use crate::data::Id; -use crate::data::entities::{EntityData, EntityHandle}; +use crate::data::entities::{EntityData, EntityHandle, WordData}; use crate::helpers::into_result; use crate::notification::{MaybeError, NotificationData}; use parking_lot::{Mutex, RwLock}; @@ -24,9 +24,11 @@ where fn create_now(&mut self, new: T) -> Result, NotificationData>; fn save(&mut self, entity: &mut EntityHandle) -> MaybeError; fn delete(&mut self, handle: EntityHandle) -> MaybeError; + fn find(&self, predicate: F) -> Option> where F : Fn(&T) -> bool; fn init(&mut self) -> MaybeError; fn start(&mut self) -> MaybeError; fn reload(&mut self) -> MaybeError; + fn shifts(&self) -> usize; } struct QueryManger @@ -101,14 +103,17 @@ where rule: Box bool + Send + Sync>, parallel: bool, _marker: PhantomData<(R, D)>, - shift_stamp: u16, + shift_stamp: usize, } -impl, D: DbLayer> Query { - pub fn iter<'a>(&mut self, data_repository_inner: &'a R) -> impl Iterator +impl, D: DbLayer> Query { + pub fn iter<'a>(&mut self, data_repository_inner: &'a DataRepositoryInner) -> impl Iterator where T: 'a, { + if self.shift_stamp != data_repository_inner.shifts() { + self.load(data_repository_inner); + } self.cache .iter_mut() .filter_map(move |e| data_repository_inner.get_ref(e)) @@ -197,7 +202,7 @@ pub struct DataRepositoryInner> data_layer: D, query_manger: QueryManger, version: u16, - shifts: u16, + shifts: usize, } impl + std::default::Default> DataRepository { @@ -389,6 +394,22 @@ impl> Repository for DataRepositoryIn Ok(()) } + fn find(&self, predicate: F) -> Option> + where + F: Fn(&T) -> bool + { + if let Some(index) = self.cache.iter().position(|entity| predicate(entity)){ + let value = &self.cache[index]; + return Some(EntityHandle::new(value.id(), index, true)) + } + + if let Some(index) = self.temporal.iter().position(|entity| predicate(entity)){ + let value = &self.temporal[index]; + return Some(EntityHandle::new(value.id(), index, false)) + } + None + } + fn init(&mut self) -> MaybeError { self.data_layer .load_all(&mut self.cache, &self.connection.read())?; @@ -411,6 +432,10 @@ impl> Repository for DataRepositoryIn self.init()?; Ok(()) } + + fn shifts(&self) -> usize { + self.shifts + } } impl + DbLayer> BatchedRepository for DataRepositoryInner diff --git a/src/data_provider/card_states.rs b/src/data_provider/card_states.rs index 7be5ec8..1091d4c 100644 --- a/src/data_provider/card_states.rs +++ b/src/data_provider/card_states.rs @@ -10,6 +10,7 @@ use std::time::Instant; use crate::data::repositories::DataRepository; pub type CardStateRepository = DataRepository>; +#[derive(Clone)] pub struct CardStatesQuerySet; impl TableAccessQuerySet for CardStatesQuerySet { fn load() -> &'static str {