Skip to content

Commit

Permalink
add minute_offset and update to fsrs 0.6.2 (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexErrant authored Apr 28, 2024
1 parent d312080 commit b1958a6
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion fsrs-rs
20 changes: 19 additions & 1 deletion sandbox/src/train.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 6 additions & 6 deletions sandbox/tests/prod.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ test('check progress and parameters', async ({ page }) => {
let [n, d] = progress.split('/').map((x) => Math.round(parseInt(x)))
return {
numeratorLargerThan0: n > 0,
numeratorLessThanMax: n < 54500,
denominatorIsMax: d === 54500,
numeratorLessThanDenominator: n < d,
denominatorIsLarge: d > 10000,
}
},
{
Expand All @@ -49,19 +49,19 @@ test('check progress and parameters', async ({ page }) => {
)
.toEqual({
numeratorLargerThan0: true,
numeratorLessThanMax: true,
denominatorIsMax: true,
numeratorLessThanDenominator: true,
denominatorIsLarge: true,
})
await expect
.poll(
async () => {
let parameters = await page.locator('#parametersResult').innerText()
return parameters.split(',').map((x) => Math.round(parseFloat(x)))
return parameters.split(',').length
},
{
timeout: 20_000,
intervals: [200],
},
)
.toEqual([1, 2, 4, 11, 5, 1, 1, 0, 2, 0, 1, 2, 0, 0, 2, 0, 3])
.toEqual(17)
})
8 changes: 6 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@ 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],
types: &[u8],
progress: Option<Progress>,
) -> Vec<f32> {
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)
}

Expand Down Expand Up @@ -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],
Expand All @@ -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))
}
Expand Down

0 comments on commit b1958a6

Please sign in to comment.