From 4e57f3fd6b7254c90698c83b90f562d7f14e348e Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Mon, 15 Jun 2026 17:06:02 +0300 Subject: [PATCH] Make db creation better --- sql/card_set.sql | 9 +++ sql/card_stats.sql | 13 ++++ sql/settings.sql | 5 ++ sql/word_group.sql | 6 ++ sql/words.sql | 13 ++++ src/data_provider/mod.rs | 1 + src/data_provider/settings.rs | 1 - src/data_provider/sqlite.rs | 51 ++++++++++++++ src/data_provider/words.rs | 88 ------------------------ src/dictionary.rs | 3 - src/lang.rs | 124 +++++++++++++++++----------------- src/main.rs | 3 +- 12 files changed, 162 insertions(+), 155 deletions(-) create mode 100644 sql/card_set.sql create mode 100644 sql/card_stats.sql create mode 100644 sql/settings.sql create mode 100644 sql/word_group.sql create mode 100644 sql/words.sql create mode 100644 src/data_provider/sqlite.rs diff --git a/sql/card_set.sql b/sql/card_set.sql new file mode 100644 index 0000000..305aca2 --- /dev/null +++ b/sql/card_set.sql @@ -0,0 +1,9 @@ +create table card_set +( + id INTEGER + primary key autoincrement, + name TEXT not null, + forward TEXT not null, + backward TEXT not null, + filter TEXT not null +); \ No newline at end of file diff --git a/sql/card_stats.sql b/sql/card_stats.sql new file mode 100644 index 0000000..1655391 --- /dev/null +++ b/sql/card_stats.sql @@ -0,0 +1,13 @@ +create table card_stats +( + id INTEGER + primary key autoincrement, + word_id INTEGER not null + references words + on delete cascade, + set_id TEXT not null + references card_set + on delete cascade, + score INTEGER default 1 not null, + last_opened integer not null +); \ No newline at end of file diff --git a/sql/settings.sql b/sql/settings.sql new file mode 100644 index 0000000..42aeafe --- /dev/null +++ b/sql/settings.sql @@ -0,0 +1,5 @@ +create table settings +( + id text primary key, + value text +); \ No newline at end of file diff --git a/sql/word_group.sql b/sql/word_group.sql new file mode 100644 index 0000000..28cf3ac --- /dev/null +++ b/sql/word_group.sql @@ -0,0 +1,6 @@ +create table word_group +( + id INTEGER + primary key autoincrement, + name TEXT not null +); \ No newline at end of file diff --git a/sql/words.sql b/sql/words.sql new file mode 100644 index 0000000..e51e2e0 --- /dev/null +++ b/sql/words.sql @@ -0,0 +1,13 @@ +create table words +( + id INTEGER + primary key autoincrement, + key TEXT not null, + value TEXT not null, + tags TEXT not null, + more TEXT, + group_id integer default 1 not null + constraint words_word_group_id_fk + references word_group + on update cascade on delete cascade +); \ No newline at end of file diff --git a/src/data_provider/mod.rs b/src/data_provider/mod.rs index 54466a0..21972a1 100644 --- a/src/data_provider/mod.rs +++ b/src/data_provider/mod.rs @@ -3,4 +3,5 @@ pub(crate) mod card_sets; pub(crate) mod card_stats; pub(crate) mod voice; pub(crate) mod settings; +pub(crate) mod sqlite; diff --git a/src/data_provider/settings.rs b/src/data_provider/settings.rs index 3e7aea0..f2acf24 100644 --- a/src/data_provider/settings.rs +++ b/src/data_provider/settings.rs @@ -1,4 +1,3 @@ -use rusqlite::fallible_iterator::FallibleIterator; use rusqlite::Connection; pub fn get_setting(key: String, connection: &Connection) -> Option { diff --git a/src/data_provider/sqlite.rs b/src/data_provider/sqlite.rs new file mode 100644 index 0000000..8b6a4d0 --- /dev/null +++ b/src/data_provider/sqlite.rs @@ -0,0 +1,51 @@ +use crate::dictionary::app_data_dir; +use rusqlite::Connection; + +pub fn create_db() { + let path = app_data_dir(); + let db_file = path.join("data.db"); + if !db_file.exists() { + std::fs::File::create(&db_file).unwrap(); + let connection = Connection::open(&db_file).unwrap(); + connection.execute("PRAGMA foreign_keys = ON;", []).unwrap(); + + create_tables(&connection); + } +} + +fn create_tables(conn: &Connection) { + make_card_set(conn).unwrap(); + make_settings(conn).unwrap(); + make_word_group(conn).unwrap(); + make_words(conn).unwrap(); + make_card_stats(conn).unwrap(); +} + +fn make_settings(conn: &Connection) -> Result<(), rusqlite::Error> { + let query = include_str!("../../sql/settings.sql"); + conn.execute(query, ())?; + Ok(()) +} + +fn make_card_set(conn: &Connection) -> Result<(), rusqlite::Error> { + let query = include_str!("../../sql/card_set.sql"); + conn.execute(query, ())?; + Ok(()) +} + +fn make_word_group(conn: &Connection) -> Result<(), rusqlite::Error> { + let query = include_str!("../../sql/word_group.sql"); + conn.execute(query, ())?; + conn.execute("insert into word_group (name) values (\"Слова\");", ())?; + Ok(()) +} +fn make_words(conn: &Connection) -> Result<(), rusqlite::Error> { + let query = include_str!("../../sql/words.sql"); + conn.execute(query, ())?; + Ok(()) +} +fn make_card_stats(conn: &Connection) -> Result<(), rusqlite::Error> { + let query = include_str!("../../sql/card_stats.sql"); + conn.execute(query, ())?; + Ok(()) +} diff --git a/src/data_provider/words.rs b/src/data_provider/words.rs index 9e9a45d..871b26f 100644 --- a/src/data_provider/words.rs +++ b/src/data_provider/words.rs @@ -1,95 +1,7 @@ -use crate::dictionary::app_data_dir; use crate::lang::{WordData, WordGroup}; use rusqlite::Connection; use std::collections::HashMap; -pub fn create_db() { - let path = app_data_dir(); - let db_file = path.join("data.db"); - if !db_file.exists() { - std::fs::File::create(&db_file).unwrap(); - let connection = Connection::open(&db_file).unwrap(); - connection.execute("PRAGMA foreign_keys = ON;", []).unwrap(); - - create_tables(&connection); - } -} - -fn create_tables(conn: &Connection) { - conn.execute( - "create table settings -( - id text primary key, - value text -);", - (), - ) - .unwrap_or_else(|e| 0); - - conn.execute( - "create table card_set -( - id INTEGER - primary key autoincrement, - name TEXT not null, - forward TEXT not null, - backward TEXT not null, - filter TEXT not null -);", - (), - ) - .unwrap_or_else(|e| 0); - conn.execute( - "create table word_group -( - id INTEGER - primary key autoincrement, - name TEXT not null -);", - (), - ) - .unwrap_or_else(|e| 0); - conn.execute( - "create table words -( - id INTEGER - primary key autoincrement, - key TEXT not null, - value TEXT not null, - tags TEXT not null, - more TEXT, - group_id integer default 1 not null - constraint words_word_group_id_fk - references word_group - on update cascade on delete cascade -);", - (), - ) - .unwrap_or_else(|e| 0); - conn.execute( - "create table card_stats -( - id INTEGER - primary key autoincrement, - word_id INTEGER not null - references words - on delete cascade, - set_id TEXT not null - references card_set - on delete cascade, - score INTEGER default 1 not null, - last_opened integer not null -);", - (), - ) - .unwrap_or_else(|e| 0); - conn.execute( - "insert into word_group (name) -values (\"Слова\");", - (), - ) - .unwrap_or_else(|e| 0); -} pub fn add_word(word: &mut WordData, connection: &Connection) { let index = connection diff --git a/src/dictionary.rs b/src/dictionary.rs index 196d10b..75afaf1 100644 --- a/src/dictionary.rs +++ b/src/dictionary.rs @@ -15,7 +15,6 @@ use iced::widget::space::horizontal; use iced::widget::*; use iced::{Border, Color, Length, Shadow, Task}; use rand::random_range; -use rayon::iter::IndexedParallelIterator; use std::collections::{HashMap, HashSet}; use std::fs; use std::ops::Add; @@ -35,7 +34,6 @@ pub struct DictionaryState { selected_group_index: usize, reverse_list: bool, auto_save_queue: HashMap>, - total_tags_list: Vec, } #[derive(Debug, Clone)] @@ -117,7 +115,6 @@ impl DictionaryState { no_typing: true, reverse_list: true, auto_save_queue: HashMap::new(), - total_tags_list: vec![], }; result.update_tags(); diff --git a/src/lang.rs b/src/lang.rs index a17489c..ead52b3 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -277,10 +277,10 @@ impl CardStatistics { } WordOpenMode::Ok => self.score = (self.calculated_score() + 2.0).round() as i32, WordOpenMode::Hard => { - self.score = (self.calculated_score() - 1.0).round() as i32; + self.score = (self.calculated_score() * 0.75).round() as i32; } WordOpenMode::None => { - self.score = (self.calculated_score() * 0.5) as i32; + self.score = (self.calculated_score() * 0.4) as i32; } } @@ -359,9 +359,9 @@ impl CardSet { state: state_for, order_module: match settings.open_mode { SetOrderMode::Default => OrderModule::SemiRandomSRS(SemiRandomSRSModule::new()), - SetOrderMode::TrainWorstFirst => { - OrderModule::WorstWordsSRS(WorstWordsSRSModule::new()) - } + // SetOrderMode::TrainWorstFirst => { + // OrderModule::WorstWordsSRS(WorstWordsSRSModule::new()) + // } SetOrderMode::FullRandom => OrderModule::RandomSRS(RandomSRSModule::new()), }, } @@ -370,7 +370,7 @@ impl CardSet { pub fn next(&mut self) -> (WordData, CardStatistics) { let index = match self.order_module.clone() { OrderModule::SemiRandomSRS(mut module) => { - if module.initializated == false { + if module.initialized == false { module.init(self) } let index = module.next(self); @@ -378,21 +378,21 @@ impl CardSet { index } OrderModule::RandomSRS(mut module) => { - if module.initializated == false { + if module.initialized == false { module.init(self) } let index = module.next(self); self.order_module = OrderModule::RandomSRS(module); index } - OrderModule::WorstWordsSRS(mut module) => { - if module.initializated == false { - module.init(self) - } - let index = module.next(self); - self.order_module = OrderModule::WorstWordsSRS(module); - index - } + // OrderModule::WorstWordsSRS(mut module) => { + // if module.initializated == false { + // module.init(self) + // } + // let index = module.next(self); + // self.order_module = OrderModule::WorstWordsSRS(module); + // index + // } }; self.current_word_index = Some(index); @@ -417,10 +417,10 @@ impl CardSet { module.open(status, index, word.clone()); self.order_module = OrderModule::RandomSRS(module); } - OrderModule::WorstWordsSRS(mut module) => { - module.open(status, index, word.clone()); - self.order_module = OrderModule::WorstWordsSRS(module); - } + // OrderModule::WorstWordsSRS(mut module) => { + // module.open(status, index, word.clone()); + // self.order_module = OrderModule::WorstWordsSRS(module); + // } } update_stat_score(word, &self.state.lock().unwrap().connection) } @@ -431,9 +431,9 @@ impl CardSet { } #[derive(Clone, PartialEq, Copy, Eq)] -pub(crate) enum SetOrderMode { +pub enum SetOrderMode { Default, - TrainWorstFirst, + // TrainWorstFirst, FullRandom, } @@ -441,7 +441,7 @@ pub(crate) enum SetOrderMode { enum OrderModule { SemiRandomSRS(SemiRandomSRSModule), RandomSRS(RandomSRSModule), - WorstWordsSRS(WorstWordsSRSModule), + // WorstWordsSRS(WorstWordsSRSModule), } trait SRSModule { @@ -452,35 +452,35 @@ trait SRSModule { #[derive(Clone)] struct RandomSRSModule { - backet: Vec, - initializated: bool, + basket: Vec, + initialized: bool, } impl RandomSRSModule { fn new() -> RandomSRSModule { Self{ - backet: vec![], - initializated: false, + basket: vec![], + initialized: false, } } } impl SRSModule for RandomSRSModule { fn next(&mut self, set: &mut CardSet) -> usize { - if self.backet.is_empty() { - self.backet = (0..set.words.len()).collect::>(); - self.backet.shuffle(&mut rand::rng()) + if self.basket.is_empty() { + self.basket = (0..set.words.len()).collect::>(); + self.basket.shuffle(&mut rand::rng()) } - self.backet.pop().unwrap() + self.basket.pop().unwrap() } fn open(&mut self, _: WordOpenMode, _: usize, _: CardStatistics) {} fn init(&mut self, set: &mut CardSet) { - self.initializated = true; - self.backet = (0..set.words.len()).collect::>(); - self.backet.shuffle(&mut rand::rng()) + self.initialized = true; + self.basket = (0..set.words.len()).collect::>(); + self.basket.shuffle(&mut rand::rng()) } } @@ -489,7 +489,7 @@ struct SemiRandomSRSModule { history: Vec, last_weights: WeightedIndex, generator: ThreadRng, - initializated: bool, + initialized: bool, } impl SemiRandomSRSModule { @@ -498,7 +498,7 @@ impl SemiRandomSRSModule { history: vec![], last_weights: WeightedIndex::new([1.0]).unwrap(), generator: rng(), - initializated: false, + initialized: false, } } } @@ -519,7 +519,7 @@ impl SRSModule for SemiRandomSRSModule { index } - fn open(&mut self, status: WordOpenMode, index: usize, word: CardStatistics) { + fn open(&mut self, _: WordOpenMode, index: usize, word: CardStatistics) { let new_weight = (100.0 / word.calculated_score()).powf(2.0); self.last_weights .update_weights(&[(index, &new_weight)]) @@ -527,7 +527,7 @@ impl SRSModule for SemiRandomSRSModule { } fn init(&mut self, set: &mut CardSet) { - self.initializated = true; + self.initialized = true; let weights = set .set .iter() @@ -546,29 +546,29 @@ impl SemiRandomSRSModule { } } -#[derive(Clone)] -struct WorstWordsSRSModule { - initializated: bool, -} +// #[derive(Clone)] +// struct WorstWordsSRSModule { +// initializated: bool, +// } -impl SRSModule for WorstWordsSRSModule { - fn next(&mut self, set: &mut CardSet) -> usize { - todo!() - } - - fn open(&mut self, status: WordOpenMode, index: usize, updated_word: CardStatistics) { - todo!() - } - - fn init(&mut self, set: &mut CardSet) { - todo!() - } -} - -impl WorstWordsSRSModule { - fn new() -> WorstWordsSRSModule { - WorstWordsSRSModule { - initializated: false, - } - } -} +// impl SRSModule for WorstWordsSRSModule { +// fn next(&mut self, _: &mut CardSet) -> usize { +// todo!() +// } +// +// fn open(&mut self, _: WordOpenMode, _: usize, _: CardStatistics) { +// todo!() +// } +// +// fn init(&mut self, _: &mut CardSet) { +// todo!() +// } +// } +// +// impl WorstWordsSRSModule { +// fn new() -> WorstWordsSRSModule { +// WorstWordsSRSModule { +// initializated: false, +// } +// } +// } diff --git a/src/main.rs b/src/main.rs index c0099d6..d472e4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ mod writing; use crate::data_provider::card_sets::load_sets; use crate::data_provider::settings::get_setting; -use crate::data_provider::words::{create_db, load_word_groups, load_words}; +use crate::data_provider::words::{ load_word_groups, load_words}; use crate::dictionary::{app_data_dir, DictionaryMessage, DictionaryState}; use crate::dictionary_test::{DictionaryQuizMessage, DictionaryQuizState}; use crate::lang::{WordData, WordGroup}; @@ -37,6 +37,7 @@ use iced::{keyboard, Element, Subscription}; use iced::{Font, Task}; use rusqlite::Connection; use std::sync::{Arc, Mutex}; +use crate::data_provider::sqlite::create_db; const DEFAULT_SPACING: f32 = 10.0;