Migrate to Id type
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::lang::{DeckSettings, OrderMode};
|
||||
use crate::lang::{DeckSettings, OrderMode, INVALID_ID};
|
||||
|
||||
use rusqlite::Connection;
|
||||
|
||||
@@ -43,11 +43,11 @@ pub fn add_set(set: &mut DeckSettings, connection: &Connection) {
|
||||
)
|
||||
.unwrap_or_else(|e| {println!("{}", e); 0});
|
||||
|
||||
set.id = index;
|
||||
set.id = index.into();
|
||||
}
|
||||
|
||||
pub fn update_card_set(set: &mut DeckSettings, connection: &Connection) {
|
||||
if set.id == 0 {
|
||||
if set.id == INVALID_ID {
|
||||
add_set(set, connection);
|
||||
} else {
|
||||
connection
|
||||
@@ -66,7 +66,7 @@ pub fn update_card_set(set: &mut DeckSettings, connection: &Connection) {
|
||||
}
|
||||
|
||||
pub fn delete_set(set: &DeckSettings, connection: &Connection) {
|
||||
if set.id == 0 {
|
||||
if set.id == INVALID_ID {
|
||||
return;
|
||||
}
|
||||
connection
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::lang::{DeckSettings, CardStatistics};
|
||||
use crate::lang::{DeckSettings, CardStatistics, INVALID_ID};
|
||||
use rusqlite::Connection;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -62,7 +62,7 @@ pub fn add_stat_list(stat: &mut [CardStatistics], connection: &Connection) {
|
||||
let start_index = last_index - (stat.len() as u32) + 1;
|
||||
|
||||
for (index, id) in (start_index..=last_index).enumerate() {
|
||||
stat[index].id = id;
|
||||
stat[index].id = id.into();
|
||||
}
|
||||
|
||||
println!("Added {} cards for {:?}", stat.len(), time.elapsed());
|
||||
@@ -103,7 +103,7 @@ pub fn update_stat_score(stat: &CardStatistics, connection: &Connection) {
|
||||
}
|
||||
|
||||
pub fn delete_stat(stat: &CardStatistics, connection: &Connection) {
|
||||
if stat.id == 0 {
|
||||
if stat.id == INVALID_ID {
|
||||
return;
|
||||
}
|
||||
connection
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::dictionary::app_data_dir;
|
||||
use crate::lang::WordOpenMode;
|
||||
use crate::lang::{Id, WordOpenMode};
|
||||
use chrono::{DateTime, Utc};
|
||||
use std::fs;
|
||||
use std::fs::{File, OpenOptions};
|
||||
@@ -7,7 +7,7 @@ use std::io::Write;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_history_of_set(id: u32) -> Vec<HistoryItem> {
|
||||
pub fn get_history_of_set(id: Id) -> Vec<HistoryItem> {
|
||||
let app_dir = history_dir();
|
||||
let head = app_dir.clone().join(format!("set_{}_history.csv", id));
|
||||
let mut lines = Vec::new();
|
||||
@@ -32,7 +32,7 @@ fn parse_history_items(strings: Vec<String>) -> Vec<HistoryItem> {
|
||||
if let [time, word, mode, before, after] = string.split(';').collect::<Vec<&str>>()[..] {
|
||||
items.push(HistoryItem {
|
||||
timestamp: DateTime::from_timestamp(time.parse().unwrap(), 0).unwrap(),
|
||||
word_id: word.parse::<u32>().unwrap(),
|
||||
word_id: word.parse::<u32>().unwrap().into(),
|
||||
mode: match mode.parse::<u8>().unwrap() {
|
||||
2 => WordOpenMode::Hard,
|
||||
3 => WordOpenMode::Ok,
|
||||
@@ -48,7 +48,7 @@ fn parse_history_items(strings: Vec<String>) -> Vec<HistoryItem> {
|
||||
items
|
||||
}
|
||||
|
||||
pub fn push_note(set_id: u32, item: HistoryItem) {
|
||||
pub fn push_note(set_id: Id, item: HistoryItem) {
|
||||
let app_dir = history_dir();
|
||||
let path = app_dir.clone().join(format!("set_{}_history.csv", set_id));
|
||||
|
||||
@@ -84,7 +84,7 @@ pub fn history_dir() -> PathBuf {
|
||||
#[derive(Clone)]
|
||||
pub struct HistoryItem {
|
||||
pub timestamp: DateTime<Utc>,
|
||||
pub word_id: u32,
|
||||
pub word_id: Id,
|
||||
pub mode: WordOpenMode,
|
||||
pub before: u8,
|
||||
pub after: u8,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::lang::{WordData, WordGroup};
|
||||
use crate::lang::{WordData, WordGroup, INVALID_ID};
|
||||
use rusqlite::{Connection, params};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn add_word(word: &mut WordData, connection: &Connection) {
|
||||
0
|
||||
});
|
||||
|
||||
word.id = index;
|
||||
word.id = index.into();
|
||||
}
|
||||
|
||||
pub fn add_words(words: &mut [WordData], connection: &mut Connection) {
|
||||
@@ -59,12 +59,12 @@ pub fn add_words(words: &mut [WordData], connection: &mut Connection) {
|
||||
let start_index = last_index - (count as u32) + 1;
|
||||
|
||||
for (index, id) in (start_index..=last_index).enumerate() {
|
||||
words[index].id = id;
|
||||
words[index].id = id.into();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_word(word: &mut WordData, connection: &Connection) {
|
||||
if word.id == 0 {
|
||||
if word.id == INVALID_ID {
|
||||
add_word(word, connection);
|
||||
} else {
|
||||
connection
|
||||
@@ -86,7 +86,7 @@ pub fn update_word(word: &mut WordData, connection: &Connection) {
|
||||
}
|
||||
|
||||
pub fn delete_word(word: &WordData, connection: &Connection) {
|
||||
if word.id == 0 {
|
||||
if word.id == INVALID_ID {
|
||||
return;
|
||||
}
|
||||
connection
|
||||
@@ -156,11 +156,11 @@ pub fn add_group(group: &mut WordGroup, connection: &Connection) {
|
||||
0
|
||||
});
|
||||
|
||||
group.id = index;
|
||||
group.id = index.into();
|
||||
}
|
||||
|
||||
pub fn update_group(group: &mut WordGroup, connection: &Connection) {
|
||||
if group.id == 0 {
|
||||
if group.id == INVALID_ID {
|
||||
add_group(group, connection);
|
||||
} else {
|
||||
connection
|
||||
@@ -176,7 +176,7 @@ pub fn update_group(group: &mut WordGroup, connection: &Connection) {
|
||||
}
|
||||
|
||||
pub fn delete_group(group: &WordGroup, connection: &Connection) {
|
||||
if group.id == 0 {
|
||||
if group.id == INVALID_ID {
|
||||
return;
|
||||
}
|
||||
connection
|
||||
|
||||
+8
-8
@@ -2,7 +2,7 @@ use crate::data_provider::words::{delete_group, delete_word, update_group, updat
|
||||
use crate::dictionary::DictionaryMessage::*;
|
||||
use crate::dictionary_test::DictionaryQuizState;
|
||||
use crate::import::ImportState;
|
||||
use crate::lang::{WordData, WordGroup};
|
||||
use crate::lang::{WordData, WordGroup, INVALID_ID};
|
||||
use crate::navigation::Page::{Import, Word};
|
||||
use crate::navigation::{NavigatedPage, Page};
|
||||
use crate::styling::*;
|
||||
@@ -96,7 +96,7 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
|
||||
let dict = &state.dictionary;
|
||||
word = dict[*index].clone();
|
||||
}
|
||||
if word.id != 0 {
|
||||
if word.id != INVALID_ID {
|
||||
return Some(Word(WordState::new(word, *index, self.state.clone())));
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
|
||||
}
|
||||
Include(i, b) => self.include_map[i] = b,
|
||||
IncludeTag(t, v) => {
|
||||
let index: u32;
|
||||
let index;
|
||||
{
|
||||
let state = self.state.lock().unwrap();
|
||||
index = state.word_groups[self.selected_group_index].id;
|
||||
@@ -197,7 +197,7 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
|
||||
let state = &mut self.state.lock().unwrap();
|
||||
|
||||
state.word_groups.push(WordGroup {
|
||||
id: 0,
|
||||
id: 0.into(),
|
||||
name: format!("Группа слов {}", random_range(100..1000)),
|
||||
});
|
||||
}
|
||||
@@ -222,7 +222,7 @@ impl NavigatedPage<DictionaryMessage> for DictionaryState {
|
||||
}
|
||||
SelectGroup(i) => {
|
||||
self.selected_group_index = i;
|
||||
let index: u32;
|
||||
let index;
|
||||
{
|
||||
let state = self.state.lock().unwrap();
|
||||
index = state.word_groups[i].id;
|
||||
@@ -423,7 +423,7 @@ impl DictionaryState {
|
||||
let line_button = || {
|
||||
let action = WordAction(index);
|
||||
|
||||
if data.id == 0 {
|
||||
if data.id == INVALID_ID {
|
||||
return button("-").on_press(action).style(|_x, _status| Style {
|
||||
background: None,
|
||||
text_color: Color::BLACK,
|
||||
@@ -532,7 +532,7 @@ impl DictionaryState {
|
||||
});
|
||||
}
|
||||
|
||||
fn update_words_include(&mut self, group_id: u32) {
|
||||
fn update_words_include(&mut self, group_id: crate::lang::Id) {
|
||||
let include_tags = self
|
||||
.tag_map
|
||||
.iter()
|
||||
@@ -626,6 +626,6 @@ struct WordLineState {
|
||||
key: String,
|
||||
value: String,
|
||||
tags: String,
|
||||
id: u32,
|
||||
id: crate::lang::Id,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ impl NavigatedPage<HistoryMessage> for HistoryState {
|
||||
}
|
||||
|
||||
impl HistoryState {
|
||||
pub fn new(id: u32, state: Arc<Mutex<AppState>>) -> Self {
|
||||
pub fn new(id: crate::lang::Id, state: Arc<Mutex<AppState>>) -> Self {
|
||||
let state = state.lock().unwrap();
|
||||
let history = get_history_of_set(id);
|
||||
let words = history
|
||||
|
||||
+1
-1
@@ -446,7 +446,7 @@ impl ImportState {
|
||||
|
||||
let map_indices = Self::get_mapping_indices(&group);
|
||||
let mut group_entity = WordGroup {
|
||||
id: 0,
|
||||
id: 0.into(),
|
||||
name: group.name.clone(),
|
||||
};
|
||||
{
|
||||
|
||||
+60
-16
@@ -11,8 +11,11 @@ use rayon::iter::IndexedParallelIterator;
|
||||
use rayon::iter::IntoParallelRefIterator;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use rhai::{Engine, Scope};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef};
|
||||
use rusqlite::ToSql;
|
||||
use std::cmp::PartialEq;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -20,6 +23,9 @@ const MAX_HISTORY_LEN: usize = 20;
|
||||
const MAX_HISTORY_LEN_PART: f32 = 0.33;
|
||||
const MAX_SCORE: u8 = 25;
|
||||
const FADE_PER_DAY: f32 = 0.95;
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy)]
|
||||
pub(crate) struct Id(u32);
|
||||
pub const INVALID_ID: Id = Id(0);
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct KanaSet {
|
||||
name: String,
|
||||
@@ -225,40 +231,40 @@ impl PartialEq<Self> for KanaSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WordData {
|
||||
pub id: u32,
|
||||
pub id: Id,
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
pub tags: String,
|
||||
pub additional: HashMap<String, String>,
|
||||
pub group_id: u32,
|
||||
pub group_id: Id,
|
||||
}
|
||||
|
||||
impl WordData {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
id: 0.into(),
|
||||
key: String::new(),
|
||||
value: String::new(),
|
||||
tags: String::new(),
|
||||
additional: Default::default(),
|
||||
group_id: 1,
|
||||
group_id: 1.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WordGroup {
|
||||
pub id: u32,
|
||||
pub id: Id,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct CardStatistics {
|
||||
pub id: u32,
|
||||
pub word_id: u32,
|
||||
pub set_id: u32,
|
||||
pub id: Id,
|
||||
pub word_id: Id,
|
||||
pub set_id: Id,
|
||||
pub last_open: DateTime<Utc>,
|
||||
pub score: u8,
|
||||
}
|
||||
@@ -320,8 +326,8 @@ impl DeckData {
|
||||
.map(|w| state_locked.dictionary.get(*w).unwrap())
|
||||
.cloned()
|
||||
.collect();
|
||||
let word_ids = last_list.iter().map(|l| l.id).collect::<Vec<u32>>();
|
||||
|
||||
let word_ids = last_list.iter().map(|l| l.id).collect::<Vec<Id>>();
|
||||
|
||||
let mut index = 0;
|
||||
for stat in current_set.clone() {
|
||||
if !word_ids.contains(&stat.word_id) {
|
||||
@@ -410,7 +416,7 @@ impl DeckData {
|
||||
self.settings.id,
|
||||
HistoryItem {
|
||||
timestamp: Utc::now(),
|
||||
word_id: word.word_id,
|
||||
word_id: word.word_id.into(),
|
||||
mode: WordOpenMode::Easy,
|
||||
before: old_score,
|
||||
after: new_score,
|
||||
@@ -606,7 +612,7 @@ impl WorstWordsSRSModule {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DeckSettings {
|
||||
pub id: u32,
|
||||
pub id: Id,
|
||||
pub name: String,
|
||||
pub forward: String,
|
||||
pub backward: String,
|
||||
@@ -619,7 +625,7 @@ pub struct DeckSettings {
|
||||
impl DeckSettings {
|
||||
pub(crate) fn with_name(name: String) -> DeckSettings {
|
||||
DeckSettings {
|
||||
id: 0,
|
||||
id: 0.into(),
|
||||
name,
|
||||
forward: "".to_string(),
|
||||
backward: "".to_string(),
|
||||
@@ -661,7 +667,7 @@ impl DeckSettings {
|
||||
}
|
||||
let mut scope = Scope::new();
|
||||
scope
|
||||
.push_constant("id", word.id)
|
||||
.push_constant("id", word.id.0)
|
||||
.push_constant("key", word.key.clone())
|
||||
.push_constant("value", word.value.clone())
|
||||
.push_constant("tags", word.tags.clone())
|
||||
@@ -691,3 +697,41 @@ impl DeckSettings {
|
||||
self.forward == "speech" || self.backward == "speech"
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Id> for u32{
|
||||
fn into(self) -> Id {
|
||||
Id(self)
|
||||
}
|
||||
}
|
||||
|
||||
// impl From<u32> for Id{
|
||||
// fn from(id: u32) -> Id{
|
||||
// Id(id)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Into<u32> for Id{
|
||||
fn into(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
impl Display for Id {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql for Id{
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
match value {
|
||||
ValueRef::Integer(i) => Ok(Id(i as u32)),
|
||||
_ => Err(FromSqlError::InvalidType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql for Id{
|
||||
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
|
||||
Ok(ToSqlOutput::from(self.0 as i64))
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -23,7 +23,7 @@ use crate::data_provider::card_sets::load_sets;
|
||||
use crate::data_provider::settings::get_setting;
|
||||
use crate::data_provider::sqlite::default_connection;
|
||||
use crate::data_provider::words::{load_word_groups, load_words};
|
||||
use crate::lang::{DeckSettings, WordData, WordGroup};
|
||||
use crate::lang::{DeckSettings, Id, WordData, WordGroup};
|
||||
use crate::navigation::{AppSettings, RootMessage, ScreenState};
|
||||
use crate::quiz::*;
|
||||
use chrono::NaiveDate;
|
||||
@@ -85,7 +85,7 @@ pub struct AppState {
|
||||
pub word_groups: Vec<WordGroup>,
|
||||
pub connection: Connection,
|
||||
pub sync_data: AppSettings,
|
||||
pub activity: HashMap<u32, Vec<(NaiveDate, u32)>>,
|
||||
pub activity: HashMap<Id, Vec<(NaiveDate, u32)>>,
|
||||
}
|
||||
|
||||
impl Default for AppState {
|
||||
|
||||
+4
-3
@@ -31,6 +31,7 @@ use hashbrown::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use rusqlite::Connection;
|
||||
use crate::lang::Id;
|
||||
|
||||
impl Default for ScreenState {
|
||||
fn default() -> Self {
|
||||
@@ -60,7 +61,7 @@ pub enum RootMessage {
|
||||
RepetitionSettings(RepetitionSettingsMessage),
|
||||
Import(ImportMessage),
|
||||
Keyboard(Event),
|
||||
DataLoaded(HashMap<u32, Vec<(NaiveDate, u32)>>),
|
||||
DataLoaded(HashMap<Id, Vec<(NaiveDate, u32)>>),
|
||||
None,
|
||||
UpdateData,
|
||||
}
|
||||
@@ -126,9 +127,9 @@ impl ScreenState {
|
||||
for file in directory.read_dir().unwrap().flatten() {
|
||||
let mut vec = vec![];
|
||||
let history_file_name = file.file_name().into_string().unwrap();
|
||||
let id = history_file_name[4..history_file_name.len() - 12]
|
||||
let id : Id = history_file_name[4..history_file_name.len() - 12]
|
||||
.parse::<u32>()
|
||||
.unwrap();
|
||||
.unwrap().into();
|
||||
|
||||
let history = get_history_of_set(id);
|
||||
let by_date = history.chunk_by(|x, x1| {
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ use iced::{Element, Fill, Task, Theme, alignment, keyboard};
|
||||
use rodio::MixerDeviceSink;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::lang::Id;
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
pub struct RepetitionState {
|
||||
@@ -24,7 +25,7 @@ pub struct RepetitionState {
|
||||
open: bool,
|
||||
can_play: bool,
|
||||
sink: Arc<MixerDeviceSink>,
|
||||
opened: HashSet<u32>,
|
||||
opened: HashSet<Id>,
|
||||
}
|
||||
|
||||
impl NavigatedPage<RepetitionMessage> for RepetitionState {
|
||||
|
||||
+8
-10
@@ -27,14 +27,12 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RepetitionsState {
|
||||
selected_set_index: Option<usize>,
|
||||
correct_filters: Vec<bool>,
|
||||
current_sets_cards_cache: HashMap<usize, (Vec<usize>, Vec<usize>)>,
|
||||
word_id_index_map: HashMap<u32, usize>,
|
||||
local_settings: HashMap<u32, DeckLocalSetting>,
|
||||
view_data: Option<SetViewData>,
|
||||
pub state: Arc<Mutex<AppState>>,
|
||||
set_names: Vec<String>
|
||||
state: Arc<Mutex<AppState>>,
|
||||
}
|
||||
|
||||
impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
||||
@@ -89,7 +87,9 @@ impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
||||
GoToHistory => {}
|
||||
GoToSettings => {}
|
||||
|
||||
CreateSet => {}
|
||||
CreateSet => {
|
||||
|
||||
}
|
||||
DeleteSet => {}
|
||||
SetName(_) => {}
|
||||
SelectSet(_) => {}
|
||||
@@ -209,15 +209,15 @@ impl RepetitionsState {
|
||||
button("Проверить фильтр")
|
||||
.style(jl_button)
|
||||
.on_press(TryFilter),
|
||||
self.count_view(&set),
|
||||
self.count_view(set),
|
||||
]
|
||||
.spacing(QUARTER_SPACING),
|
||||
]
|
||||
.spacing(DEFAULT_SPACING)
|
||||
} else {
|
||||
column![
|
||||
self.filled_set_data_view(&set),
|
||||
self.word_append_panel(&set),
|
||||
self.filled_set_data_view(set),
|
||||
self.word_append_panel(set),
|
||||
radio(
|
||||
"Обычный режим",
|
||||
OrderMode::Default,
|
||||
@@ -430,7 +430,6 @@ impl RepetitionsState {
|
||||
|
||||
impl RepetitionsState {
|
||||
fn append_all_words(&self, set: &DeckSettings) {
|
||||
let index = self.selected_set_index.unwrap();
|
||||
let cache = &self.current_sets_cards_cache[&index];
|
||||
let mut created_set = HashSet::with_capacity(cache.0.len());
|
||||
cache.0.iter().for_each(|c| {
|
||||
@@ -461,13 +460,12 @@ impl RepetitionsState {
|
||||
fn select_set(&mut self, index: usize) {
|
||||
let state = self.state.lock().unwrap();
|
||||
if let Some(set) = state.card_sets.get(index) {
|
||||
self.selected_set_index = Some(index);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_selection(&mut self) {
|
||||
self.selected_set_index = None;
|
||||
self.view_data = None;
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
|
||||
Reference in New Issue
Block a user