From 4316a42991f59fb95a7dec2c47b5fc5c7880e3ff Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 27 Apr 2024 09:28:10 -0500 Subject: [PATCH] add `minute_offset` and update to fsrs 0.6.2 --- Cargo.lock | 2 +- fsrs-rs | 2 +- sandbox/src/train.ts | 20 +++++++++++++++++++- src/lib.rs | 8 ++++++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc63c76..38b60eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -726,7 +726,7 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "fsrs" -version = "0.6.1" +version = "0.6.2" dependencies = [ "burn", "chrono", diff --git a/fsrs-rs b/fsrs-rs index 2170a29..14a6284 160000 --- a/fsrs-rs +++ b/fsrs-rs @@ -1 +1 @@ -Subproject commit 2170a2903699ccb99d913def9f5f6e485e1681ca +Subproject commit 14a62849af95a0df0f97cc1251390d03a1dda19c diff --git a/sandbox/src/train.ts b/sandbox/src/train.ts index d1010f9..1c68fea 100644 --- a/sandbox/src/train.ts +++ b/sandbox/src/train.ts @@ -135,7 +135,25 @@ function computeParameters( // Do not read from memory after `Stop` is posted! pointer: progress.pointer(), } satisfies ProgressMessage) - let parameters = fsrs.computeParametersAnki(cids, eases, ids, types, progress) + // MDN states: + // The number of minutes returned by getTimezoneOffset() is positive if the + // local time zone is behind UTC, and negative if the local time zone is ahead of UTC. + // This is useful when going from our timezone to UTC; our local time + offset = UTC. + // However, we want to go from UTC to our timezone. (Anki revlog id is UTC, and we want to convert it to local time.) + // So we flip the sign of `getTimezoneOffset()`. + let timeZoneMinutesOffset = new Date().getTimezoneOffset() * -1 + let ankiNextDayStartsAtMinutes = 4 * 60 + let parameters = fsrs.computeParametersAnki( + // We subtract ankiNextDayStartsAtMinutes because + // we want a review done at, say, 1am to be done for the *prior* day. + // Adding would move it into the future. + timeZoneMinutesOffset - ankiNextDayStartsAtMinutes, + cids, + eases, + ids, + types, + progress, + ) self.postMessage({ tag: 'Stop', parameters, diff --git a/src/lib.rs b/src/lib.rs index 3d5b7ef..0e6d659 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,9 +29,11 @@ impl FSRSwasm { Self { model } } + /// `minute_offset` should be the `user's timezone offset from UTC` minus `Anki's "next day starts at"`, in minutes. #[wasm_bindgen(js_name = computeParametersAnki)] pub fn compute_parameters_anki( &mut self, + minute_offset: i32, cids: &[i64], eases: &[u8], ids: &[i64], @@ -39,7 +41,7 @@ impl FSRSwasm { progress: Option, ) -> Vec { let revlog_entries = to_revlog_entry(cids, eases, ids, types); - let items = anki_to_fsrs(revlog_entries); + let items = anki_to_fsrs(revlog_entries, minute_offset); self.train_and_set_parameters(items, progress) } @@ -98,9 +100,11 @@ impl FSRSwasm { } #[wasm_bindgen(js_name = memoryStateAnki)] + /// `minute_offset` should be the `user's timezone offset from UTC` minus `Anki's "next day starts at"`, in minutes. /// Returns an array of 2 elements: `[stability, difficulty]` pub fn memory_state_anki( &self, + minute_offset: i32, cids: &mut [i64], eases: &[u8], ids: &[i64], @@ -116,7 +120,7 @@ impl FSRSwasm { assert_eq!(len, 1, "Expected 1 card, but was given {}", len); let revlog_entries = to_revlog_entry(cids, eases, ids, types); - anki_to_fsrs(revlog_entries) + anki_to_fsrs(revlog_entries, minute_offset) .pop() .map(|item| self._memory_state(item)) }