Skip to content

Commit e096c46

Browse files
authored
Feat/FSRS-6 (#3929)
* Feat/FSRS-6 * update comment * add decay to Card * ./ninja fix:minilints * pass check * fix NaN in evaluation * remove console * decay should fallback to 0.5 when it's None. * Update SimulatorModal.svelte * Update a few comments * Update FSRS decay defaults to use constants for better maintainability and clarity * Update rslib/src/storage/card/data.rs
1 parent 1e6c8b2 commit e096c46

31 files changed

+312
-181
lines changed

Cargo.lock

Lines changed: 85 additions & 69 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ rev = "184b2ca50ed39ca43da13f0b830a463861adb9ca"
3737
[workspace.dependencies.fsrs]
3838
# version = "=2.0.3"
3939
git = "https://github.com/open-spaced-repetition/fsrs-rs.git"
40-
rev = "08d90d1363b0c4722422bf0ef71ed8fd7d053f8a"
40+
rev = "c7717682997a8a6d53d97c7196281e745c5b3c8e"
4141
# path = "../open-spaced-repetition/fsrs-rs"
4242

4343
[workspace.dependencies]

cargo/licenses.json

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@
334334
},
335335
{
336336
"name": "bincode",
337-
"version": "2.0.0-rc.3",
337+
"version": "2.0.1",
338338
"authors": "Ty Overby <ty@pre-alpha.com>|Zoey Riordan <zoey@dos.cafe>|Victor Koenders <bincode@trangar.com>",
339339
"repository": "https://github.com/bincode-org/bincode",
340340
"license": "MIT",
@@ -415,7 +415,7 @@
415415
},
416416
{
417417
"name": "burn",
418-
"version": "0.16.0",
418+
"version": "0.16.1",
419419
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
420420
"repository": "https://github.com/tracel-ai/burn",
421421
"license": "Apache-2.0 OR MIT",
@@ -424,7 +424,7 @@
424424
},
425425
{
426426
"name": "burn-autodiff",
427-
"version": "0.16.0",
427+
"version": "0.16.1",
428428
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
429429
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-autodiff",
430430
"license": "Apache-2.0 OR MIT",
@@ -433,7 +433,7 @@
433433
},
434434
{
435435
"name": "burn-candle",
436-
"version": "0.16.0",
436+
"version": "0.16.1",
437437
"authors": "louisfd <louisfd94@gmail.com>",
438438
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-candle",
439439
"license": "Apache-2.0 OR MIT",
@@ -442,7 +442,7 @@
442442
},
443443
{
444444
"name": "burn-common",
445-
"version": "0.16.0",
445+
"version": "0.16.1",
446446
"authors": "Dilshod Tadjibaev (@antimora)",
447447
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-common",
448448
"license": "Apache-2.0 OR MIT",
@@ -451,7 +451,7 @@
451451
},
452452
{
453453
"name": "burn-core",
454-
"version": "0.16.0",
454+
"version": "0.16.1",
455455
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
456456
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-core",
457457
"license": "Apache-2.0 OR MIT",
@@ -460,7 +460,7 @@
460460
},
461461
{
462462
"name": "burn-cuda",
463-
"version": "0.16.0",
463+
"version": "0.16.1",
464464
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
465465
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-cuda",
466466
"license": "Apache-2.0 OR MIT",
@@ -469,7 +469,7 @@
469469
},
470470
{
471471
"name": "burn-dataset",
472-
"version": "0.16.0",
472+
"version": "0.16.1",
473473
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
474474
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-dataset",
475475
"license": "Apache-2.0 OR MIT",
@@ -478,7 +478,7 @@
478478
},
479479
{
480480
"name": "burn-derive",
481-
"version": "0.16.0",
481+
"version": "0.16.1",
482482
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
483483
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-derive",
484484
"license": "Apache-2.0 OR MIT",
@@ -487,7 +487,7 @@
487487
},
488488
{
489489
"name": "burn-hip",
490-
"version": "0.16.0",
490+
"version": "0.16.1",
491491
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
492492
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-hip",
493493
"license": "Apache-2.0 OR MIT",
@@ -496,7 +496,7 @@
496496
},
497497
{
498498
"name": "burn-jit",
499-
"version": "0.16.0",
499+
"version": "0.16.1",
500500
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
501501
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-jit",
502502
"license": "Apache-2.0 OR MIT",
@@ -505,7 +505,7 @@
505505
},
506506
{
507507
"name": "burn-ndarray",
508-
"version": "0.16.0",
508+
"version": "0.16.1",
509509
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
510510
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-ndarray",
511511
"license": "Apache-2.0 OR MIT",
@@ -514,7 +514,7 @@
514514
},
515515
{
516516
"name": "burn-router",
517-
"version": "0.16.0",
517+
"version": "0.16.1",
518518
"authors": "guillaumelagrange <lagrange.guillaume.1@gmail.com>|nathanielsimard <nathaniel.simard.42@gmail.com>",
519519
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-router",
520520
"license": "Apache-2.0 OR MIT",
@@ -523,7 +523,7 @@
523523
},
524524
{
525525
"name": "burn-tensor",
526-
"version": "0.16.0",
526+
"version": "0.16.1",
527527
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
528528
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-tensor",
529529
"license": "Apache-2.0 OR MIT",
@@ -532,7 +532,7 @@
532532
},
533533
{
534534
"name": "burn-train",
535-
"version": "0.16.0",
535+
"version": "0.16.1",
536536
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
537537
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-train",
538538
"license": "Apache-2.0 OR MIT",
@@ -541,7 +541,7 @@
541541
},
542542
{
543543
"name": "burn-wgpu",
544-
"version": "0.16.0",
544+
"version": "0.16.1",
545545
"authors": "nathanielsimard <nathaniel.simard.42@gmail.com>",
546546
"repository": "https://github.com/tracel-ai/burn/tree/main/crates/burn-wgpu",
547547
"license": "Apache-2.0 OR MIT",
@@ -2071,7 +2071,7 @@
20712071
},
20722072
{
20732073
"name": "itertools",
2074-
"version": "0.12.1",
2074+
"version": "0.13.0",
20752075
"authors": "bluss",
20762076
"repository": "https://github.com/rust-itertools/itertools",
20772077
"license": "Apache-2.0 OR MIT",
@@ -2080,7 +2080,7 @@
20802080
},
20812081
{
20822082
"name": "itertools",
2083-
"version": "0.13.0",
2083+
"version": "0.14.0",
20842084
"authors": "bluss",
20852085
"repository": "https://github.com/rust-itertools/itertools",
20862086
"license": "Apache-2.0 OR MIT",
@@ -2429,15 +2429,6 @@
24292429
"license_file": null,
24302430
"description": "A wrapper over a platform's native TLS implementation"
24312431
},
2432-
{
2433-
"name": "ndarray",
2434-
"version": "0.15.6",
2435-
"authors": "Ulrik Sverdrup \"bluss\"|Jim Turner",
2436-
"repository": "https://github.com/rust-ndarray/ndarray",
2437-
"license": "Apache-2.0 OR MIT",
2438-
"license_file": null,
2439-
"description": "An n-dimensional array for general elements and for numerics. Lightweight array views and slicing; views support chunking and splitting."
2440-
},
24412432
{
24422433
"name": "ndarray",
24432434
"version": "0.16.1",
@@ -2449,7 +2440,7 @@
24492440
},
24502441
{
24512442
"name": "ndarray-rand",
2452-
"version": "0.14.0",
2443+
"version": "0.15.0",
24532444
"authors": "bluss",
24542445
"repository": "https://github.com/rust-ndarray/ndarray",
24552446
"license": "Apache-2.0 OR MIT",
@@ -2971,7 +2962,7 @@
29712962
},
29722963
{
29732964
"name": "priority-queue",
2974-
"version": "2.1.1",
2965+
"version": "2.3.1",
29752966
"authors": "Gianmarco Garrisi <gianmarcogarrisi@tutanota.com>",
29762967
"repository": "https://github.com/garro95/priority-queue",
29772968
"license": "LGPL-3.0-or-later OR MPL-2.0",
@@ -3574,7 +3565,7 @@
35743565
},
35753566
{
35763567
"name": "serde",
3577-
"version": "1.0.217",
3568+
"version": "1.0.219",
35783569
"authors": "Erick Tryzelaar <erick.tryzelaar@gmail.com>|David Tolnay <dtolnay@gmail.com>",
35793570
"repository": "https://github.com/serde-rs/serde",
35803571
"license": "Apache-2.0 OR MIT",
@@ -3601,7 +3592,7 @@
36013592
},
36023593
{
36033594
"name": "serde_derive",
3604-
"version": "1.0.217",
3595+
"version": "1.0.219",
36053596
"authors": "Erick Tryzelaar <erick.tryzelaar@gmail.com>|David Tolnay <dtolnay@gmail.com>",
36063597
"repository": "https://github.com/serde-rs/serde",
36073598
"license": "Apache-2.0 OR MIT",
@@ -3851,6 +3842,15 @@
38513842
"license_file": null,
38523843
"description": "Helpful macros for working with enums and strings"
38533844
},
3845+
{
3846+
"name": "strum",
3847+
"version": "0.27.1",
3848+
"authors": "Peter Glotfelty <peter.glotfelty@microsoft.com>",
3849+
"repository": "https://github.com/Peternator7/strum",
3850+
"license": "MIT",
3851+
"license_file": null,
3852+
"description": "Helpful macros for working with enums and strings"
3853+
},
38543854
{
38553855
"name": "strum_macros",
38563856
"version": "0.26.4",
@@ -3860,6 +3860,15 @@
38603860
"license_file": null,
38613861
"description": "Helpful macros for working with enums and strings"
38623862
},
3863+
{
3864+
"name": "strum_macros",
3865+
"version": "0.27.1",
3866+
"authors": "Peter Glotfelty <peter.glotfelty@microsoft.com>",
3867+
"repository": "https://github.com/Peternator7/strum",
3868+
"license": "MIT",
3869+
"license_file": null,
3870+
"description": "Helpful macros for working with enums and strings"
3871+
},
38633872
{
38643873
"name": "subtle",
38653874
"version": "2.6.1",
@@ -4427,6 +4436,15 @@
44274436
"license_file": null,
44284437
"description": "Safe, fast, zero-panic, zero-crashing, zero-allocation parsing of untrusted inputs in Rust."
44294438
},
4439+
{
4440+
"name": "unty",
4441+
"version": "0.0.4",
4442+
"authors": "Victor Koenders <bincode@trang.ar>",
4443+
"repository": "https://github.com/bincode-org/unty",
4444+
"license": "Apache-2.0 OR MIT",
4445+
"license_file": null,
4446+
"description": "Explicitly types your generics"
4447+
},
44304448
{
44314449
"name": "url",
44324450
"version": "2.5.4",

proto/anki/cards.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ message Card {
5050
optional uint32 original_position = 18;
5151
optional FsrsMemoryState memory_state = 20;
5252
optional float desired_retention = 21;
53+
optional float decay = 22;
5354
string custom_data = 19;
5455
}
5556

proto/anki/deck_config.proto

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,10 @@ message DeckConfig {
122122

123123
repeated float fsrs_params_4 = 3;
124124
repeated float fsrs_params_5 = 5;
125+
repeated float fsrs_params_6 = 6;
125126

126127
// consider saving remaining ones for fsrs param changes
127-
reserved 6 to 8;
128+
reserved 7 to 8;
128129

129130
uint32 new_per_day = 9;
130131
uint32 reviews_per_day = 10;

proto/anki/scheduler.proto

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -432,17 +432,16 @@ message GetOptimalRetentionParametersResponse {
432432
uint32 learn_span = 2;
433433
float max_cost_perday = 3;
434434
float max_ivl = 4;
435-
repeated float learn_costs = 5;
436-
repeated float review_costs = 6;
437-
repeated float first_rating_prob = 7;
438-
repeated float review_rating_prob = 8;
439-
repeated float first_rating_offsets = 9;
440-
repeated float first_session_lens = 10;
441-
float forget_rating_offset = 11;
442-
float forget_session_len = 12;
443-
float loss_aversion = 13;
444-
uint32 learn_limit = 14;
445-
uint32 review_limit = 15;
435+
repeated float first_rating_prob = 5;
436+
repeated float review_rating_prob = 6;
437+
float loss_aversion = 7;
438+
uint32 learn_limit = 8;
439+
uint32 review_limit = 9;
440+
repeated float learning_step_transitions = 10;
441+
repeated float relearning_step_transitions = 11;
442+
repeated float state_rating_costs = 12;
443+
uint32 learning_step_count = 13;
444+
uint32 relearning_step_count = 14;
446445
}
447446

448447
message EvaluateParamsRequest {

proto/anki/stats.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ message CardStatsResponse {
6565
string preset = 21;
6666
optional string original_deck = 22;
6767
optional float desired_retention = 23;
68+
repeated float fsrs_params = 24;
6869
}
6970

7071
message GraphsRequest {

rslib/src/browser_table.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::sync::Arc;
55

66
use fsrs::FSRS;
7+
use fsrs::FSRS5_DEFAULT_DECAY;
78
use itertools::Itertools;
89
use strum::Display;
910
use strum::EnumIter;
@@ -541,10 +542,13 @@ impl RowContext {
541542
.memory_state
542543
.as_ref()
543544
.zip(self.cards[0].days_since_last_review(&self.timing))
544-
.map(|(state, days_elapsed)| {
545-
let r = FSRS::new(None)
546-
.unwrap()
547-
.current_retrievability((*state).into(), days_elapsed);
545+
.zip(Some(self.cards[0].decay.unwrap_or(FSRS5_DEFAULT_DECAY)))
546+
.map(|((state, days_elapsed), decay)| {
547+
let r = FSRS::new(None).unwrap().current_retrievability(
548+
(*state).into(),
549+
days_elapsed,
550+
decay,
551+
);
548552
format!("{:.0}%", r * 100.)
549553
})
550554
.unwrap_or_default()

rslib/src/card/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub struct Card {
9595
pub(crate) original_position: Option<u32>,
9696
pub(crate) memory_state: Option<FsrsMemoryState>,
9797
pub(crate) desired_retention: Option<f32>,
98+
pub(crate) decay: Option<f32>,
9899
/// JSON object or empty; exposed through the reviewer for persisting custom
99100
/// state
100101
pub(crate) custom_data: String,
@@ -145,6 +146,7 @@ impl Default for Card {
145146
original_position: None,
146147
memory_state: None,
147148
desired_retention: None,
149+
decay: None,
148150
custom_data: String::new(),
149151
}
150152
}

rslib/src/card/service.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ impl TryFrom<anki_proto::cards::Card> for Card {
106106
original_position: c.original_position,
107107
memory_state: c.memory_state.map(Into::into),
108108
desired_retention: c.desired_retention,
109+
decay: c.decay,
109110
custom_data: c.custom_data,
110111
})
111112
}
@@ -134,6 +135,7 @@ impl From<Card> for anki_proto::cards::Card {
134135
original_position: c.original_position,
135136
memory_state: c.memory_state.map(Into::into),
136137
desired_retention: c.desired_retention,
138+
decay: c.decay,
137139
custom_data: c.custom_data,
138140
}
139141
}

0 commit comments

Comments
 (0)