shift learning fuzz into answering stage in test scheduler

When shown on the answer buttons, it's too distracting
This commit is contained in:
Damien Elmes 2021-05-17 13:05:42 +10:00
parent 958823fd6d
commit 1f16ce2096
8 changed files with 35 additions and 29 deletions

View file

@ -1,6 +1,8 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use rand::{prelude::*, rngs::StdRng};
use super::{CardStateUpdater, RevlogEntryPartial};
use crate::{
card::{CardQueue, CardType},
@ -35,7 +37,7 @@ impl CardStateUpdater {
match interval {
IntervalKind::InSecs(secs) => {
self.card.queue = CardQueue::Learn;
self.card.due = TimestampSecs::now().0 as i32 + secs as i32;
self.card.due = self.fuzzed_next_learning_timestamp(secs);
}
IntervalKind::InDays(days) => {
self.card.queue = CardQueue::DayLearn;
@ -45,4 +47,24 @@ impl CardStateUpdater {
RevlogEntryPartial::maybe_new(current, next.into(), 0.0, self.secs_until_rollover())
}
/// Adds secs + fuzz to current time
pub(super) fn fuzzed_next_learning_timestamp(&self, secs: u32) -> i32 {
TimestampSecs::now().0 as i32 + self.with_learning_fuzz(secs) as i32
}
/// Add up to 25% increase to seconds, but no more than 5 minutes.
fn with_learning_fuzz(&self, secs: u32) -> u32 {
if let Some(seed) = self.fuzz_seed {
let mut rng = StdRng::seed_from_u64(seed);
let upper_exclusive = secs + ((secs as f32) * 0.25).min(300.0).floor() as u32;
if secs >= upper_exclusive {
secs
} else {
rng.gen_range(secs, upper_exclusive)
}
} else {
secs
}
}
}

View file

@ -27,7 +27,7 @@ impl CardStateUpdater {
let interval = next.interval_kind();
match interval {
IntervalKind::InSecs(secs) => {
self.card.due = self.now.0 as i32 + secs as i32;
self.card.due = self.fuzzed_next_learning_timestamp(secs);
}
IntervalKind::InDays(_days) => {
// unsupported

View file

@ -4,7 +4,6 @@
use super::{CardStateUpdater, RevlogEntryPartial};
use crate::{
card::{CardQueue, CardType},
prelude::*,
scheduler::states::{CardState, IntervalKind, RelearnState},
};
@ -25,7 +24,7 @@ impl CardStateUpdater {
match interval {
IntervalKind::InSecs(secs) => {
self.card.queue = CardQueue::Learn;
self.card.due = TimestampSecs::now().0 as i32 + secs as i32;
self.card.due = self.fuzzed_next_learning_timestamp(secs);
}
IntervalKind::InDays(days) => {
self.card.queue = CardQueue::DayLearn;

View file

@ -32,14 +32,14 @@ impl LearnState {
fn answer_again(self, ctx: &StateContext) -> LearnState {
LearnState {
remaining_steps: ctx.steps.remaining_for_failed(),
scheduled_secs: ctx.with_learning_fuzz(ctx.steps.again_delay_secs_learn()),
scheduled_secs: ctx.steps.again_delay_secs_learn(),
}
}
fn answer_hard(self, ctx: &StateContext) -> CardState {
if let Some(hard_delay) = ctx.steps.hard_delay_secs(self.remaining_steps) {
LearnState {
scheduled_secs: ctx.with_learning_fuzz(hard_delay),
scheduled_secs: hard_delay,
..self
}
.into()
@ -56,7 +56,7 @@ impl LearnState {
if let Some(good_delay) = ctx.steps.good_delay_secs(self.remaining_steps) {
LearnState {
remaining_steps: ctx.steps.remaining_for_good(self.remaining_steps),
scheduled_secs: ctx.with_learning_fuzz(good_delay),
scheduled_secs: good_delay,
}
.into()
} else {

View file

@ -121,21 +121,6 @@ impl<'a> StateContext<'a> {
.round() as u32
}
/// Add up to 25% increase to seconds, but no more than 5 minutes.
pub(crate) fn with_learning_fuzz(&self, secs: u32) -> u32 {
if let Some(seed) = self.fuzz_seed {
let mut rng = StdRng::seed_from_u64(seed);
let upper_exclusive = secs + ((secs as f32) * 0.25).min(300.0).floor() as u32;
if secs >= upper_exclusive {
secs
} else {
rng.gen_range(secs, upper_exclusive)
}
} else {
secs
}
}
pub(crate) fn fuzzed_graduating_interval_good(&self) -> u32 {
self.with_review_fuzz(self.graduating_interval_good as f32)
}

View file

@ -18,18 +18,18 @@ impl PreviewState {
NextCardStates {
current: self.into(),
again: PreviewState {
scheduled_secs: ctx.with_learning_fuzz(ctx.preview_step * 60),
scheduled_secs: ctx.preview_step * 60,
..self
}
.into(),
hard: PreviewState {
// ~15 minutes with the default setting
scheduled_secs: ctx.with_learning_fuzz(ctx.preview_step * 90),
scheduled_secs: ctx.preview_step * 90,
..self
}
.into(),
good: PreviewState {
scheduled_secs: ctx.with_learning_fuzz(ctx.preview_step * 120),
scheduled_secs: ctx.preview_step * 120,
..self
}
.into(),

View file

@ -36,7 +36,7 @@ impl RelearnState {
RelearnState {
learning: LearnState {
remaining_steps: ctx.relearn_steps.remaining_for_failed(),
scheduled_secs: ctx.with_learning_fuzz(again_delay),
scheduled_secs: again_delay,
},
review: ReviewState {
scheduled_days: self.review.failing_review_interval(ctx),
@ -57,7 +57,7 @@ impl RelearnState {
{
RelearnState {
learning: LearnState {
scheduled_secs: ctx.with_learning_fuzz(hard_delay),
scheduled_secs: hard_delay,
..self.learning
},
review: ReviewState {
@ -78,7 +78,7 @@ impl RelearnState {
{
RelearnState {
learning: LearnState {
scheduled_secs: ctx.with_learning_fuzz(good_delay),
scheduled_secs: good_delay,
remaining_steps: ctx
.relearn_steps
.remaining_for_good(self.learning.remaining_steps),

View file

@ -86,7 +86,7 @@ impl ReviewState {
RelearnState {
learning: LearnState {
remaining_steps: ctx.relearn_steps.remaining_for_failed(),
scheduled_secs: ctx.with_learning_fuzz(again_delay),
scheduled_secs: again_delay,
},
review: again_review,
}