-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Feat/per-deck desired retention #4194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/per-deck desired retention #4194
Conversation
Updated the logic for retrieving deck-specific desired retention in both `memory_state.rs` and `mod.rs` to handle cases where the deck's normal state may not be available. This change ensures that the default configuration is used when necessary, improving the robustness of the retention handling.
Updated the logic for effective desired retention to use the configuration default instead of the deck-specific value. This change improves consistency in the retention value used throughout the component, ensuring that the correct value is bound to the UI elements.
dae
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor feedback:
| // Whether new_today applies to today or a past day. | ||
| bool new_today_active = 6; | ||
| // Deck-specific desired retention override | ||
| optional float desired_retention = 7; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you've modelled this off the old limits code, DR is not really a 'limit', and it probably makes more sense to put in CurrentDeck instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CurrentDeck is not writable in the frontend. It seems to induce a lot of changes if we make it writable? And we should also add a new field to UpdateDeckConfigsRequest and modify the related code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a huge amount of changes, but it's not a tiny amount either, so I'm ok with you leaving things as they are currently.
|
|
||
| $: newCardsIgnoreReviewLimit = state.newCardsIgnoreReviewLimit; | ||
|
|
||
| // Create tabs for desired retention |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These looks a bit awkward without 'today only', but someone with more UI experience can tweak them later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe space-evenly/space-around looks a bit better here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be a bit better, but some people might find the standard limits are now a bit worse?
…sing method chaining
|
After reading some texts about daily limits in the manual and FAQ, I run into a problem:
So, the per-deck daily limits would affect subdecks. But the current per-deck desired retention design of this PR doesn't. After checking the related code, we need something like @dae, any thoughts? |
| <SpinBox bind:value {min} {max} {step} {percentage} bind:focused /> | ||
| <RevertButton slot="revert" bind:value {defaultValue} /> | ||
| </ConfigInput> | ||
| <Row class="flex-grow-1"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not something that needs to be done in this PR, but just a note that the SpinBoxFloatRow and SpinBoxRow components are almost identical and can probably be refactored into a single component.
|
|
||
| $: newCardsIgnoreReviewLimit = state.newCardsIgnoreReviewLimit; | ||
|
|
||
| // Create tabs for desired retention |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe space-evenly/space-around looks a bit better here.
Something like this maybe? diff --git a/rslib/src/scheduler/answering/mod.rs b/rslib/src/scheduler/answering/mod.rs
index 53f16c753..e875f245a 100644
--- a/rslib/src/scheduler/answering/mod.rs
+++ b/rslib/src/scheduler/answering/mod.rs
@@ -447,12 +447,20 @@ impl Collection {
// Get deck-specific desired retention if available, otherwise use config
// default
+ let config_desired_retention = if let Some(config_id) = self.get_current_deck()?.config_id()
+ {
+ self.get_deck_config(config_id, true)?
+ .unwrap_or_default()
+ .inner
+ .desired_retention
+ } else {
+ config.inner.desired_retention
+ };
let desired_retention = deck
.normal()
.ok()
.and_then(|d| d.desired_retention)
- .unwrap_or(config.inner.desired_retention);
-
+ .unwrap_or(config_desired_retention);
let fsrs_enabled = self.get_config_bool(BoolKey::Fsrs);
let fsrs_next_states = if fsrs_enabled {
let params = config.fsrs_params(); |
Sorry, I don't know what the |
|
It's different from card.deck_id when the card is in a subdeck of the deck you selected, so the parent deck's desired retention will be used, similar to the case with daily limits. This code is more correct (the current deck's specific value is checked first): diff --git a/rslib/src/scheduler/answering/mod.rs b/rslib/src/scheduler/answering/mod.rs
index 53f16c753..9f04436d7 100644
--- a/rslib/src/scheduler/answering/mod.rs
+++ b/rslib/src/scheduler/answering/mod.rs
@@ -447,11 +447,15 @@ impl Collection {
// Get deck-specific desired retention if available, otherwise use config
// default
- let desired_retention = deck
+ let current_deck = self.get_current_deck()?;
+ let current_deck_config = self
+ .get_deck_config(current_deck.config_id().unwrap_or_default(), true)?
+ .unwrap_or_default();
+ let desired_retention = current_deck
.normal()
.ok()
.and_then(|d| d.desired_retention)
- .unwrap_or(config.inner.desired_retention);
+ .unwrap_or(current_deck_config.inner.desired_retention);
let fsrs_enabled = self.get_config_bool(BoolKey::Fsrs);
let fsrs_next_states = if fsrs_enabled { |
|
Apologies if it's me here who's misreading things, but I think you guys might be talking about two different things?
|
I was thinking maybe it should work similar to Display Order settings, which only use the selected deck. But yes, that's inconsistent with most other settings. |
|
Let me elaborate it via a hypothetical collection with decks and presets: Preset A's desired retention = 90% Preset B: Parent: {Card 1} When I review Card 2, the possible values of desired retention to use are:
When I review Card 3, the possible values of desired retention to use are:
In my opinion, |
If someone wants to redefine all the subdecks in the deck, they will use the "Save to All Subdecks".
It seems this is exactly the option users expect. |
|
IMO, the expected behaviour would be:
Note: I have added a caveat to the second case in square brackets. |
|
Sounds good to me, lol. Let's keep the current implementation. |
|
There's duplicated logic for obtaining a deck's effective desired retention value in compute_memory_state() and answering/mod.rs. This logic can be extracted to a helper function to avoid code duplication. fn effective_desired_retention(deck: &Deck, config: &DeckConfig) -> f32 {
deck
.normal()
.ok()
.and_then(|d| d.desired_retention)
.unwrap_or(config.inner.desired_retention)
}let desired_retention = effective_desired_retention(&deck, &config); |
…ed clarity and maintainability.
|
Thanks for your work on this Jarrett, and for your patience. |
|
Hi there! I am just a user so apologies if this is not the right place to post. But what is the point of this feature if it doesn't allow for subdecks to have their own individual DRs separate from the parent deck DR? I was dismayed to find out that it doesn't work that way. It would be really great if we had a toggle for "Subdeck DR overrides parent deck DR" because otherwise this feature only works for parent level decks, no? Please correct me if I am mistaken. |
|
Please check the previous discussion. |
|
Thanks for your reply! I saw that the majority voted for the "no subdecks" approach, is it possible that we can get a toggle option to have the subdeck DR override the parent DR so everyone can be satisfied? |
|
I think it's feasible but very complicated. I recommend creating an issue to request that feature. |
|
Thanks, I made a thread! https://forums.ankiweb.net/t/request-option-for-deck-specific-dr-to-apply-subdecks/67215 |

Source: https://forums.ankiweb.net/t/allow-configuring-dr-for-each-deck-in-a-preset/61103
TODOs: