More migration code
This commit is contained in:
@@ -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>>()[..] {
|
if let [time, word, mode, before, after] = string.split(';').collect::<Vec<&str>>()[..] {
|
||||||
items.push(HistoryItem {
|
items.push(HistoryItem {
|
||||||
timestamp: DateTime::from_timestamp(time.parse().unwrap(), 0).unwrap(),
|
timestamp: DateTime::from_timestamp(time.parse().unwrap(), 0).unwrap(),
|
||||||
word_id: word.parse::<u32>().unwrap().into(),
|
word_id: word.parse::<Id>().unwrap().into(),
|
||||||
mode: match mode.parse::<u8>().unwrap() {
|
mode: match mode.parse::<u8>().unwrap() {
|
||||||
2 => WordOpenMode::Hard,
|
2 => WordOpenMode::Hard,
|
||||||
3 => WordOpenMode::Ok,
|
3 => WordOpenMode::Ok,
|
||||||
|
|||||||
+48
-79
@@ -1,9 +1,9 @@
|
|||||||
use crate::data_provider::card_stats::{delete_stat, load_stats_of_set, update_stat_score};
|
|
||||||
use crate::data_provider::history::{push_note, HistoryItem};
|
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
use crate::data_provider::card_stats::{delete_stat, load_stats_of_set, update_stat_score};
|
||||||
|
use crate::data_provider::history::{HistoryItem, push_note};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use rand::distr::weighted::WeightedIndex;
|
|
||||||
use rand::distr::Distribution;
|
use rand::distr::Distribution;
|
||||||
|
use rand::distr::weighted::WeightedIndex;
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
use rand::rng;
|
use rand::rng;
|
||||||
use rand::rngs::ThreadRng;
|
use rand::rngs::ThreadRng;
|
||||||
@@ -11,11 +11,13 @@ use rayon::iter::IndexedParallelIterator;
|
|||||||
use rayon::iter::IntoParallelRefIterator;
|
use rayon::iter::IntoParallelRefIterator;
|
||||||
use rayon::iter::ParallelIterator;
|
use rayon::iter::ParallelIterator;
|
||||||
use rhai::{Engine, Scope};
|
use rhai::{Engine, Scope};
|
||||||
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef};
|
|
||||||
use rusqlite::ToSql;
|
use rusqlite::ToSql;
|
||||||
|
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::num::ParseIntError;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
@@ -26,6 +28,47 @@ const FADE_PER_DAY: f32 = 0.95;
|
|||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy)]
|
||||||
pub(crate) struct Id(u32);
|
pub(crate) struct Id(u32);
|
||||||
pub const INVALID_ID: Id = Id(0);
|
pub const INVALID_ID: Id = Id(0);
|
||||||
|
|
||||||
|
impl FromStr for Id {
|
||||||
|
type Err = ParseIntError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(Id(s.parse::<u32>()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Id> for u32 {
|
||||||
|
fn into(self) -> Id {
|
||||||
|
Id(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct KanaSet {
|
pub struct KanaSet {
|
||||||
name: String,
|
name: String,
|
||||||
@@ -33,13 +76,11 @@ pub struct KanaSet {
|
|||||||
pub(crate) dictionary: Vec<Vec<(String, String)>>,
|
pub(crate) dictionary: Vec<Vec<(String, String)>>,
|
||||||
pub(crate) include_map: [bool; 10],
|
pub(crate) include_map: [bool; 10],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum KanaType {
|
pub enum KanaType {
|
||||||
Hiragana,
|
Hiragana,
|
||||||
Katakana,
|
Katakana,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KanaSet {
|
impl KanaSet {
|
||||||
pub fn hiragana() -> Self {
|
pub fn hiragana() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -219,7 +260,6 @@ impl KanaSet {
|
|||||||
current_set
|
current_set
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for KanaSet {
|
impl Default for KanaSet {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
KanaSet::hiragana()
|
KanaSet::hiragana()
|
||||||
@@ -230,7 +270,6 @@ impl PartialEq<Self> for KanaSet {
|
|||||||
self.name == other.name
|
self.name == other.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct WordData {
|
pub struct WordData {
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
@@ -240,11 +279,10 @@ pub struct WordData {
|
|||||||
pub additional: HashMap<String, String>,
|
pub additional: HashMap<String, String>,
|
||||||
pub group_id: Id,
|
pub group_id: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WordData {
|
impl WordData {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: 0.into(),
|
id: INVALID_ID,
|
||||||
key: String::new(),
|
key: String::new(),
|
||||||
value: String::new(),
|
value: String::new(),
|
||||||
tags: String::new(),
|
tags: String::new(),
|
||||||
@@ -253,13 +291,11 @@ impl WordData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WordGroup {
|
pub struct WordGroup {
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct CardStatistics {
|
pub struct CardStatistics {
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
@@ -268,7 +304,6 @@ pub struct CardStatistics {
|
|||||||
pub last_open: DateTime<Utc>,
|
pub last_open: DateTime<Utc>,
|
||||||
pub score: u8,
|
pub score: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardStatistics {
|
impl CardStatistics {
|
||||||
pub fn update(&mut self, status: WordOpenMode) {
|
pub fn update(&mut self, status: WordOpenMode) {
|
||||||
match status {
|
match status {
|
||||||
@@ -295,7 +330,6 @@ impl CardStatistics {
|
|||||||
(self.score as f32 * multiplier).max(1.0)
|
(self.score as f32 * multiplier).max(1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum WordOpenMode {
|
pub enum WordOpenMode {
|
||||||
Easy,
|
Easy,
|
||||||
@@ -303,7 +337,6 @@ pub enum WordOpenMode {
|
|||||||
Hard,
|
Hard,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DeckData {
|
pub struct DeckData {
|
||||||
words: Vec<WordData>,
|
words: Vec<WordData>,
|
||||||
@@ -313,7 +346,6 @@ pub struct DeckData {
|
|||||||
order_module: OrderModule,
|
order_module: OrderModule,
|
||||||
settings: DeckSettings,
|
settings: DeckSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeckData {
|
impl DeckData {
|
||||||
pub fn new(settings: &DeckSettings, state: Arc<Mutex<AppState>>) -> Self {
|
pub fn new(settings: &DeckSettings, state: Arc<Mutex<AppState>>) -> Self {
|
||||||
let state_for = state.clone();
|
let state_for = state.clone();
|
||||||
@@ -353,7 +385,6 @@ impl DeckData {
|
|||||||
settings: settings.clone(),
|
settings: settings.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) -> (WordData, CardStatistics) {
|
pub fn next(&mut self) -> (WordData, CardStatistics) {
|
||||||
let index = match self.order_module.clone() {
|
let index = match self.order_module.clone() {
|
||||||
OrderModule::SemiRandomSRS(mut module) => {
|
OrderModule::SemiRandomSRS(mut module) => {
|
||||||
@@ -385,7 +416,6 @@ impl DeckData {
|
|||||||
self.current_word_index = Some(index);
|
self.current_word_index = Some(index);
|
||||||
(self.words[index].clone(), self.set[index].clone())
|
(self.words[index].clone(), self.set[index].clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open(&mut self, status: WordOpenMode) {
|
pub fn open(&mut self, status: WordOpenMode) {
|
||||||
if self.current_word_index.is_none() {
|
if self.current_word_index.is_none() {
|
||||||
return;
|
return;
|
||||||
@@ -423,45 +453,38 @@ impl DeckData {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.set.len()
|
self.set.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Eq)]
|
#[derive(Clone, PartialEq, Copy, Eq)]
|
||||||
pub enum OrderMode {
|
pub enum OrderMode {
|
||||||
Default,
|
Default,
|
||||||
TrainWorstFirst,
|
TrainWorstFirst,
|
||||||
FullRandom,
|
FullRandom,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Default)]
|
#[derive(Clone, Copy, Eq, PartialEq, Default)]
|
||||||
pub enum AppendMode {
|
pub enum AppendMode {
|
||||||
Full,
|
Full,
|
||||||
#[default]
|
#[default]
|
||||||
Manual,
|
Manual,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum OrderModule {
|
enum OrderModule {
|
||||||
SemiRandomSRS(SemiRandomSRSModule),
|
SemiRandomSRS(SemiRandomSRSModule),
|
||||||
RandomSRS(RandomSRSModule),
|
RandomSRS(RandomSRSModule),
|
||||||
WorstWordsSRS(WorstWordsSRSModule),
|
WorstWordsSRS(WorstWordsSRSModule),
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SRSModule {
|
trait SRSModule {
|
||||||
fn next(&mut self, set: &mut DeckData) -> usize;
|
fn next(&mut self, set: &mut DeckData) -> usize;
|
||||||
fn open(&mut self, status: WordOpenMode, index: usize, updated_word: CardStatistics);
|
fn open(&mut self, status: WordOpenMode, index: usize, updated_word: CardStatistics);
|
||||||
fn init(&mut self, set: &mut DeckData);
|
fn init(&mut self, set: &mut DeckData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct RandomSRSModule {
|
struct RandomSRSModule {
|
||||||
basket: Vec<usize>,
|
basket: Vec<usize>,
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RandomSRSModule {
|
impl RandomSRSModule {
|
||||||
fn new() -> RandomSRSModule {
|
fn new() -> RandomSRSModule {
|
||||||
Self {
|
Self {
|
||||||
@@ -470,7 +493,6 @@ impl RandomSRSModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SRSModule for RandomSRSModule {
|
impl SRSModule for RandomSRSModule {
|
||||||
fn next(&mut self, set: &mut DeckData) -> usize {
|
fn next(&mut self, set: &mut DeckData) -> usize {
|
||||||
if self.basket.is_empty() {
|
if self.basket.is_empty() {
|
||||||
@@ -489,7 +511,6 @@ impl SRSModule for RandomSRSModule {
|
|||||||
self.basket.shuffle(&mut rand::rng())
|
self.basket.shuffle(&mut rand::rng())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct SemiRandomSRSModule {
|
struct SemiRandomSRSModule {
|
||||||
history: Vec<usize>,
|
history: Vec<usize>,
|
||||||
@@ -497,7 +518,6 @@ struct SemiRandomSRSModule {
|
|||||||
generator: ThreadRng,
|
generator: ThreadRng,
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SemiRandomSRSModule {
|
impl SemiRandomSRSModule {
|
||||||
fn new() -> SemiRandomSRSModule {
|
fn new() -> SemiRandomSRSModule {
|
||||||
SemiRandomSRSModule {
|
SemiRandomSRSModule {
|
||||||
@@ -508,7 +528,6 @@ impl SemiRandomSRSModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SRSModule for SemiRandomSRSModule {
|
impl SRSModule for SemiRandomSRSModule {
|
||||||
fn next(&mut self, set: &mut DeckData) -> usize {
|
fn next(&mut self, set: &mut DeckData) -> usize {
|
||||||
let index = self.last_weights.sample(&mut self.generator);
|
let index = self.last_weights.sample(&mut self.generator);
|
||||||
@@ -524,14 +543,12 @@ impl SRSModule for SemiRandomSRSModule {
|
|||||||
|
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(&mut self, _: 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);
|
let new_weight = (100.0 / word.calculated_score()).powf(2.0);
|
||||||
self.last_weights
|
self.last_weights
|
||||||
.update_weights(&[(index, &new_weight)])
|
.update_weights(&[(index, &new_weight)])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self, set: &mut DeckData) {
|
fn init(&mut self, set: &mut DeckData) {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
let weights = set
|
let weights = set
|
||||||
@@ -542,13 +559,11 @@ impl SRSModule for SemiRandomSRSModule {
|
|||||||
self.last_weights = WeightedIndex::new(weights).unwrap();
|
self.last_weights = WeightedIndex::new(weights).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SemiRandomSRSModule {
|
impl SemiRandomSRSModule {
|
||||||
fn history_len(&self, set: &DeckData) -> usize {
|
fn history_len(&self, set: &DeckData) -> usize {
|
||||||
((set.len() as f32 * MAX_HISTORY_LEN_PART) as usize).clamp(1, MAX_HISTORY_LEN)
|
((set.len() as f32 * MAX_HISTORY_LEN_PART) as usize).clamp(1, MAX_HISTORY_LEN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct WorstWordsSRSModule {
|
struct WorstWordsSRSModule {
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
@@ -558,7 +573,6 @@ struct WorstWordsSRSModule {
|
|||||||
queue: Vec<usize>,
|
queue: Vec<usize>,
|
||||||
rounds_count: u8,
|
rounds_count: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SRSModule for WorstWordsSRSModule {
|
impl SRSModule for WorstWordsSRSModule {
|
||||||
fn next(&mut self, set: &mut DeckData) -> usize {
|
fn next(&mut self, set: &mut DeckData) -> usize {
|
||||||
if self.rounds_remaining == 0 {
|
if self.rounds_remaining == 0 {
|
||||||
@@ -580,7 +594,6 @@ impl SRSModule for WorstWordsSRSModule {
|
|||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorstWordsSRSModule {
|
impl WorstWordsSRSModule {
|
||||||
fn new() -> WorstWordsSRSModule {
|
fn new() -> WorstWordsSRSModule {
|
||||||
WorstWordsSRSModule {
|
WorstWordsSRSModule {
|
||||||
@@ -592,7 +605,6 @@ impl WorstWordsSRSModule {
|
|||||||
queue: vec![],
|
queue: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_pool(&mut self, set: &DeckData) {
|
fn fill_pool(&mut self, set: &DeckData) {
|
||||||
let mut sorted = set
|
let mut sorted = set
|
||||||
.set
|
.set
|
||||||
@@ -609,7 +621,6 @@ impl WorstWordsSRSModule {
|
|||||||
self.pool = worst;
|
self.pool = worst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DeckSettings {
|
pub struct DeckSettings {
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
@@ -621,7 +632,6 @@ pub struct DeckSettings {
|
|||||||
pub worst_words_list: Option<Vec<WordData>>,
|
pub worst_words_list: Option<Vec<WordData>>,
|
||||||
pub open_mode: OrderMode,
|
pub open_mode: OrderMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeckSettings {
|
impl DeckSettings {
|
||||||
pub(crate) fn with_name(name: String) -> DeckSettings {
|
pub(crate) fn with_name(name: String) -> DeckSettings {
|
||||||
DeckSettings {
|
DeckSettings {
|
||||||
@@ -635,13 +645,11 @@ impl DeckSettings {
|
|||||||
open_mode: OrderMode::Default,
|
open_mode: OrderMode::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_filter(&self) -> bool {
|
pub(crate) fn check_filter(&self) -> bool {
|
||||||
let engine = Engine::new();
|
let engine = Engine::new();
|
||||||
let ast = engine.compile(&self.filter);
|
let ast = engine.compile(&self.filter);
|
||||||
ast.is_ok()
|
ast.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_word_list(&self, state: &AppState) -> Vec<usize> {
|
pub fn get_word_list(&self, state: &AppState) -> Vec<usize> {
|
||||||
let time = Instant::now();
|
let time = Instant::now();
|
||||||
let mut list = vec![];
|
let mut list = vec![];
|
||||||
@@ -692,46 +700,7 @@ impl DeckSettings {
|
|||||||
|
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn require_speech(&self) -> bool {
|
pub fn require_speech(&self) -> bool {
|
||||||
self.forward == "speech" || self.backward == "speech"
|
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
@@ -128,8 +128,8 @@ impl ScreenState {
|
|||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
let history_file_name = file.file_name().into_string().unwrap();
|
let history_file_name = file.file_name().into_string().unwrap();
|
||||||
let id : Id = history_file_name[4..history_file_name.len() - 12]
|
let id : Id = history_file_name[4..history_file_name.len() - 12]
|
||||||
.parse::<u32>()
|
.parse::<Id>()
|
||||||
.unwrap().into();
|
.unwrap();
|
||||||
|
|
||||||
let history = get_history_of_set(id);
|
let history = get_history_of_set(id);
|
||||||
let by_date = history.chunk_by(|x, x1| {
|
let by_date = history.chunk_by(|x, x1| {
|
||||||
|
|||||||
+10
-15
@@ -27,11 +27,9 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RepetitionsState {
|
pub struct RepetitionsState {
|
||||||
correct_filters: Vec<bool>,
|
|
||||||
current_sets_cards_cache: HashMap<usize, (Vec<usize>, Vec<usize>)>,
|
|
||||||
word_id_index_map: HashMap<u32, usize>,
|
word_id_index_map: HashMap<u32, usize>,
|
||||||
local_settings: HashMap<u32, DeckLocalSetting>,
|
view_data: Option<DeckViewData>,
|
||||||
view_data: Option<SetViewData>,
|
decks: Vec<DeckSettings>,
|
||||||
state: Arc<Mutex<AppState>>,
|
state: Arc<Mutex<AppState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,20 +487,17 @@ pub enum RepetitionsMessage {
|
|||||||
AppendWords(usize),
|
AppendWords(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone)]
|
||||||
struct DeckLocalSetting {
|
struct DeckViewData {
|
||||||
|
set_settings: DeckSettings,
|
||||||
|
existing_words_indices: Option<Vec<usize>>,
|
||||||
|
available_words_indices: Option<Vec<usize>>,
|
||||||
append_mode: AppendMode,
|
append_mode: AppendMode,
|
||||||
append_warning: bool,
|
append_warning: bool,
|
||||||
|
valid_filter: bool,
|
||||||
|
index: usize,
|
||||||
}
|
}
|
||||||
|
impl Deref for DeckViewData {
|
||||||
#[derive(Clone)]
|
|
||||||
struct SetViewData{
|
|
||||||
set_local_settings: DeckLocalSetting,
|
|
||||||
set_settings: DeckSettings,
|
|
||||||
existing_words_indices: Vec<usize>,
|
|
||||||
available_words_indices: Vec<usize>,
|
|
||||||
}
|
|
||||||
impl Deref for SetViewData {
|
|
||||||
type Target = DeckSettings;
|
type Target = DeckSettings;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|||||||
Reference in New Issue
Block a user