Update to latest fsrs-rs

The extra entries in Cargo.lock and licenses.json are mostly spurious,
and caused by https://github.com/tracel-ai/burn/pull/1025#issuecomment-1842006690
This commit is contained in:
Damien Elmes 2023-12-06 13:15:45 +10:00
parent 63260631e4
commit 96ae3a5d63
7 changed files with 2769 additions and 260 deletions

View File

@ -54,7 +54,7 @@ unknown-git = "warn"
allow-registry = ["https://github.com/rust-lang/crates.io-index"] allow-registry = ["https://github.com/rust-lang/crates.io-index"]
[sources.allow-org] [sources.allow-org]
github = ["ankitects"] github = ["ankitects", "open-spaced-repetition"]
[bans] [bans]
multiple-versions = "warn" multiple-versions = "warn"

1660
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
[workspace.dependencies.fsrs] [workspace.dependencies.fsrs]
git = "https://github.com/open-spaced-repetition/fsrs-rs.git" git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
rev = "96ae7fca09f17723ec514a1d633d36c3a09779f4" rev = "34570f396c86df857dd149921b9ed91c37993321"
# path = "../../../fsrs-rs" # path = "../../../fsrs-rs"
[workspace.dependencies] [workspace.dependencies]

File diff suppressed because it is too large Load Diff

View File

@ -369,8 +369,8 @@ impl Collection {
revlog, revlog,
timing.next_day_at, timing.next_day_at,
config.inner.sm2_retention, config.inner.sm2_retention,
); )?;
card.set_memory_state(&fsrs, item, config.inner.sm2_retention); card.set_memory_state(&fsrs, item, config.inner.sm2_retention)?;
} }
let days_elapsed = self let days_elapsed = self
.storage .storage
@ -381,7 +381,7 @@ impl Collection {
card.memory_state.map(Into::into), card.memory_state.map(Into::into),
config.inner.desired_retention, config.inner.desired_retention,
days_elapsed, days_elapsed,
)) )?)
} else { } else {
None None
}; };

View File

@ -4,6 +4,7 @@
use fsrs::FSRSError; use fsrs::FSRSError;
use crate::error::AnkiError; use crate::error::AnkiError;
use crate::error::InvalidInputError;
impl From<FSRSError> for AnkiError { impl From<FSRSError> for AnkiError {
fn from(err: FSRSError) -> Self { fn from(err: FSRSError) -> Self {
@ -12,6 +13,13 @@ impl From<FSRSError> for AnkiError {
FSRSError::OptimalNotFound => AnkiError::FsrsUnableToDetermineDesiredRetention, FSRSError::OptimalNotFound => AnkiError::FsrsUnableToDetermineDesiredRetention,
FSRSError::Interrupted => AnkiError::Interrupted, FSRSError::Interrupted => AnkiError::Interrupted,
FSRSError::InvalidWeights => AnkiError::FsrsWeightsInvalid, FSRSError::InvalidWeights => AnkiError::FsrsWeightsInvalid,
FSRSError::InvalidInput => AnkiError::InvalidInput {
source: InvalidInputError {
message: "invalid weights provided".to_string(),
source: None,
backtrace: None,
},
},
} }
} }
} }

View File

