mirror of
https://github.com/ankitects/anki.git
synced 2025-11-06 04:37:22 -05:00
Fix/Ensure fuzz doesn't go backward during rescheduling (#4364)
* Fix/Ensure fuzz doesn't go backward during rescheduling Fixes https://github.com/ankitects/anki/issues/2694 * Fix * Get previous_interval from LastRevlogInfo * Fix * Format * Format * Exclude lapses * Force reconfigure in CI The cached build.ninja may reference files that don't exist in the PR. On a local build this tends to auto-fix itself as the build scripts detect a quick failure and re-run the configure, but CI tends to be too slow. https://github.com/ankitects/anki/pull/4364#issuecomment-3338026129 * Rename min/max to make it clear they restrict interval, not fuzz * Wording tweaks/comments for clarity --------- Co-authored-by: Damien Elmes <gpg@ankiweb.net>
This commit is contained in:
parent
d8aa244a5a
commit
b0665a8ef1
3 changed files with 37 additions and 6 deletions
|
|
@ -16,6 +16,7 @@ if [ "$CLEAR_RUST" = "1" ]; then
|
|||
rm -rf $BUILD_ROOT/rust
|
||||
fi
|
||||
|
||||
rm -f out/build.ninja
|
||||
./ninja pylib qt check
|
||||
|
||||
echo "--- Ensure libs importable"
|
||||
|
|
|
|||
|
|
@ -136,6 +136,19 @@ impl Collection {
|
|||
let deckconfig_id = deck.config_id().unwrap();
|
||||
// reschedule it
|
||||
let original_interval = card.interval;
|
||||
let min_interval = |interval: u32| {
|
||||
let previous_interval =
|
||||
last_info.previous_interval.unwrap_or(0);
|
||||
if interval > previous_interval {
|
||||
// interval grew; don't allow fuzzed interval to
|
||||
// be less than previous+1
|
||||
previous_interval + 1
|
||||
} else {
|
||||
// interval shrunk; don't restrict negative fuzz
|
||||
0
|
||||
}
|
||||
.max(1)
|
||||
};
|
||||
let interval = fsrs.next_interval(
|
||||
Some(state.stability),
|
||||
desired_retention,
|
||||
|
|
@ -146,7 +159,7 @@ impl Collection {
|
|||
.and_then(|r| {
|
||||
r.find_interval(
|
||||
interval,
|
||||
1,
|
||||
min_interval(interval as u32),
|
||||
req.max_interval,
|
||||
days_elapsed as u32,
|
||||
deckconfig_id,
|
||||
|
|
@ -157,7 +170,7 @@ impl Collection {
|
|||
with_review_fuzz(
|
||||
card.get_fuzz_factor(true),
|
||||
interval,
|
||||
1,
|
||||
min_interval(interval as u32),
|
||||
req.max_interval,
|
||||
)
|
||||
});
|
||||
|
|
@ -310,6 +323,9 @@ pub(crate) struct LastRevlogInfo {
|
|||
/// reviewed the card and now, so that we can determine an accurate period
|
||||
/// when the card has subsequently been rescheduled to a different day.
|
||||
pub(crate) last_reviewed_at: Option<TimestampSecs>,
|
||||
/// The interval before the latest review. Used to prevent fuzz from going
|
||||
/// backwards when rescheduling the card
|
||||
pub(crate) previous_interval: Option<u32>,
|
||||
}
|
||||
|
||||
/// Return a map of cards to info about last review.
|
||||
|
|
@ -321,14 +337,27 @@ pub(crate) fn get_last_revlog_info(revlogs: &[RevlogEntry]) -> HashMap<CardId, L
|
|||
.into_iter()
|
||||
.for_each(|(card_id, group)| {
|
||||
let mut last_reviewed_at = None;
|
||||
let mut previous_interval = None;
|
||||
for e in group.into_iter() {
|
||||
if e.has_rating_and_affects_scheduling() {
|
||||
last_reviewed_at = Some(e.id.as_secs());
|
||||
previous_interval = if e.last_interval >= 0 && e.button_chosen > 1 {
|
||||
Some(e.last_interval as u32)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
} else if e.is_reset() {
|
||||
last_reviewed_at = None;
|
||||
previous_interval = None;
|
||||
}
|
||||
}
|
||||
out.insert(card_id, LastRevlogInfo { last_reviewed_at });
|
||||
out.insert(
|
||||
card_id,
|
||||
LastRevlogInfo {
|
||||
last_reviewed_at,
|
||||
previous_interval,
|
||||
},
|
||||
);
|
||||
});
|
||||
out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,13 +115,14 @@ impl Rescheduler {
|
|||
pub fn find_interval(
|
||||
&self,
|
||||
interval: f32,
|
||||
minimum: u32,
|
||||
maximum: u32,
|
||||
minimum_interval: u32,
|
||||
maximum_interval: u32,
|
||||
days_elapsed: u32,
|
||||
deckconfig_id: DeckConfigId,
|
||||
fuzz_seed: Option<u64>,
|
||||
) -> Option<u32> {
|
||||
let (before_days, after_days) = constrained_fuzz_bounds(interval, minimum, maximum);
|
||||
let (before_days, after_days) =
|
||||
constrained_fuzz_bounds(interval, minimum_interval, maximum_interval);
|
||||
|
||||
// Don't reschedule the card when it's overdue
|
||||
if after_days < days_elapsed {
|
||||
|
|
|
|||
Loading…
Reference in a new issue