Fsrs pools change

This commit is contained in:
micialware committed 2026-09-23 18:05:58 +03:00
1 parent 8603e9b981
commit 936efd0e99
1 file changed
+31 -57
+31 -57
View File
@@ -1,7 +1,6 @@
use crate::data::entities::CardState; use crate::data::entities::CardState;
use chrono::{Local, TimeDelta}; use chrono::{Local, TimeDelta};
use fsrs::FSRS; use fsrs::FSRS;
use log::{debug, info};
use rand::distr::weighted::WeightedIndex; use rand::distr::weighted::WeightedIndex;
use rand::prelude::ThreadRng; use rand::prelude::ThreadRng;
use rand::prelude::{Distribution, SliceRandom}; use rand::prelude::{Distribution, SliceRandom};
@@ -67,6 +66,18 @@ pub struct SemiRandomSRSModule {
generator: ThreadRng, generator: ThreadRng,
} }
impl SRSModule for SemiRandomSRSModule { impl SRSModule for SemiRandomSRSModule {
fn new(set: &[&CardState]) -> Self {
let weights = set
.iter()
.map(|s| (100.0 / s.calculated_score()).powf(2.0) * 2.0)
.collect::<Vec<f32>>();
Self {
generator: rng(),
last_weights: WeightedIndex::new(weights).expect("Incorrect weights update"),
history: vec![],
}
}
fn next(&mut self, set: &[&CardState]) -> usize { fn next(&mut self, set: &[&CardState]) -> usize {
let index = self.last_weights.sample(&mut self.generator); let index = self.last_weights.sample(&mut self.generator);
@@ -87,18 +98,6 @@ impl SRSModule for SemiRandomSRSModule {
.update_weights(&[(index, &new_weight)]) .update_weights(&[(index, &new_weight)])
.expect("update weights error"); .expect("update weights error");
} }
fn new(set: &[&CardState]) -> Self {
let weights = set
.iter()
.map(|s| (100.0 / s.calculated_score()).powf(2.0) * 2.0)
.collect::<Vec<f32>>();
Self {
generator: rng(),
last_weights: WeightedIndex::new(weights).expect("Incorrect weights update"),
history: vec![],
}
}
} }
impl SemiRandomSRSModule { impl SemiRandomSRSModule {
fn history_len(&self, set: &[&CardState]) -> usize { fn history_len(&self, set: &[&CardState]) -> usize {
@@ -114,6 +113,16 @@ pub struct WorstWordsSRSModule {
rounds_count: u8, rounds_count: u8,
} }
impl SRSModule for WorstWordsSRSModule { impl SRSModule for WorstWordsSRSModule {
fn new(_: &[&CardState]) -> Self {
WorstWordsSRSModule {
pool_size: PARTIAL_POOL_SIZE,
rounds_count: 2,
rounds_remaining: 0,
pool: vec![],
queue: vec![],
}
}
fn next(&mut self, set: &[&CardState]) -> usize { fn next(&mut self, set: &[&CardState]) -> usize {
if self.rounds_remaining == 0 { if self.rounds_remaining == 0 {
self.fill_pool(set); self.fill_pool(set);
@@ -131,16 +140,6 @@ impl SRSModule for WorstWordsSRSModule {
} }
fn open(&mut self, _: WordOpenMode, _: usize, _: &mut CardState) {} fn open(&mut self, _: WordOpenMode, _: usize, _: &mut CardState) {}
fn new(_: &[&CardState]) -> Self {
WorstWordsSRSModule {
pool_size: PARTIAL_POOL_SIZE,
rounds_count: 2,
rounds_remaining: 0,
pool: vec![],
queue: vec![],
}
}
} }
impl WorstWordsSRSModule { impl WorstWordsSRSModule {
fn fill_pool(&mut self, set: &[&CardState]) { fn fill_pool(&mut self, set: &[&CardState]) {
@@ -157,9 +156,7 @@ impl WorstWordsSRSModule {
#[derive(Clone)] #[derive(Clone)]
pub struct FsrsModule { pub struct FsrsModule {
today_set: Vec<usize>, next_round: Vec<usize>,
solved: Vec<usize>,
current_group: Vec<usize>,
queue: Vec<usize>, queue: Vec<usize>,
rng: ThreadRng, rng: ThreadRng,
fsrs: FSRS, fsrs: FSRS,
@@ -170,29 +167,22 @@ impl SRSModule for FsrsModule {
let today = Local::now().date_naive(); let today = Local::now().date_naive();
let mut new = Self { let mut new = Self {
today_set: set queue: set
.iter() .iter()
.enumerate() .enumerate()
.filter(|(_, c)| c.fsrs_open_day <= today) .filter(|(_, c)| c.fsrs_open_day <= today)
.map(|(index, _)| index) .map(|(index, _)| index)
.collect(), .collect(),
current_group: vec![], next_round: vec![],
queue: vec![],
solved: vec![],
rng: rng(), rng: rng(),
fsrs: FSRS::default(), fsrs: FSRS::default(),
}; };
new.today_set.shuffle(&mut new.rng); new.queue.shuffle(&mut new.rng);
new.fill_partial_pool();
new new
} }
fn next(&mut self, _: &[&CardState]) -> usize { fn next(&mut self, _: &[&CardState]) -> usize {
if self.current_group.is_empty() {
self.fill_partial_pool();
}
if self.queue.is_empty() { if self.queue.is_empty() {
self.fill_queue(); self.fill_queue();
self.queue.shuffle(&mut self.rng); self.queue.shuffle(&mut self.rng);
@@ -230,37 +220,21 @@ impl SRSModule for FsrsModule {
updated_word.fsrs_open_day = next_day; updated_word.fsrs_open_day = next_day;
updated_word.fsrs_opened = updated_word.last_open.date_naive(); updated_word.fsrs_opened = updated_word.last_open.date_naive();
if (updated_word.fsrs_open_day != today && !first_time) if (updated_word.fsrs_open_day == today && !first_time)
|| (first_time && status == WordOpenMode::Easy) || (first_time && status != WordOpenMode::Easy)
{ {
info!("For today word on index {} solved", index); self.next_round.push(index);
self.solved.push(index);
let index = self.current_group.iter().position(|x| *x == index).unwrap();
self.current_group.remove(index);
} }
} }
} }
impl FsrsModule { impl FsrsModule {
fn fill_partial_pool(&mut self) {
debug!("Filling partial pool");
self.current_group.extend(
self.today_set
.iter()
.filter(|x| !self.solved.contains(*x))
.take(PARTIAL_POOL_SIZE),
);
self.queue.clear();
self.queue.extend(self.current_group.clone());
}
fn fill_queue(&mut self) { fn fill_queue(&mut self) {
self.queue.extend(self.current_group.clone()); self.queue.append(&mut self.next_round);
} }
pub fn finished(&self) -> bool { pub fn finished(&self) -> bool {
self.today_set.len() == self.solved.len() self.queue.is_empty() && self.next_round.is_empty()
} }
} }