@ -64,7 +64,7 @@ impl Collection {
revlog, revlog,
timing.next_day_at, timing.next_day_at,
sm2_retention.unwrap_or(0.9), sm2_retention.unwrap_or(0.9),
); )?;
let desired_retention = req.as_ref().map(|w| w.desired_retention); let desired_retention = req.as_ref().map(|w| w.desired_retention);
let mut progress = self.new_progress_handler::<ComputeMemoryProgress>(); let mut progress = self.new_progress_handler::<ComputeMemoryProgress>();
progress.update(false, |s| s.total_cards = items.len() as u32)?; progress.update(false, |s| s.total_cards = items.len() as u32)?;
@ -73,7 +73,7 @@ impl Collection {
let mut card = self.storage.get_card(card_id)?.or_not_found(card_id)?; let mut card = self.storage.get_card(card_id)?.or_not_found(card_id)?;
let original = card.clone(); let original = card.clone();
if let Some(req) = &req { if let Some(req) = &req {
card.set_memory_state(&fsrs, item, sm2_retention.unwrap()); card.set_memory_state(&fsrs, item, sm2_retention.unwrap())?;
card.desired_retention = desired_retention; card.desired_retention = desired_retention;
// if rescheduling // if rescheduling
if let Some(reviews) = &last_revlog_info { if let Some(reviews) = &last_revlog_info {
@ -148,8 +148,8 @@ impl Collection {
revlog, revlog,
self.timing_today()?.next_day_at, self.timing_today()?.next_day_at,
sm2_retention, sm2_retention,
); )?;
card.set_memory_state(&fsrs, item, sm2_retention); card.set_memory_state(&fsrs, item, sm2_retention)?;
Ok(ComputeMemoryStateResponse { Ok(ComputeMemoryStateResponse {
state: card.memory_state.map(Into::into), state: card.memory_state.map(Into::into),
desired_retention, desired_retention,
@ -163,22 +163,21 @@ impl Card {
fsrs: &FSRS, fsrs: &FSRS,
item: Option<FsrsItemWithStartingState>, item: Option<FsrsItemWithStartingState>,
sm2_retention: f32, sm2_retention: f32,
) { ) -> Result<()> {
self.memory_state = item let memory_state = if let Some(i) = item {
.map(|i| fsrs.memory_state(i.item, i.starting_state)) Some(fsrs.memory_state(i.item, i.starting_state)?)
.or_else(|| { } else if self.ctype == CardType::New || self.interval == 0 {
if self.ctype == CardType::New || self.interval == 0 { None
None } else {
} else { // no valid revlog entries; infer state from current card state
// no valid revlog entries; infer state from current card state Some(fsrs.memory_state_from_sm2(
Some(fsrs.memory_state_from_sm2( self.ease_factor(),
self.ease_factor(), self.interval as f32,
self.interval as f32, sm2_retention,
sm2_retention, )?)
)) };
} self.memory_state = memory_state.map(Into::into);
}) Ok(())
.map(Into::into);
} }
} }
@ -197,16 +196,16 @@ pub(crate) fn fsrs_items_for_memory_state(
revlogs: Vec<RevlogEntry>, revlogs: Vec<RevlogEntry>,
next_day_at: TimestampSecs, next_day_at: TimestampSecs,
sm2_retention: f32, sm2_retention: f32,
) -> Vec<(CardId, Option<FsrsItemWithStartingState>)> { ) -> Result<Vec<(CardId, Option<FsrsItemWithStartingState>)>> {
revlogs revlogs
.into_iter() .into_iter()
.group_by(|r| r.cid) .group_by(|r| r.cid)
.into_iter() .into_iter()
.map(|(card_id, group)| { .map(|(card_id, group)| {
( Ok((
card_id, card_id,
single_card_revlog_to_item(fsrs, group.collect(), next_day_at, sm2_retention), single_card_revlog_to_item(fsrs, group.collect(), next_day_at, sm2_retention)?,
) ))
}) })
.collect() .collect()
} }
@ -258,7 +257,7 @@ pub(crate) fn single_card_revlog_to_item(
entries: Vec<RevlogEntry>, entries: Vec<RevlogEntry>,
next_day_at: TimestampSecs, next_day_at: TimestampSecs,
sm2_retention: f32, sm2_retention: f32,
) -> Option<FsrsItemWithStartingState> { ) -> Result<Option<FsrsItemWithStartingState>> {
struct FirstReview { struct FirstReview {
interval: f32, interval: f32,
ease_factor: f32, ease_factor: f32,
@ -281,32 +280,32 @@ pub(crate) fn single_card_revlog_to_item(
let mut item = items.pop().unwrap(); let mut item = items.pop().unwrap();
if found_learning { if found_learning {
// we assume the revlog is complete // we assume the revlog is complete
Some(FsrsItemWithStartingState { Ok(Some(FsrsItemWithStartingState {
item, item,
starting_state: None, starting_state: None,
}) }))
} else if let Some(first_review) = first_review { } else if let Some(first_review) = first_review {
// the revlog has been truncated, but not fully // the revlog has been truncated, but not fully
let starting_state = fsrs.memory_state_from_sm2( let starting_state = fsrs.memory_state_from_sm2(
first_review.ease_factor, first_review.ease_factor,
first_review.interval, first_review.interval,
sm2_retention, sm2_retention,
); )?;
item.reviews.remove(0); item.reviews.remove(0);
if item.reviews.is_empty() { if item.reviews.is_empty() {
None Ok(None)
} else { } else {
Some(FsrsItemWithStartingState { Ok(Some(FsrsItemWithStartingState {
item, item,
starting_state: Some(starting_state), starting_state: Some(starting_state),
}) }))
} }
} else { } else {
// only manual rescheduling; treat like empty // only manual rescheduling; treat like empty
None Ok(None)
} }
} else { } else {
None Ok(None)
} }
} }
@ -321,7 +320,7 @@ mod tests {
use crate::scheduler::fsrs::weights::tests::revlog; use crate::scheduler::fsrs::weights::tests::revlog;
#[test] #[test]
fn bypassed_learning_is_handled() { fn bypassed_learning_is_handled() -> Result<()> {
// cards without any learning steps due to truncated history still have memory // cards without any learning steps due to truncated history still have memory
// state calculated // state calculated
let fsrs = FSRS::new(Some(&[])).unwrap(); let fsrs = FSRS::new(Some(&[])).unwrap();
@ -337,7 +336,7 @@ mod tests {
], ],
TimestampSecs::now(), TimestampSecs::now(),
0.9, 0.9,
) )?
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
item.starting_state, item.starting_state,
@ -347,7 +346,7 @@ mod tests {
}) })
); );
let mut card = Card::default(); let mut card = Card::default();
card.set_memory_state(&fsrs, Some(item), 0.9); card.set_memory_state(&fsrs, Some(item), 0.9)?;
assert_eq!( assert_eq!(
card.memory_state, card.memory_state,
Some(FsrsMemoryState { Some(FsrsMemoryState {
@ -366,12 +365,12 @@ mod tests {
}], }],
TimestampSecs::now(), TimestampSecs::now(),
0.9, 0.9,
); )?;
assert!(item.is_none()); assert!(item.is_none());
card.interval = 123; card.interval = 123;
card.ease_factor = 2000; card.ease_factor = 2000;
card.ctype = CardType::Review; card.ctype = CardType::Review;
card.set_memory_state(&fsrs, item, 0.9); card.set_memory_state(&fsrs, item, 0.9)?;
assert_eq!( assert_eq!(
card.memory_state, card.memory_state,
Some(FsrsMemoryState { Some(FsrsMemoryState {
@ -379,10 +378,11 @@ mod tests {
difficulty: 6.5147333 difficulty: 6.5147333
}) })
); );
Ok(())
} }
#[test] #[test]
fn zero_history_is_handled() { fn zero_history_is_handled() -> Result<()> {
// when the history is empty, no items are produced // when the history is empty, no items are produced
assert_eq!(convert(&[], false), None); assert_eq!(convert(&[], false), None);
// but memory state should still be inferred, by using the card's current state // but memory state should still be inferred, by using the card's current state
@ -392,7 +392,7 @@ mod tests {
ease_factor: 1300, ease_factor: 1300,
..Default::default() ..Default::default()
}; };
card.set_memory_state(&FSRS::new(Some(&[])).unwrap(), None, 0.9); card.set_memory_state(&FSRS::new(Some(&[])).unwrap(), None, 0.9)?;
assert_eq!( assert_eq!(
card.memory_state, card.memory_state,
Some( Some(
@ -403,5 +403,6 @@ mod tests {
.into() .into()
) )
); );
Ok(())
} }
} }