Fsrs pools change
This commit is contained in:
1 parent
8603e9b981
commit
936efd0e99
1 file changed
+31
-57
+31
-57
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user