Repo integration #15
No files matched your search
@@ -17,6 +17,7 @@ use log::info;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use crate::data::repositories::Repository;
|
use crate::data::repositories::Repository;
|
||||||
|
use crate::data_provider::card_states::CardStateRepository;
|
||||||
use crate::data_provider::word_groups::WordGroupRepository;
|
use crate::data_provider::word_groups::WordGroupRepository;
|
||||||
|
|
||||||
pub const USER_FONT: Font = Font::with_name("Noto Sans JP");
|
pub const USER_FONT: Font = Font::with_name("Noto Sans JP");
|
||||||
@@ -65,6 +66,7 @@ pub struct AppState {
|
|||||||
pub dictionary: WordRepository,
|
pub dictionary: WordRepository,
|
||||||
pub decks: DeckRepository,
|
pub decks: DeckRepository,
|
||||||
pub word_groups: WordGroupRepository,
|
pub word_groups: WordGroupRepository,
|
||||||
|
pub card_states: CardStateRepository,
|
||||||
pub connection: Arc<RwLock<SqliteConnection>>,
|
pub connection: Arc<RwLock<SqliteConnection>>,
|
||||||
pub sync_data: Arc<RwLock<AppSettings>>,
|
pub sync_data: Arc<RwLock<AppSettings>>,
|
||||||
pub activity: HashMap<Id, Vec<(NaiveDate, u32)>>,
|
pub activity: HashMap<Id, Vec<(NaiveDate, u32)>>,
|
||||||
@@ -83,6 +85,7 @@ impl AppState {
|
|||||||
dictionary: WordRepository::new(connection.clone()),
|
dictionary: WordRepository::new(connection.clone()),
|
||||||
decks: DeckRepository::new(connection.clone()),
|
decks: DeckRepository::new(connection.clone()),
|
||||||
word_groups: WordGroupRepository::new(connection.clone()),
|
word_groups: WordGroupRepository::new(connection.clone()),
|
||||||
|
card_states: CardStateRepository::new(connection.clone()),
|
||||||
sync_data: Arc::new(RwLock::new(AppSettings {
|
sync_data: Arc::new(RwLock::new(AppSettings {
|
||||||
key: None,
|
key: None,
|
||||||
auto_web_fetch: false,
|
auto_web_fetch: false,
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ impl DeckData {
|
|||||||
) -> Result<Self, NotificationData> {
|
) -> Result<Self, NotificationData> {
|
||||||
let state_for = state.clone();
|
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
|
let words = stats
|
||||||
.iter()
|
.iter()
|
||||||
.map(|stat| {
|
.map(|stat| {
|
||||||
|
|||||||
+28
-35
@@ -1,5 +1,6 @@
|
|||||||
use crate::app::AppState;
|
use crate::app::AppState;
|
||||||
use crate::core::srs::{FADE_PER_DAY, MAX_SCORE, OrderMode, WordOpenMode};
|
use crate::core::srs::{FADE_PER_DAY, MAX_SCORE, OrderMode, WordOpenMode};
|
||||||
|
use crate::data::repositories::Repository;
|
||||||
use crate::data::{INVALID_ID, Id};
|
use crate::data::{INVALID_ID, Id};
|
||||||
use chrono::{DateTime, NaiveDate, Utc};
|
use chrono::{DateTime, NaiveDate, Utc};
|
||||||
use fsrs::MemoryState;
|
use fsrs::MemoryState;
|
||||||
@@ -116,42 +117,34 @@ impl DeckSettings {
|
|||||||
|
|
||||||
let ast = engine.compile(&self.filter);
|
let ast = engine.compile(&self.filter);
|
||||||
if let Ok(ast) = ast {
|
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
|
scope
|
||||||
.dictionary
|
.push_constant("id", word.id.0 as i64)
|
||||||
.par_iter()
|
.push_constant("key", word.key.clone())
|
||||||
.enumerate()
|
.push_constant("value", word.value.clone())
|
||||||
.filter(|(_, word)| {
|
.push_constant("tags", word.tags.clone())
|
||||||
let mut more = rhai::Map::new();
|
.push_constant("more", more)
|
||||||
for iced in &word.additional {
|
.push_constant(
|
||||||
more.insert(iced.0.clone().into(), iced.1.clone().into());
|
"group",
|
||||||
}
|
group_name,
|
||||||
let mut scope = Scope::new();
|
);
|
||||||
scope
|
|
||||||
.push_constant("id", word.id.0 as i64)
|
let result = engine.eval_ast_with_scope::<bool>(&mut scope, &ast);
|
||||||
.push_constant("key", word.key.clone())
|
if let Ok(result) = result {
|
||||||
.push_constant("value", word.value.clone())
|
return result;
|
||||||
.push_constant("tags", word.tags.clone())
|
}
|
||||||
.push_constant("more", more)
|
false
|
||||||
.push_constant(
|
});
|
||||||
"group",
|
|
||||||
groups
|
|
||||||
.iter()
|
|
||||||
.find(|g| g.id == word.group_id)
|
|
||||||
.cloned()
|
|
||||||
.expect("No group id")
|
|
||||||
.name,
|
|
||||||
);
|
|
||||||
|
|
||||||
let result = engine.eval_ast_with_scope::<bool>(&mut scope, &ast);
|
|
||||||
if let Ok(result) = result {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
})
|
|
||||||
.map(|(index, _)| index)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
info!("Collecting available words is {:?}", time.elapsed());
|
info!("Collecting available words is {:?}", time.elapsed());
|
||||||
|
|
||||||
@@ -214,7 +207,7 @@ impl CardState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CustomField{
|
pub struct CustomField {
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::data::Id;
|
use crate::data::Id;
|
||||||
use crate::data::entities::{EntityData, EntityHandle};
|
use crate::data::entities::{EntityData, EntityHandle, WordData};
|
||||||
use crate::helpers::into_result;
|
use crate::helpers::into_result;
|
||||||
use crate::notification::{MaybeError, NotificationData};
|
use crate::notification::{MaybeError, NotificationData};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
@@ -24,9 +24,11 @@ where
|
|||||||
fn create_now(&mut self, new: T) -> Result<EntityHandle<T>, NotificationData>;
|
fn create_now(&mut self, new: T) -> Result<EntityHandle<T>, NotificationData>;
|
||||||
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError;
|
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError;
|
||||||
fn delete(&mut self, handle: EntityHandle<T>) -> MaybeError;
|
fn delete(&mut self, handle: EntityHandle<T>) -> MaybeError;
|
||||||
|
fn find<F>(&self, predicate: F) -> Option<EntityHandle<T>> where F : Fn(&T) -> bool;
|
||||||
fn init(&mut self) -> MaybeError;
|
fn init(&mut self) -> MaybeError;
|
||||||
fn start(&mut self) -> MaybeError;
|
fn start(&mut self) -> MaybeError;
|
||||||
fn reload(&mut self) -> MaybeError;
|
fn reload(&mut self) -> MaybeError;
|
||||||
|
fn shifts(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct QueryManger<T, R, D>
|
struct QueryManger<T, R, D>
|
||||||
@@ -101,14 +103,17 @@ where
|
|||||||
rule: Box<dyn Fn(&T) -> bool + Send + Sync>,
|
rule: Box<dyn Fn(&T) -> bool + Send + Sync>,
|
||||||
parallel: bool,
|
parallel: bool,
|
||||||
_marker: PhantomData<(R, D)>,
|
_marker: PhantomData<(R, D)>,
|
||||||
shift_stamp: u16,
|
shift_stamp: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: EntityData + Clone, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
|
impl<T: EntityData + Clone + Send + Sync, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
|
||||||
pub fn iter<'a>(&mut self, data_repository_inner: &'a R) -> impl Iterator<Item = &'a T>
|
pub fn iter<'a>(&mut self, data_repository_inner: &'a DataRepositoryInner<T, D>) -> impl Iterator<Item = &'a T>
|
||||||
where
|
where
|
||||||
T: 'a,
|
T: 'a,
|
||||||
{
|
{
|
||||||
|
if self.shift_stamp != data_repository_inner.shifts() {
|
||||||
|
self.load(data_repository_inner);
|
||||||
|
}
|
||||||
self.cache
|
self.cache
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.filter_map(move |e| data_repository_inner.get_ref(e))
|
.filter_map(move |e| data_repository_inner.get_ref(e))
|
||||||
@@ -197,7 +202,7 @@ pub struct DataRepositoryInner<T: std::clone::Clone + EntityData, D: DbLayer<T>>
|
|||||||
data_layer: D,
|
data_layer: D,
|
||||||
query_manger: QueryManger<T, Self, D>,
|
query_manger: QueryManger<T, Self, D>,
|
||||||
version: u16,
|
version: u16,
|
||||||
shifts: u16,
|
shifts: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: std::clone::Clone + EntityData, D: DbLayer<T> + std::default::Default> DataRepository<T, D> {
|
impl<T: std::clone::Clone + EntityData, D: DbLayer<T> + std::default::Default> DataRepository<T, D> {
|
||||||
@@ -389,6 +394,22 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find<F>(&self, predicate: F) -> Option<EntityHandle<T>>
|
||||||
|
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 {
|
fn init(&mut self) -> MaybeError {
|
||||||
self.data_layer
|
self.data_layer
|
||||||
.load_all(&mut self.cache, &self.connection.read())?;
|
.load_all(&mut self.cache, &self.connection.read())?;
|
||||||
@@ -411,6 +432,10 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
|
|||||||
self.init()?;
|
self.init()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shifts(&self) -> usize {
|
||||||
|
self.shifts
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl<T: EntityData + Clone, D: BatchedDbLayer<T> + DbLayer<T>> BatchedRepository<T, D>
|
impl<T: EntityData + Clone, D: BatchedDbLayer<T> + DbLayer<T>> BatchedRepository<T, D>
|
||||||
for DataRepositoryInner<T, D>
|
for DataRepositoryInner<T, D>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use std::time::Instant;
|
|||||||
use crate::data::repositories::DataRepository;
|
use crate::data::repositories::DataRepository;
|
||||||
|
|
||||||
pub type CardStateRepository = DataRepository<CardState, SqliteDbLayer<CardState, CardStatesQuerySet>>;
|
pub type CardStateRepository = DataRepository<CardState, SqliteDbLayer<CardState, CardStatesQuerySet>>;
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct CardStatesQuerySet;
|
pub struct CardStatesQuerySet;
|
||||||
impl TableAccessQuerySet<CardState> for CardStatesQuerySet {
|
impl TableAccessQuerySet<CardState> for CardStatesQuerySet {
|
||||||
fn load() -> &'static str {
|
fn load() -> &'static str {
|
||||||
|
|||||||
Reference in new issue
Block a user