mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
Allow cards with no learning history when not training
This commit is contained in:
parent
93499d4182
commit
d16faacd0f
2 changed files with 64 additions and 6 deletions
|
@ -125,3 +125,58 @@ pub(crate) fn single_card_revlog_to_item(
|
|||
let items = single_card_revlog_to_items(entries, next_day_at, false);
|
||||
items.and_then(|mut i| i.pop())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use fsrs::MemoryState;
|
||||
|
||||
use super::super::weights::tests::fsrs_items;
|
||||
use super::*;
|
||||
use crate::revlog::RevlogReviewKind;
|
||||
use crate::scheduler::fsrs::weights::tests::convert;
|
||||
use crate::scheduler::fsrs::weights::tests::review;
|
||||
use crate::scheduler::fsrs::weights::tests::revlog;
|
||||
|
||||
#[test]
|
||||
fn bypassed_learning_is_handled() {
|
||||
// cards without any learning steps due to truncated history still have memory
|
||||
// state calculated
|
||||
assert_eq!(
|
||||
convert(
|
||||
&[
|
||||
RevlogEntry {
|
||||
ease_factor: 2500,
|
||||
..revlog(RevlogReviewKind::Manual, 7)
|
||||
},
|
||||
revlog(RevlogReviewKind::Review, 6),
|
||||
],
|
||||
false,
|
||||
),
|
||||
fsrs_items!([review(0)])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_history_is_handled() {
|
||||
// when the history is empty, no items are produced
|
||||
assert_eq!(convert(&[], false), None);
|
||||
// but memory state should still be inferred, by using the card's current state
|
||||
let mut card = Card {
|
||||
ctype: CardType::Review,
|
||||
interval: 100,
|
||||
ease_factor: 1300,
|
||||
..Default::default()
|
||||
};
|
||||
card.set_memory_state(&FSRS::new(Some(&[])).unwrap(), None);
|
||||
assert_eq!(
|
||||
card.memory_state,
|
||||
Some(
|
||||
MemoryState {
|
||||
stability: 100.0,
|
||||
difficulty: 9.692858
|
||||
}
|
||||
.into()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,8 +135,8 @@ pub(crate) fn single_card_revlog_to_items(
|
|||
if idx > 0 {
|
||||
entries.drain(..idx);
|
||||
}
|
||||
} else {
|
||||
// we ignore cards that don't have any learning steps
|
||||
} else if training {
|
||||
// when training, we ignore cards that don't have any learning steps
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -210,12 +210,12 @@ impl RevlogEntry {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
||||
const NEXT_DAY_AT: TimestampSecs = TimestampSecs(86400 * 100);
|
||||
|
||||
fn revlog(review_kind: RevlogReviewKind, days_ago: i64) -> RevlogEntry {
|
||||
pub(crate) fn revlog(review_kind: RevlogReviewKind, days_ago: i64) -> RevlogEntry {
|
||||
RevlogEntry {
|
||||
review_kind,
|
||||
id: ((NEXT_DAY_AT.0 - days_ago * 86400) * 1000).into(),
|
||||
|
@ -224,14 +224,15 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn review(delta_t: u32) -> FSRSReview {
|
||||
pub(crate) fn review(delta_t: u32) -> FSRSReview {
|
||||
FSRSReview { rating: 3, delta_t }
|
||||
}
|
||||
|
||||
fn convert(revlog: &[RevlogEntry], training: bool) -> Option<Vec<FSRSItem>> {
|
||||
pub(crate) fn convert(revlog: &[RevlogEntry], training: bool) -> Option<Vec<FSRSItem>> {
|
||||
single_card_revlog_to_items(revlog.to_vec(), NEXT_DAY_AT, training)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fsrs_items {
|
||||
($($reviews:expr),*) => {
|
||||
Some(vec![
|
||||
|
@ -244,6 +245,8 @@ mod tests {
|
|||
};
|
||||
}
|
||||
|
||||
pub(crate) use fsrs_items;
|
||||
|
||||
#[test]
|
||||
fn delta_t_is_correct() -> Result<()> {
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in a new issue